> Mini65/src 2 Source for Tiny 6502 Single-port Tube Client 2 ============================================ (; This code may be freely reused, with acknowledgements 2: <( Tiny 6502 Tube Client in 512 bytes F9 Implements OSWRCH and OSRDCH via a single I/O port. P: Z: d Boilerplate n =========== xG >&FFFF:ș "OS_GetEnv"A$:A$,5)<>"B6502":"B6502"+A$,A$," "))  :" at line ";: *ݤif(A%):A%:z%=-1:=opt% z%=P%:=opt% ;ݤendif:z%=-1:=opt% z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt% Fݤelse:z%=-1:z%=P%:=opt% z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=-1:=opt%  mcode% &1FF, L% &40 : :  Name and version  ================ &ver$="0.10":date$=" (11 Nov 2016)" ,name$="Mini65":title$="Tiny 6502 Kernel" "RDLINE%=: Implement OSWORD 0 load%=&FE00 :  System vectors  ============== "EUSERV=&200:BRKV =&202:IRQ1V=&204:IRQ2V=&206:CLIV =&208:BYTEV=&20A ,EWORDV=&20C:WRCHV=&20E:RDCHV=&210:FILEV=&212:ARGSV=&214:BGetV=&216 6:BPutV=&218:GBPBV=&21A:FINDV=&21C:FSCV =&21E:EVNTV=&220 @3LPTR=&F8:TEXT=&FA:IRQA=&FC:FAULT=&FD:ESCFLG=&FF J: T@ I/O values, these should be suitable for BenEater SBC 6551 ^@ ========================================================== hLTxStatus=&5001:TxRDY=0:TxData=&5000:TxInit=&00:TxCommand=&5002:TxCmd=&0A rLRxStatus=&5001:RxRDY=8:RxData=&5000:RxInit=&00:TxControl=&5003:TxCtl=&1E |#TxDelay=100: 6551 TxRDY bugfix ?MEMBOT%=&800:MEMTOP%=&4000:MAIN=&8000: Enter code at &8000 )name$="EaterMini":title$="BenEater65" : / I/O values, these are suitable for a 6850 / ========================================= OTxStatus=&FDF0:TxRDY=2:TxData=&FDF1:TxInit=&13:TxCommand=0: &13=Reset ACIA RRxStatus=&FDF0:RxRDY=1:RxData=&FDF1:RxInit=&55:TxControl=0: &55=8N1, clock/16  TxDelay=0 KMEMBOT%=&800:MEMTOP%=&8000:MAIN=&FFB9: Replace with address to jump to ,name$="Mini65":title$="Tiny 6502 Kernel" " MAIN=&C000:name$="Mini65_C0" :  Serial Tube system values  =========================  esc=&9B : &: 0 P=0 1:opt%=P*3+4 :P%=load%:O%=mcode% D [OPT opt% N .LF800 X JMP RESET b .PrBanner lJSR PrText v .BANNER *EQUB 13:EQUS title$:EQUS " ":EQUS ver$ EQUB 13:EQUB 0 RTS : \ Tube Client Startup Code \ ========================  .RESET 3SEI:LDX #&35 :\ Disable interupts  .RESETlp 6LDA LFF00,X:STA &0200,X :\ Copy default vectors -DEX:BPL RESETlp:TXS :\ Clear stack 3INX:STX ESCFLG :\ Clear Escape flag 5LDA #TxInit:STA TxStatus :\ Initialise I/O port OPT if(TxControl=0)  LDA #RxInit:STA RxStatus  OPT else  LDA #TxCmd:STA TxCommand *LDA #TxCtl:STA TxControl 4OPT endif >CLI:JSR PrBanner:JSR OSNEWL H4CLC:LDA #&01:JMP OSQUIT :\ Enter main program R: \ .osBYTE fCMP #&83:BCC osBYTEexit pCMP #&85:BCS osBYTEexit zLDX #0:LDY #MEMBOT% 256 ROR A:BCS osBYTEok LDY #MEMTOP% 256  .osBYTEok  ROL A .osBYTEexit RTS : 6OPT if(RDLINE%) :\ Perform RDLINE locally  .osWORD 4STX LPTR+0:STY LPTR+1 :\ LPTR=>control block string buffer, Y=0 .Word00Lp1 3JSR OSRDCH:BCS Word00Exit :\ Wait for character $+CMP #&7F:BNE Word00Char :\ Not Delete ..Word00Delete 82TYA:BEQ Word00Lp1 :\ Nothing to delete B&LDA #&7F:JSR OSWRCH :\ 127 L.Word00Back V8DEY:JMP Word00Lp1 :\ Dec. counter, loop back `.Word00Char j2CMP #&08:BEQ Word00Delete :\ BS is also Delete t+CMP #&15:BNE Word00Ins :\ Not Ctrl-U ~2TYA:BEQ Word00Lp1 :\ Nothing to delete  LDA #&7F .Word00Lp2 2JSR OSWRCH:DEY :\ Delete characters BNE Word00Lp2 3BEQ Word00Lp1 :\ Jump back to start .Word00Ins 0STA (LPTR),Y :\ Store character 0CMP #&0D:CLC:BEQ Word00cr :\ Return - finish 2CMP #&20:BCC Word00ctrl :\ Control character :INY:BEQ Word00Back :\ Too long, dec and go back .Word00ctrl 0JSR OSWRCH :\ Print character .Word00max  .JMP Word00Lp1 :\ Loop for more  .Word00cr 9JSR OSNEWL:CLC :\ Return with CC, Y=length (.Word00Exit 2RTS <OPT endif F: P\ Default error handler Z\ ===================== d.ErrorHandler nJSR OSNEWL xLDX FAULT+0:LDY FAULT+1 2INX:BNE P%+3:INY :\ XY=>error string 4JSR PRSTRNG :\ Print error string  .HALT *JMP HALT :\ And stop : \ Interrupt handlers \ ================== .IRQHandler >STA IRQA:PLA:PHA :\ Save A, get flags from stack ; #&10:BNE BRKHandler :\ If BRK, jump to BRK handler after BRK opcode @8PLA:TAX:LDA IRQA :\ Restore X, get saved A JECLI:JMP (BRKV) :\ Restore IRQs, jump to Error Handler T.IRQ2Handler ^+LDA IRQA :\ Restore A h.NMIHandler r6RTI :\ Return from interupt |: 3\ OSRDCH - Wait for character from input stream 3\ ============================================= &\ On exit, A =char, Cy=Escape flag  .osRDCH 4JSR ReadData:BCC osRDCH :\ Wait for character BNE osRDCH2  .osRDCH1 4JSR ReadData:BCC osRDCH1 :\ Wait for character  .osRDCH2 8CMP #27:BEQ osRDCH3 :\ Exit with CS if Escape .ReadDataNone 2CLC :\ CC if not Escape  .osRDCH3 RTS : .\ OSWRCH - Send character to output stream &.\ ======================================== 0\ On entry, A =character :9.osWRCH :\ WRCH is simply SendByte D .SendByte N+JSR SendData :\ Send byte X2CMP #esc:BNE SendByteDone :\ If not esc, done b<\ :\ Fall through to send again l: v:  \ *** LOW-LEVEL I/O CODE ***  \ ========================== : \ Send a raw byte of data \ -----------------------  .SendData PHA  .SendWait OPT if(TxRDY) ,LDA TxStatus :\ Get Status ; #TxRDY:BEQ SendWait :\ Wait until data can be sent OPT endif OPT if(TxDelay) 9LDA #TxDelay:SEC :\ 6551-style TxRDY bugfix  .SendWaitDelay SBC #1:BNE SendWaitDelay  OPT endif *+PLA:STA TxData :\ Send data 4.SendByteDone >RTS H: R\ Read raw data \\ ------------- f\ On exit, P =CC, no data p .ReadData z,LDA RxStatus: #RxRDY :\ Get RxStatus 9BNE ReadDataNone :\ Exit if no data present embedded string GJSR PrString2:JMP (TEXT) :\ Print string and jump back to code (: 2 .PrString <4STX TEXT+0:STY TEXT+1 :\ TEXT=>string at YX F.PrStringLp P/LDY #&00:LDA (TEXT),Y :\ Get character ZL%:"ERROR: Code overrun": : "Saving ";name$; A "Save "+name$+" "+~mcode%+" "+~O%+" "+~load%+" "+~load%