10 REM > TubeSys/src
   20 REM Source for System kernel for 65Tube Tube Emulator
   30 REM 65Tube client code with Atom/System Kernel MOS entry block
   40 :
   50 IF PAGE>&8000:SYS "OS_GetEnv"TOA$:IFLEFT$(A$,5)<>"B6502":OSCLI"B6502"+MID$(A$,INSTR(A$," "))
   60 :
   70 load%=&F800:DIM mcode% &900
   80 :
   90 USERV=&200: BRKV=&202:IRQ1V=&204:IRQ2V=&206
  100  CLIV=&208:BYTEV=&20A:WORDV=&20C:WRCHV=&20E
  110 RDCHV=&210:FILEV=&212:ARGSV=&214:BGetV=&216
  120 BPutV=&218:GBPBV=&21A:FINDV=&21C: FSCV=&21E
  130 EVNTV=&220: UPTV=&222: NETV=&224: VduV=&226
  140  KEYV=&228: INSV=&22A: RemV=&22C: CNPV=&22E
  150 IND1V=&230:IND2V=&232:IND3V=&234
  160 :
  170 FOR P=0TO1
  180   P%=load%:O%=mcode%
  190   [OPT P*3+4
  200   \ &EE/F=
  210   \ &F0/1=>membot, if &F0<>0, membot=0000, memtop=0000
  220   \ &F2/3=>command string
  230   \ &F4/5=>memtop
  240   \ &F6/7= readhex accumulator, ";params" pointer
  250   \ &F8/9=>control block
  260   \ &FA/B=>String to print with PrString
  270   \ &FC  = IRQ A store
  280   \ &FD/E=>last error
  290   \ &FF  = escape flag
  300   \ &0236= command input buffer
  310   \ &03xx= bit16-bit23 of Turbo65 (zp),Y addresses
  320   \ &03F3= b16-b23 of (&F2),Y command string pointer
  330   \ &03F5= b16-b23 of (&F4),Y memtop pointer
  340   \ &03F9= b16-b23 of (&F8),Y control block pointer
  350   \ &03FB= b16-b23 of (&FA),Y string pointer
  360   \ &03FE= b16-b23 of (&FD),Y error pointer
  370   
  380   \ Emulator opcodes
  390   \ &03 - OSCLI
  400   \ &13 - OSBYTE
  410   \ &23 - OSWORD
  420   \ &33 - OSWRCH
  430   \ &43 - OSRDCH
  440   \ &53 - OSFILE
  450   \ &63 - OSARGS
  460   \ &73 - OSBGET
  470   \ &83 - OSBPUT
  480   \ &93 - OSGBPB
  490   \ &A3 - OSFIND
  500   \ &B3 - Called by *QUIT
  510   \ &C3 - Called by *BASIC and OSBYTE 142
  520   \ &D3
  530   \ &E3
  540   \ &F3
  550   
  560   \ *OS - Enter command prompt
  570   \ ==========================
  580   .CmdOS
  590   JSR ErrorInit:JSR OSNEWL      :\ Point BRKV to ErrorHandler
  600   JSR HelpBanner:JSR OSNEWL     :\ Display Emulator banner
  610   LDY #&04:JSR OSByteA3         :\ Ask host something
  620   TYA:BNE JumpToCode            :\ If Y<>0, enter code at XY
  630   
  640   .CmdOSLoop
  650   JSR PrText                    :\ Display prompt
  660   EQUS "SYSTEM*":NOP
  670   LDA #&00
  680   LDX #LF84A AND 255
  690   LDY #LF84A DIV 256
  700   JSR osWORD:BCS OSEscape       :\ Input a command
  710   LDX #&36:LDY #&02:JSR OS_CLI  :\ Execute command
  720   JMP CmdOSLoop                 :\ Jump back for another
  730   
  740   \ *BASIC
  750   \ ======
  760   .CmdBASIC
  770   EQUB &C3                      :\ Pass to host
  780   
  790   \ NMI Handler
  800   \ ===========
  810   .NMIHandler
  820   LDY #&04:JSR OSByteA3         :\ Ask host something
  830   TYA:BEQ CmdOS                 :\ If Y=0, enter command prompt
  840   .JumpToCode
  850   JMP EnterCodeXY               :\ Y<>0, enter code at XY
  860   
  870   .OSEscape
  880   LDA #&7E:JSR osBYTE           :\ Ack. escape
  890   BRK:EQUB 17:EQUS "Escape":BRK
  900   
  910   .LF84A
  920   EQUW &0236 :\ Input buffer at &0236
  930   EQUB &C9   :\ Max. &C9 characters
  940   EQUB &20   :\ Minimum character
  950   EQUB &FF   :\ Maximum character
  960   
  970   .RESET
  980   LDX #&FF:TXS                  :\ Clear stack
  990   JSR LF87F                     :\ Reset vectors and set memory limits
 1000   LDY #&06:JSR OSByteA3         :\ Ask host something
 1010   TYA:BNE OscliXY               :\ If Y<>0, execute command at XY
 1020   \ If Y=0, display startup banner and enter command prompt
 1030   \ If Y<>0, XY=>command to execute
 1040   
 1050   JSR PrText                    :\ Print startup banner
 1060   EQUB 10:EQUS "Acorn Atom/System Tube"
 1070   EQUB 10:EQUB 10:EQUB 13
 1080   NOP
 1090   JMP CmdOS                     :\ Jump to command prompt
 1100   \ Will then call display help banner,
 1110   \ then calls OsByteA3,4 for any entry address
 1120   
 1130   .OscliXY
 1140   JSR ErrorInit                 :\ Set up error handler
 1150   JSR OS_CLI:JMP CmdQUIT        :\ Execute command then quit
 1160   
 1170   \ Reset vectors and set memory limits
 1180   \ ===================================
 1190   .LF87F
 1200   CLD:LDX #&35
 1210   .LF882
 1220   LDA LFB87,X:STA &0200,X       :\ Copy from default vectors
 1230   DEX:BPL LF882
 1240   STZ &FF:STZ &F0               :\ Clear escape flag
 1250   LDX #&08:STX &F1              :\ Set F0/1=>bottom of memory at &0800
 1260   LDX #&00:LDY #&F8             :\ XY=&F800
 1270   STX &F4:STY &F5               :\ Set F4/5=>top of memory at &F800
 1280   RTS
 1290   
 1300   \ Interupt handler
 1310   \ ================
 1320   .InterruptHandler
 1330   STA &FC:PLA:PHA           :\ Save A, get flags from stack
 1340   AND #&10:BNE BRKHandler   :\ If BRK, jump to BRK handler
 1350   JMP (IRQ1V)               :\ Continue via IRQ1V handler
 1360   
 1370   .IRQ1Handler
 1380   JMP (IRQ2V)               :\ No handlers, pass staight on to IRQ2V
 1390   
 1400   .BRKHandler
 1410   TXA:PHA                      :\ Save X
 1420   TSX:LDA &0103,X              :\ Get address from stack
 1430   CLD:SEC:SBC #&01:STA &FD
 1440   LDA &0104,X:SBC #&00:STA &FE :\ &FD/E=>after BRK opcode
 1450   LDA #&00:STA &03FE           :\ Error block at (&FD),Y is in block &00
 1460   PLA:TAX:LDA &FC              :\ Restore X, get saved A
 1470   CLI:JMP (BRKV)               :\ Restore IRQs and jump to Error Handler
 1480   
 1490   \ Default error handler
 1500   \ =====================
 1510   .ErrorHandler
 1520   LDX #&FF:TXS                 :\ Clear stack
 1530   INX:STX &03FE                :\ Error block at (&FD),Y is in block &00
 1540   CLI:JSR OSNEWL
 1550   LDY #&01
 1560   .LF8D7
 1570   LDA (&FD),Y:BEQ LF8E1        :\ Print error string
 1580   JSR OSWRCH:INY:BNE LF8D7
 1590   .LF8E1
 1600   JSR OSNEWL:JMP CmdOSLoop     :\ Jump to command prompt
 1610   
 1620   \ *QUIT
 1630   \ =====
 1640   .CmdQUIT
 1650   EQUB &B3                     :\ Pass to host
 1660   
 1670   .OSByteA3
 1680   LDA #&A3:LDX #&F3            :\ OSBYTE &A3,&F3
 1690   EQUB &13                     :\ Host OSBYTE
 1700   RTS
 1710   
 1720   \ Scan hex
 1730   \ ========
 1740   .ScanHex
 1750   LDX #&00:STX &F6:STX &F7     :\ Clear hex accumulator
 1760   STX &03F3                    :\ String at (&F2),Y is in block &00
 1770   .LF8F7
 1780   LDA (&F2),Y                  :\ Get current character
 1790   SEC:SBC #&30:BCC LF921       :\ <'0', exit
 1800   CMP #&0A:BCC LF90E           :\ '0'..'9', add into accumator
 1810   AND #&DF:SBC #&07            :\ Ignore case, convert letters
 1820   CMP #&0A:BCC LF921           :\ <'A', exit
 1830   CMP #&10:BCS LF921           :\ >'F', exit
 1840   .LF90E
 1850   ASL A:ASL A:ASL A:ASL A      :\ *16
 1860   LDX #&03
 1870   .LF914
 1880   ASL A:ROL &F6:ROL &F7        :\ Move bits into accumulator
 1890   BCS LF959                    :\ Overflowed, jump to error
 1900   DEX:BPL LF914                :\ Loop for four bits
 1910   INY:BNE LF8F7                :\ Move to next character
 1920   .LF921
 1930   JMP SkipSpaces               :\ Skip past any final spaces and exit
 1940   
 1950   \ Scan hex, error if null string
 1960   .LF924
 1970   JSR ScanHex:PHP              :\ Save <cr> flag
 1980   CPX #&00:BEQ LF959           :\ X=0, nothing read in, 'Bad number' error
 1990   PLP:RTS                      :\ Get <cr> flag back
 2000   
 2010   \ *PAGE - Set PAGE address
 2020   \ ========================
 2030   .CmdPAGE
 2040   JSR SkipSpaces:BEQ LF94A   :\ No parameters, jump to use &0800
 2050   JSR LF924:BNE LF959        :\ Error if more parameters
 2060   LDY &F7:LDX &F6:BNE LF94E  :\ addr<>&xx00, error as must by 256-byte aligned
 2070   CPY #&08:BCC LF94E         :\ addr<&0800, error as too low
 2080   CPY #&80:BCS LF94E         :\ addr>&8000, error as too high
 2090   .LF946
 2100   STY &F1:CLC:RTS            :\ Store PAGE high byte
 2110   .LF94A
 2120   LDY #&08:BRA LF946         :\ Default to &0800
 2130   
 2140   .LF94E
 2150   BRK
 2160   BRK:EQUS "Bad PAGE":BRK    :\ Unusable PAGE value
 2170   .LF959
 2180   BRK
 2190   BRK:EQUS "Bad number":BRK  :\ Bad hex
 2200   .LF966
 2210   SEC:RTS                    :\ SEC=pass command to host
 2220   
 2230   \ *GO - Call machine code
 2240   \ =======================
 2250   .CmdGO
 2260   JSR SkipSpaces:BEQ LF984   :\ If no params, re-enter existing code
 2270   JSR ScanHex                :\ Scan hex parameter
 2280   CPX #&00:BEQ LF966         :\ No hex parameter, pass to host
 2290                              :\ eg *GO HELLO
 2300   CMP #&3B:BEQ LF97C         :\ ';'
 2310   CMP #&0D:BNE LF959         :\ More parameters, error
 2320   .LF97C
 2330   LDX &F6:LDY &F7            :\ Store parameter pointer
 2340                              :\ Enter code at XY
 2350   
 2360   .EnterCodeXY
 2370   STX &F4:STY &F5            :\ Set memtop to entry address
 2380   .LF984
 2390   LDA &EF:PHA:LDA &EE:PHA    :\ Save current program
 2400   JSR EnterCode
 2410   PLA:STA &EE:STA &F4        :\ Restore current program and also set memtop
 2420   PLA:STA &EF:STA &F5
 2430   CLC:RTS                    :\ CLC=command done
 2440   
 2450   \ Check if code to be entered has a ROM header
 2460   .EnterCode
 2470   LDA &F4:STA &EE              :\ Current program starts at memtop
 2480   LDA &F5:STA &EF
 2490   LDX #&00:STX &03F5:STX &03FE :\ Set memtop and errptr are in block &00
 2500   LDY #&07:LDA (&F4),Y         :\ Get copyright offset
 2510   CLD:CLC:ADC &F4:STA &FD
 2520   LDA #&00:ADC &F5:STA &FE     :\ &FD/E=>copyright message
 2530   \ Check for &00,"(C)"
 2540   LDY #&00:LDA (&FD),Y:BNE LF9FC     :\ Check for initial &00
 2550   INY:LDA (&FD),Y:CMP #&28:BNE LF9FC :\ Check for '('
 2560   INY:LDA (&FD),Y:CMP #&43:BNE LF9FC :\ Check for 'C'
 2570   INY:LDA (&FD),Y:CMP #&29:BNE LF9FC :\ Check for ')'
 2580   \ &00,"(C)" exists
 2590   LDY #&06:LDA (&F4),Y         :\ Get ROM type
 2600   AND #&4D:CMP #&40:BCC LFA2A  :\ b6=0, Not a language
 2610   AND #&0D:BEQ LF9E6           :\ code=%x1xx00x0, enter 6502 code
 2620   CMP #&01:BNE LFA0E           :\ code<>%x1xx00x1, not 6502 code
 2630   .LF9E6
 2640   \ romtype=%0000 - A=0 - 6502 BASIC
 2650   \ romtype=%0001 - A=1 - Turbo6502
 2660   \ romtype=%0010 - A=0 - 6502 nonBASIC
 2670   \ romtype=%0011 - A=1 - reserved
 2680   PHA:LDY #&09                 :\ Save entry value &00 or &01
 2690   .LF9E9
 2700   LDA (&F4),Y:BEQ LF9F3        :\ Print ROM title
 2710   JSR OSWRCH:INY:BNE LF9E9
 2720   .LF9F3
 2730   JSR OSNEWL:JSR OSNEWL        :\ Print two NLs
 2740   PLA:BRA LF9FE                :\ Get entry value back
 2750   .LF9FC                       :\ No (C) string, enter as raw code
 2760   LDA #&00                     :\ Set flag=0
 2770   .LF9FE
 2780   STA &F0                      :\ Store flag at &F0
 2790   \ If flag=0, membot=&F0/1, memtop=&F4/5
 2800   \ If flag<>0, membot=0000, memtop=0000
 2810   LDY #&00:TYA
 2820   .LFA03
 2830   STA &0300,Y:DEY:BNE LFA03    :\ All (zp),Y accesses to block &00
 2840   LDA #&01:JMP (&00F4)         :\ Enter code with A=1
 2850   
 2860   .LFA0E
 2870   JSR ErrorInit
 2880   BRK
 2890   BRK:EQUS "I cannot run this code":BRK
 2900   .LFA2A
 2910   JSR ErrorInit
 2920   BRK
 2930   BRK:EQUS "This is not a language":BRK
 2940   
 2950   .ErrorInit
 2960   LDA #ErrorHandler AND 255:STA BRKV+0 :\ Claim BRKV
 2970   LDA #ErrorHandler DIV 256:STA BRKV+1
 2980   RTS
 2990   
 3000   \ *HELP - Display help
 3010   \ ====================
 3020   .CmdHELP
 3030   JSR SkipSpaces:BNE LFA5C :\ Exit if parameters
 3040   JSR OSNEWL:JSR HelpBanner:\ Display startup banner
 3050   .LFA5C
 3060   SEC:RTS                  :\ Return, SEC to pass to host
 3070   
 3080   .HelpBanner
 3090   JSR PrText
 3100   EQUS "6502 Emulator OS 0.64 (19 Oct 1988)"
 3110   EQUB 10:EQUB 13
 3120   NOP
 3130   RTS
 3140   
 3150   .osBYTE               :\ OSBYTE
 3160   PHA
 3170   CMP #&82:BEQ BYTE82 :\ Read memory high word
 3180   CMP #&83:BEQ BYTE83 :\ Read bottom of memory
 3190   CMP #&84:BEQ BYTE84 :\ Read top of memory
 3200   CMP #&85:BEQ BYTE85 :\ Read top of memory for screen mode
 3210   CMP #&8E:BEQ BYTE8E :\ Enter language
 3220   CMP #&A3:BNE BYTEnn :\ Jump if not Application OSBYTE
 3230   CPX #&FE:BCC BYTEnn :\ Jump if X<&FE
 3240   \ OSBYTE &A3,&FE and OSBYTE &A3,FF - return unchanged
 3250   PLA
 3260   RTS
 3270   
 3280   .BYTEnn             :\ Pass OSBYTE to host
 3290   EQUB &13            :\ MOS_BYTE
 3300   PLA:RTS             :\ Return
 3310   
 3320   .BYTE82             :\ Read memory high word
 3330   LDX #&00:LDY #&00   :\ High word=&0000
 3340   PLA:RTS
 3350   
 3360   .BYTE83             :\ Read bottom of memory
 3370   PLA                 :\ Get A back
 3380   LDX &F0:BEQ LFABC   :\ If &F0=0, &F0/F1=>memory bottom
 3390   LDA #&01            :\ Set A=&01
 3400   LDX #&00:LDY #&00   :\ Return memory bottom=&0000
 3410   RTS
 3420   .LFABC
 3430   LDX #&00:LDY &F1    :\ Get memory bottom from &F0/F1
 3440   RTS
 3450   
 3460   .BYTE84             :\ Read top of memory
 3470   PLA                 :\ Get A back
 3480   LDX &F0:BEQ LFACD   :\ If &F0=0, &F4/5=>memory top
 3490   LDA #&04            :\ Set A=&04
 3500   LDX #&00:LDY #&00   :\ Return memory top=&0000
 3510   RTS
 3520   .LFACD
 3530   LDX &F4:LDY &F5     :\ Get memory top from &F4/F5
 3540   RTS
 3550   
 3560   .BYTE85             :\ Read top of memory for screem
 3570   LDX #&00:LDY #&80   :\ Return top of memory=&8000
 3580   PLA:RTS             :\ Restore A and return
 3590   
 3600   .BYTE8E             :\ Enter language
 3610   JMP CmdBASIC        :\ Jump to enter BASIC
 3620   
 3630   .osBGet
 3640   EQUB &73            :\ Pass OSBGet to host
 3650   RTS
 3660   
 3670   .osBPut
 3680   EQUB &83            :\ Pass OSBPut to host
 3690   RTS
 3700   
 3710   .osFILE
 3720   EQUB &53            :\ Pass OSFILE to host
 3730   RTS
 3740   
 3750   .osFIND
 3760   EQUB &A3            :\ Pass OSFIND to host
 3770   RTS
 3780   
 3790   .osGBPB
 3800   EQUB &93            :\ Pass OSGBPB to host
 3810   RTS
 3820   
 3830   .osRDCH
 3840   EQUB &43            :\ Pass OSRDCH to host
 3850   RTS
 3860   
 3870   .osWRCH
 3880   EQUB &33            :\ Pass OSWRCH to host
 3890   RTS
 3900   
 3910   .osWORD                :\ OSWORD
 3920   CMP #&05:BNE LFB0C   :\ Jump if not Read I/O memory
 3930   :
 3940   \ OSWORD 5 - Read I/O memory
 3950   \ Reads from Tube memory
 3960   STX &F8:STY &F9      :\ &F8/9=>control block
 3970   LDY #&00:STY &03F9   :\ Control block at (&F8),Y in block &00
 3980   LDA (&F8),Y:STA &FA
 3990   INY
 4000   LDA (&F8),Y:STA &FB  :\ &FA/B=address to read
 4010   LDX #&00:LDA (&FA,X) :\ Read from address
 4020   LDY #&04:STA (&F8),Y :\ Store byte read in control block
 4030   LDX &F8:LDY &F9      :\ Restore X, Y
 4040   RTS
 4050   
 4060   .LFB0C
 4070   EQUB &23             :\ Pass OSWORD to host
 4080   RTS
 4090   
 4100   .osARGS              :\ OSARGS
 4110   CMP #&01:BNE LFB3C   :\ Jump if not command line/PTR=
 4120   CPY #&00:BNE LFB3C   :\ Jump if not command line
 4130   :
 4140   \ OSARGS 1,0 - Read address of command line
 4150   STY &03F3:DEY        :\ String at (&F2),Y is in block &00
 4160   .LFB1A
 4170   INY:LDA (&F2),Y      :\ Get character from command line
 4180   CMP #&20:BCC LFB26   :\ Control character found
 4190   BNE LFB1A            :\ Loop if not space
 4200   JSR SkipSpaces            :\ Skip any more spaces
 4210   .LFB26
 4220   CLC:TYA:ADC &F2:STA &00,X    :\ Add Y to base
 4230   LDA &F3:ADC #&00:STA &01,X   :\ Set returned address
 4240   LDY #&FF:STY &02,X:STY &03,X :\ Set to &FFFFxxxx
 4250   INY:LDA #&01                 :\ Return Y=&00, A=&01
 4260   RTS
 4270   .LFB3C
 4280   EQUB &63             :\ Pass OSARGS to host
 4290   RTS
 4300   
 4310   \ Print embedded string
 4320   \ =====================
 4330   .PrText
 4340   PLA:STA &FA:PLA:STA &FB   :\ &FA/B=>embedded string
 4350   LDY #&00:STY &03FB        :\ String at (&FA),Y is in block &00
 4360   INY
 4370   .LFB4A
 4380   LDA (&FA),Y               :\ Get character
 4390   CMP #&EA:BEQ LFB56        :\ Exit if NOP
 4400   JSR OSWRCH:INY:BNE LFB4A  :\ Print char and loop for next
 4410   .LFB56
 4420   TYA:CLC:ADC &FA
 4430   TAX:LDA #&00:ADC &FB      :\ Update return address
 4440   PHA:TXA:PHA               :\ Points after string
 4450   .NullReturn
 4460   RTS
 4470   
 4480   \ Print string at XY
 4490   \ ------------------
 4500   .PrString
 4510   STX &FA:STY &FB           :\ Store XY in &FA/B
 4520   LDY #&00:STY &03FB        :\ String at (&FA),Y is in block &00
 4530   .LFB6C
 4540   LDA (&FA),Y               :\ Get a character
 4550   CMP #&20:BCC LFB78        :\ Exit at control char
 4560   JSR OSWRCH:INY:BNE LFB6C  :\ Print character
 4570   .LFB78
 4580   RTS
 4590   
 4600   .Unsupported
 4610   BRK
 4620   BRK:EQUS "Unsupported":BRK
 4630   
 4640   \ Default vectors
 4650   .LFB87
 4660   EQUW Unsupported      :\ &200 - USERV
 4670   EQUW ErrorHandler     :\ &202 - BRKV
 4680   EQUW IRQ1Handler      :\ &204 - IRQ1V
 4690   EQUW Unsupported      :\ &206 - IRQ2V
 4700   EQUW osCLI            :\ &208 - CLIV
 4710   EQUW osBYTE           :\ &20A - BYTEV
 4720   EQUW osWORD           :\ &20C - WORDV
 4730   EQUW osWRCH           :\ &20E - WRCHV
 4740   EQUW osRDCH           :\ &210 - RDCHV
 4750   EQUW osFILE           :\ &212 - FILEV
 4760   EQUW osARGS           :\ &214 - ARGSV
 4770   EQUW osBGet           :\ &216 - BGetV
 4780   EQUW osBPut           :\ &218 - BPutV
 4790   EQUW osGBPB           :\ &21A - GBPBV
 4800   EQUW osFIND           :\ &21C - FINDV
 4810   EQUW Unsupported      :\ &21E - FSCV
 4820   EQUW NullReturn       :\ &220 - EVNTV
 4830   EQUW NullReturn       :\ &222 - UPTV
 4840   EQUW NullReturn       :\ &224 - NETV
 4850   EQUW Unsupported      :\ &226 - VduV
 4860   EQUW Unsupported      :\ &228 - KEYV
 4870   EQUW Unsupported      :\ &22A - INSV
 4880   EQUW Unsupported      :\ &22C - RemV
 4890   EQUW Unsupported      :\ &22E - CNPV
 4900   EQUW NullReturn       :\ &230 - IND1V
 4910   EQUW NullReturn       :\ &232 - IND2V
 4920   EQUW NullReturn       :\ &234 - IND3V
 4930   
 4940   .osCLI                :\ OSCLI
 4950   STX &F2:STY &F3       :\ &F2/3=>command string
 4960   LDY #&00:STY &03F3    :\ String at (&F2),Y is in block &00
 4970   .LFBC6
 4980   LDA (&F2),Y:STA LFC6A,Y  :\ Copy command line to command buffer
 4990   CMP #&0D:BEQ LFBD3       :\ Loop until <cr>
 5000   INY:BNE LFBC6            :\ Loop for up to 256 characters
 5010   .LFBD2
 5020   RTS                      :\ No <cr> found, exit
 5030   .LFBD3
 5040   LDX #LFC6A AND 255
 5050   LDY #LFC6A DIV 256       :\ Point XY to command buffer
 5060   STX &F2:STY &F3          :\ Point &F2/3 to command buffer
 5070   LDX #&00:LDY #&FF
 5080   .LFBDF
 5090   JSR SkipSpaces1          :\ Move past and skip spaces
 5100   CMP #ASC"*":BEQ LFBDF    :\ Skip past '*'s
 5110   CMP #&0D:BEQ LFBD2       :\ Null string, exit
 5120   CMP #ASC"|":BEQ LFBD2    :\ *|, comment, exit
 5130   CLC:TYA:ADC &F2:STA &F2  :\ Adjust &F2/3 to point to start of command
 5140   BCC LFBF8:INC &F3
 5150   .LFBF8
 5160   LDY #&00:LDA (&F2),Y     :\ Get first character
 5170   CMP #ASC".":BEQ LFC45    :\ '*.', jump to pass to host
 5180   .LFC00
 5190   TYA:PHA                  :\ Save command pointer
 5200   JSR SkipSpaces           :\ Skip any more spaces
 5210   .LFC05
 5220   LDA LFF02,X:BMI LFC20    :\ Jump if at end of command table
 5230   EOR (&F2),Y              :\ Compare with command table
 5240   AND #&DF:BNE LFC14       :\ Ignore case, jump if no match
 5250   INX:INY:BRA LFC05        :\ Loop to check next character
 5260   
 5270   .LFC14
 5280   LDA (&F2),Y:INY          :\ Get command character
 5290   CMP #ASC".":BEQ LFC29    :\ Abbreviated, jump to execute
 5300   .LFC1B
 5310   PLA:TAY                  :\ Get command pointer back
 5320   SEC:BRA LFC2B            :\ Step to next entry
 5330   
 5340   .LFC20
 5350   ASL A:BMI LFC29
 5360   LDA (&F2),Y              :\ Get next character
 5370   CMP #ASC"A":BCS LFC1B    :\ Still more letters, try next entry
 5380   .LFC29
 5390   PLA:CLC                  :\ Drop command pointer
 5400   .LFC2B
 5410   DEX
 5420   .LFC2C
 5430   INX:LDA LFF02,X:BPL LFC2C :\ Find end of entry
 5440   BCC LFC3C
 5450   INX:LDA LFF02,X
 5460   BNE LFC00:BEQ LFC45
 5470   
 5480   .LFC3C
 5490   ASL A:AND #&7F            :\ Index into command table
 5500   TAX:JSR LFC4B             :\ Call command routine
 5510   BCC LFC4A                 :\ If CLC, exit with call claimed
 5520   .LFC45
 5530   LDX &F2:LDY &F3           :\ &F2/3=XY
 5540   EQUB &03                  :\ Pass OSCLI to host
 5550                             :\ If host loads code and starts execution,
 5560                             :\ it generates an NMI and returns <>0 from
 5570                             :\ Osbyte 163,&F3
 5580   .LFC4A
 5590   RTS
 5600   
 5610   .LFC4B
 5620   LDA LFC5E+1,X:PHA         :\ Stack address high byte
 5630   LDA LFC5E+0,X:PHA         :\ Stack address low byte
 5640   RTS                       :\ Jump to routine
 5650   
 5660   .SkipSpaces1
 5670   INY
 5680   .SkipSpaces
 5690   LDA (&F2),Y:CMP #&20:BEQ SkipSpaces1
 5700   CMP #&0D:RTS
 5710   
 5720   \ Command addresses
 5730   \ -----------------
 5740   .LFC5E
 5750   EQUW CmdBASIC-1 :\ *BASIC
 5760   EQUW CmdQUIT-1  :\ *QUIT
 5770   EQUW CmdHELP-1  :\ *HELP
 5780   EQUW CmdGO-1    :\ *GO
 5790   EQUW CmdOS-1    :\ *OS
 5800   EQUW CmdPAGE-1  :\ *PAGE
 5810   
 5820   OSCLI command buffer
 5830   \ --------------------
 5840   .LFC6A
 5850   EQUS STRING$(128,CHR$0)
 5860   EQUS STRING$(128,CHR$0)
 5870   
 5880   .LFD6A
 5890   BRK:BRK
 5900   .LFD6C
 5910   STZ &C0
 5920   AND #&00
 5930   CLC
 5940   RTS
 5950   
 5960   \ This looks like a bit of BASIC code
 5970   \ -----------------------------------
 5980   .LFD72
 5990   LDA &0B:STA &19
 6000   LDA &0C:STA &1A
 6010   LDA &0A:STA &1B
 6020   .LFD7E
 6030   LDY &1B:INC &1B
 6040   LDA (&19),Y
 6050   CMP #&20:BEQ LFD7E
 6060   CMP #&3D:BEQ LFDBA
 6070   .LFD8C
 6080   BRK
 6090   EQUB &04:EQUS "Mistake"
 6100   .LFD95
 6110   BRK
 6120   EQUB &10:EQUS "Syntax error"
 6130   .LFDA3
 6140   BRK
 6150   EQUB &0D:EQUS "No ":EQUB &F2
 6160   .LFDA9
 6170   BRK
 6180   EQUB &11:EQUS "Escape"
 6190   BRK
 6200   
 6210   .LFDB2
 6220   JSR &C742
 6230   CMP #&3D:BNE LFD8C
 6240   RTS
 6250   
 6260   .LFDBA
 6270   JSR &D5AF:TXA
 6280   LDY &1B:BRA LFDDC
 6290   LDY &1B:BRA LFDD4
 6300   TSX:CPX #&FC:BCS LFDA3
 6310   LDA &01FF:CMP #&F2:BNE LFDA3
 6320   LDY &0A
 6330   .LFDD4
 6340   DEY
 6350   .LFDD5
 6360   INY:LDA (&0B),Y
 6370   CMP #&20:BEQ LFDD5
 6380   .LFDDC
 6390   CMP #&3A:BEQ LFDE8
 6400   CMP #&0D:BEQ LFDE8
 6410   CMP #&8B:BNE LFD95
 6420   .LFDE8
 6430   CLC:TYA:ADC &0B:STA &0B
 6440   BCC LFDF2:INC &0C
 6450   .LFDF2
 6460   LDY #&01:STY &0A
 6470   BIT &FF:BMI LFDA9
 6480   .LFDFA
 6490   RTS
 6500   
 6510   .LFDFB
 6520   JSR &D41A
 6530   LDA (&0B):CMP #&3A:BEQ LFDFA
 6540   LDA &0C:CMP #&07:BEQ LFE2E
 6550   LDY #&01:LDA (&0B),Y:BMI LFE2E
 6560   LDX &20:BEQ LFE1E
 6570   STA &2B:INY:LDA (&0B),Y:STA &2A
 6580   JSR &D4BF
 6590   .LFE1E
 6600   LDA #&03:CLC:ADC &0B:STA &0B
 6610   BCC LFE29:INC &0C
 6620   .LFE29
 6630   LDY #&01:STY &0A
 6640   .LFE2D
 6650   RTS
 6660   
 6670   .LFE2E
 6680   JMP &C7FB
 6690   
 6700   .LFE31
 6710   JMP &C905
 6720   
 6730   .LFE34
 6740   JSR &D5A3:BEQ LFE31
 6750   BPL LFE3E:JSR &CF38
 6760   .LFE3E
 6770   LDY &1B:STY &0A:LDA &2A
 6780   ORA &2B:ORA &2C:ORA &2D:BEQ LFE63
 6790   CPX #&8C:BEQ LFE53
 6800   .LFE50
 6810   JMP &C880
 6820   
 6830   .LFE53
 6840   INC &0A
 6850   .LFE55
 6860   JSR &D392:BCC LFE50
 6870   JSR &F018:JSR &D43A
 6880   JMP &EF05
 6890   
 6900   .LFE63
 6910   LDY &0A
 6920   .LFE65
 6930   LDA (&0B),Y:CMP #&0D:BEQ LFE74
 6940   INY:CMP #&8B:BNE LFE65
 6950   STY &0A:BEQ LFE55
 6960   .LFE74
 6970   JMP &C82D
 6980   
 6990   .LFE77
 7000   LDA &2A:CMP &21:LDA &2B
 7010   SBC &22:BCS LFE2D
 7020   LDA #&5B:JSR &F58A
 7030   JSR &D898:LDA #&5D
 7040   JSR &F58A:
 7050   JMP &F584
 7060   
 7070   .LFE91
 7080   JSR &F3EC:JSR &D6B7
 7090   TAY:JSR &CF52
 7100   JSR &F3D6:JSR &DCC4
 7110   LDA &2E:EOR &3B:BPL LFEBF
 7120   ASL &2E:BRA LFEE1
 7130   
 7140   .LFEAB
 7150   STY &2D:PLA:STA &2C
 7160   PLA:STA &2B
 7170   PLA:STA &2A
 7180   JSR &BA3A
 7190   LDA &3B:EOR #&80:STA &3B
 7200   .LFEBF
 7210   LDA &3C:CMP &30:BNE LFEDD
 7220   LDA &3D:CMP &31:BNE LFEDD
 7230   LDA &3E:CMP &32:BNE LFEDD
 7240   LDA &3F:CMP &33:BNE LFEDD
 7250   LDA &40:SBC &34:BEQ LFEE3
 7260   .LFEDD
 7270   ROR A:EOR &3B:ROL A
 7280   .LFEE1
 7290   LDA #&FF
 7300   .LFEE3
 7310   RTS
 7320   
 7330   .LFEE4
 7340   JMP &C905
 7350   
 7360   .LFEE7
 7370   INC &1B:TXA:BEQ LFF2C
 7380   BMI LFE91
 7390   LDA &2A:PHA
 7400   LDA &2B:PHA
 7410   LDA &2C:PHA
 7420   LDA &2D:PHA
 7430   JSR &D6B7:TAY:BMI P%+29
 7440   
 7450   .LFF00
 7460   EQUW LFF17
 7470   \ Command table
 7480   .LFF02
 7490   EQUS "GO"   :EQUB &C3
 7500   EQUS "HELP" :EQUB &82
 7510   EQUS "OS"   :EQUB &84
 7520   EQUS "PAGE" :EQUB &C5
 7530   EQUS "QUIT" :EQUB &81
 7540   .LFF17
 7550   EQUS "BASIC":EQUB &80
 7560   EQUB &00
 7570   
 7580   EQUS STRING$(&FF2C-P%,CHR$0)
 7590   .LFF2C
 7600   
 7610   EQUS STRING$(&FFB6-P%,CHR$0)
 7620   .VECDEF        :EQUB &36:EQUW LFB87
 7630   .LFFxx         :JMP Unsupported
 7640   .LFFxx         :JMP Unsupported
 7650   .LFFxx         :JMP Unsupported
 7660   .LFFxx         :JMP Unsupported
 7670   \.LFFxx         :\JMP Unsupported
 7680   
 7690   \ Atom/System Entry Block
 7700   \ -----------------------
 7710   \.NVRDCH        :JMP osRDCH
 7720   \.NVWRCH        :JMP osWRCH
 7730   
 7740   .OSSHUT        :JMP (FINDV)
 7750   .OSFIND        :JMP (FINDV)
 7760   .OSBPUT        :JMP (BPutV)
 7770   .OSBGET        :JMP (BGetV)
 7780   .OSSTAR        :JMP (ARGSV)
 7790   .OSRDAR        :JMP (ARGSV)
 7800   .OSSAVE        :JMP (FILEV)
 7810   .OSLOAD        :JMP (FILEV)
 7820   
 7830   \.OSFIND        :\JMP (FINDV)
 7840   \.OSGBPB        :\JMP (GBPBV)
 7850   \.OSBPUT        :\JMP (BPutV)
 7860   \.OSBGET        :\JMP (BGetV)
 7870   \.OSARGS        :\JMP (ARGSV)
 7880   \.OSFILE        :\JMP (FILEV)
 7890   
 7900   .OSRDCH        :JMP (RDCHV)
 7910   .OSECHO        :JSR OSRDCH
 7920   .OSASCI        :CMP #&0D:BNE OSWRCH
 7930   .OSNEWL        :LDA #&0A:JSR OSWRCH
 7940   .OSPRCR        :LDA #&0D
 7950   .OSWRCH        :JMP (WRCHV)
 7960   \.OSWORD        :\JMP (WORDV)
 7970   \.OSBYTE        :\JMP (BYTEV)
 7980   .OS_CLI        :JMP (CLIV)
 7990   
 8000   .NMIV          :EQUW NMIHandler
 8010   .RESETV        :EQUW RESET
 8020   .IRQV          :EQUW InterruptHandler
 8030 ]:NEXT
 8040 OSCLI"Save 65Kernel "+STR$~mcode%+" "+STR$~O%+" "+STR$~load%+" "+STR$~load%
 8050 ON ERROR ON ERROR OFF:END
 8060 *Quit
 8070 :
 8080 REM OSBYTE &A3,&F3
 8090 REM Y=
 8100 REM 4 - RESET, *OS, NMIHandler. Request code to enter
 8110 REM 6 - RESET occured, request command string to execute