AS09 Assembler for M6809 [1.40]. Copyright 1994-2005, Frank A. Kingswood Page 1 ---------------------------------------------------------- SERIAL09.SRC ---------------------------------------------------------- 1996 lines read, no errors in pass 1. ; 6809 Serial Tube Client Code ; ============================ ; Copyright (C)2010-2012, 2014, 2017 J.G.Harston ; This can be assembled with: ; DOS as9: as9 6809.src -l now bin > errors.txt ; Kingswood as09: as09-dos -i -lSerial09.lst -0 Serial09.bin Serial09.src ; 6809.org.uk asm6809: (not yet checked) ; ; v0.10 12-Jun-2011 JGH: Converted from Tube client ; Based on 6809 Tube Client and Z80 Serial Tube Client ; v0.11 07-Jan-2012 JGH: Software Reset sent on startup ; Added client error handler ; v0.12 07-Jul-2012 JGH: SendCommand adds personality bits, incoming control ; block handler, OSWORD handler. Added hardware vectors, ; workspace in RAM for ROM-only code. ; v0.23 30-Nov-2014 JGH: Brought up to same version as hardware Tube client. ; Added PRHEX and HR2HEX, execute enters at PROGRAM ; MEMTOP moved below code if code is in high memory. ; 02-Dec-2014 JGH: Added PR_STRING. Implemented KBDTST for 6809 BIOS calls. ; STARTUP and OSCLI use internal stack. Execute checks ; code header. WARM resets MEMBOT & MEMTOP. ; v0.24 07-Dec-2014 JGH: EXECUTE enters code with A=1 or A=0, PROG saved and restored, ; soft Break will re-enter at PROG. OSCLI saves all registers. ; Raw 6809 code is not made the current program. Supervisor ; prompt makes itself current program. Full header (C) check. ; RESET avoids overwriting PROG so Soft Reset will re-enter ; current program. ; 14-Dec-2014 JGH: When EXECUTE called on RESET, does not report 'Not 6809 code' ; error, but jumps directly to CLICOM. Gives a cleaner startup ; display, and this is hook for future check for booting disk ; operating system. ; v0.25 20-Dec-2014 JGH: Added local *GO and *HELP commands, LPTR set to command line, ; OSBYTE 142 sets null LPTR. OSBYTE $82-$84 return address/256 in Y. ; Testing TxRDY uses ASLA instead of AND #$40. Squashed some JSRs ; into BSRs. ; v1.00 01-Jan-2015 JGH: Rolled over to version 1.00. ; v1.01 22-Jun-2017 JGH: EXECUTE passes caller's stack to callee. EXECUTE does not set ; code as current program, that is now responsibility of ; INITERR/OSINIT. OSCLI stack saving is now recursable. ; 23-Jun-2017 JGH: Precheck for '*RUN' to point LPTR to correct parameters. ; More stack space for transient OSCLI commands. ; v1.02 05-Aug-2017 JGH: Added test for 6309 to SWI code, optimised PRHEX routines. ; Only Transfer Type &Cx updates ADDRESS, uses 16-bit address. ; Slight optimisation to BYTE_HI. ; v1.03 06-Aug-2017 JGH: Rolled over to version 1.03 to match Tube client. ; 08-Aug-2017 JGH: Command table re-ordered to optimise dispatch. Optimised some ; ADD #$80 into ASLA. Bugfix for */(space)filename. ; 12-Aug-2017 JGH: *HELP always displays help message, optimised *HELP message. ; SWI checks for 6309. ; 15-Aug-2017 JGH: Forced JMP opcode at RAWVDU entry. ; v1.04 22-Aug-2017 JGH: Rolled over to version 1.04. ; 24-Aug-2017 JGH: Optimised SEND_BLOCK and WAIT_BLOCK. ; v1.05 25-Aug-2017 JGH: OSFILE/OSGBPB/OSARGS use big-endian control blocks ; 22-Sep-2017 JGH: PRTEXT preserves X as with Z80 Client. ; 12-Jul-2019 JGH: KBDTST/KBDIN routines use pending character input 0001 = KBDPEND: EQU 1 ; KBDTST/KBDIN pending input ; v1.06 25-Jun-2017 JGH: Removed superflous use of U in EXECUTE. 0106 = VERSION: EQU $0106 0000 = BUILD: EQU 0 ; ; 0001 = BIGENDIAN: EQU 1 ; Big-endian control block contents for OSFILE/OSGBPB/OSARGS ; ; ; This code may be freely reused. ; ; Acknowledgements to: ; Johan Heuseveldt: mentioning 6809 CoPros on the BBC Mailing List inspired me to ; complete the code. ; David Banks: has tested the Tube version on the Matchbox CoPro "real" hardware. ; ; Notes: ; 07-Jan-2012: When I initially wrote this I didn't have any 6809 hardware, so didn't ; know if this executed. ; 20-Nov-2014: DMB has tested the Tube version on emulated hardware and shown it to work. ; I have tested this on 6809Tube emulator. ; ; Memory layout: ; +-------------+--------------------------------------------------------+ ; | 0000- | vvv User memory vvv | ; | 00C0-00FF | Internal variables if in low RAM | ; | 0100-01FF | Text buffers if in low RAM | ; | | | ; | -wwFF | ^^^ User stack ^^^ | ; | xx00-xxBF | Text buffers if in high RAM | ; | xxC0-xxFF | Internal variables if in high RAM | ; | -xxFF | ^^^ User stack if Client in RAM ^^^ | ; +-------------+--------------------------------------------------------+ ; | F800-FFFF | Client ROM, copied to RAM on startup | ; | F800-F815 | 6809 BIOS entry vectors | ; | | | ; | FEC0-FEEF | I/O addresses if in ROM memory area | ; | FEF0-FEFF | Hardware vectors, remapped from &FFF0-&FFFF with BA/BS | ; | FF00-FF7F | Text buffers and internal stack if running from RAM | ; | FF80- | Internal variables if running from RAM | ; | -FFFF | BBC MOS entry block | ; +-------------+--------------------------------------------------------+ ; ; BA/BS Signals are used to remap hardware vectors from &FFFx to &FEFx. ; ROM copied to RAM at startup, then ROM paged out by accessing any I/O. Any ; write-only I/O hidden "under" ROM must be disabled until I/O at IOADDR is ; accessed. ; Client error implemented with SWI (equivalent of 6502 BRK, Z80 RST &38, etc.) ; SWI2 and SWI3 reserved for applications (eg FLEX, OS-9, etc). ; ; To distinguish between 6809 and 6309 the SWI handler checks that U does not ; equal where PC is expected on the stack. This will normally be under program ; control when you call SWI to generate an error. If your code does not know ; what the contents of U is when generating an error, ensure U is cleared with ; CLR U:SWI:error block. ; ; In all cases JSR OSERROR can be used to generate an error. ; ; Tube client system configuration tweekables ; =========================================== ; 64K RAM with ROM copied to RAM and internal workspace ; ----------------------------------------------------- 0000 = RAMSTART: EQU $0000 ; Start of user RAM f800 = ROMSTART: EQU $F800 ; Start of code f800 = RAMEND: EQU ROMSTART ; End of user RAM+1 ff80 = WORKSP: EQU $FF80 ; Internal workspace f800 = STACK: EQU RAMEND ; Default stack ; This memory map looks like the SWTPC MC-09 ; ------------------------------------------ ;; RAMSTART: EQU $0000 ; Start of user RAM ;; RAMEND: EQU $DF00 ; End of user RAM+1 ;; ROMSTART: EQU $F800 ; Start of code ;; WORKSP: EQU RAMEND+$C0 ; Workspace at $DFC0 ;; STACK: EQU RAMEND ; Default stack ;; ; NB, the MC-09 can map up to 1M of memory in 4K pages via DAT ; Alternatively, put the workspace in zero page like the 6502 ; ----------------------------------------------------------- ;; RAMSTART: EQU $0200 ; Start of user RAM ;; RAMEND: EQU $E000 ; End of user RAM+1 ;; ROMSTART: EQU $F800 ; Start of code ;; WORKSP: EQU $0100-$40 ; Workspace at top of zero page ;; STACK: EQU RAMEND ; Default stack ; Serial I/O Addresses ; ==================== ; These are suitable for a 6850 ;RxTxBASE EQU $E004 ; SWTPC ;RxTxBASE EQU $FEE0 ; Tube fee8 = RxTxBASE EQU $FEE8 ; ACIA fee8 = TxSTATUS EQU RxTxBASE+0 fee9 = TxDATA EQU RxTxBASE+1 fee8 = RxSTATUS EQU RxTxBASE+0 fee9 = RxDATA EQU RxTxBASE+1 0001 = TxRDY EQU 1 0002 = RxRDY EQU 2 0003 = RxINIT EQU 3 0015 = TxINIT EQU $15 ; Serial Tube system values ; ========================= 009b = esc EQU $9B ; Client MOS Workspace ; ==================== ; If code runs from ROM, workspace is in user RAM ; ----------------------------------------------- IF WORKSP < ROMSTART IF WORKSP > $0100 ERRBLK: EQU WORKSP-$C0 ; $DF00 - Buffer to store host error block CLIBUF: EQU WORKSP-$90 ; $DF30 - Space to enter command line from CLI prompt CLIEND: EQU WORKSP-$00 ENDIF ENDIF IF WORKSP < ROMSTART RESV: EQU WORKSP+$00 ; $DFC0 or $00C0 ; Same location as SWTPC SWI3V: EQU WORKSP+$02 ; $DFC2 or $00C2 SWI2V: EQU WORKSP+$04 ; $DFC4 or $00C4 FIRQV: EQU WORKSP+$06 ; $DFC6 or $00C6 IRQV: EQU WORKSP+$08 ; $DFC8 or $00C8 SWIV: EQU WORKSP+$0A ; $DFCA or $00CA NMIV: EQU WORKSP+$0C ; $DFCC or $00CC DMA_DONE: EQU WORKSP+$0E ; $DFCE or $00CE ; Transfer completion flag PENDA: EQU WORKSP+$0F ; $DFCF or $00CF ; Pending keypress EVENTV: EQU WORKSP+$10 ; $DFD0 or $00D0 BRKV: EQU WORKSP+$12 ; $DFD2 or $00D2 xxx1V: EQU WORKSP+$14 ; $DFD4 or $00D4 IRQ2V: EQU WORKSP+$16 ; $DFD6 or $00D6 CLIV: EQU WORKSP+$18 ; $DFD8 or $00D8 BYTEV: EQU WORKSP+$1A ; $DFDA or $00DA WORDV: EQU WORKSP+$1C ; $DFDC or $00DC WRCHV: EQU WORKSP+$1E ; $DFDE or $00DE RDCHV: EQU WORKSP+$20 ; $DFE0 or $00E0 FILEV: EQU WORKSP+$22 ; $DFE2 or $00E2 ARGSV: EQU WORKSP+$24 ; $DFE4 or $00E4 BGETV: EQU WORKSP+$26 ; $DFE6 or $00E6 BPUTV: EQU WORKSP+$28 ; $DFE8 or $00E8 GBPBV: EQU WORKSP+$2A ; $DFEA or $00EA FINDV: EQU WORKSP+$2C ; $DFEC or $00EC PROGRAM: EQU WORKSP+$2E ; $DFEE or $00EE ; Program entry address MEMBOT: EQU WORKSP+$30 ; $DFF0 or $00F0 ; Bottom of user memory MEMTOP: EQU WORKSP+$32 ; $DFF2 or $00F2 ; Top of user memory ADDRESS: EQU WORKSP+$34 ; $DFF4 or $00F4 ; Tube execution address TRANSFER: EQU WORKSP+$36 ; $DFF6 or $00F6 ; Tube transfer address LPTR: EQU WORKSP+$38 ; $DFF8 or $00F8 ; Command line tail ADDRHI: EQU WORKSP+$3A ; $DFFA or $00FA ; Memory address high word CTRL: EQU WORKSP+$3A ; $DFFA or $00FA ; Control address DMA_TYPE: EQU WORKSP+$3C ; $DFFC or $00FC ; TempA/Client personality FAULT: EQU WORKSP+$3D ; $DFFD or $00FD ; Last error message ESCFLG: EQU WORKSP+$3F ; $DFFF or $00FF ; Escape flag ENDIF IF WORKSP < $0100 ERRBLK: EQU $0100 ; $0100 - Buffer to store host error block CLIBUF: EQU $0180 ; $0180 - Space to enter command line from CLI prompt CLIEND: EQU $0200 ENDIF ; If ROM copied to RAM, workspace within ROM area ; ----------------------------------------------- IF WORKSP > ROMSTART ff80 = ESCFLG: EQU WORKSP+$00 ; $FF80 - Escape flag ff81 = DMA_TYPE: EQU WORKSP+$01 ; $FF81 - TempA/Client personality ff82 = FAULT: EQU WORKSP+$02 ; $FF82 - Last error message ;DEFERR: EQU WORKSP+$04 ; $FF84 - Default error handler ff86 = LPTR: EQU WORKSP+$06 ; $FF86 - Command line tail ff88 = MEMBOT: EQU WORKSP+$08 ; $FF88 - Bottom of user memory ff8a = MEMTOP: EQU WORKSP+$0A ; $FF8A - Top of user memory ff8c = ADDRESS: EQU WORKSP+$0C ; $FF8C - Tube transfer address ff8e = TRANSFER: EQU WORKSP+$0E ; $FF8E - Transfer address ff90 = PROGRAM: EQU WORKSP+$10 ; $FF90 - Program entry address ff92 = ADDRHI: EQU WORKSP+$12 ; $FF92 - Memory address high word ff94 = DMA_DONE: EQU WORKSP+$14 ; $FF94 - Transfer completion flag ENDIF ; START OF ROM CODE ; ================= f800 = ORG ROMSTART ; 6809 BIOS entry block always at F800 ; ==================================== f800 = ORG $F800 f800 : f833 COLD: FDB RESET ; $F800 - cold start f802 : f88a WARM: FDB WARMS ; $F802 - warm start IF KBDPEND f804 : f91a INCH: FDB INCHAR ; $F804 - char input ELSE INCH: FDB OSRDCH ; $F804 - char input ENDIF f806 : f915 INCHE: FDB INECHO ; $F806 - char input with echo f808 : f923 INCHECK: FDB KBDTST ; $F808 - test for char input f80a : ffee OUTCH: FDB OSWRCH ; $F80A - char output f80c : f90a PDATA: FDB PRDAT ; $F80C - output string until EOT f80e : ffe7 PCRLF: FDB OSNEWL ; $F80E - output CR/LF f810 : f907 PSTRING: FDB PRTST ; $F810 - output CR/LF then string until EOT f812 : f906 LRA: FDB LREAL ; $F812 - Load Real Address f814 : 2074 BRA WARMS ; $F814 - for FLEX compatibility f816 : BANNER: f816 : 0d FCB 13 f817 : 36383039205345.. FCC "6809 SERIAL TUBE 64K " f82c : 31 FCB ((VERSION >> 8) & 15) + $30 f82d : 2e FCB "." f82e : 30 FCB ((VERSION >> 4) & 15) +$30 f82f : 36 FCB (VERSION & 15) + $30 IF BUILD FCB BUILD+96 ELSE f830 : 20 FCB 32 ENDIF IF DEBUG FCC " DEBUG" ENDIF f831 : 0d00 FCB 13,0 f833 : RESET: IF WORKSP > ROMSTART f833 : 1a50 ORCC #$50 ; Ensure interupts disabled f835 : 10cef800 LDS #STACK ; Put stack just under ROM IF STACK = ROMSTART f839 : 1f41 TFR S,X ; Start copying from start of ROM ELSE LDX #ROMSTART ; Start copying from start of ROM ENDIF f83b : RESETLP1: f83b : ec84 LDD ,X ; Get two bytes from ROM f83d : ed81 STD ,X++ ; Store to RAM and increment X f83f : 8cfee0 CMPX #IOADDRS f842 : 2603 BNE RESETLP2 ; Loop until hit I/O space f844 : 8efef0 LDX #ROMHIGH ; Point to ROM after I/O space f847 : RESETLP2: f847 : 8cff8c CMPX #ADDRESS ; Don't modify ADDRESS and PROG f84a : 2603 BNE RESETLP3 f84c : 8eff94 LDX #DMA_DONE f84f : RESETLP3: f84f : 8c0000 CMPX #0 f852 : 26e7 BNE RESETLP1 ; Copy top part of ROM to RAM ENDIF ; STARTUP ; ======= ; Reset all vectors, initialise Client state, tell Host we've restarted ; ; Serial Tube data: $18 $00 $FF &FF -- Cy Y X ; followed by string ; ; Hardware Tube data: via R1: string $00 -- via R2: $7F or $80 ; f854 : STARTUP: f854 : 1a50 ORCC #$50 ; Disable interupts IF WORKSP < ROMSTART LDS DEFTOP ; Put stack at default top of user memory LDX #VECTORS ; Copy default vectors and workspace contents LDY #WORKSP LDB #$2E ; 46 bytes to copy VECLOOP: LDA ,X+ ; Get byte from default vectors STA ,Y+ ; Store in vectors DECB ; Decrement number of bytes BNE VECLOOP ; Loop until add done ELSE f856 : 10ceff60 LDS #CLISTK ; Use internal stack ENDIF f85a : 8615 LDA #TxINIT f85c : b7fee8 STA >TxSTATUS ; Initialise data port and page ROM out f85f : 8603 LDA #RxINIT f861 : b7fee8 STA >RxSTATUS ; Initialise data port ; Accessing I/O registers will page ROM out if running ; from RAM. Once ROM is paged out we can do subroutine ; calls as we can now read from stack in RAM f864 : 8d74 BSR MEM_INIT ; Reset user memory limits and error handler f866 : beff90 LDX PROGRAM ; Copy current PROGRAM to ADDRESS f869 : bfff8c STX ADDRESS ; so will re-enter on Soft Break ; At this point, if 6309 could change character at BANNER+2 and PROMPT+1 f86c : 1c00 ANDCC #$00 ; Clear all flags, enable interupts ; Tell the Host that we've restarted ; ---------------------------------- ; Serial Tube data: $18 $00 $FF &FF -- Cy Y X ; followed by string ; ; Note for Host authors: Host MUST NOT respond by echoing back a SoftReset as ; the Client will be trapped in an infinite STARTUP loop. ; f86e : 86ff LDA #$FF ; As we are using a serial link, we don't share a f870 : 8e0000 LDX #$00 ; hardware Reset, so we have to tell Host we have f873 : 108e00ff LDY #$FF ; restarted. f877 : bdfb3c JSR FSC ; Send FSC &FF,&00,&FF - Soft Reset command f87a : 1f10 TFR X,D ; Copy returned X to B f87c : 3404 PSHS B ; Save Soft Reset result, will be &00 if no response f87e : bdf97e JSR PR_HELP ; Print banner via Tube WRCH protocol f881 : bdffe7 JSR OSNEWL ; If we share a hardware Reset, we wait for an Ack here ; JSR OSWRCH ; Send terminating zero byte ; CLRA ; Clear Carry Flag to indicate Reset ; STA >ESCFLG ; Clear Escape flag ; ECSFLG will have been cleared when copying ROM/initialising workspace ; JSR CLI_WAIT ; Wait for result byte f884 : 4f CLRA ; Clear Carry Flag to indicate Reset ; STA >ESCFLG ; Clear Escape flag ; ECSFLG will have been cleared when copying ROM/initialising workspace f885 : 3502 PULS A ; We sent a Software Reset, so use the Ack from that f887 : bdfa8b JSR CLI_CHECK ; Check result byte ; ; Fall through to CLICOM if nothing executed ; Supervisor command line prompt ; ============================== ; Allow user to enter *commands ; f88a : WARMS: f88a : CLILOOP: f88a : 10ceff60 LDS #CLISTK ; Initially use internal stack f88e : 8d4a BSR COM_INIT ; Reset user memory limits and error handler f890 : 10feff8a LDS MEMTOP ; Reset stack to top of user memory ; LDX #CLICOM ; Make Supervisor the current program to re-enter f894 : 8ef88a LDX #WARMS ; Make Supervisor the current program to re-enter f897 : bfff90 STX PROGRAM ; on soft reset f89a : 1c00 ANDCC #$00 ; Clear all flags, enable interupts f89c : CLILOOP2: f89c : 8ef8af LDX #PROMPT f89f : bdf981 JSR SEND_TXT ; Display prompt ; CLRA ; Set A to zero (SEND_TXT returns A=0) ; LDX #COM_BLK ; Point to control block (SEND_TXT returned X=COM_BLK) f8a2 : bdfff1 JSR OSWORD ; Read a line of text f8a5 : 2514 BCS COM_ESC ; Escape pressed f8a7 : 8eff00 LDX #CLIBUF f8aa : bdfff7 JSR OS_CLI ; Execute command f8ad : 20ed BRA CLILOOP2 ; Loop back for another line f8af : PROMPT: f8af : 363830393e2a FCC "6809>*" ; Command prompt f8b5 : 00 FCB 0 f8b6 : COM_BLK: f8b6 : ff00 FDB CLIBUF ; Input buffer f8b8 : 5f FCB CLIEND-CLIBUF-1 ; Buffer size f8b9 : 20 FCB 32 ; Lowest acceptable CHR$32 f8ba : ff FCB 255 ; Highest acceptable CHR$255 f8bb : COM_ESC: f8bb : 867e LDA #126 f8bd : bdfff4 JSR OSBYTE ; Acknowledge Escape f8c0 : ESCAPE: f8c0 : 3f SWI f8c1 : 11 FCB 17 f8c2 : 457363617065 FCC "Escape" f8c8 : 00 FCB 0 f8c9 : COM_ERR: f8c9 : 10feff8a LDS MEMTOP ; Reset stack to top of user memory f8cd : bdffe7 JSR OSNEWL f8d0 : a680 LDA ,X+ ; Step X past error number f8d2 : bdf981 JSR SEND_TXT ; Print text at X f8d5 : bdffe7 JSR OSNEWL f8d8 : 20c2 BRA CLILOOP2 ; Return to command prompt f8da : MEM_INIT: ; This has already been done by copying ROM to RAM. But, when entering ; Supervisor we want to ensure full memory available. IF WORKSP < ROMSTART CLR ESCFLG LDA $FF81 STA DMA_TYPE LDD #BANNER STD FAULT STD LPTR ENDIF f8da : COM_INIT: IF WORKSP > ROMSTART f8da : cc0000 LDD #RAMSTART f8dd : fdff88 STD MEMBOT ; Initialise bottom of user memory f8e0 : ccf800 LDD #RAMEND f8e3 : fdff8a STD MEMTOP ; Initialise top of user memory ELSE LDD DEFBOT STD MEMBOT ; Initialise bottom of user memory LDD DEFTOP STD MEMTOP ; Initialise top of user memory ENDIF f8e6 : COM_BRKV: f8e6 : ccf8c9 LDD #COM_ERR ; Get Supervisor error handler address f8e9 : fdfffa STD BRKV ; Set error handler f8ec : ERR_INIT: f8ec : 4d TSTA f8ed : 2606 BNE ERR_INIT2 ; A<>$00, just read values f8ef : fcff8e LDD TRANSFER ; Set last entered code as current program f8f2 : fdff90 STD PROGRAM f8f5 : ERR_INIT2: IF WORKSP > ROMSTART f8f5 : ccfe25 LDD #SWI_HANDLE ELSE LDD DEFSWI ; Get default SWI address = Error handler ENDIF f8f8 : fdfefa STD SWIV ; Point SWI vector to error handler f8fb : 8efffa LDX #BRKV f8fe : 108eff80 LDY #ESCFLG ; Return X=>BRKV, Y=>ESCFLG, MI=little-endian FS calls IF BIGENDIAN f902 : 5f CLRB f903 : 4f CLRA ; Return PL=big-endian filing system calls ENDIF f904 : 1f03 TFR D,U ; Set U to a defined value so SWI works f906 : NULL: ; Null routines f906 : PREND: f906 : LREAL: f906 : 39 RTS ; FLEX/OS-9 BIOS code ; =================== IF KBDPEND f907 : bdffe7 PRTST: JSR OSNEWL f90a : a680 PRDAT: LDA ,X+ ; Get character f90c : 8104 CMPA #4 ; EOT character? f90e : 27f6 BEQ PREND ; End printing f910 : bdffee JSR OSWRCH ; Print character f913 : 20f5 BRA PRDAT ; Loop to next f915 : 8d03 INECHO: BSR INCHAR f917 : 7effee JMP OSWRCH f91a : 8d07 INCHAR: BSR KBDTST f91c : 27fc BEQ INCHAR ; Loop until character available f91e : 8d25 BSR KBDFLAG ; Clear 'pending character' flag IF WORKSP > ROMSTART f920 : 8600 _PENDA: LDA #0 ; Get pending character f921 = PENDA: EQU _PENDA+1 ; Pending character is parameter of LDA ELSE LDA PENDA ; Get pending character ENDIF f922 : 39 RTS f923 : 3436 KBDTST: PSHS D,X,Y ; Save registers f925 : b6ff80 LDA ESCFLG f928 : 8440 ANDA #$40 f92a : 2617 BNE KBDTST2 ; Character pending, return with NE f92c : 8e0000 LDX #0 f92f : 1f12 TFR X,Y f931 : 8681 LDA #$81 f933 : bdfff4 JSR OSBYTE ; INKEY(0) - get any pending character ; Y=$00 - character, X=character ; Y=$1B - escape ; Y=$FF - nothing pending f936 : 1f10 TFR X,D ; B=character f938 : 108c00ff CMPY #$FF f93c : 2705 BEQ KBDTST2 ; Nothing pending, return with EQ f93e : f7f921 STB PENDA f941 : 8d02 BSR KBDFLAG ; Set 'pending character' flag ; Fall through with NE=character pending f943 : KBDTST2: f943 : 35b6 PULS D,X,Y,PC f945 : KBDFLAG: f945 : 3401 PSHS CC f947 : 1a50 ORCC #$50 ; Disable interupts f949 : 8640 LDA #$40 ; Toggle key pending flag f94b : b8ff80 EORA ESCFLG f94e : b7ff80 STA ESCFLG f951 : 3581 PULS CC,PC ; Restore IRQs and return ELSE INECHO: JSR OSRDCH JMP OSWRCH PRTST: JSR OSNEWL PRDAT: LDA ,X+ ; Get character CMPA #4 ; EOT character? BEQ PREND ; End printing JSR OSWRCH ; Print character BRA PRDAT ; Loop to next KBDTST: PSHS A,X,Y LDA #$80 LDX #$FFFF ; Should check ADVAL(-2) if Serial is current input stream TFR X,Y JSR OSBYTE ; ADVAL(-1) - keyboard input buffer CMPX #0 ; Set Z/NZ from X PULS A,X,Y,PC ENDIF ; ***************** ; Printout Routines ; ***************** ; Print X as 4-digit hex ; ====================== ; API allows A to be corrupted ; All other registers preserved (v1.04 including B) f953 : PR_HEX2: f953 : 3404 PSHS B ; Save B f955 : 1f10 TFR X,D ; Copy X to D, so copy b8-b15 to A f957 : 8d04 BSR PR_HEX1 ; Print it f959 : 1f98 TFR B,A ; Copy b0-b7 to A f95b : 3504 PULS B ; Restore B ; Fall through into PR_HEX1 ; Print A as 2-digit hex ; ====================== ; API allows A to be corrupted ; All other registers preserved f95d : PR_HEX1: f95d : 3402 PSHS A ; Standard hex-print code f95f : 44 LSRA f960 : 44 LSRA f961 : 44 LSRA f962 : 44 LSRA f963 : 8d02 BSR PR_NYBBLE f965 : 3502 PULS A ; Get A back ; Fall through into PR_NYBBLE f967 : PR_NYBBLE: f967 : 840f ANDA #$0F f969 : 810a CMPA #$0A f96b : 2502 BCS PR_DIGIT f96d : 8b07 ADDA #7 f96f : PR_DIGIT: f96f : 8b30 ADDA #$30 f971 : 7effee JMP OSWRCH ; Print inline text ; ================= ; On exit: A=$00 ; X= corrupted ; from v1.05 ; X= preserved f974 : PR_TEXT: IF VERSION*16+BUILD>$1050 f974 : 3410 PSHS X ; Save X f976 : ae62 LDX 2,S ; Get stacked PC to X f978 : 8d07 BSR SEND_TXT ; Print text f97a : af62 STX 2,S ; Update stacked PC f97c : 3590 PULS X,PC ; Restore X and return to updated PC ELSE PULS X ; Pop PC to X BSR SEND_TXT ; Print text PSHS X ; Push updated X SEND_END: RTS ; And return to it ENDIF ; Print text string at X ; ====================== ; On entry: X=>zero-terminated text string ; On exit: X=>byte after zero byte terminator ; A=$00 ; f97e : PR_HELP: f97e : 8ef816 LDX #BANNER ; Print startup banner as help message f981 : SEND_TXT: f981 : a680 LDA ,X+ ; Get byte from X, increment X f983 : 2746 BEQ SEND_END ; End if $00 byte f985 : bdffe3 JSR OSASCI ; Send to OSASCI f988 : 20f7 BRA SEND_TXT ; Loop until $00 byte ; ********************** ; Line scanning Routines ; ********************** ; Scan hex string ; =============== ; On entry, X=>start of hex string ; On exit, X=>first non-hex character ; Y=hex value ; A=terminating character ; B=corrupted ; CS if number terminated, eg 123 X or 123 ; CC if number not terminated, eg 123X ; f98a : RD_HEX: f98a : 108e0000 LDY #0 ; Clear hex accumulator f98e : RD_HEXLP: f98e : a680 LDA ,X+ ; Get current character f990 : 8130 CMPA #$30 ; <'0', exit f992 : 2533 BCS RD_HEXDONE f994 : 813a CMPA #$3A ; '0'..'9', add to accumulator f996 : 250a BCS RD_HEXADD f998 : 84df ANDA #$DF ; Ensure upper case letter f99a : 8007 SUBA #$07 ; Convert letter, if <'A', exit f99c : 2529 BCS RD_HEXDONE f99e : 8140 CMPA #$40 f9a0 : 2425 BCC RD_HEXDONE ; If >'F', exit f9a2 : RD_HEXADD: f9a2 : 840f ANDA #$0F ; AB=0Nxx, X=>line Y=acc f9a4 : 1e02 EXG D,Y ; AB=acc, X=>line Y=0Nxx f9a6 : 58 ASLB f9a7 : 49 ROLA f9a8 : 58 ASLB f9a9 : 49 ROLA f9aa : 58 ASLB f9ab : 49 ROLA f9ac : 58 ASLB f9ad : 49 ROLA ; AB=acc*16, X=>line, Y=0Nxx f9ae : 1e12 EXG X,Y ; AB=acc*16, X=0Nxx, Y=>line f9b0 : 1e01 EXG D,X ; AB=0Nxx, X=acc*16, Y=>line f9b2 : 1e89 EXG A,B ; AB=xx0N, X=acc*16, Y=>line f9b4 : 3a ABX ; AB=xx0N, X=acc*16+N, Y=>line f9b5 : 1e12 EXG X,Y ; AB=xx0N, X=>line, Y=acc*16+N f9b7 : 20d5 BRA RD_HEXLP ; Move to next character ; Skip parameter word ; =================== ; On entry, X=>command line ; On exit, X=>first non-space character after current parameter word ; A=first non-space character f9b9 : SKIPWORD: f9b9 : a680 LDA ,X+ ; Step past parameter f9bb : 8121 CMPA #'!' f9bd : 24fa BCC SKIPWORD f9bf : 301f LEAX -1,X ; Step back, then skip spaces ; Skip spaces ; =========== ; On entry, X=>command line ; On exit, X=>first non-space character ; A=first non-space character f9c1 : SKIPSPC: f9c1 : a680 LDA ,X+ f9c3 : 8120 CMPA #' ' f9c5 : 27fa BEQ SKIPSPC ; Skip space characters f9c7 : RD_HEXDONE: f9c7 : 301f LEAX -1,X ; Point to non-hex/non-space char f9c9 : 8121 CMPA #'!' ; Return CS if no following character IF VERSION*16+BUILD>$1050 f9cb : SEND_END: ENDIF f9cb : 39 RTS ; ********************** ; MOS Interface Routines ; ********************** ; OSCLI - Execute command ; ======================= ; On entry: X=>command string ; On exit: A holds any return value ; ; First check for local commands, then pass on to host ; f9cc : CLI: f9cc : 347c PSHS B,DP,X,Y,U ; Save everything on caller's stack, except A and CC IF VERSION*16+BUILD<$1060 LEAU -8,S ; Make a note of caller's stack with space for calls ELSE f9ce : 1f43 TFR S,U ; Make a note of caller's stack with space for calls ENDIF IF WORKSP < $0100 CMPS #CLISTK ; Check where the stack is BCS CLI_SYSSTK1 ; We're already using internal stack ELSE f9d0 : 118cff00 CMPS #BOTSTK ; Check where the stack is f9d4 : 2404 BCC CLI_SYSSTK1 ; We're already using internal stack ENDIF f9d6 : 10ceff60 LDS #CLISTK ; Use internal stack f9da : CLI_SYSSTK1: ; As a *command may result in data transfer, that data may end up overwriting ; a stack in user memory, so use a temporary stack to do OS_CLI. If OS_CLI ; ends up jumping to a new process, a new stack will need to be be set up by ; that new process. There is space on the CLISTK for about seven recursive ; OS_CLI calls. f9da : 3440 PSHS U ; Save caller's stack pointer f9dc : 8d13 BSR CLI_GO ; Process the *command f9de : 3540 PULS U ; Get caller's stack pointer back IF VERSION*16+BUILD<$1060 LEAS 8,U ; Restore caller's stack ELSE f9e0 : 1f34 TFR U,S ; Restore caller's stack ENDIF f9e2 : 35fc PULS B,DP,X,Y,U,PC ; Restore everything and return contents of A. ; Local *commands ; --------------- f9e4 : CLI_TABLE: f9e4 : 474f FCC "GO" f9e6 : 80 FCB $80 f9e7 : 48454c50 FCC "HELP" f9eb : 81 FCB $81 f9ec : 52554e FCC "RUN" f9ef : 82 FCB $82 f9f0 : 00 FCB 0 ; OSCLI - Check for local commands ; -------------------------------- ; On entry: X=>command string ; f9f1 : CLI_GO: f9f1 : CLI_LP1: f9f1 : 8dce BSR SKIPSPC ; Skip leading spaces f9f3 : a680 LDA ,X+ f9f5 : 812a CMPA #'*' f9f7 : 27f8 BEQ CLI_LP1 ; Skip leading '*'s f9f9 : 301f LEAX -1,X f9fb : 3410 PSHS X ; Save start of command text f9fd : 812f CMPA #'/' ; Skip to parameters for '*/name' and '*/ name' f9ff : 2770 BEQ CMD_SLASH fa01 : 8db6 BSR SKIPWORD ; Step past command fa03 : bfff86 STX LPTR ; Point LPTR to command parameters fa06 : 108ef9e4 LDY #CLI_TABLE ; Point to command table fa0a : CLI_LOOP0: fa0a : aee4 LDX ,S ; Get start of command text back fa0c : a684 LDA ,X ; Get first character fa0e : 8141 CMPA #'A' fa10 : 256a BCS CLI_TUBE ; Not a letter, pass to host fa12 : CLI_LOOP2: fa12 : a680 LDA ,X+ ; Get character from command line fa14 : 84df ANDA #$DF ; Force to upper case fa16 : a1a0 CMPA ,Y+ ; Compare with table entry fa18 : 27f8 BEQ CLI_LOOP2 ; Characters match, check next fa1a : a6a2 LDA ,-Y ; Step to command token fa1c : 2b16 BMI CLI_MATCH ; Match fa1e : a61f LDA -1,X ; Get character from command line fa20 : 812e CMPA #'.' fa22 : 270a BEQ CLI_DOT ; Abbreviated command fa24 : CLI_NEXT: fa24 : a6a0 LDA ,Y+ ; Search for command token fa26 : 2afc BPL CLI_NEXT ; Step to end of table entry fa28 : a6a4 LDA ,Y fa2a : 26de BNE CLI_LOOP0 ; Not end of table fa2c : 204e BRA CLI_TUBE ; Pass to host fa2e : CLI_DOT: fa2e : a6a0 LDA ,Y+ ; Search for command token fa30 : 2afc BPL CLI_DOT ; Step to end of table entry fa32 : 2006 BRA CLI_MATCH2 fa34 : CLI_MATCH: fa34 : e682 LDB ,-X ; Get current character fa36 : c121 CMPB #'!' fa38 : 2442 BCC CLI_TUBE ; Command line longer than table entry fa3a : CLI_MATCH2: fa3a : 8181 CMPA #$81 fa3c : 2730 BEQ CMD_HELP fa3e : 2433 BCC CMD_RUN ; *GO ; parameters ; ----------------------- fa40 : CMD_GO: fa40 : bdf9c1 BSR SKIPSPC fa43 : 10beff90 LDY PROGRAM ; Default to re-enter current program fa47 : 810d CMPA #13 fa49 : 2718 BEQ CLI_GO2 ; *GO - enter current program fa4b : 813b CMPA #';' fa4d : 2712 BEQ CLI_GO1 ; *GO ;params - enter current program fa4f : bdffa1 JSR SCANHEX ; Get hex address fa52 : 2428 BCC CLI_TUBE ; Malformed hex address, pass to host fa54 : bdf9c1 BSR SKIPSPC fa57 : 813b CMPA #';' ; Check for ';' parameter marker fa59 : 2706 BEQ CLI_GO1 ; *GO ;params or *GO ;params fa5b : 810d CMPA #13 fa5d : 261d BNE CLI_TUBE ; *GO ... or *GO .... fa5f : 301f LEAX -1,X ; Balance following 1,X fa61 : CLI_GO1: fa61 : 3001 LEAX 1,X ; Step past ';' fa63 : CLI_GO2: fa63 : bfff86 STX LPTR ; Save pointer to command parameters fa66 : 3510 PULS X ; Drop old line pointer fa68 : 1f21 TFR Y,X ; X=entry address fa6a : 1a01 ORCC #$01 ; Set Carry to indicate OSCLI fa6c : 2023 BRA EXECUTE2 ; *HELP () ; --------------- fa6e : CMD_HELP: fa6e : bdf97e JSR PR_HELP ; Print banner as help message ; Fall through to CLI_TUBE, harmlessly updating LPTR ; *RUN - updates LPTR to point to correct parameters ; -------------------------------------------------------------------------- fa71 : CMD_SLASH: fa71 : 3001 LEAX 1,X ; Step past '/' fa73 : CMD_RUN: fa73 : bdf9c1 BSR SKIPSPC fa76 : bdf9b9 BSR SKIPWORD ; Step past *RUN filename fa79 : bfff86 STX LPTR ; Update LPTR to parameters ; OSCLI - Send command line to host ; ================================= ; On entry: stacked X=>command string ; LPTR=>command parameters, prepared for EXECUTE ; On exit: All registers possibly corrupted ; Registers should be preserved by calling code ; ; Tube data: $02 string $0D -- $7F or $80 ; fa7c : CLI_TUBE: fa7c : 3510 PULS X ; Get command string back fa7e : 8602 LDA #2 fa80 : bdfd51 JSR SendCommand ; Send command $02 = OSCLI fa83 : bdfcf5 JSR SEND_STR ; Send string at X fa86 : CLI_WAIT1: fa86 : 1a01 ORCC #$01 ; Set Carry to indicate OSCLI fa88 : CLI_WAIT: fa88 : bdfd65 JSR WaitByte ; Wait for result via Tube R2 (preserves Cy) ; Data transfer may happen while waiting fa8b : CLI_CHECK: fa8b : 4d TSTA ; Check return code fa8c : 2a51 BPL CLI_DONE ; Nothing to execute, return ; EXECUTE - Enter code at ADDRESS ; =============================== ; Checks for possible code header, makes code current PROGRAM. ; On entry, ADDRESS=code entry address ; CS=entering from OSCLI ; CC=entering from RESET ; ; If code in high memory, MEMTOP moved to below code. ; If code returns, MEMTOP and PROGRAM restored to previous value. ; ; If code has a header it is entered with A=1. If not, it is entered with A=0. ; Code has a small initial stack with 100 bytes available on it (eg 50 subroutine ; calls) unless OSCLI calls OSCLI recursively. If the code calls OSINIT it ; becomes the current program and is re-entered at soft reset. Code that becomes ; the current program must set up their own stack in user space. ; ; If called from RESET and not 6809 code, error not reported, jumps directly ; to CLICOM. In future this is the point where a disk operating system would ; be checked for and booted. ; fa8e : EXECUTE: fa8e : beff8c LDX ADDRESS ; Get transfer address, note: big-endian fa91 : EXECUTE2: fa91 : 3401 PSHS CC ; Save RESET/OSCLI flag fa93 : 1f12 TFR X,Y ; Save address in Y fa95 : e607 LDB 7,X ; Get (C) offset fa97 : 3a ABX ; X=>(C) string fa98 : cefaec LDU #EXEC_CHK+4 ; U=>check string fa9b : c604 LDB #4 ; 4 bytes to check fa9d : EXEC_LP: fa9d : a680 LDA ,X+ ; Get byte from header fa9f : a1c2 CMPA ,-U ; Compare with check string faa1 : 263d BNE EXEC_JUMP ; No match, enter as raw code faa3 : 5a DECB faa4 : 26f7 BNE EXEC_LP ; Loop to check all four bytes faa6 : a626 LDA 6,Y ; Get code type faa8 : 48 ASLA ; Check b6 by moving it into b7 faa9 : 2a41 BPL ERR_NOTCODE faab : 841e ANDA #2*15 ; Byte has been moved up, so mask and compare with 2*n faad : 8106 CMPA #2*3 faaf : 263b BNE ERR_NOT6809 IF FALSE LDA ,Y ; Get entry opcode. Check if 6809 BRA or JMP to ADDA #2 ; filter out 68000 code with ROMTYPE=3 ANDA #$5D ; Error if not 6809 BRA or JMP BNE ERR_NOT6809 ENDIF fab1 : 301c LEAX -4,X fab3 : bfff82 STX FAULT ; Point FAULT to (C) string (should be version string) fab6 : feff90 LDU PROGRAM fab9 : beff8a LDX MEMTOP fabc : 3502 PULS A ; Get RESET/OSCLI flag to A fabe : 3450 PSHS X,U ; Save current MEMTOP and PROGRAM fac0 : 108c8000 CMPY #$8000 fac4 : 2504 BCS EXEC_ENTER ; Entering code in low memory, leave MEMTOP where it is fac6 : 10bfff8a STY MEMTOP ; Entering in high memory, put MEMTOP below entered code faca : EXEC_ENTER: faca : 10bfff8e STY TRANSFER ; Set as last entered code face : beff86 LDX LPTR ; X=>command line IF VERSION*16+BUILD<$1060 LDU 6,S ; U=>caller's stack *BUG* Faulty if not called from OSCLI ENDIF fad1 : 46 RORA ; Move RESET/OSCLI flag back into Carry fad2 : 8601 LDA #1 ; A=1 for code with a header fad4 : ada4 JSR ,Y ; Call program execution address fad6 : 3560 PULS Y,U fad8 : 10bfff8a STY MEMTOP ; Restore previous MEMTOP if code returns fadc : ffff90 STU PROGRAM ; Restore previous PROGRAM fadf : CLI_DONE: fadf : 39 RTS ; Return fae0 : EXEC_JUMP: fae0 : beff86 LDX LPTR ; X=>command line IF VERSION*16+BUILD<$1060 LDU 3,S ; U=>caller's stack *BUG* Faulty if not called from OSCLI ENDIF fae3 : 4f CLRA ; A=0 for raw code fae4 : 3501 PULS CC ; Get RESET/OSCLI flag fae6 : 6ea4 JMP ,Y ; Enter raw code fae8 : EXEC_CHK: fae8 : 294328 FCC ")C(" ; Deliberately backwards so doesn't match itself faeb : 00 FCB 0 faec : ERR_NOTCODE: ; PULS CC ; Get RESET/OSCLI flag ; LBCC CLICOM ; If called from RESET, drop straight into Supervisor ; JSR COM_BRKV ; SWI ; FCB 249 ; FCC "Not code" ; FCB 0 faec : ERR_NOT6809: faec : 3501 PULS CC ; Get RESET/OSCLI flag faee : 102404c7 LBCC CLICOM ; If called from RESET, drop straight into Supervisor ; Here is where we would check if this is hard reset, ; and look for a disk operating system to boot instead. faf2 : bdf8e6 JSR COM_BRKV ; Error handler may have been overwritten, so set up faf5 : 3f SWI ; Supervisor error handler faf6 : f9 FCB 249 faf7 : 4e6f7420363830.. FCC "Not 6809 code" fb04 : 00 FCB 0 ; OSRDCH - Wait for character from input stream ; ============================================= ; On exit: A=char, Cy=carry ; fb05 : RDCH: fb05 : RDCH_RAW: fb05 : bdfd65 JSR WaitByte ; Wait for character fb08 : 3402 PSHS A ; Save character fb0a : b6ff80 LDA >ESCFLG ; Get Escape flag fb0d : 48 ASLA ; Copy b7 of ESCFLG to Carry fb0e : 3502 PULS A ; Get character back fb10 : BYTE_DONE: fb10 : 39 RTS ; OSRDCH_IO - Request character via Tube API ; ========================================== ; Tube data: $00 -- Carry Char ; ; On exit: A=char, Cy=carry ; fb11 : RDCH_IO: fb11 : 4f CLRA fb12 : bdfd51 JSR SendCommand ; Send command $00 - OSRDCH fb15 : WAIT_CHAR: fb15 : bdfd65 JSR WaitByte ; Get returned byte fb18 : 48 ASLA ; Move b7 of ESCFLG to Carry fb19 : 7efd65 JMP WaitByte ; Jump to get character ; OSBYTE ; ====== ; On entry: A,X,Y=OSBYTE parameters ; On exit: A preserved ; If A<$80, X=returned value ; If A>$7F, X, Y, Carry=returned values ; ; Tube data: $04 X A -- X ; $06 X Y A -- Cy Y X ; fb1c : BYTE: fb1c : 3406 PSHS A,B fb1e : 4d TSTA fb1f : 2b2a BMI BYTE_HI fb21 : 8604 LDA #4 fb23 : bdfd51 JSR SendCommand ; Send command $04 - short BYTE fb26 : 1f10 TFR X,D ; B=X fb28 : bdfd39 JSR SendByteB ; Send second parameter from B fb2b : 3506 PULS A,B fb2d : 3406 PSHS A,B fb2f : bdfd3b JSR SendByte ; Send first parameter fb32 : bdfd65 JSR WaitByte ; Wait for response fb35 : 1f89 TFR A,B ; Move result to low byte fb37 : 4f CLRA ; Ensure AB is only 8-bit value fb38 : 1f01 TFR D,X fb3a : 3586 PULS A,B,PC ; OSFSC ; ===== ; On entry: A,X,Y=OSFSC parameters ; NB: Only implemented for A>$7F ; On exit: A preserved ; X, Y, Carry=returned values ; ; Tube data: $18 X Y A -- Cy Y X ; fb3c : FSC: fb3c : 3406 PSHS A,B fb3e : 8618 LDA #$18 ; Set command $18 - FSC fb40 : 2015 BRA BYTE_CMD ; Jump to send command fb42 : BYTE_WAIT: fb42 : 8ef816 LDX #BANNER ; Point LPTR to fb45 : bfff86 STX LPTR fb48 : 7efa86 BRA CLI_WAIT1 ; Wait for program start ; OSBYTE >$7F ; ----------- fb4b : BYTE_HI: fb4b : 8182 CMPA #$82 ; A bit of optimisation fb4d : 2506 BCS BYTE_HI1 ; <$82, not a memory OSBYTE fb4f : 2737 BEQ MEM82 ; =$82, fetch address high word fb51 : 8185 CMPA #$85 fb53 : 2535 BCS MEM83 ; <$85, fetch low/high memory limit fb55 : BYTE_HI1 fb55 : 8606 LDA #6 fb57 : BYTE_CMD: fb57 : bdfd51 JSR SendCommand ; Send command fb5a : 1f10 TFR X,D ; B=X - second parameter fb5c : bdfd39 JSR SendByteB ; Send second parameter from B fb5f : bdfd37 JSR SendByteY ; Send third parameter from Y fb62 : 3506 PULS A,B fb64 : bdfd3b JSR SendByte ; Send first parameter fb67 : 819d CMPA #$9D ; Was it fast BPUT? fb69 : 27a5 BEQ BYTE_DONE ; Don't wait for response fb6b : 818e CMPA #$8E ; Was it start language? fb6d : 27d3 BEQ BYTE_WAIT ; Wait for program start fb6f : 3406 PSHS A,B fb71 : bdfd65 JSR WaitByte ; Wait for response fb74 : 48 ASLA ; Move b7 into carry fb75 : 3401 PSHS CC ; Save flags fb77 : bdfd65 JSR WaitByte ; Wait for response fb7a : 1f89 TFR A,B ; Move result to low byte fb7c : 4f CLRA ; Ensure AB is only 8-bit value fb7d : 1f02 TFR D,Y ; Return result in Y fb7f : bdfd65 JSR WaitByte ; Wait for response, high byte still in B fb82 : 1e89 EXG A,B ; Swap so high byte is Y, low byte is fetched byte fb84 : 1f01 TFR D,X ; Return result in X is returned Y*256+X value fb86 : 3587 PULS CC,A,B,PC ; Get flags, A and B back and return fb88 : MEM82: fb88 : 8688 LDA #$88 fb8a : MEM83: fb8a : MEM84: fb8a : 48 ASLA ; A=16,8,10 fb8b : 8eff82 LDX #MEMBOT-6 ; Point to addresses fb8e : ec86 LDD A,X ; Fetch address value fb90 : 1f01 TFR D,X ; Return X=address fb92 : 1f89 TFR A,B ; Copy top byte to bottom byte fb94 : 4f CLRA ; Clear top byte fb95 : 1f02 TFR D,Y ; Return Y=address DIV 256 fb97 : 3586 PULS A,B,PC ; OSWORD ; ====== ; On entry: A=OSWORD number ; X=>control block ; fb99 : WORD: fb99 : 4d TSTA fb9a : 274b BEQ RDLINE ; Jump with OSWORD 0 - RDLINE ; OSWORD <>&00 ; ------------ ; Tube data: &08 function in_length block out_length -- block ; fb9c : 3426 PSHS A,B,Y ; Save A, B and Y fb9e : 3410 PSHS X ; Save X=>control block fba0 : 1f89 TFR A,B ; B=function fba2 : 8608 LDA #$08 fba4 : bdfd51 JSR SendCommand ; Send command $08 - OSWORD fba7 : bdfd39 JSR SendByteB ; Send OSWORD function from B fbaa : 5d TSTB ; Check OSWORD function fbab : 2b0a BMI WORD_SEND ; Jump to send control block with functions>&7F fbad : WORD_TXLO: fbad : 8610 LDA #$10 ; Default SendBlock length fbaf : c115 CMPB #$15 ; Check OSWORD function fbb1 : 2406 BCC WORD_SEND1 ; Use 16 bytes for OSWORD &15 to &7F fbb3 : 8efc16 LDX #WORDTX-1 ; X=>send length table for OSWORD 1 to &14 fbb6 : 3a ABX ; X=X+B, X=>send length fbb7 : WORD_SEND: fbb7 : a684 LDA ,X ; Get block length from control block or table fbb9 : WORD_SEND1: fbb9 : 1f89 TFR A,B ; B=control block length fbbb : aee4 LDX ,S ; Get X=>control block back fbbd : bdfd39 JSR SendByteB ; Send outward block length fbc0 : 5a DECB fbc1 : 2b04 BMI WORD_NOTX ; Only send length 1 to 128 fbc3 : 5c INCB fbc4 : bdfcfe JSR SEND_BLOCK ; B=length, X=>block, returns B=0, X=>block fbc7 : WORD_NOTX: fbc7 : e662 LDB 2,S ; Get OSWORD function fbc9 : 2b0a BMI WORD_RECV ; Jump to send control block with function>&7F fbcb : WORD_RXLO: fbcb : 8610 LDA #$10 ; Default ReceiveBlock length fbcd : c115 CMPB #$15 ; Check OSWORD function fbcf : 2406 BCC WORD_RECV1 ; Use 16 bytes for OSWORD &15 to &7F fbd1 : 8efc29 LDX #WORDRX-2 ; X=>receive length table fbd4 : 3a ABX ; X=X+B, X=>receive length for OSWORD 1 to &14 fbd5 : WORD_RECV: fbd5 : a601 LDA 1,X ; Get receive length from table or control block fbd7 : WORD_RECV1: fbd7 : 1f89 TFR A,B ; B=send block length fbd9 : 3510 PULS X ; Get X=>control block back fbdb : bdfd39 JSR SendByteB ; Send inward block length fbde : 5a DECB fbdf : 2b04 BMI WORD_NORX ; Only receive length 1 to 128 fbe1 : 5c INCB fbe2 : bdfd08 JSR WAIT_BLOCK ; Wait for returned control block fbe5 : WORD_NORX: fbe5 : 35a6 PULS A,B,Y,PC ; Restore A,B,Y and return ; OSWORD 0 - Read a line of text ; ------------------------------ ; On entry: X=>addr.hi, addr.lo, maxlen, charlo, charhi ; On exit: Cy=0: Ok, Cy=1: Escape ; Y=length of returned string in buffer at addr ; ; Note: Address of text string in control block is local big-endian address ; All other OSWORD calls use little-endian addresses to match Host ; ; Tube data: $0A block -- $FF or $7F string $0D ; fbe7 : RDLINE: fbe7 : 860a LDA #10 fbe9 : bdfd51 JSR SendCommand ; Send Command $0A - RDLINE fbec : 3404 PSHS B fbee : 3002 LEAX 2,X ; X=X+2, point to parameters fbf0 : c603 LDB #3 fbf2 : bdfcfe JSR SEND_BLOCK ; Send 3-byte control block fbf5 : 8607 LDA #7 fbf7 : bdfd3b JSR SendByte ; Send $0700 fbfa : bdfd39 JSR SendByteB ; Send $00 as B=0 from SEND_BLK fbfd : bdfd65 JSR WaitByte ; Wait for response fc00 : 48 ASLA ; Move b7 into Carry fc01 : 250d BCS RD_DONE fc03 : ae83 LDX ,--X ; Get text pointer from control block ; CLRB ; B=number received - B already zero from SEND_BLOCK fc05 : RD_STR: fc05 : bdfd65 JSR WaitByte ; Wait for byte from Tube fc08 : a780 STA ,X+ ; Store in text buffer, increment X fc0a : 5c INCB ; Increment character count fc0b : 810d CMPA #13 ; Check current byte fc0d : 26f6 BNE RD_STR ; Loop until fc0f : 5a DECB ; Decrement character count to balance ; ANDCC #$FE ; Clear carry (already CC from CMPA #13) fc10 : RD_DONE: fc10 : 8600 LDA #0 ; Clear A without clearing Carry fc12 : 1f02 TFR D,Y ; Y=length fc14 : 3504 PULS B ; Restore B fc16 : 39 RTS ; Table of OSWORD control block lengths for &01-&14 ; ------------------------------------------------- fc17 : WORDTX: fc17 : 0005000504 FCB $00,$05,$00,$05,$04 fc1c : 05080e0401 FCB $05,$08,$0E,$04,$01 fc21 : 0105001020 FCB $01,$05,$00,$10,$20 fc26 : 100d000880 FCB $10,$0D,$00,$08,$80 fc2b : WORDRX: fc2b : 0500050005 FCB $05,$00,$05,$00,$05 fc30 : 0000000509 FCB $00,$00,$00,$05,$09 fc35 : 0500081900 FCB $05,$00,$08,$19,$00 fc3a : 010d800880 FCB $01,$0D,$80,$08,$80 ; OSARGS - Read info on open file ; =============================== ; On entry: A=action ; X=>data (little-endian) ; Y=handle ; On exit: A=returned value ; X preserved ; X=>any returned data ; Y preserved ; ; Tube Data: $0C handle block function -- result block ; fc3f : ARGS: fc3f : 3426 PSHS A,B,Y ; Save handle, B reg, and function fc41 : 860c LDA #$0C fc43 : bdfd51 JSR SendCommand ; Send command $0C - OSARGS fc46 : bdfd37 JSR SendByteY ; Send handle IF BIGENDIAN fc49 : 5f CLRB ; Point to first byte of word to send fc4a : bdfd12 JSR SEND_WORDS ; Send four-byte control block ELSE LDB #4 ; Four bytes to send JSR SEND_BLOCK ; Send four-byte control block ENDIF fc4d : 3502 PULS A ; Get action back fc4f : bdfd3b JSR SendByte ; Send action fc52 : bdfd65 JSR WaitByte ; Wait for returned result fc55 : 3402 PSHS A ; Save result IF BIGENDIAN fc57 : 5f CLRB ; Point to first byte of word to read fc58 : bdfd24 JSR WAIT_WORDS ; Wait for four-byte control block ELSE LDB #4 ; Four bytes to read JSR WAIT_BLOCK ; Wait for four-byte control block ENDIF fc5b : 35a6 PULS A,B,Y,PC ; Get result and original handle back, and return ; OSBGET - Get a byte from open file ; ================================== ; On entry: Y=handle ; On exit: A=byte Read ; Y=preserved ; Cy set if EOF ; ; Tube data: $0E handle -- Carry byte ; fc5d : BGet: fc5d : 3404 PSHS B fc5f : 860e LDA #$0E fc61 : bdfd51 JSR SendCommand ; Send command $0E - OSBGET fc64 : bdfd37 JSR SendByteY ; Send handle fc67 : 3504 PULS B fc69 : 7efb15 JMP WAIT_CHAR ; Wait for Carry, Byte ; OSBPUT - Put a byte to an open file ; =================================== ; On entry: A=byte to write ; Y=handle ; On exit: A=preserved ; Y=preserved ; ; Tube data: $10 handle byte -- $7F ; fc6c : BPut: fc6c : 3406 PSHS A,B ; Save byte and B fc6e : 8610 LDA #$10 fc70 : bdfd51 JSR SendCommand ; Send command $10 - OSBPUT fc73 : bdfd37 JSR SendByteY ; Send handle fc76 : 3506 PULS A,B ; Get A and B back fc78 : 3406 PSHS A,B fc7a : bdfd3b JSR SendByte ; Send byte to Tube fc7d : bdfd65 JSR WaitByte ; Wait for acknowledgement fc80 : 3586 PULS A,B,PC ; Restore A and B, and return ; OSFIND - Open or Close a file ; ============================= ; On entry: A=function ; Y=handle or X=>filename ; On exit: A=zero or handle ; X,Y preserved ; ; Tube data: $12 function string $0D -- handle ; $12 $00 handle -- $7F ; fc82 : FIND: fc82 : 3406 PSHS A,B ; Save function and B fc84 : 8612 LDA #$12 fc86 : bdfd51 JSR SendCommand ; Send command $12 - OSFIND fc89 : 3506 PULS A,B ; Get A back fc8b : bdfd3b JSR SendByte ; Send function fc8e : 4d TSTA ; Check function fc8f : 2706 BEQ Close ; Jump to deal with Close fc91 : bdfcf5 JSR SEND_STR ; Send string at X fc94 : 7efd65 JMP WaitByte ; Wait for returned handle fc97 : Close: fc97 : 3404 PSHS B fc99 : bdfd37 JSR SendByteY ; Send handle fc9c : bdfd65 JSR WaitByte ; Wait for acknowledgement fc9f : 4f CLRA ; Zero A fca0 : 3584 PULS B,PC ; Restore B and return ; OSFILE - Operate on whole files ; =============================== ; On entry: A=function ; X=>control block ; On exit: A=result ; X preserved ; control block updated ; ; Note: Address of text string in control block is local big-endian address ; ; Tube data: $14 block string function -- result block ; fca2 : FILE: fca2 : 3436 PSHS A,B,X,Y ; Save B,X,Y registers and function in A fca4 : 8614 LDA #$14 fca6 : bdfd51 JSR SendCommand ; Send command $14 - OSFILE fca9 : 3002 LEAX 2,X ; Point to control block contents IF BIGENDIAN fcab : c60c LDB #12 ; Point to first byte to send fcad : bdfd12 JSR SEND_WORDS ; Send 16-byte control block ELSE LDB #16 ; 16 bytes to send JSR SEND_BLOCK ; Send 16-byte control block ENDIF fcb0 : ae83 LDX ,--X ; Get big-endian filename pointer to X fcb2 : bdfcf5 JSR SEND_STR ; Send filename string fcb5 : 3502 PULS A ; Get function back fcb7 : bdfd3b JSR SendByte ; Send function fcba : bdfd65 JSR WaitByte ; Wait for returned result ; ; Data transfer via interupts may happen while waiting fcbd : 3514 PULS B,X ; Restore B, get control block pointer back fcbf : 3406 PSHS A,B ; Save result and B again fcc1 : 3002 LEAX 2,X ; Point to control block contents IF BIGENDIAN fcc3 : c60c LDB #12 ; Point to first byte to read fcc5 : bdfd24 JSR WAIT_WORDS ; Wait for 16-byte control block ELSE LDB #16 ; 16 bytes to read JSR WAIT_BLOCK ; Wait for 16-byte control block ENDIF fcc8 : 301e LEAX -2,X ; Restore X fcca : 35a6 PULS A,B,Y,PC ; Get result, restore registers, and return ; OSGBPB - Multiple byte Read and write ; ===================================== ; On entry: A=function ; X=>control block ; On exit: A=returned value ; control block updated ; ; Tube data: $16 block function -- block Carry result ; fccc : GBPB: fccc : 3426 PSHS A,B,Y ; Save Y and function fcce : 8616 LDA #$16 fcd0 : bdfd51 JSR SendCommand ; Send command $16 - OSGBPB IF BIGENDIAN fcd3 : 3001 LEAX 1,X ; Step past handle fcd5 : c608 LDB #8 ; Point to first byte to send fcd7 : bdfd12 JSR SEND_WORDS ; Send 12-byte control block fcda : a682 LDA ,-X ; Get handle fcdc : bdfd3b JSR SendByte ; Send 0th byte of control block ELSE LDB #13 JSR SEND_BLOCK ; Send 13-byte control block ENDIF fcdf : 3502 PULS A ; Get function back fce1 : bdfd3b JSR SendByte ; Send function IF BIGENDIAN fce4 : 3001 LEAX 1,X ; Step past handle fce6 : c608 LDB #8 ; Point to first byte to read fce8 : bdfd24 JSR WAIT_WORDS ; Read 12-byte control block fceb : bdfd65 JSR WaitByte ; Get 0th byte of control block fcee : a782 STA ,-X ELSE LDB #13 JSR WAIT_BLOCK ; Wait for 13-byte control block ENDIF fcf0 : 3524 PULS B,Y ; Get B and Y back fcf2 : 7efb15 JMP WAIT_CHAR ; Get Carry and result byte ; ***************** ; Tube I/O routines ; ***************** ; Send cr-string at X to Tube ; =========================== fcf5 : SEND_STR: fcf5 : a680 LDA ,X+ ; Get byte from X, increment X fcf7 : 8d42 BSR SendByte ; Send byte via Tube fcf9 : 810d CMPA #13 ; Test current character ; EORA #13 would preserve carry fcfb : 26f8 BNE SEND_STR ; Loop until CR sent fcfd : 39 RTS ; Send block at X to Tube Register 2, B=block length ; ================================================== ; Returns X=preserved, B=0 fcfe : SEND_BLOCK: fcfe : 3a ABX ; X=X+B, X=>after last byte to send fcff : SEND_BLKLP: fcff : a682 LDA ,-X ; Decrement X, get byte from X fd01 : bdfd3b JSR SendByte ; Send byte via Tube fd04 : 5a DECB ; Decrement count of bytes to send fd05 : 26f8 BNE SEND_BLKLP ; Loop until all bytes sent fd07 : 39 RTS ; Wait for block at X from Tube Register 2, B=block length ; ======================================================== ; Returns X=preserved, B=0 fd08 : WAIT_BLOCK: fd08 : 3a ABX ; X=X+B, X=>after last byte to receive fd09 : WAIT_BLKLP: fd09 : bdfd65 JSR WaitByte ; Get byte from Tube fd0c : a782 STA ,-X ; Decrement X, store byte at X fd0e : 5a DECB ; Decrement count of bytes fd0f : 26f8 BNE WAIT_BLKLP ; Loop until all bytes sent fd11 : 39 RTS IF BIGENDIAN ; Send big-endian block at X to Tube Register 2, B=>first word ; ============================================================= ; Returns X=preserved, B<0 fd12 : SEND_WORDS: fd12 : 3a ABX ; X=X+B, X=>first byte to send fd13 : SEND_WDLP: fd13 : a680 LDA ,X+ ; Get byte from X, increment X fd15 : 8d24 BSR SendByte ; Send byte via Tube R2 fd17 : 5a DECB ; Decrement byte count fd18 : c503 BITB #3 fd1a : 26f7 BNE SEND_WDLP ; Loop for four bytes fd1c : 3018 LEAX -8,X ; Point to next word down fd1e : 5d TSTB fd1f : 2af2 BPL SEND_WDLP ; Another word to do fd21 : 3004 LEAX 4,X ; Restore X fd23 : 39 RTS ; Wait for big-endian block at X from Tube Register 2, B=>first word ; ================================================================== ; Returns X=preserved, B<0 fd24 : WAIT_WORDS: fd24 : 3a ABX ; X=X+B, X=>first byte to receive fd25 : WAIT_WDLP: fd25 : bdfd65 JSR WaitByte ; Get byte via Tube R2 fd28 : a780 STA ,X+ ; Store byte at X, increment X fd2a : 5a DECB ; Decrement count of bytes fd2b : c503 BITB #3 fd2d : 26f6 BNE WAIT_WDLP ; Loop for four bytes fd2f : 3018 LEAX -8,X ; Point to next word down fd31 : 5d TSTB fd32 : 2af1 BPL WAIT_WDLP ; Another word to do fd34 : 3004 LEAX 4,X ; Restore X fd36 : 39 RTS ENDIF ; Send byte in Y to Tube via B ; ============================ fd37 : SendByteY: fd37 : 1f20 TFR Y,D ; ; Fall through into SendByteB ; Send byte in B to Tube ; ====================== fd39 : SendByteB: fd39 : 1f98 TFR B,A ; ; Fall through into SendByte ; OSWRCH - Send character in A to Tube ; ==================================== ; On entry, A =character ; On exit, A =preserved fd3b : WRCH: ; ; WRCH is simply SendByte ; ********************** ; Tube Core I/O Routines ; ********************** ; Characters and commands are sent over the same single port. ; Outward commands are escaped, and inward responses are escaped. ; ; Outward ; x VDU x ; esc,esc VDU esc ; esc,n MOS function, control block follows ; ; Inward ; x char/byte x ; esc,esc char/byte esc ; esc,&00 BRK, error number+text+null follows ; esc,<&80 read returned control block set length ; esc,&8n Escape change, b0=new state ; esc,&9x,Y,X,A Event ; esc,&Ax reserved for networking ; esc,&Bx end transfer ; esc,&Cx,addr set address ; esc,&Dx,addr execute address ; esc,&Ex,addr start load from address ; esc,&Fx,addr start save from address ; All commands are data inward, except esc,&Fx which is data outward ; Send byte in A, escaping it if needed ; ===================================== fd3b : SendByte: fd3b : 819b CMPA #esc ; Escape character? fd3d : 2603 BNE SEND_DATA ; No, send raw fd3f : bdfd42 JSR SEND_DATA ; Double escape character fd42 : SEND_DATA: fd42 : 3402 PSHS A ; Save byte fd44 : SEND_WAIT: fd44 : b6fee8 LDA >TxSTATUS fd47 : 8401 ANDA #TxRDY fd49 : 27f9 BEQ SEND_WAIT ; Loop until data can be sent fd4b : 3502 PULS A ; Get byte back fd4d : b7fee9 STA >TxDATA ; Send data fd50 : 39 RTS ; Send an escaped command ; ======================= fd51 : SendCommand: fd51 : 3402 PSHS A ; Save command byte ; Should flush input here fd53 : 869b LDA #esc fd55 : 8deb JSR SEND_DATA ; Send esc prefix fd57 : 3502 PULS A fd59 : baff81 ORA >DMA_TYPE ; Add personality bits fd5c : 20e4 BRA SEND_DATA ; Send command byte ; Check if a byte is waiting, and read it if there ; ================================================ fd5e : BYTE_READ: fd5e : b6fee8 LDA >RxSTATUS fd61 : 8402 ANDA #RxRDY fd63 : 2617 BNE WAIT_EXIT ; Nothing pending, return ; ; Continue into WaitByte ; Wait for a byte, decoding escaped data ; ====================================== ; On exit, A =byte ; F =preserved ; fd65 : WaitByte: fd65 : 3401 PSHS CC ; Save flags fd67 : WaitByteLP: fd67 : bdfd7d JSR WAIT_DATA fd6a : 260e BNE WaitByteOK ; Not esc, return fd6c : bdfd7d JSR WAIT_DATA ; Get another byte fd6f : 2709 BEQ WaitByteOK ; esc,esc, return fd71 : 3474 PSHS X,Y,B,U ; Push all registers fd73 : bdfd8a JSR WAIT_COMMAND ; Decode escaped command fd76 : 3574 PULS X,Y,B,U ; Pop all registers fd78 : 20ed BRA WaitByteLP fd7a : WaitByteOK: fd7a : 3501 PULS CC ; Pop flags fd7c : WAIT_EXIT: fd7c : SendByte2: fd7c : 39 RTS ; Wait for data ; ============= ; On exit, A =byte ; F =Z byte=esc, NZ byte<>esc ; fd7d : WAIT_DATA: fd7d : b6fee8 LDA >RxSTATUS fd80 : 8402 ANDA #RxRDY fd82 : 27f9 BEQ WAIT_DATA ; Loop until data present fd84 : b6fee9 LDA >RxDATA ; Fetch data fd87 : 819b CMPA #esc ; Is it esc prefix? fd89 : 39 RTS ; Decode escaped command ; ====================== ; On entry, A=command ; All registers can be trashed ; fd8a : WAIT_COMMAND: fd8a : 4d TSTA fd8b : 270a BEQ WAIT_ERROR ; esc,&00 - error fd8d : 2b2f BMI WAIT_TRANSFER ; esc,>&7F - data transfer ; esc,1..127 - read a control block ; ================================= ; This depends on MOS calls storing control block address, ; which none of them do for this CPU. ; Just read data and absorb it. ; May think of something else to do with this. ; fd8f : 1f89 TFR A,B ; Move count to low byte of AB fd91 : WAIT_LEN: fd91 : 8dd2 JSR WaitByte ; Wait for a byte fd93 : 5a DECB ; Decrement count of bytes read fd94 : 26fb BNE WAIT_LEN ; Loop to read all bytes fd96 : 39 RTS ; Return to WaitByte ; esc,&00 - error ; =============== fd97 : WAIT_ERROR: fd97 : 10ceff60 LDS #ERRSTK ; Collapse stack fd9b : 8eff00 LDX #ERRBLK ; Point to error buffer fd9e : 863f LDA #$3F ; SWI opcode fda0 : a780 STA ,X+ ; Store SWI opcode fda2 : 8dc1 JSR WaitByte ; Get error number fda4 : a780 STA ,X+ ; Store error number fda6 : FIRQ_R4LP: fda6 : 8dbd JSR WaitByte ; Wait for byte of error string fda8 : a780 STA ,X+ ; Store in error buffer fdaa : 26fa BNE FIRQ_R4LP ; Loop until terminating $00 received ;;;6502 Client pauses at this point ;;;ANFS generates error 0 for 0,"Remoted" when remote starts ;;;NFS generates error 0 for 0,"" when remote starts ;;;Check for 0,0,0 which is error 0,"" fdac : b6ff01 LDA ERRBLK+1 fdaf : baff02 ORA ERRBLK+2 ; Check for error 0,"" fdb2 : 1027fa9e LBEQ STARTUP ; Restart client fdb6 : 8eff01 LDX #ERRBLK+1 ; Point to error block after SWI opcode fdb9 : 3410 PSHS X ; Push error pointer onto stack fdbb : 7effbc JMP OSERROR ; Jump to generate error ; esc,&8n - Escape change ; ======================= fdbe : WAIT_TRANSFER: fdbe : 81c0 CMPA #$C0 fdc0 : 2429 BCC WAIT_START fdc2 : 81a0 CMPA #$A0 fdc4 : 241e BCC WAIT_END fdc6 : 8190 CMPA #$90 fdc8 : 2406 BCC WAIT_EVENT ; %1000xxxE:1 fdca : 44 LSRA ; %01000xxx:E fdcb : 46 RORA ; %E01000xx:x ; Move b0 into b7, b6=0 fdcc : b7ff80 STA >ESCFLG ; Store Escape flag fdcf : 39 RTS ; esc,&9x - Event ; =============== fdd0 : WAIT_EVENT: fdd0 : 8d93 JSR WaitByte ; Get event Y parameter fdd2 : 1f89 TFR A,B fdd4 : 4f CLRA fdd5 : 1f02 TFR D,Y fdd7 : 8d8c JSR WaitByte ; Get event X parameter fdd9 : 1f89 TFR A,B fddb : 4f CLRA fddc : 1f01 TFR D,X fdde : 8d85 JSR WaitByte ; Get event A parameter fde0 : 6e9ffffc JMP [EVENTV] ; Dispatch event ; esc,&Ax - Reserved ; ================== fde4 : WAIT_END: fde4 : 81b0 CMPA #$B0 fde6 : 2594 BCS WAIT_EXIT ; &Ax - Return to WaitByte ; esc,&Bx - End transfer ; ====================== fde8 : 326c LEAS 12,S ; Drop data from stack to fall ; ; out of WaitSave/WaitLoad loop fdea : WAIT_EXIT2: fdea : 39 RTS ; Return to WaitByte ; esc,&C0+ - Start transfer ; ========================= fdeb : WAIT_START: fdeb : 3402 PSHS A ; Save transfer type fded : bdfd65 JSR WaitByte ; Get data address MSB fdf0 : bdfd65 JSR WaitByte ; Get data address fdf3 : bdfd65 JSR WaitByte ; Get data address fdf6 : 1e89 EXG A,B fdf8 : bdfd65 JSR WaitByte ; Get data address LSB fdfb : 1e89 EXG A,B ; D=data address fdfd : 1f01 TFR D,X ; X=data address fdff : 3502 PULS A ; Get transfer type back fe01 : 81d0 CMPA #$D0 fe03 : 251b BCS WAIT_ADDR ; &Cx - set address fe05 : 81e0 CMPA #$E0 fe07 : 2515 BCS WAIT_CODE ; &Dx - enter code fe09 : 81f0 CMPA #$F0 fe0b : 2407 BCC WAIT_SAVE ; &Fx - save data fe0d : WAIT_LOAD: fe0d : bdfd65 JSR WaitByte ; &Ex - load data fe10 : a780 STA ,X+ ; Get byte, store it fe12 : 20f9 BRA WAIT_LOAD ; Loop until terminated fe14 : WAIT_SAVE: fe14 : a680 LDA ,X+ ; Get byte fe16 : bdfd3b JSR SendByte ; Send it fe19 : bdfd5e JSR BYTE_READ ; Poll input for termination fe1c : 20f6 BRA WAIT_SAVE ; Loop until terminated fe1e : WAIT_CODE: fe1e : 6e84 JMP ,X ; Jump directly to code fe20 : WAIT_ADDR: fe20 : bfff8c STX ADDRESS ; Set entry address fe23 : 39 RTS ; Null interupt routines ; ====================== ; OS-9 and FLEX use a timer on IRQ to poll background processes ; fe24 : NULL_RTI: fe24 : RES_HANDLE: fe24 : SWI2_HANDLE: fe24 : SWI3_HANDLE: fe24 : FIRQ_HANDLE: fe24 : IRQ_HANDLE: fe24 : NMI_HANDLE: fe24 : 3b RTI ; SWI - Generate an error ; ======================= 0001 = M6309: EQU 1 ; Check for 6309 CPU fe25 : SWI_HANDLE: IF M6309 fe25 : 11a36a CMPU 10,S ; Compare U with stacked U or stacked PC fe28 : 2602 BNE SWI_6809 ; It's stacked PC, so is not 6309 native mode fe2a : 3262 LEAS 2,S ; Step past stacked W fe2c : SWI_6809: ENDIF fe2c : 326a LEAS 10,S ; Point to stacked PC fe2e : ERR_HANDLE: fe2e : 3510 PULS X ; Pop address of error block after SWI opcode fe30 : bfff82 STX FAULT ; Save pointer to last error fe33 : 1c00 ANDCC #$00 ; Clear all flags, enable interupts fe35 : 6e9ffffa JMP [BRKV] ; Jump to current error handler with X=>error IF WORKSP < ROMSTART ; Default values for WORKSP ; ========================= ORG $FE40 ; Same location as SWTPC VECTORS: FDB RES_HANDLE ; RESV FDB SWI3_HANDLE ; SWI3V FDB SWI2_HANDLE ; SWI2V FDB FIRQ_HANDLE ; FIRQV FDB IRQ_HANDLE ; IRQV DEFSWI: FDB SWI_HANDLE ; SWIV FDB NMI_HANDLE ; NMIV FDB $0000 ; DMA_DONE, PENDA FDB NULL ; EVENTV DEFBRK: FDB COM_ERR ; BRKV FDB NULL ; xxx1V FDB NULL_RTI ; IRQ2V FDB CLI ; CLIV FDB BYTE ; BYTEV FDB WORD ; WORDV FDB WRCH ; WRCHV FDB RDCH ; RDCHV FDB FILE ; FILEV FDB ARGS ; ARGSV FDB BGet ; BGETV FDB BPut ; BPUTV FDB GBPB ; GBPBV FDB FIND ; FINDV ; FDB WARM ; PROGRAM - Program entry address ;DEFBOT:FDB RAMSTART ; MEMBOT - Bottom of user memory ;DEFTOP:FDB RAMEND ; MEMTOP - Top of user memory ; FDB $0000 ; ADDRESS - Tube exectution address ; FDB $0000 ; TRANSFER - Tube transfer address ; FDB BANNER ; LPTR - Command line tail ; FDB $0000 ; CTRL - Control block address ; FCB $00 ; DMA_TYPE - TempA/Client personality ; FDB BANNER ; FAULT - Last error message ; FCB $00 ; ESCFLG - Escape flag ; Vector dispatch ; =============== ORG $FE80 XRES: JMP [RESV] ; $FE80 via $DFC0 or $00C0 XSWI3: JMP [SWI3V] ; $FE84 via $DFC2 or $00C2 XSWI2: JMP [SWI2V] ; $FE88 via $DFC4 or $00C4 XFIRQ: JMP [FIRQV] ; $FE8C via $DFC6 or $00C6 XIRQ: JMP [IRQV] ; $FE90 via $DFC8 or $00C8 XSWI: JMP [SWIV] ; $FE94 via $DFCA or $00CA XNMI: JMP [NMIV] ; $FE98 via $DFCC or $00CC JMP [NMIV+2] ; $FE9C XEVENT: JMP [EVENTV] ; $FEA0 via $DFD0 or $00D0 XBRK: JMP [BRKV] ; $FEA4 via $DFD2 or $00D2 Xxxx1: JMP [xxx1V] ; $FEA8 via $DFD4 or $00D4 ; QUITV? XIRQ2: JMP [IRQ2V] ; $FEAC via $DFD6 or $00D6 XCLI: JMP [CLIV] ; $FEB0 via $DFD8 or $00D8 XBYTE: JMP [BYTEV] ; $FEB4 via $DFDA or $00DA XWORD: JMP [WORDV] ; $FEB8 via $DFDC or $00DC XWRCH: JMP [WRCHV] ; $FEBC via $DFDE or $00DE XRDCH: JMP [RDCHV] ; $FEC0 via $DFE0 or $00E0 XFILE: JMP [FILEV] ; $FEC4 via $DFE2 or $00E2 XARGS: JMP [ARGSV] ; $FEC8 via $DFE4 or $00E4 XBGet: JMP [BGETV] ; $FECC via $DFE6 or $00E6 XBPut: JMP [BPUTV] ; $FED0 via $DFE8 or $00E8 XGBPB: JMP [GBPBV] ; $FED4 via $DFEA or $00EA XFIND: JMP [FINDV] ; $FED8 via $DFEC or $00EC JMP [FINDV+2] ; $FEDC ENDIF ; I/O address space ; ================= fee0 = ORG $FEE0 fee0 : IOADDRS: fee0 : 0000000000000000 FDB 0,0,0,0 fee8 : 0000000000000000 FDB 0,0,0,0 ; Remapped hardware vectors ; ========================= ; BA/BS decoded to toggle address line A8 to map hardware vectors to $FEF0 ; fef0 = ORG $FEF0 fef0 : ROMHIGH: IF WORKSP < ROMSTART FDB XRES ; $FEF0 FDB XSWI3 ; $FEF2 FDB XSWI2 ; $FEF4 FDB XFIRQ ; $FEF6 FDB XIRQ ; $FEF8 FDB XSWI ; $FEFA FDB XNMI ; $FEFC FDB RESET ; $FEFE ELSE fef0 : fe24 RESV: FDB RES_HANDLE ; $FEF0 fef2 : fe24 SWI3V: FDB SWI3_HANDLE ; $FEF2 fef4 : fe24 SWI2V: FDB SWI2_HANDLE ; $FEF4 fef6 : fe24 FIRQV: FDB FIRQ_HANDLE ; $FEF6 fef8 : fe24 IRQV: FDB IRQ_HANDLE ; $FEF8 fefa : fe25 SWIV: FDB SWI_HANDLE ; $FEFA fefc : fe24 NMIV: FDB NMI_HANDLE ; $FEFC fefe : f833 FDB RESET ; $FEFE ENDIF ; Text buffers ; ============ ff00 = ORG $FF00 IF WORKSP > ROMSTART ff00 : ERRBLK: ; Buffer to store host error block ff00 : 00000000000000.. CLIBUF: RMB 128-32 ; Space to enter command line from CLI prompt ff60 : 00000000000000.. CLIEND: RMB 32 ENDIF ff00 = BOTSTK: EQU ERRBLK ; Bottom of internal stack ff60 = ERRSTK: EQU CLIEND ; Internal stack for host errors ff60 = CLISTK: EQU CLIEND ; Internal stack for CLI commands ; as main memory may be overwritten ; Tube system workspace and MOS entry block ; ========================================= ff80 = ORG $FF80 ; Use same addresses as Z80 ff80 : 00 FCB 0 ; $FF80 ; Escape flag ff81 : 00 FCB 0 ; $FF81 ; TempA/Client personality ff82 : f816 FDB BANNER ; $FF82 ; Last error message ff84 : f8c9 DEFERR: FDB COM_ERR ; $FF84 ; Default error handler ff86 : f816 FDB BANNER ; $FF86 ; Command line tail ff88 : 0000 DEFBOT: FDB RAMSTART ; $FF88 ; Bottom of user memory ff8a : f800 DEFTOP: FDB RAMEND ; $FF8A ; Top of user memory ff8c : ffb9 FDB CLICOM ; $FF8C ; Tube execution address ff8e : ffb9 FDB CLICOM ; $FF8E ; Tube transfer address ff90 : ffb9 FDB CLICOM ; $FF90 ; Current program address ff92 : 0000 FDB 0 ; $FF92 ; Memory address high word ff94 : 00 FCB 0 ; $FF94 ; Transfer completion flag ; BBC MOS entry points ; -------------------- ff95 = ORG $FF95 ff95 : 7ef906 JMP >NULL ; &FF95 ; Service ff98 : 7ef833 OSCOLD: JMP >RESET ; &FF98 ; Cold ff9b : 7ef981 PRSTRING: JMP >SEND_TXT ; &FF9B ; Print ASCIIZ text at X ff9e : 7e FCB $7E ; &FF9E ; Force a JMP opcode ff9f : ffee FDB OSWRCH ffa1 : 7ef98a SCANHEX: JMP >RD_HEX ; &FFA1 ; ReadHex ffa4 : 7ef906 DISKACC: JMP >NULL ; &FFA4 ; DiskAccess ffa7 : 7ef906 DISKCPP: JMP >NULL ; &FFA7 ffaa : 7ef95d PRHEX: JMP >PR_HEX1 ; &FFAA ; Print A as 8-bit hex ffad : 7ef953 PR2HEX: JMP >PR_HEX2 ; &FFAD ; Print X as 16-bit hex ffb0 : 7efe24 USERINT: JMP >NULL_RTI ; &FFB0 ; Pass on FIRQs if not Tube FIRQ ffb3 : 7ef974 PRTEXT: JMP >PR_TEXT ; &FFB3 ; Print inline ASCIIZ text ffb6 : 7ef906 JMP >NULL ; &FFB6 ; VecDef/PrntC ffb9 : CLICOM: ffb9 : 7ef88a OSQUIT: JMP >CLILOOP ; &FFB9 ; Quit current process, enter Supervisor ffbc : ERRJMP: ffbc : 7efe2e OSERROR: JMP >ERR_HANDLE; &FFBC ; Generate an error ffbf : INITERR: ffbf : 7ef8ec OSINIT: JMP >ERR_INIT ; &FFBF ; Initialise program environment ffc2 : 7ef906 DISKRST: JMP >NULL ; &FFC2 ; DiskReset ffc5 : 7ef906 JMP >NULL ; &FFC5 ; Deprecated ffc8 : 7ef906 JMP >NULL ; &FFC8 ffcb : 7efb3c JMP >FSC ; &FFCB IF WORKSP > ROMSTART ; MOS file entry points ; --------------------- ffce : 7efc82 OSFIND: JMP >FIND ; $FFCE ffd1 : 7efccc OSGBPB: JMP >GBPB ; $FFD1 ffd4 : 7efc6c OSBPUT: JMP >BPut ; $FFD4 ffd7 : 7efc5d OSBGET: JMP >BGet ; $FFD7 ffda : 7efc3f OSARGS: JMP >ARGS ; $FFDA ffdd : 7efca2 OSFILE: JMP >FILE ; $FFDD ; MOS character entry points ; -------------------------- ffe0 : 7efb05 OSRDCH: JMP >RDCH ; $FFE0 ffe3 : 810d OSASCI: CMPA #13 ; $FFE3 ffe5 : 2607 BNE OSWRCH ffe7 : 860a OSNEWL: LDA #10 ; $FFE7 ffe9 : bdffee JSR OSWRCH ffec : 860d OSWRCR: LDA #13 ; $FFEC ffee : 7efd3b OSWRCH: JMP >WRCH ; $FFEE ; MOS system entry points ; ----------------------- fff1 : 7efb99 OSWORD: JMP >WORD ; $FFF1 fff4 : 7efb1c OSBYTE: JMP >BYTE ; $FFF4 fff7 : 7ef9cc OS_CLI: JMP >CLI ; $FFF7 ; System vectors ; -------------- fffa : f8c9 FDB COM_ERR ; $FFFA - BRKV - Error handler fffc : f906 FDB NULL ; $FFFC - EVENTV - Event vector fffe : f833 L_FFFE: FDB RESET ; $FFFE - Reset vector ; This has to be here otherwise as9 complains ; ------------------------------------------- fffa = BRKV: EQU $FFFA ; $FFFA fffc = EVENTV: EQU $FFFC ; $FFFC fff8 = CLIV: EQU OS_CLI+1 ; $FFF8 fff5 = BYTEV: EQU OSBYTE+1 ; $FFF5 fff2 = WORDV: EQU OSWORD+1 ; $FFF2 ffef = WRCHV: EQU OSWRCH+1 ; $FFEF ffe1 = RDCHV: EQU OSRDCH+1 ; $FFE1 ffde = FILEV: EQU OSFILE+1 ; $FFDE ffdb = ARGSV: EQU OSARGS+1 ; $FFDB ffd8 = BGETV: EQU OSBGET+1 ; $FFD8 ffd5 = BPUTV: EQU OSBPUT+1 ; $FFD5 ffd2 = GBPBV: EQU OSGBPB+1 ; $FFD2 ffcf = FINDV: EQU OSFIND+1 ; $FFCF ffb1 = IRQ2V: EQU USERINT+1 ; $FFB1 ELSE ; File I/O entries ; ---------------- OSFIND: JMP >XFIND ; $FFCE OSGBPB: JMP >XGBPB ; $FFD1 OSBPUT: JMP >XBPut ; $FFD4 OSBGET: JMP >XBGet ; $FFD7 OSARGS: JMP >XARGS ; $FFDA OSFILE: JMP >XFILE ; $FFDD ; Character I/O entries ; --------------------- OSRDCH: JMP >XRDCH ; $FFE0 OSASCI: CMPA #13 ; $FFE3 BNE OSWRCH OSNEWL: LDA #10 ; $FFE7 JSR >OSWRCH OSWRCR: LDA #13 ; $FFEC OSWRCH: JMP >XWRCH ; $FFEE ; MOS entries ; ----------- OSWORD: JMP >XWORD ; $FFF1 OSBYTE: JMP >XBYTE ; $FFF4 OS_CLI: JMP >XCLI ; $FFF7 ; System vectors ; -------------- FDB COM_ERR ; $FFFA - BRKV - Error handler FDB NULL ; $FFFC - EVENTV - Event vector L_FFFE: FDB RESET ; $FFFE - Reset vector ENDIF No errors in pass 2. Wrote binary from address $f800 through $ffff. Total size 2048 bytes.