AS09 Assembler for M6809 [1.40]. Copyright 1994-2005, Frank A. Kingswood Page 1 ---------------------------------------------------------- CLIENT09.SRC ---------------------------------------------------------- 1707 lines read, no errors in pass 1. ; 6809 Tube Client Code ; ===================== ; Copyright (C)1989, 2008, 2012, 2014, 2017 J.G.Harston ; This can be assembled with: ; DOS as9: as9 Client09.src -l now bin > errors.txt ; Kingswood as09: as09-dos -i -lTube09.lst -oTube09.bin Client09.src ; 6809.org.uk asm6809: (not yet checked) ; ; v0.10 1989 JGH: Initial unfinished version. ; v0.20 11-Mar-2008 JGH: Inspired by Johan Heuseveldt to complete ; 12-Mar-2008 JGH: Fixed where A/B was wrong way around in D ; OSBYTE &8E no longer ends with unbalanced stack ; BYTE_HI sends X,Y correct way around ; Internal variables at same address as Z80 ; v0.21 07-Jan-2012 JGH: Added client error handler ; v0.22 20-Nov-2014 DMB: Bugfix in FIRQ code from David Banks ; JGH: Added PRHEX and HR2HEX, execute enters at PROGRAM ; 25-Nov-2014 JGH: Added OSWORD <>0 handler, preparing to merge source ; with 6809 Serial Tube client. Crunched some JSRs to BSRs. ; Shorter FIRQ dispatch code. Moved text buffers to $FF00. ; 28-Nov-2014 JGH: Replaced LDA #0 with CLRA, use returned flags from WAIT_BYTE. ; STARTUP and OSCLI use internal stack. ; MEMTOP moved below code if code is in high memory. ; v0.23 30-Nov-2014 DMB: JSR [,X] should be JSR ,X in EXEC_ENTER. ; JGH: Fixed off-by-one in PR_HEX and preserves A, added PR_STRING. ; PULS reg followed by RTS merged into PULS reg,PC ; 02-Dec-2014 JGH: Implemented KBDTST for 6809 BIOS calls. 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. ; Bugfix: data transfer FIRQs corrupted foreground X and B. ; DMB: Bugfix: EXECUTE should use ADDRESS+2 big-endian address. ; JGH: 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. ; DMB: Bug: Hangs on Ctrl-Break, but not on Soft-Break ; v0.25 20-Dec-2014 JGH: Bugfix: Fixed hang on Ctrl-Break, FIRQ6/7 was wrong way around. ; 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 21-Jun-2017 DMB: Bugfix: Event handler status register was read wrong way. ; 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 25-Jun-2017 JGH: Rolled over to version 1.02. ; 28-Jun-2017 JGH: Added test for 6309 to SWI code, optimised PRHEX routines. ; 16-Jul-2017 JGH: Checking with 6502 Client, only Transfer Type 4 updates ADDRESS. ; Byte/Word transfers check DMA_DONE before doing transfers. ; 25-Jul-2017 DMB: Bugfix: FIRQ6/7 were using signed counter offset. ; JGH: FIRQ execute/transfer addresses now a seperate variable so able ; to rationalise and tidy ADDRHI/ADDR/TRANS/PROG variables. ; 30-Jul-2017 DMB: Swap Sync/EnableIRQ in data transfer. ; 31-Jul-2017 JGH: Slight optimisation to BYTE_HI. ; v1.03 06-Aug-2017 JGH: Rolled over to version 1.03. ; 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. 0105 = VERSION: EQU $0105 ; v1.05 25-Aug-2017 JGH: OSFILE/OSGBPB/OSARGS use big-endian control blocks ; 02-Sep-2017 JGH: PRTEXT preserves X as with Z80 Client. ; 12-Jul-2019 JGH: KBDTST/KBDIN routines use pending input from OSRDCH 0001 = KBDPEND: EQU 1 ; KBDTST/KBDIN pending input 0002 = BUILD: EQU 2 ; 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: plenty of testing 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 this on Matchbox emulated hardware and shown it to work. ; ; Memory layout: ; +-------------+--------------------------------------------------------+ ; | 0000- | vvv User memory vvv | ; | 00C0-00FF | Internal variables if in low RAM | ; | 0100-01FF | Text buffers if in low RAM | ; | | | ; | -F6FF | ^^^ User stack ^^^ | ; | F700-F7BF | Text buffers if in high RAM | ; | F7C0-F7FF | Internal variables if in high RAM | ; | -F7FF | ^^^ User stack if Client in RAM ^^^ | ; +-------------+--------------------------------------------------------+ ; | F800-FFFF | Client ROM, copied to RAM on startup | ; | F800-F815 | 6809 BIOS entry vectors | ; | | | ; | FEE0-FEEF | Tube registers | ; | 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 | ; | -FFF9 | 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). ; START OF ROM CODE ; ================= f800 = ORG $F800 f800 : ROMSTART: 0000 = RAMSTART: EQU $0000 f800 = RAMEND: EQU ROMSTART ; 6809 BIOS entry block always at F800 ; ==================================== f800 = ORG $F800 f800 : f82c COLD: FDB RESET ; $F800 - cold start f802 : f86e WARM: FDB WARMS ; $F802 - warm start IF KBDPEND f804 : f8fc INCH: FDB INCHAR ; $F804 - char input ELSE INCH: FDB OSRDCH ; $F804 - char input ENDIF f806 : f8f7 INCHE: FDB INECHO ; $F806 - char input with echo f808 : f905 INCHECK: FDB KBDTST ; $F808 - test for char input f80a : ffee OUTCH: FDB OSWRCH ; $F80A - char output f80c : f8ec PDATA: FDB PRDAT ; $F80C - output string until EOT f80e : ffe7 PCRLF: FDB OSNEWL ; $F80E - output CR/LF f810 : f8e9 PSTRING: FDB PRTST ; $F810 - output CR/LF then string until EOT f812 : f8e8 LRA: FDB LREAL ; $F812 - Load Real Address f814 : 2058 BRA WARMS ; $F814 - for FLEX compatibility f816 : BANNER: f816 : 0d FCB 13 f817 : 36383039205455.. FCC "6809 TUBE 64K " f825 : 31 FCB ((VERSION >> 8) & 15) + $30 f826 : 2e FCB "." f827 : 30 FCB ((VERSION >> 4) & 15) +$30 f828 : 35 FCB (VERSION & 15) + $30 IF BUILD f829 : 62 FCB BUILD+96 ELSE FCB 32 ENDIF IF DEBUG FCC " DEBUG" ENDIF f82a : 0d00 FCB 13,0 f82c : RESET: f82c : 1a50 ORCC #$50 ; Ensure interupts disabled f82e : 10cef800 LDS #RAMEND ; Put stack at top of RAM IF RAMEND = ROMSTART f832 : 1f41 TFR S,X ; Start copying from start of ROM ELSE LDX #ROMSTART ; Start copying from start of ROM ENDIF f834 : RESETLP1: f834 : ec84 LDD ,X ; Get two bytes from ROM f836 : ed81 STD ,X++ ; Store to RAM and increment X f838 : 8cfec0 CMPX #IOADDRS f83b : 2603 BNE RESETLP2 ; Loop until hit I/O space f83d : 8efef0 LDX #ROMHIGH ; Point to ROM after I/O space f840 : RESETLP2: f840 : 8cff8c CMPX #ADDRESS ; Don't modify ADDRESS and PROG f843 : 2603 BNE RESETLP3 f845 : 8eff94 LDX #DMA_DONE f848 : RESETLP3: f848 : 8c0000 CMPX #0 f84b : 26e7 BNE RESETLP1 ; Copy top part of ROM to RAM f84d : b6fee0 LDA >TUBE1S ; Access I/O registers to page ROM out ; Once ROM is paged out we can do subroutine calls ; as we can now read from stack in RAM ; STARTUP ; ======= ; Tube data: via R1: string $00 -- via R2: $7F or $80 ; f850 : STARTUP: f850 : 1a50 ORCC #$50 ; Disable interupts f852 : 10ceff80 LDS #CLISTK ; Use internal stack f856 : 8d66 BSR MEM_INIT ; Reset user memory limits and error handler f858 : beff90 LDX PROGRAM ; Copy current PROGRAM to ADDRESS f85b : bfff8c STX ADDRESS ; so will re-enter on Soft Break ; At this point, if 6309 could change character at BANNER+2 and PROMPT+1 f85e : 1c00 ANDCC #$00 ; Clear all flags, enable interupts f860 : bdf960 JSR PR_HELP ; Print banner via Tube WRCH protocol f863 : bdffe7 JSR OSNEWL ; SEND_TXT will use 7 bytes on stack f866 : 4f CLRA ; Set A to zero ; STA >ESCFLG ; Clear Escape flag ; ECSFLG will have been cleared when copying ROM/initialising workspace f867 : bdffee JSR OSWRCH ; Send terminating zero byte ; This will use 3 bytes on stack f86a : 4f CLRA ; Carry Clear to indicate Reset f86b : bdfa6a JSR CLI_WAIT ; Wait for result byte and enter code ; This will use 14 bytes on stack including data transfer ; Data transfer may happen while waiting ; Fall through to CLICOM if nothing executed ; Supervisor command line prompt ; ============================== ; Allow user to enter *command ; f86e : WARMS: f86e : CLILOOP: f86e : 10ceff80 LDS #CLISTK ; Initially use internal stack f872 : 8d4a BSR COM_INIT ; Reset user memory limits and error handler f874 : 10feff8a LDS MEMTOP ; Reset stack to top of user memory f878 : 8effb9 LDX #CLICOM ; Make CLICOM the current program to re-enter f87b : bfff90 STX PROGRAM ; on soft reset f87e : 1c00 ANDCC #$00 ; Clear all flags, enable interupts f880 : CLILOOP2: f880 : 8ef893 LDX #PROMPT f883 : bdf963 JSR SEND_TXT ; Display prompt ; CLRA ; Set A to zero (SEND_TXT returned A=0) ; LDX #COM_BLK ; Point to control block (SEND_TXT returned X=COM_BLK) f886 : bdfff1 JSR OSWORD ; OSWORD &00 - Read a line of text f889 : 2514 BCS COM_ESC ; Escape pressed f88b : 8eff00 LDX #CLIBUF f88e : bdfff7 JSR OS_CLI ; Execute command f891 : 20ed BRA CLILOOP2 ; Loop back for another line f893 : PROMPT: f893 : 363830393e2a FCC "6809>*" ; Command prompt f899 : 00 FCB 0 f89a : COM_BLK: f89a : ff00 FDB CLIBUF ; Input buffer f89c : 6f FCB CLIEND-CLIBUF-1 ; Buffer size f89d : 20 FCB 32 ; Lowest acceptable CHR$32 f89e : ff FCB 255 ; Highest acceptable CHR$255 f89f : COM_ESC: f89f : 867e LDA #126 f8a1 : bdfff4 JSR OSBYTE ; Acknowledge Escape f8a4 : ESCAPE: f8a4 : 3f SWI f8a5 : 11 FCB 17 f8a6 : 457363617065 FCC "Escape" f8ac : 00 FCB 0 f8ad : COM_ERR: f8ad : 10feff8a LDS MEMTOP ; Reset stack to top of user memory f8b1 : bdffe7 JSR OSNEWL f8b4 : a680 LDA ,X+ ; Step X past error number f8b6 : bdf963 JSR SEND_TXT ; Print text at X f8b9 : bdffe7 JSR OSNEWL f8bc : 20c2 BRA CLILOOP2 ; Return to command prompt f8be : MEM_INIT: f8be : COM_INIT: ; This has already been done by copying ROM to RAM. But, when entering ; Supervisor we want to ensure full memory available. f8be : cc0000 LDD #RAMSTART f8c1 : fdff88 STD MEMBOT ; Initialise bottom of user memory f8c4 : ccf800 LDD #RAMEND f8c7 : fdff8a STD MEMTOP ; Initialise top of user memory f8ca : COM_BRKV: f8ca : ccf8ad LDD #COM_ERR ; Get Supervisor error handler address f8cd : fdfffa STD BRKV ; Set error handler f8d0 : ERR_INIT: f8d0 : 4d TSTA f8d1 : 2606 BNE ERR_INIT2 ; A<>$00, just read values f8d3 : fcff8e LDD TRANSFER ; Set last entered code as current program f8d6 : fdff90 STD PROGRAM f8d9 : ERR_INIT2: f8d9 : ccfe53 LDD #SWI_HANDLE f8dc : fdfefa STD XSWIV ; Point SWI vector to error BRK handler f8df : 8efffa LDX #BRKV f8e2 : 108eff80 LDY #ESCFLG ; Return X=BRKV, Y=ESCFLG, MI=little-endian FS calls IF BIGENDIAN f8e6 : 5f CLRB f8e7 : 4f CLRA ; Return PL=big-endian filing system calls ENDIF f8e8 : PREND: f8e8 : LREAL: f8e8 : 39 RTS ; FLEX/OS-9 BIOS code ; =================== IF KBDPEND f8e9 : bdffe7 PRTST: JSR OSNEWL f8ec : a680 PRDAT: LDA ,X+ ; Get character f8ee : 8104 CMPA #4 ; EOT character? f8f0 : 27f6 BEQ PREND ; End printing f8f2 : bdffee JSR OSWRCH ; Print character f8f5 : 20f5 BRA PRDAT ; Loop to next f8f7 : 8d03 INECHO: BSR INCHAR f8f9 : 7effee JMP OSWRCH f8fc : 8d07 INCHAR: BSR KBDTST f8fe : 27fc BEQ INCHAR ; Loop until character available f900 : 8d25 BSR KBDFLAG ; Clear 'pending character' flag f902 : 8600 _PENDA: LDA #0 ; Get pending character f904 : 39 RTS f903 = PENDA: EQU _PENDA+1 ; Pending character is parameter of LDA ; LDA PENDA ; Get pending character ; RTS f905 : 3436 KBDTST: PSHS D,X,Y ; Save registers f907 : b6ff80 LDA ESCFLG f90a : 8440 ANDA #$40 f90c : 2617 BNE KBDTST2 ; Character pending, return with NE f90e : 8e0000 LDX #0 f911 : 1f12 TFR X,Y f913 : 8681 LDA #$81 f915 : bdfff4 JSR OSBYTE ; INKEY(0) - get any pending character ; Y=$00 - character, X=character ; Y=$1B - escape ; Y=$FF - nothing pending f918 : 1f10 TFR X,D ; B=character f91a : 108c00ff CMPY #$FF f91e : 2705 BEQ KBDTST2 ; Nothing pending, return with EQ f920 : f7f903 STB PENDA f923 : 8d02 BSR KBDFLAG ; Set 'pending character' flag ; Fall through with NE=character pending f925 : KBDTST2: f925 : 35b6 PULS D,X,Y,PC f927 : KBDFLAG: f927 : 3401 PSHS CC f929 : 1a50 ORCC #$50 ; Disable interupts f92b : 8640 LDA #$40 ; Toggle key pending flag f92d : b8ff80 EORA ESCFLG f930 : b7ff80 STA ESCFLG f933 : 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) f935 : PR_2HEX: f935 : 3404 PSHS B ; Save B f937 : 1f10 TFR X,D ; Copy X to D, so copy b8-b15 to A f939 : 8d04 BSR PR_HEX ; Print it f93b : 1f98 TFR B,A ; Copy b0-b7 to A f93d : 3504 PULS B ; Restore B ; Fall through into PR_HEX ; Print A as 2-digit hex ; ====================== ; API allows A to be corrupted ; All other registers preserved f93f : PR_HEX: f93f : 3402 PSHS A ; Standard hex-print code f941 : 44 LSRA f942 : 44 LSRA f943 : 44 LSRA f944 : 44 LSRA f945 : 8d02 BSR PR_NYBBLE f947 : 3502 PULS A ; Get A back ; Fall through into PR_NYBBLE f949 : PR_NYBBLE: f949 : 840f ANDA #$0F f94b : 810a CMPA #$0A f94d : 2502 BCS PR_DIGIT f94f : 8b07 ADDA #7 f951 : PR_DIGIT: f951 : 8b30 ADDA #$30 f953 : 7effee JMP OSWRCH ; Print inline text ; ================= ; On exit: A=$00 ; X= corrupted ; after v1.05 ; X= preserved f956 : PR_TEXT: IF VERSION*16+BUILD>$1050 f956 : 3410 PSHS X ; Save X f958 : ae62 LDX 2,S ; Get stacked PC to X f95a : 8d07 BSR SEND_TXT ; Print text f95c : af62 STX 2,S ; Update stacked PC f95e : 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 ; f960 : PR_HELP: f960 : 8ef816 LDX #BANNER ; Print banner as help message f963 : SEND_TXT: f963 : a680 LDA ,X+ ; Get byte from X, increment X f965 : 2746 BEQ SEND_END ; End if $00 byte f967 : bdffe3 JSR OSASCI ; Send to OSASCI f96a : 20f7 BRA SEND_TXT ; Loop until $00 sent ; ********************** ; 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 ; f96c : RD_HEX: f96c : 108e0000 LDY #0 ; Clear hex accumulator f970 : RD_HEXLP: f970 : a680 LDA ,X+ ; Get current character f972 : 8130 CMPA #$30 ; <'0', exit f974 : 2533 BCS RD_HEXDONE f976 : 813a CMPA #$3A ; '0'..'9', add to accumulator f978 : 250a BCS RD_HEXADD f97a : 84df ANDA #$DF ; Ensure upper case letter f97c : 8007 SUBA #$07 ; Convert letter, if <'A', exit f97e : 2529 BCS RD_HEXDONE f980 : 8140 CMPA #$40 f982 : 2425 BCC RD_HEXDONE ; If >'F', exit f984 : RD_HEXADD: f984 : 840f ANDA #$0F ; AB=0Nxx, X=>line Y=acc f986 : 1e02 EXG D,Y ; AB=acc, X=>line Y=0Nxx f988 : 58 ASLB f989 : 49 ROLA f98a : 58 ASLB f98b : 49 ROLA f98c : 58 ASLB f98d : 49 ROLA f98e : 58 ASLB f98f : 49 ROLA ; AB=acc*16, X=>line, Y=0Nxx f990 : 1e12 EXG X,Y ; AB=acc*16, X=0Nxx, Y=>line f992 : 1e01 EXG D,X ; AB=0Nxx, X=acc*16, Y=>line f994 : 1e89 EXG A,B ; AB=xx0N, X=acc*16, Y=>line f996 : 3a ABX ; AB=xx0N, X=acc*16+N, Y=>line f997 : 1e12 EXG X,Y ; AB=xx0N, X=>line, Y=acc*16+N f999 : 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 f99b : SKIPWORD: f99b : a680 LDA ,X+ ; Step past parameter f99d : 8121 CMPA #'!' f99f : 24fa BCC SKIPWORD f9a1 : 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 f9a3 : SKIPSPC: f9a3 : a680 LDA ,X+ f9a5 : 8120 CMPA #' ' f9a7 : 27fa BEQ SKIPSPC ; Skip space characters f9a9 : RD_HEXDONE: f9a9 : 301f LEAX -1,X ; Point to non-hex/non-space char f9ab : 8121 CMPA #'!' ; Return CS if no following character IF VERSION*16+BUILD>$1050 f9ad : SEND_END: ENDIF f9ad : 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 ; f9ae : CLI: f9ae : 347c PSHS B,DP,X,Y,U ; Save everything on caller's stack, except A and CC f9b0 : 3378 LEAU -8,S ; Make a note of caller's stack with space for calls f9b2 : 118cf800 CMPS #ROMSTART ; Check where the stack is f9b6 : 2404 BCC CLI_SYSSTK1 ; We're already using internal stack f9b8 : 10ceff80 LDS #CLISTK ; Use internal stack f9bc : 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. f9bc : 3440 PSHS U ; Save caller's stack pointer f9be : 8d13 BSR CLI_GO ; Process the *command f9c0 : 3540 PULS U ; Get caller's stack pointer back f9c2 : 3248 LEAS 8,U ; Restore caller's stack f9c4 : 35fc PULS B,DP,X,Y,U,PC ; Restore everything and return contents of A. ; Local *commands ; --------------- f9c6 : CLI_TABLE: f9c6 : 474f FCC "GO" f9c8 : 80 FCB $80 f9c9 : 48454c50 FCC "HELP" f9cd : 81 FCB $81 f9ce : 52554e FCC "RUN" f9d1 : 82 FCB $82 f9d2 : 00 FCB 0 ; OSCLI - Check for local commands ; -------------------------------- ; On entry: X=>command string ; f9d3 : CLI_GO: f9d3 : CLI_LP1: f9d3 : 8dce BSR SKIPSPC ; Skip leading spaces f9d5 : a680 LDA ,X+ f9d7 : 812a CMPA #'*' f9d9 : 27f8 BEQ CLI_LP1 ; Skip leading '*'s f9db : 301f LEAX -1,X f9dd : 3410 PSHS X ; Save start of command text f9df : 812f CMPA #'/' ; Skip to parameters for '*/name' and '*/ name' f9e1 : 2770 BEQ CMD_SLASH f9e3 : 8db6 BSR SKIPWORD ; Step past command f9e5 : bfff86 STX LPTR ; Point LPTR to command parameters f9e8 : 108ef9c6 LDY #CLI_TABLE ; Point to command table f9ec : CLI_LOOP1: f9ec : aee4 LDX ,S ; Get start of command text back f9ee : a684 LDA ,X ; Get first character f9f0 : 8141 CMPA #'A' f9f2 : 256a BCS CLI_TUBE ; Not a letter, pass to host f9f4 : CLI_LOOP2: f9f4 : a680 LDA ,X+ ; Get character from command line f9f6 : 84df ANDA #$DF ; Force to upper case f9f8 : a1a0 CMPA ,Y+ ; Compare with table entry f9fa : 27f8 BEQ CLI_LOOP2 ; Characters match, check next f9fc : a6a2 LDA ,-Y ; Step to command token f9fe : 2b16 BMI CLI_MATCH ; Match fa00 : a61f LDA -1,X ; Get character from command line fa02 : 812e CMPA #'.' fa04 : 270a BEQ CLI_DOT ; Abbreviated command fa06 : CLI_NEXT: fa06 : a6a0 LDA ,Y+ ; Search for command token fa08 : 2afc BPL CLI_NEXT ; Step to end of table entry fa0a : a6a4 LDA ,Y fa0c : 26de BNE CLI_LOOP1 ; Not end of table fa0e : 204e BRA CLI_TUBE ; Pass to host fa10 : CLI_DOT: fa10 : a6a0 LDA ,Y+ ; Search for command token fa12 : 2afc BPL CLI_DOT ; Step to end of table entry fa14 : 2006 BRA CLI_MATCH2 fa16 : CLI_MATCH: fa16 : e682 LDB ,-X ; Get current character fa18 : c121 CMPB #'!' fa1a : 2442 BCC CLI_TUBE ; Command line longer than table entry fa1c : CLI_MATCH2: fa1c : 8181 CMPA #$81 fa1e : 2730 BEQ CMD_HELP fa20 : 2433 BCC CMD_RUN ; *GO ; parameters ; ----------------------- fa22 : CMD_GO: fa22 : bdf9a3 BSR SKIPSPC fa25 : 10beff90 LDY PROGRAM ; Default to re-enter current program fa29 : 810d CMPA #13 fa2b : 2718 BEQ CLI_GO2 ; *GO - enter current program fa2d : 813b CMPA #';' fa2f : 2712 BEQ CLI_GO1 ; *GO ;params - enter current program fa31 : bdffa1 JSR SCANHEX ; Get hex address to Y fa34 : 2428 BCC CLI_TUBE ; Malformed hex address, pass to host fa36 : bdf9a3 BSR SKIPSPC fa39 : 813b CMPA #';' ; Check for ';' parameter marker fa3b : 2706 BEQ CLI_GO1 ; *GO ;params or *GO ;params fa3d : 810d CMPA #13 fa3f : 261d BNE CLI_TUBE ; *GO ... or *GO .... fa41 : 301f LEAX -1,X ; Balance following 1,X fa43 : CLI_GO1: fa43 : 3001 LEAX 1,X ; Step past ';' fa45 : CLI_GO2: fa45 : bfff86 STX LPTR ; Save pointer to command parameters fa48 : 3510 PULS X ; Drop old line pointer fa4a : 1f21 TFR Y,X ; X=entry address fa4c : 1a01 ORCC #$01 ; Set Carry to indicate OSCLI fa4e : 2022 BRA EXECUTE2 ; *HELP () ; --------------- fa50 : CMD_HELP: fa50 : bdf960 JSR PR_HELP ; Print banner as help message ; Fall through to CLI_TUBE, harmlessly updating LPTR ; *RUN - updates LPTR to point to correct parameters ; -------------------------------------------------------------------------- fa53 : CMD_SLASH: fa53 : 3001 LEAX 1,X ; Step past '/' fa55 : CMD_RUN: fa55 : bdf9a3 BSR SKIPSPC fa58 : bdf99b BSR SKIPWORD ; Step past filename fa5b : 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 ; fa5e : CLI_TUBE: fa5e : 3510 PULS X ; Get command string back fa60 : 8602 LDA #2 fa62 : bdfd1c JSR SEND_CMD ; Send command $02 = OSCLI fa65 : bdfcc9 JSR SEND_STR ; Send string at X fa68 : CLI_WAIT1: fa68 : 1a01 ORCC #$01 ; Set Carry to indicate OSCLI fa6a : CLI_WAIT: fa6a : bdfaf1 JSR WAIT_BYTE ; Wait for result via Tube R2 (preserves Cy) ; Data transfer may happen while waiting ; TSTA ; Check return code ; WAIT_BYTE returns flags set from A fa6d : 2a53 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. fa6f : EXECUTE: fa6f : beff8c LDX ADDRESS ; Get execution address, note: big-endian fa72 : EXECUTE2: fa72 : 3401 PSHS CC ; Save RESET/OSCLI flag fa74 : 1f12 TFR X,Y ; Save address in Y fa76 : e607 LDB 7,X ; Get (C) offset fa78 : 3a ABX ; X=>(C) string fa79 : cefad1 LDU #EXEC_CHK+4 ; U=>check string fa7c : c604 LDB #4 ; 4 bytes to check fa7e : EXEC_LP: fa7e : a680 LDA ,X+ ; Get byte from header fa80 : a1c2 CMPA ,-U ; Compare with check string fa82 : 263f BNE EXEC_JUMP ; No match, enter as raw code fa84 : 5a DECB fa85 : 26f7 BNE EXEC_LP ; Loop to check all four bytes fa87 : a626 LDA 6,Y ; Get code type fa89 : 48 ASLA ; Check b6 by moving it into b7 fa8a : 2a45 BPL ERR_NOTCODE fa8c : 841e ANDA #2*15 ; Byte has been moved up, so mask and compare with 2*n fa8e : 8106 CMPA #2*3 fa90 : 263f 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 fa92 : 301c LEAX -4,X fa94 : bfff82 STX FAULT ; Point FAULT to (C) string (should be version string) fa97 : feff90 LDU PROGRAM fa9a : beff8a LDX MEMTOP fa9d : 3502 PULS A ; Get RESET/OSCLI flag to A fa9f : 3450 PSHS X,U ; Save current MEMTOP and PROGRAM faa1 : 108c8000 CMPY #$8000 faa5 : 2504 BCS EXEC_ENTER ; Entering code in low memory, leave MEMTOP where it is faa7 : 10bfff8a STY MEMTOP ; Entering in high memory, put MEMTOP below entered code faab : EXEC_ENTER: faab : 10bfff8e STY TRANSFER ; Set as last entered code faaf : beff86 LDX LPTR ; X=>command line fab2 : ee66 LDU 6,S ; U=>caller's stack fab4 : 46 RORA ; Move RESET/OSCLI flag back into Carry fab5 : 8601 LDA #1 ; A=1 for code with a header fab7 : ada4 JSR ,Y ; Call program execution address fab9 : 3560 PULS Y,U fabb : 10bfff8a STY MEMTOP ; Restore previous MEMTOP if code returns fabf : ffff90 STU PROGRAM ; Restore previous PROGRAM fac2 : NULL: ; Null routines fac2 : CLI_DONE: fac2 : 39 RTS ; Return fac3 : EXEC_JUMP: fac3 : beff86 LDX LPTR ; X=>command line fac6 : ee63 LDU 3,S ; U=>caller's stack fac8 : 4f CLRA ; A=0 for raw code fac9 : 3501 PULS CC ; Get RESET/OSCLI flag facb : 6ea4 JMP ,Y ; Enter raw code facd : EXEC_CHK: facd : 294328 FCC ")C(" ; Deliberately backwards so doesn't match itself fad0 : 00 FCB 0 fad1 : 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 fad1 : ERR_NOT6809: fad1 : 3501 PULS CC ; Get RESET/OSCLI flag fad3 : 102404e2 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. fad7 : bdf8ca JSR COM_BRKV ; Error handler may have been overwritten, so set up fada : 3f SWI ; Supervisor error handler fadb : f9 FCB 249 fadc : 4e6f7420363830.. FCC "Not 6809 code" fae9 : 00 FCB 0 ; OSRDCH - Wait for character from input stream ; ============================================= ; On exit: A=char, Cy=carry ; ; Tube data: $00 -- Carry Char ; faea : RDCH: faea : 4f CLRA faeb : bdfd1c JSR SEND_CMD ; Send command $00 - OSRDCH faee : WAIT_CHAR: faee : 8d01 BSR WAIT_BYTE ; Get returned byte faf0 : 48 ASLA ; Move b7 into Carry ; Fall through to fetch byte from Tube R2 ; Wait for a byte from Tube Register 2 ; ==================================== ; On exit: A=byte read ; PL/MI, EQ/NE set from A ; Other flags preserved ; faf1 : WAIT_BYTE: faf1 : b6fee2 LDA >TUBE2S ; Read Tube R2 Status faf4 : 2afb BPL WAIT_BYTE ; Wait for b7 set faf6 : b6fee3 LDA >TUBE2 ; Get byte from Tube R2 faf9 : BYTE_DONE: faf9 : 39 RTS ; 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 ; fafa : BYTE: fafa : 3406 PSHS A,B fafc : 4d TSTA fafd : 2b23 BMI BYTE_HI faff : 8604 LDA #4 fb01 : bdfd1c JSR SEND_CMD ; Send command $04 - short BYTE fb04 : 1f10 TFR X,D ; B=X fb06 : bdfd1a JSR SEND_BYTEB ; Send second parameter from B fb09 : 3506 PULS A,B fb0b : 3406 PSHS A,B fb0d : bdfd1c JSR SEND_BYTE ; Send first parameter fb10 : 8ddf JSR WAIT_BYTE ; Wait for response fb12 : 1f89 TFR A,B ; Move result to low byte fb14 : 4f CLRA ; Ensure AB is only 8-bit value fb15 : 1f01 TFR D,X fb17 : 3586 PULS A,B,PC fb19 : BYTE_WAIT: fb19 : 8ef816 LDX #BANNER ; Point LPTR to fb1c : bfff86 STX LPTR fb1f : 7efa68 BRA CLI_WAIT1 ; Wait for program start ; OSBYTE >$7F ; ----------- fb22 : BYTE_HI: fb22 : 8182 CMPA #$82 ; A bit of optimisation fb24 : 2506 BCS BYTE_HI1 ; <$82, not a memory OSBYTE fb26 : 2734 BEQ MEM82 ; =$82, fetch address high word fb28 : 8185 CMPA #$85 fb2a : 2532 BCS MEM83 ; <$85, fetch low/high memory limit fb2c : BYTE_HI1: fb2c : 8606 LDA #6 fb2e : bdfd1c JSR SEND_CMD ; Send command $06 - long byte fb31 : 1f10 TFR X,D ; B=X - second parameter fb33 : bdfd1a JSR SEND_BYTEB ; Send second parameter from B fb36 : bdfd18 JSR SEND_BYTEY ; Send third parameter from Y fb39 : 3506 PULS A,B fb3b : bdfd1c JSR SEND_BYTE ; Send first parameter fb3e : 819d CMPA #$9D ; Was it fast BPUT? fb40 : 27b7 BEQ BYTE_DONE ; Don't wait for response fb42 : 818e CMPA #$8E ; Was it start language? fb44 : 27d3 BEQ BYTE_WAIT ; Wait for program start fb46 : 3406 PSHS A,B fb48 : 8da7 JSR WAIT_BYTE ; Wait for response fb4a : 48 ASLA ; Move b7 into Carry fb4b : 3401 PSHS CC ; Save flags fb4d : 8da2 JSR WAIT_BYTE ; Wait for response fb4f : 1f89 TFR A,B ; Move result to low byte fb51 : 4f CLRA ; Ensure AB is only 8-bit value fb52 : 1f02 TFR D,Y ; Return result in Y fb54 : 8d9b JSR WAIT_BYTE ; Wait for response, high byte still in B fb56 : 1e89 EXG A,B ; Swap so high byte is Y, low byte is fetched byte fb58 : 1f01 TFR D,X ; Return result in X as returned Y*256+X value fb5a : 3587 PULS CC,A,B,PC ; Restore flags/A/B and return fb5c : MEM82: fb5c : 8688 LDA #$88 fb5e : MEM83: fb5e : MEM84: fb5e : 48 ASLA ; A=16,8,10 fb5f : 8eff82 LDX #MEMBOT-6 ; Point to addresses fb62 : ec86 LDD A,X ; Fetch address value fb64 : 1f01 TFR D,X ; Return X=address fb66 : 1f89 TFR A,B ; Copy top byte to bottom byte fb68 : 4f CLRA ; Clear top byte fb69 : 1f02 TFR D,Y ; Return Y=address DIV 256 fb6b : 3586 PULS A,B,PC ; OSWORD ; ====== ; On entry: A=OSWORD number ; X=>control block ; fb6d : WORD: fb6d : 4d TSTA fb6e : 274b BEQ RDLINE ; Jump with OSWORD 0 - RDLINE ; OSWORD <>&00 ; ------------ ; Tube data: &08 function in_length block out_length -- block ; fb70 : 3426 PSHS A,B,Y ; Save A, B and Y fb72 : 3410 PSHS X ; Save X=>control block fb74 : 1f89 TFR A,B ; B=function fb76 : 8608 LDA #$08 fb78 : bdfd1c JSR SEND_CMD ; Send command $08 - OSWORD fb7b : bdfd1a JSR SEND_BYTEB ; Send OSWORD function in B fb7e : 5d TSTB ; Check OSWORD function fb7f : 2b0a BMI WORD_SEND ; Jump to send control block with functions>&7F fb81 : WORD_TXLO: fb81 : 8610 LDA #$10 ; Default SendBlock length fb83 : c115 CMPB #$15 ; Check OSWORD function fb85 : 2406 BCC WORD_SEND1 ; Use 16 bytes for OSWORD &15 to &7F fb87 : 8efbea LDX #WORDTX-1 ; X=>send length table fb8a : 3a ABX ; X=X+B, X=>send length fb8b : WORD_SEND: fb8b : a684 LDA ,X ; Get block length from control block or table fb8d : WORD_SEND1: fb8d : 1f89 TFR A,B ; B=control block length fb8f : aee4 LDX ,S ; Get X=>control block back fb91 : bdfd1a JSR SEND_BYTEB ; Send outward block length fb94 : 5a DECB fb95 : 2b04 BMI WORD_NOTX ; Only send length 1 to 128 fb97 : 5c INCB fb98 : bdfcd2 JSR SEND_BLOCK ; B=length, X=>block, returns B=0, X=>block fb9b : WORD_NOTX: fb9b : e662 LDB 2,S ; Get OSWORD function fb9d : 2b0a BMI WORD_RECV ; Jump to send control block with function>&7F fb9f : WORD_RXLO: fb9f : 8610 LDA #$10 ; Default ReceiveBlock length fba1 : c115 CMPB #$15 ; Check OSWORD function fba3 : 2406 BCC WORD_RECV1 ; Use 16 bytes for OSWORD &15 to &7F fba5 : 8efbfd LDX #WORDRX-2 ; X=>receive length table fba8 : 3a ABX ; X=X+B, X=>receive length fba9 : WORD_RECV: fba9 : a601 LDA 1,X ; Get receive length from table or control block fbab : WORD_RECV1: fbab : 1f89 TFR A,B ; B=send block length fbad : 3510 PULS X ; Get X=>control block back fbaf : bdfd1a JSR SEND_BYTEB ; Send inward block length fbb2 : 5a DECB fbb3 : 2b04 BMI WORD_NORX ; Only receive length 1 to 128 fbb5 : 5c INCB fbb6 : bdfcdb JSR WAIT_BLOCK ; Wait for returned control block fbb9 : WORD_NORX: fbb9 : 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 (Y=0 if escape) ; ; 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 ; fbbb : RDLINE: fbbb : 860a LDA #10 fbbd : bdfd1c JSR SEND_CMD ; Send command $0A - RDLINE fbc0 : 3404 PSHS B fbc2 : 3002 LEAX 2,X ; X=X+2, point to parameters fbc4 : c603 LDB #3 fbc6 : bdfcd2 JSR SEND_BLOCK ; Send 3-byte control block fbc9 : 8607 LDA #7 fbcb : bdfd1c JSR SEND_BYTE ; Send $0700 fbce : bdfd1a JSR SEND_BYTEB ; Send $00 as B=0 from SEND_BLK fbd1 : bdfaf1 JSR WAIT_BYTE ; Wait for response fbd4 : 48 ASLA ; Move bit 7 into Carry fbd5 : 250d BCS RD_DONE fbd7 : ae83 LDX ,--X ; Get text pointer from control block ; LDB #0 ; B=number received (B already zero from SEND_BLK) fbd9 : RD_STR: fbd9 : bdfaf1 JSR WAIT_BYTE ; Wait for bytes from Tube R2 fbdc : a780 STA ,X+ ; Store in text buffer, increment X fbde : 5c INCB ; Increment character count fbdf : 810d CMPA #13 ; Check current byte fbe1 : 26f6 BNE RD_STR ; Loop until fbe3 : 5a DECB ; Decrement character count to balance ; ANDCC #$FE ; Clear carry (already CC from CMPA #13) fbe4 : RD_DONE: fbe4 : 8600 LDA #0 ; Clear A without clearing Carry fbe6 : 1f02 TFR D,Y ; Y=length fbe8 : 3504 PULS B ; Restore B fbea : 39 RTS ; Table of OSWORD control block lengths for &01-&14 ; ------------------------------------------------- fbeb : WORDTX: fbeb : 0005000504 FCB $00,$05,$00,$05,$04 fbf0 : 05080e0401 FCB $05,$08,$0E,$04,$01 fbf5 : 0105001020 FCB $01,$05,$00,$10,$20 fbfa : 100d000480 FCB $10,$0D,$00,$04,$80 fbff : WORDRX: fbff : 0500050005 FCB $05,$00,$05,$00,$05 fc04 : 0000000509 FCB $00,$00,$00,$05,$09 fc09 : 0500081900 FCB $05,$00,$08,$19,$00 fc0e : 010d800480 FCB $01,$0D,$80,$04,$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 ; fc13 : ARGS: fc13 : 3426 PSHS A,B,Y ; Save handle, B and function fc15 : 860c LDA #$0C fc17 : bdfd1c JSR SEND_CMD ; Send command $0C - OSARGS fc1a : bdfd18 JSR SEND_BYTEY ; Send handle IF BIGENDIAN fc1d : 5f CLRB ; Point to first byte of word to send fc1e : bdfce5 JSR SEND_WORDS ; Send four-byte control block ELSE LDB #4 ; Four bytes to send JSR SEND_BLOCK ; Send four-byte control block ENDIF fc21 : 3502 PULS A ; Get action back fc23 : bdfd1c JSR SEND_BYTE ; Send action fc26 : bdfaf1 JSR WAIT_BYTE ; Wait for returned result fc29 : 3402 PSHS A ; Save result IF BIGENDIAN fc2b : 5f CLRB ; Point to first byte of word to read fc2c : bdfcf7 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 fc2f : 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 ; fc31 : BGet: fc31 : 3404 PSHS B fc33 : 860e LDA #$0E fc35 : bdfd1c JSR SEND_CMD ; Send command $0E - OSBGet fc38 : bdfd18 JSR SEND_BYTEY ; Send handle fc3b : 3504 PULS B fc3d : 7efaee 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 ; fc40 : BPut: fc40 : 3406 PSHS A,B ; Save byte and B fc42 : 8610 LDA #$10 fc44 : bdfd1c JSR SEND_CMD ; Send command $10 - OSBPut fc47 : bdfd18 JSR SEND_BYTEY ; Send handle fc4a : 3506 PULS A,B ; Get A and B back fc4c : 3406 PSHS A,B fc4e : bdfd1c JSR SEND_BYTE ; Send byte to Tube fc51 : bdfaf1 JSR WAIT_BYTE ; Wait for acknowledgement fc54 : 3586 PULS A,B,PC ; Restore A/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 ; fc56 : FIND: fc56 : 3406 PSHS A,B ; Save A fc58 : 8612 LDA #$12 fc5a : bdfd1c JSR SEND_CMD ; Send command $12 - OSFIND fc5d : 3506 PULS A,B ; Get function back fc5f : bdfd1c JSR SEND_BYTE ; Send function fc62 : 4d TSTA ; Check function fc63 : 2706 BEQ Close ; Jump to deal with Close fc65 : bdfcc9 JSR SEND_STR ; Send string at X fc68 : 7efaf1 JMP WAIT_BYTE ; Wait for returned handle fc6b : Close: fc6b : 3404 PSHS B fc6d : bdfd18 JSR SEND_BYTEY ; Send handle to Tube fc70 : bdfaf1 JSR WAIT_BYTE ; Wait for acknowledgement fc73 : 4f CLRA ; Zero A fc74 : 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 ; ; Tube data: $14 block string function -- result block ; fc76 : FILE: fc76 : 3436 PSHS A,B,X,Y ; Save B,X,Y registers and function in A fc78 : 8614 LDA #$14 fc7a : bdfd1c JSR SEND_CMD ; Send command $14 - OSFILE fc7d : 3002 LEAX 2,X ; Point to control block contents IF BIGENDIAN fc7f : c60c LDB #12 ; Point to first byte to send fc81 : bdfce5 JSR SEND_WORDS ; Send 16-byte control block ELSE LDB #16 ; 16 bytes to send JSR SEND_BLOCK ; Send 16-byte control block ENDIF fc84 : ae83 LDX ,--X ; Get big-endian filename pointer to X fc86 : bdfcc9 JSR SEND_STR ; Send filename string fc89 : 3502 PULS A ; Get function back fc8b : bdfd1c JSR SEND_BYTE ; Send function fc8e : bdfaf1 JSR WAIT_BYTE ; Wait for returned result ; Data transfer via interupts may happen while waiting fc91 : 3514 PULS B,X ; Restore B, get control block pointer back fc93 : 3406 PSHS A,B ; Save result and B again fc95 : 3002 LEAX 2,X ; Point to control block contents IF BIGENDIAN fc97 : c60c LDB #12 ; Point to first byte to read fc99 : bdfcf7 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 fc9c : 301e LEAX -2,X ; Restore X fc9e : 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 ; fca0 : GBPB: fca0 : 3426 PSHS A,B,Y ; Save Y and function fca2 : 8616 LDA #$16 fca4 : bdfd1c JSR SEND_CMD ; Send command $16 - OSGBPB IF BIGENDIAN fca7 : 3001 LEAX 1,X ; Step past handle fca9 : c608 LDB #8 ; Point to first byte to send fcab : bdfce5 JSR SEND_WORDS ; Send 12-byte control block fcae : a682 LDA ,-X ; Get handle fcb0 : bdfd1c JSR SEND_BYTE ; Send 0th byte of control block ELSE LDB #13 JSR SEND_BLOCK ; Send 13-byte control block ENDIF fcb3 : 3502 PULS A fcb5 : bdfd1c JSR SEND_BYTE ; Send function IF BIGENDIAN fcb8 : 3001 LEAX 1,X ; Step past handle fcba : c608 LDB #8 ; Point to first byte to read fcbc : bdfcf7 JSR WAIT_WORDS ; Read 12-byte control block fcbf : bdfaf1 JSR WAIT_BYTE ; Get 0th byte of control block fcc2 : a782 STA ,-X ELSE LDB #13 JSR WAIT_BLOCK ; Wait for 13-byte control block ENDIF fcc4 : 3524 PULS B,Y ; Get B and Y back fcc6 : 7efaee JMP WAIT_CHAR ; Get Carry and result byte ; ***************** ; Tube I/O routines ; ***************** ; Send cr-string at X to Tube Register 2 ; ========================================= fcc9 : SEND_STR: fcc9 : a680 LDA ,X+ ; Get byte from X, increment X fccb : 8d4f BSR SEND_BYTE ; Send byte via Tube R2 fccd : 810d CMPA #13 ; Test current character ; EORA #13 would preserve carry fccf : 26f8 BNE SEND_STR ; Loop until CR sent fcd1 : 39 RTS ; Send block at X to Tube Register 2, B=block length ; ================================================== ; Returns X=preserved, B=0 fcd2 : SEND_BLOCK: fcd2 : 3a ABX ; X=X+B, X=>after last byte to send fcd3 : SEND_BLKLP: fcd3 : a682 LDA ,-X ; Decrement X, get byte from X fcd5 : 8d45 BSR SEND_BYTE ; Send byte via Tube R2 fcd7 : 5a DECB ; Decrement count of bytes to send fcd8 : 26f9 BNE SEND_BLKLP ; Loop until all bytes sent fcda : 39 RTS ; Wait for block at X from Tube Register 2, B=block length ; ======================================================== ; Returns X=preserved, B=0 fcdb : WAIT_BLOCK: fcdb : 3a ABX ; X=X+B, X=>after last byte to receive fcdc : WAIT_BLKLP: fcdc : bdfaf1 JSR WAIT_BYTE ; Get byte via Tube R2 fcdf : a782 STA ,-X ; Decrement X, store byte at X fce1 : 5a DECB ; Decrement count of bytes fce2 : 26f8 BNE WAIT_BLKLP ; Loop until all bytes sent fce4 : 39 RTS IF BIGENDIAN ; Send big-endian block at X to Tube Register 2, B=>first word ; ============================================================= ; Returns X=preserved, B<0 fce5 : SEND_WORDS: fce5 : 3a ABX ; X=X+B, X=>first byte to send fce6 : SEND_WDLP: fce6 : a680 LDA ,X+ ; Get byte from X, increment X fce8 : 8d32 BSR SEND_BYTE ; Send byte via Tube R2 fcea : 5a DECB ; Decrement byte count fceb : c503 BITB #3 fced : 26f7 BNE SEND_WDLP ; Loop for four bytes fcef : 3018 LEAX -8,X ; Point to next word down fcf1 : 5d TSTB fcf2 : 2af2 BPL SEND_WDLP ; Another word to do fcf4 : 3004 LEAX 4,X ; Restore X fcf6 : 39 RTS ; Wait for big-endian block at X from Tube Register 2, B=>first word ; ================================================================== ; Returns X=preserved, B<0 fcf7 : WAIT_WORDS: fcf7 : 3a ABX ; X=X+B, X=>first byte to receive fcf8 : WAIT_WDLP: fcf8 : bdfaf1 JSR WAIT_BYTE ; Get byte via Tube R2 fcfb : a780 STA ,X+ ; Store byte at X, increment X fcfd : 5a DECB ; Decrement count of bytes fcfe : c503 BITB #3 fd00 : 26f6 BNE WAIT_WDLP ; Loop for four bytes fd02 : 3018 LEAX -8,X ; Point to next word down fd04 : 5d TSTB fd05 : 2af1 BPL WAIT_WDLP ; Another word to do fd07 : 3004 LEAX 4,X ; Restore X fd09 : 39 RTS ENDIF ; OSWRCH - Send character in A to Tube Register 1 ; =============================================== ; Preserves A, corrupts flags ; fd0a : WRCH: fd0a : 3402 PSHS A ; Save A fd0c : SEND_R1LP: fd0c : b6fee0 LDA >TUBE1S ; Read Tube R1 status fd0f : 48 ASLA ; Move TxRDY from b6 to b7 fd10 : 2afa BPL SEND_R1LP ; Loop until TxRDY set fd12 : 3502 PULS A ; Get A back fd14 : b7fee1 STA >TUBE1 ; Send byte to Tube R1 fd17 : 39 RTS ; Send byte in Y to Tube Register 2 via B ; ======================================= fd18 : SEND_BYTEY: fd18 : 1f20 TFR Y,D ; ; Fall through into SEND_BYTEB ; Send byte in B to Tube Register 2 ; ================================== fd1a : SEND_BYTEB: fd1a : 1f98 TFR B,A ; ; Fall through into SendByte ; Send byte in A to Tube Register 2 ; ================================== ; Preserves A, corrupts flags ; fd1c : SEND_CMD: fd1c : SEND_BYTE: fd1c : 3402 PSHS A ; Save A fd1e : SEND_BYTELP: fd1e : b6fee2 LDA >TUBE2S ; Read Tube R2 status fd21 : 48 ASLA ; Move TxRDY from b6 to b7 ; ANDA #$40 would preserve carry fd22 : 2afa BPL SEND_BYTELP ; Loop until TxRDY set fd24 : 3502 PULS A ; Get A back fd26 : b7fee3 STA >TUBE2 ; Send byte to Tube R2 fd29 : 39 RTS ; **************************************** ; Host->Client communication via interupts ; **************************************** ; When Host sends a byte to R1 or R4 it generates a Client IRQ. ; Data transfers are syncronised with client NMIs. Graham Toal's ; design sends Tube IRQs to 6809 FIRQs and Tube NMIs to 6809 IRQs. ; Transfers are synchronised with SYNC instruction waiting for IRQs. ; ; This code manually translated from Graham Toal's Skimp code ; with half an eye on the PDP-11, Z80 and 6502 code. ; Most code before this point translated from JGH PDP-11 client. ; Interupt handler ; ================ ; Stack holds: CC with E=0, PC ; CC has I and F set to disable further IRQs and FIRQs ; fd2a : FIRQ_HANDLE: fd2a : 3402 PSHS A fd2c : b6fee6 LDA >TUBE4S ; Read Tube R4 status fd2f : 2b51 BMI FIRQ_R4 ; If data in Tube R4, jump to process errors and transfers fd31 : b6fee0 LDA >TUBE1S ; Read Tube R1 status fd34 : 2b06 BMI FIRQ_R1 ; If data in Tube R1, jump to process Escape and Events fd36 : 3502 PULS A ; Get A back fd38 : 6e9fffb1 JMP [IRQ2V] ; Pass interupt onwards ; Interupt generated by data in Tube R1 ; ------------------------------------- fd3c : FIRQ_R1: fd3c : b6fee1 LDA >TUBE1 fd3f : 2b1b BMI FIRQ_Escape ; b7=1, jump to set Escape state ; ; A<$80 - Host event being passed to client ; Tube data: via R1: $00 Y X A ; fd41 : 3502 PULS A ; Pop A to restack all registers fd43 : 3476 PSHS A,B,X,Y,U ; Save everything fd45 : 8d1c BSR Get_R1 ; Get event Y parameter fd47 : 1f89 TFR A,B fd49 : 4f CLRA ; Ensure AB is 8-bit value fd4a : 1f02 TFR D,Y fd4c : 8d15 BSR Get_R1 ; Get event X parameter fd4e : 1f89 TFR A,B fd50 : 4f CLRA ; Ensure AB is 8-bit value fd51 : 1f01 TFR D,X fd53 : 8d0e BSR Get_R1 ; Get event A parameter fd55 : ad9ffffc JSR [EVENTV] ; Dispatch event fd59 : 3576 PULS U,Y,X,B,A ; Restore registers fd5b : 3b RTI ; Return from interupt ; A>$7F - Host changing Escape state ; Tube data: via R1: flag, b7=1, b6=state ; fd5c : FIRQ_Escape: fd5c : 48 ASLA ; Move b6 into b7 fd5d : b7ff80 STA >ESCFLG ; Store Escape flag fd60 : 3502 PULS A ; Restore A fd62 : 3b RTI ; Return from interupt ; Read byte from Tube R1, allowing Tube R4 transfers to take place ; ---------------------------------------------------------------- fd63 : Get_R1: fd63 : b6fee6 LDA >TUBE4S ; Read Tube R4 status fd66 : 2a02 BPL NotFIRQ_R4 ; Pending R4 transfer higher priority than R1 transfer fd68 : 8d12 BSR FIRQ_R4_CC ; Deal with R4 interupt fd6a : NotFIRQ_R4: fd6a : b6fee0 LDA >TUBE1S ; Read Tube R1 status fd6d : 2af4 BPL Get_R1 ; Loop until b7 set fd6f : b6fee1 LDA >TUBE1 ; Get byte from Tube R1 fd72 : 39 RTS ; Read byte from Tube R4 ; ---------------------- fd73 : Get_R4: fd73 : b6fee6 LDA >TUBE4S ; Read Tube R4 status fd76 : 2afb BPL Get_R4 ; Loop until b7 set fd78 : b6fee7 LDA >TUBE4 ; Get byte from Tube R4 fd7b : 39 RTS ; Interrupt generated by data in Tube R4 ; -------------------------------------- fd7c : FIRQ_R4_CC: fd7c : 1c7f ANDCC #$7F ; Clear 'all registers' bit fd7e : 3401 PSHS CC ; Push CC to let this be a subroutine fd80 : 3402 PSHS A ; Push A to balance following Pull fd82 : FIRQ_R4: fd82 : 3502 PULS A ; Pop A to restack registers fd84 : 3416 PSHS A,B,X ; Rearrange stack contents fd86 : b6fee7 LDA >TUBE4 fd89 : 2a22 BPL FIRQ_Data ; b7=0, jump for data transfer ; A>$7F - Error occured ; Tube data: via R2: $00 err string $00 ; fd8b : 10ceff80 LDS #ERRSTK ; Collapse stack fd8f : 8eff00 LDX #ERRBLK ; Point to error buffer fd92 : bdfaf1 JSR WAIT_BYTE ; Wait for BRK error code fd95 : 863f LDA #$3F ; SWI opcode fd97 : a780 STA ,X+ ; Store SWI opcode fd99 : bdfaf1 JSR WAIT_BYTE ; Get error number fd9c : a780 STA ,X+ ; Store error number fd9e : FIRQ_R4LP: fd9e : bdfaf1 JSR WAIT_BYTE ; Wait for byte of error string fda1 : a780 STA ,X+ ; Store in error buffer ; WAIT_BYTE returns flags set from A fda3 : 26f9 BNE FIRQ_R4LP ; Loop until terminating $00 received fda5 : 8eff01 LDX #ERRBLK+1 ; Point to error block after SWI opcode fda8 : 3410 PSHS X ; Push error pointer onto stack fdaa : 7effbc JMP ERRJMP ; Jump to generate error ; FIRQ and IRQ will be enabled by error handler ; Data transfer via FIRQs ; ----------------------- ; R4<$80 - Data transfer ; Tube data: via R4: action ID block sync, via R3: data ; ; Cribbed from Graham Toal's Skimp code ; fdad : FIRQ_Data: ; A=transfer type ; fdad : 3402 PSHS A ; Save transfer type fdaf : 8dc2 BSR Get_R4 ; Wait for caller ID fdb1 : 3502 PULS A ; Get transfer type back fdb3 : 8105 CMPA #5 ; Is it 'release'? fdb5 : 2606 BNE FIRQ_NotDone; No, jump to do transfer DMB: fixed BEQ/BNE error fdb7 : 7fff94 CLR DMA_DONE ; Signal 'transfer done' fdba : 3516 PULS A,B,X ; Restore registers fdbc : 3b RTI ; and return from interupt ; fdbd : FIRQ_NotDone: fdbd : 3402 PSHS A ; Save transfer type again fdbf : 8db2 BSR Get_R4 ; Get data address MSB fdc1 : 8db0 BSR Get_R4 ; Get data address fdc3 : 8dae BSR Get_R4 ; Get data address fdc5 : 1e89 EXG A,B fdc7 : 8daa BSR Get_R4 ; Get data address LSB fdc9 : 1e89 EXG A,B ; D=data address fdcb : 1f01 TFR D,X ; X=data address ; LDA >TUBE3S ; Read from Tube R3 twice to clear FIFO ; LDA >TUBE3S ; Z80, 32016 and 80x86 client don't actually do this fdcd : 86ff LDA #$FF fdcf : b7ff94 STA DMA_DONE ; Signal 'transfer in progress' fdd2 : 8d9f BSR Get_R4 ; Get sync byte fdd4 : 1cbf ANDCC #$BF ; DMB: re-enable FIRQ interrupts to allow Release FIRQ fdd6 : a6e0 LDA ,S+ ; Pop A from stack and set Z flag fdd8 : 2766 BEQ FIRQ0 ; Dispatch to FIRQ subhandler fdda : 8102 CMPA #2 fddc : 2555 BCS FIRQ1 fdde : 2743 BEQ FIRQ2 fde0 : 8104 CMPA #4 fde2 : 252f BCS FIRQ3 fde4 : 2767 BEQ FIRQ4 fde6 : 5f CLRB ; B=counter for 256-byte transfers fde7 : 8107 CMPA #7 ; We will never get a FIRQ5 here as filtered out earlier fde9 : 2511 BCS FIRQ6 fdeb : 2663 BNE FIRQ_DONE ; 1-byte and 2-byte Tube R3 interrupts done via IRQ/SYNC mechanism ; 256-byte transfers done by polling transfer register ; Transfer 7 - Multiple byte host -> parasite ; ------------------------------------------- fded : FIRQ7: fded : FIRQ7lp: fded : b6fee4 LDA >TUBE3S ; Wait for Tube R3 ready fdf0 : 2afb BPL FIRQ7lp fdf2 : b6fee5 LDA >TUBE3 ; Get byte from Tube host via R3 fdf5 : a780 STA ,X+ ; Store in parasite memory at X fdf7 : 5a DECB ; Decrement counter fdf8 : 26f3 BNE FIRQ7lp ; Loop 256 times fdfa : 2054 BRA FIRQ_DONE ; Transfer 6 - Multiple byte parasite -> host ; ------------------------------------------- fdfc : FIRQ6: fdfc : FIRQ6lp: fdfc : b6fee4 LDA >TUBE3S ; Wait for Tube R3 ready fdff : 2afb BPL FIRQ6lp fe01 : a680 LDA ,X+ ; Get byte from parasite memory at X fe03 : b7fee5 STA >TUBE3 ; Send to Tube host via R3 fe06 : 5a DECB ; Decrement counter fe07 : 26f3 BNE FIRQ6lp ; Loop 256 times fe09 : FIRQ6lp2: fe09 : b6fee4 LDA >TUBE3S ; Wait for Tube R3 ready fe0c : 2afb BPL FIRQ6lp2 fe0e : b7fee5 STA >TUBE3 ; Send 257th byte to flush FIFO fe11 : 203d BRA FIRQ_DONE ; Transfer 3 - Double byte host -> parasite ; ----------------------------------------- fe13 : FIRQ3: fe13 : FIRQ3lp: fe13 : 13 SYNC ; Wait for IRQ fe14 : b6ff94 LDA DMA_DONE ; Has flag changed? fe17 : 2737 BEQ FIRQ_DONE ; FIRQ5 has cleared flag fe19 : b6fee5 LDA >TUBE3 ; Get two bytes from Tube host fe1c : f6fee5 LDB >TUBE3 fe1f : ed81 STD ,X++ ; Store them in parasite memory fe21 : 20f0 BRA FIRQ3lp ; Loop until FIRQ5 clears flag ; Transfer 2 - Double byte parasite -> host ; ----------------------------------------- fe23 : FIRQ2: fe23 : FIRQ2lp: fe23 : 13 SYNC ; Wait for IRQ fe24 : b6ff94 LDA DMA_DONE ; Has flag changed? fe27 : 2727 BEQ FIRQ_DONE ; FIRQ5 has cleared flag fe29 : ec81 LDD ,X++ ; Fetch two bytes from parasite memory fe2b : b7fee5 STA >TUBE3 ; Send them to Tube host fe2e : f7fee5 STB >TUBE3 fe31 : 20f0 BRA FIRQ2lp ; Loop until FIRQ5 clears flag ; Transfer 1 - Single bytes host -> parasite ; ------------------------------------------ fe33 : FIRQ1: fe33 : FIRQ1lp: fe33 : 13 SYNC ; Wait for IRQ fe34 : b6ff94 LDA DMA_DONE ; Has flag changed? fe37 : 2717 BEQ FIRQ_DONE ; FIRQ5 has cleared flag fe39 : b6fee5 LDA >TUBE3 ; Get byte from Tube host fe3c : a780 STA ,X+ ; Store in parasite memory fe3e : 20f3 BRA FIRQ1lp ; Loop until FIRQ5 clears flag ; Transfer 0 - Single bytes parasite -> host ; ------------------------------------------ fe40 : FIRQ0: fe40 : FIRQ0lp: fe40 : 13 SYNC ; Wait for IRQ fe41 : b6ff94 LDA DMA_DONE ; Has flag changed? fe44 : 270a BEQ FIRQ_DONE ; FIRQ5 has cleared flag fe46 : a680 LDA ,X+ ; Get byte from parasite memory fe48 : b7fee5 STA >TUBE3 ; Send to Tube host fe4b : 20f3 BRA FIRQ0lp ; Loop until FIRQ5 clears flag ; Transfer 4 - Set program execute address ; ---------------------------------------- fe4d : FIRQ4: fe4d : bfff8c STX ADDRESS ; Update Execution Address fe50 : FIRQ_DONE: fe50 : FIRQ_EXIT: fe50 : 3516 PULS A,B,X ; After a FIRQ4 the Host will then send a FIRQ5 to release the Tube and ; clear DNA_DONE. OSCLI handler will pick up execution address and pass ; it to EXECUTE. ; Null interupt routines ; ====================== ; OS-9 and FLEX use a timer on IRQ to poll background processes ; fe52 : NULL_RTI: fe52 : RES_HANDLE: fe52 : SWI2_HANDLE: fe52 : SWI3_HANDLE: fe52 : IRQ_HANDLE: fe52 : NMI_HANDLE: fe52 : 3b RTI ; SWI - Generate an error ; ======================= 0001 = M6309: EQU 1 ; Check for 6309 CPU fe53 : SWI_HANDLE: IF M6309 fe53 : 11a36a CMPU 10,S ; Compare U with stacked U or stacked PC fe56 : 2602 BNE SWI_6809 ; It's stacked PC, so is not 6309 native mode fe58 : 3262 LEAS 2,S ; Step past stacked W fe5a : SWI_6809: ENDIF fe5a : 326a LEAS 10,S ; Point to stacked PC fe5c : ERR_HANDLE: fe5c : 3510 PULS X ; Pop address of error block after SWI opcode fe5e : bfff82 STX FAULT ; Save pointer to last error fe61 : 1c00 ANDCC #$00 ; Clear all flags, enable interupts fe63 : 6e9ffffa JMP [BRKV] ; Jump to current error handler with X=>error ; I/O address space ; ================= fec0 = ORG $FEC0 fec0 : IOADDRS: ; Add any extra I/O devices here ; For example: ; $FECx VIA ; $FEDx MMU ; $FEEx TUBE fee0 = ORG $FEE0 fee0 : 00 TUBE1S: FCB 0 ; $FEE0 ; Tube registers fee1 : 00 TUBE1: FCB 0 ; $FEE1 fee2 : 00 TUBE2S: FCB 0 ; $FEE2 fee3 : 00 TUBE2: FCB 0 ; $FEE3 fee4 : 00 TUBE3S: FCB 0 ; $FEE4 fee5 : 00 TUBE3: FCB 0 ; $FEE5 fee6 : 00 TUBE4S: FCB 0 ; $FEE6 fee7 : 00 TUBE4: FCB 0 ; $FEE7 ; If Tube registers fully decoded, space for 8 I/O addresses here ; For example: ; $FEE8/9 ACIA ; Remapped hardware vectors ; ========================= ; BA/BS decoded to toggle address line A8 to map hardware vectors to $FEF0 ; fef0 = ORG $FEF0 fef0 : ROMHIGH: fef0 : fe52 XTRAPV: FDB RES_HANDLE ; $FEF0 ; Hardware vectors, paged in to $FFFx fef2 : fe52 XSWI3V: FDB SWI3_HANDLE ; $FEF2 fef4 : fe52 XSWI2V: FDB SWI2_HANDLE ; $FEF4 fef6 : fd2a XFIRQV: FDB FIRQ_HANDLE ; $FEF6 fef8 : fe52 XIRQV: FDB IRQ_HANDLE ; $FEF8 fefa : fe53 XSWIV: FDB SWI_HANDLE ; $FEFA fefc : fe52 XNMIV: FDB NMI_HANDLE ; $FEFC fefe : f82c XRESETV: FDB RESET ; $FEFE ; Text buffers ; ============ ff00 = ORG $FF00 ff00 : ERRBLK: ; Buffer to store host error block ff00 : 00000000000000.. CLIBUF: RMB 128-16 ; Space to enter command line from CLI prompt ff70 : 00000000000000.. CLIEND: RMB 16 ff80 : ERRSTK: ; Internal stack for host errors ff80 : CLISTK: ; Internal stack for CLI commands ; as main memory may be overwritten ; Tube system workspace and MOS entry block ; ========================================= ff80 = ORG $FF80 ff80 : WORKSP: ; Use same addresses as Z80 ff80 : 00 ESCFLG: FCB 0 ; $FF80 ; Escape and pending input flag ff81 : 00 TEMPA: FCB 0 ; $FF81 ; TempA/Personality ff82 : f816 FAULT: FDB BANNER ; $FF82 ; Last error message ff84 : f8ad DEFERR: FDB COM_ERR ; $FF84 ; Default error handler ff86 : f816 LPTR: FDB BANNER ; $FF86 ; Command line tail ff88 : 0000 MEMBOT: FDB RAMSTART ; $FF88 ; Bottom of user memory ff8a : f800 MEMTOP: FDB RAMEND ; $FF8A ; Top of user memory ff8c : ffb9 ADDRESS: FDB CLICOM ; $FF8C ; Execution address ff8e : ffb9 TRANSFER: FDB CLICOM ; $FF8E ; Transfer address ff90 : ffb9 PROGRAM: FDB CLICOM ; $FF90 ; Current program address ff92 : 0000 ADDRHI: FDB 0 ; $FF92 ; Memory address high word ff94 : 00 DMA_DONE: FCB 0 ; $FF94 ; Transfer completion flag ; BBC MOS entry points ; -------------------- ff95 = ORG $FF95 ff95 : 7efac2 JMP >NULL ; &FF95 ; Service ff98 : 7ef82c JMP >RESET ; &FF98 ; Cold ff9b : 7ef963 PRSTRING: JMP >SEND_TXT ; &FF9B ; Print ASCIIZ text at X ff9e : 7e FCB $7E ; &FF9E ; Force a JMP opcode ff9f : ffee FDB OSWRCH ffa1 : 7ef96c SCANHEX: JMP >RD_HEX ; &FFA1 ; ReadHex ffa4 : 7efac2 DISKACC: JMP >NULL ; &FFA4 ; DiskAccess ffa7 : 7ef86e OSQUIT: JMP >WARMS ; &FFA7 ; Quit current process ffaa : 7ef93f PRHEX: JMP >PR_HEX ; &FFAA ; Print A as 8-bit hex ffad : 7ef935 PR2HEX: JMP >PR_2HEX ; &FFAD ; Print X as 16-bit hex ffb0 : 7efe52 USERINT: JMP >NULL_RTI ; &FFB0 ; Pass on FIRQs if not Tube FIRQ ffb1 = IRQ2V: EQU USERINT+1 ffb3 : 7ef956 PRTEXT: JMP >PR_TEXT ; &FFB3 ; Print inline ASCIIZ text ffb6 : 7efac2 JMP >NULL ; &FFB6 ; VecDef/PrntC ffb9 : 7ef86e CLICOM: JMP >CLILOOP ; &FFB9 ; Enter Supervisor *command prompt ffbc : 7efe5c ERRJMP: JMP >ERR_HANDLE; &FFBC ; Generate an error ffbf : OSINIT: ffbf : 7ef8d0 INITERR: JMP >ERR_INIT ; &FFBF ; Initialise program environment ffc2 : 7efac2 DISKRST: JMP >NULL ; &FFC2 ; DiskReset ffc5 : 7ef963 JMP >SEND_TXT ; &FFC5 ; Deprecated ffc8 : 7efac2 JMP >NULL ; &FFC8 ffcb : 7efac2 JMP >NULL ; &FFCB ; BBC MOS file entry points ; ------------------------- ffce : 7efc56 OSFIND: JMP >FIND ; $FFCE ffd1 : 7efca0 OSGBPB: JMP >GBPB ; $FFD1 ffd4 : 7efc40 OSBPUT: JMP >BPut ; $FFD4 ffd7 : 7efc31 OSBGET: JMP >BGet ; $FFD7 ffda : 7efc13 OSARGS: JMP >ARGS ; $FFDA ffdd : 7efc76 OSFILE: JMP >FILE ; $FFDD ; BBC MOS character entry points ; ------------------------------ ffe0 : 7efaea 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 : 7efd0a OSWRCH: JMP >WRCH ; $FFEE ; BBC MOS system entry points ; --------------------------- fff1 : 7efb6d OSWORD: JMP >WORD ; $FFF1 fff4 : 7efafa OSBYTE: JMP >BYTE ; $FFF4 fff7 : 7ef9ae OS_CLI: JMP >CLI ; $FFF7 ; System vectors ; -------------- fffa : f8ad BRKV: FDB COM_ERR ; $FFFA ; Error handler fffc : fac2 EVENTV: FDB NULL ; $FFFC ; Event vector fffe : f82c L_FFFE: FDB RESET ; $FFFE ; Reset vector ; Memory Mapping Unit/Dynamic Address Translation ; =============================================== ; SWTPC clones have write-only MMU/DAT at $FFF0 No errors in pass 2. Wrote binary from address $f800 through $ffff. Total size 2048 bytes.