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