2025년 10월 18일 토요일

SLT-Turbo 제작 #18 - 기본 사용법


1) SLT-X 및 MIDI 케이블 연결


단자 위치를 확인하세요.




2) 기본 셋업


대부분의 MSX2 이상 기종들은 외부 슬롯 커넥터가 2개 있습니다.

IQ2000, X-II는 슬롯 커넥터 1개와 확장버스 커넥터(IDC 단자 모양)가 1개 있죠.


사용자 환경에 따라, 상단/전면 또는 후면 슬롯에 SLT-Turbo를 장착하면 되겠습니다.

아래는 A1WSX의 상단 슬롯에 장착한 모습입니다.



아래는 A1WSX의 후면 슬롯에 장착한 모습입니다.

상단 슬롯에 PAC-V를 꽂으면 딱 맞는 셋업이 되겠습니다!



아래는 X-II의 전면 슬롯에 장착한 모습입니다.

전면에 카트리지를 세로로 꽂을 수 있는 어댑터를 쓰셔도 좋겠습니다.



만약 IQ2000, X-II의 후면 슬롯에 연결하려면, 당연히 '확장버스 to 에지슬롯' 어댑터가 필요하겠습니다.

갖고 계신 분은 활용하시면 좋을 듯요! ㅎ.ㅎ



3) 최소 셋업


'나는 SLT-X도 없고 주변기기도 별로 없는데, 그냥 SLT-Turbo만 꽂아서 쓸 수 없나요?'

라고 생각하시는 분들을 위한 사용법입니다 ㅎ.ㅎ


SLT-X 대신 카트리지를 연결할 수 있는 어댑터가 제공됩니다.

이걸 MMC/SD V4에 꽂으세요! ㅎ.ㅎ



아래는 A1WSX의 후면 슬롯에 SLT-Turbo와 MMC/SD V4를 장착한 모습입니다.

MIDI 모듈이 있다면, 케이블을 함께 연결하면 되겠네요.

PAC-V를 상단 슬롯에 꽂으면 더 좋구요 ㅎ.ㅎ



이 상태에서 본체의 전원을 켜면, SLT-Turbo가 turboR GT로 부팅되는 걸 볼 수 있겠습니다.

그 다음은 뭐... 그냥 GT를 쓰는 것 처럼 사용하시면 되겠네요. ㅎ.ㅎ/


그럼, 다음편에서 보아요~


2025년 10월 16일 목요일

SLT-Turbo 제작 #17 - Z80 듀얼 프로세서

[서론]

제목이 살짝 낚시(ㅋ) 같습니다만... 으흠, 암튼 그렇습니다요 ㅎ.ㅎ


본체에 SLT-Turbo를 꽂으면, 본체의 Z80은 기본적으로 I/O 프로세서로 동작합니다.

실제로는 Z80 2개가 병렬로 동작하고 있지만, 사용자 입장에서는 CPU가 하나처럼 느껴지게 됩니다.


만약, 아예 작업을 나눠서 두개의 CPU로 구동할 수 있다면 어떨까요? 작업시간을 절반으로 낮출 수 있겠죠!


예를 들어 곱셈 구구단 표를 만들 때,

Z80 1번: 1단 ~ 5단 계산

Z80 2번: 6단 ~ 9단 계산

-> 이렇게 동시에 동작하는 걸 의미합니다.


물론 단순 계산작업이 아닌 주변기기 I/O가 포함된 작업이라면, I/O를 기준으로 CPU 코드를 나눠야겠지만요.



[본론]


그럼, 실전으로 넘어갑시다!

듀얼 CPU를 활용하는 동영상 플레이어를 만들어보아요~

이름은 MV2 player입니다!


기존 MV player의 경우,

초당 12프레임의 비디오 데이터를 SD카드에서 VRAM으로 전송하고,

VRAM 전송 중 틈틈이 오디오 데이터를 PCM으로 출력합니다.

SD카드는 커맨드를 보내고 응답받는데 걸리는 시간이 제각각이라서, 동작 시간도 계산해서 구현해야하죠.

코딩할 때 명령어 하나씩 사이클 계산해서 맞추느라 무쟈게 귀찮...ㅋ



MV2에서는 아래처럼 작업을 나눕니다.


SLT-Turbo:

 SD카드에서 데이터 읽기

 비디오 데이터를 공유버퍼로 전송

 MP3 데이터 출력(WAU 카트리지)


본체:

 공유버퍼의 비디오 데이터를 VRAM으로 전송

 키입력(ESC 키) 상태를 SLT-Turbo로 전달


본체의 Z80은 동작시간 대부분을 VRAM 전송하며 보내게 됩니다.

페이지 플리핑이나 팔레트 변경도 들어가겠지만, VRAM 데이터량에 비하면 '새발의 피'입니다요.


CPU가 단순 VRAM 전송만 해도 된다면, 최대 전송량은 얼마가 될지 계산해봐야겠죠?

OUTI 풀어쓰기로 VRAM 전송과 팔레트 설정을 할테니,

-> 1바이트 전송에 Z80 19클럭이 필요합니다. (MSX2+, turboR 기준)


SCREEN 2 풀스크린 256 x 192 화면에서 전송량

패턴테이블 = 6144 bytes

컬러테이블 = 6144 bytes

팔레트 = 30 bytes

-> 총 12318 bytes


초당 처리가능한 bytes 수를 계산해보면....

3579545clk / 19clk / 12318 = 15.29 frame/s

-> 초당 15프레임이 가능하다는 결론이 나옵니다.


15프레임은 디스플레이 60프레임 / 4로 나눠지니까, 페이지 플립을 해도 문제없으니 딱 좋네요 ㅎ.ㅎ



본체의 Z80에서 비디오 1프레임을 VRAM에 전송 후 CPU IDLE 타임을 표시해보면 아래처럼 나타납니다.

화면 아래쪽에서 스캔라인 테두리(BD) 영역이 녹색으로 보이는 부분이 CPU IDLE입니다.




SLT-Turbo쪽에서는 MMC/SD V4에서 MV2 데이터를 읽은 후 공유 버퍼에 저장합니다.

오디오는 직접 출력을 하는데요. 기존 MV 11kHz PCM에서 MV2 128kbps MP3로 바뀌었습니다.

I/O는 WAU 전용이니까, WAU가 없으면 무음으로 출력됩니다 ㅎ.ㅎ


설명이 길었네요. 그럼, 실제 동작 모습을 보시죠!




[결론]


예전 SLT-Turbo V1을 만들고 나서, 활용할 방법을 생각하느라 시간이 좀 걸렸습니다.

사실 SLT-Turbo V2도 애매한 포지션이라서 접었었구요.

결국 이 듀얼 CPU 활용 때문에 SLT-Turbo V2.1으로 진행이 되었습니다~ ㅎ.ㅎ/


그럼, 다음편에서 보아요~


2025년 10월 8일 수요일

SLT-Turbo 제작 #16 - Z80 확장명령

1) Z280 호환 명령


turboR 호환기를 만들기 위해서는 R800에 추가된 곱셈 명령도 구현이 필요합니다.

SLT-Turbo V1에서는 Z280을 활용했지만, 이번에는 그냥 CPLD의 도움으로 처리했어요.


Z80 명령어 ED C0 ~ ED FF, 총 64개 명령어 공간을 사용합니다.

오리지널 Z80에서 이 명령어를 쓰면 그냥 무시됩니다. NOP 명령을 2개 쓴 효과랑 같아요.


참고로, Z280의 경우는 이 영역 대부분이 확장 명령어로 들어 있습니다.

8bit 곱셈/나눗셈, 16bit 곱셈/나눗셈, signed/unsigned 다 있죠.


R800은 unsigned 8bit, 16bit 곱셈 명령어 중에서 극히 일부인 6개만 들어가는데요,

SLT-Turbo에서는 unsigned 곱셈 명령어 10개를 넣었습니다.


ED C1 ; MULUB  A,  B -> HL ; Z280/R800

ED C3 ; MULUW HL, BC -> DE:HL ; Z280/R800

ED C9 ; MULUB  A,  C -> HL ; Z280/R800

ED D1 ; MULUB  A,  D -> HL ; Z280/R800

ED D3 ; MULUW HL, DE -> DE:HL ; Z280

ED D9 ; MULUB  A,  E -> HL ; Z280/R800

ED E1 ; MULUB  A,  H -> HL ; Z280

ED E3 ; MULUW HL, HL -> DE:HL ; Z280

ED E9 ; MULUB  A,  L -> HL ; Z280

ED F3 ; MULUW HL, SP -> DE:HL ; Z280/R800


한가지 주의할 부분은 이 곱셈 명령어들의 결과 flag 처리는 넣지 않습니다요.

(사실 곱셈결과에 의미있는 flag가 없...ㅋ)

간단한 테스트 프로그램으로 곱셈 결과가 맞는지 확인해보아요~



그나저나, turboR이 나온지 거의 35년이 됐는데, R800 곱셈을 쓰는 상용프로그램이 없다는 게 참 신기하죠?

제가 만든 ASO remake가 유일한 R800 테스트 프로그램이라고 볼 수 있겠는데요.

지난번 동작하는 영상을 보셨을테니 ASO는 넘어갑니다~ ㅎ.ㅎ



2) X-II BIOS 확장


X-II의 BIOS는 롬영역을 다 쓰고 있어서, 추가 코드를 넣을 공간이 없습니다.

심지어 BIOS 엔트리까지 다 잡아먹고 있죠. (역시 내일이 없는 회사ㅋ)


CHGGPU(0180H), GETCPU(0183H) 루틴을 명령어 하나로 대체하도록 해봤습니다.

ED FE ; CHGCPU

ED FF ; GETCPU


원래 BIOS 엔트리는 JP NN 코드(3바이트)를 넣게 되어있는데,

확장 명령어가 2바이트니까 RET 명령까지 다 넣으면 딱 3바이트로 끝나게 됩니다.

아래처럼 되겠네요 ㅎ.ㅎ



음... 사실 굳이 이렇게 만들 필요는 없는데요.

예전 paraMSX-R과 MMC/SD V4에서는 BIOS롬을 뱅킹으로 처리해서 코드를 확장하긴 했었죠 ㅎ.ㅎ



3) 고속 LDIR


Z80에서는 LDIR, OTIR의 비중이 큰데요.

OTIR, OUTI 등의 경우는 주변장치의 속도(VDP 등)때문에 고속으로 최적화할 여지가 별로 없겠구요.

LDIR은 LDI x N개로 풀어(unroll)쓰는 걸 많이 사용합니다.

메모리 여유가 있다면 루프 명령을 쓰는 것 보다는 많이 빠르니까요.


물론 기존 디스크롬들은 이미 다 적용이 되어있죠.

지금 해보려는 건... 고속모드에서 더 빠르게 돌리기 위해 메인램에서 코드를 구동하는 것입니다.


요약하면, '외부 슬롯의 코드에서 LDI x N 풀어쓰기가 필요할 때 메인램에서 구동'입니다.


일단 2개의 명령어를 만들어봤어요.

ED CF ; LDIR

ED DF ; LDIR256


ED CF는 기존 LDIR과 똑같은 기능이지만 속도만 더 빠른 버전이구요.

실제로는 RAM에서 LDI x 32개로 풀어진 명령어로 최적화가 됩니다.


ED DF는 LDIR 수행 시 반복(루프)를 256 배수일 때 쓰면 더 빠른 버전입니다.

실제로는 RAM에서 LDI x 256개가 루프를 돌게 됩니다요.

보통 디스크에서 섹터를 읽게 되면 1섹터 512바이트씩 전송을 하니까 이 경우 꽤 쓸모가 있어요.


turboR에서는 MMC/SD V4로 DOSSCAN을 돌려보면 520~540KB/s 정도가 나오는데요.

SLT-Turbo + V4에서 구동하면 470KB/s 정도가 나옵니다.

이걸 LDIR 최적화 명령어를 이용하면 560KB/s 수준으로 빨라지게 됩니다.

아래 사진 참고하세요.




그럼, 다음편에서 보아요~