"어디선가 많이 듣던 말인데, 어떻게 동작하는건지 모르겠네~" 라고
생각하신 분을 위한 강좌입니다. ^^
일단 메모리 매퍼는,
MSX에서 쓰이는 메모리을 특정 크기로 분할해서,
HW/SW로 편리하게 쓸수 있도록 만든 기기라고 생각하시면 되겠네요.
근데, 여기서 중요한 사실 한가지가 있는데요.
일부 모델을 제외한 MSX2 이상의 본체에는 DRAM에 매퍼가 장착되어 있고,
코나미 메가롬팩 안에도 대용량 롬을 처리하기위한 매퍼가 들어가 있습니다.
둘다 메모리 매퍼라고 불러도 상관없지만,
일반적으로 MSX 에서 메인램에 연결된 것을 '메모리 매퍼'라고 부르고요,
메가롬팩이나 재미나 메가램팩 등에 들어 있는 건, '메가롬 매퍼'라고 합니다.
헷갈릴 수 있지만, 오래전(?)부터 그렇게 이름을 붙인거니 그냥 이해해주세요.
그럼, 이번 내용은 메인램에 관리하는 '메모리 매퍼'에 대한 것임을 알수 있겠죠? ^^
(메가롬 매퍼는 필요하시면, 따로 강좌를 만들겠습니다요~)
MSX의 슬롯 구조에서 64KB의 CPU 메모리 공간은 16KB 4조각으로 관리됩니다.
만약 슬롯에 메모리 최대 용량인 64KB를 모두 채우면,
기본적으로 MSX-DOS에서 모두 램으로 활용이 가능하고요. (물론, 시스템의 Work Area는 제외)
BASIC에서는 주소가 8000H~FFFFH인 Page2,3만 램으로,
Page0,1은 BIOS/BASIC인터프리터로 세팅이 되는데요.
CALL MEMINI 등의 램디스크 기능을 사용하면,
나머지 0000H~7FFFH의 32KB를 램 디스크로 모두 활용할 수 있습니다.
여기서 잠깐 Work Area의 대한 얘기도 해야겠군요.
MSX가 구동되는 동안에는, 각종 시스템 설정이 저장될 공간이 필요한데요.
이 영역을 Work Area라고 부릅니다.
주소는 FFFFH 에서부터 0000H 방향으로 내려오면서 메모리가 할당 되는데,
시스템의 중요 변수들은 미리 주소가 정해져서 할당되어 있습니다.
예를 들어, LINLEN 이라는 시스템 변수의 주소는 F3B0H 인데요,
현재 텍스트 모드의 WIDTH 값을 저장하고 있습니다.
BASIC에서 WIDTH 명령을 쓰거나, DOS에서 MODE 명령으로 수평 글자수를 바꿀수가 있는데,
이때 설정 값이 기록되어 있습니다.
만약 프로그램에서 텍스트 화면의 특정 영역을 복사 또는 스크롤 한다면,
이런 설정값을 참조해서 프로그래밍를 하면 되겠지요.
시스템 변수 이외에도, 각종 BIOS 점프 루틴(확장BIOS처리 또는 HOOK)이나
슬롯에 있는 롬SW가 사용하는 설정 값들도 Work Area에 저장됩니다.
특히 BASIC 인터프리터가 사용하는 영역도 꽤 됩니다.
그렇다면, MSX에서 메인램에 로딩할 수 있는 프로그램의 크기는,
DOS상에서 약 55KB 정도, BASIC라면 23KB 정도 되겠네요.
만약 MSX에 연결된 디스크 기기가 많거나, Work Area를 많이 쓰는 SW가 슬롯에 존재할 경우,
여유 메모리는 점점 줄어들게 됩니다.
만약 BASIC 상태에서 여러가지 커맨드 확장 루틴(기계어 코드)을 로딩했을때는,
이런 부족한 메모리로는 활용이 쉽지 않다는 상태에 직면하게 됩니다.
물론 롬으로 만들어서 슬롯에 주르륵 탑재한다면 편하겠지만,
매번 EPROM에 구워서 SW 교체하는 식은 별로 편하다고 볼수 없겠지요.
일단 메모리 매퍼가 없는 경우에도 메모리를 확보할수 있는 방법은,
BASIC 모드에서 사용하지 않는 0000H~7FFFH의 메모리를 슬롯 전환을 통해 쓰거나,
비디오 메모리의 일부를 데이터 저장으로 활용할수 있습니다.
MSX2의 경우는 0000H~7FFFH의 메모리를 램디스크로 사용하면
디스크에서 데이터/프로그램 읽고 쓰는 것보다 훨씬 빠르니 좋죠.
더 많은 메모리가 필요하다면... 메모리 매퍼를 사용해야합니다.
메모리 매퍼 레지스터 사용법은 슬롯 전환 방법과 매우 유사한데요.
메모리는 16KB로 분할되어 세그먼트 번호가 매겨집니다.
만약 128KB 램이 매퍼에 연결되어 있다면, 총 16KB x 8개의 세그먼트를 쓸수 있는것이죠.
근데 한가지 주의해야될 사항은,
MSX/MSX2의 메인 BIOS는 메모리 매퍼 구성에 관여를 하지 않습니다.
좀 애매한 설명이지만, ^^
메모리 매퍼를 활용하려면 BIOS와는 상관없이 메모리 관리하는 SW를 만들어야한다는 얘기입니다.
MSX2+/MSXturboR은 부팅시 모든 슬롯의 메모리 매퍼의 용량은 체크합니다만,
실제 관리는 DOS2의 메모리 매퍼용 확장 BIOS 루틴을 써야만 합니다.
일단 DOS2의 도움없이 사용하는 방법은 이렇습니다.
I/O 주소는 아래 네개가 사용됩니다.
FCH : Page0(0000H~3FFFH)의 세그먼트 전환
FDH : Page1(4000H~7FFFH)의 세그먼트 전환
FEH : Page2(8000H~BFFFH)의 세그먼트 전환
FFH : Page3(C000H~FFFFH)의 세그먼트 전환
만약 Page1의 메모리를 세그먼트 5로 바꾼다면,
LD A,5
OUT (0FDH),A
등의 명령으로 바꿀수 있습니다.
사실 바꾸는건 간단한데, 다시 이전 세그먼트로 복구하는건 쉽지 않습니다.
원래 Page1에 세팅된 세그먼트 번호를 알아야하는데요.
그걸 알아내려면,
다른 Page에 램 세그먼트를 하나씩 바꿔가면서 특정 값을 기록하고,
원래 Page의 값이 같이 바뀌는지를 체크하면 알수가 있습니다.
물론 체크후에는 원래 값으로 복구시켜야겠지요.
저도 이런건 생각만 했지 실제로 메모리 활용하기위해 이렇게 프로그래밍해본 적은 없습니다.
한때 매퍼 레지스터를 읽어서 세그먼트 번호로 쓴적은 있었어요.
나중에 알고보니 이렇게 하면 안되는거더군요.
상당수 프로그램(터보알용 게임 포함)이 이런 잘못된 램 테스트를 함으로써, 구동에 실패합니다.
SW 만드는 사람 마음이겠지만, 개조안된 특정 본체에서 구동되도록 만들었다면,
같은 모델 쓰든 다른 사람도 같은 결과물을 얻을수 있겠지요.
무슨 소리인지 대충 이해하셨으리라고 믿고, 간단하게 BASIC으로 테스트해보겠습니다.
MSX2의 BASIC 모드에서 기본 메모리맵은 아래처럼 됩니다.
Page0/1 : 메인 BIOS 및 BASIC 인터프리터
Page2/3 : 메인 램 (Page3 끝에는 WorkArea 존재)
만약 BASIC 프로그램을 작성하게 되면 Page2 부터 저장이 되는데요.
그럼, Page2의 메모리 세그먼트(16KB)를 바꾸면 기존 프로그램을 지우지 않고
새로운 프로그램을 저장할 수 있게됩니다.
아래 BASIC 프로그램을 그대로 따라서 한번 해보세요.
실제 MSX 기종에서는 매퍼 상태에 따라 동작 안될수 있으니,
에뮬레이터에서 MSX2 기종으로 부팅해서 해보시기 바랍니다.
참고로 저는 paraMSX의 FS-A1WSX 설정으로 테스트했습니다.
부팅후, 프로그램 하나(한줄짜리 ^^)를 입력합니다.
10 PRINT "This is RAM segment 1"
run으로 실행시키면 아래처럼 되겠죠? (Ok는 BASIC 프롬프트입니다. 입력하지는 마세요. ㅋ)
This is RAM segment 1
Ok
그럼, 여기서 Page2의 세그먼트를 바꿔서 다른 프로그램을 입력해보겠습니다.
OUT (&HFE),2
Ok
new
Ok
새 프로그램을 입력합니다.
10 PRINT "New program in RAM segment 2"
20 PRINT "Hello MSX"
run으로 실행하면
New program in RAM segment 2
Hello MSX
Ok
라고 나오죠?
그럼, 다시 Page2를 원래 세그먼트로 복구해보겠습니다.
OUT (&HFE),1
Ok
list
10 PRINT "This is RAM segment 1"
Ok
처음에 입력한 프로그램이 나오나요?
매퍼의 상태를 설명드리면,
현재 동작중인 MSX 본체의 메모리 매퍼가 초기에 아래처럼 됩니다.
한번더 강조하지만, 매퍼 설정은 모든 MSX에서 동일한 것이 아닙니다.
제품 만드는 사람 마음이에요. ^^
Page0: RAM segment 3
Page1: RAM segment 2
Page2: RAM segment 1
Page3: RAM segment 0
뭔가 감이 오시죠?
처음 프로그램을 입력 후, Page2의 세그먼트를 2번으로 전환하고 다른 프로그램을 입력한 것입니다.
요건 간단한 메모리 세그먼트 전환이 어떻게 되는지 설명하기 위한것이었고요.
실제로 사용시, 여러개의 BASIC 프로그램을 빠르게 전환하려면
램디스크 기능을 쓰는게 훨 편합니다. ^^
만약 DOS1에서 프로그램을 만든다면,
기본 프로그램은 Page0,1을 쓰고 부가적인 루틴은 16KB씩 나눠서
Page2에 세그먼트 전환으로 사용하면 좋겠지요.
만약 DOS2에서 구동되는 프로그램이라면, 매퍼 레지스터를 직접 액세스하면 안됩니다.
DOS2의 확장 BIOS에서 제공하는 루틴을 쓰면 쉽게 세그먼트 관리를 할수가 있습니다.
자세한 설명은 아래 홈페이지를 참고하세요. "5. MAPPER SUPPORT ROUTINES"를 보시면 됩니다.
http://map.grauw.nl/resources/dos2_environment.php
실제 사용은 어셈블리로 해야되니,
이번 강의에 예제 코드를 올리는건 좀 무리겠네요. ^^
방법을 요약하면,
1. 먼저 확장 BIOS 루틴의 매퍼 엔트리(주소)를 얻어와야합니다.
2. 엔트리에서 필요한 루틴(세그먼트 할당/전환 등등)을 직접 CALL하면 됩니다.
3. 세그먼트 할당시 유저/시스템 두가지 영역을 지정할 수 있습니다.
4. 유저 영역은 프로그램이 종료되면 할당된 세그먼트가 자동으로 반환됩니다.
5. 시스템 영역은 프로그램이 종료하더라도 할당된 상태가 유지됩니다.
시스템 영역은 서로 다른 프로그램이 데이터를 공유하거나,
프로그램이 종료된 후 다시 실행해서 재사용 하는데 쓸수 있습니다.
PS. 아래 스크린샷은 paraMSX에서 BASIC 프로그램 예제를 실행한 모습입니다.
댓글 없음:
댓글 쓰기