REM > EURO414/S REM Source for Euro-Beeb Terminal 4.14 : REM EuroBeeb Terminal allows the CUBE-65 or EuroBEEB to be used REM as a 6502 second processor for the BBC/Master. The communication REM is via the BBC's and the CUBE's serial ports. : REM NOTE: This is a bug-fixed version of 4.13. REM EURO 4.13 stores a configuration value in osbyte 249, corrupting REM the Break Intercept Vector. This crashes the system on BREAK if REM the BIV is in use. This patched version uses osbyte 247, disabling REM the BIV as a side effect. REM EURO 4.13 text printing corrupts the error pointer. Do *HELP REM then REPORT and a nonsense message is displayed. This patched REM version uses &F6/7. : OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0 load%=&8000 DIM mcode% &2014 FOR P=0 TO 1 P%=load%:O%=mcode% [OPT P*3+4 JMP L81E1 :\ Language Entry JMP L8047 :\ Service Entry EQUB &C2 :\ ROM type=Lang+Serv+6502 EQUB Copyright-Start .L8008 EQUB &04 :\ Default *EURO parameter .L8009 EQUS "EURO-Beeb Terminal" EQUB 0 EQUS "21 FEB 1986" .Copyright EQUB 0 EQUS "(C)Control Universal Ltd" EQUB 0 .L8042 EQUS "EURO" EQUB &FF \ SERVICE HANDLER \ =============== .L8047 PHP:PHA:TXA:PHA:TYA:PHA :\ Save all registers TSX:LDA &0103,X :\ Get stacked A JSR L80AD :\ Call service hander TAX:BEQ L805E :\ If call claimed, jump to claim call PLA:TAY:PLA:TAX:PLA:PLP :\ Restore all registers RTS :\ Return unclaimed .L805E PLA:PLA:TAX:PLA:ROR A PLP:ROL A:LDA #&00 :\ Claim call RTS \ Print inline text \ ================= .L8068 PLA:STA &F6:PLA:STA &F7 :\ Pop return address to &F6/7 (was &FD/E) TYA:PHA:LDY #&00:BEQ L8077 .L8074 JSR OSASCI .L8077 INC &F6:BNE L807D:INC &F7 :\ Increment address (was &FD/E) .L807D LDA (&F6),Y :\ Get character (was &FD) CMP #&EA:BNE L8074 :\ If not 'NOP' opcode, loop to print it PLA:TAY:JMP (&00F6) :\ Pop Y and jump back to code (was &FD) \ Check for 'EURO' string \ ======================= .L8088 STY &E6 :\ Save Y, corrupting &E6 .L808A LDA L8042,X:BMI L80A3 :\ End of match string LDA (&F2),Y CMP #&2E:BEQ L80A2 :\ Match found with '.' CMP L8042,X:BNE L809E :\ Exit with no match found INY:INX:BNE L808A :\ Increment and check next chars .L809E LDY &E6:SEC:RTS :\ Restore Y, set carry to indicate no match \ Skip spaces \ =========== .L80A2 INY .L80A3 LDA (&F2),Y :\ Fetch character CMP #&20:BEQ L80A2 :\ Skip any spaces CMP #&0D:CLC:RTS :\ Clear carry, set Z if found \ CHECK SERVICE CALLS \ =================== .L80AD CMP #&04:BEQ L80CD :\ *COMMAND CMP #&09:BEQ L80ED :\ *HELP CMP #&27:BEQ L80BD :\ CMP #&03:BNE L80CC :\ Exit if not Boot FS \ SERVICE 3 - BOOT FS or SERVICE &27 - RESET \ ========================================== .L80BD PHA:LDA #&FD:JSR L82D4 :\ *FX253,0,255 - read last BREAK type BEQ L80CB :\ If zero, soft BREAK, skip past and return LDA L8008:STA &0287 :\ *BUG* Copy default *EURO parameter to *FX247 location, :\ (was *FX249, corrupting Break Intercept Vector) PLA .L80CC RTS \ SERVICE 4 - *COMMAND \ ==================== .L80CD LDX #&00:JSR L8088 :\ Check for 'EURO' command BCC L80D7 :\ Jump to *EURO routine LDA #&04:RTS :\ Return unclaimed \ *EURO () \ =========== .L80D7 BEQ L80E6 :\ Jump if no parameters CMP #&31:BCC L80E6 :\ If <'1', treat as no parameters CMP #&35:BCS L80E6 :\ If >'4', treat as no parameters AND #&07:STA &0287 :\ Store parameter in *FX247 location (was :\ *FX249, corrupting Break Intercept Vector) .L80E6 LDX &F4:LDA #&8E JMP OSBYTE :\ Enter this ROM as a language \ SERVICE 9 - *HELP \ ================= .L80ED LDA (&F2),Y :\ Get character from *HELP command CMP #&0D:BNE L8119 :\ Jump if parameters exist JSR L8105 :\ Print ROM title and *EURO parameter JSR L8068 :\ Print inline text EQUB 13:EQUS "EURO":EQUB 13 NOP .L8102 LDA #&09:RTS :\ Return unclaimed \ Print ROM title \ --------------- .L8105 LDX #&FF:LDA #&0D :\ Prepare to print newline .L8109 JSR OSASCI:INX LDA L8009,X:BNE L8109 :\ Get character, loop until &00 byte LDA &0287:JSR L852F:RTS:\ Print *FX247 value (set by *EURO) :\ (was *FX249 value) \ *HELP with parameters \ --------------------- .L8119 LDX #&00 JSR L8088:BCS L8102 :\ If 'EURO' no present, exit unclaimed JSR L8105 :\ Print ROM title JSR L8068 :\ Print inline text EQUB 13:EQUS "shift" NOP LDA &0287 :\ Get *EURO parameter from *FX247 (was *FX249) CMP #&04:BNE L813F :\ Skip past if not 4 JSR L8068 :\ Print inline text EQUS "/ctrl" :\ If *EURO 4, then print "shift/ctrl", else "shift" NOP .L813F JSR L8068 :\ Print inline text EQUS " functions keys:":EQUB 13 EQUS " f0 *command":EQUB 13 NOP LDA &0287 :\ Get *EURO parameter from *FX247 (was *FX249) CMP #&03:BNE L81C5 :\ Skip past if not 3 JSR L8068 :\ Print inline text EQUS " f1 Select new station":EQUB 13 EQUS " f2 Poll all stations":EQUB 13 EQUS " f8 software RESET current station":EQUB 13 NOP .L81C5 JSR L8068 :\ Print inline text EQUW " f9 hardware RESET":EQUB 13 NOP LDA #0:RTS :\ Claim and return \ LANGUAGE STARTUP \ ================ .L81E1 CMP #&01:BEQ L81E6:RTS :\ Exit if not A=1 language startup .L81E6 LDX #&FF:TXS:CLI :\ Clear stack, enable IRQs LDA #L88A0 AND 255:STA &0202 :\ Set up error handler LDA #L88A0 DIV 256:STA &0203 LDA #&F7:JSR L82D4:STX &60 :\ Fetch byte stored by *EURO command :\ (was LDA #&F9) LDA #&02:LDX #&01:JSR OSBYTE :\ *FX2,1 - select serial input LDA #&B5:LDX #&01:LDY #&00 JSR OSBYTE :\ *FX181,1 - select raw serial input JSR L8068 :\ Print inline text EQUS "EURO" NOP LDA &60:JSR L852F :\ Print passed parameter in decimal JSR L8068 :\ Print inline text EQUS " Issue X4.14":EQUB 13 NOP .L822B JSR L8262:JSR L83F9 \ Main loop \ --------- .L8231 JSR L82AB :\ Select keyboard input, enable serial LDA #&D8:JSR L82D4:BNE L8252 :\ If function key pending, jump to read input LDA #&80:LDX #&FE:JSR OSBYTE :\ Read ADVAL(-2) - serial input buffer TXA:BEQ L8248 :\ Buffer empty, check for keyboard input JSR L82DD :\ Deal with serial input .L8248 LDA #&80:LDX #&FF:JSR OSBYTE :\ Read ADVAL(-1) - keyboard buffer TXA:BEQ L8231 :\ Buffer empty, loop back \ Keyboard input pending \ ---------------------- .L8252 LDA #&80:LDX #&FD:JSR OSBYTE :\ Read ADVAL(-3) - serial output buffer TXA:BEQ L8231 :\ No free space, loop back until space appears JSR L8351:JMP L8231 :\ Deal with keyboard input and loop back \ Set up function keys \ -------------------- .L8262 LDA &60:CMP #&04:BNE L828F :\ If *EURO 4, jump forward to set up LDA #&E1:LDX #&80 LDY #&00:JSR OSBYTE :\ *FX225,128 - fkey base=128 LDA #&E2:LDX #&90 LDY #&00:JSR OSBYTE :\ *FX226,144 - shift-fkey base=144 LDA #&E3:LDX #&A0 LDY #&00:JSR OSBYTE :\ *FX227,160 - ctrl-fkey base=160 LDA #&E4:LDX #&F0 LDY #&00:JSR OSBYTE :\ *FX228,224 - sh-ct-fkey base=224 JMP L8298 :\ Jump forward to set cursor keys, etc. \ *EURO 4 function key setup \ -------------------------- .L828F LDA #&E2:LDX #&F0 LDY #&00:JSR OSBYTE :\ *FX226,224 - shift-fkey base=224 .L8298 JSR L82C4 :\ Set cursor keys LDA #&0F:LDX #&00:JSR OSBYTE :\ Clear all buffers .L82A2 LDA #&E5:LDX #&01 LDY #&00:JSR OSBYTE :\ *FX229,1 - Escape key gives ASCII .L82AB LDA #&02:LDX #&02:JSR OSBYTE :\ *FX2,2 - enable serial input, read from keyboard RTS \ Set cursor and escape keys to normal \ ------------------------------------ .L82B3 LDA #&E5:LDX #&00 LDY #&00:JSR OSBYTE :\ *FX229,0 - Escape generates Escape state .L82BC LDA #&04:LDX #&00:JSR OSBYTE :\ Enable cursor keys .L82C3 RTS \ Set cursor keys according to *EURO parameter \ -------------------------------------------- .L82C4 LDA &60:BEQ L82C3 :\ If &00, exit LDX #&01:CMP #&04:BNE L82CF :\ If not 4, cursor keys are &87..&8B INX :\ *EURO 4, cursor keys are f11-f15 .L82CF LDA #&04:JMP OSBYTE \ Read OSBYTE value to A \ ---------------------- .L82D4 LDX #&00:LDY #&FF:JSR OSBYTE :\ Read OSBYTE value TXA:RTS :\ Pass to A and return \ Deal with serial input \ ====================== .L82DD LDA #&02:LDX #&01:JSR OSBYTE :\ *FX 2,1 - select serial input LDA #&03:LDX #&00:JSR OSBYTE :\ *FX 3,0 - Output to VDU, etc. JSR L8844:BCS L82F3 :\ Get character, jump if escaped command JMP OSWRCH :\ Output to VDU and return \ Escaped command received \ ------------------------ .L82F3 LDX #&FF:STA &64 :\ Store command byte in &64 .L82F7 INX:LDA L831C,X :\ Get byte from command table CMP &64:BEQ L8304 :\ If it matches, jump to call code CMP #&FF:BNE L82F7 :\ If not end of table, loop to check next entry RTS :\ Command not found, return silently .L8304 JSR L830E:JMP L82A2 :\ Call code, return via Escape off, serial on \ Perform action on Ctrl-Shift-fkey \ ================================= .L830A SEC:SBC #&E5:TAX :\ Index into address table .L830E LSR &61:LSR &62 :\ Clear &61 bit7 and &62 bit 7 - not in command LDA L833C,X:PHA :\ Stack address byte LDA L8327,X:PHA :\ Stack address byte SEC:RTS :\ Jump to routine with Carry set \ Recognised serial link command bytes \ ------------------------------------ .L831C EQUB &07 EQUB &08 EQUB &FD EQUB &FE EQUB &FC EQUB &FB EQUB &FA EQUB &05 EQUB &03 EQUB &00 EQUB &FF \ Serial link and function key command address low bytes \ ------------------------------------------------------ .L8327 EQUB (L86EC-1)AND255 :\ Link command 07 - OSBYTE EQUB (L86B5-1)AND255 :\ Link command 08 - OSWORD EQUB (L8688-1)AND255 :\ Link command FD - OSBGET EQUB (L869D-1)AND255 :\ Link command FE - OSBPUT EQUB (L8667-1)AND255 :\ Link command FC - OSFIND EQUB (L863A-1)AND255 :\ Link command FB - OSARGS EQUB (L8564-1)AND255 :\ Link command FA - OSGBPB EQUB (L8733-1)AND255 :\ Link command 05 - *CAT EQUB (L8739-1)AND255 :\ Link command 03 - *command EQUB (L879B-1)AND255 :\ Link command 00 - SAVE file EQUB (L874D-1)AND255 :\ Link command FF - LOAD file EQUB (L8396-1)AND255 :\ Ctrl-Shift-f0 - Enter *command EQUB (L83C8-1)AND255 :\ Ctrl-Shift-f1 - Select new station EQUB (L8410-1)AND255 :\ Ctrl-Shift-f2 - Poll all stations EQUB (L84CF-1)AND255 :\ Ctrl-Shift-f3 - do nothing EQUB (L84CF-1)AND255 :\ Ctrl-Shift-f4 - do nothing EQUB (L84CF-1)AND255 :\ Ctrl-Shift-f5 - do nothing EQUB (L84CF-1)AND255 :\ Ctrl-Shift-f6 - do nothing EQUB (L84CF-1)AND255 :\ Ctrl-Shift-f7 - do nothing EQUB (L84D1-1)AND255 :\ Ctrl-Shift-f8 - Software reset EQUB (L84D8-1)AND255 :\ Ctrl-Shift-f9 - Hardware reset \ Serial link and function key command address high bytes \ ------------------------------------------------------- .L833C EQUB (L86EC-1)DIV256 EQUB (L86B5-1)DIV256 EQUB (L8688-1)DIV256 EQUB (L869D-1)DIV256 EQUB (L8667-1)DIV256 EQUB (L863A-1)DIV256 EQUB (L8564-1)DIV256 EQUB (L8733-1)DIV256 EQUB (L8739-1)DIV256 EQUB (L879B-1)DIV256 EQUB (L874D-1)DIV256 EQUB (L8396-1)DIV256 EQUB (L83C8-1)DIV256 EQUB (L8410-1)DIV256 EQUB (L84CF-1)DIV256 EQUB (L84CF-1)DIV256 EQUB (L84CF-1)DIV256 EQUB (L84CF-1)DIV256 EQUB (L84CF-1)DIV256 EQUB (L84D1-1)DIV256 EQUB (L84D8-1)DIV256 \ Key pressed on keyboard \ ======================= .L8351 LDA #&02:LDX #&02:JSR OSBYTE :\ *FX2,2 - select keybaord input JSR OSRDCH :\ Get character from input CMP #&0D:BNE L8364 :\ If not , jump past JSR L82C4:LDA #&0D .L8364 CMP #&F0:BEQ L830A :\ If Ctrl-Shift-f0, jump to fkey commands BCC L8376 :\ If key<&F0, jump to send to serial CMP #&F9:BEQ L830A :\ If Ctrl-Shift-f9, jump to fkey commands BCS L8376 :\ If key>&F9, jump to send to serial LDX &60:CPX #&03:BEQ L830A :\ If flag=3, then Ctrl-Shift-f1 to f8 jump to fkey commands \ Send byte to serial \ ------------------- .L8376 PHA:TXA:PHA:TYA:PHA :\ Save registers LDA #&03:LDX #&07:JSR OSBYTE :\ *FX3,7 - Output to serial only TSX:LDA &0103,X:JSR OSWRCH :\ Output stacked character LDA #&03:LDX #&00:JSR OSBYTE :\ *FX3,0 - Output to VDU, etc. PLA:TAY:PLA:TAX:PLA:RTS :\ Restore registers and return \ Ctrl-Shift-f0 - Prompt for *command \ =================================== .L8396 JSR OSNEWL LDA #&2A:JSR OSWRCH :\ Print '*' prompt JSR L82B3:JSR L83AF :\ Escape on, cursors keys normal, input line JSR OS_CLI:JMP L83F9 :\ Do *command, jump to check response and return \ OSWORD 0 control block \ ---------------------- .L83AA EQUW &0700:EQUB &50 :\ Input buffer at &0700, length &50 bytes EQUB &20:EQUB &7E :\ Acceptable characters &20 to &7E .L83AF LDX #&04 .L83B1 LDA L83AA,X:STA &0780,X :\ Copy OSWORD 0 control block to &0780 DEX:BPL L83B1 LDX #&80:LDY #&07:LDA #&00 :\ Point to control block JSR OSWORD:LDX #&00:LDY #&07 :\ Call OSWORD and return XY=>input text .L83C7 RTS \ Ctrl-Shift-f1 - Select new station \ =================================== \ Prompt for new number. \ If 0..31, sends &9A,&80,&9A,num, if 128, sends &9A,&80 \ If no response after a bit, sends .L83C8 JSR L8068 :\ Print inline text EQUB 13:EQUS "Station " NOP JSR L83AF :\ Input line to &700 STX &F2:STY &F3 LDY #&00:JSR L84F3 :\ Scan for decimal value BCC L8403:BNE L8403 :\ Give error for 0 or no number TXA:CMP #&80:BEQ L83F4 :\ If 128, jump to send with no prefix CMP #&20:BCS L8403 :\ If >31, jump to give error LDA #&80:JSR L885E:TXA :\ Send &9A,&80 to serial port .L83F4 STA &63:JSR L885E :\ Save station in &63 and send &9A,num to serial port .L83F9 JSR L84B9:BCC L83C7 :\ Wait a bit, if serial replies, jump to return LDA #&0D:JMP L8376 :\ Send to serial and return .L8403 BRK:EQUB &FC EQUS "Bad number":BRK \ Ctrl-Shift-f2 - Poll all stations \ ================================= .L8410 JSR L8068 :\ Print inline text EQUB 13:EQUS "Poll all stations":EQUB 13 NOP LDX #&80:LDY #&07 :\ Point to &0780 LDA #&1F:STA &0780 :\ End at station 31 LDA #&14:JSR L8482 :\ Poll stations 0 to 31, store results at &0781 onwards LDA &63:JSR L885E :\ Send &9A,(current station) to serial LDX #&00 :\ Start with station 0 .L843C TXA:AND #&07:BNE &8444 :\ Print a newline every 8 items JSR OSNEWL .L8444 LDA &0781,X :\ Get response for this station CMP #&FF:BEQ L8478 :\ If &FF (no response), print a white dot STA &64:AND #&1F:TAY:LDA #&82:\ Save top 2 bits, prepare green text BIT &64:BPL L845C :\ If b7=0, jump to do green or yellow LDA #&81:BVS L8460:LDA #&86 :\ If %10, cyan text; if %11 red text .L845C BVC L8460:LDA #&83 :\ If %00, green text; if %01, yellow text .L8460 CPY &63:BNE L8466:LDA #&87 :\ If current station, override with white text \ \ Print response b0-b5 as coloured text \ b76 - %00 - green \ %01 - yellow \ %10 - cyan \ %11 - red \ Changes to white if current station \ Prints white dot if no response \ .L8466 JSR OSWRCH:TYA:JSR L852F :\ Print response in decimal .L846D INX:CPX #&20:BNE L843C :\ Increment station, loop until all done JSR OSNEWL:JMP L83F9 :\ Print newline, check serial response and return .L8478 JSR L8068 :\ Print inline text EQUB &87:EQUB &20:EQUB &2E :\ White text, space, dot NOP JMP L846D :\ Jump back to step to next station \ Poll stations 0 to (XY), store results at (XY+1) onwards \ ======================================================== \ For each station, sends &9A,&80,&9A,&40+stn .L8482 STX &64:STY &65 :\ Store pointer in XY LDA #&80:JSR &885E :\ Send &9A,&80 to serial LDA #&15:LDX #&01:JSR OSBYTE :\ *FX21,1 - Clear serial input buffer LDY #&00:STY &66 :\ Start with station 0 .L8496 LDA &66:ORA #&40 :\ Get &66 value OR &40 JSR &885E :\ Send &9A,num OR &40 to serial JSR &84B9:BCS &84AA :\ Wait for input, skip past with A=&FF if no response LDA #&91:LDX #&01:JSR OSBYTE :\ *FX145,1 - Read from serial input buffer .L84A9 TYA .L84AA INC &66:LDY &66:STA (&64),Y :\ Get station and store response or &FF DEY:TYA:LDY #&00 :\ Pass station number to A CMP (&64),Y:BNE L8496 :\ Loop until done station at first byte in block RTS \ Wait a short while to for serial input \ ====================================== .L84B9 LDA #&C8:STA &67 :\ Loop 200 times .L84BD LDA #&80:LDX #&FE:JSR OSBYTE :\ Read ADVAL(-2) - serial input buffer CLC:TXA:BNE L84CF :\ If data present, exit with carry clear DEC &67:BNE L84BD :\ Loop back to keep waiting LDA #&FF:SEC :\ Set carry - no data present .L84CF RTS .L84D0 RTS \ Ctrl-Shift-f8 - Software reset \ ============================== .L84D1 LDA &63:ORA #&E0:JMP L885E :\ Send &9A,station OR &E0 \ Ctrl-Shift-f9 - Hardware reset - send serial break signal \ ========================================================= .L84D8 LDX #&77:JSR L84EC :\ Set ACIA control - transmit serial break and reset ACIA LDY #&00 .L84DF LDA #&FF:SEC :\ Delay for 65536*(8 opcodes) .L84E2 SBC #&01:JSR L84D0:BCS L84E2 :\ Loop for 256 JSR/RTSs DEY:BNE L84DF :\ Loop for 65536 JSR/RTSs .L84EC LDA #&9C:LDY #&00:JMP OSBYTE :\ Restore ACIA to previous setting \ Scan string at (&F2),Y for a decimal number \ =========================================== .L84F3 JSR L80A3:JSR L8522 :\ Skip spaces, check if character is a digit BCC L851A :\ Not a digit, return with carry clear .L84FB STA &64:INY:JSR L8522 :\ Store current value, get and check next character BCC L851C :\ End of digits, return with carry set TAX:LDA &64:ASL A:BCS L851A :\ Multiply Current value by 10, exit with carry clear ASL A:BCS L851A :\ if overflow ADC &64:BCS L851A ASL A:BCS L851A:STA &64 TXA:ADC &64:BCC L84FB :\ Add digit to current value, loop if no overflow .L851A CLC:RTS :\ Clear carry to indicate invalid number .L851C LDX &64:CMP #&0D:SEC:RTS :\ Return value in X, set carry for OK, check any more parameters \ Check if character in A is a digit \ ================================== .L8522 LDA (&F2),Y CMP #&3A:BCS L851A :\ >'9', return with carry clear CMP #&30:BCC L851A :\ <'0', return with carry clear AND #&0F:RTS :\ A=digit value, return with carry set \ Print A in decimal \ ================== .L852F LDY #&FF:SEC .L8532 INY:SBC #&0A:BCS L8532 :\ Subtract tens ADC #&0A:PHA:TYA:BNE L853F :\ Save units, convert 0*10 to space LDA #&F0 .L853F JSR L855E:PLA:JMP L855E :\ Print tens, units \ Print A in hex - nothing seems to call these \ ============================================ .L8546 PHA:LDA #&20:JSR OSWRCH:PLA :\ Print a space .L854D PHA:LSR A:LSR A:LSR A:LSR A JSR L8556:PLA :\ Print top nybble .L8556 AND #&0F:CMP #&0A BCC L855E:ADC #&06 .L855E CLC:ADC #&30:JMP OSWRCH \ Link command FA - OSGBPB \ ======================== .L8564 ROR &62 :\ Set b7 of &62 - within command JSR L8844:STA &68 :\ Get GBPB action from serial, store in &68 LDY #&0C :\ Collect 12+1 bytes for control block .L856D JSR L8844:STA &0780,Y :\ Get byte, store in control block at &0780 DEY:BPL L856D :\ Loop for high down to low JSR L8618 :\ Set &66/7 to LDA #&00:STA &0781:STA &64 :\ Replace address with &1900, so corrupting LDA #&19:STA &0782:STA &65 :\ sideways workspace. Point &64/5 to address LDA &68:CMP #&03:BCS L85BC :\ If GBPB 3+, jump to do data read \ GBPB 1,2 - write data \ --------------------- .L858D JSR L8844:BCS L859C :\ Get byte, jump when command byte received LDY #&00:STA (&64),Y :\ Store byte in buffer JSR L8611:JMP L858D :\ Increment address and loop for next byte .L859C LDA &68:LDX #&80:LDY #&07 :\ Get GBPB action, point to local control block JSR OSGBPB:PHP :\ Call OSGBPB, save carry flag .L85A6 JSR L8868 :\ Clear &62.b7, send &9B,&00 JSR L8628:LDY #&0C :\ Update address in local control block .L85AE LDA &0780,Y:JSR L887C :\ Send byte from control block at &0780 DEY:BPL L85AE :\ Loop from byte down to low PLP:ROR A:JMP L887C :\ Get carry, send it and return \ GBPB 3+ - read data \ ------------------- .L85BC LDX #&80:LDY #&07:JSR OSGBPB :\ Read data to local buffer PHP:JSR L8868 :\ Clear &62 bit 7, send &9B,&00 LDY #&00:LDA &68 :\ Initialise Y to 0, get GBPB action CMP #&05:BCS L85E8 :\ Jump if action was read info .L85CF LDA &64:CMP &0781:BNE L85DD LDA &65:CMP &0782:BEQ L85A6 :\ If address=end, jump to send control block and return .L85DD LDA (&64),Y:JSR L8611 :\ Get byte, increment address JSR L887C:JMP L85CF :\ Send byte, loop for next byte \ GBPB 5+ - read info \ ------------------- \ Grrr - Shouldn't impose expectations, should just send whatever is received .L85E8 BEQ L85F9 :\ Jump with A=5 - read disk title CMP #&08:BEQ L85CF :\ A=8 - read directory entries - jump to return read data BCS L85A6 :\ If >8, jump to do nothing and return control block :\ Why? Interface should never impose restrictions on calls \ GBPB 6,7 - read directory/library name JSR L8604:JSR L8604 :\ Send length,string twice JMP L85A6 :\ Jump to return control block and finish \ GBPB 5 - Read disk title \ ------------------------ .L85F9 JSR L8604 ;\ Send length,string LDA (&64),Y:JSR L887C :\ Send boot option after string to serial JMP L85A6 :\ Jump to return control block and finish \ Send length,string from received data \ ------------------------------------- .L8604 LDA (&64),Y:TAX :\ Get first byte of data .L8607 LDA (&64),Y:INY:JSR L887C :\ Get byte and send it DEX:BPL L8607:RTS :\ Loop for count specified in first byte \ Update transfer address \ ----------------------- .L8611 INC &64:BNE L8617:INC &65 .L8617 RTS \ Calculate offset from &1900 to update control block later \ --------------------------------------------------------- .L8618 SEC:LDA &0781:SBC #&00:STA &66 LDA &0782:SBC #&19:STA &67:RTS \ Update control block address with resultant final address \ --------------------------------------------------------- .L8628 CLC:LDA &66:ADC &0781:STA &0781 LDA &67:ADC &0782:STA &0782:RTS \ Link command FB - OSARGS \ ======================== .L863A ROR &62 :\ Set bit7 - with command JSR L8844:TAY :\ Get ARGS handle JSR L8844:PHA:LDX #&00 :\ Get ARGS action .L8646 JSR L8844:STA &64,X :\ Get ARGS data, low to high INX:CPX #&04:BNE L8646 PLA:LDX #&64:JSR OSARGS :\ Do the OSARGS call JSR L8868 :\ Send acknowledge, &9B,&00 JSR L887C:LDX #&03 :\ Send ARGS result .L865E LDA &64,X:JSR L887C :\ Send ARGS data, high to low DEX:BPL L865E:RTS \ Link command FC - OSFIND \ ======================== .L8667 JSR L8844:TAY:BEQ L867F :\ Get FIND action, jump with CLOSE SEC:ROR &62 :\ Set bit7 - within command PHA:SEC:JSR L8824 :\ Save action, fetch string PLA:JSR OSFIND :\ Do the OSFIND call JSR L8868:JMP L887C :\ Send acknowledge, send result and return \ OSFIND 0 - CLOSE \ ---------------- .L867F JSR L8844:TAY:LDA #&00 :\ Get handle JMP OSFIND :\ Do the CLOSE call and return \ Link command FD - OSBGET \ ======================== .L8688 ROR &62:JSR L8844:TAY :\ Set bit 7 - withing command, fetch handle JSR OSBGET:PHP :\ Do the OSBGET call, save carry JSR L8868:JSR L887C :\ Send acknowledge, then read byte PLP:ROR A:JMP L887C :\ Send carry and return \ Link command FE - OSBPUT \ ======================== .L869D JSR L8844:TAY:JSR L8844 :\ Get handle to Y, get byte to write JMP OSBPUT :\ Do the OSBPUT call and return \ OSWORD reply block length \ ------------------------- .L86A7 EQUB &00 :\ Read input line EQUB &06 :\ Read TIME EQUB &00 :\ Write TIME EQUB &06 :\ Read interval EQUB &00 :\ Write interval EQUB &05 :\ Read from memory EQUB &00 :\ Write to memory EQUB &00 :\ SOUND EQUB &00 :\ ENVELOPE EQUB &05 :\ Read POINT EQUB &09 :\ Read character definition EQUB &05 :\ Read palette EQUB &00 :\ Write palette EQUB &08 :\ Read graphics coordinates \ Link command 08 - OSWORD \ ============================== .L86B5 JSR L8844:PHA :\ Get OSWORD number from serial link LDY #&00 .L86BB JSR L8844:BCS L86C6 STA &0780,Y:INY:BCC L86BB :\ Read incoming control block .L86C6 LDX #&80:LDY #&07:PLA :\ Point to local control block JSR OSWORD:TAY :\ Do the OSWORD call LDA L86A7,Y:STA &64 :\ Index into reply length table LDA #&00:JSR L8872 :\ Send ESC,&00 LDY #&00:BEQ L86E4 :\ Jump to send reply block .L86DD LDA &0780,Y:JSR L887C:INY :\ Send byte from control block .L86E4 CPY &64:BNE L86DD :\ Not at end of block, jump to send byte LDA #&04:BNE L871D :\ Send ESC,&04 to terminate reply \ Link command 07 - OSBYTE A,X,Y \ ============================== .L86EC JSR L8844:PHA :\ Get byte from serial link JSR L8844:TAX :\ Get X byte from serial link JSR L8844:TAY:PLA :\ Get Y byte from serial link CMP #&87:BNE L8705 :\ A<>&87, jump to do OSBYTE CPX #&8C:BCS L8705 :\ A=&87 with X>=&8C, do OSBYTE CPX #&87:BCS L8720 :\ A=&87 with X=&87..&8B, special call .L8705 JSR OSBYTE :\ Do OSBYTE call .L8708 PHP LDA #&00:JSR L8872 :\ Send ESC,&00 to serial link TXA:JSR L887C :\ Send X TYA:JSR L887C :\ Send Y PLP:ROR A:JMP L887C :\ Send Carry and return .L871B LDA #&FF .L871D JMP L8872 \ OSBYTE &87,&87..&8B - Insert cursor key \ --------------------------------------- .L8720 TXA:CLC:ADC #&04:TAY :\ Y=&8B..&8F - cursor keypress bytes LDA #&8A:LDX #&00:JSR OSBYTE :\ Insert cursor keypress into keyboard buffer JSR L82BC :\ Set cursor keys to normal LDX #&00:BEQ L8708 :\ Jump to return OSBYTE results \ Link command 05 - FSC 5 - *CAT \ ============================== .L8733 JSR L880E:JMP L873C :\ Fetch CAT string and jump to do OSCLI \ Link command 03 - FSC 3 - *command \ ================================== .L8739 JSR L8824 :\ Read string to text buffer .L873C TXA:PHA:TYA:PHA:JSR L82B3 :\ Save all regs, set cursor keys to normal JSR L82AB:PLA:TAY:PLA:TAX :\ Enable serial, select keyboard input JMP OS_CLI :\ Do OSCLI command and return \ Link command FF - LOAD \ ====================== .L874D ROR &62:JSR L8823 :\ Set 'within command', read string to &0700 LDA #&05:JSR OSFILE :\ See if object present TAY:BEQ L871B :\ Object not found, jump to return &9B,&FF JSR L8868 :\ Send acknowledge LDA #&40:LDX #&00:LDY #&07 JSR OSFIND:TAY :\ Open the specified file for input LDX #&64:LDA #&02:JSR OSARGS :\ Read file extent LDA &00,X:STA &078A :\ Save extent b0-b15 LDA &01,X:STA &078B STY &64:LDY #&0F :\ Save handle .L877C LDA &0782,Y:JSR L887C :\ Send control block back DEY:BPL L877C :\ Loop from high down to low BMI L878A :\ Jump ahead to start transfering .L8787 JSR L887C :\ Send byte to serial .L878A LDY &64:JSR OSBGET :\ Get byte from open file BCC L8787 :\ If not at EOF, loop back to send it LDA #&00:JSR OSFIND :\ Close file LDA #&04:JMP L8872 :\ Send ESC,&04 to end data, and return \ Link command 00 - SAVE \ ====================== .L879B ROR &61:JSR L8823 :\ Set 'within SAVE', read string to &0700 LDA #&06:JSR OSFILE :\ Delete any existing file LDX #&00:LDY #&07:LDA #&80 JSR OSFIND:PHA:LDY #&0F :\ Open the specified file for output .L87B1 JSR L8844:STA &0782,Y :\ Read control block for SAVE DEY:BPL L87B1 :\ Loop from high to low LDA &078A:STA &64 :\ Save &64/5 to start address LDA &078B:STA &65 PLA:TAY :\ Get file handle back .L87C6 JSR L8844:BCS L87D7 :\ Wait for byte, jump if command received JSR OSBPUT :\ Send byte to open file INC &64:BNE L87C6:INC &65 :\ Increment address JMP L87C6 :\ Loop until all received .L87D7 LSR &61:LDA #&00:JSR OSFIND :\ Clear 'within SAVE', close file LDA &64:CMP &078E:BNE L87F5 :\ Compare final address with expected end address LDA &65:CMP &078F:BNE L87F5 :\ If different, jump to error LDA #&02 :\ Write file information .L87EE LDX #&80:LDY #&07 :\ Point to control block JMP OSFILE :\ Call OSFILE to write info or delete file .L87F5 JSR L8068 :\ Print inline text EQUB 13:EQUS "TFS input error":EQUB 13 NOP LDA #&06:BNE L87EE :\ Jump back to delete file \ Store 'CAT' followed by string from serial \ ========================================== \ Previously, this stored 'CAT' with no spaces, so causes, eg 'CATFRED' \ instead of 'CAT FRED' .L880E LDA #ASC"*":STA &0700 :\ Store '*. ' in text buffer LDA #ASC".":STA &0701 LDA #ASC" ":STA &0702 SEC:PHP:LDY #&01:BNE L8827 :\ Read string to after '*.' \ Read string from serial link \ ============================ .L8823 CLC .L8824 PHP:LDY #&FF .L8827 INY:JSR L8844:STA &0700,Y :\ Get byte, store in text buffer CMP #&0D:BNE L8827 :\ Loop until received LDX #&00:LDY #&07 :\ Point XY to string STX &0780:STY &0781 :\ Point OSFILE block to string PLP:BCS L8843 :\ If carry set, return pointing to string LDX #&80:LDY #&07 :\ If carry clear, return point to control block .L8843 RTS \ Get character from input \ ------------------------ .L8844 JSR OSRDCH:PHA :\ Get character from input LDA &60:CMP #&02 :\ If EURO <2, return raw character PLA:BCC L885D :\ Return with carry clear CMP #&9B:BNE L885C :\ If not &9B, return with carry clear JSR OSRDCH :\ Get escaped character CMP #&9B:BEQ L885C :\ If ESC-ESC, return ESC with carry clear SEC:RTS :\ Return carry set to indicate escaped character .L885C CLC .L885D RTS \ Send &9A escaped byte to serial \ =============================== .L885E PHA:LDA #&9A:JSR L8376 :\ Send &9A prefix PLA:JMP L8376 :\ Send data byte \ Clear 'within command' flag and send acknowledge \ ================================================ .L8868 PHA:LSR &62 :\ Clear 'within command' flag LDA #&00:JSR L8872 :\ Send &9B,&00 PLA:RTS \ Send &9B escaped byte to serial \ =============================== .L8872 PHA:LDA #&9B:JSR L8376 :\ Send &9B prefix PLA:JMP L8376 :\ Send data byte \ Send data byte, escaping if needed \ ================================== .L887C CMP #&9A:BEQ L8894 :\ Jump with &9A CMP #&9B:BNE L8891 :\ Not &9B, send it LDA &60:CMP #&02:PHP :\ Get EURO setting LDA #&9B:PLP:BCC L8891 :\ If <2, send raw byte .L888E JSR L8376 :\ Send double-escape byte .L8891 JMP L8376 :\ Send byte .L8894 LDA &60:CMP #&03:PHP :\ Get EURO setting LDA #&9A:PLP:BNE L8891 :\ If EURO<>3, send raw BEQ L888E :\ Send double-byte sequence \ Error handler \ ============= .L88A0 LDX #&FF:TXS:CLI :\ Clear stack, enable IRQs JSR OSNEWL :\ Print newline LDY #&00:BEQ L88AE :\ Jump to print error message .L88AB JSR OSASCI :\ Print error character .L88AE INY:LDA (&FD),Y:BNE L88AB :\ Get byte, not zero, loop to print it JSR OSNEWL :\ Print another newline BIT &62:BMI L88C6 :\ If 'within command', jump to... BIT &61:BPL L88C3 :\ If not 'within SAVE', .L88BE JSR L8844:BCC L88BE :\ Loop to swallow all data from aborted SAVE .L88C3 JMP L822B :\ Return to main system loop .L88C6 JSR L871B:JMP L822B :\ Send ESC,&FF to abort, return to main system loop ]NEXT PRINT "*SAVE ";~mcode%;" ";~O%;" ";~exec%;" ";~load%