0001 ; 6809 Serial Tube Client Code 0002 ; ============================ 0003 ; Copyright (C)2010 J.G.Harston 0004 ; 0005 ; v0.10 12-Jun-2011 JGH: Converted from Tube client 0006 ; Based on 6809 Tube Client and Z80 Serial Tube Client 0007 ; v0.21 07-Jan-2012 JGH: Software reset sent on startup 0008 ; Added client error handler, version matches Tube client 0009 0010 ; This code may be freely reused. 0011 0012 ; NOTE! I don't have any 6809 hardware, so I don't know if this executes 0013 ; BA/BS Signals are used to remap hardware vectors from &FFFx to &FEFx 0014 0015 ; Memory layout: 0016 ; -F7FF - System stack 0017 ; F800-FFFF - Client ROM, copied to RAM on startup 0018 ; F800-F82E - Monitor ROM entry vectors 0019 ; FEF0-FEFF - Hardware vectors, remapped from &FFF0-&FFFF 0020 ; FF80- - Internal variables 0021 ; FFCE-FFE7 - Standard BBC MOS Entry Block 0022 0023 ; Client error implemented with SWI (equivalent of 6502 BRK, Z80 RST &38, etc.) 0024 0025 0026 ; Serial I/O Addresses 0027 ; ==================== 0028 ; These are suitable for a 6850 0029 fee0 TxSTATUS EQU $FEE0 0030 fee1 TxDATA EQU $FEE1 0031 fee0 RxSTATUS EQU $FEE0 0032 fee1 RxDATA EQU $FEE1 0033 0001 TxRDY EQU 1 0034 0002 RxRDY EQU 2 0035 0003 RxINIT EQU 3 0036 0015 TxINIT EQU $15 0037 0038 0039 ; Serial Tube system values 0040 ; ========================= 0041 007f esc EQU 127 0042 0043 0044 ; START OF ROM CODE 0045 ; ================= 0046 0047 f800 ORG $F800 0048 STACK: 0049 ROMSTART: 0050 f800 f8 34 COLD: FDB RESET ; $F800 - cold start 0051 f802 f8 90 WARM: FDB WARMS ; $F802 - warm start 0052 f804 ff e0 INCH: FDB OSRDCH ; $F804 - char input 0053 f806 f8 eb INCHE: FDB INECHO ; $F806 - char input with echo 0054 f808 ff c5 INCHECK: FDB KBDTST ; $F808 - test for char input 0055 f80a ff ee OUTCH: FDB OSWRCH ; $F80A - char output 0056 f80c f8 f4 PDATA: FDB PRDAT ; $F80C - output string until EOT 0057 f80e ff e7 PCRLF: FDB OSNEWL ; $F80E - output CR/LF 0058 f810 f8 f1 PSTRING: FDB PRTST ; $F810 - output CR/LF then string until EOT 0059 f812 f8 ff LRA: FDB LREAL ; $F812 - Load Real Address 0060 f814 20 7a BRA WARMS ; $F814 - for FLEX compatibility 0061 0062 BANNER: 0063 f816 0d FCB 13 0064 f817 36 38 30 39 20 53 FCC "6809 SERIAL TUBE 64K v0.21" 45 52 49 41 4c 20 54 55 42 45 20 36 34 4b 20 76 30 2e 32 31 0065 f831 0d FCB 13 0066 f832 0d FCB 13 0067 f833 00 FCB 0 0068 RESET: 0069 f834 1a 50 ORCC #$50 ; Ensure interupts disabled 0070 f836 10 ce f8 00 LDS #STACK ; Put stack at top of memory 0071 f83a 8e f8 00 LDX #ROMSTART ; Start at start of ROM 0072 RESETLP1: 0073 f83d a6 84 LDA ,X ; Get a byte from ROM 0074 f83f a7 80 STA ,X+ ; Store to RAM and increment X 0075 f841 8c fe e0 CMPX #IOADDRS 0076 f844 26 f7 BNE RESETLP1 ; Loop until hit I/O space 0077 f846 8e fe f0 LDX #ROMHIGH ; Point to ROM after I/O space 0078 RESETLP2: 0079 f849 a6 84 LDA ,X 0080 f84b a7 80 STA ,X+ 0081 f84d 8c 00 00 CMPX #0 0082 f850 26 f7 BNE RESETLP2 ; Copy top part of ROM to RAM 0083 0084 0085 ; STARTUP 0086 ; ======= 0087 ; Serial Tube data: $18 $00 $FF &FF -- Cy Y X 0088 ; followed by string 0089 ; 0090 ; Hardware Tube data: via R1: string $00 -- via R2: $7F or $80 0091 ; 0092 STARTUP: 0093 f852 1a 50 ORCC #$50 ; Disable interupts 0094 f854 10 ce f8 00 LDS #STACK 0095 f858 10 ff ff 8a STS MEMTOP ; Initialise top of memory 0096 f85c 32 7f LEAS -1,S ; Put stack at top of memory 0097 f85e 8e 00 00 LDX #0 0098 f861 bf ff 88 STX MEMBOT ; Initialise bottom of memory 0099 f864 86 15 LDA #TxINIT 0100 f866 b7 fe e0 STA >TxSTATUS ; Initialise serial port 0101 f869 86 03 LDA #RxINIT 0102 f86b b7 fe e0 STA >RxSTATUS ; Initialise serial port 0103 f86e 1c 00 ANDCC #$00 ; Clear all flags, enable interupts 0104 f870 bd ff bf JSR INITERR ; Initialise error handler 0105 0106 f873 86 ff LDA #$FF ; As we are using a serial link, we don't share a 0107 f875 10 8e 00 ff LDY #$FF ; hardware Reset, so we have to tell Host we have 0108 f879 bd f9 63 JSR FSC ; restarted. Send FSC &FF,&00,&FF - Soft Reset command 0109 f87c 1f 10 TFR X,D 0110 f87e 34 04 PSHS B ; Save Soft Reset result, will be &00 if no response 0111 0112 f880 8e f8 16 LDX #BANNER ; Point to startup banner 0113 f883 bd f9 08 JSR SEND_TXT ; Print it via Tube wrch protocol 0114 ; ; Accessing Tube registers pages ROM out 0115 f886 86 00 LDA #0 0116 f888 b7 ff 80 STA >ESCFLG ; Clear Escape flag 0117 0118 ; If we share a hardware Reset, we wait for an Ack here 0119 ; JSR OSWRCH ; Send terminating zero byte 0120 ; JSR CLI_WAIT ; Wait for result byte 0121 0122 f88b 35 02 PULS A ; We sent a Software Reset, so use the Ack from that 0123 f88d bd f9 37 JSR CLI_CHECK ; Check result byte 0124 ; ; Fall through to CLICOM if nothing executed 0125 0126 ; Command line prompt 0127 ; =================== 0128 ; Allow user to enter *commands 0129 ; 0130 WARMS: 0131 CLILOOP: 0132 f890 10 fe ff 8a LDS MEMTOP ; Reset stack to top of memory 0133 f894 bd ff bf JSR INITERR ; Initialise error handler 0134 f897 1c 00 ANDCC #$00 ; Clear all flags, enable interupts 0135 f899 8e f8 b1 LDX #PROMPT 0136 f89c bd f9 08 JSR SEND_TXT ; Display prompt 0137 f89f 8e f8 b7 LDX #COM_BLK ; Point to control block 0138 f8a2 86 00 LDA #0 0139 f8a4 bd ff f1 JSR OSWORD ; Read a line of text 0140 f8a7 25 1c BCS COM_ESC ; Escape pressed 0141 f8a9 8e fc 75 LDX #CLIBUF 0142 f8ac bd ff f7 JSR OS_CLI ; Execute command 0143 f8af 20 df BRA CLILOOP ; Loop back for another line 0144 PROMPT: 0145 f8b1 36 38 30 39 2a FCC "6809*" ; Command prompt 0146 f8b6 00 FCB 0 0147 ; 0148 COM_BLK: 0149 f8b7 fc 75 FDB CLIBUF ; Input buffer 0150 f8b9 7f FCB 127 ; Up to 127 characters 0151 f8ba 20 FCB 32 ; Lowest acceptable CHR$32 0152 f8bb ff FCB 255 ; Highest acceptable CHR$255 0153 ; 0154 ESCAPE: 0155 f8bc 3f SWI 0156 f8bd 11 FCB 17 0157 f8be 45 73 63 61 70 65 FCC "Escape" 0158 f8c4 00 FCB 0 0159 0160 COM_ESC: 0161 f8c5 86 7c LDA #124 0162 f8c7 bd ff f4 JSR OSBYTE ; Acknowledge Escape 0163 f8ca 8e f8 bd LDX #ESCAPE+1 ; Fall through into error handler 0164 0165 COM_ERR: 0166 f8cd 10 fe ff 8a LDS MEMTOP ; Reset stack to top of memory 0167 f8d1 bd ff e7 JSR OSNEWL 0168 f8d4 a6 80 LDA ,X+ ; Step X past error number 0169 f8d6 bd f9 08 JSR SEND_TXT ; Print text at X 0170 f8d9 bd ff e7 JSR OSNEWL 0171 f8dc 20 b2 BRA WARMS ; Return to command prompt 0172 0173 COM_INIT: 0174 f8de cc fb e4 LDD #SWI 0175 f8e1 fd fe fc STD XSWIV ; Point SWI vector to error BRK handler 0176 f8e4 cc f8 cd LDD #COM_ERR ; Point error vector to command prompt 0177 f8e7 fd ff fa STD BRKV ; error handler 0178 f8ea 39 RTS 0179 0180 0181 ; FLEX/OS-9 BIOS code 0182 ; =================== 0183 f8eb bd f8 04 INECHO: JSR INCH 0184 f8ee 7e f8 0a JMP OUTCH 0185 f8f1 bd f8 0e PRTST: JSR PCRLF 0186 f8f4 a6 80 PRDAT: LDA ,X+ ; Get character 0187 f8f6 81 04 CMPA #4 ; EOT character? 0188 f8f8 27 05 BEQ PREND ; End printing 0189 f8fa bd f8 0a JSR OUTCH ; Print character 0190 f8fd 20 f5 BRA PRDAT ; Loop to next 0191 PREND: 0192 LREAL: 0193 f8ff 39 RTS 0194 0195 0196 ; Print inline text 0197 ; ================= 0198 PR_TEXT: 0199 f900 35 10 PULS X ; Pop PC to X 0200 f902 bd f9 08 JSR SEND_TXT ; Print text 0201 f905 34 10 PSHS X ; Push updated X 0202 f907 39 RTS ; And return to it 0203 0204 ; Print text string at X 0205 ; ====================== 0206 SEND_TXT: 0207 f908 a6 80 LDA ,X+ ; Get byte from x, increment x 0208 f90a 81 00 CMPA #0 ; Test current character 0209 f90c 27 10 BEQ SEND_END ; End if $00 byte 0210 f90e bd ff e3 JSR OSASCI ; Send to OSASCI 0211 f911 20 f5 BRA SEND_TXT ; Loop until $00 byte 0212 0213 0214 ; OSRDCH - Wait for character from input stream 0215 ; ============================================= 0216 ; On exit: A=char, Cy=carry 0217 ; 0218 RDCH: 0219 f913 bd fb 1f JSR WaitByte ; Wait for character 0220 f916 34 02 PSHS A ; Save character 0221 f918 b6 ff 80 LDA >ESCFLG ; Get Escape flag 0222 f91b 49 ROLA ; Copy b7 of ESCFLG to Carry 0223 f91c 35 02 PULS A ; Get character back 0224 SEND_END: 0225 f91e 39 RTS 0226 0227 0228 ; OSRDCH_IO - Request character via Tube API 0229 ; ========================================== 0230 ; Tube data: $00 -- Carry Char 0231 ; 0232 ; On exit: A=char, Cy=carry 0233 ; 0234 RDCH_IO: 0235 f91f 86 00 LDA #0 0236 f921 bd fb 0d JSR SendCommand ; Send command $00 - OSRDCH 0237 WAIT_CHAR: 0238 f924 bd fb 1f JSR WaitByte ; Get returned byte 0239 f927 8b 80 ADDA #$80 ; Copy b7 into Carry 0240 f929 7e fb 1f JMP WaitByte ; Jump to get character 0241 0242 0243 ; OSCLI - Send command line to host 0244 ; ================================= 0245 ; Tube data: $02 string $0D -- $7F or $80 0246 ; 0247 ; On entry: X=>command string 0248 ; 0249 CLI: 0250 f92c 86 02 LDA #2 0251 f92e bd fb 0d JSR SendCommand ; Send command $02 = OSCLI 0252 f931 bd fa c9 JSR SEND_STR ; Send string at X 0253 CLI_WAIT: 0254 f934 bd fb 1f JSR WaitByte ; Wait for result via Tube R2 0255 CLI_CHECK: 0256 f937 81 80 CMPA #$80 ; Check return code 0257 f939 26 04 BNE CLI_DONE ; Nothing to execute, return 0258 CALL_CODE: 0259 f93b ad 9f ff 8e JSR [ADDRESS+2] ; Call program, 6809 is big-endian 0260 CLI_DONE: 0261 f93f 39 RTS 0262 0263 0264 ; OSBYTE 0265 ; ====== 0266 ; Tube data: $04 X A -- X 0267 ; $06 X Y A -- Cy Y X 0268 ; 0269 ; On entry: A,X,Y=OSBYTE parameters 0270 ; On exit: A preserved 0271 ; If A<$80, X=returned value 0272 ; If A>$7F, X, Y, Carry=returned values 0273 ; 0274 BYTE: 0275 f940 81 80 CMPA #$80 0276 f942 24 25 BCC BYTE_HI 0277 f944 34 06 PSHS A,B 0278 f946 86 04 LDA #4 0279 f948 bd fb 0d JSR SendCommand ; SEND COMMAND $04 - SHORT BYTE 0280 f94b 1f 10 TFR X,D ; B=X 0281 f94d bd fa f5 JSR SendByteB ; SEND SECOND PARAMETER FROM B 0282 f950 35 06 PULS A,B 0283 f952 34 06 PSHS A,B 0284 f954 bd fa f7 JSR SendByte ; SEND FIRST PARAMETER 0285 f957 bd fb 1f JSR WaitByte ; WAIT FOR RESPONSE 0286 f95a 1f 89 TFR A,B ; Move result to low byte 0287 f95c 86 00 LDA #0 ; Ensure AB is only 8-bit value 0288 f95e 1f 01 TFR D,X 0289 f960 35 06 PULS A,B 0290 f962 39 RTS 0291 0292 ; OSFSC 0293 ; ===== 0294 ; Tube data: $18 X Y A -- Cy Y X 0295 ; 0296 ; On entry: A,X,Y=OSFSC parameters 0297 ; NB: Only implemented for A>$7F 0298 ; On exit: A preserved 0299 ; X, Y, Carry=returned values 0300 ; 0301 FSC: 0302 f963 34 06 PSHS A,B 0303 f965 86 18 LDA #$18 ; Set command $18 - FSC 0304 f967 20 10 BRA BYTE_CMD ; Jump to send command 0305 0306 ; OSBYTE >$7F 0307 ; ----------- 0308 BYTE_HI: 0309 f969 81 82 CMPA #$82 0310 f96b 27 44 BEQ MEM82 ; FETCH ADDRESS HIGH WORD 0311 f96d 81 83 CMPA #$83 0312 f96f 27 44 BEQ MEM83 ; FETCH LOW MEMORY LIMIT 0313 f971 81 84 CMPA #$84 0314 f973 27 44 BEQ MEM84 ; FETCH HIGH MEMORY LIMIT 0315 f975 34 06 PSHS A,B 0316 f977 86 06 LDA #6 ; Set command $06 - long byte 0317 BYTE_CMD: 0318 f979 bd fb 0d JSR SendCommand ; Send command 0319 f97c 1f 10 TFR X,D ; B=X - second parameter 0320 f97e bd fa f5 JSR SendByteB ; Send second parameter from B 0321 f981 1f 20 TFR Y,D ; B=Y - third parameter 0322 f983 bd fa f5 JSR SendByteB ; Send third parameter from B 0323 f986 35 06 PULS A,B 0324 f988 bd fa f7 JSR SendByte ; Send first parameter 0325 f98b 81 9d CMPA #$9D ; Was it fast BPUT? 0326 f98d 27 21 BEQ BYTE_DONE ; Don't wait for response 0327 f98f 81 8e CMPA #$8E ; Was it start language? 0328 f991 27 a1 BEQ CLI_WAIT ; Wait for program start 0329 f993 34 06 PSHS A,B 0330 f995 bd fb 1f JSR WaitByte ; Wait for response 0331 f998 8b 80 ADDA #$80 ; Copy b7 into carry 0332 f99a 34 01 PSHS CC ; Save flags 0333 f99c bd fb 1f JSR WaitByte ; Wait for response 0334 f99f 1f 89 TFR A,B ; Move result to low byte 0335 f9a1 86 00 LDA #0 ; Ensure AB is only 8-bit value 0336 f9a3 1f 02 TFR D,Y ; Return result in Y 0337 f9a5 bd fb 1f JSR WaitByte ; Wait for response, high byte still in B 0338 f9a8 1e 89 EXG A,B ; Swap so high byte is Y, low byte is fetched byte 0339 f9aa 1f 01 TFR D,X ; Return result in X is returned Y*256+X value 0340 f9ac 35 01 PULS CC ; Get flags back 0341 f9ae 35 06 PULS A,B 0342 BYTE_DONE: 0343 f9b0 39 RTS 0344 0345 MEM82: 0346 f9b1 8e 00 00 LDX #0 ; Local memory is $0000xxxx 0347 f9b4 39 RTS 0348 0349 MEM83: 0350 f9b5 be ff 88 LDX MEMBOT ; Return bottom of user memory in X 0351 f9b8 39 RTS 0352 0353 MEM84: 0354 f9b9 be ff 8a LDX MEMTOP ; Return top of user memory in X 0355 f9bc 39 RTS 0356 0357 ; OSWORD 0358 ; ====== 0359 ; On entry: A=OSWORD number 0360 ; X=>control block 0361 ; 0362 WORD: 0363 f9bd 81 00 CMPA #0 0364 f9bf 27 01 BEQ RDLINE 0365 f9c1 39 RTS ; Ignore OSWORD <>0 for the moment 0366 ;PSHS A 0367 ;LDA #8 0368 ;JSR SendCommand ; SEND COMMAND $08 - OSWORD 0369 ; 0370 ; SEND PARAM BLOCK, ETC. 0371 ; 0372 ;RTS 0373 0374 ; OSWORD 0 - Read a line of text 0375 ; ------------------------------ 0376 ; Tube data: $0A block -- $FF or $7F string $0D 0377 ; 0378 RDLINE: 0379 f9c2 86 0a LDA #10 0380 f9c4 bd fb 0d JSR SendCommand ; Send Command $0A - RDLINE 0381 f9c7 30 02 LEAX 2,X ; X=X+2, point to parameters 0382 f9c9 10 8e 00 03 LDY #3 0383 f9cd bd fa d3 JSR SEND_BLK ; Send 3-byte control block 0384 f9d0 30 1e LEAX -2,X ; X=X-2, point back to text pointer 0385 f9d2 86 07 LDA #7 0386 f9d4 bd fa f7 JSR SendByte ; Send $0700 0387 f9d7 86 00 LDA #0 0388 f9d9 bd fa f7 JSR SendByte 0389 f9dc bd fb 1f JSR WaitByte ; Wait for response 0390 f9df 8b 80 ADDA #$80 ; Copy b7 into Carry 0391 f9e1 25 15 BCS RD_DONE 0392 f9e3 ae 84 LDX ,X ; Get text pointer from control block 0393 READ_STR: 0394 f9e5 10 8e 00 00 LDY #0 ; Y=number received 0395 f9e9 bd fb 1f JSR WaitByte ; Wwait for byte from Tube 0396 f9ec a7 80 STA ,X+ ; Store in text buffer, increment X 0397 f9ee 31 21 LEAY 1,Y ; Increment character count 0398 f9f0 81 0d CMPA #13 ; CHECK CURRENT BYTE 0399 f9f2 26 f1 BNE READ_STR ; LOOP UNTIL 0400 f9f4 31 3f LEAY -1,Y ; Decrement character count to balance 0401 f9f6 1c fe ANDCC #$FE ; CLEAR CARRY 0402 RD_DONE: 0403 f9f8 39 RTS 0404 0405 0406 ; OSARGS - Read info on open file 0407 ; =============================== 0408 ; Tube Data: $0C handle block function -- result block 0409 ; 0410 ; On entry: A=action 0411 ; X=>data 0412 ; Y=handle 0413 ; On exit: A=returned value 0414 ; X preserved 0415 ; X=>any returned data 0416 ; Y preserved 0417 ; 0418 ARGS: 0419 f9f9 34 20 PSHS Y ; Save handle 0420 f9fb 34 06 PSHS D ; Save function and B 0421 f9fd 86 0c LDA #$0C 0422 f9ff bd fb 0d JSR SendCommand ; Send command $0C - OSARGS 0423 fa02 1f 20 TFR Y,D 0424 fa04 bd fa f5 JSR SendByteB ; Send handle 0425 fa07 10 8e 00 04 LDY #4 0426 fa0b bd fa d3 JSR SEND_BLK ; Send four-byte control block 0427 fa0e 35 06 PULS D ; Get action back 0428 fa10 bd fa f7 JSR SendByte ; Send action 0429 fa13 bd fb 1f JSR WaitByte ; Wait for returned result 0430 fa16 34 02 PSHS A ; Save result 0431 fa18 10 8e 00 04 LDY #4 0432 fa1c bd fa e4 JSR WAIT_BLK ; Wait for four-byte control block 0433 fa1f 35 02 PULS A ; Get result back 0434 fa21 35 20 PULS Y ; Get original handle back 0435 fa23 39 RTS 0436 0437 0438 ; OSBGET - Get a byte from open file 0439 ; ================================== 0440 ; Tube data: $0E handle -- Carry byte 0441 ; 0442 ; On entry: Y=handle 0443 ; On exit: A=byte Read 0444 ; Y=preserved 0445 ; Cy set if EOF 0446 ; 0447 BGet: 0448 fa24 86 0e LDA #$0E 0449 fa26 bd fb 0d JSR SendCommand ; Send command $0E - OSBGET 0450 fa29 34 06 PSHS D 0451 fa2b 1f 20 TFR Y,D 0452 fa2d bd fa f5 JSR SendByteB ; Send handle 0453 fa30 35 06 PULS D 0454 fa32 16 fe ef LBRA WAIT_CHAR ; Wait for Carry, Byte 0455 0456 0457 ; OSBPUT - Put a byte to an open file 0458 ; =================================== 0459 ; Tube data: $10 handle byte -- $7F 0460 ; 0461 ; On entry: A=byte to write 0462 ; Y=handle 0463 ; On exit: A=preserved 0464 ; Y=preserved 0465 ; 0466 BPut: 0467 fa35 34 06 PSHS D ; Save byte 0468 fa37 86 10 LDA #$10 0469 fa39 bd fb 0d JSR SendCommand ; Send command $10 - OSBPUT 0470 fa3c 1f 20 TFR Y,D 0471 fa3e bd fa f5 JSR SendByteB ; Send handle 0472 fa41 35 06 PULS D ; Get A and B back 0473 fa43 34 06 PSHS D 0474 fa45 bd fa f7 JSR SendByte ; Send byte to Tube 0475 fa48 bd fb 1f JSR WaitByte ; Wait for acknowledgement 0476 fa4b 35 06 PULS D ; Restore A 0477 fa4d 39 RTS 0478 0479 0480 ; OSFIND - Open or Close a file 0481 ; ============================= 0482 ; Tube data: $12 function string $0D -- handle 0483 ; $12 $00 handle -- $7F 0484 ; 0485 ; On entry: A=function 0486 ; Y=handle or X=>filename 0487 ; On exit: A=zero or handle 0488 ; 0489 FIND: 0490 fa4e 34 06 PSHS D ; Save A 0491 fa50 86 12 LDA #$12 0492 fa52 bd fb 0d JSR SendCommand ; Send command $12 - OSFIND 0493 fa55 35 06 PULS D ; Get R0 back 0494 fa57 bd fa f7 JSR SendByte ; Send function 0495 fa5a 81 00 CMPA #0 ; Check function 0496 fa5c 27 07 BEQ Close ; Jump to deal with Close 0497 fa5e bd fa c9 JSR SEND_STR ; Send string at X 0498 fa61 bd fb 1f JSR WaitByte ; Wait for returned handle 0499 fa64 39 RTS 0500 Close: 0501 fa65 34 04 PSHS B 0502 fa67 1f 20 TFR Y,D 0503 fa69 bd fa f5 JSR SendByteB ; Send handle to Tube 0504 fa6c bd fb 1f JSR WaitByte ; Wait for acknowledgement 0505 fa6f 35 04 PULS B 0506 fa71 86 00 LDA #0 ; Zero A 0507 fa73 39 RTS 0508 0509 0510 ; OSFILE - Operate on whole files 0511 ; =============================== 0512 ; Tube data: $14 block string function -- result block 0513 ; 0514 ; On entry: A=function 0515 ; X=>control block 0516 ; On exit: A=result 0517 ; X preserved 0518 ; control block updated 0519 ; 0520 FILE: 0521 fa74 34 20 PSHS Y ; Save Y 0522 fa76 34 10 PSHS X ; Save X 0523 fa78 34 02 PSHS A ; Save function 0524 fa7a 86 14 LDA #$14 0525 fa7c bd fb 0d JSR SendCommand ; Send command $14 - OSFILE 0526 fa7f 30 02 LEAX 2,X ; Point to control block contents 0527 fa81 10 9e 00 LDY  #16 0528 fa84 bd fa d3 JSR SEND_BLK ; Send 16-byte control block 0529 fa87 30 1e LEAX -2,X ; Point to filename pointer 0530 fa89 ae 84 LDX ,X ; Get filename pointer to X 0531 fa8b bd fa c9 JSR SEND_STR ; Send filename string 0532 fa8e 35 02 PULS A 0533 fa90 bd fa f7 JSR SendByte ; Send function 0534 fa93 bd fb 1f JSR WaitByte ; Wait for returned result 0535 ; ; Data transfer via interupts may happen while waiting 0536 fa96 35 10 PULS X ; Get control block pointer back 0537 fa98 34 02 PSHS A ; Save result 0538 fa9a 30 02 LEAX 2,X ; Point to control block contents 0539 fa9c 10 8e 00 10 LDY #16 0540 faa0 bd fa e4 JSR WAIT_BLK ; Wait for 16-byte control block 0541 faa3 35 02 PULS A ; Get result back 0542 faa5 35 20 PULS Y ; Get Y back 0543 faa7 39 RTS 0544 0545 0546 ; OSGBPB - Multiple byte Read and write 0547 ; ===================================== 0548 ; Tube data: $16 block function -- block Carry result 0549 ; 0550 ; On entry: A=function 0551 ; X=>control block 0552 ; On exit: A=returned value 0553 ; control block updated 0554 ; 0555 GBPB: 0556 faa8 34 20 PSHS Y ; Save Y 0557 faaa 34 02 PSHS A ; Save function 0558 faac 86 16 LDA #$16 0559 faae bd fb 0d JSR SendCommand ; Send command $16 - OSGBPB 0560 fab1 10 8e 00 0d LDY #13 0561 fab5 bd fa d3 JSR SEND_BLK ; Send 13-byte control block 0562 fab8 35 02 PULS A 0563 faba bd fa f7 JSR SendByte ; Send function 0564 fabd 10 8e 00 0d LDY #13 0565 fac1 bd fa e4 JSR WAIT_BLK ; Wait for 13-byte control block 0566 fac4 35 20 PULS Y ; Get Y back 0567 fac6 16 fe 5b LBRA WAIT_CHAR ; Get Carry and result byte 0568 0569 0570 ; Tube I/O routines 0571 ; ================= 0572 0573 ; Send cr-string at X to Tube 0574 ; =========================== 0575 SEND_STR: 0576 fac9 a6 80 LDA ,X+ ; GET BYTE FROM X, INCREMENT X 0577 facb bd fa f7 JSR SendByte ; SEND BYTE VIA TUBE R2 0578 face 81 0d CMPA #13 ; TEST CURRENT CHARACTER 0579 fad0 26 f7 BNE SEND_STR ; LOOP UNTIL CR SENT 0580 fad2 39 RTS 0581 0582 0583 ; Send block at X to Tube, Y=block length 0584 ; ======================================= 0585 SEND_BLK: 0586 fad3 34 04 PSHS B ; Save B 0587 fad5 1f 20 TFR Y,D ; B=Y 0588 fad7 3a ABX ; X=X+B, X points to end of block+1 0589 fad8 35 04 PULS B ; Restore B 0590 SEND_BLKLP: 0591 fada a6 82 LDA ,-X ; DECREMENT X, GET BYTE FROM X 0592 fadc bd fa f7 JSR SendByte ; SEND BYTE VIA TUBE R2 0593 fadf 31 3f LEAY -1,Y ; DECREMENT COUNT OF BYTES TO SEND 0594 fae1 26 f7 BNE SEND_BLKLP ; LOOP UNTIL ALL BYTES SENT 0595 fae3 39 RTS 0596 0597 0598 ; Wait for block at X from Tube, Y=block length 0599 ; ============================================= 0600 WAIT_BLK: 0601 fae4 34 04 PSHS B ; Save B 0602 fae6 1f 20 TFR Y,D ; B=Y 0603 fae8 3a ABX ; X=X+B, X points to end of block+1 0604 fae9 35 04 PULS B ; Restore B 0605 WAIT_BLKLP: 0606 faeb bd fb 1f JSR WaitByte ; GET BYTE VIA TUBE R2 0607 faee a7 82 STA ,-X ; DECREMENT X, STORE BYTE AT X 0608 faf0 31 3f LEAY -1,Y ; DECREMENT COUNT OF BYTES 0609 faf2 26 f7 BNE WAIT_BLKLP ; LOOP UNTIL ALL BYTES SENT 0610 faf4 39 RTS 0611 0612 0613 ; Send byte in B to Tube 0614 ; ====================== 0615 SendByteB: 0616 faf5 1f 98 TFR B,A 0617 ; ; Fall through into SendByte 0618 0619 0620 ; OSWRCH - Send character in A to Tube 0621 ; ==================================== 0622 ; On entry, A =character 0623 ; On exit, A =preserved 0624 WRCH: 0625 ; ; WRCH is simply SendByte 0626 0627 0628 ; Tube Core I/O Routines 0629 ; ====================== 0630 ; Characters and commands are sent over the same single port 0631 ; Outward commands are escaped, and inward responses are escaped 0632 ; 0633 ; Outward 0634 ; x VDU x 0635 ; esc,esc VDU esc 0636 ; esc,n MOS function, control block follows 0637 ; 0638 ; Inward 0639 ; x char/byte x 0640 ; esc,esc char/byte esc 0641 ; esc,&00 BRK, error number+text+null follows 0642 ; esc,<&80 read returned control block set length 0643 ; esc,&8n Escape change, b0=new state 0644 ; esc,&9x,Y,X,A Event 0645 ; esc,&Ax reserved for networking 0646 ; esc,&Bx end transfer 0647 ; esc,&Cx,addr set address 0648 ; esc,&Dx,addr execute address 0649 ; esc,&Ex,addr start load from address 0650 ; esc,&Fx,addr start save from address 0651 ; All commands are data inward, except esc,&Fx which is data outward 0652 0653 0654 ; Send byte in A, escaping it if needed 0655 ; ===================================== 0656 SendByte: 0657 faf7 81 7f CMPA #esc ; Escape character? 0658 faf9 26 03 BNE SEND_DATA ; No, send raw 0659 fafb bd fa fe JSR SEND_DATA ; Double escape character 0660 SEND_DATA: 0661 fafe 34 02 PSHS A ; Save byte 0662 SEND_WAIT: 0663 fb00 b6 fe e0 LDA >TxSTATUS 0664 fb03 84 01 ANDA #TxRDY 0665 fb05 27 f9 BEQ SEND_WAIT ; Loop until data can be sent 0666 fb07 35 02 PULS A ; Get byte back 0667 fb09 b7 fe e1 STA >TxDATA ; Send data 0668 fb0c 39 RTS 0669 0670 0671 ; Send an escaped command 0672 ; ======================= 0673 SendCommand: 0674 fb0d 34 02 PSHS A ; Save command byte 0675 fb0f 86 7f LDA #esc 0676 fb11 bd fa fe JSR SEND_DATA ; Send esc prefix 0677 fb14 35 02 PULS A 0678 fb16 20 e6 BRA SEND_DATA ; Send command byte 0679 0680 0681 ; Check if a byte is waiting, and read it if there 0682 ; ================================================ 0683 READ_BYTE: 0684 fb18 b6 fe e0 LDA >RxSTATUS 0685 fb1b 84 02 ANDA #RxRDY 0686 fb1d 26 17 BNE WAIT_EXIT ; Nothing pending, return 0687 ; ; Continue into WaitByte 0688 0689 0690 ; Wait for a byte, decoding escaped data 0691 ; ====================================== 0692 ; On exit, A =byte 0693 ; F =preserved 0694 ; 0695 WaitByte: 0696 fb1f 34 01 PSHS CC ; Save flags 0697 WaitByteLP: 0698 fb21 bd fb 37 JSR WAIT_DATA 0699 fb24 26 0e BNE WaitByteOK ; Not esc, return 0700 fb26 bd fb 37 JSR WAIT_DATA ; Get another byte 0701 fb29 27 09 BEQ WaitByteOK ; esc,esc, return 0702 fb2b 34 74 PSHS X,Y,B,U ; Push all registers 0703 fb2d bd fb 44 JSR WAIT_COMMAND ; Decode escaped command 0704 fb30 35 74 PULS X,Y,B,U ; Pop all registers 0705 fb32 20 ed BRA WaitByteLP 0706 WaitByteOK: 0707 fb34 35 01 PULS CC ; Pop flags 0708 WAIT_EXIT: 0709 fb36 39 RTS 0710 0711 0712 ; Wait for data 0713 ; ============= 0714 ; On exit, A =byte 0715 ; F =Z byte=esc, NZ byte<>esc 0716 ; 0717 WAIT_DATA: 0718 fb37 b6 fe e0 LDA >RxSTATUS 0719 fb3a 84 02 ANDA #RxRDY 0720 fb3c 27 f9 BEQ WAIT_DATA ; Loop until data present 0721 fb3e b6 fe e1 LDA >RxDATA ; Fetch data 0722 fb41 81 7f CMPA #esc ; Is it esc prefix? 0723 fb43 39 RTS 0724 0725 0726 ; Decode escaped command 0727 ; ====================== 0728 ; On entry, A=command 0729 ; All registers can be trashed 0730 ; 0731 WAIT_COMMAND: 0732 fb44 84 ff ANDA #255 0733 fb46 27 02 BEQ WAIT_ERROR ; esc,&00 - error 0734 fb48 2b 26 BMI WAIT_TRANSFER ; esc,>&7F - data transfer 0735 0736 ; esc,1..127 - read a control block 0737 ; ================================= 0738 0739 ; esc,&00 - error 0740 ; =============== 0741 WAIT_ERROR: 0742 fb4a 8e fb f5 LDX #ERRBLK ; Point to error buffer 0743 fb4d 86 3f LDA #$3F ; SWI opcode 0744 fb4f a7 80 STA ,X+ ; Store SWI opcode 0745 fb51 bd fb 1f JSR WaitByte ; Get error number 0746 fb54 a7 80 STA ,X+ ; Store error number 0747 FIRQ_R4LP: 0748 fb56 bd fb 1f JSR WaitByte ; Wait for byte of error string 0749 fb59 a7 80 STA ,X+ ; Store in error buffer 0750 fb5b 81 00 CMPA #0 ; Check current character 0751 fb5d 26 f7 BNE FIRQ_R4LP ; Loop until terminating $00 received 0752 fb5f b6 fb f6 LDA ERRBLK+1 0753 fb62 ba fb f7 ORA ERRBLK+2 ; Check for error 0,"" 0754 fb65 27 06 BEQ JMP_START 0755 fb67 8e fb f5 LDX #ERRBLK ; Point to error block 0756 fb6a 7e ff bc JMP ERRJMP ; Jump to generate error 0757 JMP_START: 0758 fb6d 7e f8 52 JMP STARTUP 0759 0760 ; esc,&8n - Escape change 0761 ; ======================= 0762 WAIT_TRANSFER: 0763 fb70 81 c0 CMPA #$C0 0764 fb72 24 31 BCC WAIT_START 0765 fb74 81 a0 CMPA #$A0 0766 fb76 24 24 BCC WAIT_END 0767 fb78 81 90 CMPA #$90 0768 fb7a 24 06 BCC WAIT_EVENT 0769 fb7c 46 RORA 0770 fb7d 46 RORA ; Move b0 into b7 0771 fb7e b7 ff 80 STA >ESCFLG ; Store Escape flag 0772 fb81 39 RTS 0773 0774 ; esc,&9x - Event 0775 ; =============== 0776 WAIT_EVENT: 0777 fb82 bd fb 1f JSR WaitByte ; Get event Y parameter 0778 fb85 1f 89 TFR A,B 0779 fb87 86 00 LDA #0 0780 fb89 1f 02 TFR D,Y 0781 fb8b bd fb 1f JSR WaitByte ; Get event X parameter 0782 fb8e 1f 89 TFR A,B 0783 fb90 86 00 LDA #0 0784 fb92 1f 01 TFR D,X 0785 fb94 bd fb 1f JSR WaitByte ; Get event A parameter 0786 fb97 ad 9f ff fc JSR [EVENTV] ; Dispatch event 0787 fb9b 39 RTS 0788 0789 ; esc,&Ax - Reserved 0790 ; ================== 0791 WAIT_END: 0792 fb9c 81 b0 CMPA #$B0 0793 fb9e 25 96 BCS WAIT_EXIT ; &Ax - Return to WaitByte 0794 0795 ; esc,&Bx - End transfer 0796 ; ====================== 0797 fba0 35 36 PULS X,Y,D 0798 fba2 35 30 PULS X,Y ; Drop data from stack to fall 0799 ; ; out of WaitSave/WaitLoad loop 0800 WAIT_EXIT2: 0801 fba4 39 RTS ; Return to WaitByte 0802 0803 ; esc,&C0+ - Start transfer 0804 ; ========================= 0805 WAIT_START: 0806 fba5 34 02 PSHS A ; Save transfer type 0807 fba7 bd fb 1f JSR WaitByte 0808 fbaa b7 ff 8c STA ADDRESS+0 ; Note - 6809 is big-endian 0809 fbad bd fb 1f JSR WaitByte ; Get data address 0810 fbb0 b7 ff 8d STA ADDRESS+1 0811 fbb3 bd fb 1f JSR WaitByte ; Get data address 0812 fbb6 b7 ff 8e STA ADDRESS+2 0813 fbb9 bd fb 1f JSR WaitByte ; Get data address LSB 0814 fbbc b7 ff 8f STA ADDRESS+3 0815 fbbf be ff 8e LDX ADDRESS+2 ; Get transfer address 0816 fbc2 35 02 PULS A ; Get transfer type back 0817 fbc4 81 d0 CMPA #$D0 0818 fbc6 25 dc BCS WAIT_EXIT2 ; &Cx - set address 0819 fbc8 81 e0 CMPA #$E0 0820 fbca 25 15 BCS WAIT_CODE ; &Dx - enter code 0821 fbcc 81 f0 CMPA #$F0 0822 fbce 24 07 BCC WAIT_SAVE ; &Fx - save data 0823 WAIT_LOAD: 0824 fbd0 bd fb 1f JSR WaitByte ; &Ex - load data 0825 fbd3 a7 80 STA ,X+ ; Get byte, store it 0826 fbd5 20 f9 BRA WAIT_LOAD ; Loop until terminated 0827 WAIT_SAVE: 0828 fbd7 a6 80 LDA ,X+ ; Get byte 0829 fbd9 bd fa f7 JSR SendByte ; Send it 0830 fbdc bd fb 18 JSR READ_BYTE ; Poll input for termination 0831 fbdf 20 f6 BRA WAIT_SAVE ; Loop until terminated 0832 WAIT_CODE: 0833 fbe1 7e f9 3b JMP CALL_CODE 0834 0835 ; SWI - Generate an error 0836 ; ======================= 0837 SWI: 0838 fbe4 32 6a LEAS 10,S ; Step past stack contents 0839 fbe6 35 10 PULS X ; Pop PC to X 0840 fbe8 1c 00 ANDCC #$00 ; Clear all flags, enable interupts 0841 ERRHANDLE: 0842 fbea bf ff 82 STX FAULT ; Save pointer to last error 0843 fbed 6e 9f ff fa JMP [BRKV] ; Jump to current error handler 0844 0845 ; Null interupt routines 0846 ; ====================== 0847 FIRQ: 0848 RES: 0849 SWI2: 0850 SWI3: 0851 IRQ: 0852 NMI: 0853 fbf1 3b RTI 0854 0855 0856 ; Null routines 0857 ; ============= 0858 fbf2 1c fb TSTKBD: ANDCC #$FB ; Clear Z 0859 NULL: 0860 fbf4 39 RTS 0861 0862 0863 fbf5 ERRBLK: RMB 128 ; Buffer to store host error block 0864 fc75 CLIBUF: RMB 128 ; Space to enter command line from CLI prompt 0865 fcf5 00 FCB 0 ; Generate a line in the listing 0866 0867 0868 fee0 ORG $FEE0 0869 IOADDRS: 0870 0871 fef0 ORG $FEF0 0872 ROMHIGH: 0873 fef0 fb f1 XRESV: FDB RES ; $FEF0 ; Hardware vectors, paged in to $FFFx 0874 fef2 fb f1 XSWI2V: FDB SWI2 ; $FEF2 0875 fef4 fb f1 XSWI3V: FDB SWI3 ; $FEF4 0876 fef6 fb f1 XFIRQV: FDB FIRQ ; $FEF6 0877 fef8 fb f1 XIRQV: FDB IRQ ; $FEF8 0878 fefa fb f1 XNMIV: FDB NMI ; $FEFA 0879 fefc fb e4 XSWIV: FDB SWI ; $FEFC 0880 fefe f8 34 XRESETV: FDB RESET ; $FEFE 0881 0882 0883 ff80 ORG $FF80 ; Use same addresses as Z80 0884 ff80 00 ESCFLG: FCB 0 ; $FF80 ; Escape flag 0885 ff81 00 FCB 0 0886 ff82 00 00 FAULT: FDB 0 ; $FF82 ; Last error message 0887 ff84 00 00 FDB 0 ; $FF84 0888 ff86 00 00 FDB 0 ; $FF86 0889 ff88 00 00 MEMBOT: FDB 0 ; $FF88 ; Bottom of user memory 0890 ff8a f8 00 MEMTOP: FDB $F800 ; $FF8A ; Top of user memory 0891 ff8c 00 00 ADDRESS: FDB 0 ; $FF8C ; Tube transfer address 0892 ff8e 00 00 FDB 0 0893 ff90 00 00 PROGRAM: FDB 0 ; $FF90 ; Program entry address 0894 ff92 00 DMA_DONE: FCB 0 ; $FF92 ; Transfer completion flag 0895 0896 ffb0 ORG $FFB0 0897 ffb0 7e fb f4 USERINT: JMP >NULL ; &FFB0 0898 ffb1 IRQ2V: EQU USERINT+1 0899 ffb3 7e f9 00 PRTEXT: JMP >PR_TEXT ; &FFB3 0900 ffb6 7e fb f4 JMP >NULL ; &FFB6 0901 ffb9 7e f8 90 CLICOM: JMP >CLILOOP ; &FFB9 0902 ffbc 7e fb ea ERRJMP: JMP >ERRHANDLE; &FFBC 0903 ffbf 7e f8 de INITERR: JMP >COM_INIT ; &FFBF 0904 ffc2 7e fb f4 JMP >NULL ; &FFC2 0905 ffc5 7e fb f2 KBDTST: JMP >TSTKBD ; &FFC5 0906 ffc8 7e fb f4 JMP >NULL ; &FFC8 0907 ffcb 7e fb f4 JMP >NULL ; &FFCB 0908 0909 ffce 7e fa 4e OSFIND: JMP >FIND ; $FFCE 0910 ffd1 7e fa a8 OSGBPB: JMP >GBPB ; $FFD1 0911 ffd4 7e fa 24 OSBGET: JMP >BGet ; $FFD4 0912 ffd7 7e fa 35 OSBPUT: JMP >BPut ; $FFD7 0913 ffda 7e f9 f9 OSARGS: JMP >ARGS ; $FFDA 0914 ffdd 7e fa 74 OSFILE: JMP >FILE ; $FFDD 0915 ffe0 7e f9 13 OSRDCH: JMP >RDCH ; $FFE0 0916 ffe3 81 0d OSASCI: CMPA #13 ; $FFE3 0917 ffe5 26 07 BNE OSWRCH 0918 ffe7 86 0a OSNEWL: LDA #10 ; $FFE7 0919 ffe9 bd ff ee JSR OSWRCH 0920 ffec 86 0d OSWRCR: LDA #13 ; $FFEC 0921 ffee 7e fa f7 OSWRCH: JMP >WRCH ; $FFEE 0922 fff1 7e f9 bd OSWORD: JMP >WORD ; $FFF1 0923 fff4 7e f9 40 OSBYTE: JMP >BYTE ; $FFF4 0924 fff7 7e f9 2c OS_CLI: JMP >CLI ; $FFF7 0925 fffa f8 cd BRKV: FDB COM_ERR ; $FF84 ; Error handler 0926 fffc fb f4 EVENTV: FDB NULL ; $FF86 ; Event vector 0927 fffe f8 34 L_FFFE: FDB RESET 0928