E Sent from my iPad
On Jan 28, 2024, at 5:29 PM, Darren Clark <biggran...@gmail.com> wrote: Minor correction. Any commands that get translated to an index higher than 0x13 will return an invalid command, not crash the firmware. This statement is incorrect: "I haven't looked for any other logic that would prevent this, but a command 0x13 to 0x2A (except 0x23), or 0x35 to 0x3F will select addresses past the jump table (author name and reset vector table) causing the firmware to crash and reset." [F104] [58 ] [X ] ASL B ;B*2 - set pointer correctly for function table [F105] [C1 26 ] [ & ] CMP B #0x26 ;if command > 0x13 branch to Command_FMT_Invalid [F107] [24 2E ] [$. ] BCC Command_FMT_Invalid The "I haven't looked..." part is true, I found it at F014 and F105. So the firmware does protect against invalid commands. Darren Clark On 1/28/24 12:40, Darren Clark wrote: The part of the code that picks out the commands is a bit goofy, but I believe it's like this to maintain a standard command set across multiple drives with other added functionality. There is a bit mask for the command, so we're only looking at the lower 6 bits (0x00 to 0x3F). Bit 6 and 7 (6 being bank select) is masked out of the command selection code. It'll require some more digging around to see where it is used. Here is some of the logic: If the command = 0x23 (line F0F5), make the command 0x09. This is the Drive Version Info command. If the command > 0x30, subtract 0x22 from it. That makes the following commands into index positions: 0x30 = 0x0E 0x31 = 0x0F 0x32 = 0x10 0x33 = 0x11 0x34 = 0x12 The end result is the command becomes the index of the jump table: Index Command Function 0x00 0x00 ;Command_FMT00_CreateDirectory 0x01 0x01 ;Command_FMT01_FileOpen 0x02 0x02 ;Command_FMT02_FileClose 0x03 0x03 ;Command_FMT03_FileRead 0x04 0x04 ;Command_FMT04_File_Write 0x05 0x05 ;Command_FMT05_FileDelete 0x06 0x06 ;Command_FMT06_DiskFormat 0x07 0x07 ;Command_FMT07_DriveStatus 0x08 0x08 ;Command_FMT_Invalid 0x09 0x23 ;Command_FMT23_DriveVersionInfo (SM Page 93) 0x0A 0x0A ;Command_FMT_Invalid 0x0B 0x0B ;Command_FMT_Invalid 0x0C 0x0C ;Command_FMT0C_DriveCondition 0x0D 0x0D ;Command_FMT0D_FileNameChange 0x0E 0x30 ;Command_FMT30_SectorModeReadWrite 0x0F 0x31 ;Command_FMT31_DriveMemorySet 0x10 0x32 ;Command_FMT32_DriveMemoryGet 0x11 0x33 ;Command_FMT33_SystemVersionInfo (SM Page 92) 0x12 0x34 ;Command_FMT34_ExecuteProgram I haven't looked for any other logic that would prevent this, but a command 0x13 to 0x2A (except 0x23), or 0x35 to 0x3F will select addresses past the jump table (author name and reset vector table) causing the firmware to crash and reset. Also command 0x0F is the same as 0x31, so it returns the memory set return block 0x38. And looking at the table, there are several other overlapping commands: 0x0E, 0x10, 0x11, 0x12 The memory write commands set flags in the internal RAM, these need to still be deciphered. There is also a block of code that reads a file off of a disk into the 2K external RAM and executes it. On 1/28/24 10:45, Brian K. White wrote: This is great for making the emulators and clients definitive instead of full of mysteries and "here we recite the words lest the gods be angry". Can you see why command 0x11 works as a synonym for 0x33? And why does 0x0F respond with the 0x38 return block? When neither of those are commands. There are some other dupes like that too where an undocumented code results in some other response than the invalid code response. It's like it's not checking the entire value but masking bits, and looking at fewer than all 8 bits, and multiple values can give the same bits. Definitely bank 1 must work that way. A bunch of commands that all get one part of their meaning changed by adding 0x40, which is just flipping 1 bit on the normal command code. IE 0x00 is dirent, 0x40 is dirent in bank 1. Ah speaking of "we don't know why we do this but we must recite the words here" there are a few things exactly like that. The service manual describes a routine it calls "reset drive status" on pg 102. It's just using mem_write to write 3 bytes at 3 addresses but doesn't explain what they do. write 0xFF to 0x0084 write 0x0F to 0x0096 write 0x0F to 0x0094 And with dl2 I have captured TS-DOS doing exactly that sequence. The tpdd2 backup.ba<http://backup.ba> also does something similar but not the same, just before each each cache commit (write cache to disk): write 0x00 to 0x0083 write 0x00 to 0x0096 To be clear it never does the other 3 bytes, it just does these 2 before each cache write-to-disk. https://trs80stuff.net/tpdd/tpdd2_boot_disk_backup_log_hex.txt ... 17/08/2016 20:03:01.667 [M100] - 5A 5A 31 04 01 00 83 00 46 17/08/2016 20:03:01.671 [TPDD] - 38 01 00 C6 17/08/2016 20:03:01.676 [M100] - 5A 5A 31 04 01 00 96 00 33 17/08/2016 20:03:01.679 [TPDD] - 38 01 00 C6 ... They are in the cpu internal 128 bytes is all I can tell. Maybe one of those bytes holds the drive status/condition bit flags used by the status or condition commands? Also I just realized I was dumb to talk about reading the external 2k ram on TPDD1 before. On TPDD1 you can't read any ram without rebooting into the special cpu mode anyway, so it's not like you can examine the ram to see where the drive stored bits of info about the disk or a loaded sector or anything like that, so there is no point to a more generic version of the rom dumper. ... and as soon as I said that I thought, well maybe as a drive diagnostic tool, you could read the sensors directly instead of relying on the drive firmware to report error conditions while trying to repair a drive or something. Maybe even operate the gate array? It is a marvel getting that much functionality out of so few bytes. -- bkw On Sun, Jan 28, 2024, 12:19 AM Darren Clark <biggran...@gmail.com<mailto:biggran...@gmail.com>> wrote: Spent some time digging through the source of the TPDD2 firmware, adding comments, labels, and variable names. It's documented (as far as I got so far) here: https://github.com/BiggRanger/Tandy_PDD/blob/master/PDD2.ASM Doesn't look like any hidden commands exist in the firmware. This is the list from the command table at 0xFFB9: code 0xF230 Command_FMT00_CreateDirectory code 0xF4D0 Command_FMT01_FileOpen code 0xF495 Command_FMT02_FileClose code 0xF69D Command_FMT03_FileRead code 0xF63D Command_FMT04_File_Write code 0xF425 Command_FMT05_FileDelete code 0xF212 Command_FMT06_DiskFormat code 0xF6F3 Command_FMT07_DriveStatus code 0xF137 Command_FMT_Invalid code 0xF75F Command_FMT23_DriveVersionInfo code 0xF746 Command_FMT0C_DriveCondition code 0xF365 Command_FMT0D_FileNameChange code 0xF801 Command_FMT30_SectorModeReadWrite code 0xF76B Command_FMT31_DriveMemorySet code 0xF78E Command_FMT32_DriveMemoryGet code 0xF757 Command_FMT33_SystemVersionInfo code 0xF7DC Command_FMT34_ExecuteProgram Some other interesting tables are at 0xFF67 and 0xFF6D [FF67] [80 ] [ ] Table_SysInfo: DB 0x80 ;Hard sector data port address MSB [FF68] [13 ] [ ] DB 0x13 ;Hard sector data port address LSB [FF69] [05 ] [ ] DB 0x05 ;Buffer size MSB [FF6A] [00 ] [ ] DB 0x00 ;Buffer size LSB [FF6B] [10 ] [ ] DB 0x10 ;CPU type. 0x10 = HD6301 [FF6C] [E1 ] [ ] DB 0xE1 ;Model code [FF6D] [41 ] [A ] Table_Version: DB 0x41 ;System Version Number MSB [FF6E] [10 ] [ ] DB 0x10 ;System Version Number LSB [FF6F] [01 ] [ ] DB 0x01 ;Number of sides [FF70] [00 ] [ ] DB 0x00 ;Number of tracks MSB [FF71] [50 ] [P ] DB 0x50 ;Number of tracks LSB [FF72] [05 ] [ ] DB 0x05 ;Sector length MSB [FF73] [00 ] [ ] DB 0x00 ;Sector length LSB [FF74] [02 ] [ ] DB 0x02 ;Sectors per track [FF75] [00 ] [ ] DB 0x00 ;Directory Entries MSB [FF76] [28 ] [( ] DB 0x28 ;Directory Entries LSB [FF77] [00 ] [ ] DB 0x00 ;Max files [FF78] [E1 ] [ ] DB 0xE1 ;Model code There is also a BAUD rate table at 0xFF85, I see logic for reading the dip switch setting from the CPLD at the program initialization. 2 switches for the BAUD rate and the other 2 for some other mode settings. Just a w.a.g. it almost looks like the programming on the CPLD could be the same on the TPPD2 as the TPPD1. It might be possible to set 9600 and 38400 BAUD, just guessing though as I don't have any TPDD2 hardware to play with. Overall an amazing amount of work went into this firmware. From what I can see, it's all hand coded and has a lot of space saving optimizations in it. Out of 4K of available space, there is only 15 bytes of unused space, and the author put his name into it (with one byte filled with a 0xFF): [FFDF] [***********] [ ] DB '(C) M.FUTAMURA',0xFF ;Author Darren Clark