Close

Working on disk DSR

A project log for RC2016/99: TI-99/4A clone using TMS99105 CPU

Retrochallenge 2016/10 entry and winner: try to build a TI-99/4A clone using a TMS99105 CPU and an FPGA. In a month...

erik-piehlErik Piehl 11/08/2016 at 11:010 Comments

In the TI parlance device drivers were called DSRs, or Device Service Routines. I started working one, in order to support disk drives (i.e. SD cards and PC access) in a manner compatible with existing TI software. Perhaps it is due to the terminology, perhaps it's because I never had a disk drive for the original TI, but it took some reading to start to understand how the software setup works. As one might expect for systems of the day, it does not seem complex. I got last evening to the point where the TI recognizes my DSR and calls it when DSK1 or DSK2 is accessed.

The way the TI firmware works is such that it constructs in video memory (of all places - but that was the primary memory of an unexpanded TI-99/4A) a structure called "PAB". It has the following layout (story continues after the code below):

Byte 0: OPCODE
Byte 1: Flagbyte/status
        MSB 7 6 5 4 3 2 1 0 LSB
            | | | | | | | |
            | | | | | | | +— Filetype: 0=sequential, 1=relative record type
            | | | | | +-+--- Mode of operation(2): 00=Update, 01=Output, 10=Input, 11=Append
            | | | | +——— Datatype: 0=Display, 1=Internal
            | | | +————Record type: 0=Fixed length, 1=Variable length
            +-+-+—————————— Errorcode(3): 0 = no error
Bytes 2,3: Data buffer address
Byte 4: Logical record length: 
* Record length of fixed records or
* Max length of variable record length (see flag byte)
Byte 5: character count:
* Number of characters to be transferred for write opcode, or
* number of bytes actually read for a read opcode
Bytes 6, 7: Record number: 
* only required for relative record type file
* indicates the record number of the current I/O operation (0-32767)
* highest bit ignored
Byte 8: screen offset: 
* offset of the screen characters in respect to their normal ASCII value
Byte 9: Name length:
* Length of the file descriptor following the PAB
Byte 10+: File descriptor:
* device name and, if required, the filename and options.
* the length of this descriptor is given in 9.

My simple DSR just computes the address of the PAB in VDP memory, and copies the PAB into CPU RAM at address >8010. This address would in a regular TI be mapped to the scratchpad RAM (the address decoding is not fully implemented, so the 256 byte RAM repeats in memory four times, but is normally accessed at address >8300). In my system the scratchpad is 1024 bytes, so I have 768 bytes of extra memory available in the memory map, in the region >8000..82FF which is unused by normal TI software.

My PC interface circuit has access to the external SRAM, including the region >8000..>82FF, so I was able to successfully read the PAB from TI's memory after my DSR routine copied it over there. So this is a starting point for a disk subsystem implementation! So far I have only tested what types of PAB's are created by TI BASIC using "save" and "load" commands. Basically I wrote a one line program, something like:

10 print "hello world"
save DSK1.HELLO
and the command save "DSK1.HELLO" resulted in a call into my DSR (after I realized that the device names indeed are case sensitive). The DSR copied the PAB from VDP RAM to CPU RAM, and from there I was able to read the following back to the PC:
8000  0b 14 00 01 07 00 12 34  00 01 60 df a7 b7 00 0e  |.......4..`.....|
8010  06 00 3f ea 00 00 00 16  60 0a 44 53 4b 31 2e 48  |..?.....`.DSK1.H|
8020  45 4c 4c 4f 00 00 00 00  00 00 00 00 00 00 00 00  |ELLO............|
So we can see the opcode at memory location >8010 (6 stands for SAVE) and the device/filename can be seen from >801A onwards. My DSR at this point does not do much more, it just sets an error code and returns successfully to firmware i.e. BASIC.While the functionality at this point does not seem much, these are the building blocks to first create a disk subsystem on PC and later with the SD card available through the FPGA.

Discussions