> AtomCP/src 8 Source for Atom/System kernel for 6502 CoProcessor : (G >&8000:ș "OS_GetEnv"A$:A$,5)<>"B6502":"B6502"+A$,A$," ")) 2 :" at line ";: <: Ffname$="KernelCP" 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 IOADDR=&FEE0 IOTUBE=&FEF8 C &0E21 - keypress, b7=1 - nothing pressed, 27=Escape pressed 1 &B001 - key matrix, b5=0 - Escape 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 6 &FD/E => last error @ &FF = Escape flag J: T" &0236 = command input buffer ^" &2EE = OSFILE control block h: r P=01 |P%=load%:O%=mcode% [OPT P*3+4+16  .RESET  LDX #&00  .LF802 9LDA &FF00,X:STA &FF00,X :\ Copy entry block to RAM DEX:BNE LF802  LDX #&36  .LF80D 8LDA VECTABLE,X:STA &200,X :\ Set up default vectors DEX:BPL LF80D -TXS :\ Clear stack LDX #IOADDR 255  .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 09.LF82A :\ Copy rest of ROM to RAM :4LDA (&F8),Y:STA (&F8),Y :\ Copy a page to RAM D4INY:BNE LF82A :\ Loop for 256 bytes N8INC &F9:LDA &F9 :\ Inc. address high byte X:CMP #&FE:BNE LF82A :\ Loop from &F800 to &FDFF b LDX #&10 l .LF83B v8LDA LF859,X:STA &0100,X :\ Copy jump code to &100 DEX:BPL LF83B 5LDA &EE:STA &F6 :\ Copy &EE/F to &F6/7 LDA &EF:STA &F7 3LDA #&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  )EQUB 10:EQUS "Acorn Atom/System Tube" *"EQUB 10:EQUB 10:EQUB 13:EQUB 0 4NOP >@LDA #CmdOSLoop 255 :\ Next time RESET is soft entered, H4STA LF85D+1 :\ banner not printed RLDA #CmdOSLoop 256 \STA LF85D+2 fALDA #&00 :\ Look for a entry point at &EC/D pLDX &EC:LDY &ED:STA &ED zBNE JumpToCode 6JSR WaitByte :\ Wait for Acknowledge * ":NOP :\ Display 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 2< #&4F:CMP #&40:BCC NotLanguage :\ b6=0, not a language 0 and <>2, not 6502 code F+]:z%=P%-z%:P%=P%-z%:O%=O%-z%:[OPT P*3+4 P .LF8FA Z=LDA #&01:JMP (&00F2) :\ Enter code with A=1 d\ n.z% xD\ Any existing error handler will probably have been overwritten 9\ Set up new error handler before generating an error .NotLanguage =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 \ ===================== B\ On Atom/System, adjustment of &FD/E is done in error handler \ SP=>flags, ret.lo, ret.hi "\ ,.ErrorHandler 6*TXA:PHA :\ Save X @:TSX:LDA &0103,X :\ Get address from stack JCLD:SEC:SBC #&01:STA &FD T;LDA &0104,X:SBC #&00:STA &FE :\ &FD/E=>after BRK opcode ^:PLA:TAX:LDA &FC:CLI :\ Restore X, get saved A h r,\ Now continue into normal error handler |-LDX #&FF:TXS :\ Clear stack JSR OSNEWL:LDY #&01  .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 &\ ============= 0\ :\ D.\ OSWRCH - Send character to output stream N.\ ======================================== X\ On entry, A =character b\ On exit, A =preserved l\ v\ Tube data character -- \ .osWRCH:.atomWRCH 5BIT 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 RDCH $\ ------------------------------  .atomRDCH LDA &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 43\ ============================================= >&\ On exit, A =char, Cy=Escape flag H\ R$\ Tube data &00 -- Carry Char \\ f .osRDCH p;LDA #&00:JSR SendCommand :\ Send command &00 - OSRDCH z6.WaitCarryChar :\ Wait for Carry and A 0JSR WaitByte:ASL A :\ Wait for carry  .WaitByte =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 8\ ======== B .ScanHex L7LDX #&00:STX &F0:STX &F1 :\ Clear hex accumulator V .LF98C `7LDA (&F8),Y :\ Get current character j,CMP #&30:BCC LF9B1 :\ <'0', exit t>CMP #&3A:BCC LF9A0 :\ '0'..'9', add to accumulator ~= #&DF:SBC #&07:BCC LF9B1:\ Convert letter, if <'A', exit ,CMP #&40:BCS LF9B1 :\ >'F', exit .LF9A0 %ASL A:ASL A:ASL A:ASL A :\ *16 :LDX #&03 :\ Prepare to move 3+1 bits .LF9A6 string (.SendStringF8 2 LDY #&00 < .LF9B8 F7BIT TubeS2:BVC LF9B8 :\ Wait for Tube R2 free P;LDA (&F8),Y:STA TubeR2 :\ Send character to Tube R2 Z6INY:CMP #&0D:BNE LF9B8 :\ Loop until sent d?LDY &F9:RTS :\ Restore Y from &F9 and return n x \ - Execute command \ ======================= \ 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 63CPX #"G":BEQ CmdGO :\ Jump to check '*GO' @@CPX #"H":BNE osCLI_IO :\ Not "H---", jump to pass to Tube J4CMP #".":BEQ CmdHELP :\ "H.", jump to do *Ǔ T+ #&DF :\ Ignore case ^ACMP #"E":BNE osCLI_IO :\ Not "HE---", jump to pass to Tube h4INY:LDA (&F8),Y :\ Get next character r5CMP #".":BEQ CmdHELP :\ "HE.", jump to do *Ǔ |+ #&DF :\ Ignore case BCMP #"L":BNE osCLI_IO :\ Not "HEL---", jump to pass to Tube 4INY: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 0 : D#\ - Send command line to host N'\ ================================= X%\ On entry, &F8/9=>command string b\ l/\ Tube data &02 string &0D -- &7F or &80 v\ .osCLI_IO 6LDA #&02:JSR SendCommand :\ Send command &02 - >JSR SendStringF8 :\ Send command string at &F8/9 .osCLI_Ack :JSR WaitByte :\ Wait for acknowledgement LDA &F1:STA &F7 H R .LFA5C \6LDA &EF:PHA:LDA &EE:PHA :\ Save current program fJSR EnterCode p=PLA:STA &EE:STA &F2 :\ Restore current program and zBPLA:STA &EF:STA &F3 :\ set address top of memory to it PLA:RTS  .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 .\ 8PHA:LDA #&04 B .LFA7A L7BIT TubeS2:BVC LFA7A :\ Wait for Tube R2 free V=STA TubeR2 :\ Send command &04 - OSBYTELO ` .LFA82 j7BIT TubeS2:BVC LFA82 :\ Wait for Tube R2 free t7STX TubeR2:PLA :\ Send single parameter ~ .LFA8B 7BIT TubeS2:BVC LFA8B :\ Wait for Tube R2 free /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 2 .LFAB3 <7BIT TubeS2:BVC LFAB3 :\ Wait for Tube R2 free F2STX TubeR2 :\ Send parameter 1 P .LFABB Z7BIT TubeS2:BVC LFABB :\ Wait for Tube R2 free d2STY TubeR2 :\ Send parameter 2 nPLA x .LFAC4 7BIT TubeS2:BVC LFAC4 :\ Wait for Tube R2 free /STA TubeR2 :\ Send function ICMP #&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 6:.Byte83:LDX #&00:LDY #&10:RTS :\ Read bottom of memory @E.Byte82:LDX #&00:LDY #&00:RTS :\ Return &0000 as memory high word J T ^ \ OSWORD - Various functions h \ ========================== r\ On entry, A =function |!\ XY=>control block \  .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  .LFB71 H3LDY &F9:LDX &F8:PLA :\ Restore registers RRTS \ f p"\ RDLINE - Read a line of text z"\ ============================ \ On entry, A =0 !\ XY=>control block \ 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 8 .LFB96 B7BIT TubeS2:BVC LFB96 :\ Wait for Tube R2 free L>STY TubeR2 :\ Send &00 as address low byte VBLDA (&F8),Y:PHA :\ Get text buffer address low byte `3LDX #&FF:JSR WaitByte :\ Wait for response j9CMP #&80:BCS RdLineEscape :\ Jump if Escape returned t8PLA:STA &F8:PLA:STA &F9 :\ Set &F8/9=>text buffer ~ LDY #&00  .RdLineLp ?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   %\ OSARGS - Read info on open file  %\ =============================== \ On entry, A =function *\ X =>data word in zero page (\ Y =handle 2!\ On exit, A =returned value <\ X preserved F\ Y preserved P\ Z<\ Tube data &0C handle block function -- result block d\ n .osARGS x=PHA:LDA #&0C:JSR SendCommand :\ Send command &0C - OSARGS  .LFBD2 9BIT 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 J&\ CS=Open file for input T'\ CC=Open file for output ^3\ On exit, A=file handle, 0 if file not found h\ X,Y=preserved r .atomFIND |/PHA :\ Space for returned A #TYA:PHA:TXA:PHA :\ Save X,Y '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 0-PHA:LDA #0 :\ OSFIND &00 - Close :.JSR osFIND :\ Pass OSFIND to host D PLA:RTS N X b#\ OSFIND - Open of Close a file l#\ ============================= v\ On entry, A =function )\ Y =handle or XY=>filename !\ On exit, A =zero or handle \ 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 4(\ ================================== >\ On entry, Y =handle H\ On exit, A =byte Read R\ Y =preserved \\ Cy set if f\ p*\ Tube data &0E handle -- Carry byte z\ .osBGET:.atomBGET ;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 8-PLA:JSR SendByte :\ Send byte BCPHA:JSR WaitByte:PLA:RTS :\ Wait for acknowledge and return L V `\ Send a byte to Tube R2 j\ ====================== t.SendCommand ~ .SendByte 7BIT TubeS2:BVC SendByte :\ Wait for Tube R2 free 6STA 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 ( 2\ OSSAVE - Save a file <\ -------------------- F\ On entry, X=>zero page P#\ X+0/1=file name Z&\ X+2/3=load address d+\ X+4/5=execution address n7\ X+6/7=start address of data to save x9\ X+8/9=(end address)+1 of data to save %\ CC=Return immediately 7\ 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 6,TSX:LDA &103,X :\ Get OSFILE action @CMP #&FF:BNE callFILE JLDA &2F4: #&FF TSTA &2F4:LDA #&FF ^ .callFILE h1LDX #&EE:LDY #&02 :\ Point to control block r.JSR osFILE :\ Pass OSFILE to host |6TSX:STA &103,X :\ Store return value on stack ,PLA:TAX:PLA:TAY :\ Restore registers 6PLA: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 0 .LFC5F :4LDA (&FA),Y:JSR SendByte :\ Send control block D3DEY:CPY #&01:BNE LFC5F :\ Loop for &11..&02 NDEY:LDA (&FA),Y:TAX Xcontrol block !\ On exit, A =returned value (\ control block updated  \ <\ Tube data &16 block function -- block Carry result  \ * .osGBPB 48STY &FB:STX &FA :\ &FA/B=>control block >=PHA:LDA #&16:JSR SendCommand :\ Send command &16 - OSGBPB H LDY #&0C R .LFC9A \4LDA (&FA),Y:JSR SendByte :\ Send control block f3DEY:BPL LFC9A :\ Loop for &0C..&00 p/PLA:JSR SendByte :\ Send function z LDY #&0C  .LFCA8 8JSR 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 8'EQUB &05:EQUB &09:EQUB &05:EQUB &00 B'EQUB &08:EQUB &18:EQUB &00:EQUB &01 L'EQUB &0D:EQUB &80:EQUB &04:EQUB &80 V ` j\ Interrupt Handler t\ ================= ~.InterruptHandler >STA &FC:PLA:PHA :\ Save A, get flags from stack ; #&10:BNE BRKHandler :\ If BRK, jump to BRK handler : [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  .BRKHandler JLDA &FC:PLP:PHP:JMP (brkv) :\ Restore A and flags, jump to BRK handler   ,\ 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 2>JSR LFE80:TAX :\ Get X parameter from Tube R1 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 , 60\ Data transfer initiated by IRQ via Tube R4 @0\ ------------------------------------------ J .LFD65 TPLA:TAY:LDA &FC:RTI :\ Restore registers and return ! ! %\ Read 256 bytes from Tube via R3 !%\ ------------------------------- ! .LFDEC !* LDY #&00 !4 .LFDEE !>?LDA TubeS3: #&80:BPL LFDEE:\ Wait for Tube R3 data present !H9LDA TubeR3 :\ Fetch byte from Tube R3 !R .NMI7Addr !\CSTA &FFFF,Y:INY:BNE LFDEE :\ Store byte and loop for 256 bytes !fFBEQ LFDE7 :\ Jump to restore registers and return !p !z/\ Transfer 0 - Transfer single byte to Tube !/\ ----------------------------------------- ! .NMI0 !(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 "LDA (&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 #F #P$\ Data transfer address pointers #Z$\ ------------------------------ #d .LFE60 #n3EQUB (NMI0Addr+1) 255:EQUB (NMI1Addr+1) 255 #x,EQUB &00F6 255 :EQUB &00F6 255 #,EQUB &00F6 255 :EQUB &00F6 255 #3EQUB (NMI6Addr+1) 255:EQUB (NMI7Addr+1) 255 # .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 $6)EQUB NMI_Ack 256:EQUB NMI_Ack 256 $@)EQUB NMI_Ack 256:EQUB NMI_Ack 256 $J $T $^B\ Wait for byte in Tube R1 while allowing requests via Tube R4 $hB\ ============================================================ $r .LFE80 $|FBIT TubeS1:BMI LFE94 :\ If data in Tube R1, jump to fetch it $ .LFE85 $BBIT TubeS4 :\ Check if data present in Tube R4 $NBPL 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 IOADDR-P%,255) % % %\ I/O Space %&\ ========= %0EQUS IOTUBE-P%,0) %: %D\ Tube I/O Registers %N\ ================== %X.TubeS1 :\ &FEF8 :EQUB 0 %b.TubeR1 :\ &FEF9 :EQUB 0 %l.TubeS2 :\ &FEFA :EQUB 0 %v.TubeR2 :\ &FEFB :EQUB 0 %.TubeS3 :\ &FEFC :EQUB 0 %.TubeR3 :\ &FEFD :EQUB 0 %.TubeS4 :\ &FEFE :EQUB 0 %.TubeR4 :\ &FEFF :EQUB 0 % % .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 &4 &>\ Print hex &H\ ========= &R .Pr2Hex &\TYA:JSR PrHex:TXA &f .PrHex &pPHA:LSR A:LSR A:LSR A:LSR A &zJSR PrNyb:PLA & .PrNyb & #15:CMP #10:BCC P%+4 &ADC #6:ADC #48:JMP OSWRCH & &$\ 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 & \ A,X,Y preserved ' .atomRDAR ':PHA:CLC:BCC doARGS :\ Jump to do even-numbered OSARGS ' '$#\ OSSTAR - Set file's arguments '.#\ ----------------------------- '8&\ On entry, X=>zero page location 'B\ Y=handle 'L1\ A=0 - write (usually, A=unset) 'V#\ X+0-X+3 = argument '` \ On exit, A,X,Y preserved 'j .atomSTAR 't1PHA:LDA #0:SEC :\ Do odd-numbered OSARGS '~ .doARGS '3ROL A:JSR osARGS :\ Convert to OSARGS action ' PLA:RTS ' '\ 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 (2#.XOSBPUT :\ &FF54 :JMP osBPUT (<#.XOSBGET :\ &FF57 :JMP osBGET (F#.XOSARGS :\ &FF5A :JMP osARGS (P#.XOSFILE :\ &FF5D :JMP osFILE (Z (d#.XOSRDCH :\ &FF60 :JMP osRDCH (n-.XOSASCI :\ &FF63 :CMP #&0D:BNE XOSWRCH (x-.XOSNEWL :\ &FF67 :LDA #&0A:JSR XOSWRCH (!.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 (\ ==================== ) .VECTABLE )(EQUW NullIRQ :\ &200 - nmiv )(EQUW ErrorHandler :\ &202 - brkv )")EQUW NullIRQ :\ &204 - irq1v ),(EQUW atomCLI :\ &206 - cliv )6)EQUW atomWRCH :\ &208 - wrchv )@)EQUW atomRDCH :\ &20A - rdchv )J)EQUW atomLOAD :\ &20C - loadv )T)EQUW atomSAVE :\ &20E - savev )^)EQUW atomRDAR :\ &210 - rdarv )h)EQUW atomSTAR :\ &212 - starv )r)EQUW atomBGET :\ &214 - bgetv )|)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 )\ ======================== *EQUS &FFA1-P%,255) *9.LFFAA :\ &FFAA :JMP PrHex :\ Print A in hex *:.LFFAD :\ &FFAD :JMP Pr2Hex :\ Print XY in hex *&3.LFFB0 :\ &FFB0 :JMP NullReturn :\ IRQ stub *0<.LFFB3 :\ &FFB3 :JMP PrText :\ Print inline text *:/.VECDEF :\ &FFB6 :EQUB &2A:EQUW VECTABLE *D(.LFFB9 :\ &FFB9 :JMP Unsupported *N(.LFFBC :\ &FFBC :JMP Unsupported *X>.LFFBF :\ &FFBF :JMP NullReturn :\ Reset vectors, etc. *b(.LFFC2 :\ &FFC2 :JMP Unsupported *l(.LFFC5 :\ &FFC5 :JMP Unsupported *v(.LFFC8 :\ &FFC8 :JMP Unsupported * *\ 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) +4#.OS_CLI :\ &FFF7 :JMP (cliv) +> +H\ Hardware vectors +R\ ---------------- +\:.NMIV :\ &FFFA :EQUW NMI0 :\ NMI Vector +f<.RESETV :\ &FFFC :EQUW RESET :\ RESET Vector +p:.IRQV :\ &FFFE :EQUW InterruptHandler :\ IRQ Vector +z]: +A"Save "+fname$+" "+~mcode%+" "+~O%+" "+~load%+" "+~load% + : + *Quit