From 0d563870d27505bfe926e384e7a1670edd35e19e Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Mon, 2 Feb 2026 14:15:37 -0800 Subject: [PATCH] TMS Clean Up, Issue #649 This is still a work in progress! --- Source/HBIOS/std.asm | 11 +- Source/HBIOS/tms.asm | 314 +++++++++++++++++++++++-------------------- 2 files changed, 171 insertions(+), 154 deletions(-) diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 761ba9c9..59f034c9 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -317,11 +317,12 @@ TMSMODE_N8PC .EQU 11 ; N8 BUILT-IN VIDEO + PS2 KEYBOARD ; ; TMS DRIVER VDP TYPES ; -TMSVDP_TMS9918 .EQU 0 ; TMS9918A -TMSVDP_V9938 .EQU 1 ; YAMAHA V9938 VDP (WITH 64K TO 192K VRAM) -TMSVDP_V9958 .EQU 2 ; YAMAHA V9958 VDP (WITH 64K TO 192K VRAM) -TMSVDP_SUPER .EQU 3 ; FPGA V9958 MODULE WITH EXTENSIONS -TMSVDP_F18A .EQU 4 ; MSX FPGA TMS9918 REPLACEMENT +TMSVDP_UNK .EQU 0 ; UNKNOWN +TMSVDP_TMS9918 .EQU 1 ; TMS9918A +TMSVDP_V9938 .EQU 2 ; YAMAHA V9938 VDP (WITH 64K TO 192K VRAM) +TMSVDP_V9958 .EQU 3 ; YAMAHA V9958 VDP (WITH 64K TO 192K VRAM) +TMSVDP_SUPER .EQU 4 ; FPGA V9958 MODULE WITH EXTENSIONS +TMSVDP_F18A .EQU 5 ; FPGA TMS9918 REPLACEMENT ; ; CVDU VIDEO MODE SELECTIONS ; diff --git a/Source/HBIOS/tms.asm b/Source/HBIOS/tms.asm index 7e45d12a..430c2e24 100644 --- a/Source/HBIOS/tms.asm +++ b/Source/HBIOS/tms.asm @@ -9,7 +9,7 @@ ; 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 ; UPDATED BY: HENK BERENDS - 1/15/2026 - ADDED F18A FPGA DETECTION AND REPORT VDP_ID IN VDADEV FUNCTION - +; ;====================================================================== ; ; TODO: @@ -22,6 +22,29 @@ ; - DETECT VRAM SIZES 4KB,16KB AND 32KB ; - REPORT OTHER ATTRIBUTES IN VDADEV FUNCTION? ; +; +;====================================================================== +; +; NOTES: +; +; - WHEN SETTING REGISTERS, YOU FIRST WRITE THE VALUE FOLLOWED BY +; THE ACTUAL VALUE. IF A TMS VDP INTERRUPT OCCURS BETWEEN THESE +; TWO PORT OUTPUTS, IT WILL DISRUPT THE SEQUENCE. IF VDP INTS +; ARE ACTIVE, THEN INTS MUST BE DISABLED WHEN SETTING REGISTERS. +; +; - THE TMS CHIP FAMILY IS VERY SENSITIVE TO REQUIRED DELAYS BETWEEN +; PORT WRITES. TMS9938/58 REQUIRES LONGER DELAY THAN 9918. THE +; DRIVER IMPLEMENTS THESE DELAYS IN SOFTWARE, BUT MAY NEED TO BE +; TUNED DEPENDING ON SPEED OF SYSTEM CPU. THE V9958 HAS A /WAIT +; PIN THAN CAN BE CONNECTED TO THE CPU. IF THIS IS USED, THEN +; THE SOFTWARE WAITS CAN POTENTIALLY BE DISABLED. HOWEVER, I +; HAVE NOT HAD SUCCESS WITH THIS IN PRACTICE. +; +; - THE TMS80COLS EQUATE IS CURRENTLY OVERLOADED. IF IT IS NOT SET +; ON A 9958 CHIP, THEN THE CODE WILL TREAT THE 9958 AS THOUGH IT +; IS A 9918 AND MAY NOT WORK WELL (FOR EXAMPLE, DELAYS WILL BE +; WRONG). +; ;====================================================================== ; TMS DRIVER - CONSTANTS ;====================================================================== @@ -225,8 +248,11 @@ USBKYBENABLE .SET TRUE ; INCLUDE USB KEYBOARD SUPPORT ; #IF (CPUFAM == CPU_Z180) ; BELOW WAS TUNED FOR Z180 AT 18MHZ - #DEFINE TMS_IODELAY EX (SP),HL \ EX (SP),HL ; 38 W/S - ;#DEFINE TMS_IODELAY NOP \ NOP \ NOP \ NOP \ NOP ; 20 W/S ### JLC Mod for Clock/2 (9 MHz) ### + ;#DEFINE TMS_IODELAY EX (SP),HL \ EX (SP),HL ; 38 T/S + ;#DEFINE TMS_IODELAY EX (SP),HL \ EX (SP),HL \ EX (SP),HL \ EX (SP),HL \ EX (SP),HL \ EX (SP),HL ; 76 T/S + #DEFINE TMS_IODELAY CALL DLY4 ; 100 T/S + + ;#DEFINE TMS_IODELAY NOP \ NOP \ NOP \ NOP \ NOP ; 20 T/S ### JLC Mod for Clock/2 (9 MHz) ### #ELSE #IF (PLATFORM == PLT_MSX) #DEFINE TMS_IODELAY EX (SP),HL \ EX (SP),HL @@ -235,7 +261,7 @@ USBKYBENABLE .SET TRUE ; INCLUDE USB KEYBOARD SUPPORT #IF (TMS80COLS) #DEFINE TMS_IODELAY NOP \ NOP \ NOP \ NOP \ NOP \ NOP \ NOP ; V9958 NEEDS AT WORST CASE, APPROX 4us (28T) DELAY BETWEEN I/O (WHEN IN TEXT MODE) #ELSE - #DEFINE TMS_IODELAY NOP \ NOP ; 8 W/S + #DEFINE TMS_IODELAY NOP \ NOP ; 8 T/S #ENDIF #ENDIF #ENDIF @@ -342,60 +368,34 @@ TMS_INIT: RET ; TMS_INIT1: - CALL PRTSTRD - .TEXT " VDP=$" - - HB_DI + HB_DI ; NO INTERRUPTS DURING PROBES AND INITIALIZATION +; + ; PROBE AND RECORD CHIP TYPE CALL TMS_GETTYP ; A <- 0: TMS9918A, 1: V9938, 2: V9958, 3: SUPER V9958, 4:F18A - LD (TMS_ATTRIB),A ; SET VDP_ID IN LOW BYTE OF DEVICE ATTRIBUTES - HB_EI - + LD (TMS_VDPID),A ; SET VDP_ID IN LOW BYTE OF DEVICE ATTRIBUTES +; ; PRINT THE CHIP TYPE DETECTED - LD DE,TMS_CHIPSTR - CALL PRTIDXDEA - + PRTS(" VDP=$") ; TAG + LD DE,TMS_CHIPSTR ; POINT TO CHIP ID STRINGS + CALL PRTIDXDEA ; PRINT +; + ; PRIMARY CRT INITIALIZATION CALL TMS_CRTINIT ; SETUP THE TMS/V99x8 CHIP REGISTERS -TMS_INIT2: - ; ONLY DO VRAM DETECTION FOR V99X8 (NOT THE TMS OR F18A) - - LD A, (TMS_ATTRIB) - OR A - JR Z, TMS_INIT3 ; SKIP VRAM PROBE FOR TMS9918x - CP TMSVDP_F18A - JR Z, TMS_INIT3 ; SKIP VRAM PROBE FOR F18A - - CALL PRTSTRD - .TEXT " VRAM=$" - - CP TMSVDP_SUPER ; SUPER HAS 1MB OF VRAM, NO NEED TO PROBE IT - JR NZ, TMS_INIT2A - - CALL PRTSTRD - .TEXT "1MB$" - JR TMS_INIT3 - -TMS_INIT2A: - - 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$") - + ; PROBE AND RECORD CHIP VRAM SIZE + CALL TMS_VRMPRB ; PROBE FOR VRAM SIZE + LD (TMS_RAMID),A ; SET VDP_RAMID IN HIGH BYTE OF DEVICE ATTRIBUTES +; + ; PRINT CHIP VRAM SIZE + OR A ; SET FLAGS + JR Z,TMS_INIT3 ; IF SIZE UNKNOWN, SKIP + PRTS(" VRAM=$") ; TAG + LD DE,TMS_VRAMSTR ; POINT TO VRAM SIZE STRINGS + CALL PRTIDXDEA ; PRINT +; TMS_INIT3: + HB_EI ; RESTORE INTERRUPTS +; #IF (TMSTIMENABLE) CALL PRTSTRD #IF (TICKFREQ == 50) @@ -561,7 +561,7 @@ TMS_VDARES: RET TMS_VDADEV: - LD BC,(TMS_ATTRIB) ; C := DEVICE ATTRIBUTES: VDP ID (B:= 0,RESERVED) + LD BC,(TMS_ATTRIB) ; C := DEVICE ATTRIBUTES (C=VDPID, B=VRAM SIZE ID) LD D,VDADEV_TMS ; D := DEVICE TYPE LD E,0 ; E := PHYSICAL UNIT IS ALWAYS ZERO LD H,TMSMODE ; H := MODE @@ -796,11 +796,11 @@ TMS_PROBE: LD A,$A5 ; FIRST BYTE EZ80_IO OUT (TMS_DATREG),A ; OUTPUT - CALL DLY64 ; DELAY + TMS_IODELAY CPL ; COMPLEMENT ACCUM EZ80_IO OUT (TMS_DATREG),A ; SECOND BYTE - CALL DLY64 ; DELAY + TMS_IODELAY ; ; SET READ ADDRESS TO $0000 LD HL,0 @@ -809,12 +809,12 @@ TMS_PROBE: LD C,$A5 ; VALUE TO EXPECT EZ80_IO IN A,(TMS_DATREG) ; READ FIRST BYTE - CALL DLY64 ; DELAY + TMS_IODELAY CP C ; COMPARE RET NZ ; RETURN ON MISCOMPARE EZ80_IO IN A,(TMS_DATREG) ; READ SECOND BYTE - CALL DLY64 ; DELAY + TMS_IODELAY CPL ; COMPLEMENT IT CP C ; COMPARE RET ; RETURN WITH RESULT IN Z @@ -831,39 +831,40 @@ TMS_GETTYP: JR Z,TMS_ISF18A ; IF TMS9918A CHECK FOR F18A VARIANT ; ; NOT A 9918 OR F18A, SO USE VDP ID - 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 + LD C,15 ; REGISTER #15 + LD A,1 ; SELECT STATUS REGISTER #1 + CALL TMS_SET_X ; DO IT + EZ80_IO + IN A,(TMS_CMDREG) ; READ STATUS BYTE (VDP ID) + TMS_IODELAY + + AND 00111110B ; ISOLATE VDP ID BITS RRCA ; 00000 - V9938 1 ; 00010 - V9958 2 ; 10010 - v9958 3 ; ; RESTORE SELECT REGISTER TO S#0 FOR INT HANDLER - PUSH AF - XOR A - EZ80_IO - OUT (TMS_CMDREG),A - LD A,15 + 128 - EZ80_IO - OUT (TMS_CMDREG),A - POP AF + PUSH AF ; SAVE VDP ID + LD C,15 ; REG #15 + XOR A ; SELECT STATUS REG #0 + CALL TMS_SET_X ; DO IT + POP AF ; RESTORE VDP ID ; ; RETURN THE IDENTIFIED CHIP ID - JR Z, TMS_ISV9938 - CP TMSVDP_V9958 - RET Z ; RETURN 2 FOR V9958 - LD A, TMSVDP_SUPER - RET ; RETURN 3 FOR SUPER V9958 - -TMS_ISV9938: - INC A ; RETURN 1 (TMSVDP_V9938) - RET + LD E,TMSVDP_V9938 ; ASSUME 9938 + OR A ; IS IT SO? + JR Z,TMS_GETTYP_Z ; IF YES, DONE + INC E ; ASSUME 9958 + CP %00000010 ; IS IT SO? + JR Z,TMS_GETTYP_Z ; IF YES, DONE + INC E ; ASSUME SUPER 9958 + CP %00010010 ; IS IT SO? + JR Z,TMS_GETTYP_Z ; IF YES, DONE + LD E,TMSVDP_UNK ; FAILSAFE OF UNKNOWN +; +TMS_GETTYP_Z: + LD A,E ; VDP ID TO A + RET ; AND DONE TMS_ISF18A: ; CHECK FOR F18A FPGA/EMULATOR VARIANT @@ -871,28 +872,19 @@ TMS_ISF18A: ; RETURN A <- 0:TMS9918A 4:F18A ; ; UNLOCK THE F18A: SEND VALUE $1C TO REGISTER 57 TWICE + LD C,57 ; REG #57 LD A,$1C ; UNLOCK VALUE - EZ80_IO - OUT (TMS_CMDREG),A - LD A,57 + 128 ; REGISTER #57 - EZ80_IO - OUT (TMS_CMDREG),A + CALL TMS_SET_X ; DO IT LD A,$1C ; UNLOCK VALUE - EZ80_IO - OUT (TMS_CMDREG),A - LD A,57 + 128 ; REGISTER #57 - EZ80_IO - OUT (TMS_CMDREG),A + CALL TMS_SET_X ; DO IT AGAIN ; - ; GET VDP ID - LD A,1 ; SELECT S#1 - EZ80_IO - OUT (TMS_CMDREG),A - LD A,15 + 128 ; REGISTER #15 + ; READ STATUS REGISTER #1 + LD C,15 ; REG #15 + LD A,1 ; SELECT STATUS REG #1 + CALL TMS_SET_X ; DO IT EZ80_IO - OUT (TMS_CMDREG),A - EZ80_IO - IN A,(TMS_CMDREG) ; READ S#1 + IN A,(TMS_CMDREG) ; READ STATUS REG #1 + TMS_IODELAY ; ; CHECK FOR F18A AND 11110000B ; MASK HIGH NIBBLE @@ -902,36 +894,28 @@ TMS_ISF18A: ; ON A TRUE 9918, THE F18A UNLOCK CODE ABOVE WILL ENABLE ; INTERRUPTS (REGISTER 57 ON A REAL 9918 WILL BE TREATED ; AS REGISTER 1!). HERE WE GET INTERRUPTS TURNED BACK OFF. - LD A, (TMS_INITVDU_REG_1) - RES TMSINTEN,A ; RESET INTERRUPT ENABLE BIT - LD C, TMSCTRL1 - CALL TMS_SET_X ; SET REG W/O INT MGMT + LD C,TMSCTRL1 ; REGISTER #1 + LD A,(TMS_INITVDU_REG_1) ; VALUE TO SET + RES TMSINTEN,A ; CLEAR INTERRUPT ENABLE BIT + CALL TMS_SET_X ; DO IT ; WE DON'T BOTHER TO RESET THE STATUS REGISTER SELECTION OR ; RELOCK BECAUSE THIS IS NOT AN F18A! - XOR A ; CHIP ID FOR 9918A (TMSVDP_TMS9918) - RET ; NOT F18A: A=0 + LD A,TMSVDP_TMS9918 ; CHIP ID FOR 9918A + RET ; DONE TMS_ISF18A1: - ; RESTORE STATUS REGISTER S#0 FOR INT HANDLER - XOR A ; SELECT S#0 / NOT F18A - EZ80_IO - OUT (TMS_CMDREG),A - LD A,15 + 128 - EZ80_IO - OUT (TMS_CMDREG),A + LD C,15 ; REG #15 + XOR A ; VALUE + CALL TMS_SET_X ; DO IT ; - ; RELOCK THE F18A - XOR A ; LOCK VALUE - EZ80_IO - OUT (TMS_CMDREG),A - LD A,57 + 128 ; REGISTER #57 - EZ80_IO - OUT (TMS_CMDREG),A + LD C,57 ; REG #57 + XOR A ; VALUE + CALL TMS_SET_X ; DO IT ; - LD A, TMSVDP_F18A ; F18A: A=4 + LD A,TMSVDP_F18A ; F18A RET - + ; ; TEST IF THE VDP IS A TMS9918A. ; @@ -947,35 +931,33 @@ TMS_ISF18A1: ; TMS_IS9918: LD C,TMS_CMDREG ; POINT TO CMD REG PORT + TMS_IODELAY ; TMSIS9918_WAIT1: EZ80_IO - IN A,(C) ; READ S#0, MAKE SURE INTERRUPT FLAG (F) IS RESET + IN A,(C) ; READ S#0 + TMS_IODELAY JP M,TMSIS9918_WAIT1 ; LOOP UNTIL INT FLAG (F) IS RESET ; TMS_IS9918_WAIT2: EZ80_IO IN A,(C) ; READ S#0 + TMS_IODELAY JP P,TMS_IS9918_WAIT2 ; WAIT UNTIL INTERRUPT FLAG (F) IS SET ; ; READ VB STATUS - 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) + LD C,15 ; REG #15 (MIRRORS #7 ON 9918 VDP) + LD A,2 ; SELECT STATUS REG #2 + CALL TMS_SET_X ; DO IT EZ80_IO - OUT (TMS_CMDREG),A - EZ80_IO - IN A,(TMS_CMDREG) ; READ S#2 / S#0 + IN A,(TMS_CMDREG) ; READ STATUS #2 (9938/58) / STATUS #0 (9918) + TMS_IODELAY ; ; RESTORE SELECT REGISTER TO S#0 FOR INT HANDLER PUSH AF - XOR A - EZ80_IO - OUT (TMS_CMDREG),A - LD A,15 + 128 - EZ80_IO - OUT (TMS_CMDREG),A + LD C,15 ; REG #15 + XOR A ; SELECT STATUS REG #0 + CALL TMS_SET_X ; DO IT POP AF ; ; SET ZF APPROPRIATELY AND RETURN @@ -985,11 +967,32 @@ TMS_IS9918_WAIT2: ; PROBE VRAM SIZE OF V99x8 VDP ; ; ASSUMES INTERRUPTS ARE DISABLED (DI) +; ASSUMES CHIP VARIANT HAS ALREADY BEEN IDENTIFIED +; +; A <- 0: 1: 4K 2: 16K 3: 32K 4: 64K 5: 128K 6: 192K 7: 1MB ; -; A <- 1: 64K, 2: 128K, 3: 192K TMS_VRMPRB: - XOR A ; SET RETURN VALUE FOR 64K - INC A + ; HANDLE EXCEPTIONS + LD A,(TMS_VDPID) ; GET VDP ID + CP TMSVDP_TMS9918 ; IF BASIC TMS9918 + JR Z,TMS_VRMPRB_UNK ; ... THEN VRAM SIZE IS UNKNOWN + CP TMSVDP_F18A ; IF FPGA + JR Z,TMS_VRMPRB_UNK ; ... THEN VRAM SIZE IS UNKNOWN + CP TMSVDP_SUPER ; IF SUPER V9958 + JR Z,TMS_VRMPRB_1MB ; ... THEN VRAM SIZE IS ALWAYS 1MB + JR TMS_VRMPRB1 ; OTHERWISE, PROCEED TO DETECTION LOGIC +; +TMS_VRMPRB_UNK: + XOR A ; SET VALUE TO UNKNOWN + RET ; AND RETURN +; +TMS_VRMPRB_1MB: + LD A,7 ; SET VALUE TO 1MB + RET ; AND RETUNR +; +TMS_VRMPRB1: + ; START OF REAL VRAM PROBING + LD A,4 ; SET RETURN VALUE FOR 64K EX AF,AF' LD A,4 ; USE 16 BIT I/O ADDRESS FOR EZ80 COMPATIBILITY @@ -1030,7 +1033,7 @@ TMS_VRMPRB: VRAMSIZE_128K: ; WE HAVE AT LEAST 128K EX AF, AF' - INC A ; SET RETURN VALUE TO 1 FOR 128K + INC A ; SET RETURN VALUE TO 5 FOR 128K EX AF, AF' LD A, $40 ; CHECK TO SEE IF WE HAVE 192K (EXPANSION RAM INSTALLED) @@ -1071,7 +1074,7 @@ VRAMSIZE_128K: JR NZ,VRAMSIZE_DONE ; IF ITS $5A, WE HAVE EXAPANSION VRAM EX AF, AF' - INC A ; SET RETURN VALUE TO 2 FOR 192K + INC A ; SET RETURN VALUE TO 6 FOR 192K EX AF, AF' VRAMSIZE_DONE: @@ -1547,17 +1550,30 @@ TMS_CURSAV .DB 0 ; SAVES ORIGINAL CHARACTER UNDER CURSOR TMS_BUF .FILL 256,0 ; COPY BUFFER ; TMS_CHIPSTR: -TMS_STR9918 .TEXT "TMS9918A$" -TMS_STR9938 .TEXT "V9938$" -TMS_STR9958 .TEXT "V9958$" -TMS_STR9958X .TEXT "SUPER V9958$" -TMS_STRF18A .TEXT "F18A$" +TMS_STRUNK .TEXT "UNKNOWN$" ; 0 +TMS_STR9918 .TEXT "TMS9918A$" ; 1 +TMS_STR9938 .TEXT "V9938$" ; 2 +TMS_STR9958 .TEXT "V9958$" ; 3 +TMS_STR9958X .TEXT "SUPER V9958$" ; 4 +TMS_STRF18A .TEXT "F18A$" ; 5 +; +TMS_VRAMSTR: +TMS_STRRAMUNK .TEXT "UNK$" ; 0 +TMS_STRRAM4K .TEXT "4K$" ; 1 +TMS_STRRAM16K .TEXT "16K$" ; 2 +TMS_STRRAM32K .TEXT "32K$" ; 3 +TMS_STRRAM64K .TEXT "64K$" ; 4 +TMS_STRRAM128K .TEXT "128K$" ; 5 +TMS_STRRAM192K .TEXT "192K$" ; 6 +TMS_STRRAM1MB .TEXT "1MB$" ; 7 ; ; ### JLC Mod ; ANSI-->TMS Color Conversion Table TMS_COLOR_TBL .DB $01,$08,$02,$0A,$04,$06,$0C,$0F,$0E,$09,$03,$0B,$05,$0D,$07,$0F ; -TMS_ATTRIB .DW 0 ; VDA DEVICE ATTRIBUTES (VDP_ID,VRAM,FREQ) (TMSVDP_xxxx) +TMS_ATTRIB: +TMS_VDPID .DB 0 ; VDP CHIP ID (TMSVDP_...) +TMS_RAMID .DB 0 ; VDP VRAM SIZE ID ; ;================================================================================================== ; TMS DRIVER - INSTANCE DATA