10
20
30
40
50 :
60
70
80 :
90 :
100
110
120 IF HIMEM>&FFFF:SYS "OS_GetEnv"TOA$:IFLEFT$(A$,5)<>"B6502":OSCLI"B6502"+MID$(A$,INSTR(A$," "))
130 ON ERROR REPORT:PRINT" at line ";ERL:END
140 DEFFNif(A%):IFA%:z%=-1:=opt% ELSE z%=P%:=opt%
150 DEFFNendif:IFz%=-1:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt%
160 DEFFNelse:IFz%=-1:z%=P%:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=-1:=opt%
170 DIM mcode% &1FF, L% &40
180 :
190 :
200
210
220 ver$="0.10":date$=" (11 Nov 2016)"
230 name$="Mini65":title$="Tiny 6502 Kernel"
240 RDLINE%=TRUE:
250 load%=&FE00
260 :
270
280
290 USERV=&200:BRKV =&202:IRQ1V=&204:IRQ2V=&206:CLIV =&208:BYTEV=&20A
300 WORDV=&20C:WRCHV=&20E:RDCHV=&210:FILEV=&212:ARGSV=&214:BGetV=&216
310 BPutV=&218:GBPBV=&21A:FINDV=&21C:FSCV =&21E:EVNTV=&220
320 LPTR=&F8:TEXT=&FA:IRQA=&FC:FAULT=&FD:ESCFLG=&FF
330 :
340
350
360 TxStatus=&5001:TxRDY=0:TxData=&5000:TxInit=&00:TxCommand=&5002:TxCmd=&0A
370 RxStatus=&5001:RxRDY=8:RxData=&5000:RxInit=&00:TxControl=&5003:TxCtl=&1E
380 TxDelay=100:
390 MEMBOT%=&800:MEMTOP%=&4000:MAIN=&8000:
400 name$="EaterMini":title$="BenEater65"
410 :
420
430
440 TxStatus=&FDF0:TxRDY=2:TxData=&FDF1:TxInit=&13:TxCommand=0:
450 RxStatus=&FDF0:RxRDY=1:RxData=&FDF1:RxInit=&55:TxControl=0:
460 TxDelay=0
470 MEMBOT%=&800:MEMTOP%=&8000:MAIN=&FFB9:
480 name$="Mini65":title$="Tiny 6502 Kernel"
490
500 :
510
520
530 esc=&9B
540 :
550 :
560 FOR P=0 TO 1:opt%=P*3+4
570 P%=load%:O%=mcode%
580 [OPT opt%
590 .LF800
600 JMP RESET
610 .PrBanner
620 JSR PrText
630 .BANNER
640 EQUB 13:EQUS title$:EQUS " ":EQUS ver$
650 EQUB 13:EQUB 0
660 RTS
670 :
680 \ Tube Client Startup Code
690 \ ========================
700 .RESET
710 SEI:LDX #&35 :\ Disable interupts
720 .RESETlp
730 LDA LFF00,X:STA &0200,X :\ Copy default vectors
740 DEX:BPL RESETlp:TXS :\ Clear stack
750 INX:STX ESCFLG :\ Clear Escape flag
760 LDA #TxInit:STA TxStatus :\ Initialise I/O port
770 OPT FNif(TxControl=0)
780 LDA #RxInit:STA RxStatus
790 OPT FNelse
800 LDA #TxCmd:STA TxCommand
810 LDA #TxCtl:STA TxControl
820 OPT FNendif
830 CLI:JSR PrBanner:JSR OSNEWL
840 CLC:LDA #&01:JMP OSQUIT :\ Enter main program
850 :
860 .osBYTE
870 CMP #&83:BCC osBYTEexit
880 CMP #&85:BCS osBYTEexit
890 LDX #0:LDY #MEMBOT% DIV 256
900 ROR A:BCS osBYTEok
910 LDY #MEMTOP% DIV 256
920 .osBYTEok
930 ROL A
940 .osBYTEexit
950 RTS
960 :
970 OPT FNif(RDLINE%) :\ Perform RDLINE locally
980 .osWORD
990 STX LPTR+0:STY LPTR+1 :\ LPTR=>control block
1000 TAY:BNE Word00Exit :\ OSWORD 0, jump to read line
1010 LDA (LPTR),Y:TAX:INY
1020 LDA (LPTR),Y:STA LPTR+1
1030 STX LPTR+0:DEY :\ (LPTR)=>string buffer, Y=0
1040 .Word00Lp1
1050 JSR OSRDCH:BCS Word00Exit :\ Wait for character
1060 CMP #&7F:BNE Word00Char :\ Not Delete
1070 .Word00Delete
1080 TYA:BEQ Word00Lp1 :\ Nothing to delete
1090 LDA #&7F:JSR OSWRCH :\ VDU 127
1100 .Word00Back
1110 DEY:JMP Word00Lp1 :\ Dec. counter, loop back
1120 .Word00Char
1130 CMP #&08:BEQ Word00Delete :\ BS is also Delete
1140 CMP #&15:BNE Word00Ins :\ Not Ctrl-U
1150 TYA:BEQ Word00Lp1 :\ Nothing to delete
1160 LDA #&7F
1170 .Word00Lp2
1180 JSR OSWRCH:DEY :\ Delete characters
1190 BNE Word00Lp2
1200 BEQ Word00Lp1 :\ Jump back to start
1210 .Word00Ins
1220 STA (LPTR),Y :\ Store character
1230 CMP #&0D:CLC:BEQ Word00cr :\ Return - finish
1240 CMP #&20:BCC Word00ctrl :\ Control character
1250 INY:BEQ Word00Back :\ Too long, dec and go back
1260 .Word00ctrl
1270 JSR OSWRCH :\ Print character
1280 .Word00max
1290 JMP Word00Lp1 :\ Loop for more
1300 .Word00cr
1310 JSR OSNEWL:CLC :\ Return with CC, Y=length
1320 .Word00Exit
1330 RTS
1340 OPT FNendif
1350 :
1360 \ Default error handler
1370 \ =====================
1380 .ErrorHandler
1390 JSR OSNEWL
1400 LDX FAULT+0:LDY FAULT+1
1410 INX:BNE P%+3:INY :\ XY=>error string
1420 JSR PRSTRNG :\ Print error string
1430 .HALT
1440 JMP HALT :\ And stop
1450 :
1460 \ Interrupt handlers
1470 \ ==================
1480 .IRQHandler
1490 STA IRQA:PLA:PHA :\ Save A, get flags from stack
1500 AND #&10:BNE BRKHandler :\ If BRK, jump to BRK handler
1510 JMP (IRQ1V) :\ Continue via IRQ1V handler
1520 .IRQ1Handler
1530 JMP (IRQ2V) :\ Pass on to IRQ2V
1540 .BRKHandler
1550 TXA:PHA :\ Save X
1560 TSX:LDA &0103,X:CLD :\ Get address from stack
1570 SEC:SBC #&01:STA FAULT+0
1580 LDA &0104,X
1590 SBC #&00:STA FAULT+1 :\ &FD/E=>after BRK opcode
1600 PLA:TAX:LDA IRQA :\ Restore X, get saved A
1610 CLI:JMP (BRKV) :\ Restore IRQs, jump to Error Handler
1620 .IRQ2Handler
1630 LDA IRQA :\ Restore A
1640 .NMIHandler
1650 RTI :\ Return from interupt
1660 :
1670 \ OSRDCH - Wait for character from input stream
1680 \ =============================================
1690 \ On exit, A =char, Cy=Escape flag
1700 .osRDCH
1710 JSR ReadData:BCC osRDCH :\ Wait for character
1720 BNE osRDCH2
1730 .osRDCH1
1740 JSR ReadData:BCC osRDCH1 :\ Wait for character
1750 .osRDCH2
1760 CMP #27:BEQ osRDCH3 :\ Exit with CS if Escape
1770 .ReadDataNone
1780 CLC :\ CC if not Escape
1790 .osRDCH3
1800 RTS
1810 :
1820 \ OSWRCH - Send character to output stream
1830 \ ========================================
1840 \ On entry, A =character
1850 .osWRCH :\ WRCH is simply SendByte
1860 .SendByte
1870 JSR SendData :\ Send byte
1880 CMP #esc:BNE SendByteDone :\ If not esc, done
1890 \ :\ Fall through to send again
1900 :
1910 :
1920 \ *** LOW-LEVEL I/O CODE ***
1930 \ ==========================
1940 :
1950 \ Send a raw byte of data
1960 \ -----------------------
1970 .SendData
1980 PHA
1990 .SendWait
2000 OPT FNif(TxRDY)
2010 LDA TxStatus :\ Get Status
2020 AND #TxRDY:BEQ SendWait :\ Wait until data can be sent
2030 OPT FNendif
2040 OPT FNif(TxDelay)
2050 LDA #TxDelay:SEC :\ 6551-style TxRDY bugfix
2060 .SendWaitDelay
2070 SBC #1:BNE SendWaitDelay
2080 OPT FNendif
2090 PLA:STA TxData :\ Send data
2100 .SendByteDone
2110 RTS
2120 :
2130 \ Read raw data
2140 \ -------------
2150 \ On exit, P =CC, no data
2160 .ReadData
2170 LDA RxStatus:AND #RxRDY :\ Get RxStatus
2180 BNE ReadDataNone :\ Exit if no data present
2190 LDA RxData:CMP #esc:SEC:RTS:\ CS=Data present, EQ/NE=esc
2200 :
2210 :
2220 \ DEFAULT VECTOR TABLE
2230 \ ====================
2240 .LFF00
2250 EQUW NullReturn :\ &200 - USERV
2260 EQUW ErrorHandler :\ &202 - BRKV
2270 EQUW IRQ1Handler :\ &204 - IRQ1V
2280 EQUW IRQ2Handler :\ &206 - IRQ2V
2290 EQUW NullReturn :\ &208 - CLIV
2300 EQUW osBYTE :\ &20A - BYTEV
2310 OPT FNif(RDLINE%)
2320 EQUW osWORD :\ &20C - WORDV
2330 OPT FNelse
2340 EQUW NullReturn :\ &20C - WORDV
2350 OPT FNendif
2360 EQUW osWRCH :\ &20E - WRCHV
2370 EQUW osRDCH :\ &210 - RDCHV
2380 EQUW NullReturn :\ &212 - FILEV
2390 EQUW NullReturn :\ &214 - ARGSV
2400 EQUW NullReturn :\ &216 - BGetV
2410 EQUW NullReturn :\ &218 - BPutV
2420 EQUW NullReturn :\ &21A - GBPBV
2430 EQUW NullReturn :\ &21C - FINDV
2440 EQUW Unsupported :\ &21E - FSCV
2450 EQUW NullReturn :\ &220 - EVNTV
2460 EQUW Unsupported :\ &222 - UPTV
2470 EQUW Unsupported :\ &224 - NETV
2480 EQUW Unsupported :\ &226 - VduV
2490 EQUW Unsupported :\ &228 - KEYV
2500 EQUW Unsupported :\ &22A - INSV
2510 EQUW Unsupported :\ &22C - RemV
2520 EQUW Unsupported :\ &22E - CNPV
2530 EQUW NullReturn :\ &230 - IND1V
2540 EQUW NullReturn :\ &232 - IND2V
2550 EQUW NullReturn :\ &234 - IND3V
2560 :
2570 .PrText
2580 PLA:STA TEXT+0:PLA:STA TEXT+1 :\ TEXT=>embedded string
2590 JSR PrString2:JMP (TEXT) :\ Print string and jump back to code
2600 :
2610 .PrString
2620 STX TEXT+0:STY TEXT+1 :\ TEXT=>string at YX
2630 .PrStringLp
2640 LDY #&00:LDA (TEXT),Y :\ Get character
2650 BEQ PrString2:JSR OSASCI :\ Print character if not &00
2660 .PrString2
2670 INC TEXT+0:BNE LFEA6:INC TEXT+1 :\ Increment address
2680 .LFEA6
2690 TAY:BNE PrStringLp :\ Loop back if not &00
2700 :
2710 .ScanHex
2720 .InitError
2730 .Unsupported
2740 .NullReturn
2750 RTS
2760 :
2770 OPT FNif(P%<&FF7D)
2780 .PrHexXY
2790 TYA:JSR PrHex:TXA
2800 .PrHex
2810 PHA:LSR A:LSR A:LSR A:LSR A
2820 JSR PrNybble:PLA:AND #15
2830 .PrNybble
2840 PHP:SED:CLC:ADC #&90:ADC #&40:PLP:JMP OSWRCH
2850 OPT FNendif
2860 :
2870 \ Standard Tube entry points
2880 \ ==========================
2890 EQUS STRING$((&FF95-P%)AND255,CHR$255)
2900 .LFF95 :JMP NullReturn :\ &FF95
2910 .OSCOLD :JMP RESET :\ &FF98
2920 .PRSTRNG :JMP PrString :\ &FF9B Print zero-terminated text at YX, returns A=0, Y corrupted
2930 .LFF9E :JMP NullReturn :\ &FF9E
2940 .SCANHEX :JMP NullReturn :\ &FFA1
2950 .DISKACC :JMP NullReturn :\ &FFA4
2960 .DISKCCP :JMP NullReturn :\ &FFA7
2970 .PRHEX :JMP PrHex :\ &FFAA Print A in hex, A corrupted
2980 .PR2HEX :JMP PrHexXY :\ &FFAD Print YX in hex, A corrupted
2990 .USERINT :JMP NullReturn :\ &FFB0
3000 .PRTEXT :JMP PrText :\ &FFB3 Print zero-terminated inline text, returns A=0, Y corrupted
3010 .VECDEF :EQUB &36:EQUW LFF00 :\ &FFB6 Default vector table
3020 .OSQUIT :JMP MAIN :\ &FFB9 Quit current program
3030 .OSERROR :JMP NullReturn :\ &FFBC
3040 .OSINIT :JMP InitError :\ &FFBF Initialise MOS error handler, A corrupted
3050 .DISKRST :JMP NullReturn :\ &FFC2
3060 .LFFC5 :JMP NullReturn :\ &FFC5
3070 .NVRDCH :JMP osRDCH :\ &FFC8
3080 .NVWRCH :JMP osWRCH :\ &FFCB
3090 :
3100 .OSFIND :JMP (FINDV) :\ &FFCE
3110 .OSGBPB :JMP (GBPBV) :\ &FFD1
3120 .OSBPUT :JMP (BPutV) :\ &FFD4
3130 .OSBGET :JMP (BGetV) :\ &FFD7
3140 .OSARGS :JMP (ARGSV) :\ &FFDA
3150 .OSFILE :JMP (FILEV) :\ &FFDD
3160 :
3170 .OSRDCH :JMP (RDCHV) :\ &FFE0
3180 .OSASCI :CMP #&0D:BNE OSWRCH :\ &FFE3
3190 .OSNEWL :LDA #&0A:JSR OSWRCH :\ &FFE7
3200 .OSWRCR :LDA #&0D :\ &FFEC
3210 .OSWRCH :JMP (WRCHV) :\ &FFEE
3220 .OSWORD :JMP (WORDV) :\ &FFF1
3230 .OSBYTE :JMP (BYTEV) :\ &FFF4
3240 .OS_CLI :JMP (CLIV) :\ &FFF7
3250 :
3260 .NMIV :EQUW NMIHandler :\ &FFFA NMI Vector
3270 .RESETV :EQUW RESET :\ &FFFC RESET Vector
3280 .IRQV :EQUW IRQHandler :\ &FFFE IRQ Vector
3290 ]:IF O%>L%:PRINT"ERROR: Code overrun":END
3300 NEXT:PRINT "Saving ";name$;
3310 OSCLI "Save "+name$+" "+STR$~mcode%+" "+STR$~O%+" "+STR$~load%+" "+STR$~load%
3320 PRINT