그냥 오래전부터 생각했던 프로젝트였는데, 이제서야 실천(!)에 옮기려고 진행하는 것인데요...
그게 뭐냐고요? ㅋ 으흠~ ㅎ.ㅎ
MSX에는 메모리 매퍼를 이용해 64KB 이상의 메모리를 사용할 수 있도록 설계되어있습니다.
이 메모리를 좀 더 효과적으로 사용하는 프로그램을 만들자라는 것이 목표이고요.
물론 기존에도 그냥 메모리 매퍼를 직접 액세스하거나 DOS2의 매퍼 루틴으로 잘 썼긴했습니다.
근데 솔직히, DOS2에 메모리도 넉넉하게 쓸수 있는 유저가 많지 않았었죠?
저도 이것 때문에 일반적으로 배포하려고 만드는 프로그램은,
메모리 매퍼를 쓰지않고 DOS1의 기본 메모리에서 구동되도록 했었습니다.
대신, 디스크 퍼포먼스는 DOS2 쪽이 좋기 때문에,
DOS2에서 실행되는 경우에는 DOS2의 시스템 콜을 쓰도록 만들었습니다.
최근에 저와 흥건남자님과 힘을 합쳐 확장슬롯+1MB램을 쓸수 있는 기기가 나오게 되었는데요,
이제 메모리를 활용할수 있는 프로그램을 본격적으로 만들어도 될때가 되지않았나 생각됩니다.
메모리가 많으면, 스크린7의 인터레이스 모드 그래픽을 쓰거나,
안티앨리어스 적용되는 한글 폰트룰 만든다던가... 재밌는걸 할수 있겠지요. ^^
일단 메모리 매퍼를 조금 설명드리면...
다른 대부분의 MSX기본 기기처럼, 메모리 매퍼도 IO 맵 I/O로 동작합니다.
근데 한가지 이상한 부분이 있죠.
MSX에서는 메모리 매퍼를 여러개 써도 되도록 규격이 만들어져 있습니다.
그러니까 슬롯1에는 1024KB, 슬롯3-0에는 512KB... 이런식으로 쓸 수 있다는 것이지요.
근데, 중요한건 메모리 매퍼용 IO 주소는 슬롯 제한을 받지 않는다는 사실인데요.
(IO 맵 방식이니까, 당연한 것이지만요.)
이게 SW 개발하는 사람한테는 참 머리아픈 문제입니다.
왜냐면, 예를 들어 현재 Page2 메모리(8000H~BFFFH)를 다른 세그먼트(뱅크 또는 페이지라고 보시면됩니다.)로
할당하게 되면, 모든 슬롯에 장착된 메모리 매퍼의 세그먼트가 같이 바뀝니다.
게다가 한가지 문제가 더 있는데요.
메모리 매퍼중에는 현재 세그먼트 번호를 읽을 수 있도록 만들어진게 대부분입니다.
MSX2 이상의 본체 내장된 건 아마 다 읽을 수 있을꺼에요.
문제는 Write 할때는 같은 주소에 연결된 기기가 한번에 동작은 하는데,
반대로 Read 할때는 램의 용량에 따라 세그먼트 최대 갯수가 다르니 읽은 값도 다를 수가 있겠죠?
이 때문에, 매퍼 레지스터를 읽는 것은... 법(!!)으로 금지되어 있습니다.
하지만 안타깝게도 MSX의 메인 바이오스는 메모리 매퍼에 관한 루틴이 하나도 없어서,
메모리 매퍼를 컨트롤하려면 SW 만드는 사람이 알아서 해야된다는 것이었죠.
이 때문에 많은 메모리 관련 호환성 문제가 발생하게 되었습니다.
어떤 슬롯에 얼마나 메모리가 장착되어 있는지, 확인하는 것이 쉽지가 않습니다.
아까 말했듯이 특정 세그먼트를 바꾸면, 원하지 않는 슬롯의 메모리도 변경이 되고...
용량을 확인하려면, 16KB 영역을 R/W 해보면서 램인지 일일이 체크를 해야하는데 쉽지 않죠.
그래서 많은 프로그래머들이 그냥 용량 체크는 세그먼트 값을 썼다가 읽은 값이 같아지는 숫자만을 인식하거나,
특성 슬롯만 메모리 확인을 하거나... 매퍼가 두개 이상일때는 메인(Primary) 매퍼만 사용하거나... 등의
방법을 썼습니다.
제 경우에도 터보알(A1GT)의 내장램을 1024KB로 확장하니까, 대부분 유럽산 프로그램들이 동작하지 않더군요.
보통 128KB~256KB 메모리를 요구하는 프로그램들입니다.
재밌게도 일본에서 만든 프로그램은 대부분 64KB 전용이라 크게 문제될게 없더군요.
국내 SW는 대우 MSX에 맞춰서 슬롯/메모리 등을 설정해서 또 문제가 됐었고요.
단지 일반 개발자 뿐만 아니라 유명한 게임들도 비슷한 제들이 있었습니다.
마이크로 캐빈의 FRAY는 메모리 확장된 터보알에서 부팅 안되는게 제일 유명한가요?
암튼 HW 설계상의 약점과 SW 개발의 어려움이 한데 뭉쳐져서 메모리 활용이 상당히 힘들었습니다.
이게 MSX-DOS2의 디스크 바이오스에서 메모리 매퍼를 지원하게 되어 이런 문제가 해결되었습니다.
바이오스 콜을 통해 메모리 세그먼트의 할당/해제/전환을 쉽게 할수 있게 되었지요.
Page3을 제외한 Page0,1,2 (0000H~BFFFH)의 메모리를 마음데로 바꿀수가 있습니다.
Page0의 경우는 인터럽트 사용시 주의해야겠지만... 암튼요.
방법은 DOS2 매뉴얼에 나오니 여기서 설명하진 않겠습니다.
다시 말씀드리지만, 메모리 매퍼 강좌를 하려는게 아니에요. ^^;
어쨋꺼나 DOS2 바이오스의 지원으로 메모리는 좀 더 사용이 쉬워졌지만,
개발자가 메모리 구성을 잘해서 SW를 만들어야 하는 것은 변함이 없습니다.
MSX용 개발 툴 중에서 DOS2 메모리 관련 루틴을 활용한 것이 따로 있는지는 잘 모르겠네요.
몇 종류의 어셈블리와 파스칼, C 정도의 컴파일러가 있지만, 대부분 CP/M용이라 (MSX-DOS1 겸용)
활용이 불가능 할 겁니다.
암튼, 서론이 길었는데요. ㅎ.ㅎ;
이번에 HI-TECH C에서 DOS2 메모리 매퍼 활용을 높일 수 있도록,
관련 라이브러리와 단일화된 메모리맵을 만들고 있습니다.
일단 컴파일러로 HI-TECH C를 고른 이유는...
라이브러리가 풀 소스로 제공되고, 인라인 어셈블리 사용도 편리한 편이고,
ANSI C를 풀로 지원한다거나 여러가지가 있겠지만,
제가 최근 수년간 쓰면서 많이 익숙하다는게 주 이유일 것 같네요.
함수 파라미터와 로컬 변수가 모두 스택에 할당되기 때문에
퍼포먼스가 좀 딸린다는 단점이 있지만, 대신 항상 함수의 Re-entrant(재진입)가 가능합니다.
메모리 관리는 DOS2의 확장 바이오스 루틴에 의존합니다.
메모리 세그먼트가 다른 함수 간의 호출은 별도의 뱅킹 루틴을 통해 이루어지는데요.
총 약4MB의 메모리를 사용할 수 있습니다.(DOS2와 터보알의 시스템 영역은 제외)
16KB 세그먼트 2개를 한개의 프로그램 뱅크로 사용합니다.
그러니까 최대 128개의 뱅크(32KB x 128 = 4096KB)를 프로그램으로 쓸수 있습니다.
일단 아래 메모리 맵을 보세요.
0000H~00FFH : DOS 시스템 콜 영역
0100H~7FFFH : 뱅킹 가능한 프로그램 영역(TEXT/DATA/BSS) (약 32KB)
8000H~8FFFH : 뱅킹(세그먼트 전환) 루틴, 뱅킹 스택 (4KB)
9000H~9FFFH : 공용 ISR 및 뱅크간 공유 DATA 영역 (4KB)
A000H~FFFFH : 스택 및 Work Area (24KB)
한동안 고민했던 메모리맵이었는데요,
함수 갯수가 많아지고 뱅킹간의 함수 콜도 왠만큼 하려면 스택이 많이 필요해지는데,
일단 현상태로 괜찮을지는 모르겠습니다.
부족하면 뱅크간 공유 DATA 영역을 줄여야겠지요. ^^
0100H~7FFFH 영역을 프로그램으로 할당한 것은,
Page1(4000H~7FFFH) 영역을 다른 슬롯에 있는 SW를 사용하거나,
메모리맵 IO를 쓰는 주변기기를 쉽게 액세스하기 위함입니다.
그리고, 실제 뱅킹은 Page0,1(0000H~7FFFH) 전체 영역이 바뀌게 되니까,
개별적인 인터럽트 루틴을 잠깐씩 쓸때도 유용하지 않을까 생각되네요.
아직 DOS2 시스템 콜을 사용시, Page0를 제대로 복구하는지는 테스트를 해봐야됩니다.
현재 뱅킹 루틴을 만들어서 테스트 중인데요.
HI-TECH C 컴파일 했을때 일반 함수에서 다른 뱅크로 잘 전환되는지 확인중입니다.
진행 상황은 가끔 글로 올리겠습니다.
혹시 질문 있으면 댓글로 달아주세요~