<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://bitchin100.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=208.77.91.41</id>
	<title>Bitchin100 DocGarden - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://bitchin100.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=208.77.91.41"/>
	<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Special:Contributions/208.77.91.41"/>
	<updated>2026-04-14T14:23:12Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_TPDD_Protocol&amp;diff=1411</id>
		<title>M100 TS-DOS ROM TPDD Protocol</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_TPDD_Protocol&amp;diff=1411"/>
		<updated>2009-04-03T17:55:01Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TS-DOS Model 100/102 ROM TPDD Protocol routines ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Flush the RX output buffer to the TPDD file&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
46DDH  LHLD FCCEH           ; Get address of FD control        &lt;br /&gt;
46E0H  LXI B,0007H          ; Load offset of write buffer length         &lt;br /&gt;
46E3H  DAD B                ; Calculate address of write buffer length within FD control   &lt;br /&gt;
46E4H  MOV A,M              ; Load the write buffer length     &lt;br /&gt;
46E5H  PUSH H               ; Save pointer to write buffer length in FD control on stack    &lt;br /&gt;
46E6H  INX H                ; Skip the LSB of the write buffer pointer   &lt;br /&gt;
46E7H  INX H                ; Skip the MSB of the write buffer pointer   &lt;br /&gt;
46E8H  INX H                ; Point to the actual data in the file write buffer   &lt;br /&gt;
46E9H  LXI D,FD04H          ; DE points to the data area in RX buffer         &lt;br /&gt;
46ECH  MOV C,A              ; Load buffer length into BC      &lt;br /&gt;
46EDH  MVI B,00H            ; Make MSB of BC zero       &lt;br /&gt;
46EFH  PUSH PSW             ; Save write buffer length to stack      &lt;br /&gt;
46F0H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment        &lt;br /&gt;
46F3H  POP PSW              ; Retrieve write buffer length from stack     &lt;br /&gt;
46F4H  ANA A                ; Test if write buffer is empty   &lt;br /&gt;
46F5H  CNZ 4095H            ; Send TPDD Write File opcode using RX buffer with length in A if not empty       &lt;br /&gt;
46F8H  POP H                ; Retrieve pointer to write buffer length in FD control from stack   &lt;br /&gt;
46F9H  MVI M,00H            ; Set length of write buffer to zero - it is flushed       &lt;br /&gt;
46FBH  INX H                ; Increment to address in FD control of write buffer    &lt;br /&gt;
46FCH  MOV D,H              ; Save HL to DE for storage of new buffer pointer address     &lt;br /&gt;
46FDH  MOV E,L              ; Save MSB of HL to DE     &lt;br /&gt;
46FEH  INX H                ; Increment to MSB of address in FD conrol of write buffer   &lt;br /&gt;
46FFH  INX H                ; Increment to actual write buffer address   &lt;br /&gt;
4700H  SHLX                 ; Save new write buffer pointer to FD control           &lt;br /&gt;
4701H  RET         &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Appears to be unused code&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4702H  POP PSW&lt;br /&gt;
4703H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Display or print all disk files and free space&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4704H  LXI H,F685H          ; Keyboard buffer  &lt;br /&gt;
4707H  SHLD FCDBH           ; Initialize pointer to File Length table       &lt;br /&gt;
470AH  CALL 4735H           ; Clear #files displayed, init TPDD and send 1st file dir referene opode       &lt;br /&gt;
470DH  JNZ 486AH            ; Communication Error &lt;br /&gt;
4710H  XRA A                ; Prepare to initialize &amp;quot;skip page&amp;quot; count to zero  &lt;br /&gt;
4711H  STA FCDAH            ; Load the &amp;quot;skip page&amp;quot; count      &lt;br /&gt;
4714H  STA FCD4H            ; Current Page of files being displayed      &lt;br /&gt;
4717H  DCR A                ; Set A to 0xFF&lt;br /&gt;
4718H  STA FCD7H            ; Save as Page size to print (print 255 files per page)&lt;br /&gt;
471BH  MVI A,01H            ; &lt;br /&gt;
471DH  STA F63AH            ; ???&lt;br /&gt;
4720H  CALL 4747H           ; Get next page of files from server (NADSBox) with page size = 255&lt;br /&gt;
4723H  JMP 4C23H            ; Send CRLF to screen or printer        &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Display Disk free space on LCD at current position&lt;br /&gt;
;     NOT CALLED!&lt;br /&gt;
;     Old function - reporting of Free space was merged into the printing of the function&lt;br /&gt;
;     key display routine.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4726H  CALL 4A10H           ; Multiply TPDD free sectors len x 128 = free space&lt;br /&gt;
4729H  CALL 4C3EH           ; Print binary number in HL at current position&lt;br /&gt;
472CH  LXI H,4AD1H          ; Point to &amp;quot;0 Bytes free&amp;quot; text&lt;br /&gt;
472FH  CALL 4A2CH           ; Send buffer at M to screen&lt;br /&gt;
4732H  JMP 4C23H            ; Send CRLF to screen or printer&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Clear #files displayed, init TPDD and send 1st file dir referene opode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4735H  XRA A                ; Indicate zero files being displayed &lt;br /&gt;
4736H  STA FCD6H            ; Count of files on screen&lt;br /&gt;
4739H  CALL 4943H           ; Configure baud, test for NADSBox, get NADSBox dir &lt;br /&gt;
473CH  LXI H,0146H          ; Load code for &amp;quot;F&amp;quot; attribute and First File dir reference&lt;br /&gt;
473FH  JMP 476FH            ; Send Directory Reference opcode with HL=access mode&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Get next page of files from server (NADSBox / TPDD)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4742H  MVI A,14H            ; Maximum files that will fit on the display      &lt;br /&gt;
4744H  STA FCD7H            ; Save for comparison of file count      &lt;br /&gt;
4747H  LDA FCCBH            ; NADSBox / Desklink / TPDD2 flag      &lt;br /&gt;
474AH  ANA A                ; Test if TPDD  &lt;br /&gt;
474BH  JNZ 4757H            ; Skip 1st invocation of &amp;quot;Next file&amp;quot; if NADSBox or TPDD2??      &lt;br /&gt;
474EH  LXI H,02F6H          ; Load access mode code for &amp;quot;Next entry&amp;quot; dir reference        &lt;br /&gt;
4751H  CALL 476FH           ; Send Directory Reference opcode with HL=access mode       &lt;br /&gt;
4754H  JNZ 47F8H            ; Check RX packet for Noraml Response &amp;amp; report errors      &lt;br /&gt;
4757H  LDA FD04H            ; 1st filename byte      &lt;br /&gt;
475AH  ANA A                ; Test if 1st filename byte is zero  &lt;br /&gt;
475BH  RZ                   ; Return if last file retrieved&lt;br /&gt;
475CH  LDA FCDAH            ; Load the &amp;quot;skip page&amp;quot; count      &lt;br /&gt;
475FH  ANA A                ; Test if this is a &amp;quot;skip page&amp;quot;  &lt;br /&gt;
4760H  CZ 4781H             ; Call routine to display file if not a skip page     &lt;br /&gt;
4763H  LXI H,FCD6H          ; Count of files on screen        &lt;br /&gt;
4766H  INR M                ; Increment #files displayed on LCD  &lt;br /&gt;
4767H  LDA FCD7H            ; Load count of max files that will fit on LCD      &lt;br /&gt;
476AH  CMP M                ; Compare with current file count          &lt;br /&gt;
476BH  JNZ 474EH            ; Jump back to get next file from TPDD if not full      &lt;br /&gt;
476EH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send Directory Reference opcode with HL=access mode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
476FH  SHLD FD00H           ; Save file attrib and reference mode to TX buffer     &lt;br /&gt;
4772H  LXI H,1A00H          ; Load code and length for Directory Reference opcode      &lt;br /&gt;
4775H  CALL 4822H           ; Send TPDD Command/Len in HL     &lt;br /&gt;
4778H  CALL 47CCH           ; Receive a packet     &lt;br /&gt;
477BH  LDA FD02H            ; Storage for RX packet - response byte    &lt;br /&gt;
477EH  CPI 11H              ; Test if response was 0x11  (valid Dir Ref response)&lt;br /&gt;
4780H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Print filename in RX buffer to LCD and save length info&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4781H  MVI C,09H            ; Prepare to draw 9 bytes of filename to LCD     &lt;br /&gt;
4783H  LXI H,FD04H          ; Location of filename in RX packet       &lt;br /&gt;
4786H  CALL 48E5H           ; Redraw C characters from buffer at HL using current video mode      &lt;br /&gt;
4789H  MVI A,20H            ; Prepare to draw a trailing space            &lt;br /&gt;
478BH  RST 4                ; Send char in A to LCD    &lt;br /&gt;
478CH  LHLD FD1DH           ; Get file size parameter from RX buffer      &lt;br /&gt;
478FH  MOV E,H              ; Save file size LSB in E   &lt;br /&gt;
4790H  MOV D,L              ; Save file size MSB in D          &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Store next file length to keyboard buffer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4791H  LHLD FCDBH           ; Next storage location for file size info       &lt;br /&gt;
4794H  XCHG                 ; HL &amp;lt;--&amp;gt; DE &lt;br /&gt;
4795H  SHLX                 ; Store file length at address of next file save &lt;br /&gt;
4796H  XCHG                 ; HL &amp;lt;--&amp;gt; DE &lt;br /&gt;
4797H  INX H                ; Increment storage address of next file length  &lt;br /&gt;
4798H  INX H                ; Increment again (2 byte length)  &lt;br /&gt;
4799H  SHLD FCDBH           ; Save new address for lenght storage for next file&lt;br /&gt;
479CH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Receive an RX packet.  This routine gets copied into RAM and executed from there while&lt;br /&gt;
;       the Main ROM is selected.  This allows the RX packet to be recieved without&lt;br /&gt;
;       switching to and from the Main ROM to receive each individual byte.  The jump&lt;br /&gt;
;       addresses represent the RAM execution locations.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
479DH  LXI H,FD02H          ; Storage for RX packet         &lt;br /&gt;
47A0H  PUSH H               ; Save start of packet address on stack    &lt;br /&gt;
47A1H  CALL FDB2H           ; Get next byte from RX into HL        &lt;br /&gt;
47A4H  CALL FDB2H           ; Get next byte from RX into HL        &lt;br /&gt;
47A7H  MOV C,A              ; Move length byte into C     &lt;br /&gt;
47A8H  CALL FDB2H           ; Get next byte from RX into HL        &lt;br /&gt;
47ABH  MOV B,C              ; Move length byte to B     &lt;br /&gt;
47ACH  MOV A,C              ; Move length byte to A for zero test     &lt;br /&gt;
47ADH  ANA A                ; Test if length is zero   &lt;br /&gt;
47AEH  JZ FDA4H             ; Skip reading payload if zero length      &lt;br /&gt;
47B1H  CALL FDB2H           ; Get next byte from RX into HL        &lt;br /&gt;
47B4H  DCR C                ; Decrement length byte   &lt;br /&gt;
47B5H  JNZ FD9DH            ; Keep looping until all data received       &lt;br /&gt;
47B8H  POP H                ; Restore start of RX packet address   &lt;br /&gt;
47B9H  INR B                ; Add opcode byte to length for checksum   &lt;br /&gt;
47BAH  INR B                ; Add length byte to length for checksum   &lt;br /&gt;
47BBH  XRA A                ; Clear A for checksum calculation   &lt;br /&gt;
47BCH  SIM                  ; ?Clear Interrupts &lt;br /&gt;
47BDH  ADD M                ; Add next byte to checksum   &lt;br /&gt;
47BEH  INX H                ; Increment RX data pointer   &lt;br /&gt;
47BFH  DCR B                ; Decrement length counter   &lt;br /&gt;
47C0H  JNZ FDA9H            ; Keep looping until all bytes added       &lt;br /&gt;
47C3H  CMA                  ; Compliment the checksum          &lt;br /&gt;
47C4H  CMP M                ; Compare with received checksum   &lt;br /&gt;
47C5H  RET                  ; Branch if no match - Communication Error&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Get next RX byte and store at HL, test for drive ready &amp;amp; print errors&lt;br /&gt;
;    This routine (and the one above) get copied into RAM and then executed&lt;br /&gt;
;    when the Main ROM is selected, so a direct call to the Main ROM address&lt;br /&gt;
;    is allowed.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
47C6H  CALL 6D7EH           ; Get a character from RS232 receive queue&lt;br /&gt;
47C9H  MOV M,A              ; Save byte at HL&lt;br /&gt;
47CAH  INX H                ; Increment HL&lt;br /&gt;
47CBH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy the 2 Receive RX Packet routines above to RAM and execute&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
47CCH  LXI H,479DH          ; Point to Receive RX Packet routine&lt;br /&gt;
47CFH  LXI D,FD89H          ; Point to target destination in RAM&lt;br /&gt;
47D2H  LXI B,002FH          ; Length of the routine&lt;br /&gt;
47D5H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment      &lt;br /&gt;
47D8H  CALL 4862H           ; Test if DSR is set - drive ready, error otherwise&lt;br /&gt;
47DBH  CALL 4BDBH           ; Call Main ROM&#039;s Set interrupt to 1DH routine.&lt;br /&gt;
47DEH  RST 1                ; Switch to Main ROM and execute &amp;quot;Receive RX Pakcet&amp;quot; routine&lt;br /&gt;
47DFH  DW   FD89H           ; Address of our RX routine we just copied to RAM&lt;br /&gt;
47E1H  JNZ 486AH            ; Communication Error if no /DSR&lt;br /&gt;
47E4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Get next RX byte and store at HL, test for drive ready &amp;amp; print errors&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
47E5H  CALL 47EBH           ; Test drive and get byte from RX&lt;br /&gt;
47E8H  MOV M,A              ; Save byte at HL&lt;br /&gt;
47E9H  INX H                ; Increment HL &lt;br /&gt;
47EAH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Test drive ready and get byte from RX,  Report error if not ready&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
47EBH  CALL 4862H           ; Test if DSR is set - Drive Ready&lt;br /&gt;
47EEH  CALL 4BE7H           ; Get a character from RS232 receive queue&lt;br /&gt;
47F1H  JC 488DH             ; Empty Error Text&lt;br /&gt;
47F4H  JNZ 486AH            ; Communication Error&lt;br /&gt;
47F7H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Check RX packet for Normal Response &amp;amp; report errors&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
47F8H  LDA FD02H            ; Storage for RX packet        &lt;br /&gt;
47FBH  CPI 12H              ; Test for normal return code      &lt;br /&gt;
47FDH  JNZ 486AH            ; Communication Error        &lt;br /&gt;
4800H  LDA FD04H            ; Location of error code in RX packet        &lt;br /&gt;
4803H  ANA A                ; Test if error code is zero    &lt;br /&gt;
4804H  RZ                   ; Return if no error &lt;br /&gt;
4805H  CPI 10H        &lt;br /&gt;
4807H  JZ 487EH             ; File Exists Error       &lt;br /&gt;
480AH  CPI 50H        &lt;br /&gt;
480CH  JZ 486DH             ; Write Protect Error       &lt;br /&gt;
480FH  CPI 60H        &lt;br /&gt;
4811H  JZ 4881H             ; Disk Full Error       &lt;br /&gt;
4814H  JC 486AH             ; Communication Error       &lt;br /&gt;
4817H  JZ 4873H             ; Disk not in drive error       &lt;br /&gt;
481AH  CPI 80H        &lt;br /&gt;
481CH  JC 4873H             ; Disk not in drive error       &lt;br /&gt;
481FH  JMP 4870H            ; Drive Trouble Error        &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send TPDD Command/Len in HL,  H=len, L=Cmd. 0XED8A already has data&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4822H  SHLD FCE6H           ; Store TDD CMD/Len passed in HL        &lt;br /&gt;
4825H  LXI H,FCE6H          ; Point to Command/Len storage location         &lt;br /&gt;
&lt;br /&gt;
4828H  PUSH H               ; Save Cmd/Len storage address to stack    &lt;br /&gt;
4829H  LDA FCCAH            ; TPDD Bank Numbere       &lt;br /&gt;
482CH  ANA A                ; Test if reading from side zero   &lt;br /&gt;
482DH  JZ 4837H             ; Skip ahead if reading from side zero      &lt;br /&gt;
4830H  ANI 01H              ; Mask off all but LSB (only side 1 allowed)     &lt;br /&gt;
4832H  RAR                  ; Move the &amp;quot;1&amp;quot; to C          &lt;br /&gt;
4833H  RAR                  ; Move the &amp;quot;1&amp;quot; to bit 7 &lt;br /&gt;
4834H  RAR                  ; Move the &amp;quot;1&amp;quot; to bit 6 (could just do MVI 0x40 !!) &lt;br /&gt;
4835H  ORA M                ; OR the 0x40 with Cmd to access Disk Bank 1   &lt;br /&gt;
4836H  MOV M,A              ; Save the updated cmd value back at (HL)     &lt;br /&gt;
4837H  MOV A,M              ; Get the command value / modified value     &lt;br /&gt;
4838H  INX H                ; Point to length parameter passed in   &lt;br /&gt;
4839H  ADD M                ; Add the length parameter (checksum)   &lt;br /&gt;
483AH  MOV B,A              ; Store checksum in B                                &lt;br /&gt;
483BH  MOV A,M              ; Get the Length parameter     &lt;br /&gt;
483CH  PUSH PSW             ; Save length on stack      &lt;br /&gt;
483DH  INX H                ; Point to data (already loaded before invocation)   &lt;br /&gt;
483EH  ANA A                ; Test if length is zero   &lt;br /&gt;
483FH  JZ 484BH             ; Skip data checksum if length zero        &lt;br /&gt;
4842H  MOV C,A              ; Save current count     &lt;br /&gt;
4843H  MOV A,B              ; Get running checksum value     &lt;br /&gt;
4844H  ADD M                ; Add this byte to checksum   &lt;br /&gt;
4845H  INX H                ; Point to next data byte   &lt;br /&gt;
4846H  DCR C                ; Decrement count   &lt;br /&gt;
4847H  JNZ 4844H            ; Keep looping until count is zero       &lt;br /&gt;
484AH  MOV B,A              ; Save updated checksum in B     &lt;br /&gt;
484BH  MOV A,B              ; Get Checksum from B    &lt;br /&gt;
484CH  CMA                  ; Compliment the checksum (protocol thing) &lt;br /&gt;
484DH  MOV D,A              ; Save complimented checksum in D     &lt;br /&gt;
484EH  LXI B,5A5AH          ; Load &amp;quot;ZZ&amp;quot; header signature into BC         &lt;br /&gt;
4851H  CALL 49DBH           ; Send BC to the serial port using XON/XOFF        &lt;br /&gt;
4854H  POP B                ; Get the length from stack into BC                     &lt;br /&gt;
4855H  MOV C,B              ; Move the length into C     &lt;br /&gt;
4856H  MVI B,00H            ; Clear upper MSB of count       &lt;br /&gt;
4858H  INX B                ; Add Opcode byte to the TX length    &lt;br /&gt;
4859H  INX B                ; Add length byte to the TX length    &lt;br /&gt;
485AH  POP H                ; Get address of TX packet from stack    &lt;br /&gt;
485BH  CALL 48D9H           ; Send BC bytes to RS-232 from (HL) using XON/XOFF                  &lt;br /&gt;
485EH  MOV A,D              ; Get checksum byte for TX       &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send A to RS-232 using XON/XOFF and check DSR when done&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
485FH  CALL 4BE3H           ; Call Main ROM&#039;s Send A to RS-232 using XON/XOFF routine         &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Test if DSR is set - drive ready, error otherwise&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4862H  IN BBH               ; Get I/O port with /DSR bit&lt;br /&gt;
4864H  ANI 20H              ; Mask all but the /DSR bit&lt;br /&gt;
4866H  RZ                   ; Return if /DSR is asserted (low = asserted)&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Error jump table.  Loads A with error number and prints&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4867H  (3EH) MVI A,01H&lt;br /&gt;
       DB	0x21            ; Filler - looks like &amp;quot;LXI H,XXXX&amp;quot;&lt;br /&gt;
486AH  MVI A,02H            ; Communication Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
486DH  MVI A,03H            ; Write Protect Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4870H  MVI A,04H            ; Drive Trouble Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4873H  MVI A,05H            ; Disk not in drive Error&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; For any of the errors above, change the RAM/Disk mode back to RAM&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4875H  LXI H,FCD9H          ; RAM / Disk mode (0=RAM,  1=DISK)&lt;br /&gt;
4878H  MVI M,00H            ; Go back to RAM mode&lt;br /&gt;
       DB   0x21            ; Filler - looks like &amp;quot;LXI H,XXXX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
487BH  MVI A,06H            ; Printer Not Ready Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
487EH  MVI A,07H            ; File Exists Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4881H  MVI A,08H            ; Disk Full Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4884H  MVI A,09H            ; File Empty Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4887H  MVI A,0AH            ; Directory Full Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
488AH  MVI A,0BH            ; Ram Full Error&lt;br /&gt;
       DB	0x21&lt;br /&gt;
488DH  MVI A,0CH            ; ID Error (No text...runtime error only)&lt;br /&gt;
       DB	0x21&lt;br /&gt;
4890H  MVI A,0DH            ; Bad File Name Error&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Generate the error loaded in A above&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4892H  LXI H,4B02H          ; Pointer to error string table&lt;br /&gt;
4895H  MOV C,A              ; Save error number for loop counting   &lt;br /&gt;
4896H  DCR C                ; Decrement error counter to test if string found &lt;br /&gt;
4897H  JZ 48A4H             ; String found in table    &lt;br /&gt;
489AH  MOV A,M              ; Get next byte of error string   &lt;br /&gt;
489BH  INX H                ; Inrcrement pointer &lt;br /&gt;
489CH  CPI 00H              ; Test if end of string   &lt;br /&gt;
489EH  JNZ 489AH            ; Loop until end of string found     &lt;br /&gt;
48A1H  JMP 4896H            ; Branch back to decrement string counter     &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Print error string at HL from error table&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48A4H  LDA FCD2H            ; Get the &amp;quot;Print error messages&amp;quot; flag       &lt;br /&gt;
48A7H  ANA A                ; Test if printing allowed   &lt;br /&gt;
48A8H  JZ 48D0H             ; Jump to generate system error if not allowed to print      &lt;br /&gt;
48ABH  MVI A,07H            ; Print BELL to cause a beep       &lt;br /&gt;
48ADH  RST 4                ; Send A to the LCD     &lt;br /&gt;
48AEH  INX H                ; Skip the error code   &lt;br /&gt;
48AFH  CALL 48F4H           ; Print string at HL to col 1 on the bottom line        &lt;br /&gt;
48B2H  CALL 48C7H           ; Display &amp;quot;Press any key&amp;quot; and wait for key     &lt;br /&gt;
   &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Perform Long jump&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48B5H  LHLD FCCEH           ; Stack pointer upon entry        &lt;br /&gt;
48B8H  SPHL                 ; Restore stack frame  &lt;br /&gt;
48B9H  LHLD FCD0H           ; Get return vector after error        &lt;br /&gt;
48BCH  PUSH H               ; Prepare to return to return vector    &lt;br /&gt;
48BDH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Draw &amp;quot;Press any key&amp;quot; text with pre&amp;amp;post CR and wait for key press&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48BEH  CALL 4C23H           ; Send CRLF to screen or printer&lt;br /&gt;
48C1H  CALL 48C7H           ; Display &amp;quot;Press any key&amp;quot; and wait for key&lt;br /&gt;
48C4H  JMP 4C23H            ; Send CRLF to screen or printer&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Draw &amp;quot;Press any key&amp;quot; text and wait for key press&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48C7H  LXI H,4BBBH          ; Point to &amp;quot;Press any key&amp;quot; text&lt;br /&gt;
48CAH  CALL 4A2CH           ; Send buffer at M to screen&lt;br /&gt;
48CDH  JMP 4BEBH            ; Wait for key from keyboard&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Generate system error from code saved at (HL).  This is called in liu of printing when&lt;br /&gt;
;      the print/generate system error flag is set.  The 1st byte of each error entry&lt;br /&gt;
;      contains the system error number to generate.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48D0H  MOV E,M              ; Get the error code&lt;br /&gt;
48D1H  LHLD FCCEH           ; Stack pointer upon entry&lt;br /&gt;
48D4H  MVI M,00H            ; Indicate all arguments (none) processed&lt;br /&gt;
48D6H  JMP 4C37H            ; Generate error in E&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send BC bytes to RS-232 from (HL) using XON/XOFF&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48D9H  MOV A,M              ; Get next byte from (HL)&lt;br /&gt;
48DAH  CALL 485FH           ; Send A to RS-232 using XON/XOFF&lt;br /&gt;
48DDH  INX H                ; Increment poiner &lt;br /&gt;
48DEH  DCX B                ; Decrement byte count &lt;br /&gt;
48DFH  MOV A,C              ; Get C for zero comparison&lt;br /&gt;
48E0H  ORA B                ; Or in MSB of count&lt;br /&gt;
48E1H  JNZ 48D9H            ; Jump to send next byte if not zero&lt;br /&gt;
48E4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Draw C characters to LCD from buffer at HL using current video mode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48E5H  MOV A,M              ; Get next byte from LCD buffer &lt;br /&gt;
48E6H  CPI 20H              ; Test if it is a space &lt;br /&gt;
48E8H  JNC 48EDH            ; Test if it&#039;s less than space, jump if not to redraw &lt;br /&gt;
48EBH  MVI A,20H            ; Draw a space for &amp;quot;illegal&amp;quot; values &lt;br /&gt;
48EDH  RST 4                ; Draw byte with current regular/inverse video mode &lt;br /&gt;
48EEH  INX H                ; Increment to next byte in LCD buffer &lt;br /&gt;
48EFH  DCR C                ; Decrement the loop counter &lt;br /&gt;
48F0H  JNZ 48E5H            ; Branch if not done to process next character &lt;br /&gt;
48F3H  RET                  ; Done&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Print string at HL to col 1 on the bottom line&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
48F4H  PUSH H               ; Save pointer to error text on stack  &lt;br /&gt;
48F5H  LXI H,0108H          ; Position cursor on col 1 of row 16&lt;br /&gt;
48F8H  SHLD F639H           ; Cursor row (1-8)  &lt;br /&gt;
48FBH  CALL 4C2BH           ; Erase from cursor to end of line      &lt;br /&gt;
48FEH  POP H                ; Restore pointer to error text from stack &lt;br /&gt;
48FFH  JMP 4A2CH            ; Send buffer at M to screen&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy filename at (HL) to current BASIC program&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4902H  PUSH H               ; Save pointer to filename on stack    &lt;br /&gt;
4903H  MVI A,20H            ; Load A with code for SPACE       &lt;br /&gt;
4905H  LXI H,FC93H          ; Filename of current BASIC program            &lt;br /&gt;
4908H  MVI B,08H            ; Prepare to fill current BASIC program with 8 spaces       &lt;br /&gt;
490AH  CALL 4A34H           ; Fill (HL) with B bytes of A        &lt;br /&gt;
490DH  POP H                ; Retrieve filename pointer from stack   &lt;br /&gt;
490EH  LXI D,FC93H          ; Filename of current BASIC program             &lt;br /&gt;
4911H  MVI B,06H            ; Prepare to copy 6 bytes of filename before ext       &lt;br /&gt;
4913H  MOV A,M              ; Get next byte of filename from source     &lt;br /&gt;
4914H  CPI 41H              ; Compare byte with &#039;A&#039; to test validity     &lt;br /&gt;
4916H  JC 4890H             ; Bad Filename Error if invalid char      &lt;br /&gt;
4919H  MOV A,M              ; Get next byte again     &lt;br /&gt;
491AH  CPI 2EH              ; Compare with &#039;.&#039;     &lt;br /&gt;
491CH  JZ 492BH             ; Branch if &#039;.&#039; to fill remaining with &#039; &#039;      &lt;br /&gt;
491FH  ORA A                ; Test for zero (NULL term)   &lt;br /&gt;
4920H  RZ                   ; Return if done copying filename (NULL term)&lt;br /&gt;
4921H  STAX D               ; Store next filename byte at (DE)    &lt;br /&gt;
4922H  INX H                ; Increment source pointer   &lt;br /&gt;
4923H  INX D                ; Increment dest pointer   &lt;br /&gt;
4924H  DCR B                ; Decrement counter   &lt;br /&gt;
4925H  JNZ 4919H            ; Keep looping until all bytes copied       &lt;br /&gt;
4928H  JMP 4933H            ; Jump to copy 2 extension bytes       &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Fill remainder of filename at (DE) with spaces,  B has count&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
492BH  MVI A,20H            ; Load code for &#039; &#039;        &lt;br /&gt;
492DH  STAX D               ; Save next byte as &#039; &#039;     &lt;br /&gt;
492EH  INX D                ; Increment pointer    &lt;br /&gt;
492FH  DCR B                ; Decrement count    &lt;br /&gt;
4930H  JNZ 492DH            ; Keep looping until full &lt;br /&gt;
       &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy 2 extention bytes from (HL) to (DE)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4933H  MVI B,02H            ; Setup count = 2        &lt;br /&gt;
4935H  INX H                ; Skip the &#039;.&#039; in the source name    &lt;br /&gt;
4936H  MOV A,M              ; Load next extension byte from source      &lt;br /&gt;
4937H  ORA A                ; Test for NULL termination    &lt;br /&gt;
4938H  RZ                   ; Return if NULL terminated &lt;br /&gt;
4939H  STAX D               ; Store in destination     &lt;br /&gt;
493AH  INX D                ; Increment destination    &lt;br /&gt;
493BH  DCR B                ; Decrement the counter    &lt;br /&gt;
493CH  JNZ 4935H            ; Keep looping until done        &lt;br /&gt;
493FH  MVI A,00H            ; Load NULL termination byte        &lt;br /&gt;
4941H  STAX D               ; Add NULL termination to filename     &lt;br /&gt;
4942H  RET        &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Configure baud, test for NADSBox, get NADSBox dir&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4943H  CALL 4A94H           ; Configure baud (19200 for NADSBox/Desklink, 9600 otherwise)        &lt;br /&gt;
4946H  CALL 49A2H           ; Send M1 and test for NADSBox/Desklink response        &lt;br /&gt;
4949H  CALL 47CCH           ; Receive a packet        &lt;br /&gt;
494CH  CALL 47F8H           ; Check RX packet for Normal Response &amp;amp; report errors        &lt;br /&gt;
494FH  LDA FCCBH            ; NADSBo / Desklink / TPDD2 flag       &lt;br /&gt;
4952H  ANA A                ; Test if server is NADSBox / Desklink   &lt;br /&gt;
4953H  RZ                   ; Return if not NADSBox / Desklink&lt;br /&gt;
4954H  LXI H,0008H          ; Load opcode 0x08 - FDC Emulation mode         &lt;br /&gt;
4957H  CALL 4822H           ; Send TPDD Command/Len in HL        &lt;br /&gt;
495AH  CALL 47CCH           ; Receive a packet - should be the current directory name        &lt;br /&gt;
495DH  LDA FD03H            ; Load length byte from the RX payload area       &lt;br /&gt;
4960H  CPI 01H              ; Test if length 1     &lt;br /&gt;
4962H  JZ 4977H             ; Jump to send mystery opcodes if length = 1      &lt;br /&gt;
4965H  DCR A                ; Subtract 1 from length (skip reserved 0x00 in filename)   &lt;br /&gt;
4966H  MOV C,A              ; Save count in C     &lt;br /&gt;
4967H  MVI A,02H            ; Prepare to indicate we have a NADSBox / Desklink directory name       &lt;br /&gt;
4969H  STA FCCBH            ; NADSBox / Desklink flag = HAVE_NADS_DIR       &lt;br /&gt;
496CH  MVI B,00H            ; Clear MSB of count       &lt;br /&gt;
496EH  LXI H,FD05H          ; Point to filename in RX payload (skip 1st byte)         &lt;br /&gt;
4971H  LXI D,FCC0H          ; Storage area for NADSBox directory           &lt;br /&gt;
4974H  JMP 4A05H            ; Move BC bytes from M to (DE) with increment       &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send mystery opcodes&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4977H  LXI H,0023H          ; Load mystery opcode 23    &lt;br /&gt;
497AH  CALL 4822H           ; Send TPDD Command/Len in HL   &lt;br /&gt;
497DH  CALL 47CCH           ; Receive a packet   &lt;br /&gt;
4980H  LXI H,4AE7H          ; Point to mystery opcode 0x31    &lt;br /&gt;
4983H  CALL 498FH           ; Send 9-byte protocol packet at HL   &lt;br /&gt;
4986H  LXI H,4AF0H          ; Point to 2nd mystery opcode 0x31    &lt;br /&gt;
4989H  CALL 498FH           ; Send 9-byte protocol packet at HL   &lt;br /&gt;
498CH  LXI H,4AF9H          ; Point to 3rd mystery opcode 0x31    &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send 9-byte protocol packet at HL&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
498FH  LXI B,0009H          ; Load byte counter to send 9 bytes    &lt;br /&gt;
4992H  CALL 48D9H           ; Send BC bytes at (HL) to RS-232 using XON/XOFF   &lt;br /&gt;
4995H  JMP 47CCH            ; Receive a packet  &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Flush the RX queue &amp;amp; discard&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4998H  CALL 4BDFH           ; Check RS232 queue for pending characters&lt;br /&gt;
499BH  RZ                   ; Return if RS232 queue is empty&lt;br /&gt;
499CH  CALL 47EBH           ; Test drive ready and get byte from RX.&lt;br /&gt;
499FH  JMP 4998H            ; Branch to get next byte from RX&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send M1 and test for NADSBox / Desklink response&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
49A2H  CALL 4862H           ; Test if DSR set - drive ready      &lt;br /&gt;
49A5H  CALL 49CDH           ; Send &amp;quot;M1&amp;quot;,0x0D to TX and delay about 3ms      &lt;br /&gt;
49A8H  CALL 4998H           ; Flush the RX queue &amp;amp; discard      &lt;br /&gt;
49ABH  CALL 419BH           ; Send Opcode 0x08 - FDC emulation mode      &lt;br /&gt;
49AEH  CALL 49D3H           ; Send 0x0D to RS-232 and Delay 3ms      &lt;br /&gt;
49B1H  CALL 4BDFH           ; Check RS232 queue for pending characters      &lt;br /&gt;
49B4H  MVI A,00H            ; NADSBox / Desklink / TPDD2 flag     &lt;br /&gt;
49B6H  JNZ 49BAH            ; Skip setting NADSBox / Desklink flag if no response     &lt;br /&gt;
49B9H  INR A                ; Indicate response from &amp;quot;M1&amp;quot; command = NADSBox / Desklink &lt;br /&gt;
49BAH  STA FCCBH            ; Store NADSBox / Desklink / TPDD2 flag     &lt;br /&gt;
49BDH  CALL 4998H           ; Flush the RX queue &amp;amp; discard      &lt;br /&gt;
49C0H  CALL 49CDH           ; Send &amp;quot;M1&amp;quot; to TX and delay about 3ms      &lt;br /&gt;
49C3H  CALL 4998H           ; Flush the RX queue &amp;amp; discard      &lt;br /&gt;
49C6H  LXI H,0007H          ; Load opcode for Drive Status       &lt;br /&gt;
49C9H  CALL 4822H           ; Send TPDD Command/Len in HL      &lt;br /&gt;
49CCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send &amp;quot;M1&amp;quot;,0x0D to RS-232 and delay about 3ms&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
49CDH  LXI B,4D31H          ; Load code for &amp;quot;M1&amp;quot;&lt;br /&gt;
49D0H  CALL 49DBH           ; Send BC to RS-232 using XON/XOFF&lt;br /&gt;
49D3H  MVI A,0DH            ; Load code for CR (0x0D)&lt;br /&gt;
49D5H  CALL 485FH           ; Send A to RS-232 using XON/XOFF&lt;br /&gt;
49D8H  JMP 49E3H            ; Delay routine - about 3ms&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send BC to RS-232 using XON/XOFF&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
49DBH  MOV A,B              ; Get first byte to send&lt;br /&gt;
49DCH  CALL 485FH           ; Send A to RS-232 using XON/XOFF&lt;br /&gt;
49DFH  MOV A,C              ; Get 2nd byte to send&lt;br /&gt;
49E0H  JMP 485FH            ; Send A to RS-232 using XON/XOFF&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Delay routine - about 72000 cycles = 28.9ms&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
49E3H  MVI H,14H            ; 7 Cycles&lt;br /&gt;
49E5H  MVI L,FFH            ; 7 Cycles&lt;br /&gt;
49E7H  DCR L                ; 4 Cycles  &lt;br /&gt;
49E8H  JNZ 49E7H            ; 10 Cycles to Jump back. 14 * 255 = 3570 cycles inner loop&lt;br /&gt;
49EBH  DCR H                ; 4 Cycles.  But we save 3 cycles from the final JNZ, so 1 cycle  &lt;br /&gt;
49ECH  JNZ 49E5H            ; 10 Cycles to jump back. (3570+1+7)*20+7 = 71567 cycles&lt;br /&gt;
49EFH  RET                  ; 71567 * 403.877ns = 28.904ms&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Wait for drive to be ready for 20480 counts of 28.9ms = 9.8 minutes???.&lt;br /&gt;
; Report error if no data received.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
49F0H  LXI B,FF50H          ; Get count of delay times to wait&lt;br /&gt;
49F3H  CALL 49E3H           ; Delay 28.9ms      &lt;br /&gt;
49F6H  CALL 4BDFH           ; Check RS232 queue for pending characters             &lt;br /&gt;
49F9H  RNZ                  ; Return if data available&lt;br /&gt;
49FAH  DCR B                ; Decrement inner loop count &lt;br /&gt;
49FBH  JNZ 49F3H            ; Branch to delay and test again     &lt;br /&gt;
49FEH  DCR C                ; Decrement outer loop count &lt;br /&gt;
49FFH  JNZ 49F3H            ; Branch to delay and test again     &lt;br /&gt;
4A02H  JMP 4867H            ; No data received - Drive Not Ready error     &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Move BC bytes from M to (DE) with increment&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A05H  MOV A,M              ; Get next byte from (HL)&lt;br /&gt;
4A06H  STAX D               ; Store next byte at (DE)&lt;br /&gt;
4A07H  INX H                ; Increment source pointer&lt;br /&gt;
4A08H  INX D                ; Increment destination poiner&lt;br /&gt;
4A09H  DCX B                ; Decrement loop control&lt;br /&gt;
4A0AH  MOV A,B              ; Prepare to test for zero&lt;br /&gt;
4A0BH  ORA C                ; OR in LSB to test for zero&lt;br /&gt;
4A0CH  JNZ 4A05H            ; Keep looping until done&lt;br /&gt;
4A0FH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Multiply TPDD free sectors len x 128 = free space.  A &#039;0&#039; is added to LCD to convert this&lt;br /&gt;
;      multiplication to x1280 (the TPDD sector size).&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A10H  LDA FD1FH            ; Get number of free sectors reported from server (TPDD)&lt;br /&gt;
4A13H  MOV L,A              ; Move #free sectors into HL for multiply&lt;br /&gt;
4A14H  MVI H,00H            ; Clear MSB of HL&lt;br /&gt;
4A16H  LXI D,0080H          ; Prepare to multiply #sectors x 128 &lt;br /&gt;
4A19H  JMP 4C1FH            ; Signed integer muliply (FAC1=HL*DE)&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Compare (HL) with (DE), C bytes long&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A1CH  PUSH D               ; Save pointer to 1st buffer   &lt;br /&gt;
4A1DH  PUSH H               ; Save pointer to 2nd buffer  &lt;br /&gt;
4A1EH  LDAX D               ; Load next byte from 1st buffer  &lt;br /&gt;
4A1FH  SUB M                ; Compare with nex byte from 2nd buffer &lt;br /&gt;
4A20H  JNZ 4A29H            ; Jump to exit if no match     &lt;br /&gt;
4A23H  INX H                ; Increment 2nd buffer pointer &lt;br /&gt;
4A24H  INX D                ; Increment 1st buffer pointer &lt;br /&gt;
4A25H  DCR C                ; Decrement length &lt;br /&gt;
4A26H  JNZ 4A1EH            ; Jump to compare next byte if not at end     &lt;br /&gt;
4A29H  POP H                ; Restore pointer to 2nd buffer &lt;br /&gt;
4A2AH  POP D                ; Restore pointer to 1st buffer &lt;br /&gt;
4A2BH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send buffer at M to screen&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A2CH  (7EH) MOV A,M        ; Get next byte to send to LCD&lt;br /&gt;
4A2DH  (A7H) ANA A          ; Test for end of string&lt;br /&gt;
4A2EH  (C8H) RZ             ; Return if end of string (NULL terminated)&lt;br /&gt;
4A2FH  (E7H) RST 4          ; Send character in A to screen/printer&lt;br /&gt;
4A30H  (23H) INX H          ; Increment to next byte&lt;br /&gt;
4A31H  (C3H) JMP 4A2CH      ; Branch to test next byte for zero and print&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Fill (HL) with B bytes of A&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A34H  MOV M,A              ; Load next byte at (HL) with A&lt;br /&gt;
4A35H  INX H                ; Increment pointer&lt;br /&gt;
4A36H  DCR B                ; Decrement counter&lt;br /&gt;
4A37H  JNZ 4A34H            ; Keep looping until B bytes copied&lt;br /&gt;
4A3AH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Initialize blank filename and attribute byte&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A3BH  MVI A,20H            ; Prepare to fill TX packet with spaces&lt;br /&gt;
4A3DH  MVI B,18H            ; Fill TX buffer with 24 spaces&lt;br /&gt;
4A3FH  LXI H,FCE8H          ; Address of TX packet data&lt;br /&gt;
4A42H  CALL 4A34H           ; Fill (HL) with B bytes of A&lt;br /&gt;
4A45H  MVI A,46H            ; Load &amp;quot;F&amp;quot; TPDD file attribute flag&lt;br /&gt;
4A47H  STA FD00H            ; Store in TX packet data location&lt;br /&gt;
4A4AH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Get RAM directory address of selected file into HL&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A4BH  LHLD FCE4H           ; LCD Buffer address of current file selection&lt;br /&gt;
4A4EH  CALL 4902H           ; Copy filename at (HL) to current BASIC program&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Get RAM directory address of current BASIC program&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A51H  CALL 4C0FH           ; Update system pointers&lt;br /&gt;
4A54H  JMP 4BFBH            ; Find catalog entry address of current BASIC program&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send Dir Reference for filename at (HL)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A57H  PUSH H               ; Save filename address on stack  &lt;br /&gt;
4A58H  CALL 4A3BH           ; Initialize blank filename and attribute byte      &lt;br /&gt;
4A5BH  POP H                ; Restore filename address &lt;br /&gt;
4A5CH  LXI D,FCE8H          ; Address of TX packet data       &lt;br /&gt;
4A5FH  LXI B,0006H          ; Prepare to copy 6 bytes of TX data       &lt;br /&gt;
4A62H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment      &lt;br /&gt;
4A65H  MVI A,2EH            ; Load code for &#039;.&#039;     &lt;br /&gt;
4A67H  STAX D               ; Add &#039;.&#039; between name and extension  &lt;br /&gt;
4A68H  INX D                ; Increment TX pkt address pointer &lt;br /&gt;
4A69H  LXI B,0002H          ; Prepare to copy extension from filename&lt;br /&gt;
4A6CH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment      &lt;br /&gt;
4A6FH  CALL 4943H           ; Configure baud, test for NADSBox, get NADSBox dir      &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send Dir Reference opcode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A72H  MVI A,00H            ; Set dir reference type to &amp;quot;reference&amp;quot; for open     &lt;br /&gt;
4A74H  STA FD01H            ; Save in dir reference location in TX buffer     &lt;br /&gt;
4A77H  LXI H,1A00H          ; Load opcode for directory reference&lt;br /&gt;
4A7AH  CALL 4822H           ; Send TPDD Command/Len in HL      &lt;br /&gt;
4A7DH  CALL 47CCH           ; Receive a packet      &lt;br /&gt;
4A80H  LDA FD1CH            ; Load attribute byte     &lt;br /&gt;
4A83H  ANA A                ; Test attribute byte for zero &lt;br /&gt;
4A84H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Save OS&#039;s baud rate string to storage area, A = &amp;quot;Print error messages&amp;quot; flag&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A85H  STA FCD2H            ; Store &amp;quot;Print error messages&amp;quot; flag&lt;br /&gt;
4A88H  LXI D,F9A8H          ; Storage area for previous baud setting&lt;br /&gt;
4A8BH  LXI H,F65BH          ; RS232 parameter setting table   &lt;br /&gt;
4A8EH  LXI B,0005H          ; Copy 7 bytes of parameter data&lt;br /&gt;
4A91H  JMP 4A05H            ; Move BC bytes from M to (DE) with increment&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Configure baud, check for Desklink/NADSBox.  Set to 9600 if not Desklink/NADSBox&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4A94H  CALL 4BD7H           ; Wait for TX empty and Reset UART to accept mode bits         &lt;br /&gt;
4A97H  LXI H,4ADEH          ; Baud rate string for &amp;quot;98N1D&amp;quot;          &lt;br /&gt;
4A9AH  LXI D,F65BH          ; RS232 parameter setting table&lt;br /&gt;
4A9DH  LXI B,0005H          ; Prepare to copy 5 bytes to Baud Parameter table&lt;br /&gt;
4AA0H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment&lt;br /&gt;
4AA3H  LXI H,F65BH          ; Point to RS232 parameter setting table&lt;br /&gt;
4AA6H  STC                  ; Indicate Baud rate is part of string&lt;br /&gt;
4AA7H  CALL 4BD3H           ; Set RS232 parameters from string at M&lt;br /&gt;
4AAAH  CALL 4998H           ; Flush the RX queue &amp;amp; discard&lt;br /&gt;
4AADH  CALL 49A2H           ; Send M1 and test for NADSBox / Desklink response&lt;br /&gt;
4AB0H  CALL 49E3H           ; Delay routine - about 3ms&lt;br /&gt;
4AB3H  CALL 4BDFH           ; Check RS232 queue for pending characters&lt;br /&gt;
4AB6H  JNZ 4998H            ; Jump to flush RX and keep 19200 if NADSBox / Desklink found       &lt;br /&gt;
4AB9H  CALL 4BD7H           ; Wait for TX empty and Reset UART to accept mode bits        &lt;br /&gt;
4ABCH  LXI H,F65BH          ; Baud rate string for &amp;quot;98N1D&amp;quot;   &lt;br /&gt;
4ABFH  DCR M                ; Set baud rate to &#039;8&#039; = 9600 baud   &lt;br /&gt;
4AC0H  STC                  ; Indicate Baud rate is part of string &lt;br /&gt;
4AC1H  JMP 4BD3H            ; Set RS232 parameters from string at M - change to 9600 Baud       &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Restore original baud settings&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4AC4H  LXI H,F9A8H          ; Storage for OS&#039;s baud settings&lt;br /&gt;
4AC7H  MOV A,M              ; Get 1st byte of setting   &lt;br /&gt;
4AC8H  SUI 3AH              ; Test if 1st byte is numeric   &lt;br /&gt;
4ACAH  JC 4BD3H             ; Set RS232 parameters from string at M    &lt;br /&gt;
4ACDH  INX H                ; Skip setting baud if 1st byte is &amp;quot;M&amp;quot;odem &lt;br /&gt;
4ACEH  JMP 4BD3H            ; Set RS232 parameters from string at M     &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Strings and table data&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4AD1H  DB	&amp;quot;0 Bytes free&amp;quot;,0x00  ; Old Text - NOT USED in ROM version, only RAM version&lt;br /&gt;
4ADEH  DB	&amp;quot;98N1DNN&amp;quot;, 0x00      ; Parameters for setting baud rate&lt;br /&gt;
4ADFH  DB   &amp;quot;8N1D&amp;quot;,0x00&lt;br /&gt;
4AE4H  DB	0x02,0x03,0x01       ; RST 7,30h open mode to TPDD Open mode mapping&lt;br /&gt;
&lt;br /&gt;
4AE9H  DB	&amp;quot;ZZ1&amp;quot;,0x04,0x01,0x00,0x84,0xFF,&amp;quot;F&amp;quot;&lt;br /&gt;
4AF0H  DB	&amp;quot;ZZ1&amp;quot;,0x04,0x01,0x00,0x96,0x0F,0x24&lt;br /&gt;
4AF9H  DB	&amp;quot;ZZ1&amp;quot;,0x04,0x01,0x00,0x94,0x0F,0x26&lt;br /&gt;
&lt;br /&gt;
4B02H  DB	0x12,&amp;quot;Drive Not Ready&amp;quot;,0x00&lt;br /&gt;
       DB	0x12,&amp;quot;Communication Error&amp;quot;,0x00&lt;br /&gt;
       DB	0x12,&amp;quot;Write Protect&amp;quot;,0x00&lt;br /&gt;
       DB	0x12,&amp;quot;Drive Trouble&amp;quot;,0x00&lt;br /&gt;
       DB	0x12,&amp;quot;Disk not in drive&amp;quot;,0x00&lt;br /&gt;
       DB	0x34,&amp;quot;Printer not ready&amp;quot;,0x00&lt;br /&gt;
       DB	0x05,&amp;quot;File Exists&amp;quot;,0x00&lt;br /&gt;
       DB	0x39,&amp;quot;Disk Full&amp;quot;,0x00&lt;br /&gt;
       DB	0x1A,&amp;quot;File Empty&amp;quot;,0x00&lt;br /&gt;
       DB	0x39,&amp;quot;Directory Full&amp;quot;,0x00&lt;br /&gt;
       DB	0x07,&amp;quot;Ram Full&amp;quot;,0x00&lt;br /&gt;
       DB	0x36,0x00&lt;br /&gt;
       DB	0x37,&amp;quot;Bad File Name&amp;quot;,0x00&lt;br /&gt;
4BBBH  DB	&amp;quot; Press any key.&amp;quot;,0x00&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 1 Vectors to Main ROM.  At places in the code where a call is needed to the Main ROM,&lt;br /&gt;
;       a RST 1 followed by a 2-byte address is issued.  The routines will jump to one of&lt;br /&gt;
;       the handler functions below to perform that RST 1 operation.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
&lt;br /&gt;
4BCBH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BCCH  DW    340AH&lt;br /&gt;
4BCEH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Evaluate expressino at M-1 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BCFH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BD0H  DW    1113H&lt;br /&gt;
4BD2H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Set RS232 parameters from string at M routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BD3H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BD4H  DW    17E6H&lt;br /&gt;
4BD6H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Wait for TX empty and Reset UART routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BD7H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BD8H  DW    6ECBH&lt;br /&gt;
4BDAH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Set interrupt to 1DH routine.&lt;br /&gt;
;    Seems like it would be easy enough to just do it in this ROM!&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BDBH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BDCH  DW    765CH&lt;br /&gt;
4BDEH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Check RS232 queue for pending characters routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BDFH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BE0H  DW    6D6DH&lt;br /&gt;
4BE2H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Send A to RS-232 using XON/XOFF routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BE3H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BE4H  DW    6E32H&lt;br /&gt;
4BE6H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Get a character from RS232 receive queue routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BE7H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BE8H  DW    6D7EH&lt;br /&gt;
4BEAH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Wait for key from keyboard routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BEBH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BECH  DW    12CBH&lt;br /&gt;
4BEEH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Scan keyboard for character (CTRL-BREAK ==&amp;gt; CTRL-C) routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BEFH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BF0H  DW    7242H&lt;br /&gt;
4BF2H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Power Down routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BF3H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BF4H  DW    13B5H&lt;br /&gt;
4BF6H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Renew automatic power-off counter routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BF7H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BF8H  DW    1BB1H&lt;br /&gt;
4BFAH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Find Catalog Entry Address of current BASIC program routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BFBH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4BFCH  DW    20AFH&lt;br /&gt;
4BFEH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Kill .DO file routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4BFFH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C00H  DW    1FBFH&lt;br /&gt;
4C02H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Kill .BA file routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C03H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C04H  DW    2017H&lt;br /&gt;
4C06H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Kill .CO file routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C07H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C08H  DW    1FD9H&lt;br /&gt;
4C0AH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C0BH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C0CH  DW    6B6DH&lt;br /&gt;
4C0EH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Update system pointers routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C0FH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C10H  DW    2146H&lt;br /&gt;
4C12H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Find BASIC end of program routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C13H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C14H  DW    05F4H&lt;br /&gt;
4C16H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main Rom&#039;s Write new entry to catalog routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C17H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C18H  DW    2239H&lt;br /&gt;
4C1AH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Signed integer divide (FAC1=DE/HL) routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C1BH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C1CH  DW    377EH&lt;br /&gt;
4C1EH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Signed integer muliply (FAC1=HL*DE) routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C1FH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C20H  DW    3725H&lt;br /&gt;
4C22H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Send CRLF to LCD routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C23H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C24H  DW    4222H&lt;br /&gt;
4C26H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s CLS statement routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C27H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C28H  DW    4231H&lt;br /&gt;
4C2AH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Erase from cursor to end of line routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C2BH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C2CH  DW    425DH&lt;br /&gt;
4C2EH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Start inverse character mode routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C2FH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C30H  DW    4269H&lt;br /&gt;
4C32H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Cancel inverse video routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C33H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C34H  DW    426EH&lt;br /&gt;
4C36H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Generate error in E routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C37H  LXI H,045DH          ; Load address of Main ROM&#039;s Generate Error in E routine&lt;br /&gt;
4C3AH  PUSH H               ; Push routine to the stack&lt;br /&gt;
4C3BH  JMP 00A6H            ; Jump to Main ROM&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Print binary number in HL at current position routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C3EH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C3FH  DW    39D4H&lt;br /&gt;
4C41H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Print A to printer, expanding tabs if necessary routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C42H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C43H  DW    4B55H&lt;br /&gt;
4C45H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Input and display (no &amp;quot;?&amp;quot;) line and store routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C46H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C47H  DW    4644H&lt;br /&gt;
4C49H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Check keyboard queue for pending characters routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C4AH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C4BH  DW    13DBH&lt;br /&gt;
4C4DH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Move BC bytes from M to (DE) with decrement routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C4EH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C4FH  DW    6BE6H&lt;br /&gt;
4C51H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s LCOPY statement routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C52H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C53H  DW    1E5EH&lt;br /&gt;
4C55H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Stop automatic scrolling routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C56H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C57H  DW    423FH&lt;br /&gt;
4C59H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Resume Automatic Scrolling routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C5AH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C5BH  DW    4244H&lt;br /&gt;
4C5DH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Get char at M and convert to uppercase routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C5EH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C5FH  DW    0FE8H&lt;br /&gt;
4C61H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Get file descriptor for file in A routine&lt;br /&gt;
; NOT CALLED&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C62H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C63H  DW    4C81H&lt;br /&gt;
4C65H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Update line addresses for current BASIC program routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C66H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C67H  DW    05F0H&lt;br /&gt;
4C69H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Copy CO header bytes (6) from (HL) to &amp;quot;active&amp;quot; CO Header storage area routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C6AH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C6BH  DW    253DH&lt;br /&gt;
4C6DH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s print CO address, length and invocation address to LCD routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C6EH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C6FH  DW    25A4H&lt;br /&gt;
4C71H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Process SAVEM arguments for address, length and entry point routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
4C72H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
4C73H  DW    2346H&lt;br /&gt;
4C75H  RET&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Navigate to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DPL&amp;gt;&lt;br /&gt;
category=M100 TS-DOS ROM Disassembly&lt;br /&gt;
&amp;lt;/DPL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:M100 TS-DOS ROM Disassembly]]&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1392</id>
		<title>M100 TS-DOS ROM OptROM Support</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1392"/>
		<updated>2009-04-03T16:38:14Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TS-DOS Model 100/102 ROM OptROM Support ==&lt;br /&gt;
&lt;br /&gt;
This code defines the variables used throughout the TS-DOS application as well as the support routines needed to navigate between the Main ROM and the Option ROM (most of them).  Also included is the TS-DOS startup code.  The assembly labels defined are open for discussion and have not been applied to any of the disassembled code yet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 =========================================================================================&lt;br /&gt;
; TS-DOS M100 ROM version Disassembly&lt;br /&gt;
;&lt;br /&gt;
; Initial Disassembly By Kenneth D. Pettit&lt;br /&gt;
; March, 2009&lt;br /&gt;
;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Variables in ALTLCD buffer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
NB_CUR_DIR    equ FCC0H              ; NADSBox current directory (&amp;quot;MYFILE.&amp;lt;&amp;gt; &amp;quot;)&lt;br /&gt;
TPDD_BANK     equ FCCAH              ; TPDD2 Bank (side)&lt;br /&gt;
NB_TPDD_FLG   equ FCCBH              ; NADSBox/Desklink/TPDD2 flag (0=TPDD, 1=TPDD2, 2=NADSBox)&lt;br /&gt;
LAST_TAG      equ FCCCH              ; Tag/Untag last operation code&lt;br /&gt;
CUR_FILE      equ FCCDH              ; Currently selected file index on UI (1 based)&lt;br /&gt;
LJ_SP         equ FCCEH              ; Stack pointer upon entry for Long Jump&lt;br /&gt;
LJ_RET        equ FCD0H              ; Return vector for Long Jump &amp;quot;RETURN&amp;quot;&lt;br /&gt;
ERR_MODE      equ FCD2H              ; Print Error Messages flag, 1=Print, 0=Generate System Error&lt;br /&gt;
FDC_OPCODE    equ FCD3H              ; FDC Emulation mode opcode&lt;br /&gt;
CUR_PAGE      equ FCD4H              ; Current page of files being displayed (0 based)&lt;br /&gt;
TMP_FILE_IDX  equ FCD5H              ; Currently selected file index on UI - temp&lt;br /&gt;
FILE_COUNT    equ FCD6H              ; Count of files currently displayed on LCD&lt;br /&gt;
MAX_FILES     equ FCD7H              ; Maximum files that fit on the LCD&lt;br /&gt;
DISP_MODE     equ FCD9H              ; RAM / Disk Display mode (0=RAM,  1=DISK)&lt;br /&gt;
SKIP_PAGE     equ FCDAH              ; TPDD &amp;quot;skip page&amp;quot; count (number of pages to read and discard)&lt;br /&gt;
FILE_LEN      equ FCDBH              ; Pointer to &amp;quot;Current file&amp;quot; length bytes (in keyboard buffer)&lt;br /&gt;
PHYS_SCTR     equ FCDDH              ; FDC Emulation Physical Sector Number / Active File Length LSB&lt;br /&gt;
LOG_SCTR      equ FCDEH              ; FDC Emulation Logical Sector Number / Active File Length MSB&lt;br /&gt;
KEY_TYPE      equ FCDFH              ; Storage for FDC emulation / New file type code / Keypress storage&lt;br /&gt;
FILE_ADDR     equ FCE0H              ; Address of file being displayed/printed/loaded/saved&lt;br /&gt;
FILE_BUFF     equ FCE2H              ; Pointer for TPDD direct read data / address of file being read/written&lt;br /&gt;
TX_PKT_BUF    equ FCE6H              ; Storage for TX packets (28 bytes)&lt;br /&gt;
RX_PKT_BUF    equ FD02H              ; Storage for RX packets (130 bytes ??)&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Main Entry point when called from &amp;quot;CALL 63013,1&amp;quot;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
   &lt;br /&gt;
   .org 0000H&lt;br /&gt;
&lt;br /&gt;
0000H  JMP 00B2H            ; Jump to entry point handler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Pop registers after we power back up from a powerdown (I think)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0003H  POP H&lt;br /&gt;
0004H  POP D&lt;br /&gt;
0005H  POP B&lt;br /&gt;
0006H  POP PSW&lt;br /&gt;
0007H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 1 - Call Main ROM at location whose address follows RST 1 opcode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0008H  JMP 0080H            ; BASIC statement keyword table END to NEW&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 2 - Call Main ROM&#039;s RST 2 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0010H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0011H  DW    0010H          ; Call the Main ROM&#039;s RST 2 function&lt;br /&gt;
0013H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Compare HL and DE&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0018H  JMP 006CH            ; Jump to comparison routine&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return to Main ROM.  After issuing the OUT E0H, we will be in Main ROM.  The next opcode&lt;br /&gt;
; in Main ROM after this OUT statement occurs will be a RET (part of RST 1).  We have &lt;br /&gt;
; PUSHed a return address to the stack, so the main ROM&#039;s RET instruction will get us &lt;br /&gt;
; where to intend to go.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001BH  OUT E0H              ; Send A to the ROM bank port to switch to Main ROM&lt;br /&gt;
001DH  RET                  ; Should never execute this instruction, but just in case&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send a space to the screen/printer - Not called from anywhere.  Copy of Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001EH  MVI A,20H      ; Prepare to print a SPACE&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Send character in A to the screen / printer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0020H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0021H  DW    0020H          ; Main ROM&#039;s RST 3 routine&lt;br /&gt;
0023H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Power down TRAP.  Let Main ROM deal with it.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0024H  DI                   ; Disable interrupts while we jump   &lt;br /&gt;
0025H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector &lt;br /&gt;
0028H  POP H      &lt;br /&gt;
0029H  JMP 0003H            ; Pop regs after we power back up from a power-down? &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Bar Code Reader&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
002CH  DI                   ; Disable interrupts while we jump  &lt;br /&gt;
002DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return from Main ROM hook in RAM returns here via RST 6&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0030H  POP PSW              ; Cleanup stack&lt;br /&gt;
0031H  POP PSW              ; Cleanup stack&lt;br /&gt;
0032H  RET                  ; Return to OptROM execution point        &lt;br /&gt;
&lt;br /&gt;
0033H  NOP                  ; Filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - RS232 character pending&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0034H  DI                   ; Disable interrupts while we jump&lt;br /&gt;
0035H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
0038H  JMP 00A6H            ; Stack cleanup&lt;br /&gt;
&lt;br /&gt;
003BH  NOP                  ; UNUSED - filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Timer background task&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
003CH  DI                   ; Disable interrupts&lt;br /&gt;
003DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM to be used for switching back to the TS-DOS ROM after&lt;br /&gt;
;      calling a routine in the Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0040H  PUSH PSW             ; Preserve the PSW&lt;br /&gt;
0041H  LDA FF45H            ; Contents of port E8H&lt;br /&gt;
0044H  INR A                ; Prepare to switch to OptRom&lt;br /&gt;
0045H  OUT E0H              ; Switch to OptRom&lt;br /&gt;
0047H  RST 6                ; Get sign of FAC1&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM and appears to detect the presence of the TS-DOS ROM&lt;br /&gt;
;       after power-up and copies the original &amp;quot;External ROM&amp;quot; detection routine to RAM&lt;br /&gt;
;       if the TS-DOS ROM is no longer present.  At least I think that&#039;s what it&#039;s doing.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0048H  LXI D,F605H          ; Copy address for &amp;quot;Ext ROM detect&amp;quot; routine&lt;br /&gt;
004BH  INR A                ; Set bit to enable OptROM&lt;br /&gt;
004CH  OUT E0H              ; Switch to OptROM&lt;br /&gt;
004EH  XRA A                ; Prepare to switch back to Main ROM&lt;br /&gt;
004FH  LHLD 0049H           ; Load target address of the LXI D instruction above&lt;br /&gt;
0052H  OUT E0H              ; Switch back to Main ROM&lt;br /&gt;
0054H  RST 3                ; Compare DE and HL - Test if OptROM is TS-DOS&lt;br /&gt;
0055H  CPI 01H              ; Test for TS-DOS ROM&lt;br /&gt;
0057H  RC                   ; Return if TS-DOS ROM&lt;br /&gt;
0058H  LXI H,111DH          ; Load &amp;quot;Return&amp;quot; address to the CALL below&lt;br /&gt;
005BH  SHLD FAE0H&lt;br /&gt;
005EH  SHLD F5F2H           ; Save a &amp;quot;Restart signature&amp;quot; ???&lt;br /&gt;
0061H  CALL 2905H           ; Copy the DB number of bytes from the DW address to (DE)&lt;br /&gt;
0064H  DB   24H             ; ....copy 24H bytes&lt;br /&gt;
0065H  DW   036FH           ; ....from ROM addres 036F (external ROM detect)&lt;br /&gt;
0067H  RST 0                ; I&#039;m not sure it it every actually returns here or not&lt;br /&gt;
0068H  NOP&lt;br /&gt;
0069H  CALL FAA4H           ; Call our installed RAM hook to return to TS-DOS&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Compare HL and DE - called by the RST 3 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
006CH  MOV A,H              ; Move H into A for comparison&lt;br /&gt;
006DH  SUB D                ; Compare MSB first&lt;br /&gt;
006EH  RNZ                  ; Return if no match&lt;br /&gt;
006FH  MOV A,L              ; Now move L into A&lt;br /&gt;
0070H  SUB E                ; Compare LSB&lt;br /&gt;
0071H  RET                  ; Return with flags set&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy 8 bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0072H  LXI B,0008H          ; Prepare to copy 8 bytes &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy BC bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0075H  LDAX D               ; Load value from (DE)&lt;br /&gt;
0076H  MOV M,A              ; Save value to (HL)&lt;br /&gt;
0077H  INX D                ; Increment DE&lt;br /&gt;
0078H  INX H                ; Increment HL&lt;br /&gt;
0079H  DCX B                ; Decrement counter&lt;br /&gt;
007AH  MOV A,B              ; Prepare to test counter for zero&lt;br /&gt;
007BH  ORA C                ; Test counter for zero&lt;br /&gt;
007CH  JNZ 0075H            ; Keep looping until 8 bytes copied&lt;br /&gt;
007FH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Handle the RST 1 routine.  Read the Main ROM address from the 2 bytes after the RST 1&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0080H  SHLD F9B2H           ; Save HL off in &amp;quot;RickY&amp;quot; Cat entry so we don&#039;t clobber it&lt;br /&gt;
0083H  POP H                ; Get out return address (location of the ROM address to call&lt;br /&gt;
0084H  PUSH D               ; Push the return address back to the stack as storage &lt;br /&gt;
0085H  MOV E,M              ; Get LSB of the ROM address to call&lt;br /&gt;
0086H  INX H                ; Point to MSB of ROM address to call&lt;br /&gt;
0087H  MOV D,M              ; Get MSB of the ROM address to call&lt;br /&gt;
0088H  INX H                ; Point to return address after the RST 1 DB address&lt;br /&gt;
0089H  XTHL                 ; Put the return address on the stack so we return after the RST 1&lt;br /&gt;
008AH  XCHG                 ; Now get the address within ROM to call&lt;br /&gt;
008BH  PUSH H               ; Push the target ROM address to the stack so we &amp;quot;RETurn&amp;quot; there&lt;br /&gt;
008CH  LXI H,FAA4H          ; Load address of our RAM hook to switch back to our ROM bank and RET&lt;br /&gt;
008FH  XTHL                 ; Push that address on the stack for after the ROM call is complete&lt;br /&gt;
0090H  PUSH H               ; Now put the ROM address back on the stack so we will RET there&lt;br /&gt;
0091H  LHLD F9B2H           ; Restore HL from temp storage in &amp;quot;RickY&amp;quot;&lt;br /&gt;
0094H  JMP 00A6H            ; Branch to switch to Main ROM and &amp;quot;RET&amp;quot; to the address we pushed&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST handler for calling the Main ROM&#039;s RST handlers.  This routine restores the original&lt;br /&gt;
;      RST vector address to the stack, and jumps to the Main ROM&#039;s RST routine while &lt;br /&gt;
;      preserving all register values.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0097H  SHLD F9B4H           ; Save HL temporarily (somewhere in RickY&#039;s name)&lt;br /&gt;
009AH  LXI H,FAA4H          ; Point to our RAM hook for returning to TS-DOS&lt;br /&gt;
009DH  XTHL                 ; Put the hook address as the return address on the stack&lt;br /&gt;
009EH  DCX H                ; Decrement the return address by 4&lt;br /&gt;
009FH  DCX H                ; ...this will result in the starting address of the RST&lt;br /&gt;
00A0H  DCX H                ; ...that brought us here&lt;br /&gt;
00A1H  DCX H&lt;br /&gt;
00A2H  PUSH H               ; Push the RST vector address to the stack&lt;br /&gt;
00A3H  LHLD F9B4H           ; Restore HL upon entry&lt;br /&gt;
00A6H  PUSH PSW             ; Save A to the stack&lt;br /&gt;
00A7H  PUSH H               ; Save the HL to the stack so we can preserve through XTHL&lt;br /&gt;
00A8H  LXI H,1488H          ; Load a RETurn address in the Main ROM (a POP PSW &amp;amp; RET) &lt;br /&gt;
00ABH  XTHL                 ; Push the address and get HL back&lt;br /&gt;
00ACH  LDA FF45H            ; Contents of port E8H - prepare for jump to Main ROM&lt;br /&gt;
00AFH  JMP 001BH            ; Jump to Main ROM &amp;amp; our custom &amp;quot;RET&amp;quot; address in the ROM&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Manual invocation entry point.  This is where we jump when &amp;quot;CALL 63013,1&amp;quot; is invoked&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
00B2H  DI                   ; Disable interrupts so nobody bugs us yet&lt;br /&gt;
00B3H  CPI 08H              ; Check the invocation parameter to test for recovery request&lt;br /&gt;
00B5H  JNC 0100H            ; Jump to test for recovery mode&lt;br /&gt;
00B8H  MOV B,A              ; Save the calling paramter to B&lt;br /&gt;
00B9H  PUSH B               ; Save BC to the stack&lt;br /&gt;
00BAH  PUSH D               ; Save DE to the stack&lt;br /&gt;
00BBH  PUSH H               ; Save HL to the stack&lt;br /&gt;
00BCH  LXI D,0040H          ; Load address of our &amp;quot;Change to OptROM&amp;quot; routine&lt;br /&gt;
00BFH  LXI H,FAA4H          ; Load pointer to somewhere in RAM to hold our routine&lt;br /&gt;
00C2H  CALL 0072H           ; Copy 8 bytes from DE to HL &lt;br /&gt;
00C5H  LXI B,0024H          ; Now prepare to copy 36 bytes worth of &amp;quot;routine&amp;quot;&lt;br /&gt;
00C8H  LXI H,F605H          ; Point to another RAM location&lt;br /&gt;
00CBH  CALL 0075H           ; Copy the next &amp;quot;ROM Bank Switching&amp;quot; routine from our ROM&lt;br /&gt;
00CEH  POP H                ; Restore HL&lt;br /&gt;
00CFH  POP D                ; Restore DE&lt;br /&gt;
00D0H  POP PSW              ; Restore A&lt;br /&gt;
00D1H  EI                   ; Allow interrupts again&lt;br /&gt;
00D2H  JMP 0100H            ; Go test if a &amp;quot;Cold Start&amp;quot; recovery is being requested&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    .org 100H&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Test if cold-start recovery requested&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0100H  MOV A,H              ; Move H to A to test HL for zero&lt;br /&gt;
0101H  ORA L                ; Test for zero&lt;br /&gt;
0102H  JZ 7000H             ; Call recovery routine if requested&lt;br /&gt;
0105H  POP H                ; Pop the return address.  We will exit manually&lt;br /&gt;
0106H  CALL 0117H           ; Ensure the TS-DOS progam is installed in the MENU&lt;br /&gt;
0109H  JMP 3535H            ; Jump to the TS-DOS UI&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
010CH  MOV A,M              ; Get next byte from (HL)&lt;br /&gt;
010DH  STAX D               ; Save byte in (DE)&lt;br /&gt;
010EH  INX H                ; Increment source pointer&lt;br /&gt;
010FH  INX D                ; Increment destination pointer&lt;br /&gt;
0110H  DCX B                ; Decrement loop control&lt;br /&gt;
0111H  MOV A,B              ; Move MSB to A to test for zero&lt;br /&gt;
0112H  ORA C                ; OR in LSB to test for zero&lt;br /&gt;
0113H  JNZ 010CH            ; Branch to copy next byte until done&lt;br /&gt;
0116H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert the &amp;quot;TS-DOS&amp;quot; invocation program (BASIC program) into the Catalog / MENU.&lt;br /&gt;
;    we insert ourselves just before the &amp;quot;unsaved BASIC program&amp;quot;.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0117H  LXI H,01E1H          ; Point to &amp;quot;TS-DOS&amp;quot; catalog entry in our ROM&lt;br /&gt;
011AH  PUSH H               ; Save the address on the stack for later&lt;br /&gt;
011BH  INX H                ; Point to the text portion of the catalog entry&lt;br /&gt;
011CH  LXI B,0008H          ; Prepare to copy 8 filename byte&lt;br /&gt;
011FH  LXI D,FC93H          ; Filename of current BASIC program&lt;br /&gt;
0122H  CALL 010CH           ; Copy BC bytes from HL to DE - put &amp;quot;TS-DOS  &amp;quot; in cur. BASIC prog.&lt;br /&gt;
0125H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  DE now has the address of the invocation program&lt;br /&gt;
0126H  LHLX                 ; Get the length of the BASIC program into HL&lt;br /&gt;
0127H  SHLD FCC4H           ; Save the BASIC program length in the ALTLCD buffer for now&lt;br /&gt;
012AH  INX D                ; Point to MSB of the length&lt;br /&gt;
012BH  INX D                ; Point to LSB of the pointer to the &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
012CH  XCHG                 ; HL &amp;lt;--&amp;gt; DE HL has the pointer to the &amp;quot;Next&amp;quot; BASIC inst address&lt;br /&gt;
012DH  SHLD FCC8H           ; Save the &amp;quot;Next&amp;quot; BASIC inst pointer to ALTLCD (start of program)&lt;br /&gt;
0130H  CALL 01D1H           ; Update the System pointers&lt;br /&gt;
0133H  CALL 01CDH           ; Search Catalog for entry matching current BASIC program&lt;br /&gt;
0136H  POP B                ; Pop address in case we return&lt;br /&gt;
0137H  RNZ                  ; Return if &amp;quot;TS-DOS&amp;quot; is already in the catalog&lt;br /&gt;
0138H  LHLD F99AH           ; Get the BASIC program not saved pointer - insert before that&lt;br /&gt;
013BH  SHLD FCC2H           ; Save storage location for the TS-DOS invocation progam&lt;br /&gt;
013EH  LDAX B               ; Load the file type byte from our ROM (B has the address from above)&lt;br /&gt;
013FH  STA FCC6H            ; Store the Type byte in the ALTLCD &lt;br /&gt;
0142H  CALL 0185H           ; Find empty entry in Catalog&lt;br /&gt;
0145H  RC                   ; Return if catalog full&lt;br /&gt;
0146H  PUSH H               ; Save the address of the empty catalog entry to the stack&lt;br /&gt;
0147H  LHLD FCC4H           ; Restore the BASIC program length from ALTLCD&lt;br /&gt;
014AH  MOV B,H              ; Move BASIC program length to BC for copy&lt;br /&gt;
014BH  MOV C,L              ; Move LSB of length&lt;br /&gt;
014CH  PUSH B               ; Save Length to the stack&lt;br /&gt;
014DH  LHLD FCC2H           ; Get address of insertion for TS-DOS just before the unsaved BASIC prog.&lt;br /&gt;
0150H  CALL 01DDH           ; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
0153H  JC 0182H             ; Abort if RAM full&lt;br /&gt;
0156H  LHLD FCC2H           ; Get address of insertion point again&lt;br /&gt;
0159H  XCHG                 ; DE now has insertion point for BASIC program&lt;br /&gt;
015AH  LHLD FCC8H           ; Get the address of the BASIC program (in our ROM) from ALTLCD&lt;br /&gt;
015DH  POP B                ; Restore copy length of the BASIC program&lt;br /&gt;
015EH  CALL 010CH           ; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
0161H  POP D                ; Get the address of the empty catalog entry we will use for TS-DOS&lt;br /&gt;
0162H  PUSH D               ; Save it back to the stack&lt;br /&gt;
0163H  LHLD FBAEH           ; Load the start of DO files pointer&lt;br /&gt;
0166H  DCX H                ; Derement the start of DO files pointer&lt;br /&gt;
0167H  SHLD F99AH           ; Save it as the new BASIC program not saved pointer&lt;br /&gt;
016AH  INX H                ; Point to start of DO files again&lt;br /&gt;
016BH  XCHG                 ; Move it to DE&lt;br /&gt;
016CH  LHLD FCC4H           ; Load the TS-DOS BASIC progam length from ALTLCD&lt;br /&gt;
016FH  DAD D                ; Offset the start of DO files by the insertion amount&lt;br /&gt;
0170H  SHLD FBAEH           ; Save the new start of DO files pointer&lt;br /&gt;
0173H  POP D                ; Restore the address of the empty catalog entry&lt;br /&gt;
0174H  LHLD FCC2H           ; Get the starting address of the newly inserted TS-DOS program&lt;br /&gt;
0177H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  Swap for the call to the catalog insertion routine &lt;br /&gt;
0178H  LDA FCC6H            ; Load A with the file type byte&lt;br /&gt;
017BH  CALL 01D5H           ; Save current BASIC program to the Catalog entry at HL&lt;br /&gt;
017EH  CALL 01D1H           ; Update system pointers&lt;br /&gt;
0181H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert &amp;quot;TS-DOS&amp;quot; RAM full abort routine ... stack cleanup.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0182H  POP H                ; Pop the BASIC program length from the stack&lt;br /&gt;
0183H  POP H                ; Pop the catalog entry address from the stack&lt;br /&gt;
0184H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Find an empty entry in the Catalog.  HL points to start of new entry&lt;br /&gt;
;     This routine appears again at address 3E48H&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0185H  LXI H,F9AFH          ; Point to &amp;quot;RickY&amp;quot; to start search at beginning of catalog&lt;br /&gt;
0188H  LXI B,000BH          ; Get length of each entry in the Catalog&lt;br /&gt;
018BH  DAD B                ; Point to next entry in the catalog&lt;br /&gt;
018CH  MOV A,M              ; Get the File Attribute byte from the catalog for this file&lt;br /&gt;
018DH  CPI FFH              ; Test if at end of the catalog&lt;br /&gt;
018FH  JZ 0197H             ; Jump to set Carry flag and exit if at end&lt;br /&gt;
0192H  ADD A                ; Test if MSB set (test if entry available)&lt;br /&gt;
0193H  JC 018BH             ; Branch to get next entry if this one is used&lt;br /&gt;
0196H  RET                  ; Return with Carry clear to indicate entry found&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Empty catalog entry not found in Catalog, set Carry and return&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0197H  STC                  ; Set the Carry flag - not found&lt;br /&gt;
0198H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Display function key line routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0199H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019AH  DW    42A8H&lt;br /&gt;
019CH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Erase function key display routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
019DH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019EH  DW    428AH&lt;br /&gt;
01A0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Set new function key table routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A2H  DW    5A7CH&lt;br /&gt;
01A4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Wait for key from keyboard routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A6H  DW    12CBH&lt;br /&gt;
01A8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Scan keyboard for character (CTRL-BREAK ==&amp;gt; CTRL-C) routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AAH  DW    7242H&lt;br /&gt;
01ACH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Power Down routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01ADH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AEH  DW    13B5H&lt;br /&gt;
01B0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Renew automatic power-off counter routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B2H  DW    1BB1H&lt;br /&gt;
01B4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s CLS statement routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B6H  DW    4231H&lt;br /&gt;
01B8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Start inverse character mode routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BAH  DW    4269H&lt;br /&gt;
01BCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Cancel inverse video routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01BDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BEH  DW    426EH&lt;br /&gt;
01C0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Check keyboard queue for pending characters routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C2H  DW    13DBH&lt;br /&gt;
01C4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Stop automatic scrolling routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C6H  DW    423FH&lt;br /&gt;
01C8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Reset vector routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CAH  DW    0000H&lt;br /&gt;
01CCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Search Catalog for entry matching current BASIC program&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01CDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CEH  DW    20AFH&lt;br /&gt;
01D0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Update system pointers routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D2H  DW    2146H&lt;br /&gt;
01D4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s routine to save current BASIC program to the Catalog entry at HL&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D6H  DW    2239H&lt;br /&gt;
01D8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Not a valid entry into ROM and not called anywhere&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DAH  DW    5825H&lt;br /&gt;
01DCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01DDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DEH  DB    6B6DH&lt;br /&gt;
01E0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; TS-DOS entry that will be inserted into the catalog for invoking TS-DOS&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01E1H  DB   80H             ; TS-DOS file type for catalog entry&lt;br /&gt;
01E2H  DB   &amp;quot;TS-DOS  &amp;quot;      ; TS-DOS Catalog name entry&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; BASIC program that will be inserted into RAM to launch TS-DOS from the MENU/Catalog entry&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01EAH  DB   0FH,00H,0EH,80H ; BASIC program length and pointer to &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
01EDH  DB   0AH,00H,B9H     ; BASIC Line number &amp;quot;10&amp;quot; and BASIC token for CALL&lt;br /&gt;
01EFH  DB   &amp;quot;63013,1&amp;quot;       ; CALL argument &lt;br /&gt;
01F5H  DB   00H,00H         ; BASIC terminating zeros&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
End of disassembly for OptROM Support.&lt;br /&gt;
&lt;br /&gt;
Navigate to:&lt;br /&gt;
* [[Dissasembly of RAM and ROM versions of TS-DOS]]&lt;br /&gt;
* [[M100 TS-DOS ROM UI Code]]&lt;br /&gt;
* [[M100 TS-DOS ROM RST 7 Handlers]]&lt;br /&gt;
* [[M100 TS-DOS ROM TPDD Protocol]]&lt;br /&gt;
* [[M100 TS-DOS ROM Compression]]&lt;br /&gt;
* [[M100 TS-DOS ROM Cold Boot Recovery]]&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1391</id>
		<title>M100 TS-DOS ROM OptROM Support</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1391"/>
		<updated>2009-04-03T16:36:51Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TS-DOS Model 100/102 ROM OptROM Support ==&lt;br /&gt;
&lt;br /&gt;
This code defines the variables used throughout the TS-DOS application as well as the support routines needed to navigate between the Main ROM and the Option ROM (most of them).  Also included is the TS-DOS startup code.  The assembly labels defined are open for discussion and have not been applied to any of the disassembled code yet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 =========================================================================================&lt;br /&gt;
; TS-DOS M100 ROM version Disassembly&lt;br /&gt;
;&lt;br /&gt;
; Initial Disassembly By Kenneth D. Pettit&lt;br /&gt;
; March, 2009&lt;br /&gt;
;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Variables in ALTLCD buffer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
NB_CUR_DIR    equ FCC0H              ; NADSBox current directory (&amp;quot;MYFILE.&amp;lt;&amp;gt; &amp;quot;)&lt;br /&gt;
TPDD_BANK     equ FCCAH              ; TPDD2 Bank (side)&lt;br /&gt;
NB_TPDD_FLG   equ FCCBH              ; NADSBox/Desklink/TPDD2 flag (0=TPDD, 1=TPDD2, 2=NADSBox)&lt;br /&gt;
LAST_TAG      equ FCCCH              ; Tag/Untag last operation code&lt;br /&gt;
CUR_FILE      equ FCCDH              ; Currently selected file index on UI (1 based)&lt;br /&gt;
LJ_SP         equ FCCEH              ; Stack pointer upon entry for Long Jump&lt;br /&gt;
LJ_RET        equ FCD0H              ; Return vector for Long Jump &amp;quot;RETURN&amp;quot;&lt;br /&gt;
ERR_MODE      equ FCD2H              ; Print Error Messages flag, 1=Print, 0=Generate System Error&lt;br /&gt;
FDC_OPCODE    equ FCD3H              ; FDC Emulation mode opcode&lt;br /&gt;
CUR_PAGE      equ FCD4H              ; Current page of files being displayed (0 based)&lt;br /&gt;
TMP_FILE_IDX  equ FCD5H              ; Currently selected file index on UI - temp&lt;br /&gt;
FILE_COUNT    equ FCD6H              ; Count of files currently displayed on LCD&lt;br /&gt;
MAX_FILES     equ FCD7H              ; Maximum files that fit on the LCD&lt;br /&gt;
DISP_MODE     equ FCD9H              ; RAM / Disk Display mode (0=RAM,  1=DISK)&lt;br /&gt;
SKIP_PAGE     equ FCDAH              ; TPDD &amp;quot;skip page&amp;quot; count (number of pages to read and discard)&lt;br /&gt;
FILE_LEN      equ FCDBH              ; Pointer to &amp;quot;Current file&amp;quot; length bytes (in keyboard buffer)&lt;br /&gt;
PHYS_SCTR     equ FCDDH              ; FDC Emulation Physical Sector Number / Active File Length LSB&lt;br /&gt;
LOG_SCTR      equ FCDEH              ; FDC Emulation Logical Sector Number / Active File Length MSB&lt;br /&gt;
KEY_TYPE      equ FCDFH              ; Storage for FDC emulation / New file type code / Keypress storage&lt;br /&gt;
FILE_ADDR     equ FCE0H              ; Address of file being displayed/printed/loaded/saved&lt;br /&gt;
FILE_BUFF     equ FCE2H              ; Pointer for TPDD direct read data / address of file being read/written&lt;br /&gt;
TX_PKT_BUF    equ FCE6H              ; Storage for TX packets (28 bytes)&lt;br /&gt;
RX_PKT_BUF    equ FD02H              ; Storage for RX packets (130 bytes ??)&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Main Entry point when called from &amp;quot;CALL 63013,1&amp;quot;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
   &lt;br /&gt;
   .org 0000H&lt;br /&gt;
&lt;br /&gt;
0000H  JMP 00B2H            ; Jump to entry point handler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Pop registers after we power back up from a powerdown (I think)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0003H  POP H&lt;br /&gt;
0004H  POP D&lt;br /&gt;
0005H  POP B&lt;br /&gt;
0006H  POP PSW&lt;br /&gt;
0007H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 1 - Call Main ROM at location whose address follows RST 1 opcode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0008H  JMP 0080H            ; BASIC statement keyword table END to NEW&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 2 - Call Main ROM&#039;s RST 2 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0010H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0011H  DW    0010H          ; Call the Main ROM&#039;s RST 2 function&lt;br /&gt;
0013H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Compare HL and DE&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0018H  JMP 006CH            ; Jump to comparison routine&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return to Main ROM.  After issuing the OUT E0H, we will be in Main ROM.  The next opcode&lt;br /&gt;
; in Main ROM after this OUT statement occurs will be a RET (part of RST 1).  We have &lt;br /&gt;
; PUSHed a return address to the stack, so the main ROM&#039;s RET instruction will get us &lt;br /&gt;
; where to intend to go.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001BH  OUT E0H              ; Send A to the ROM bank port to switch to Main ROM&lt;br /&gt;
001DH  RET                  ; Should never execute this instruction, but just in case&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send a space to the screen/printer - Not called from anywhere.  Copy of Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001EH  MVI A,20H      ; Prepare to print a SPACE&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Send character in A to the screen / printer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0020H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0021H  DW    0020H          ; Main ROM&#039;s RST 3 routine&lt;br /&gt;
0023H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Power down TRAP.  Let Main ROM deal with it.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0024H  DI                   ; Disable interrupts while we jump   &lt;br /&gt;
0025H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector &lt;br /&gt;
0028H  POP H      &lt;br /&gt;
0029H  JMP 0003H            ; Pop regs after we power back up from a power-down? &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Bar Code Reader&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
002CH  DI                   ; Disable interrupts while we jump  &lt;br /&gt;
002DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return from Main ROM hook in RAM returns here via RST 6&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0030H  POP PSW              ; Cleanup stack&lt;br /&gt;
0031H  POP PSW              ; Cleanup stack&lt;br /&gt;
0032H  RET                  ; Return to OptROM execution point        &lt;br /&gt;
&lt;br /&gt;
0033H  NOP                  ; Filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - RS232 character pending&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0034H  DI                   ; Disable interrupts while we jump&lt;br /&gt;
0035H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
0038H  JMP 00A6H            ; Stack cleanup&lt;br /&gt;
&lt;br /&gt;
003BH  NOP                  ; UNUSED - filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Timer background task&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
003CH  DI                   ; Disable interrupts&lt;br /&gt;
003DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM to be used for switching back to the TS-DOS ROM after&lt;br /&gt;
;      calling a routine in the Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0040H  PUSH PSW             ; Preserve the PSW&lt;br /&gt;
0041H  LDA FF45H            ; Contents of port E8H&lt;br /&gt;
0044H  INR A                ; Prepare to switch to OptRom&lt;br /&gt;
0045H  OUT E0H              ; Switch to OptRom&lt;br /&gt;
0047H  RST 6                ; Get sign of FAC1&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM and appears to detect the presence of the TS-DOS ROM&lt;br /&gt;
;       after power-up and copies the original &amp;quot;External ROM&amp;quot; detection routine to RAM&lt;br /&gt;
;       if the TS-DOS ROM is no longer present.  At least I think that&#039;s what it&#039;s doing.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0048H  LXI D,F605H          ; Copy address for &amp;quot;Ext ROM detect&amp;quot; routine&lt;br /&gt;
004BH  INR A                ; Set bit to enable OptROM&lt;br /&gt;
004CH  OUT E0H              ; Switch to OptROM&lt;br /&gt;
004EH  XRA A                ; Prepare to switch back to Main ROM&lt;br /&gt;
004FH  LHLD 0049H           ; Load target address of the LXI D instruction above&lt;br /&gt;
0052H  OUT E0H              ; Switch back to Main ROM&lt;br /&gt;
0054H  RST 3                ; Compare DE and HL - Test if OptROM is TS-DOS&lt;br /&gt;
0055H  CPI 01H              ; Test for TS-DOS ROM&lt;br /&gt;
0057H  RC                   ; Return if TS-DOS ROM&lt;br /&gt;
0058H  LXI H,111DH          ; Load &amp;quot;Return&amp;quot; address to the CALL below&lt;br /&gt;
005BH  SHLD FAE0H&lt;br /&gt;
005EH  SHLD F5F2H           ; Save a &amp;quot;Restart signature&amp;quot; ???&lt;br /&gt;
0061H  CALL 2905H           ; Copy the DB number of bytes from the DW address to (DE)&lt;br /&gt;
0064H  DB   24H             ; ....copy 24H bytes&lt;br /&gt;
0065H  DW   036FH           ; ....from ROM addres 036F (external ROM detect)&lt;br /&gt;
0067H  RST 0                ; I&#039;m not sure it it every actually returns here or not&lt;br /&gt;
0068H  NOP&lt;br /&gt;
0069H  CALL FAA4H           ; Call our installed RAM hook to return to TS-DOS&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Compare HL and DE - called by the RST 3 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
006CH  MOV A,H              ; Move H into A for comparison&lt;br /&gt;
006DH  SUB D                ; Compare MSB first&lt;br /&gt;
006EH  RNZ                  ; Return if no match&lt;br /&gt;
006FH  MOV A,L              ; Now move L into A&lt;br /&gt;
0070H  SUB E                ; Compare LSB&lt;br /&gt;
0071H  RET                  ; Return with flags set&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy 8 bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0072H  LXI B,0008H          ; Prepare to copy 8 bytes &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy BC bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0075H  LDAX D               ; Load value from (DE)&lt;br /&gt;
0076H  MOV M,A              ; Save value to (HL)&lt;br /&gt;
0077H  INX D                ; Increment DE&lt;br /&gt;
0078H  INX H                ; Increment HL&lt;br /&gt;
0079H  DCX B                ; Decrement counter&lt;br /&gt;
007AH  MOV A,B              ; Prepare to test counter for zero&lt;br /&gt;
007BH  ORA C                ; Test counter for zero&lt;br /&gt;
007CH  JNZ 0075H            ; Keep looping until 8 bytes copied&lt;br /&gt;
007FH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Handle the RST 1 routine.  Read the Main ROM address from the 2 bytes after the RST 1&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0080H  SHLD F9B2H           ; Save HL off in &amp;quot;RickY&amp;quot; Cat entry so we don&#039;t clobber it&lt;br /&gt;
0083H  POP H                ; Get out return address (location of the ROM address to call&lt;br /&gt;
0084H  PUSH D               ; Push the return address back to the stack as storage &lt;br /&gt;
0085H  MOV E,M              ; Get LSB of the ROM address to call&lt;br /&gt;
0086H  INX H                ; Point to MSB of ROM address to call&lt;br /&gt;
0087H  MOV D,M              ; Get MSB of the ROM address to call&lt;br /&gt;
0088H  INX H                ; Point to return address after the RST 1 DB address&lt;br /&gt;
0089H  XTHL                 ; Put the return address on the stack so we return after the RST 1&lt;br /&gt;
008AH  XCHG                 ; Now get the address within ROM to call&lt;br /&gt;
008BH  PUSH H               ; Push the target ROM address to the stack so we &amp;quot;RETurn&amp;quot; there&lt;br /&gt;
008CH  LXI H,FAA4H          ; Load address of our RAM hook to switch back to our ROM bank and RET&lt;br /&gt;
008FH  XTHL                 ; Push that address on the stack for after the ROM call is complete&lt;br /&gt;
0090H  PUSH H               ; Now put the ROM address back on the stack so we will RET there&lt;br /&gt;
0091H  LHLD F9B2H           ; Restore HL from temp storage in &amp;quot;RickY&amp;quot;&lt;br /&gt;
0094H  JMP 00A6H            ; Branch to switch to Main ROM and &amp;quot;RET&amp;quot; to the address we pushed&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST handler for calling the Main ROM&#039;s RST handlers.  This routine restores the original&lt;br /&gt;
;      RST vector address to the stack, and jumps to the Main ROM&#039;s RST routine while &lt;br /&gt;
;      preserving all register values.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0097H  SHLD F9B4H           ; Save HL temporarily (somewhere in RickY&#039;s name)&lt;br /&gt;
009AH  LXI H,FAA4H          ; Point to our RAM hook for returning to TS-DOS&lt;br /&gt;
009DH  XTHL                 ; Put the hook address as the return address on the stack&lt;br /&gt;
009EH  DCX H                ; Decrement the return address by 4&lt;br /&gt;
009FH  DCX H                ; ...this will result in the starting address of the RST&lt;br /&gt;
00A0H  DCX H                ; ...that brought us here&lt;br /&gt;
00A1H  DCX H&lt;br /&gt;
00A2H  PUSH H               ; Push the RST vector address to the stack&lt;br /&gt;
00A3H  LHLD F9B4H           ; Restore HL upon entry&lt;br /&gt;
00A6H  PUSH PSW             ; Save A to the stack&lt;br /&gt;
00A7H  PUSH H               ; Save the HL to the stack so we can preserve through XTHL&lt;br /&gt;
00A8H  LXI H,1488H          ; Load a RETurn address in the Main ROM (a POP PSW &amp;amp; RET) &lt;br /&gt;
00ABH  XTHL                 ; Push the address and get HL back&lt;br /&gt;
00ACH  LDA FF45H            ; Contents of port E8H - prepare for jump to Main ROM&lt;br /&gt;
00AFH  JMP 001BH            ; Jump to Main ROM &amp;amp; our custom &amp;quot;RET&amp;quot; address in the ROM&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Manual invocation entry point.  This is where we jump when &amp;quot;CALL 63013,1&amp;quot; is invoked&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
00B2H  DI                   ; Disable interrupts so nobody bugs us yet&lt;br /&gt;
00B3H  CPI 08H              ; Check the invocation parameter to test for recovery request&lt;br /&gt;
00B5H  JNC 0100H            ; Jump to test for recovery mode&lt;br /&gt;
00B8H  MOV B,A              ; Save the calling paramter to B&lt;br /&gt;
00B9H  PUSH B               ; Save BC to the stack&lt;br /&gt;
00BAH  PUSH D               ; Save DE to the stack&lt;br /&gt;
00BBH  PUSH H               ; Save HL to the stack&lt;br /&gt;
00BCH  LXI D,0040H          ; Load address of our &amp;quot;Change to OptROM&amp;quot; routine&lt;br /&gt;
00BFH  LXI H,FAA4H          ; Load pointer to somewhere in RAM to hold our routine&lt;br /&gt;
00C2H  CALL 0072H           ; Copy 8 bytes from DE to HL &lt;br /&gt;
00C5H  LXI B,0024H          ; Now prepare to copy 36 bytes worth of &amp;quot;routine&amp;quot;&lt;br /&gt;
00C8H  LXI H,F605H          ; Point to another RAM location&lt;br /&gt;
00CBH  CALL 0075H           ; Copy the next &amp;quot;ROM Bank Switching&amp;quot; routine from our ROM&lt;br /&gt;
00CEH  POP H                ; Restore HL&lt;br /&gt;
00CFH  POP D                ; Restore DE&lt;br /&gt;
00D0H  POP PSW              ; Restore A&lt;br /&gt;
00D1H  EI                   ; Allow interrupts again&lt;br /&gt;
00D2H  JMP 0100H            ; Go test if a &amp;quot;Cold Start&amp;quot; recovery is being requested&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    .org 100H&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Test if cold-start recovery requested&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0100H  MOV A,H              ; Move H to A to test HL for zero&lt;br /&gt;
0101H  ORA L                ; Test for zero&lt;br /&gt;
0102H  JZ 7000H             ; Call recovery routine if requested&lt;br /&gt;
0105H  POP H                ; Pop the return address.  We will exit manually&lt;br /&gt;
0106H  CALL 0117H           ; Ensure the TS-DOS progam is installed in the MENU&lt;br /&gt;
0109H  JMP 3535H            ; Jump to the TS-DOS UI&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
010CH  MOV A,M              ; Get next byte from (HL)&lt;br /&gt;
010DH  STAX D               ; Save byte in (DE)&lt;br /&gt;
010EH  INX H                ; Increment source pointer&lt;br /&gt;
010FH  INX D                ; Increment destination pointer&lt;br /&gt;
0110H  DCX B                ; Decrement loop control&lt;br /&gt;
0111H  MOV A,B              ; Move MSB to A to test for zero&lt;br /&gt;
0112H  ORA C                ; OR in LSB to test for zero&lt;br /&gt;
0113H  JNZ 010CH            ; Branch to copy next byte until done&lt;br /&gt;
0116H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert the &amp;quot;TS-DOS&amp;quot; invocation program (BASIC program) into the Catalog / MENU.&lt;br /&gt;
;    we always insert ourselves at the lowest RAM address.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0117H  LXI H,01E1H          ; Point to &amp;quot;TS-DOS&amp;quot; catalog entry in our ROM&lt;br /&gt;
011AH  PUSH H               ; Save the address on the stack for later&lt;br /&gt;
011BH  INX H                ; Point to the text portion of the catalog entry&lt;br /&gt;
011CH  LXI B,0008H          ; Prepare to copy 8 filename byte&lt;br /&gt;
011FH  LXI D,FC93H          ; Filename of current BASIC program&lt;br /&gt;
0122H  CALL 010CH           ; Copy BC bytes from HL to DE - put &amp;quot;TS-DOS  &amp;quot; in cur. BASIC prog.&lt;br /&gt;
0125H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  DE now has the address of the invocation program&lt;br /&gt;
0126H  LHLX                 ; Get the length of the BASIC program into HL&lt;br /&gt;
0127H  SHLD FCC4H           ; Save the BASIC program length in the ALTLCD buffer for now&lt;br /&gt;
012AH  INX D                ; Point to MSB of the length&lt;br /&gt;
012BH  INX D                ; Point to LSB of the pointer to the &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
012CH  XCHG                 ; HL &amp;lt;--&amp;gt; DE HL has the pointer to the &amp;quot;Next&amp;quot; BASIC inst address&lt;br /&gt;
012DH  SHLD FCC8H           ; Save the &amp;quot;Next&amp;quot; BASIC inst pointer to ALTLCD (start of program)&lt;br /&gt;
0130H  CALL 01D1H           ; Update the System pointers&lt;br /&gt;
0133H  CALL 01CDH           ; Search Catalog for entry matching current BASIC program&lt;br /&gt;
0136H  POP B                ; Pop address in case we return&lt;br /&gt;
0137H  RNZ                  ; Return if &amp;quot;TS-DOS&amp;quot; is already in the catalog&lt;br /&gt;
0138H  LHLD F99AH           ; Get the BASIC program not saved pointer - insert before that&lt;br /&gt;
013BH  SHLD FCC2H           ; Save storage location for the TS-DOS invocation progam&lt;br /&gt;
013EH  LDAX B               ; Load the file type byte from our ROM (B has the address from above)&lt;br /&gt;
013FH  STA FCC6H            ; Store the Type byte in the ALTLCD &lt;br /&gt;
0142H  CALL 0185H           ; Find empty entry in Catalog&lt;br /&gt;
0145H  RC                   ; Return if catalog full&lt;br /&gt;
0146H  PUSH H               ; Save the address of the empty catalog entry to the stack&lt;br /&gt;
0147H  LHLD FCC4H           ; Restore the BASIC program length from ALTLCD&lt;br /&gt;
014AH  MOV B,H              ; Move BASIC program length to BC for copy&lt;br /&gt;
014BH  MOV C,L              ; Move LSB of length&lt;br /&gt;
014CH  PUSH B               ; Save Length to the stack&lt;br /&gt;
014DH  LHLD FCC2H           ; Get address of insertion for TS-DOS just before the unsaved BASIC prog.&lt;br /&gt;
0150H  CALL 01DDH           ; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
0153H  JC 0182H             ; Abort if RAM full&lt;br /&gt;
0156H  LHLD FCC2H           ; Get address of insertion point again&lt;br /&gt;
0159H  XCHG                 ; DE now has insertion point for BASIC program&lt;br /&gt;
015AH  LHLD FCC8H           ; Get the address of the BASIC program (in our ROM) from ALTLCD&lt;br /&gt;
015DH  POP B                ; Restore copy length of the BASIC program&lt;br /&gt;
015EH  CALL 010CH           ; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
0161H  POP D                ; Get the address of the empty catalog entry we will use for TS-DOS&lt;br /&gt;
0162H  PUSH D               ; Save it back to the stack&lt;br /&gt;
0163H  LHLD FBAEH           ; Load the start of DO files pointer&lt;br /&gt;
0166H  DCX H                ; Derement the start of DO files pointer&lt;br /&gt;
0167H  SHLD F99AH           ; Save it as the new BASIC program not saved pointer&lt;br /&gt;
016AH  INX H                ; Point to start of DO files again&lt;br /&gt;
016BH  XCHG                 ; Move it to DE&lt;br /&gt;
016CH  LHLD FCC4H           ; Load the TS-DOS BASIC progam length from ALTLCD&lt;br /&gt;
016FH  DAD D                ; Offset the start of DO files by the insertion amount&lt;br /&gt;
0170H  SHLD FBAEH           ; Save the new start of DO files pointer&lt;br /&gt;
0173H  POP D                ; Restore the address of the empty catalog entry&lt;br /&gt;
0174H  LHLD FCC2H           ; Get the starting address of the newly inserted TS-DOS program&lt;br /&gt;
0177H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  Swap for the call to the catalog insertion routine &lt;br /&gt;
0178H  LDA FCC6H            ; Load A with the file type byte&lt;br /&gt;
017BH  CALL 01D5H           ; Save current BASIC program to the Catalog entry at HL&lt;br /&gt;
017EH  CALL 01D1H           ; Update system pointers&lt;br /&gt;
0181H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert &amp;quot;TS-DOS&amp;quot; RAM full abort routine ... stack cleanup.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0182H  POP H                ; Pop the BASIC program length from the stack&lt;br /&gt;
0183H  POP H                ; Pop the catalog entry address from the stack&lt;br /&gt;
0184H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Find an empty entry in the Catalog.  HL points to start of new entry&lt;br /&gt;
;     This routine appears again at address 3E48H&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0185H  LXI H,F9AFH          ; Point to &amp;quot;RickY&amp;quot; to start search at beginning of catalog&lt;br /&gt;
0188H  LXI B,000BH          ; Get length of each entry in the Catalog&lt;br /&gt;
018BH  DAD B                ; Point to next entry in the catalog&lt;br /&gt;
018CH  MOV A,M              ; Get the File Attribute byte from the catalog for this file&lt;br /&gt;
018DH  CPI FFH              ; Test if at end of the catalog&lt;br /&gt;
018FH  JZ 0197H             ; Jump to set Carry flag and exit if at end&lt;br /&gt;
0192H  ADD A                ; Test if MSB set (test if entry available)&lt;br /&gt;
0193H  JC 018BH             ; Branch to get next entry if this one is used&lt;br /&gt;
0196H  RET                  ; Return with Carry clear to indicate entry found&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Empty catalog entry not found in Catalog, set Carry and return&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0197H  STC                  ; Set the Carry flag - not found&lt;br /&gt;
0198H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Display function key line routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0199H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019AH  DW    42A8H&lt;br /&gt;
019CH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Erase function key display routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
019DH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019EH  DW    428AH&lt;br /&gt;
01A0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Set new function key table routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A2H  DW    5A7CH&lt;br /&gt;
01A4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Wait for key from keyboard routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A6H  DW    12CBH&lt;br /&gt;
01A8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Scan keyboard for character (CTRL-BREAK ==&amp;gt; CTRL-C) routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AAH  DW    7242H&lt;br /&gt;
01ACH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Power Down routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01ADH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AEH  DW    13B5H&lt;br /&gt;
01B0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Renew automatic power-off counter routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B2H  DW    1BB1H&lt;br /&gt;
01B4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s CLS statement routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B6H  DW    4231H&lt;br /&gt;
01B8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Start inverse character mode routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BAH  DW    4269H&lt;br /&gt;
01BCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Cancel inverse video routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01BDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BEH  DW    426EH&lt;br /&gt;
01C0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Check keyboard queue for pending characters routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C2H  DW    13DBH&lt;br /&gt;
01C4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Stop automatic scrolling routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C6H  DW    423FH&lt;br /&gt;
01C8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Reset vector routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CAH  DW    0000H&lt;br /&gt;
01CCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Search Catalog for entry matching current BASIC program&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01CDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CEH  DW    20AFH&lt;br /&gt;
01D0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Update system pointers routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D2H  DW    2146H&lt;br /&gt;
01D4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s routine to save current BASIC program to the Catalog entry at HL&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D6H  DW    2239H&lt;br /&gt;
01D8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Not a valid entry into ROM and not called anywhere&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DAH  DW    5825H&lt;br /&gt;
01DCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01DDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DEH  DB    6B6DH&lt;br /&gt;
01E0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; TS-DOS entry that will be inserted into the catalog for invoking TS-DOS&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01E1H  DB   80H             ; TS-DOS file type for catalog entry&lt;br /&gt;
01E2H  DB   &amp;quot;TS-DOS  &amp;quot;      ; TS-DOS Catalog name entry&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; BASIC program that will be inserted into RAM to launch TS-DOS from the MENU/Catalog entry&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01EAH  DB   0FH,00H,0EH,80H ; BASIC program length and pointer to &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
01EDH  DB   0AH,00H,B9H     ; BASIC Line number &amp;quot;10&amp;quot; and BASIC token for CALL&lt;br /&gt;
01EFH  DB   &amp;quot;63013,1&amp;quot;       ; CALL argument &lt;br /&gt;
01F5H  DB   00H,00H         ; BASIC terminating zeros&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
End of disassembly for OptROM Support.&lt;br /&gt;
&lt;br /&gt;
Navigate to:&lt;br /&gt;
* [[Dissasembly of RAM and ROM versions of TS-DOS]]&lt;br /&gt;
* [[M100 TS-DOS ROM UI Code]]&lt;br /&gt;
* [[M100 TS-DOS ROM RST 7 Handlers]]&lt;br /&gt;
* [[M100 TS-DOS ROM TPDD Protocol]]&lt;br /&gt;
* [[M100 TS-DOS ROM Compression]]&lt;br /&gt;
* [[M100 TS-DOS ROM Cold Boot Recovery]]&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1390</id>
		<title>M100 TS-DOS ROM OptROM Support</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=M100_TS-DOS_ROM_OptROM_Support&amp;diff=1390"/>
		<updated>2009-04-03T16:21:11Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== TS-DOS Model 100/102 ROM OptROM Support ==&lt;br /&gt;
&lt;br /&gt;
This code defines the variables used throughout the TS-DOS application as well as the support routines needed to navigate between the Main ROM and the Option ROM (most of them).  Also included is the TS-DOS startup code.  The assembly labels defined are open for discussion and have not been applied to any of the disassembled code yet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 =========================================================================================&lt;br /&gt;
; TS-DOS M100 ROM version Disassembly&lt;br /&gt;
;&lt;br /&gt;
; Initial Disassembly By Kenneth D. Pettit&lt;br /&gt;
; March, 2009&lt;br /&gt;
;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Variables in ALTLCD buffer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
NB_CUR_DIR    equ FCC0H              ; NADSBox current directory (&amp;quot;MYFILE.&amp;lt;&amp;gt; &amp;quot;)&lt;br /&gt;
TPDD_BANK     equ FCCAH              ; TPDD2 Bank (side)&lt;br /&gt;
NB_TPDD_FLG   equ FCCBH              ; NADSBox/Desklink/TPDD2 flag (0=TPDD, 1=TPDD2, 2=NADSBox)&lt;br /&gt;
LAST_TAG      equ FCCCH              ; Tag/Untag last operation code&lt;br /&gt;
CUR_FILE      equ FCCDH              ; Currently selected file index on UI (1 based)&lt;br /&gt;
LJ_SP         equ FCCEH              ; Stack pointer upon entry for Long Jump&lt;br /&gt;
LJ_RET        equ FCD0H              ; Return vector for Long Jump &amp;quot;RETURN&amp;quot;&lt;br /&gt;
ERR_MODE      equ FCD2H              ; Print Error Messages flag, 1=Print, 0=Generate System Error&lt;br /&gt;
FDC_OPCODE    equ FCD3H              ; FDC Emulation mode opcode&lt;br /&gt;
CUR_PAGE      equ FCD4H              ; Current page of files being displayed (0 based)&lt;br /&gt;
TMP_FILE_IDX  equ FCD5H              ; Currently selected file index on UI - temp&lt;br /&gt;
FILE_COUNT    equ FCD6H              ; Count of files currently displayed on LCD&lt;br /&gt;
MAX_FILES     equ FCD7H              ; Maximum files that fit on the LCD&lt;br /&gt;
DISP_MODE     equ FCD9H              ; RAM / Disk Display mode (0=RAM,  1=DISK)&lt;br /&gt;
SKIP_PAGE     equ FCDAH              ; TPDD &amp;quot;skip page&amp;quot; count (number of pages to read and discard)&lt;br /&gt;
FILE_LEN      equ FCDBH              ; Pointer to &amp;quot;Current file&amp;quot; length bytes (in keyboard buffer)&lt;br /&gt;
PHYS_SCTR     equ FCDDH              ; FDC Emulation Physical Sector Number / Active File Length LSB&lt;br /&gt;
LOG_SCTR      equ FCDEH              ; FDC Emulation Logical Sector Number / Active File Length MSB&lt;br /&gt;
KEY_TYPE      equ FCDFH              ; Storage for FDC emulation / New file type code / Keypress storage&lt;br /&gt;
FILE_ADDR     equ FCE0H              ; Address of file being displayed/printed/loaded/saved&lt;br /&gt;
FILE_BUFF     equ FCE2H              ; Pointer for TPDD direct read data / address of file being read/written&lt;br /&gt;
TX_PKT_BUF    equ FCE6H              ; Storage for TX packets (28 bytes)&lt;br /&gt;
RX_PKT_BUF    equ FD02H              ; Storage for RX packets (130 bytes ??)&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Main Entry point when called from &amp;quot;CALL 63013,1&amp;quot;&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
   &lt;br /&gt;
   .org 0000H&lt;br /&gt;
&lt;br /&gt;
0000H  JMP 00B2H            ; Jump to entry point handler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Pop registers after we power back up from a powerdown (I think)&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0003H  POP H&lt;br /&gt;
0004H  POP D&lt;br /&gt;
0005H  POP B&lt;br /&gt;
0006H  POP PSW&lt;br /&gt;
0007H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 1 - Call Main ROM at location whose address follows RST 1 opcode&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0008H  JMP 0080H            ; BASIC statement keyword table END to NEW&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 2 - Call Main ROM&#039;s RST 2 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0010H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0011H  DW    0010H          ; Call the Main ROM&#039;s RST 2 function&lt;br /&gt;
0013H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Compare HL and DE&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0018H  JMP 006CH            ; Jump to comparison routine&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return to Main ROM.  After issuing the OUT E0H, we will be in Main ROM.  The next opcode&lt;br /&gt;
; in Main ROM after this OUT statement occurs will be a RET (part of RST 1).  We have &lt;br /&gt;
; PUSHed a return address to the stack, so the main ROM&#039;s RET instruction will get us &lt;br /&gt;
; where to intend to go.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001BH  OUT E0H              ; Send A to the ROM bank port to switch to Main ROM&lt;br /&gt;
001DH  RET                  ; Should never execute this instruction, but just in case&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Send a space to the screen/printer - Not called from anywhere.  Copy of Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
001EH  (3EH) MVI A,20H      ; Prepare to print a SPACE&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST 3 routine - Send character in A to the screen / printer&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0020H  (CFH) RST 1          ; Call main ROM at address in following 2 bytes&lt;br /&gt;
0021H  DW    0020H          ; Main ROM&#039;s RST 3 routine&lt;br /&gt;
0023H  (C9H) RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Power down TRAP.  Let Main ROM deal with it.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0024H  DI                   ; Disable interrupts while we jump   &lt;br /&gt;
0025H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector &lt;br /&gt;
0028H  POP H      &lt;br /&gt;
0029H  JMP 0003H            ; Pop regs after we power back up from a power-down? &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Bar Code Reader&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
002CH  DI                   ; Disable interrupts while we jump  &lt;br /&gt;
002DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Return from Main ROM hook in RAM returns here via RST 6&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0030H  POP PSW              ; Cleanup stack&lt;br /&gt;
0031H  POP PSW              ; Cleanup stack&lt;br /&gt;
0032H  RET                  ; Return to OptROM execution point        &lt;br /&gt;
&lt;br /&gt;
0033H  NOP                  ; Filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - RS232 character pending&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0034H  DI                   ; Disable interrupts while we jump&lt;br /&gt;
0035H  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
0038H  JMP 00A6H            ; Stack cleanup&lt;br /&gt;
&lt;br /&gt;
003BH  NOP                  ; UNUSED - filler&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Hardware Interrupt - Let Main ROM deal with it - Timer background task&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
003CH  DI                   ; Disable interrupts&lt;br /&gt;
003DH  CALL 0097H           ; Jump to Main ROM&#039;s RST handler for this vector&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM to be used for switching back to the TS-DOS ROM after&lt;br /&gt;
;      calling a routine in the Main ROM.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0040H  PUSH PSW             ; Preserve the PSW&lt;br /&gt;
0041H  LDA FF45H            ; Contents of port E8H&lt;br /&gt;
0044H  INR A                ; Prepare to switch to OptRom&lt;br /&gt;
0045H  OUT E0H              ; Switch to OptRom&lt;br /&gt;
0047H  RST 6                ; Get sign of FAC1&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; This routine gets copied to RAM and appears to detect the presence of the TS-DOS ROM&lt;br /&gt;
;       after power-up and copies the original &amp;quot;External ROM&amp;quot; detection routine to RAM&lt;br /&gt;
;       if the TS-DOS ROM is no longer present.  At least I think that&#039;s what it&#039;s doing.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0048H  LXI D,F605H          ; Copy address for &amp;quot;Ext ROM detect&amp;quot; routine&lt;br /&gt;
004BH  INR A                ; Set bit to enable OptROM&lt;br /&gt;
004CH  OUT E0H              ; Switch to OptROM&lt;br /&gt;
004EH  XRA A                ; Prepare to switch back to Main ROM&lt;br /&gt;
004FH  LHLD 0049H           ; Load target address of the LXI D instruction above&lt;br /&gt;
0052H  OUT E0H              ; Switch back to Main ROM&lt;br /&gt;
0054H  RST 3                ; Compare DE and HL - Test if OptROM is TS-DOS&lt;br /&gt;
0055H  CPI 01H              ; Test for TS-DOS ROM&lt;br /&gt;
0057H  RC                   ; Return if TS-DOS ROM&lt;br /&gt;
0058H  LXI H,111DH          ; Load &amp;quot;Return&amp;quot; address to the CALL below&lt;br /&gt;
005BH  SHLD FAE0H&lt;br /&gt;
005EH  SHLD F5F2H           ; Save a &amp;quot;Restart signature&amp;quot; ???&lt;br /&gt;
0061H  CALL 2905H           ; Copy the DB number of bytes from the DW address to (DE)&lt;br /&gt;
0064H  DB   24H             ; ....copy 24H bytes&lt;br /&gt;
0065H  DW   036FH           ; ....from ROM addres 036F (external ROM detect)&lt;br /&gt;
0067H  RST 0                ; I&#039;m not sure it it every actually returns here or not&lt;br /&gt;
0068H  NOP&lt;br /&gt;
0069H  CALL FAA4H           ; Call our installed RAM hook to return to TS-DOS&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Compare HL and DE - called by the RST 3 routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
006CH  MOV A,H              ; Move H into A for comparison&lt;br /&gt;
006DH  SUB D                ; Compare MSB first&lt;br /&gt;
006EH  RNZ                  ; Return if no match&lt;br /&gt;
006FH  MOV A,L              ; Now move L into A&lt;br /&gt;
0070H  SUB E                ; Compare LSB&lt;br /&gt;
0071H  RET                  ; Return with flags set&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy 8 bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0072H  LXI B,0008H          ; Prepare to copy 8 bytes &lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Copy BC bytes from DE to HL &lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0075H  LDAX D               ; Load value from (DE)&lt;br /&gt;
0076H  MOV M,A              ; Save value to (HL)&lt;br /&gt;
0077H  INX D                ; Increment DE&lt;br /&gt;
0078H  INX H                ; Increment HL&lt;br /&gt;
0079H  DCX B                ; Decrement counter&lt;br /&gt;
007AH  MOV A,B              ; Prepare to test counter for zero&lt;br /&gt;
007BH  ORA C                ; Test counter for zero&lt;br /&gt;
007CH  JNZ 0075H            ; Keep looping until 8 bytes copied&lt;br /&gt;
007FH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Handle the RST 1 routine.  Read the Main ROM address from the 2 bytes after the RST 1&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0080H  SHLD F9B2H           ; Save HL off in &amp;quot;RickY&amp;quot; Cat entry so we don&#039;t clobber it&lt;br /&gt;
0083H  POP H                ; Get out return address (location of the ROM address to call&lt;br /&gt;
0084H  PUSH D               ; Push the return address back to the stack as storage &lt;br /&gt;
0085H  MOV E,M              ; Get LSB of the ROM address to call&lt;br /&gt;
0086H  INX H                ; Point to MSB of ROM address to call&lt;br /&gt;
0087H  MOV D,M              ; Get MSB of the ROM address to call&lt;br /&gt;
0088H  INX H                ; Point to return address after the RST 1 DB address&lt;br /&gt;
0089H  XTHL                 ; Put the return address on the stack so we return after the RST 1&lt;br /&gt;
008AH  XCHG                 ; Now get the address within ROM to call&lt;br /&gt;
008BH  PUSH H               ; Push the target ROM address to the stack so we &amp;quot;RETurn&amp;quot; there&lt;br /&gt;
008CH  LXI H,FAA4H          ; Load address of our RAM hook to switch back to our ROM bank and RET&lt;br /&gt;
008FH  XTHL                 ; Push that address on the stack for after the ROM call is complete&lt;br /&gt;
0090H  PUSH H               ; Now put the ROM address back on the stack so we will RET there&lt;br /&gt;
0091H  LHLD F9B2H           ; Restore HL from temp storage in &amp;quot;RickY&amp;quot;&lt;br /&gt;
0094H  JMP 00A6H            ; Branch to switch to Main ROM and &amp;quot;RET&amp;quot; to the address we pushed&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; RST handler for calling the Main ROM&#039;s RST handlers.  This routine restores the original&lt;br /&gt;
;      RST vector address to the stack, and jumps to the Main ROM&#039;s RST routine while &lt;br /&gt;
;      preserving all register values.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0097H  SHLD F9B4H           ; Save HL temporarily (somewhere in RickY&#039;s name)&lt;br /&gt;
009AH  LXI H,FAA4H          ; Point to our RAM hook for returning to TS-DOS&lt;br /&gt;
009DH  XTHL                 ; Put the hook address as the return address on the stack&lt;br /&gt;
009EH  DCX H                ; Decrement the return address by 4&lt;br /&gt;
009FH  DCX H                ; ...this will result in the starting address of the RST&lt;br /&gt;
00A0H  DCX H                ; ...that brought us here&lt;br /&gt;
00A1H  DCX H&lt;br /&gt;
00A2H  PUSH H               ; Push the RST vector address to the stack&lt;br /&gt;
00A3H  LHLD F9B4H           ; Restore HL upon entry&lt;br /&gt;
00A6H  PUSH PSW             ; Save A to the stack&lt;br /&gt;
00A7H  PUSH H               ; Save the HL to the stack so we can preserve through XTHL&lt;br /&gt;
00A8H  LXI H,1488H          ; Load a RETurn address in the Main ROM (a POP PSW &amp;amp; RET) &lt;br /&gt;
00ABH  XTHL                 ; Push the address and get HL back&lt;br /&gt;
00ACH  LDA FF45H            ; Contents of port E8H - prepare for jump to Main ROM&lt;br /&gt;
00AFH  JMP 001BH            ; Jump to Main ROM &amp;amp; our custom &amp;quot;RET&amp;quot; address in the ROM&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Manual invocation entry point.  This is where we jump when &amp;quot;CALL 63013,1&amp;quot; is invoked&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
00B2H  DI                   ; Disable interrupts so nobody bugs us yet&lt;br /&gt;
00B3H  CPI 08H              ; Check the invocation parameter to test for recovery request&lt;br /&gt;
00B5H  JNC 0100H            ; Jump to test for recovery mode&lt;br /&gt;
00B8H  MOV B,A              ; Save the calling paramter to B&lt;br /&gt;
00B9H  PUSH B               ; Save BC to the stack&lt;br /&gt;
00BAH  PUSH D               ; Save DE to the stack&lt;br /&gt;
00BBH  PUSH H               ; Save HL to the stack&lt;br /&gt;
00BCH  LXI D,0040H          ; Load address of our &amp;quot;Change to OptROM&amp;quot; routine&lt;br /&gt;
00BFH  LXI H,FAA4H          ; Load pointer to somewhere in RAM to hold our routine&lt;br /&gt;
00C2H  CALL 0072H           ; Copy 8 bytes from DE to HL &lt;br /&gt;
00C5H  LXI B,0024H          ; Now prepare to copy 36 bytes worth of &amp;quot;routine&amp;quot;&lt;br /&gt;
00C8H  LXI H,F605H          ; Point to another RAM location&lt;br /&gt;
00CBH  CALL 0075H           ; Copy the next &amp;quot;ROM Bank Switching&amp;quot; routine from our ROM&lt;br /&gt;
00CEH  POP H                ; Restore HL&lt;br /&gt;
00CFH  POP D                ; Restore DE&lt;br /&gt;
00D0H  POP PSW              ; Restore A&lt;br /&gt;
00D1H  EI                   ; Allow interrupts again&lt;br /&gt;
00D2H  JMP 0100H            ; Go test if a &amp;quot;Cold Start&amp;quot; recovery is being requested&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    .org 100H&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Test if cold-start recovery requested&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0100H  MOV A,H              ; Move H to A to test HL for zero&lt;br /&gt;
0101H  ORA L                ; Test for zero&lt;br /&gt;
0102H  JZ 7000H             ; Call recovery routine if requested&lt;br /&gt;
0105H  POP H                ; Pop the return address.  We will exit manually&lt;br /&gt;
0106H  CALL 0117H           ; Ensure the TS-DOS progam is installed in the MENU&lt;br /&gt;
0109H  JMP 3535H            ; Jump to the TS-DOS UI&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
010CH  MOV A,M              ; Get next byte from (HL)&lt;br /&gt;
010DH  STAX D               ; Save byte in (DE)&lt;br /&gt;
010EH  INX H                ; Increment source pointer&lt;br /&gt;
010FH  INX D                ; Increment destination pointer&lt;br /&gt;
0110H  DCX B                ; Decrement loop control&lt;br /&gt;
0111H  MOV A,B              ; Move MSB to A to test for zero&lt;br /&gt;
0112H  ORA C                ; OR in LSB to test for zero&lt;br /&gt;
0113H  JNZ 010CH            ; Branch to copy next byte until done&lt;br /&gt;
0116H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert the &amp;quot;TS-DOS&amp;quot; invocation program (BASIC program) into the Catalog / MENU.&lt;br /&gt;
;    we always insert ourselves at the lowest RAM address.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0117H  LXI H,01E1H          ; Point to &amp;quot;TS-DOS&amp;quot; catalog entry in our ROM&lt;br /&gt;
011AH  PUSH H               ; Save the address on the stack for later&lt;br /&gt;
011BH  INX H                ; Point to the text portion of the catalog entry&lt;br /&gt;
011CH  LXI B,0008H          ; Prepare to copy 8 filename byte&lt;br /&gt;
011FH  LXI D,FC93H          ; Filename of current BASIC program&lt;br /&gt;
0122H  CALL 010CH           ; Copy BC bytes from HL to DE - put &amp;quot;TS-DOS  &amp;quot; in cur. BASIC prog.&lt;br /&gt;
0125H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  DE now has the address of the invocation program&lt;br /&gt;
0126H  LHLX                 ; Get the length of the BASIC program into HL&lt;br /&gt;
0127H  SHLD FCC4H           ; Save the BASIC program length in the ALTLCD buffer for now&lt;br /&gt;
012AH  INX D                ; Point to MSB of the length&lt;br /&gt;
012BH  INX D                ; Point to LSB of the pointer to the &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
012CH  XCHG                 ; HL &amp;lt;--&amp;gt; DE HL has the pointer to the &amp;quot;Next&amp;quot; BASIC inst address&lt;br /&gt;
012DH  SHLD FCC8H           ; Save the &amp;quot;Next&amp;quot; BASIC inst pointer to ALTLCD (start of program)&lt;br /&gt;
0130H  CALL 01D1H           ; Update the System pointers&lt;br /&gt;
0133H  CALL 01CDH           ; Search Catalog for entry matching current BASIC program&lt;br /&gt;
0136H  POP B                ; Pop address in case we return&lt;br /&gt;
0137H  RNZ                  ; Return if &amp;quot;TS-DOS&amp;quot; is already in the catalog&lt;br /&gt;
0138H  LHLD F99AH           ; Get the BASIC program not saved pointer - insert before that&lt;br /&gt;
013BH  SHLD FCC2H           ; Save storage location for the TS-DOS invocation progam&lt;br /&gt;
013EH  LDAX B               ; Load the file type byte from our ROM (B has the address from above)&lt;br /&gt;
013FH  STA FCC6H            ; Store the Type byte in the ALTLCD &lt;br /&gt;
0142H  CALL 0185H           ; Find empty entry in Catalog&lt;br /&gt;
0145H  RC                   ; Return if catalog full&lt;br /&gt;
0146H  PUSH H               ; Save the address of the empty catalog entry to the stack&lt;br /&gt;
0147H  LHLD FCC4H           ; Restore the BASIC program length from ALTLCD&lt;br /&gt;
014AH  MOV B,H              ; Move BASIC program length to BC for copy&lt;br /&gt;
014BH  MOV C,L              ; Move LSB of length&lt;br /&gt;
014CH  PUSH B               ; Save Length to the stack&lt;br /&gt;
014DH  LHLD FCC2H           ; Get address of insertion for TS-DOS just before the unsaved BASIC prog.&lt;br /&gt;
0150H  CALL 01DDH           ; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
0153H  JC 0182H             ; Abort if RAM full&lt;br /&gt;
0156H  LHLD FCC2H           ; Get address of insertion point again&lt;br /&gt;
0159H  XCHG                 ; DE now has insertion point for BASIC program&lt;br /&gt;
015AH  LHLD FCC8H           ; Get the address of the BASIC program (in our ROM) from ALTLCD&lt;br /&gt;
015DH  POP B                ; Restore copy length of the BASIC program&lt;br /&gt;
015EH  CALL 010CH           ; Move BC bytes from (HL) to (DE) with increment&lt;br /&gt;
0161H  POP D                ; Get the address of the empty catalog entry we will use for TS-DOS&lt;br /&gt;
0162H  PUSH D               ; Save it back to the stack&lt;br /&gt;
0163H  LHLD FBAEH           ; Load the start of DO files pointer&lt;br /&gt;
0166H  DCX H                ; Derement the start of DO files pointer&lt;br /&gt;
0167H  SHLD F99AH           ; Save it as the new BASIC program not saved pointer&lt;br /&gt;
016AH  INX H                ; Point to start of DO files again&lt;br /&gt;
016BH  XCHG                 ; Move it to DE&lt;br /&gt;
016CH  LHLD FCC4H           ; Load the TS-DOS BASIC progam length from ALTLCD&lt;br /&gt;
016FH  DAD D                ; Offset the start of DO files by the insertion amount&lt;br /&gt;
0170H  SHLD FBAEH           ; Save the new start of DO files pointer&lt;br /&gt;
0173H  POP D                ; Restore the address of the empty catalog entry&lt;br /&gt;
0174H  LHLD FCC2H           ; Get the starting address of the newly inserted TS-DOS program&lt;br /&gt;
0177H  XCHG                 ; HL &amp;lt;--&amp;gt; DE  Swap for the call to the catalog insertion routine &lt;br /&gt;
0178H  LDA FCC6H            ; Load A with the file type byte&lt;br /&gt;
017BH  CALL 01D5H           ; Save current BASIC program to the Catalog entry at HL&lt;br /&gt;
017EH  CALL 01D1H           ; Update system pointers&lt;br /&gt;
0181H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Insert &amp;quot;TS-DOS&amp;quot; RAM full abort routine ... stack cleanup.&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0182H  POP H                ; Pop the BASIC program length from the stack&lt;br /&gt;
0183H  POP H                ; Pop the catalog entry address from the stack&lt;br /&gt;
0184H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Find an empty entry in the Catalog.  HL points to start of new entry&lt;br /&gt;
;     This routine appears again at address 3E48H&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0185H  LXI H,F9AFH          ; Point to &amp;quot;RickY&amp;quot; to start search at beginning of catalog&lt;br /&gt;
0188H  LXI B,000BH          ; Get length of each entry in the Catalog&lt;br /&gt;
018BH  DAD B                ; Point to next entry in the catalog&lt;br /&gt;
018CH  MOV A,M              ; Get the File Attribute byte from the catalog for this file&lt;br /&gt;
018DH  CPI FFH              ; Test if at end of the catalog&lt;br /&gt;
018FH  JZ 0197H             ; Jump to set Carry flag and exit if at end&lt;br /&gt;
0192H  ADD A                ; Test if MSB set (test if entry available)&lt;br /&gt;
0193H  JC 018BH             ; Branch to get next entry if this one is used&lt;br /&gt;
0196H  RET                  ; Return with Carry clear to indicate entry found&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Empty catalog entry not found in Catalog, set Carry and return&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0197H  STC                  ; Set the Carry flag - not found&lt;br /&gt;
0198H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Display function key line routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
0199H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019AH  DW    42A8H&lt;br /&gt;
019CH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Erase function key display routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
019DH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
019EH  DW    428AH&lt;br /&gt;
01A0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Set new function key table routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A2H  DW    5A7CH&lt;br /&gt;
01A4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Wait for key from keyboard routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01A6H  DW    12CBH&lt;br /&gt;
01A8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Scan keyboard for character (CTRL-BREAK ==&amp;gt; CTRL-C) routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01A9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AAH  DW    7242H&lt;br /&gt;
01ACH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Power Down routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01ADH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01AEH  DW    13B5H&lt;br /&gt;
01B0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Renew automatic power-off counter routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B2H  DW    1BB1H&lt;br /&gt;
01B4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s CLS statement routine&lt;br /&gt;
;      This apears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01B6H  DW    4231H&lt;br /&gt;
01B8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Start inverse character mode routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01B9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BAH  DW    4269H&lt;br /&gt;
01BCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Cancel inverse video routine&lt;br /&gt;
;      This appears later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01BDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01BEH  DW    426EH&lt;br /&gt;
01C0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Check keyboard queue for pending characters routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C2H  DW    13DBH&lt;br /&gt;
01C4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Stop automatic scrolling routine&lt;br /&gt;
;      This appers later in the code also&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01C6H  DW    423FH&lt;br /&gt;
01C8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Reset vector routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01C9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CAH  DW    0000H&lt;br /&gt;
01CCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Search Catalog for entry matching current BASIC program&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01CDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01CEH  DW    20AFH&lt;br /&gt;
01D0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Update system pointers routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D1H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D2H  DW    2146H&lt;br /&gt;
01D4H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s routine to save current BASIC program to the Catalog entry at HL&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D5H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01D6H  DW    2239H&lt;br /&gt;
01D8H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Not a valid entry into ROM and not called anywhere&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01D9H  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DAH  DW    5825H&lt;br /&gt;
01DCH  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; Call Main ROM&#039;s Insert BC spaces at M routine&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01DDH  RST 1                ; Call main ROM at address in following 2 bytes&lt;br /&gt;
01DEH  DB    6B6DH&lt;br /&gt;
01E0H  RET&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; TS-DOS entry that will be inserted into the catalog for invoking TS-DOS&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01E1H  DB   80H             ; TS-DOS file type for catalog entry&lt;br /&gt;
01E2H  DB   &amp;quot;TS-DOS  &amp;quot;      ; TS-DOS Catalog name entry&lt;br /&gt;
&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
; BASIC program that will be inserted into RAM to launch TS-DOS from the MENU/Catalog entry&lt;br /&gt;
; =========================================================================================&lt;br /&gt;
01EAH  DB   0FH,00H,0EH,80H ; BASIC program length and pointer to &amp;quot;Next&amp;quot; BASIC instruction&lt;br /&gt;
01EDH  DB   0AH,00H,B9H     ; BASIC Line number &amp;quot;10&amp;quot; and BASIC token for CALL&lt;br /&gt;
01EFH  DB   &amp;quot;63013,1&amp;quot;       ; CALL argument &lt;br /&gt;
01F5H  DB   00H,00H         ; BASIC terminating zeros&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
End of disassembly for OptROM Support.&lt;br /&gt;
&lt;br /&gt;
Navigate to:&lt;br /&gt;
* [[Dissasembly of RAM and ROM versions of TS-DOS]]&lt;br /&gt;
* [[M100 TS-DOS ROM UI Code]]&lt;br /&gt;
* [[M100 TS-DOS ROM RST 7 Handlers]]&lt;br /&gt;
* [[M100 TS-DOS ROM TPDD Protocol]]&lt;br /&gt;
* [[M100 TS-DOS ROM Compression]]&lt;br /&gt;
* [[M100 TS-DOS ROM Cold Boot Recovery]]&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=761</id>
		<title>Desklink/TS-DOS Directory Access</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=761"/>
		<updated>2008-12-31T01:13:18Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: /* TPDD Service discovery */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;p&amp;gt;TS-DOS Directory Management Extensions Programmer&#039;s Guide&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;By Kenneth D. Pettit&amp;lt;/p&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
TS-DOS was developed as an alternative for accessing the TPDD and TPDD-2 drives from the Tandy and NEC line of laptops (Model 100, 102, 200 and PC-8201a). As part of the design, when used with the companion &amp;quot;DeskLink&amp;quot; PC program, TS-DOS adds the ability to create and manage a directory structure on the target media. This same directory access extension is also built into the NADSBox SD card reader and allows navigation and access of the FAT directory structure on the media card. The extensions were discovered by reverse engineering the communication between a Model 102 and Desklink (running on an HP 200LX) and between TS-DOS and a TPDD-1 using an HP 4951B serial protocol analyzer. This document describes the TS-DOS directory management extensions (DME) and is, to my knowledge, a complete description of the protocol.&lt;br /&gt;
&lt;br /&gt;
== Protocol Structure ==&lt;br /&gt;
&lt;br /&gt;
=== History ===&lt;br /&gt;
&lt;br /&gt;
The TPDD-1 supported two modes of operation for accessing data on the floppy disc - an &amp;quot;Operational&amp;quot; mode and an &amp;quot;FDC Emulation&amp;quot; mode. Each of these modes have a very different command structure and are well documented in the TPDD-1 reference manual. The FDC Emulation mode was used for direct sector access of the data stored on the disc. Neither the TPDD-2 nor Desklink support the FDC Emulation mode and instead add sector access commands in Operational mode to provide the same functionality.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Basic premise for extension addition ===&lt;br /&gt;
&lt;br /&gt;
The directory management extensions in TS-DOS are implemented partially using commands to support the FDC Emulation mode, and partially using a targeted file extension (&amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;) in operational mode commands to denote references to a directory or subdirectory on the media. The FDC Emulation mode commands are used to identify if the client supports DME and the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension is used to specify target directories for creation, deletion or navigation.&lt;br /&gt;
&lt;br /&gt;
=== Request Format ===&lt;br /&gt;
&lt;br /&gt;
Both FDC Emulation requests and Operational mode requests are issued by TS-DOS, although only a single FDC Emulation mode request is used. FDC Emulation requests consist of a single ASCII character with one or more ASCII arguments followed by a carriage return (0Dh). Operational mode requests consist of a Preamble of ZZ (5Ah 5Ah), followed by a Request ID byte, a Payload Length byte, 0 or more payload bytes, terminated by a checksum.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;strong&amp;gt;Note:&amp;lt;/strong&amp;gt; All values are shown as hexadecimal. ASCII character strings are enclosed with quotation marks. The quotation marks are not part of the command or response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Response Format ===&lt;br /&gt;
&lt;br /&gt;
In operational mode, the reponse format is identical to the request format, except that no preamble is sent. In FDC Emulation mode, the reponse format varies depending on the command and the TPDD service. Specific details regarding FDC Emulation mode responses will be described as needed.&lt;br /&gt;
&lt;br /&gt;
== TPDD Service discovery ==&lt;br /&gt;
&lt;br /&gt;
Since TS-DOS must operate with with various TPDD servers, and since not all servers follow the same protocol, it must determine if the server is capable of supporting DME. This is done by sending an FDC Emulation mode command to go into operational mode (&amp;quot;M1&amp;quot;), followed by an operational mode command to go into FDC Emulation mode. For this operational mode sequence, TS-DOS actually terminates the command with a carriage return (0Dh) which isn&#039;t part of the standard operational mode protocol. The following two commands are sent:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Request (DMEReq) ===&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;10&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| &amp;quot;M1&amp;quot;&lt;br /&gt;
| 0D&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 08&lt;br /&gt;
| 00&lt;br /&gt;
| F7&lt;br /&gt;
|}&lt;br /&gt;
| 0D&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; For a TPDD service that supports FDC Emulation mode, the standard response for both commands is no response. If the server does not respond to either command, or responds with an error message, then TS-DOS knows the server does not support DME.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; If the server does support DME, then after the final carriage return (0Dh), it shall reply with a standard operational mode response. The response ID must be 12h and the payload field must be 11 bytes long and contain the name of the current directory, or at least the lowest level name in the tree, as shown below. The name should be 6 characters long and should be terminated with &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h. Names shorter than 6 characters should be padded with spaces before the &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h extension.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; TS-DOS will display the directory name reported in the DMEResp payload in the upper right corner of the display in reverse video characters. If the current directory is the root &amp;quot;/&amp;quot; directory, then the server should return &amp;quot;ROOT .&amp;amp;lt;&amp;amp;gt; &amp;quot; in the payload filed as a standard, although any name could be provided. TS-DOS will send the DMEReq sequence multiple times including when it has requested a directory change operation. This provides a way of reporting the new subdirectory name for display in the TS-DOS title bar.&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Response (DMEResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 12&lt;br /&gt;
| 0B&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Rsvd&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Extension&lt;br /&gt;
|-&lt;br /&gt;
| 00&lt;br /&gt;
| 6 bytes, space padded&lt;br /&gt;
| &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory reporting from Server ==&lt;br /&gt;
&lt;br /&gt;
The server device (DeskLink, NADSBox, etc.) should use the receipt of a DMEReq as an indication to provide directory and subdirectory information to TS-DOS (or any other client). If the DMEReq sequence is not received, then the server is communicating with a DOS that does not support DME, such as TEENY or FLOPPY, etc. Directory information is reported using the same protocol as regular files using the Directory Reference Request with the exception that the extension is reported as &amp;quot;&amp;amp;amp;lt&amp;amp;amp;gt &amp;quot;. Directory Reference Requests are part of the standard TPDD-1 and TPDD-2 protocol and can refer to a specific directory entry, or the first, next or previous entry in the directory. For filename discovery, the &amp;quot;first&amp;quot;, &amp;quot;next&amp;quot; or &amp;quot;previous&amp;quot; search forms are used, and the filename is all 00h.&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Request (DRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| File Name&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 24d bytes of 00&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 01, 02 or 03&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; When DME support has been established, the server reports directory information by responding to the DRReq sequence with a Directory Reference Response (DRResp) packet with the filename field containing the directory name in 6.2 filename format. The directory name should be 6 characters or less with space padding and the 2 character extension must be set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;. TS-DOS uses the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension to identify the entry as a directory. When the server is reporting file / directory entries for a directory other than the root, it should provide a mechanism for navigating to the parent directory. In both DeskLink and NADSBox, this is done by reporting the first entry of a subdirectory as &amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;. The number of Free Sectors on the media should be a single byte with the value 80H or less. Sectors in the TPDD protocol are 1280 bytes in length.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Response (DRResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
| 1C&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Size&lt;br /&gt;
| Free&lt;br /&gt;
|}&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;# Sectors&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Change Directory requests from TS-DOS ==&lt;br /&gt;
&lt;br /&gt;
When the user navigates the cursor to a directory entry that has the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension and pressed Enter, TS-DOS will perform a Directory Change operation to naviagte to that directory. This is accomplished by sending a Change Direcotry Reference Request (CDRReq) followed by a standard Open File Request and then a Close File Request. The CDRReq packet is the same as a standard DRReq packet except the filename extension is set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Change Directory Reference Request (CDRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; The server should respond to the CDRReq packet with a DRResp response packet containing the same directory name that was passed in the CDRReq. The server should save the directory name and expect to receive a subsequent Open File Request. When the Open File Request is received, the server should process it as a Change Directory operation to the directory specified in the CDRReq packet and return a standard Normal Response Packet (Id = 12H) with the appropriate error code. If the directory name matches the special name given for the parent directory (&amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;), then the server should change to the parent of the current directory. The the server should then expect a Close File Request and respond as usual.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Checksum Algorithm ===&lt;br /&gt;
&lt;br /&gt;
 Total = Sum of all bytes from TypeID..Last byte of Payload&amp;lt;br /&amp;gt; Checksum = (Total &amp;amp;amp; FFh) XOR FFh&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=760</id>
		<title>Desklink/TS-DOS Directory Access</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=760"/>
		<updated>2008-12-31T01:06:22Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: /* Change Directory requests from TS-DOS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;p&amp;gt;TS-DOS Directory Management Extensions Programmer&#039;s Guide&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;By Kenneth D. Pettit&amp;lt;/p&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
TS-DOS was developed as an alternative for accessing the TPDD and TPDD-2 drives from the Tandy and NEC line of laptops (Model 100, 102, 200 and PC-8201a). As part of the design, when used with the companion &amp;quot;DeskLink&amp;quot; PC program, TS-DOS adds the ability to create and manage a directory structure on the target media. This same directory access extension is also built into the NADSBox SD card reader and allows navigation and access of the FAT directory structure on the media card. The extensions were discovered by reverse engineering the communication between a Model 102 and Desklink (running on an HP 200LX) and between TS-DOS and a TPDD-1 using an HP 4951B serial protocol analyzer. This document describes the TS-DOS directory management extensions (DME) and is, to my knowledge, a complete description of the protocol.&lt;br /&gt;
&lt;br /&gt;
== Protocol Structure ==&lt;br /&gt;
&lt;br /&gt;
=== History ===&lt;br /&gt;
&lt;br /&gt;
The TPDD-1 supported two modes of operation for accessing data on the floppy disc - an &amp;quot;Operational&amp;quot; mode and an &amp;quot;FDC Emulation&amp;quot; mode. Each of these modes have a very different command structure and are well documented in the TPDD-1 reference manual. The FDC Emulation mode was used for direct sector access of the data stored on the disc. Neither the TPDD-2 nor Desklink support the FDC Emulation mode and instead add sector access commands in Operational mode to provide the same functionality.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Basic premise for extension addition ===&lt;br /&gt;
&lt;br /&gt;
The directory management extensions in TS-DOS are implemented partially using commands to support the FDC Emulation mode, and partially using a targeted file extension (&amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;) in operational mode commands to denote references to a directory or subdirectory on the media. The FDC Emulation mode commands are used to identify if the client supports DME and the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension is used to specify target directories for creation, deletion or navigation.&lt;br /&gt;
&lt;br /&gt;
=== Request Format ===&lt;br /&gt;
&lt;br /&gt;
Both FDC Emulation requests and Operational mode requests are issued by TS-DOS, although only a single FDC Emulation mode request is used. FDC Emulation requests consist of a single ASCII character with one or more ASCII arguments followed by a carriage return (0Dh). Operational mode requests consist of a Preamble of ZZ (5Ah 5Ah), followed by a Request ID byte, a Payload Length byte, 0 or more payload bytes, terminated by a checksum.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;strong&amp;gt;Note:&amp;lt;/strong&amp;gt; All values are shown as hexadecimal. ASCII character strings are enclosed with quotation marks. The quotation marks are not part of the command or response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Response Format ===&lt;br /&gt;
&lt;br /&gt;
In operational mode, the reponse format is identical to the request format, except that no preamble is sent. In FDC Emulation mode, the reponse format varies depending on the command and the TPDD service. Specific details regarding FDC Emulation mode responses will be described as needed.&lt;br /&gt;
&lt;br /&gt;
== TPDD Service discovery ==&lt;br /&gt;
&lt;br /&gt;
Since TS-DOS must operate with with various TPDD servers, and since not all servers follow the same protocol, it must determine if the server is capable of supporting DME. This is done by sending an FDC Emulation mode command to go into operational mode (&amp;quot;M1&amp;quot;), followed by an operational mode command to go into FDC Emulation mode. For this operational mode sequence, TS-DOS actually terminates the command with a carriage return (0Dh) which isn&#039;t part of the standard operational mode protocol. The following two commands are sent:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Request (DMEReq) ===&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;10&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| &amp;quot;M1&amp;quot;&lt;br /&gt;
| 0D&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 08&lt;br /&gt;
| 00&lt;br /&gt;
| F7&lt;br /&gt;
|}&lt;br /&gt;
| 0D&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; For a TPDD service that supports FDC Emulation mode, the standard response for both commands is no response. If the server does not respond to either command, or responds with an error message, then TS-DOS knows the client does not support DME.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; If the client does support DME, then after the final carriage return (0Dh), it shall reply with a standard operational mode response. The response ID must be 12h and the payload field must be 11 bytes long and contain the name of the current directory, or at least the lowest level name in the tree, as shown below. The name should be 6 characters long and should be terminated with &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h. Names shorter than 6 characters should be padded with spaces before the &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h extension.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; TS-DOS will display the directory name reported in the DMEResp payload in the upper right corner of the display in reverse video characters. If the current directory is the root &amp;quot;/&amp;quot; directory, then the client should return &amp;quot;ROOT .&amp;amp;lt;&amp;amp;gt; &amp;quot; in the payload filed as a standard, although any name could be provided. TS-DOS will send the DMEReq sequence multiple times including when it has requested a directory change operation. This provides a way of reporting the new subdirectory name for display in the TS-DOS title bar.&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Response (DMEResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 12&lt;br /&gt;
| 0B&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Rsvd&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Extension&lt;br /&gt;
|-&lt;br /&gt;
| 00&lt;br /&gt;
| 6 bytes, space padded&lt;br /&gt;
| &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory reporting from Server ==&lt;br /&gt;
&lt;br /&gt;
The server device (DeskLink, NADSBox, etc.) should use the receipt of a DMEReq as an indication to provide directory and subdirectory information to TS-DOS (or any other client). If the DMEReq sequence is not received, then the server is communicating with a DOS that does not support DME, such as TEENY or FLOPPY, etc. Directory information is reported using the same protocol as regular files using the Directory Reference Request with the exception that the extension is reported as &amp;quot;&amp;amp;amp;lt&amp;amp;amp;gt &amp;quot;. Directory Reference Requests are part of the standard TPDD-1 and TPDD-2 protocol and can refer to a specific directory entry, or the first, next or previous entry in the directory. For filename discovery, the &amp;quot;first&amp;quot;, &amp;quot;next&amp;quot; or &amp;quot;previous&amp;quot; search forms are used, and the filename is all 00h.&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Request (DRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| File Name&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 24d bytes of 00&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 01, 02 or 03&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; When DME support has been established, the server reports directory information by responding to the DRReq sequence with a Directory Reference Response (DRResp) packet with the filename field containing the directory name in 6.2 filename format. The directory name should be 6 characters or less with space padding and the 2 character extension must be set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;. TS-DOS uses the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension to identify the entry as a directory. When the server is reporting file / directory entries for a directory other than the root, it should provide a mechanism for navigating to the parent directory. In both DeskLink and NADSBox, this is done by reporting the first entry of a subdirectory as &amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;. The number of Free Sectors on the media should be a single byte with the value 80H or less. Sectors in the TPDD protocol are 1280 bytes in length.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Response (DRResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
| 1C&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Size&lt;br /&gt;
| Free&lt;br /&gt;
|}&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;# Sectors&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Change Directory requests from TS-DOS ==&lt;br /&gt;
&lt;br /&gt;
When the user navigates the cursor to a directory entry that has the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension and pressed Enter, TS-DOS will perform a Directory Change operation to naviagte to that directory. This is accomplished by sending a Change Direcotry Reference Request (CDRReq) followed by a standard Open File Request and then a Close File Request. The CDRReq packet is the same as a standard DRReq packet except the filename extension is set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Change Directory Reference Request (CDRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; The server should respond to the CDRReq packet with a DRResp response packet containing the same directory name that was passed in the CDRReq. The server should save the directory name and expect to receive a subsequent Open File Request. When the Open File Request is received, the server should process it as a Change Directory operation to the directory specified in the CDRReq packet and return a standard Normal Response Packet (Id = 12H) with the appropriate error code. If the directory name matches the special name given for the parent directory (&amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;), then the server should change to the parent of the current directory. The the server should then expect a Close File Request and respond as usual.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Checksum Algorithm ===&lt;br /&gt;
&lt;br /&gt;
 Total = Sum of all bytes from TypeID..Last byte of Payload&amp;lt;br /&amp;gt; Checksum = (Total &amp;amp;amp; FFh) XOR FFh&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=759</id>
		<title>Desklink/TS-DOS Directory Access</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Desklink/TS-DOS_Directory_Access&amp;diff=759"/>
		<updated>2008-12-31T01:03:23Z</updated>

		<summary type="html">&lt;p&gt;208.77.91.41: /* Directory reporting from Client */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;p&amp;gt;TS-DOS Directory Management Extensions Programmer&#039;s Guide&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;By Kenneth D. Pettit&amp;lt;/p&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
TS-DOS was developed as an alternative for accessing the TPDD and TPDD-2 drives from the Tandy and NEC line of laptops (Model 100, 102, 200 and PC-8201a). As part of the design, when used with the companion &amp;quot;DeskLink&amp;quot; PC program, TS-DOS adds the ability to create and manage a directory structure on the target media. This same directory access extension is also built into the NADSBox SD card reader and allows navigation and access of the FAT directory structure on the media card. The extensions were discovered by reverse engineering the communication between a Model 102 and Desklink (running on an HP 200LX) and between TS-DOS and a TPDD-1 using an HP 4951B serial protocol analyzer. This document describes the TS-DOS directory management extensions (DME) and is, to my knowledge, a complete description of the protocol.&lt;br /&gt;
&lt;br /&gt;
== Protocol Structure ==&lt;br /&gt;
&lt;br /&gt;
=== History ===&lt;br /&gt;
&lt;br /&gt;
The TPDD-1 supported two modes of operation for accessing data on the floppy disc - an &amp;quot;Operational&amp;quot; mode and an &amp;quot;FDC Emulation&amp;quot; mode. Each of these modes have a very different command structure and are well documented in the TPDD-1 reference manual. The FDC Emulation mode was used for direct sector access of the data stored on the disc. Neither the TPDD-2 nor Desklink support the FDC Emulation mode and instead add sector access commands in Operational mode to provide the same functionality.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Basic premise for extension addition ===&lt;br /&gt;
&lt;br /&gt;
The directory management extensions in TS-DOS are implemented partially using commands to support the FDC Emulation mode, and partially using a targeted file extension (&amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;) in operational mode commands to denote references to a directory or subdirectory on the media. The FDC Emulation mode commands are used to identify if the client supports DME and the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension is used to specify target directories for creation, deletion or navigation.&lt;br /&gt;
&lt;br /&gt;
=== Request Format ===&lt;br /&gt;
&lt;br /&gt;
Both FDC Emulation requests and Operational mode requests are issued by TS-DOS, although only a single FDC Emulation mode request is used. FDC Emulation requests consist of a single ASCII character with one or more ASCII arguments followed by a carriage return (0Dh). Operational mode requests consist of a Preamble of ZZ (5Ah 5Ah), followed by a Request ID byte, a Payload Length byte, 0 or more payload bytes, terminated by a checksum.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;strong&amp;gt;Note:&amp;lt;/strong&amp;gt; All values are shown as hexadecimal. ASCII character strings are enclosed with quotation marks. The quotation marks are not part of the command or response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Response Format ===&lt;br /&gt;
&lt;br /&gt;
In operational mode, the reponse format is identical to the request format, except that no preamble is sent. In FDC Emulation mode, the reponse format varies depending on the command and the TPDD service. Specific details regarding FDC Emulation mode responses will be described as needed.&lt;br /&gt;
&lt;br /&gt;
== TPDD Service discovery ==&lt;br /&gt;
&lt;br /&gt;
Since TS-DOS must operate with with various TPDD servers, and since not all servers follow the same protocol, it must determine if the server is capable of supporting DME. This is done by sending an FDC Emulation mode command to go into operational mode (&amp;quot;M1&amp;quot;), followed by an operational mode command to go into FDC Emulation mode. For this operational mode sequence, TS-DOS actually terminates the command with a carriage return (0Dh) which isn&#039;t part of the standard operational mode protocol. The following two commands are sent:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Request (DMEReq) ===&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;10&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| &amp;quot;M1&amp;quot;&lt;br /&gt;
| 0D&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 08&lt;br /&gt;
| 00&lt;br /&gt;
| F7&lt;br /&gt;
|}&lt;br /&gt;
| 0D&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; For a TPDD service that supports FDC Emulation mode, the standard response for both commands is no response. If the server does not respond to either command, or responds with an error message, then TS-DOS knows the client does not support DME.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; If the client does support DME, then after the final carriage return (0Dh), it shall reply with a standard operational mode response. The response ID must be 12h and the payload field must be 11 bytes long and contain the name of the current directory, or at least the lowest level name in the tree, as shown below. The name should be 6 characters long and should be terminated with &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h. Names shorter than 6 characters should be padded with spaces before the &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h extension.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; TS-DOS will display the directory name reported in the DMEResp payload in the upper right corner of the display in reverse video characters. If the current directory is the root &amp;quot;/&amp;quot; directory, then the client should return &amp;quot;ROOT .&amp;amp;lt;&amp;amp;gt; &amp;quot; in the payload filed as a standard, although any name could be provided. TS-DOS will send the DMEReq sequence multiple times including when it has requested a directory change operation. This provides a way of reporting the new subdirectory name for display in the TS-DOS title bar.&lt;br /&gt;
&lt;br /&gt;
=== Directory Management Extensions Response (DMEResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 12&lt;br /&gt;
| 0B&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Rsvd&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Extension&lt;br /&gt;
|-&lt;br /&gt;
| 00&lt;br /&gt;
| 6 bytes, space padded&lt;br /&gt;
| &amp;quot;.&amp;amp;lt;&amp;amp;gt;&amp;quot;,20h&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory reporting from Server ==&lt;br /&gt;
&lt;br /&gt;
The server device (DeskLink, NADSBox, etc.) should use the receipt of a DMEReq as an indication to provide directory and subdirectory information to TS-DOS (or any other client). If the DMEReq sequence is not received, then the server is communicating with a DOS that does not support DME, such as TEENY or FLOPPY, etc. Directory information is reported using the same protocol as regular files using the Directory Reference Request with the exception that the extension is reported as &amp;quot;&amp;amp;amp;lt&amp;amp;amp;gt &amp;quot;. Directory Reference Requests are part of the standard TPDD-1 and TPDD-2 protocol and can refer to a specific directory entry, or the first, next or previous entry in the directory. For filename discovery, the &amp;quot;first&amp;quot;, &amp;quot;next&amp;quot; or &amp;quot;previous&amp;quot; search forms are used, and the filename is all 00h.&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Request (DRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| File Name&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 24d bytes of 00&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 01, 02 or 03&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; When DME support has been established, the server reports directory information by responding to the DRReq sequence with a Directory Reference Response (DRResp) packet with the filename field containing the directory name in 6.2 filename format. The directory name should be 6 characters or less with space padding and the 2 character extension must be set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;. TS-DOS uses the &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot; extension to identify the entry as a directory. When the server is reporting file / directory entries for a directory other than the root, it should provide a mechanism for navigating to the parent directory. In both DeskLink and NADSBox, this is done by reporting the first entry of a subdirectory as &amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;. The number of Free Sectors on the media should be a single byte with the value 80H or less. Sectors in the TPDD protocol are 1280 bytes in length.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Reference Response (DRResp) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Response ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
| 1C&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Size&lt;br /&gt;
| Free&lt;br /&gt;
|}&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;# Sectors&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Change Directory requests from TS-DOS ==&lt;br /&gt;
&lt;br /&gt;
When the user navigates the cursor to a directory entry that has the &amp;quot;&amp;amp;amp;lt&amp;amp;amp;gt&amp;quot; extension and pressed Enter, TS-DOS will perform a Directory Change operation to naviagte to that directory. This is accomplished by sending a Change Direcotry Reference Request (CDRReq) followed by a standard Open File Request and then a Close File Request. The CDRReq packet is the same as a standard DRReq packet except the filename extension is set to &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Change Directory Reference Request (CDRReq) ===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: left; background-color: rgb(255, 255, 204); height: 113px&amp;quot; border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
| Preamble&lt;br /&gt;
| Request ID&lt;br /&gt;
| Payload Length&lt;br /&gt;
| Payload&lt;br /&gt;
| Checksum&lt;br /&gt;
|-&lt;br /&gt;
| 5A 5A&lt;br /&gt;
| 00&lt;br /&gt;
| 1A&lt;br /&gt;
|&lt;br /&gt;
{| style=&amp;quot;text-align: left; width: 100%&amp;quot; border=&amp;quot;1&amp;quot; frame=&amp;quot;box&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; frame=&amp;quot;box&amp;quot;&lt;br /&gt;
| Dir Name&lt;br /&gt;
| Ext.&lt;br /&gt;
| Spaces (or 00h)&lt;br /&gt;
| Attribute&lt;br /&gt;
| Search Form&lt;br /&gt;
|-&lt;br /&gt;
| 6 bytes&lt;br /&gt;
| &amp;quot;&amp;amp;lt;&amp;amp;gt;&amp;quot;&lt;br /&gt;
| 18 (decimal) bytes&lt;br /&gt;
| &amp;quot;F&amp;quot;&lt;br /&gt;
| 00&lt;br /&gt;
|}&lt;br /&gt;
| Checksum&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt; The client should respond to the CDRReq packet with a DRResp response packet containing the same directory name that was passed in the CDRReq. The client should save the directory name and expect to receive a subsequent Open File Request. When the Open File Request is received, the client should process it as a Change Directory operation to the directory specified in the CDRReq packet and return a standard Normal Response Packet (Id = 12H) with the appropriate error code. If the directory name matches the special name given for the parent directory (&amp;quot;PARENT.&amp;amp;lt;&amp;amp;gt;&amp;quot;), then the client should change to the parent of the current directory. The the client should then expect a Close File Request and respond as usual.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Checksum Algorithm ===&lt;br /&gt;
&lt;br /&gt;
 Total = Sum of all bytes from TypeID..Last byte of Payload&amp;lt;br /&amp;gt; Checksum = (Total &amp;amp;amp; FFh) XOR FFh&lt;/div&gt;</summary>
		<author><name>208.77.91.41</name></author>
	</entry>
</feed>