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