Jump to content

Recommended Posts

Starting a new thread, as this affects multiple of the VDPs types and variants out there.

 

How can I reliably detect on what VDP I’m connected to?

And do this with the least code possible in assembly language (and as a bonus in TI Basic or TI Extended Basic).

 

This got me thinking, if going forward it makes sense and have agreed on to get a common ID register that returns type and firmware revision.

And just to be clear on this. I am in favour of having multiple VDPs out there, as this is the reality and we can all benefit from it.

Even if there’s a risk of fragmentation (no discussing it in this thread here please).

 

  • Like 3

A PICO9918 with the base TMS9918A firmware can't be distinguished from a regular TMS9918A (as far as I'm aware). There's no real reason to care either I guess.

 

When it comes to the F18A compatibility mode, there are well-established methods to detect an F18A, primarily using the GPU to set a value in VRAM. The PICO9918 in F18A compatibility mode can be unlocked and detected as F18A compatible using those same methods.

 

To distinguish an F18A from a PICO9918 at this point, you can read the ID status register (status register #1). As far as I can tell, the F18A uses the most significant 3-4 bits for its ID (0xE0). Currently, the PICO9918 sets those upper 3 bits to 0xE0 so it can be detected as F18A compatible, but also sets bit 3 high (where the F18A has it low). So, status register #1 will be 0xE8 for the PICO9918.

 

Note: My information on the F18A could well be wrong as it's only based on some observations I've made.

  • Like 4

Oh, the reason I say top 3-4 bits instead of the documented top 3 bits is some existing software seems to just check the high nibble is 1110 (0xE0) rather than masking out the top three bits.

 

That's the reason my PICO9918 ID bit is in the lower nibble, instead of being say... 0x10.

 

On the F18A, those top three bits should have the values:

  • 111 for F18A
  • 010 for V9958
  • 000 for V9938

When I add V9938 support to the PICO9918 (Yes, I have started on this @dhe and @Gary from OPA). I will ensure those top three bits are set the same way.

Edited by visrealm
  • Like 4

Thanks for the update, sounds good. This is something I think one can work with.

Do agree that when running in  F18a compatibility mode it perhaps does not make much sense to have a different reading (unless you like to tackle compatibility bugs/issues) from the client program.

At that stage it's perhaps just better to get a firmware upgrade if available.

  • Like 3

There was a conversation about this not too long ago here: https://forums.atariage.com/topic/207586-f18a-programming-info-and-resources/?do=findComment&comment=5468548

 

Ultimately the best solution is to just state your software requirements, i.e. "this program requires an F18A", or whatever, and just write your code under the assumption that the hardware is what you expect.  The 9918A did not provision for any kind of ID, and the 9938/58 did so in an undocumented and crappy way (mixing in a register that has other bits that reset (or not) on read).

 

There is no good way, so leave it to the user to know that they have some other VDP installed in their system.

 

Otherwise, if you insist, then every variation you want to support means a lot of extra code.

 

The F18A, 9938, and 9958 have "ID" bits set in SR1.  But just getting set up to read the extended status registers takes more code.  The F18A bits are designed to be detectable in the case where the VDP is not and F18A.  It does this by setting the three MS-bits of SR1 to "111", which if reading the 9918A/28/29 status register will return "000" in those bits when you read it twice in a row (and you do need to read it twice).

 

The 9938/59 have five "ID" bits, the F18A has three "ID" bits, in addition to the fixed MS-bits set to "111" as described above.

 

F18A/9938/58
L=light pen flag, 9938/58   -- reset on read
F=light pen switch, 9938/58 -- NOT reset on read
I=identity bits
B=blanking
H=horz interrupt flag       -- reset on read

9918A
F=Interrupt flag    - reset on read
S=Fifth sprite flag - reset on read
C=Coincidence flag  - reset on read
5=Fifth spite number

  Mask    Value
III000BH 111000BH   Up to v19
111III0H 1110000H   v1b onward, blanking bit removed
LFIIIIIH LF00000H   9938
LFIIIIIH LF00010H   9958
FSC55555 FSC55555   9918A SR0

MK0 111000BH (MK1 v19)
MK1 1110010H (starting with v1b)
MK2 1110100H (future)

 

So basically, the SECOND READ values for the MK0, MK1, MK2 (future), 9938, 9958 when reading SR1, or 9918A when reading SR0:

00111100 3C MASK
--------
00100000 20 MK0
00100100 24 MK1
00101000 28 MK2
00000000 00 9938
00000100 04 9958
000????? 0? 9918A

 

A mask of >3C is used over >FC because the 9938/58 have the light-pen bits that could be 1 or 0, so they need to be ignored.  The low two bits of the F18A are also dependent on VDP conditions, so those are also ignored via the mask.  The main unknown is the 9918A 5th Spite Number, I do not remember if testing was done to see what happens to it after reading the status.

 

After a 2nd read, any reset-on-read flags will be zero, and the ID can be inspected.  The F18A will report the same value for both reads, since all masked bits are constant.

 

*NOTE: I released 20 MK1 boards with a V1.A firmware that broke the SR1 having "111" in the MS-bits.  I am working to make sure those boards are updated, and anyone with that revision can get a newer firmware that will correct that minor screw up.  Sorry about that.

 

  • Like 1
  • Thanks 1

Thank you for the detailed explanation, this really helps me to better understand.

Stating what VDP the code is expecting is a good idea and can go with that.

It’s not that big of a deal to have multiple revisions of the code for the specific VDPs 

(depending on the feature set used)

 

I just was thinking about a VDP identification library that could be used

in assembly language or extended basic to kinda (realiably) detect the installed VDP and then

let it up to the program developer to just halt the program with a corresponding message,

if the required VDP isn’t there.

 

Discussing the details and challenges, is most interesting and this thread will certainly be added to my documentation

 

  • Like 1

Currently evaluating CVBasic as an option to produce a platform independent config tool for the PICO9918. It's looking promising.

 

Here's some initial (not pretty) CVBasic code that works to determine if the current machine is running an original TMS VDP (or a PICO9918 with base firmware) versus a genuine F18A versus a PICO9918. And in the case of the last two, also reads the firmware version.

 

'
' Project: pico9918tool
'
' Copyright (c) 2024 Troy Schrapel
'
' This code is licensed under the MIT license
'
' https://github.com/visrealm/pico9918
'

    PRINT AT 36,"PICO9918 TOOL"

    PRINT AT 36 + 64, "DETECTING..."
    
    GOSUB vdp_detect
    
    IF isF18ACompatible THEN
        PRINT AT 36 + 64, "DETECTED F18A COMPATIBLE"
        
        VDP(15) = 1
        ASM movb @VDPSTATUS, @vdp_status
        statReg = VDP.STATUS
        VDP(15) = 14
        ASM movb @VDPSTATUS, @vdp_status
        verReg = VDP.STATUS
        VDP(15) = 0
        verMaj = (verReg AND $f0) / 16
        verMin = verReg AND $0f
        
        IF (statReg AND $E8) = $E8 THEN
            PRINT AT 36 + 128, "PICO9918 ver ", verMaj, ".", verMin
        ELSEIF (statReg AND $E0) = $E0 THEN
            PRINT AT 36 + 128, "GENUINE F18A ver ", verMaj, ".", verMin
        ELSE
            PRINT AT 36 + 128, "STATUS REG 1 = ", <>statReg
        END IF
        
    ELSE
        PRINT AT 36 + 64, "DETECTED ORIGINAL TMS9918A VDP"
    END IF
    
game_loop:
    WAIT
    GOTO game_loop

vdp_detect: PROCEDURE
    GOSUB vdp_unlock
    DEFINE VRAM $3F00, 6, vdp_gpu_detect
    VDP($36) = $3F                        ' set gpu start address msb
    VDP($37) = $00                      ' set gpu start address lsb (triggers)
    isF18ACompatible = VPEEK($3F00)=0    ' check result
    END    
    
vdp_unlock: PROCEDURE
    VDP(1) = $C2        ' disable interrupts
    VDP(57) = $1C       ' unlock
    VDP(57) = $1C       ' unlock... again
    VDP(1) = $E2        ' enable interrupts
    END

vdp_gpu_detect:
    ' TMS9900 machine code (for GPU) to write $00 to VDP $3F00
    DATA BYTE $04, $E0  ' CLR  @>3F00
    DATA BYTE $3F, $00
    DATA BYTE $03, $40  ' IDLE    

 

Thanks to @nanochess for adding the new VDP.STATUS command to CVBasic literally overnight (for me). It is used to get the status register value which was read during the last interrupt.

 

I was hoping I could use it like this:

 

VDP(15) = 1
WAIT
status1 = VDP.STATUS
VDP(15) = 0

 

Unfortunately, that doesn't work for grabbing the F18A's virtual status registers since the interrupt handler needs to read status register #0 to clear the interrupt and it has no way of knowing it's currently set to an extended status register. As a workaround, I've added some in-line assembly for the TMS9900 so this code won't work for any other systems at the moment. Will need a platform-independent method of doing that preferably.

 

I've attached the compiled version which runs fine on JS99'er and can determine if the current VDP is an F18A or not. On my real TI-99, it can query all three VDP types correctly.

pico9918tool_8.bin

  • Like 5
  • Thanks 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...