2010년 7월 30일 금요일

DOS2 Banking Library & Build tool 제작 #5

이번에는 특정 슬롯의 메모리를 R/W 할수 있는 함수들을 만들어봤습니다.

MPX 또는 MMC/SD 드라이브, 메가플래시롬팩 등의 메모리맵 I/O를 쓰는 기기를 액세스시 사용할 수 있습니다.

 

1바이트 R/W는 MSX 메인 바이오스 루틴을 쓰면 페이지 제한없이 가능하니깐,

일단 메인 바이오스 콜을 기본으로 넣었습니다.

 

그 다음은 블럭 메모리 전송인데, 이 경우는 목적지 페이지1,2만 가능하도록 했습니다.

메모리 위치는 페이지 상관없지만, 목적지 페이지와 동일하면 안되겠지요.

물론 전송 사이즈가 커서 어드레스가 페이지를 가로지르면 문제가 됩니다요. ㅋ

안전하게 페이지0->1, 페이지1->2, 페이지2->1 등등으로 

 

테스트용으로 MPXP 프로그램을 뱅킹 라이브러리를 쓰도록 초간단 버전을 하나 만들었습니다.

이름은 MPXPS (마지막 S는 Simple을 의미합니다.ㅋ)

참고로, 뱅킹라이브러리 릴리즈할때, MPXPS 소스도 예제로 들어갈 예정입니다.

 

실행해보니, MMC/SD HW V2에서 128KBPS짜리가 겨우 돌아가는 정도는 되네요. ㅎ.ㅎ

사실 원본 MPXP는 전송루틴이 어셈으로 되어서 속도가 조금 빠른편인데요,

어셈 안쓰고 일반 C함수 콜만으로도 어느정도는 쓸만한 것 같습니다. ㅋ

  

그 외, 틈틈히 필요한 함수들 만들고 있습니다.

키보드 입력(RAW I/O)이나 터보알/파나소닉MSX2P CPU 모드 등등...

점점 라이브러리가 커지고 있네요. ㅋ

 

그래픽과 사운드(BGM?) 예제 두어개 만들면, 이대로 1차 릴리즈해야될거 같습니다.

생각날때마다 조금씩 진행하다보니 진도가 넘 느리네요. ㅎ.ㅎ

 

혹시 관심있으신분, 요청사항 있으면 댓글 달아주세요.


2010년 7월 18일 일요일

DOS2 Banking Library & Build tool 제작 #4

몇주 쉬다가 다시 작업 들어갔습니다. ㅎ

 

인터럽트 처리를 보완하기 위해 구상을 좀더 해봤습니다.

 

일단 DOS2 상태에서 인터럽트가 발생되면,

기존 SW의 ISR(Interrupt Servie Routine)을 구동하기 위해, 페이지0이 원래의 메인 BIOS로 변경이 됩니다.

 

결국, 이 때는 원래 프로그램 내의 루틴이 정상으로 돌아갈 수 있는 상태가 아닌 것이지요.

각 뱅크(페이지0,1) 내의 ISR을 처리하기 위해, 페이지0의 슬롯 처리 및 뱅킹 처리가 같이 되어야 합니다.

 

그외 BIOS의 ISR 처리는 여러가지 키보드 등의 입력 기기와 음악(PLAY) 루틴이 함께 들어가있는데,

필요 없는 코드를 그대로 실행할 필요는 없을 것 같고요.

여기에 추가로 KEYI와 TIMI 두개의 훅(HOOK) 으로 실행되는 유저 ISR도 옵션 처리가 가능하도록 바꿨습니다.

보통 TIMI 훅에는 디스크 드라이버의 타이머 루틴이나 그 외 타이머 류의 SW가 들어가게 되는데,

필요한 경우 멈출수 있도록 하는 것이지요.

 

이렇게 하려면, 메인 BIOS에서 첫 KEYI 훅으로 유저 ISR이 콜될때 강제로 스택의 리턴 주소를 지우고,

따로 필요한 ISR만 콜해주면 쉽게 됩니다.

기존 BIOS 루틴의 JIFFY 카운트도 따로 처리합니다.

 

VDP의 스프라이트 충돌, 스캔라인 인터럽트(H-Blank), V싱크 인터럽트(V-Blank) 3개의 인터럽트와

외부 인터럽트 8개를 사용할 수 있도록 했습니다. (좀 많나요? ㅋ)

 

일단 ISR 우선 순위는 아래처럼 해놨습니다.

EXT0,EXT1,HBLK,EXT2,EXT3,SPRT,VBLK,EXT4,EXT5,EXT6,EXT7

의 순으로 체크됩니다.

 

EXTn -> 외부 인터럽트

HBLK -> VDP H-Blank

VBLK -> VDP V-Blank

SPRT -> VDP Sprite 충돌

인데요.

여기서 스프라이트 충돌은 실제 VDP에서는 인터럽트가 아니라 단지 State만 알려주는 것인데,

V-Blank 때 같이 인터럽트로 ISR를 콜하도록 해놨습니다.

 

특별히 게임이나 음악 등 타이밍 처리를 위한 wait 함수들도 구현해봤습니다.

VDP의 60Hz V-Blank 인터럽트를 활용한 것인데요.

물론 기존의 JIFFY 값으로 처리해도 상관없지만 어셈으로 만든 라이브러리가 쓰기편할테니...ㅋ

wait_60hz(), wait_30hz() 이런식의 함수로, 타이밍 동기처리를 할 수 있습니다.

 

그리고, 게임 등 경우에 따라, 범용 키보드 I/O가 필요없을 때에는,

메인 BIOS의 키처리 루틴을 스킵할 수 있습니다.

물론 C라이브러리의 scanf 등으로 키입력을 쓸때는 켜놔야겠지요. (기본은 상태는 ON 입니다.)

 

실제로 모두 구현해서 테스트해보니,

DOS2의 매퍼 뱅킹 처리나, 슬롯 전환 등의 코드가 수행되느라 인터럽트 응답이 약간 느리긴한데요.

그래도 편리성을 생각하면, 이런식이 훨씬 쓰기 편한 것 같습니다요.

 

인터럽트 처리는 이정도로 마무리하고,

다음은 각 슬롯의 메모리맵 I/O를 위한 루틴을 만드려고 합니다. 

 

아래는 인터럽트 테스트를 위해 만든 코드가 돌아가는 모습인데요.

터보알에서 VDP의 스캔라인 인터럽트와 V-Blank의 타이밍 루틴을 이용해서,

화면이 좌우로 흔들리는 효과를 구현해봤습니다. (참고로 좌우 흔들림은 V9938의 ADJUST 기능입니다.)




2010년 6월 22일 화요일

[강좌] 04. MSX의 메가롬 매퍼

메가롬 매퍼를 모르시는 분은 아마 없겠지만, 간단하게 설명해볼까합니다. ㅎ.ㅎ

(MSX로 게임을 안하셨다면, 모르실지도 !!!)


먼저 메가롬이 뭔지 알아야겠지요?


일반적인 롬카트리지 형태의 SW는 기본적으로 페이지1,2를 사용하도록 되어있습니다.

(참고로 MSX의 페이지, 슬롯이 헷갈린다면 지난 강좌를 찾아보세요~)


메인 BIOS가 부팅시 각슬롯의 롬 SW를 체크해서 초기화 루틴을 수행한다고 했었죠?

이때 롬의 초기화 루틴, BASIC 확장 루틴 등등 외부에서 콜되는 루틴들은

모두 페이지 1에 있어야 합니다. 요건 MSX SW 표준의 일부입니다.


롬 SW 전체 표준에 대해서는 여기서 다루지 않겠지만, 약간 설명드리면...

기본적으로 롬 SW는 BASIC 또는 DOS상에서 실행될 수 있도록 만들어져 있습니다.

사실 롬 자체는 페이지0부터 3까지 모두 사용하도록 만들어도 되지만,

일반적으로 페이지0의 메인 BIOS를 자주 액세스 하게 되고,

페이지3도 램으로 쓰는게 일반적입니다.


여기서 페이지 한개는 16KBytes이니까,

결국 롬으로 된 SW는 16KB 또는 32KB 크기로 만들수 있다는 말이 됩니다.

일반적으로 롬이나 램의 크기는 비트(어드레스 개수 x 데이터 라인 개수)로 나타내는데요.

대표적인 128KBit의 EEPROM이 16Kbytes 용량이 되겠습니다.

많은 MSX 롬팩들이 단일 128KBit 롬 하나로 만들어져 있지요.


그럼 256KBit 롬팩은 사이즈가 두배가 되는 프로그램이겠죠?

용량이 크면 좀 더 재밌는 게임이 될 확률은 있었지요. ㅎ.ㅎ


참고로 롬 카트리지 또는 주변기기의 BIOS를 만들경우, CPU가 페이지1,2를 액세스할때

 부가적인 어드레스 디코더 회로가 필요할 수 있습니다.

(어드레스 디코더란 원하는 CPU 어드레스가 되는 것을 디텍트 하는 용도로 쓰입니다.)


MSX 슬롯 커넥터의 핀들 중에 1,2,3번 핀이 각각 /CS1,/CS2,/CS12 신호를 출력하는데요.

이게 페이지 셀렉트 신호입니다.

롬팩 만드는데 매번 어드레스 디코더를 붙여야 한다면, 귀찮기도 하겠지만 HW 제작 단가도 

올라가겠죠? 그래서 요건 MSX 본체에서 기본적으로 신호를 만들어 주는 것이지요.

16KBytes EPROM 두개로 32KBytes 롬팩 만들때는 요긴하게 쓸 수 있겠지요.

(간단 롬 하나로 만들때는 /CSxx 핀들은 별로 쓸모가 없긴합니다요.)


메가롬과 메가롬 매퍼가 왜 필요한지 설명하려다 보니, 일반 롬 설명을 어쩔수 없이 하게 

되었네요.


서론이 길었습니다. 그럼 메가롬팩은 뭘까요?

롬 용량이 Mega Bit 급인 롬을 사용하는 롬팩입니다.

(참고로 1Mega Bit는 128KBytes입니다요.)


앞에서 얘기했지만, 기본적으로는 페이지1,2가 해당 롬의 슬롯으로 매핑되니까,

32KB를 초과하는 프로그램 또는 데이터는 그냥 액세스가 불가능하겠지요.

MSX2부터 지원되는 메모리 매퍼의 경우 16KB씩 세그먼트로 관리되어 매핑되는 것 처럼,

메가롬팩도 비슷한 방법을 사용합니다.


보통 메가롬팩은 8KB 또는 16KB씩 분할해서 매핑할수 있도록 회로를 내장하고 있습니다.

참고로 코나미 SCC의 경우는 사운드와 메가롬 매퍼가 합체(!)된 칩이고요.


그럼 분할된 8KB의 롬 뱅크는 어떻게 선택할까요?

메모리 매퍼의 경우는 IO 맵 방식으로 회로가 만들어져 있지만,

메가롬 매퍼는 메모리맵 방식으로 구현이 되어있습니다.

그러니까 특정 어드레스에 페이지 번호를 Write하면 원하는 뱅크의 메모리가 매핑되게 됩니다.


코나미 8KB 매퍼의 동작을 예로 들어보겠습니다.

(http://bifi.msxnet.org/msxnet/tech/megaroms.html 한번 참고하세요.)


아래처럼 뱅크 4개로 나누어져 있고,

처음 부팅을 하게 되면 페이지가 순서데로 매핑이 되어있습니다. (롬의 첫 32KB영역)

여기서 페이지는 메가롬 매퍼의 8KB 분할 공간을 의미하는 것입니다.

MSX 슬롯의 16KB 분할된 페이지를 말하는 건 아니에요.


Bank 1: 4000H - 5FFFH  -> Page0

Bank 2: 6000H - 7FFFH  -> Page1

Bank 3: 8000H - 9FFFH  -> Page2

Bank 4: A000H - BFFFH  -> Page3


각 뱅크의 페이지는 아래의 주소에 해당 페이지 값을 쓰면 바뀌게 됩니다.


Bank 1: 변경 불가

Bank 2: 6000H - 7FFFH (주로 6000H)

Bank 3: 8000H - 9FFFH (주로 8000H)

Bank 4: A000H - BFFFH (주로 A000H)


만약 부팅 후 6000H에 4를 쓰고, 8000H에 5를 쓴다면,

각 뱅크의 페이지는 아래처럼 바뀌게 되겠죠?


Bank 1: 4000H - 5FFFH  -> Page0

Bank 2: 6000H - 7FFFH  -> Page1

Bank 3: 8000H - 9FFFH  -> Page4

Bank 4: A000H - BFFFH  -> Page5


이런식으로 슬롯의 페이지1,2 영역에서 32KB를 초과하는 롬의 데이터를 매핑할수 있도록 됩니다.

만약 그라디우스 같은 슈팅 게임에서 배경화면 데이터를 8KB로 관리한다면,

뱅크 하나만 바꾸면서 쉽게 데이터를 읽을 수가 있겠지요.

물론 SW 관점에서 본다면, 매핑되는 뱅크 페이지에 따라 CPU의 주소가 결정되니까,

각종 데이터나 서브루틴들을 잘 관리해야 되겠지요.


이런 메가롬 매퍼는 코나미, 아스키 매퍼가 많이 쓰이고요.

게임에 따라 특수한 분할방식과 IO를 쓰는 경우도 있습니다.

뱅크는 8KB 또는 16KB 분할이 주로 쓰입니다.

특이하게 MSX-AUDIO 카트리지는 32KB 분할의 메가롬 매퍼를 갖고 있지요.

부팅시 첫 페이지 매핑은 롬팩에 따라 조금씩 다른 경우가 있지만,

대부분 페이지0,1,2,3 이런 순서 그대로 초기화됩니다.


특이하게 MSX-DOS2 카트리지는 용량이 64KB인데요. (DOS2 커널 48KB + KANJI 드라이버 16KB)

16KB 분할 매퍼로 구현되어있습니다.

메가롬은 아니지만 메가롬 매퍼와 비슷하게 구현되어 있습니다.

참고로 MMC/SD 드라이브의 BIOS도 8KB 분할의 SCC 매퍼로 구현되어 있는데요.

DOS1 커널 + DOS2 커널 + MMC/SD 드라이버 + 롬디스크가 512KB 한개 플래쉬롬으로 되어있지요.


일종의 메가롬팩 에뮬레이터인 재미나 램카드는, 8KB 매퍼와 16KB 매퍼를 다 갖고 있는데요.

게임에 따라 8KB 또는 16KB로 설정해서 사용합니다.

참고로 재미나 8KB 매퍼는 코나미 8KB 매퍼와 구조가 동일합니다.

따라서 아스키 8KB 매퍼용 게임은 코나미 매퍼 방식으로 롬을 패치해서 로딩하게 됩니다.


코나미의 스내쳐/SD스내쳐 게임에 들어있는 SCC사운드 카트리지에는 64KB의 DRAM이 들어있는데요.

DRAM을 128KB로 증설하게 되면, 1메가비트 메가롬팩 처럼 사용이 가능합니다.

물론 SCC칩도 들어 있으니, 파로디우스,사라만다 등의 게임에서 SCC 사운드도 즐길수가 있지요.


근데, 이런 메가램카드의 경우 전원을 끄면 내용이 사라지게 때문에,

게임을 하려면 매번 디스크에서 롬파일을 다운로드해야합니다.

요즘엔 플래시롬을 활용한 카트리지가 있어서, 실제 롬팩을 쓰는 것처럼 즐길 수가 있지요.

(참고로, 플래시롬은 한번 Write되면 전원이 꺼져도 내용이 그대로 남아있습니다.)

SCC메가플래시팩이나 MMC/SD 드라이브의 롬팩 기능이 대표적이겠지요.


글 내용을 요약하면 아래와 같습니다.

- 메가롬팩은 용량이 메가비트급이다. (1MBit = 128KBytes)

- 롬 SW는 페이지0,1,2를 주로 사용, 메가롬팩은 페이지1,2를 주로 사용.

- 32KB를 초과하는 영역은 메가롬 매퍼로 페이지1,2에 매핑됨.

- 메가롬 매퍼는 주로 8KB 또는 16KB 단위로 매핑됨.

- 재미나 램카드, SCC메가플래시팩 등으로 메가롬팩을 에뮬할수 있다.