> ClientTu/src 8 Source for Atom/System kernel for 6502 CoProcessor : (G >&8000:ș "OS_GetEnv"A$:A$,5)<>"B6502":"B6502"+A$,A$," ")) 2 :" at line ";: <: Fsave$="KernelTube" Pload%=&F800: mcode% &900 Z: d/nmiv =&200:brkv =&202:irq1v=&204:cliv =&206 n/wrchv=&208:rdchv=&20A:loadv=&20C:savev=&20E x/rdarv=&210:starv=&212:bgetv=&214:bputv=&216 $findv=&218:shutv=&21A:EVNTV=&220 0 &0E21 - keypress, b7=1 - nothing pressed : ERRBUF=&236:INPBUF=&236 :  Memory addresses: - &EC/D =>address to enter on MOS startup & &EE/F = PROG - Current program & &F0/1 = NUM - hex accumulator $ &F2/3 = MEMTOP - top of memory ? &F4/5 = address of byte transfer address, NMIAddr or ADDR , &F6/7 = ADDR - Data transfer address 2 &F8/9 = String pointer, OSWORD control block J &FA/B = CTRL - OSFILE, OSGBPB control block, PrText string pointer  &FC = IRQ A store  &FD/E => last error " &FF = Escape flag ,: 6" &0236 = command input buffer @" &2EE = OSFILE control block J: T P=01 ^P%=load%:O%=mcode% h[OPT P*3+4+16 r .RESET | LDX #&00  .LF802 9LDA &FF00,X:STA &FF00,X :\ Copy entry block to RAM DEX:BNE LF802  LDX #&36  .LF80D 8LDA LFF80,X:STA &200,X :\ Set up default vectors DEX:BPL LF80D -TXS:LDX #&F0 :\ Clear stack  .LF819 CLDA &FDFF,X:STA &FDFF,X :\ Copy &FE00-&FEEF to RAM, avoiding :DEX:BNE LF819 :\ Tube registers at &FEFx 5LDY #RESET 255:STY &F8 :\ Point to start of ROM LDA #RESET 256:STA &F9 9.LF82A :\ Copy rest of ROM to RAM 4LDA (&F8),Y:STA (&F8),Y :\ Copy a page to RAM 4INY:BNE LF82A :\ Loop for 256 bytes &8INC &F9:LDA &F9 :\ Inc. address high byte 0:CMP #&FE:BNE LF82A :\ Loop from &F800 to &FDFF : LDX #&10 D .LF83B N8LDA LF859,X:STA &0100,X :\ Copy jump code to &100 XDEX:BPL LF83B b5LDA &EE:STA &F6 :\ Copy &EE/F to &F6/7 lLDA &EF:STA &F7 v3LDA #&00:STA &FF :\ Clear Escape flag ESTA &F2:LDA #&F8:STA &F3 :\ Set memtop to start of ROM at &F800 EJMP &0100 :\ Jump via low memory to page ROM out  ,\ Executed in low memory to page ROM out ,\ --------------------------------------  .LF859 FLDA TubeS1:CLI :\ Check Tube R1 status to page ROM out  .LF85D CJMP LF860 :\ Jump to initilise I/O with banner   .LF860 8JSR PrText :\ Display startup banner HEQUB 10:EQUS "Acorn Atom/System Tube" :\ ** Different from 6502 TUBE "EQUB 10:EQUB 10:EQUB 13:EQUB 0  NOP @LDA #CmdOSLoop 255 :\ Next time RESET is soft entered,  4STA LF85D+1 :\ banner not printed *LDA #CmdOSLoop 256 4STA LF85D+2 >ALDA #&00 :\ Look for a entry point at &EC/D HLDX &EC:LDY &ED:STA &ED RBNE JumpToCode \6JSR WaitByte :\ Wait for Acknowledge f* ":NOP 0LDA #"*":JSR OSWRCH :\ Print '*' prompt LDX #LF95D 255 LDY #LF95D 256 5LDA #&00:JSR XOSWORD :\ Read line to INPBUF BCS CmdOSEscape LDX #INPBUF 255 /LDY #INPBUF 256 :\ Execute command copyright message \ \ Now check for &00,"(C)" @LDY #&00:LDA (&FD),Y:BNE LF8FA :\ Jump if no initial &00 8INY:LDA (&FD),Y:CMP #&28:BNE LF8FA :\ Jump if no '(' 8INY:LDA (&FD),Y:CMP #&43:BNE LF8FA :\ Jump if no 'C' 8INY:LDA (&FD),Y:CMP #&29:BNE LF8FA :\ Jump if no ')' \ \ &00,"(C)" exists  6LDY #&06:LDA (&EE),Y :\ Get ROM type < #&4F:CMP #&40:BCC NotLanguage :\ b6=0, not a language F #&0D:BNE Not6502Code :\ type<>0 and <>2, not 6502 code (+]:z%=P%-z%:P%=P%-z%:O%=O%-z%:[OPT P*3+4 2 .LF8FA <=LDA #&01:JMP (&00F2) :\ Enter code with A=1 F\ P.z% ZD\ Any existing error handler will probably have been overwritten d9\ Set up new error handler before generating an error n.NotLanguage x=LDA #ErrorHandler 255:STA brkv+0 :\ Claim error handler &LDA #ErrorHandler 256:STA brkv+1 3BRK:EQUB 0:EQUS "This is not a language":EQUB 0  .Not6502Code =LDA #ErrorHandler 255:STA brkv+0 :\ Claim error handler &LDA #ErrorHandler 256:STA brkv+1 3BRK:EQUB 0:EQUS "I cannot run this code":EQUB 0 +]:z%=P%-z%:P%=P%-z%:O%=O%-z%:[OPT P*3+4  \ Default error handler \ ===================== ;\ On Atom, adjustment of &FD/E is done in error handler \ SP=>flags, ret.lo, ret.hi \ .ErrorHandler *TXA:PHA :\ Save X ":TSX:LDA &0103,X :\ Get address from stack ,CLD:SEC:SBC #&01:STA &FD 6;LDA &0104,X:SBC #&00:STA &FE :\ &FD/E=>after BRK opcode @:PLA:TAX:LDA &FC:CLI :\ Restore X, get saved A J T,\ Now continue into normal error handler ^-LDX #&FF:TXS :\ Clear stack hJSR OSNEWL:LDY #&01 r .LF94D |4LDA (&FD),Y:BEQ LF957 :\ Print error string JSR OSWRCH:INY:BNE LF94D  .LF957 8JSR OSNEWL:JMP CmdOSLoop :\ Jump to command prompt  ,\ Control block for command prompt input ,\ --------------------------------------  .LF95D >EQUW INPBUF :\ Input text to INPBUF at &236 6EQUB &B7 :\ Up to &CA characters 2EQUB &20:EQUB &FF :\ Min=&20, Max=&FF   \ MOS ERFACE \ ============= \ \ &.\ OSWRCH - Send character to output stream 0.\ ======================================== :\ On entry, A =character D\ On exit, A =preserved N\ X\ Tube data character -- b\ l.osWRCH:.atomWRCH v5BIT TubeS1 :\ Read Tube R1 status 3NOP:BVC osWRCH :\ Loop until b6 set ;STA TubeR1:RTS :\ Send character to Tube R1   )\ A bit of hand-holding for Atom RDCH )\ -----------------------------------  .atomRDCH BIT &FF:BPL doRDCH +LDA #&7E:JSR XOSBYTE :\ Ack. any Escape  .doRDCH 0LDA #&FF:STA &0E21 :\ Set 'no key pressed' 0 :\ Continue into osRDCH    3\ OSRDCH - Wait for character from input stream 3\ =============================================  &\ On exit, A =char, Cy=Escape flag *\ 4$\ Tube data &00 -- Carry Char >\ H .osRDCH R;LDA #&00:JSR SendCommand :\ Send command &00 - OSRDCH \6.WaitCarryChar :\ Wait for Carry and A f0JSR WaitByte:ASL A :\ Wait for carry p .WaitByte z=BIT TubeS2:BPL WaitByte :\ Loop until Tube R2 has data 1LDA TubeR2 :\ Fetch character .NullReturn RTS   \ Skip Spaces \ =========== .SkipSpaces1 INY .SkipSpaces (LDA (&F8),Y:CMP #&20:BEQ SkipSpaces1 RTS   \ Scan hex \ ======== $ .ScanHex .7LDX #&00:STX &F0:STX &F1 :\ Clear hex accumulator 8 .LF98C B7LDA (&F8),Y :\ Get current character L,CMP #&30:BCC LF9B1 :\ <'0', exit V>CMP #&3A:BCC LF9A0 :\ '0'..'9', add to accumulator `= #&DF:SBC #&07:BCC LF9B1:\ Convert letter, if <'A', exit j,CMP #&40:BCS LF9B1 :\ >'F', exit t .LF9A0 ~%ASL A:ASL A:ASL A:ASL A :\ *16 :LDX #&03 :\ Prepare to move 3+1 bits .LF9A6 string .SendStringF8  LDY #&00  .LF9B8 (7BIT TubeS2:BVC LF9B8 :\ Wait for Tube R2 free 2;LDA (&F8),Y:STA TubeR2 :\ Send character to Tube R2 <6INY:CMP #&0D:BNE LF9B8 :\ Loop until sent F?LDY &F9:RTS :\ Restore Y from &F9 and return P Z d\ - Execute command n\ ======================= x\ Command string is at &100 \ .atomCLI CLDX #&00:LDY #&01 :\ Point XY=>&100, Atom command buffer  "\ On entry, XY=>command string \ On exit, XY= preserved \ .osCLI ?PHA:STX &F8:STY &F9 :\ Save A, &F8/9=>command string LDY #&00 .LF9D1 JSR SkipSpaces:INY 5CMP #"*":BEQ LF9D1 :\ Skip spaces and stars : #&DF:TAX :\ Ignore case, and save in X 4LDA (&F8),Y :\ Get next character 3CPX #"G":BEQ CmdGO :\ Jump to check '*GO' "@CPX #"H":BNE osCLI_IO :\ Not "H---", jump to pass to Tube ,4CMP #".":BEQ CmdHELP :\ "H.", jump to do *Ǔ 6+ #&DF :\ Ignore case @ACMP #"E":BNE osCLI_IO :\ Not "HE---", jump to pass to Tube J4INY:LDA (&F8),Y :\ Get next character T5CMP #".":BEQ CmdHELP :\ "HE.", jump to do *Ǔ ^+ #&DF :\ Ignore case hBCMP #"L":BNE osCLI_IO :\ Not "HEL---", jump to pass to Tube r4INY:LDA (&F8),Y :\ Get next character |6CMP #".":BEQ CmdHELP :\ "HEL.", jump to do *Ǔ + #&DF :\ Ignore case CCMP #"P":BNE osCLI_IO :\ Not "HELP---", jump to pass to Tube 4INY:LDA (&F8),Y :\ Get next character + #&DF :\ Ignore case GCMP #"A":BCC CmdHELP :\ "HELP" terminated by non-letter, do *Ǔ GCMP #"[":BCC osCLI_IO :\ "HELP" followed by letter, pass to Tube  &\ *Help - Display help information &\ -------------------------------- .CmdHELP 4JSR PrText :\ Print help message IEQUB 10:EQUB 13:EQUS "65C102 Tube Atom/System MOS 0.10 (21 Feb 2012)" EQUB 10:EQUB 13 HNOP :\ Continue to pass '*Ǔ' command to Tube   &#\ - Send command line to host 0'\ ================================= :%\ On entry, &F8/9=>command string D\ N/\ Tube data &02 string &0D -- &7F or &80 X\ b .osCLI_IO l6LDA #&02:JSR SendCommand :\ Send command &02 - v>JSR SendStringF8 :\ Send command string at &F8/9 .osCLI_Ack :JSR WaitByte :\ Wait for acknowledgement 6LDA &EF:PHA:LDA &EE:PHA :\ Save current program HJSR EnterCode R=PLA:STA &EE:STA &F2 :\ Restore current program and \BPLA:STA &EF:STA &F3 :\ set address top of memory to it f PLA:RTS p z .CheckAck BEQ osCLI_Ack   !\ OSBYTE - Byte MOS functions !\ =========================== )\ On entry, A, X, Y=OSBYTE parameters \ On exit, A preserved *\ If A<&80, X=returned value 5\ If A>&7F, X, Y, Carry=returned values \ .osBYTE 7CMP #&80:BCS ByteHigh :\ Jump for long OSBYTEs \ !\ Tube data &04 X A -- X \ PHA:LDA #&04 $ .LFA7A .7BIT TubeS2:BVC LFA7A :\ Wait for Tube R2 free 8=STA TubeR2 :\ Send command &04 - OSBYTELO B .LFA82 L7BIT TubeS2:BVC LFA82 :\ Wait for Tube R2 free V7STX TubeR2:PLA :\ Send single parameter ` .LFA8B j7BIT TubeS2:BVC LFA8B :\ Wait for Tube R2 free t/STA TubeR2 :\ Send function ~ .LFA93 ?BIT TubeS2:BPL LFA93 :\ Wait for Tube R2 data present 2LDX TubeR2:RTS :\ Get return value   .ByteHigh 7CMP #&82:BEQ Byte82 :\ Read memory high word 7CMP #&83:BEQ Byte83 :\ Read bottom of memory 4CMP #&84:BEQ Byte84 :\ Read top of memory \ &\ Tube data &06 X Y A -- Cy Y X \ PHA:LDA #&06  .LFAAB 7BIT TubeS2:BVC LFAAB :\ Wait for Tube R2 free  =STA TubeR2 :\ Send command &06 - OSBYTEHI  .LFAB3 7BIT TubeS2:BVC LFAB3 :\ Wait for Tube R2 free (2STX TubeR2 :\ Send parameter 1 2 .LFABB <7BIT TubeS2:BVC LFABB :\ Wait for Tube R2 free F2STY TubeR2 :\ Send parameter 2 PPLA Z .LFAC4 d7BIT TubeS2:BVC LFAC4 :\ Wait for Tube R2 free n/STA TubeR2 :\ Send function xICMP #&8E:BEQ CheckAck :\ If select language, check to enter code 9CMP #&9D:BEQ LFAEF :\ Fast return with Fast /PHA :\ Save function  .LFAD5 ?BIT TubeS2:BPL LFAD5 :\ Wait for Tube R2 data present +LDA TubeR2:ASL A:PLA :\ Get Carry  .LFADF ?BIT TubeS2:BPL LFADF :\ Wait for Tube R2 data present 6LDY TubeR2 :\ Get return high byte  .LFAE7 ?BIT TubeS2:BPL LFAE7 :\ Wait for Tube R2 data present 5LDX TubeR2 :\ Get return low byte  .LFAEF RTS  B.Byte84:LDX &F2:LDY &F3:RTS :\ Read top of memory from &F2/3 :.Byte83:LDX #&00:LDY #&10:RTS :\ Read bottom of memory "E.Byte82:LDX #&00:LDY #&00:RTS :\ Return &0000 as memory high word , 6 @ \ OSWORD - Various functions J \ ========================== T\ On entry, A =function ^!\ XY=>control block h\ r .osWORD |6STX &F8:STY &F9 :\ &F8/9=>control block =TAY:BEQ RDLINE :\ OSWORD 0, jump to read line PHA:LDY #&08  .LFB09 9BIT TubeS2:BVC LFB09 :\ Loop until Tube R2 free ;STY TubeR2 :\ Send command &08 - OSWORD  .LFB11 9BIT TubeS2:BVC LFB11 :\ Loop until Tube R2 free /STA TubeR2 :\ Send function 9TAX:BPL WordSendLow :\ Jump with functions<&80 JLDY #&00:LDA (&F8),Y :\ Get send block length from control block LDA (&F8),Y:STA TubeR2 :\ Send byte from control block l H R"\ RDLINE - Read a line of text \"\ ============================ f\ On entry, A =0 p!\ XY=>control block z\ On exit, A =undefined ,\ Y =length of returned string $\ Cy=0 ok, Cy=1 Escape \ 5\ Tube data &0A block -- &FF or &7F string &0D \  .RDLINE ;LDA #&0A:JSR SendCommand :\ Send command &0A - RDLINE  LDY #&04  .LFB7E 7BIT TubeS2:BVC LFB7E :\ Wait for Tube R2 free 4LDA (&F8),Y:STA TubeR2 :\ Send control block 2DEY:CPY #&01:BNE LFB7E :\ Loop for 4, 3, 2 ?LDA #&07:JSR SendByte :\ Send &07 as address high byte CLDA (&F8),Y:PHA :\ Get text buffer address high byte DEY  .LFB96 $7BIT TubeS2:BVC LFB96 :\ Wait for Tube R2 free .>STY TubeR2 :\ Send &00 as address low byte 8BLDA (&F8),Y:PHA :\ Get text buffer address low byte B3LDX #&FF:JSR WaitByte :\ Wait for response L9CMP #&80:BCS RdLineEscape :\ Jump if Escape returned V8PLA:STA &F8:PLA:STA &F9 :\ Set &F8/9=>text buffer ` LDY #&00 j .RdLineLp t?BIT TubeS2:BPL RdLineLp :\ Wait for Tube R2 data present ~:LDA TubeR2:STA (&F8),Y :\ Store returned character 1INY:CMP #&0D:BNE RdLineLp :\ Loop until ?LDA #&00:DEY:CLC:INX :\ Return A=0, Y=len, X=00, Cy=0 RTS : .RdLineEscape ?PLA:PLA:LDA #&00 :\ Return A=0, Y=len, X=FF, Cy=1 RTS   $\ OSRDAR - Read file's arguments $\ ------------------------------ &\ On entry, X=>zero page location \ Y=handle  \ A=0 - read \ A=1 - read &\ A=2 - read allocation (,\ On exit, X+0-X+3 = returned argument 2 \ A,X,Y preserved < .atomRDAR F:PHA:CLC:BCC doARGS :\ Jump to do even-numbered OSARGS P Z#\ OSSTAR - Set file's arguments d#\ ----------------------------- n&\ On entry, X=>zero page location x\ Y=handle 1\ A=0 - write (usually, A=unset) #\ X+0-X+3 = argument  \ On exit, A,X,Y preserved  .atomSTAR 1PHA:LDA #0:SEC :\ Do odd-numbered OSARGS  .doARGS 3ROL A:JSR osARGS :\ Convert to OSARGS action  PLA:RTS   %\ OSARGS - Read info on open file %\ =============================== \ On entry, A =function *\ X =>data word in zero page \ Y =handle !\ On exit, A =returned value "\ X preserved ,\ Y preserved 6\ @<\ Tube data &0C handle block function -- result block J\ T .osARGS ^=PHA:LDA #&0C:JSR SendCommand :\ Send command &0C - OSARGS h .LFBD2 r9BIT TubeS2:BVC LFBD2 :\ Loop until Tube R2 free |-STY TubeR2 :\ Send handle 0LDA &03,X:JSR SendByte :\ Send data word LDA &02,X:JSR SendByte LDA &01,X:JSR SendByte LDA &00,X:JSR SendByte /PLA:JSR SendByte :\ Send function 5JSR WaitByte:PHA :\ Get and save result 3JSR WaitByte:STA &03,X :\ Receive data word JSR WaitByte:STA &02,X JSR WaitByte:STA &01,X JSR WaitByte:STA &00,X zero page &#\ X+0/1=file name 0&\ CS=Open file for input :'\ CC=Open file for output D3\ On exit, A=file handle, 0 if file not found N\ X,Y=preserved X .atomFIND b/PHA :\ Space for returned A l#TYA:PHA:TXA:PHA :\ Save X,Y v'LDA 1,X:TAY :\ XY=>filename LDA 0,X:TAX / :\ Create OSFIND action 'LDA #0 :\ A=00, CS CC 'PHP:ROR A:PLP:ROR A :\ C0 00 % #&80 :\ 40 80 .JSR osFIND :\ Pass OSFIND to host )TSX:STA &103,X :\ Store on stack &PLA:TAX:PLA:TAY :\ Restore X,Y 0PLA:RTS :\ Get handle and return  \ OSSHUT - Close a file \ --------------------- \ On entry, Y=file handle \ On exit, all preserved  .atomSHUT -PHA:LDA #0 :\ OSFIND &00 - Close  .JSR osFIND :\ Pass OSFIND to host * PLA:RTS 4 > H#\ OSFIND - Open of Close a file R#\ ============================= \\ On entry, A =function f)\ Y =handle or XY=>filename p!\ On exit, A =zero or handle z\ 4\ Tube data &12 function string &0D -- handle (\ &12 &00 handle -- &7F \  .osFIND =PHA:LDA #&12:JSR SendCommand :\ Send command &12 - OSFIND 1PLA:JSR SendByte :\ Send function ;CMP #&00:BNE OPEN :\ If <>0, jump to do OPEN /PHA:TYA:JSR SendByte :\ Send handle QJSR WaitByte:PLA:RTS :\ Wait for acknowledge, restore regs and return  .OPEN 1JSR SendString :\ Send pathname >JMP WaitByte :\ Wait for and return handle   (\ OSBGET - Get a byte from open file (\ ================================== $\ On entry, Y =handle .\ On exit, A =byte Read 8\ Y =preserved B\ Cy set if L\ V*\ Tube data &0E handle -- Carry byte `\ j.osBGET:.atomBGET t;LDA #&0E:JSR SendCommand :\ Send command &0E - OSBGET ~-TYA:JSR SendByte :\ Send handle AJMP WaitCarryChar :\ Jump to wait for Carry and byte   )\ OSBPUT - Put a byte to an open file )\ ===================================  \ On entry, A =byte to write \ Y =handle \ On exit, A =preserved \ Y =preserved \ )\ Tube data &10 handle byte -- &7F \ .osBPUT:.atomBPUT  =PHA:LDA #&10:JSR SendCommand :\ Send command &10 - OSBPUT /TYA:JSR SendByte :\ Send handle -PLA:JSR SendByte :\ Send byte (CPHA:JSR WaitByte:PLA:RTS :\ Wait for acknowledge and return 2 < F\ Send a byte to Tube R2 P\ ====================== Z.SendCommand d .SendByte n7BIT TubeS2:BVC SendByte :\ Wait for Tube R2 free x6STA TubeR2:RTS :\ Send byte to Tube R2   \ OSLOAD - Load a file \ -------------------- \ On entry, X=>zero page $\ X+0/1=>file name &\ X+2/3=Load address A\ X+4 =if bit 7=0 use the file's start address %\ CC=Return immediately 7\ CS=Wait until IRQ/DMA actions completed \ On exit, all preserved \  .atomLOAD LDA #&FF:BNE doFILE  \ OSSAVE - Save a file "\ -------------------- ,\ On entry, X=>zero page 6#\ X+0/1=file name @&\ X+2/3=load address J+\ X+4/5=execution address T7\ X+6/7=start address of data to save ^9\ X+8/9=(end address)+1 of data to save h%\ CC=Return immediately r7\ CS=Wait until IRQ/DMA actions completed |\ On exit, all preserved  .atomSAVE  LDA #&00  .doFILE PHA TYA:PHA:TXA:PHA %LDA 0,X:STA &2EE :\ =>filename LDA 1,X:STA &2EF  LDY #0  .doFILElp LDA 2,X:STA &2F0,Y:INX:INY LDA 2,X:STA &2F0,Y:INX:INY /LDA #0 :\ Expand control block STA &2F0,Y:INY STA &2F0,Y:INY CPY #16:BNE doFILElp ,TSX:LDA &103,X :\ Get OSFILE action &CMP #&FF:BNE callFILE 0LDA &2F4: #&FF :STA &2F4:LDA #&FF D .callFILE N1LDX #&EE:LDY #&02 :\ Point to control block X.JSR osFILE :\ Pass OSFILE to host b6TSX:STA &103,X :\ Store return value on stack l,PLA:TAX:PLA:TAY :\ Restore registers v6PLA:RTS :\ Get return value and return   %\ OSFILE - Operate on whole files %\ =============================== \ On entry, A =function !\ XY=>control block \ On exit, A =result %\ control block updated \ A\ Tube data &14 block string function -- result block \  .osFILE 8STY &FB:STX &FA :\ &FA/B=>control block =PHA:LDA #&14:JSR SendCommand :\ Send command &14 - OSFILE  LDY #&11  .LFC5F  4LDA (&FA),Y:JSR SendByte :\ Send control block *3DEY:CPY #&01:BNE LFC5F :\ Loop for &11..&02 4DEY:LDA (&FA),Y:TAX >control block !\ On exit, A =returned value (\ control block updated \ <\ Tube data &16 block function -- block Carry result \  .osGBPB 8STY &FB:STX &FA :\ &FA/B=>control block $=PHA:LDA #&16:JSR SendCommand :\ Send command &16 - OSGBPB . LDY #&0C 8 .LFC9A B4LDA (&FA),Y:JSR SendByte :\ Send control block L3DEY:BPL LFC9A :\ Loop for &0C..&00 V/PLA:JSR SendByte :\ Send function ` LDY #&0C j .LFCA8 t8JSR WaitByte:STA (&FA),Y :\ Get control block back ~3DEY:BPL LFCA8 :\ Loop for &0C..&00 3LDY &FB:LDX &FA :\ Restore registers >JMP WaitCarryChar :\ Jump to get Carry and result   "\ OSWORD control block lengths "\ ============================ .WordLengthsLo 'EQUB &00:EQUB &05:EQUB &00:EQUB &05 ]EQUB &04:EQUB &05:EQUB &08:EQUB &0E :\ ** Different, 6502 TUBE sends only 2 bytes for =IO 'EQUB &04:EQUB &01:EQUB &01:EQUB &05 'EQUB &00:EQUB &01:EQUB &20:EQUB &10 'EQUB &0D:EQUB &00:EQUB &04:EQUB &80 .WordLengthsHi  'EQUB &05:EQUB &00:EQUB &05:EQUB &00 'EQUB &05:EQUB &00:EQUB &00:EQUB &00 'EQUB &05:EQUB &09:EQUB &05:EQUB &00 ('EQUB &08:EQUB &18:EQUB &00:EQUB &01 2'EQUB &0D:EQUB &80:EQUB &04:EQUB &80 < F P\ Interrupt Handler Z\ ================= d.InterruptHandler n>STA &FC:PLA:PHA :\ Save A, get flags from stack x; #&10:BNE BRKHandler :\ If BRK, jump to BRK handler <\LDA &FC:\JMP (irq1v) :\ Continue via IRQ1V handler  .IRQ1Handler [BIT TubeS4:BMI LFD3F :\ If data in Tube R4, jump to process errors and transferes WBIT TubeS1:BMI LFD18 :\ If data in Tube R1, jump to process Escape and Events 2LDA &FC:PHA:JMP (irq1v) :\ Pass on to IRQ1V   ,\ Interrupt generated by data in Tube R1 ,\ --------------------------------------  .LFD18 @LDA TubeR1:BMI LFD39 :\ b7=1, jump to set Escape state 0TYA:PHA:TXA:PHA :\ Save registers >JSR LFE80:TAY :\ Get Y parameter from Tube R1 >JSR LFE80:TAX :\ Get X parameter from Tube R1 ?JSR LFE80 :\ Get event number from Tube R1 "CJSR LFD36:PLA:TAX:PLA:TAY :\ Dispatch event, restore registers ,BLDA &FC:RTI :\ Restore A, return from interrupt 6 .LFD36 @JMP (EVNTV) J .LFD39 T9ASL A:STA &FF :\ Set Escape flag from b6 ^BLDA &FC:RTI :\ Restore A, return from interrupt h r |,\ Interrupt generated by data in Tube R4 ,\ --------------------------------------  .LFD3F >LDA TubeR4:BPL LFD65 :\ b7=0, jump for data transfer CLI  .LFD45 :BIT TubeS2:BPL LFD45 :\ Wait for data in Tube R2 LDA TubeR2 BLDA #&00:STA ERRBUF:TAY :\ Store BRK opcode in error buffer 2JSR WaitByte:STA ERRBUF+1 :\ Get error number  .LFD59 BINY:JSR WaitByte :\ Store bytes fetched from Tube R2 7STA ERRBUF+1,Y:BNE LFD59 :\ Loop until final zero GJMP ERRBUF :\ Jump to error block to generate error  0\ Data transfer initiated by IRQ via Tube R4 0\ ------------------------------------------ & .LFD65 0@CMP #&06:BCC LFDE7 :\ Exit if not 256-byte transfers !H9BNE LFDEC :\ Jump with 256-byte read !R !\#\ Send 256 bytes to Tube via R3 !f#\ ----------------------------- !p LDY #&00 !z .LFDCF !7LDA TubeS3: #&80:BPL LFDCF:\ Wait for Tube R3 free ! .NMI6Addr !@LDA &FFFF,Y:STA TubeR3 :\ Fetch byte and send to Tube R3 !4INY:BNE LFDCF :\ Loop for 256 bytes ! .LFDDF !7BIT TubeS3:BPL LFDDF :\ Wait for Tube R3 free !6STA TubeR3 :\ Send final sync byte ! .LFDE7 !>PLA:TAY:LDA &FC:RTI :\ Restore registers and return ! !%\ Read 256 bytes from Tube via R3 !%\ ------------------------------- ! .LFDEC " LDY #&00 " .LFDEE "?LDA TubeS3: #&80:BPL LFDEE:\ Wait for Tube R3 data present "$9LDA TubeR3 :\ Fetch byte from Tube R3 ". .NMI7Addr "8CSTA &FFFF,Y:INY:BNE LFDEE :\ Store byte and loop for 256 bytes "BFBEQ LFDE7 :\ Jump to restore registers and return "L "V/\ Transfer 0 - Transfer single byte to Tube "`/\ ----------------------------------------- "j .NMI0 "t(PHA :\ Save A "~ .NMI0Addr ">LDA &FFFF:STA TubeR3 :\ Get byte and send to Tube R3 "LDA (&F6),Y:STA TubeR3 :\ Get byte and send to Tube R3 #nLDA (&F6),Y:STA TubeR3 :\ Get byte and send to Tube R3 #PLA:TAY:PLA:RTI :\ Restore registers and return # #/\ Transfer 3 - Transfer two bytes from Tube #/\ ----------------------------------------- # .NMI3 #0PHA:TYA:PHA:LDY #&00 :\ Save registers #ALDA TubeR3:STA (&F6),Y :\ Get byte from Tube R3 and store #PLA:TAY:PLA:RTI :\ Restore registers and return $" $,$\ Data transfer address pointers $6$\ ------------------------------ $@ .LFE60 $J3EQUB (NMI0Addr+1) 255:EQUB (NMI1Addr+1) 255 $T,EQUB &00F6 255 :EQUB &00F6 255 $^,EQUB &00F6 255 :EQUB &00F6 255 $h3EQUB (NMI6Addr+1) 255:EQUB (NMI7Addr+1) 255 $r .LFE68 $|3EQUB (NMI0Addr+1) 256:EQUB (NMI1Addr+1) 256 $,EQUB &00F6 256 :EQUB &00F6 256 $,EQUB &00F6 256 :EQUB &00F6 256 $3EQUB (NMI6Addr+1) 256:EQUB (NMI7Addr+1) 256 $ $%\ Data transfer routine addresses $%\ ------------------------------- $ .LFE70 $&EQUB NMI0 255 :EQUB NMI1 255 $&EQUB NMI2 255 :EQUB NMI3 255 $)EQUB NMI_Ack 255:EQUB NMI_Ack 255 $)EQUB NMI_Ack 255:EQUB NMI_Ack 255 $ .LFE78 $&EQUB NMI0 256 :EQUB NMI1 256 %&EQUB NMI2 256 :EQUB NMI3 256 %)EQUB NMI_Ack 256:EQUB NMI_Ack 256 %)EQUB NMI_Ack 256:EQUB NMI_Ack 256 %& %0 %:B\ Wait for byte in Tube R1 while allowing requests via Tube R4 %DB\ ============================================================ %N .LFE80 %XFBIT TubeS1:BMI LFE94 :\ If data in Tube R1, jump to fetch it %b .LFE85 %lBBIT TubeS4 :\ Check if data present in Tube R4 %vNBPL LFE80 :\ If nothing there, jump back to check Tube R1 %BLDA &FC :\ Save IRQ's A store in A register %LPHP:CLI:PLP :\ Allow an IRQ through to process R4 request %QSTA &FC:JMP LFE80 :\ Restore IRQ's A store and jump back to check R1 % .LFE94 %DLDA TubeR1:RTS :\ Fetch byte from Tube R1 and return % %\ Spare space %\ =========== %EQUS &FEF0-P%,255) % % %\ I/O Space %\ ========= &EQUS 8,0) &  &\ Tube I/O Registers & \ ================== &*.TubeS1 :\ &FEF8 :EQUB 0 &4.TubeR1 :\ &FEF9 :EQUB 0 &>.TubeS2 :\ &FEFA :EQUB 0 &H.TubeR2 :\ &FEFB :EQUB 0 &R.TubeS3 :\ &FEFC :EQUB 0 &\.TubeR3 :\ &FEFD :EQUB 0 &f.TubeS4 :\ &FEFE :EQUB 0 &p.TubeR4 :\ &FEFF :EQUB 0 &z & .LFF00 & &\ Print embedded string &\ ===================== & .PrText &8PLA:STA &FA:PLA:STA &FB :\ &FA/B=>embedded string & LDY #&00 & .LFEA0 &3INC &FA:BNE LFEA6:INC &FB :\ Increment address & .LFEA6 &=LDA (&FA),Y:BMI LFEB0 :\ Get character, exit if >&7F &HJSR OSWRCH:JMP LFEA0 :\ Print character and loop back for more & .LFEB0 '@JMP (&00FA) :\ Jump back to code after string ' '\ Print hex '$\ ========= '. .Pr2Hex '8TYA:JSR PrHex:TXA 'B .PrHex 'LPHA:LSR A:LSR A:LSR A:LSR A 'VJSR PrNyb:PLA '` .PrNyb 'j #15:CMP #10:BCC P%+4 'tADC #6:ADC #48:JMP OSWRCH '~ '.BRKHandler 'JLDA &FC:PLP:PHP:JMP (brkv) :\ Restore A and flags, jump to BRK handler ' '\ Null NMI code '\ ------------- ' .NMI_Ack 'CSTA TubeR3:RTI :\ Store to TubeR3 to acknowlege NMI ' '.Unsupported '"BRK:EQUB 255:EQUS "Bad":EQUB 0 ' '%\ Copy of BBC MOS API entry block (%\ =============================== ( EQUS &FF4E-P%,0) (#.XOSFIND :\ &FF4E :JMP osFIND (#.XOSGBPB :\ &FF51 :JMP osGBPB ((#.XOSBPUT :\ &FF54 :JMP osBPUT (2#.XOSBGET :\ &FF57 :JMP osBGET (<#.XOSARGS :\ &FF5A :JMP osARGS (F#.XOSFILE :\ &FF5D :JMP osFILE (P (Z#.XOSRDCH :\ &FF60 :JMP osRDCH (d-.XOSASCI :\ &FF63 :CMP #&0D:BNE XOSWRCH (n-.XOSNEWL :\ &FF67 :LDA #&0A:JSR XOSWRCH (x!.XOSPRCR :\ &FF6C :LDA #&0D (#.XOSWRCH :\ &FF6E :JMP osWRCH (#.XOSWORD :\ &FF71 :JMP osWORD (#.XOSBYTE :\ &FF74 :JMP osBYTE (".XOS_CLI :\ &FF77 :JMP osCLI ( (".XNMIV :\ &FF7A :EQUW NMI0 (#.XRESETV :\ &FF7C :EQUW RESET (..XIRQV :\ &FF7E :EQUW InterruptHandler ( ( (\ AULT VECTOR TABLE (\ ==================== ( .LFF80 )(EQUW NullIRQ :\ &200 - nmiv )(EQUW ErrorHandler :\ &202 - brkv ))EQUW NullIRQ :\ &204 - irq1v )"(EQUW atomCLI :\ &206 - cliv ),)EQUW atomWRCH :\ &208 - wrchv )6)EQUW atomRDCH :\ &20A - rdchv )@)EQUW atomLOAD :\ &20C - loadv )J)EQUW atomSAVE :\ &20E - savev )T)EQUW atomRDAR :\ &210 - rdarv )^)EQUW atomSTAR :\ &212 - starv )h)EQUW atomBGET :\ &214 - bgetv )r)EQUW atomBPUT :\ &216 - bputv )|)EQUW atomFIND :\ &218 - findv ))EQUW atomSHUT :\ &21A - shutv )(EQUW NullReturn :\ &21C - v21C )(EQUW NullReturn :\ &21E - v21E ))EQUW NullReturn :\ &220 - EVNTV )(EQUW Unsupported :\ &222 - v222 )(EQUW Unsupported :\ &224 - v224 )(EQUW Unsupported :\ &226 - v226 )(EQUW Unsupported :\ &228 - v228 ) ) )\ Main MOS API entry block )\ ======================== )9.LFFAA :\ &FFAA :JMP PrHex :\ Print A in hex *:.LFFAD :\ &FFAD :JMP Pr2Hex :\ Print XY in hex *3.LFFB0 :\ &FFB0 :JMP NullIRQ :\ IRQ stub *<.LFFB3 :\ &FFB3 :JMP PrText :\ Print inline text *&,.VECDEF :\ &FFB6 :EQUB &2A:EQUW LFF80 *0(.LFFB9 :\ &FFB9 :JMP Unsupported *:(.LFFBC :\ &FFBC :JMP Unsupported *D>.LFFBF :\ &FFBF :JMP NullReturn :\ Reset vectors, etc. *N(.LFFC2 :\ &FFC2 :JMP Unsupported *X(.LFFC5 :\ &FFC5 :JMP Unsupported *b(.LFFC8 :\ &FFC8 :JMP Unsupported *l *v\ Atom/System Entry Block *\ ----------------------- *$.OSSHUT :\ &FFCB :JMP (shutv) *$.OSFIND :\ &FFCE :JMP (findv) *$.OSBPUT :\ &FFD1 :JMP (bputv) *$.OSBGET :\ &FFD4 :JMP (bgetv) *$.OSSTAR :\ &FFD7 :JMP (starv) *$.OSRDAR :\ &FFDA :JMP (rdarv) *$.OSSAVE :\ &FFDD :JMP (savev) *$.OSLOAD :\ &FFE0 :JMP (loadv) * *$.OSRDCH :\ &FFE3 :JMP (rdchv) *#.OSECHO :\ &FFE6 :JSR OSRDCH *,.OSASCI :\ &FFE9 :CMP #&0D:BNE OSWRCH +,.OSNEWL :\ &FFED :LDA #&0A:JSR OSWRCH + !.OSPRCR :\ &FFF2 :LDA #&0D +$.OSWRCH :\ &FFF4 :JMP (wrchv) + #.OS_CLI :\ &FFF7 :JMP (cliv) +* +4\ Hardware vectors +>\ ---------------- +H:.NMIV :\ &FFFA :EQUW NMI0 :\ NMI Vector +R<.RESETV :\ &FFFC :EQUW RESET :\ RESET Vector +\:.IRQV :\ &FFFE :EQUW InterruptHandler :\ IRQ Vector +f]: +p@"Save "+save$+" "+~mcode%+" "+~O%+" "+~load%+" "+~load% +z : + *Quit