|
|
|
@ -6,11 +6,14 @@ |
|
|
|
; UPDATED BY: DEAN NETHERTON -- 5/26/2021 - V9958 SUPPORT |
|
|
|
; UPDATED BY: JOSE L. COLLADO -- 11/15/2023 - MEMORY MAP CHANGES |
|
|
|
; UPDATED BY: DAN WERNER -- 2/11/2024 - DUODYNE SUPPORT |
|
|
|
; UPDATED BY: DAN WERNER -- 11/271/2025 - N8PC SUPPORT |
|
|
|
; UPDATED BY: DAN WERNER -- 11/27/2025 - N8PC SUPPORT |
|
|
|
; UPDATED BY: DEAN NETHERTON -- 1/7/2026 - ADDED RUNTIME DETECTION OF CHIP TYPE AND VRAM SIZE |
|
|
|
|
|
|
|
;====================================================================== |
|
|
|
; |
|
|
|
; TODO: |
|
|
|
; - CAN WE AUTO DETECT TMS VS V99x8 AND THUS AUTO SELECT TMS80COLS AT RUNTIME? |
|
|
|
; - CAN WE AUTO DETECT TYPE FOR FPGA EMULATED VERSIONS? |
|
|
|
; - IMPLEMENT SET CURSOR STYLE (VDASCS) FUNCTION? |
|
|
|
; - IMPLEMENT ALTERNATE DISPLAY MODES? |
|
|
|
; - IMPLEMENT DYNAMIC READ/WRITE OF CHARACTER BITMAP DATA? |
|
|
|
@ -318,10 +321,68 @@ TMS_INIT: |
|
|
|
RET |
|
|
|
; |
|
|
|
TMS_INIT1: |
|
|
|
CALL TMS_CRTINIT ; SETUP THE TMS/V99x8 CHIP REGISTERS |
|
|
|
; THIS IS BEST DONE BEFORE DETECTION OF TYPE |
|
|
|
; AND VRAM SIZE |
|
|
|
|
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT " VDP=$" |
|
|
|
|
|
|
|
CALL TMS_GETTYP ; A <- 0: TMS9918A, 1: V9938, 2: V9958, x: VDP ID |
|
|
|
|
|
|
|
INC A |
|
|
|
DEC A |
|
|
|
JR NZ, TMS_NOT9918 |
|
|
|
|
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT "TMS9918 VRAM=16KB INTERRUPT=60HZ$" |
|
|
|
JR TMS_INIT3 |
|
|
|
|
|
|
|
TMS_NOT9918: |
|
|
|
DEC A |
|
|
|
JR NZ, TMS_NOT9938 |
|
|
|
|
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT "V9938$" |
|
|
|
JR TMS_INIT2 |
|
|
|
|
|
|
|
TMS_NOT9938: |
|
|
|
; ASSUME V9958 |
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT "V9958$" |
|
|
|
|
|
|
|
TMS_INIT2: |
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT " VRAM=$" |
|
|
|
|
|
|
|
CALL TMS_VRMPRB |
|
|
|
|
|
|
|
DEC A |
|
|
|
JR NZ, NOT_64K |
|
|
|
|
|
|
|
PRTS("64KB$") |
|
|
|
JR TMS_INIT3 |
|
|
|
|
|
|
|
NOT_64K: |
|
|
|
DEC A |
|
|
|
JR NZ, NOT_128K |
|
|
|
|
|
|
|
PRTS("128KB$") |
|
|
|
JR TMS_INIT3 |
|
|
|
|
|
|
|
NOT_128K: |
|
|
|
PRTS("192KB$") |
|
|
|
|
|
|
|
#IF (TMSTIMENABLE) |
|
|
|
CALL PRTSTRD |
|
|
|
.TEXT " INTERRUPT ENABLED$" |
|
|
|
#IF (TICKFREQ == 50) |
|
|
|
.TEXT " INTERRUPT=50HZ$" |
|
|
|
#ELSE |
|
|
|
.TEXT " INTERRUPT=60HZ$" |
|
|
|
#ENDIF |
|
|
|
|
|
|
|
#ENDIF |
|
|
|
TMS_INIT3: |
|
|
|
CALL PC_SPACE |
|
|
|
LD A,TMS_COLS |
|
|
|
CALL PRTDEC8 |
|
|
|
@ -330,7 +391,6 @@ TMS_INIT1: |
|
|
|
LD A,TMS_ROWS |
|
|
|
CALL PRTDEC8 |
|
|
|
; |
|
|
|
CALL TMS_CRTINIT ; SETUP THE TMS CHIP REGISTERS |
|
|
|
CALL TMS_LOADFONT ; LOAD FONT DATA FROM ROM TO TMS STRORAGE |
|
|
|
; *** DIAGNOSE FONT LOAD ERROR HERE!!! *** |
|
|
|
CALL TMS_CLEAR ; CLEAR SCREEN, HOME CURSOR |
|
|
|
@ -712,12 +772,10 @@ TMS_PROBE: |
|
|
|
LD A,$A5 ; FIRST BYTE |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_DATREG),A ; OUTPUT |
|
|
|
;TMS_IODELAY ; DELAY |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
CPL ; COMPLEMENT ACCUM |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_DATREG),A ; SECOND BYTE |
|
|
|
;TMS_IODELAY ; DELAY |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
; |
|
|
|
; SET READ ADDRESS TO $0000 |
|
|
|
@ -727,18 +785,205 @@ TMS_PROBE: |
|
|
|
LD C,$A5 ; VALUE TO EXPECT |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_DATREG) ; READ FIRST BYTE |
|
|
|
;TMS_IODELAY ; DELAY |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
CP C ; COMPARE |
|
|
|
RET NZ ; RETURN ON MISCOMPARE |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_DATREG) ; READ SECOND BYTE |
|
|
|
;TMS_IODELAY ; DELAY |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
CPL ; COMPLEMENT IT |
|
|
|
CP C ; COMPARE |
|
|
|
RET ; RETURN WITH RESULT IN Z |
|
|
|
; |
|
|
|
; DETECT VDP VERSION |
|
|
|
; |
|
|
|
; ASSUMES INTERRUPTS ARE DISABLED (DI) |
|
|
|
; |
|
|
|
; A <- 0: TMS9918A, 1: V9938, 2: V9958, x: VDP ID |
|
|
|
; F <- z: TMS9918A, nz: other |
|
|
|
; |
|
|
|
TMS_GETTYP: |
|
|
|
; Code sourced from https://map.grauw.nl/sources/vdp_detection.php |
|
|
|
CALL TMS_IS9918 ; USE A DIFFERENT WAY TO DETECT TMS9918A |
|
|
|
RET Z ; RETURN 0 FOR TMS9918 |
|
|
|
LD A,1 ; SELECT S#1 |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
LD A,15 + 128 |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_CMDREG) ; READ S#1 |
|
|
|
AND 00111110B ; GET VDP ID |
|
|
|
RRCA |
|
|
|
|
|
|
|
EX AF,AF' |
|
|
|
XOR A ; RESTORE SELECT REGISTER TO S#0 FOR INT HANDLER |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
LD A,15 + 128 |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
EX AF,AF' |
|
|
|
|
|
|
|
RET NZ ; RETURN VDP ID FOR V9958 OR HIGHER |
|
|
|
INC A ; RETURN 1 FOR V9938 |
|
|
|
RET |
|
|
|
; |
|
|
|
; TEST IF THE VDP IS A TMS9918A. |
|
|
|
; |
|
|
|
; THE VDP ID NUMBER WAS ONLY INTRODUCED IN THE V9938, SO WE HAVE TO USE A |
|
|
|
; DIFFERENT METHOD TO DETECT THE TMS9918A. WE WAIT FOR THE VERTICAL BLANKING |
|
|
|
; INTERRUPT FLAG, AND THEN QUICKLY READ STATUS REGISTER 2 AND EXPECT BIT 6 |
|
|
|
; (VR, VERTICAL RETRACE FLAG) TO BE SET AS WELL. THE TMS9918A HAS ONLY ONE |
|
|
|
; STATUS REGISTER, SO BIT 6 (5S, 5TH SPRITE FLAG) WILL RETURN 0 INSTEAD. |
|
|
|
; |
|
|
|
; ASSUMES INTERRUPTS ARE DISABLED (DI) |
|
|
|
; |
|
|
|
; F <- Z: TMS9918A, NZ: V99X8 |
|
|
|
; |
|
|
|
TMS_IS9918: |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_CMDREG) ; READ S#0, MAKE SURE INTERRUPT FLAG (F) IS RESET |
|
|
|
|
|
|
|
TMS_IS9918_WAIT: |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_CMDREG) ; READ S#0 |
|
|
|
AND A ; WAIT UNTIL INTERRUPT FLAG (F) IS SET |
|
|
|
JP P,TMS_IS9918_WAIT |
|
|
|
|
|
|
|
LD A,2 ; SELECT S#2 ON V9938 |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
LD A,15 + 128 ; (THIS MIRRORS TO R#7 ON TMS9918 VDPS) |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
EZ80_IO |
|
|
|
IN A,(TMS_CMDREG) ; READ S#2 / S#0 |
|
|
|
|
|
|
|
EX AF,AF' |
|
|
|
XOR A ; RESTORE SELECT REGISTER TO S#0 FOR INT HANDLER |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
LD A,15 + 128 |
|
|
|
EZ80_IO |
|
|
|
OUT (TMS_CMDREG),A |
|
|
|
EX AF,AF' |
|
|
|
|
|
|
|
AND 01000000B ; CHECK IF BIT 6 WAS 0 (S#0 5S) OR 1 (S#2 VR) |
|
|
|
RET |
|
|
|
|
|
|
|
; PROBE VRAM SIZE OF V99x8 VDP |
|
|
|
; |
|
|
|
; ASSUMES INTERRUPTS ARE DISABLED (DI) |
|
|
|
; |
|
|
|
; A <- 1: 64K, 2: 128K, 3: 192K |
|
|
|
TMS_VRMPRB: |
|
|
|
XOR A ; SET RETURN VALUE FOR 64K |
|
|
|
INC A |
|
|
|
EX AF,AF' |
|
|
|
LD A,4 |
|
|
|
; USE 16 BIT I/O ADDRESS FOR EZ80 COMPATIBILITY |
|
|
|
; (AVOID NEED FOR EZ80_IO MACRO) |
|
|
|
LD BC, (IO_SEGMENT<<8)+TMS_CMDREG |
|
|
|
OUT (C),A |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A,$8E |
|
|
|
OUT (C),A ; R#14 = 4 -> A16 = 1, A15..A14 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
XOR A |
|
|
|
OUT (C),A ; A7..A0 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
OR $40 |
|
|
|
OUT (C),A ; SET WR, A13..A8 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A,$76 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD C, TMS_DATREG |
|
|
|
OUT (C),A ; SET VRAM $10000 = $76 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
XOR A |
|
|
|
LD C, TMS_CMDREG |
|
|
|
OUT (C),A ; A7..A0 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
|
|
|
|
OUT (C),A ; SET RD, A13..A8 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD C, TMS_DATREG |
|
|
|
IN A,(C) ; A = VRAM $10000 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
CP $76 |
|
|
|
JR Z,VRAMSIZE_128K ; IF ITS $76, WE HAVE AT LEAST 128K |
|
|
|
|
|
|
|
; OTHERWISE ITS ONLY 64K |
|
|
|
JR VRAMSIZE_DONE |
|
|
|
|
|
|
|
VRAMSIZE_128K: |
|
|
|
; WE HAVE AT LEAST 128K |
|
|
|
EX AF, AF' |
|
|
|
INC A ; SET RETURN VALUE TO 1 FOR 128K |
|
|
|
EX AF, AF' |
|
|
|
|
|
|
|
LD A, $40 ; CHECK TO SEE IF WE HAVE 192K (EXPANSION RAM INSTALLED) |
|
|
|
LD C, TMS_CMDREG |
|
|
|
OUT (C), A ; ENABLE EXANSION MEMORY ACCESS |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A, $80 | 45 |
|
|
|
OUT (C), A ; R#45 = $40 (MXC=1, MXD,MXS,DIY,DIX,EQ,MAJ=0) |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
|
|
|
|
LD A,1 |
|
|
|
OUT (C),A |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A,$8E |
|
|
|
OUT (C),A ; R#14 = 4 -> A16 = 0, A15..A14 = 1 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
XOR A |
|
|
|
OUT (C),A ; A7..A0 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
OR $40 |
|
|
|
OUT (C),A ; SET WR, A13..A8 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A,$5A |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD C, TMS_DATREG |
|
|
|
OUT (C),A ; SET VRAM $14000 = $76 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
XOR A |
|
|
|
LD C, TMS_CMDREG |
|
|
|
OUT (C),A ; A7..A0 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
OUT (C),A ; SET RD, A13..A8 = 0 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD C, TMS_DATREG |
|
|
|
IN A,(C) ; A = VRAM $14000 |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
CP $5A |
|
|
|
JR NZ,VRAMSIZE_DONE ; IF ITS $5A, WE HAVE EXAPANSION VRAM |
|
|
|
|
|
|
|
EX AF, AF' |
|
|
|
INC A ; SET RETURN VALUE TO 2 FOR 192K |
|
|
|
EX AF, AF' |
|
|
|
|
|
|
|
VRAMSIZE_DONE: |
|
|
|
XOR A |
|
|
|
LD C, TMS_CMDREG |
|
|
|
OUT (C), A ; DISABLE EXANSION MEMORY ACCESS |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A, $80 | 45 |
|
|
|
OUT (C), A ; R#45 = $00 (MXC=0, MXD,MXS,DIY,DIX,EQ,MAJ=0) |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
|
|
|
|
XOR A |
|
|
|
OUT (C),A |
|
|
|
CALL DLY64 ; DELAY |
|
|
|
LD A,$8E |
|
|
|
OUT (C),A ; R#14 = 0 -> A16..A14 = 0 |
|
|
|
|
|
|
|
EX AF, AF' |
|
|
|
RET |
|
|
|
|
|
|
|
; |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
; TMS9918 DISPLAY CONTROLLER CHIP INITIALIZATION |
|
|
|
;---------------------------------------------------------------------- |
|
|
|
|