REM > AP1v1311.src REM Source for Electron Plus 1 Support : ON ERROR REPORT:PRINT" at line ";ERL:END IF PAGE>&8000:SYS "OS_GetEnv"TOA$:IFLEFT$(A$,5)<>"B6502":OSCLI"B6502"+MID$(A$,INSTR(A$," ")) DEFFNif(A%):IFA%:z%=-1:=opt% ELSE z%=P%:=opt% DEFFNendif:IFz%=-1:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt% DEFFNelse:IFz%=-1:z%=P%:=opt% ELSE z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=-1:=opt% : name$="AP1" DIM mcode% &1000,L% -1:load%=&8000 OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0 OSFILE=&FFDD:OSARGS=&FFDA:OSBGET=&FFD7:OSBPUT=&FFD4 OSGBPB=&FFD1:OSFIND=&FFCE:GSINIT=&FFC2:GSREAD=&FFC5 : TARGET%=-1:REM Build for 6502Em with no FDC hardware, no real ADFS TARGET%=5 :REM Build for Compact TARGET%=0 :REM Build for Electron : : REM v1.30 22-Jan-2016: Date of whole ROM build REM 28-Feb-2016: Serial IRQ mask ignores IRQs if no 6281 present REM 01-Mar-2016: Fixed wrong destination in serial-absence test REM IRQ handler checks ignore-all before RxRDY/TxRDY : verROM$="1.31" :dateROM$="22 Jun 2018":REM Date of whole ROM build ver$ ="1.31" :date$ ="22 Jun 2018":REM Date of AP1 Support REM 28-Jun-2018: Ensures LANG only used b7-b6,b3-b0 of L0D6D : verROM$="1.33" :dateROM$="22 May 2020":REM Date of whole ROM build ver$ ="1.31" :date$ ="22 Jun 2018":REM Date of AP1 Support : verROM$="1.33" :dateROM$="22 Jun 2018":REM Date of whole ROM build ver$ ="1.311":date$ ="22 Jun 2018":REM Date of AP1 Support REM 28-Dec-2020: Claims BRKV on startup to catch startup errors REM Removed pre-v1.311 code : : REM Base addresses REM -------------- IF TARGET%<1 :ROMtable=&2A0:REM Electron IF TARGET%>0 :ROMtable=&2A1:REM BBC, Master : : REM Workspace REM --------- L0D70=&0D70 :REM Saved file vectors L0D6C=&0D6C :REM Saved ROM semaphore when disabled L0D6D=&0D6D :REM Default language ROM : : REM Saved file vectors REM ------------------ L0D70=L0D70+&0:L0D72=L0D70+&2:L0D74=L0D70+&4:L0D76=L0D70+&6 L0D78=L0D70+&8:L0D7A=L0D70+&A:L0D7C=L0D70+&C : : REM Workspace REM --------- REM &0D68-&0D6C Plus 1 Support REM &0D6D-&0D6F ROM Manager Support REM &0D70-&0D7F ROM/TAPE intercept REM REM &0D68 flags REM &Fx = 100Hz poll enabled REM &80 = Plus 1 100Hz handlers disabled REM &40 = printer buffer active REM &20 = ADC active REM &10 = serial active REM &08 = temporarily disabled for TAPE/ROM access REM &04 = ROM table has been moved during Reset REM &02 = ignore serial interupts REM &01 = Plus 1 disabled REM &0D69 Serial speed control register (&FC61) RAM copy REM &0D6A Serial interupt mask (&FC65) REM &80 = input port change (incoming RTS) REM &01 = serial output buffer active REM &02 = serial input buffer active REM &0D6B ROMSTROBE (&FC73) RAM copy REM &0D6C Saved ROM paging semaphore when temporarily disabled REM &0D6D If b7=0 - default language ROM in b3-b0 REM If b6=1 - reserved for NoRelocate REM If b5=1 - Tube disabled REM If b4=1 - spare REM b3-b0 - language ROM REM &0D6E INSERT/UNPLUG bitmap 0-7, b7=7, 0=inserted, 1=unplugged REM &0D6F INSERT/UNPLUG bitmap 8-15, b7=15, 0=inserted, 1=unplugged REM REM &0D70 Old FILEV when TAPE/ROM selected REM &0D72 Old ARGSV when TAPE/ROM selected REM &0D74 Old BGETV when TAPE/ROM selected REM &0D76 Old BPUTV when TAPE/ROM selected REM &0D78 Old GBPBV when TAPE/ROM selected REM &0D7A Old FINDV when TAPE/ROM selected REM &0D7C Old FSCV when TAPE/ROM selected REM &0D7E (no longer used) REM REM &0DF0,X b7=disabled, b6-b0=unused : REM I/O addresses REM ------------- REM &FC60-6F Electron 2681 serial controller REM &FC60 Control REM &FC61 Serial speed control register REM b7-b4=tranmit, b3-b0-receive REM &FC62 Serial command register REM &FC63 Transmit/Receive Data Register REM &FC64 Aux Control/Input Changed REM &FC65 Serial interupt mask - RAM copy in &0D6A REM &FC6D Output config/Input port REM Read CTS in bit 2 REM &FC6E Serial set output bits REM Write &01 to clear RTS REM &FC6F Serial clear output bits REM Write &01 to set RTS REM REM &FC70-73 Electron expansion REM &FC70 AtoD convertor REM Read: data value, Write: control REM &FC71 Centronics port REM Write: write to port REM &FC72 Electron expansion status REM Read: b7=BUSY, b6=ADC, b5=Fire1, b4=Fire2 REM &FC73 Electron REM Write: ROMSTROBE REM REM &FCC0-08 Floppy disk controller REM &FCC0 Drive select register REM &FCC4 FDC command/status REM &FCC7 FDC data REM REM &FCD8/&FCD9 lock/unlock register bank 5/6 REM &FCDA/&FCDB lock/unlock register bank 13/15 REM &FCDC/&FCDD lock/unlock register bank 0/2 REM &FCDE/&FCDF lock/unlock register bank 1/3 REM REM &FCFC AQR paging register REM &FCFD unlock AQR REM &FCFE lock AQR : : file$=name$+"v"+LEFT$(ver$,1)+MID$(ver$,3,2) FOR P=0 TO 1:opt%=P*2+4 P%=load%:O%=mcode% [OPT opt% .exec% .L8000:JMP L8021 :\ Language entry .L8003:JMP PlusOne :\ Service entry .L8006:EQUB &C0 :\ ROM type=Serv+Lang+6502 BASIC .L8007:EQUB L8019-L8000-1 :\ Copyright offset .L8008:EQUB EVAL("&"+MID$(verROM$,3,2)) :\ ROM version byte .L8009 OPT FNif(TARGET%<>0) EQUS MID$("6502EmBBC B+MasterCompact",((TARGET%+1)AND-2)*3+1,6+3*(TARGET%=1)-(TARGET%=5))+" " OPT FNendif \EQUS "RH Plus 1/AP6":\EQUB 0 :\ ROM title EQUS "RH Plus 1":EQUB 0 :\ ROM title EQUS LEFT$(verROM$,4)+LEFT$(CHR$(96+VALRIGHT$(verROM$,1)),LENverROM$-4) :\ Version string EQUS " ("+dateROM$+")":EQUB 0 :\ Version date .L8019 EQUS "(C)J.G.Harston":EQUB 0 :\ Copyright string .NULL RTS .PlusOne JSR NULL:JMP L8067 EQUB &82:EQUB PlusCopy-PlusOne-1:EQUB EVAL("&"+MID$(ver$,3,2)) EQUS "Plus 1 Support":EQUB 0 EQUS LEFT$(ver$,4)+" ("+date$+")":EQUB 0 :\ Version string .PlusCopy EQUS "(C)JGH & Acorn":EQUB 0 \ LANGUAGE HANDLER \ ================ \ Languages higher than me are disabled, so I am entered by default. \ Restore ROM table then try to enter default language. If no default look \ for a default language lower than me, then above me. \ Results in my ROM name being displayed then new default ROM name displayed. \ .L8021 LDA #&A3:LDX #&80 :\ OSBYTE &A3,&80,&04 LDY #&04:JSR OSBYTE :\ Restore ROM table, find default language .L803B TXA:BMI Prompt :\ No language, or entering me as a language LDA #142:JMP OSBYTE :\ Enter as a language : \ No-Language Environment \ ----------------------- .Report JSR OSNEWL:LDY #1 .ReportLp LDA (&FD),Y:BEQ ReportDone JSR OSWRCH:INY:BNE ReportLp .ReportDone JSR OSNEWL .Prompt LDX #&FF:TXS:CLI JSR ClaimBRKV LDA #ASC"*":JSR OSWRCH LDX #Osword0 AND 255 LDY #Osword0 DIV 256 LDA #0:JSR OSWORD:BCS PromptEsc LDX #0:LDY #7:JSR OS_CLI JMP Prompt .PromptEsc LDA #126:JSR OSBYTE BRK:EQUB 17:EQUS "Escape":BRK .Osword0 EQUW &0700:EQUB 255:EQUB 32:EQUB 255 .Serv10 LDA &203:CMP #&C0 PLA:BCC ClaimBRKexit :\ Only claim if MOS has BRKV .ClaimBRKV LDX #&03:STX &202 LDX #&FF:STX &203 LDX #Report AND 255:STX &DA2 LDX #Report DIV 256:STX &DA3 LDX &F4:STX &DA4 .ClaimBRKexit RTS \ SERVICE HANDLER \ =============== .L8067 PHA LDA &0DF0,X:BMI L80CD:\ If b7=1, disabled, ignore service call \ Dispatch service call \ --------------------- .L808E PLA:PHA:TAX :\ Get service call back CPX #&16:BCS L80CC :\ Unsupported, exit ASL A:TAX :\ Index into dispatch table LDA L80A0+1,X:PHA :\ Stack high byte of address LDA L80A0+0,X:PHA :\ Stack low byte of address RTS :\ Return to jump to routine \ Service call dispatch table \ --------------------------- .L80A0 EQUW L80CC-1 :\ &00 - Null EQUW L815E-1 :\ &01 - Private workspace EQUW L80CC-1 :\ &02 - Null EQUW L80CC-1 :\ &03 - Null EQUW L80CC-1 :\ &04 - Null EQUW L81A6-1 :\ &05 - Interupt EQUW L8617-1 :\ &06 - Error EQUW L83BA-1 :\ &07 - OSBYTE EQUW L80CC-1 :\ &08 - Null EQUW L80CC-1 :\ &09 - Null EQUW L80CC-1 :\ &0A - Null EQUW L80CC-1 :\ &0B - Null EQUW L80CC-1 :\ &0C - Null EQUW L80CC-1 :\ &0D - Null EQUW L80CC-1 :\ &0E - Null EQUW L8690-1 :\ &0F - Vectors changed EQUW Serv10-1:\ &10 - Close Spool/Exec EQUW L80CC-1 :\ &11 - Null EQUW L80CC-1 :\ &12 - Null EQUW L8258-1 :\ &13 - Character in serial buffer EQUW L8261-1 :\ &14 - Character in printer buffer EQUW L8232-1 :\ &15 - 100Hz poll .L80CC:LDX &F4 :\ Restore registers and return .L80CD:PLA:RTS :\ Restore A and return .L80D0:STA &F0 :\ Pass A to returned X .L80D1:LDX &F4 :\ Restore ROM to X PLA:LDA #&00:RTS :\ Claim call and return \ SERVICE 1 - Shared workspace \ ============================ \ Set up Plus 1 support .L815E TYA:PHA :\ Save workspace pointer OPT FNif(TARGET%<1) LDA &FFB2 CMP #&40:BEQ L8160 :\ Running on Electron? LDX &F4:LDA &0DF0,X ORA #&80:STA &0DF0,X :\ Not Electron, disable myself .L8160 OPT FNendif LDA #0:STA &0D68 :\ No 100Hz calls enabled, ROM table not moved, nothing disabled STA &0D6B:STA &FC73 :\ Set ROMSTROBE and copy to &00 OPT FNif(TARGET%<1) LDA &28D :\ Check Break type OPT FNendif BEQ L8182 :\ Soft Break (or not Electron), don't move ROM table LDX &F4:BPL L816E :\ Jump to start at the ROM above me .L8163 LDA ROMtable,X:STA &0380,X :\ Copy ROM table to &0380-&038F AND #&BF:STA ROMtable,X :\ Remove language bit from ROM byte .L816E INX:CPX #&10:BCC L8163 LDA #4:STA &0D68 :\ Set 'ROM table moved' .L8182 LDX #&04:JSR L8388 :\ Set maximum ADC channel to 4 LDA &028D:CLC:BEQ L8192 :\ Soft Break, don't set defaults .L818C OPT FNif(FALSE) LDA &28F:AND #&CF:STA &28F :\ Reset disk access speed OPT FNendif LDX #&01:STX &285 :\ Set Printer Type to 1 (parallel) SEC :\ SEC=use default serial speed .L8192 JSR L8567 :\ Initialise serial interface PLA:TAY:JMP L80CC \ SERVICE 5 - Interrupt \ ===================== .L81A6 LDA #&02 BIT &0D68:BNE L81BB :\ If IRQ Ignore, exit LDA &0D6A:BPL L81BB :\ Serial Mask b7=0, ignore all IRQs AND &FC65:BMI L81BE :\ Mask with 6281 IRQ, b7=input port changed (RTS) LSR A:BCS L81CB :\ b0 set -> TxRDY LSR A:BCS L8206 :\ b1 set -> RxRDY .L81BB JMP L80CC :\ Restore all and return unclaimed .L81BE LDA #&04 :\ Test bit 2 BIT &FC64:BNE L81C8 :\ Input bit 2 not changes JSR L85AA :\ .L81C8 JMP L80D1 :\ Claim call and return .L81CB LDA #&04 :\ Test CTS in bit 2 BIT &FC6D:BNE L8200 :\ Not CTS, skip to set serial inactive JSR L85CD :\ Get byte from SerOut buffer BCC L81EA :\ If not empty, write it to SerTx LDX &0285 :\ Get Printer Type CPX #&02:BNE L81F2 :\ Not 2=Serial JSR L85D3 :\ Get byte from Printer Buffer PHA:PHP JSR L87AB :\ Set/Clear printer Buffer Busy flag PLP:PLA BCS L81F2 :\ Printer Buffer was empty, skip past .L81EA STA &FC63 :\ Write byte to DataTx LDX #&00:JMP L81FA :\ Set SerialFlag to 0 and return .L81F2 JSR L85B9 :\ Set serial inactive JSR L82EB :\ Set/Clear CTS from buffer space LDX #&FF :\ Set SerialFlag to &FF and return .L81FA STX &024F :\ Serial Use Flag JMP L80D1 :\ Claim call and return .L8200 JSR L85B9 :\ Set serial inactive JMP L80D1 :\ Claim call and return .L8206 LDX &FC63 :\ Read from 2681 Data Register LDA &FC61 :\ Read from 2681 Status Register AND #&F0:BNE L8221 :\ If any error bit set, skip to generate event TXA:JSR L85C8 :\ Insert into serial input buffer JSR L85D9:BCS L821E :\ At least 8 bytes left, exit LDA #&01:STA &FC6F :\ Raise RTS to stop other end sending .L821E JMP L80D1 :\ Claim and return .L8221 TXA:PHA :\ Save byte read LDX &FC61 :\ Read from 2681 Status again JSR L85A0 :\ Reset 6281 Error Status PLA :\ Get byte back LDY #&07:JSR &FFBF :\ Generate Event 7 - Serial Error JMP L80D1 :\ Claim and return \ SERVICE &15 - 100Hz Poll \ ======================== .L8232 DEY:TYA:PHA :\ Decrement semaphore LDA #&40:BIT &0D68 :\ Check printer buffer active BEQ L823F:JSR L827D :\ If active, try to send character to printer .L823F LDA #&20:BIT &0D68 :\ Check if ADC active BEQ L8249:JSR L82A1 :\ If active, check for ADC conversion .L8249 LDA #&10:BIT &0D68 :\ Check if serial active BEQ L8253:JSR L82EB .L8253 PLA:TAY :\ Restore semaphore JMP L80CC :\ Return unclaimed \ Character entering serial output buffer \ ======================================= .L8258 JSR L85AA :\ Write something to serial port JSR L82F2 :\ Set/Clear CTS if input buffer almost full JMP L80D1 :\ Claim call and return \ Character entering printer output buffer \ ======================================== .L8261 TYA:PHA :\ Preserve Y JSR L826B :\ Process output character PLA:TAY:JMP L80D1 :\ Restore, claim call and return .L826B LDX &0285 :\ Get printer destination CPX #&01:BEQ L827D :\ Parallel printer CPX #&02:BNE L827C :\ Not serial printer \ Output to serial printer \ ------------------------ JSR L85AA :\ Write something to serial port JSR L82F2 :\ Set/Clear CTS if input buffer almost full .L827C RTS \ Output to parallel printer \ -------------------------- .L827D BIT &FC72:BMI L829C :\ If printer busy, turn 100Hz poll on and return JSR L85D3 :\ Get character from printer buffer BCS L8293 :\ If buffer empty, turn off 100Hz poll STA &FC71 :\ Send to printer port LDA #&40:JSR L85EA :\ Set b6 of &0D68, turn on 100Hz poll CLC:JMP L8299 :\ Clear Printer Buffer Busy flag and return \ Printer buffer empty \ -------------------- .L8293 LDA #&40:JSR L85FD :\ Clear b6 of &0D68, turn off 100Hz poll SEC :\ Set b7 of &02C6 and return :\ Set Serial Error event flag .L8299 JMP L87AB :\ Set/Clear Printer Buffer Busy flag \ Printer busy \ ------------ .L829C LDA #&40:JMP L85EA :\ Set b6 of &0D68, turn on 100Hz poll \ Check for ADC conversion \ ======================== .L82A1 BIT &FC72:BVS L82FC :\ If no ADC ready, return LDX &024C :\ Get current ADC channel TXA:BEQ L82FC :\ No ADC channel, return LDA #&00:STA &02F7,X :\ Set low byte to zero LDA &FC70:STA &02FB,X :\ Set high byte from ADC STX &02F7 :\ Store as last channel converted LDY #&03:JSR &FFBF :\ Event 3 - ADC complete LDX &02F7 :\ Get last channel converted DEX :\ Step down to next channel BNE L82D0 :\ If nonzero, start this channel LDX &024D :\ Get maximum ADC channel TXA:BNE L82D0 :\ If nonzero, start this channel LDA #&20:JMP L85FD :\ Clear b5 of &0D68, turn off 100Hz poll .L82D0 .L82D3 CPX #&05:BCC L82D9 :\ If channel<5, use it LDX #&04 :\ Channel>4, force to channel 4 .L82D9 TXA:STX &024C :\ Store as current channel TAX:BEQ L82E6 :\ If channel zero, exit LDA L82E7-1,X :\ Get control value for this channel STA &FC70 :\ Write to ADC control .L82E6 RTS \ ADC control values \ ------------------ .L82E7 EQUB &04:EQUB &05 EQUB &06:EQUB &07 \ Set CTS according to input buffer state \ --------------------------------------- .L82EB LDA &0D6A AND #&02:BEQ L82F7 :\ Serial input buffer inactive, raise CTS \ Set/Clear CTS if serial input buffer nearly full \ ------------------------------------------------ .L82F2 JSR L85D9 :\ Count space in serial input buffer BCS L82FD :\ Still space left in input buffer .L82F7 LDA #&01:STA &FC6F :\ Raise RTS to pause sender .L82FC RTS .L82FD LDA #&01:STA &FC6E :\ Lower RTS to unpause sender RTS \ OSBYTE &A3 - Application call \ ============================= .L8303 LDA &F0 CMP #&80:BNE L8319 :\ Not reason &80, exit LDX &F1:CPX #4 BEQ L831C :\ Subcall &04 - restore ROM table BCS L8319 :\ Subcall >&04 - exit TXA:ROR A :\ Cy=b0 of subcall, enable/disable flag LDA &0D68:PHA :\ Save old setting BCC AppEnable :\ b0=0, enable setting ORA AppMask,X :\ Set a bit in flags BCS AppReturn .AppEnable AND AppMask,X:INX :\ Clear bit in flags, point to set bit .AppReturn STA &0D68 :\ Store new setting PLA:AND AppMask,X:PHA :\ Get old setting TXA:EOR #1:BNE AppDone :\ Subcall 2,3 just return BCS AppDisable :\ Subcall 1, disable Plus 1 functions JSR L8671 :\ Enable Plus 1 functions JMP AppDone .AppDisable JSR L8641 :\ Disable Plus 1 functions .AppDone PLA:JMP L80D0 :\ Jump to return old flags .AppMask EQUB &FE:EQUB &01 EQUB &FD:EQUB &02 .L8319 JMP L80CC \ OSBYTE &A3,&80,4 - Restore ROM table \ ------------------------------------ .L831C LDA &0D68 :\ Check system flags AND #4:BEQ L832A :\ ROM table not moved LDX &F4:BPL L8325 :\ Start at the ROM above me .L831F LDA &0380,X:STA ROMtable,X :\ Copy &0380-&038F back to ROM table .L8325 INX:CPX #&10:BCC L831F LDA &0D68:AND #&FB:STA &0D68 :\ Set 'ROM table not moved' .L832A LDY #1 :\ On first pass, start at Plus 1 ROM LDA L0D6D:AND #&8F :\ Get default LANG ROM number TAX:BPL TryThisROM :\ b7=0, default ROM .LookForROMlp DEY:BNE P%+4:LDX &F4 :\ Start at Plus 1 ROM DEX:BPL P%+4:LDX #15 :\ Step down, looping around CPX &F4:BEQ NoLanguage :\ If looped back to Plus 1, no more left .TryThisROM LDA ROMtable,X :\ Get ROM byte ASL A:BPL LookForROMlp :\ No language, try next one down .NoLanguage TXA CMP &F4:BNE P%+4:ORA #&80 :\ If no language found, return &80+Plus1 JMP L80D0 :\ Jump to return A as returned X \ OSBYTE &80 - ADVAL \ ================== \ ADVAL 1-4 are performed by MOS .L8366 LDA &F0:BNE L8319 :\ Not ADVAL(0), exit LDA &FC72:PHA :\ Read Plus 1 status BPL L8373:JSR L826B :\ If printer not busy, try to send a character .L8373 PLA:LSR A:LSR A :\ Move fire buttons into b0-b1 LSR A:LSR A AND #&03:EOR #&03 :\ Keep and toggle b0-b1 JMP L80D0 :\ Return fire buttons \ OSBYTE &10 - Maximum ADC channel \ ================================ .L837F LDX &F0:JSR L8388 :\ Set maximum ADC channel JMP L80D0 :\ Return maximum actually set .L8388 TXA:BEQ L8395 :\ Zero channels, set and return JSR L82D3:TXA :\ Check within range and initialise ADC PHA LDA #&20:JSR L85EA :\ Enable 100Hz poll for ADC PLA .L8395 STA &024D:RTS :\ Store maximum ADC channel \ OSBYTE &11 - Start ADC conversion \ ================================= .L839A LDA #&00:STA &02F7 :\ Clear 'last channel' LDX &F0:JSR L82D3:TXA :\ Start conversion on channel X PHA:LDA #&20:JSR L85EA :\ Enable 100Hz poll for ADC PLA:JMP L80D0 :\ Return X=channel actually started \ OSBYTE &6E - Write to ROMSTROBE \ =============================== \ Writes X to ROMSTROBE at &FC73 and RAM copy at &0D6B \ Returns old ROMSTROBE from RAM copy \ .L83AC LDX &F0 :\ Get new ROMSTROBE from X parameter LDA &0D6B :\ Get old ROMSTROBE STX &0D6B:STX &FC73 :\ Store new ROMSTROBE and output it JMP L80D0 :\ Return old ROMSTROBE as X \ SERVICE 7 - OSBYTE \ ================== .L83BA LDA &EF :\ Get OSBYTE number CMP #&80:BEQ L8366 :\ &80 - ADVAL CMP #&10:BEQ L837F :\ *FX16 - Maximum ADC channel CMP #&11:BEQ L839A :\ *FX17 - Start ADC conversion CMP #&07:BEQ L83E6 :\ *FX7 - serial receive speed CMP #&08:BEQ L83EC :\ *FX8 - serial transmit speed CMP #&9C:BEQ L8436 :\ &9C - serial control CMP #&02:BEQ L840F :\ *FX2 - input stream CMP #&6E:BEQ L83AC :\ *FX110 - write to ROMSTROBE CMP #&A3:BNE L83E3 JMP L8303 :\ &A3 - application call .L83E3 JMP L80CC \ OSBYTE 7 and 8 - set serial speed \ ================================= \ On entry, X=baud rate setting (0=default) \ On exit X=control register setting that wasn't changed \ OSBYTE &07 - Serial receive speed \ ---------------------------------- .L83E6 LDA #&F0:STA &F1 :\ Set &F1 to &F0 for 'receive' BNE L83F0 \ OSBYTE &08 - Serial transmit speed \ ---------------------------------- .L83EC LDA #&0F:STA &F1 :\ Set &F1 to &0F for 'transmit' \ Set serial speed, &F1=control mask \ ---------------------------------- .L83F0 LDX &F0 :\ Get OSBYTE X value CPX #&0C:BCS L840C :\ If speed>11, exit unchanged LDA &F1:EOR #&FF :\ Get mask and toggle it AND &0D69 :\ Mask with current baud register copy STA &F0 :\ Keep the bits we aren't going to change LDA L84B2,X :\ Translate X to baud rate control value AND &F1 :\ Mask to keep the half we are going to change ORA &F0 :\ Merge with current setting STA &0D69 :\ Update the baud register RAM copy STA &FC61 :\ Store in baud register .L840C JMP L80D1 :\ Claim call and return \ OSBYTE &02 - select input stream \ ================================ .L840F LDA &F0:PHA :\ Save OSBYTE X value, input source AND #&01:TAX :\ Keep bit 0, keyboard/serial select STA &0241 :\ Store selected source PLA:BEQ L8471 :\ Get original selection, exit if X=0, serial disabled LDA #&01:STA &FC62 :\ Enable serial input LDA &0D6A:ORA #&02 :\ Enable receive interupts STA &0D6A:STA &FC65 :\ Write to IRQ mask and 6281 IRQ register JSR L82EB :\ Set/Clear CTS LDA #&10:JSR L85EA :\ Increment ROM polling register if needed JMP L80D1 :\ Claim call and return \ OSBYTE &9C - serial control \ =========================== \ On entry, Y=action, X=parameters, in 6850 format .L8436 LDA #&E3 :\ *FX156,x,227 to set word format CMP &F1:BNE L8492 :\ Not Y=227 \ Y=227, set serial word format \ ----------------------------- BIT &F0:BNE L846E :\ X must be %000xxx00 LDA &F0 :\ Get X parameter LSR A:LSR A:NOP:TAX :\ Move up two bits JSR L85A4 :\ Select control register &10 LDA &FC60 :\ Read from control register &10 AND #&E0:STA &F1 :\ Save temporarily \ Manipulate stuff to set serial word size JSR L85A4 :\ Select control register &10 LDA L84BE,X :\ AND #&1F :\ ORA &F1 :\ STA &FC60 :\ Write to control register LDA &FC60 :\ Read from control register AND #&F0 :\ Keep b7-b4 LDY L84BE,X BMI L8469 :\ If b7 set, skip ORA #&0F :\ If b7 clear, set b3-b0 .L8469 ORA #&07 :\ Set to %xxxxx111 STA &FC60 :\ Write to control register .L846E JMP L80D1 :\ Claim call and return \ Turn off serial input \ --------------------- .L8471 LDA #&02:STA &FC62 :\ Disable receiver JSR L8598 :\ Reset reciever JSR L85A0 :\ Reset error status LDA &0D6A:AND #&FD :\ Reset serial input IRQ STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register JSR L82EB :\ Set/Clear CTS LDA #&10:JSR L85FD :\ Clear b4 of flags, turn off polling JMP L80D1 :\ Claim call and return .L8492 LDA #&9F :\ *FX156,x,159 for a serial break CMP &F1:BNE L846E :\ Not Y=159, exit \ Y=159, start/stop a serial break \ -------------------------------- BIT &F0:BNE L846E :\ X must be %0xx00000 LDA &F0 :\ Get X parameter CMP #&60:BEQ L84AA :\ *FX156,96,159 - start a break LDA #&70:STA &FC62 :\ Else, stop transmitting a break JMP L846E :\ Claim call and return .L84AA LDA #&64:STA &FC62 :\ Start transmitting a break JMP L846E :\ Claim call and return \ Baud rate look-up table \ ----------------------- .L84B2 EQUB &BB:EQUB &00:EQUB &33 :\ 0=9600, 1=75, 2=150 EQUB &44:EQUB &66:EQUB &88 :\ 3=300, 4=1200, 5=2400 EQUB &99:EQUB &BB:EQUB &CC :\ 6=4800, 7=9600, 8=19200 EQUB &11:EQUB &55:EQUB &AA :\ 9=110, 10=600, 11=1800 \ Serial control look-up table \ ---------------------------- .L84BE EQUB &02:EQUB &06:EQUB &82:EQUB &86 EQUB &13:EQUB &93:EQUB &83:EQUB &87 \ Initialise serial interface \ --------------------------- \ CC=use current settings, CS=use default settings .L8567 LDA #0:STA &0D6A :\ DMB, ignore serial interupts JSR L85A4 :\ Reset MC6281 MR pointer LDA #&93:STA &FC60 :\ First write, RTS=enabled, NoParity, 8bit LDA #&07:STA &FC60 :\ Second write, StopBit=1 bit length EOR &FC60:BNE L8597 :\ DMB, read back, if hardware absent, exit LDA #&8F:STA &FC64 :\ Set AuxControl to Baud Rate 2, IRQs on LDA &0D69:BCC L8580 :\ Get current baud setting LDA #&BB :\ Default baud rate=9600 .L8580 STA &0D69:STA &FC61 :\ Set baud register and RAM copy JSR L8598 :\ Reset 6821 receiver JSR L859C :\ Reset 6821 transmitter JSR L85A0 :\ Reset 6821 error status LDA #&80:STA &0D6A :\ Set IRQ mask to allow serial interupts STA &FC65 :\ Enable 6821 interupts .L8597 RTS .L8598 LDA #&20:BNE L85A6 :\ &20=Reset Receiver .L859C LDA #&30:BNE L85A6 :\ &30=Reset Transmitter .L85A0 LDA #&40:BNE L85A6 :\ &40=Reset Error Status .L85A4 LDA #&10 :\ &10=Reset MR pointer .L85A6 STA &FC62:RTS :\ Write to command register .L85AA LDA &0D6A:ORA #&01 :\ Set serial buffer active STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register LDA #&04:BNE L85A6 :\ Write &04=Transmitter Enabled to command register .L85B9 LDA &0D6A:AND #&FE :\ Set serial buffer inactive STA &0D6A:STA &FC65 :\ Write to IRQ mask and serial port IRQ register LDA #&08:BNE L85A6 :\ Write &08=Transmitter Disabled to command register .L85C8 LDX #&01 :\ X=1 - serial input buffer JMP (&022A) :\ Jump to INSV .L85CD CLV :\ CLV=remove character LDX #&02 :\ X=2 - serial output buffer JMP (&022C) :\ Jump to REMV .L85D3 CLV :\ CLV=remove character LDX #&03 :\ X=3 - printer buffer JMP (&022C) :\ Jump to REMV \ Count space left in serial input buffer \ --------------------------------------- \ Returns CS=more than 8 bytes left \ CC=less than 8 bytes left .L85D9 JSR L85E3 :\ Count space in serial input buffer CPY #&01:BCS L85E2 :\ If >&00FF, return CS CPX #&09 :\ If >&0008, return CS .L85E2 RTS .L85E3 SEC :\ SEC=count space left CLV :\ CLV=count buffer LDX #&01 :\ X=1 - serial input buffer JMP (&022E) :\ Jump to CNPV .L85EA ORA &0D68 :\ Merge into current flags LDX &0D68 :\ Get old value of flags to X STA &0D68 :\ Store updated flags TXA :\ Get old flags into A AND #&F0:BNE L85E2 :\ If old flags had polling enabled, exit : :\ We've changed to needing polling, increment semaphore .L85F8 LDA #&16:JMP OSBYTE :\ Inc. ROM polling semaphore .L85FD TAX :\ Save mask in X LDA #&F0:BIT &0D68 :\ Check current polling flags BEQ L85E2 :\ No flags have polling enabled, exit TXA:EOR #&FF :\ Get mask back and toggle it AND &0D68:STA &0D68 :\ Remove the bit and update flags AND #&F0:BNE L85E2 :\ If any polling enabled, exit : :\ Nothing left needing polling, decrement semaphor .L8612 LDA #&17:JMP OSBYTE :\ Dec. ROM polling semaphore \ SERVICE 6 - Error \ ================= .L8617 LDA #&08:BIT &0D68:BEQ L8622 :\ Not temporarily disabled, skip LDA L0D6C:STA &0249 :\ Restore ROM paging semaphore .L8622 LDA #&01:BIT &0D68:BNE L863E :\ Plus 1 disabled, ignore error LDA &EF:PHA LDA &F0:PHA:LDA &F1:PHA :\ Save OSBYTE/OSWORD parameters JSR L8671 PLA:STA &F1:PLA:STA &F0 PLA:STA &EF .L863E JMP L80CC :\ Restore and return unclaimed \ Disable Plus 1 functions \ ======================== .L8641 PHA:TXA:PHA:TYA:PHA LDA &0D68:BMI L865C :\ Bit 7 set, already disabled PHA ORA #&80:STA &0D68 :\ Set bit 7 of flags PLA:BEQ L865C :\ No handlers to disable JSR L8612 :\ Decrement ROM polling semaphore LDA #&01:STA &FC6F :\ Raise 'RTS', stop serial sender .L865C PLA:TAY:PLA:TAX:PLA RTS \ Enable Plus 1 functions \ ======================= \ Called after calling filing vector, so all four registers need to be saved .L8662 PHP:PHA LDA L0D6C:STA &0249 :\ Restore ROM paging semaphore LDA &0D68:AND #&F7 STA &0D68 :\ Clear 'disabled' flag PLA:PLP .L8671 PHP:PHA:TXA:PHA:TYA:PHA LDA &0D68:BPL L8689 :\ Bit 7 clear, already enabled AND #&7F:STA &0D68 :\ Clear bit 7 of flags BEQ L8689 :\ No handlers to enable JSR L85F8 :\ Increment ROM polling semaphore JSR L82EB :\ Restore CTS state .L8689 PLA:TAY:PLA:TAX:PLA:PLP RTS \ SERVICE &0F - Vectors changed \ ============================= .L8690 LDX &0213:INX:BEQ L86A3 :\ FILEV not pointing to MOS, exit LDA #&00:TAY:JSR OSARGS :\ Read current filing system CMP #&03:BCS L86A3 :\ Not TAPE/ROM, exit CMP #&00:BNE L86B4 .L86A3 JMP L80CC \ Filing system vectors \ --------------------- .L86A6 EQUW L8736 :\ FILEV EQUW L875F :\ ARGSV EQUW L8709 :\ BGETV EQUW L8712 :\ BPUTV EQUW L871F :\ GBPBV EQUW L873F :\ FINDV EQUW L874C :\ FSCV \ Vectors changed, now using TAPE/ROM \ ----------------------------------- .L86B4 PHP:SEI :\ Disable IRQs while changing vectors LDY #&1B:LDX #&12 .X86D1 LDA &0200,X:STA L0D70-&12,X :\ Copy filing system vectors TYA:STA &0200,X :\ to L0D70-L0D7D and redirect them LDA &0201,X:STA L0D70-&11,X :\ to extended vectors LDA #&FF:STA &0201,X LDA L86A6-&12,X:STA &0D9F,Y :\ Claim extended filing system vectors INX:INY LDA L86A6-&12,X:STA &0D9F,Y INX:INY LDA &F4:STA &0D9F,Y INY:CPX #&20:BNE X86D1 PLP .L8706 JMP L80CC \ Redirected BGETV \ ---------------- .L8709 JSR L877E:JSR L879C:JMP L8662 :\ Disable Plus 1, call BGET, enable Plus 1 \ Redirected BPUTV \ ---------------- .L8712 JSR L877E:JSR L879F:JMP L8662 :\ Disable Plus 1, call BPUT, enable Plus 1 \ Pass OSGBPB 5-7, 9+ on without disabling Plus 1 \ ----------------------------------------------- .L871B PLP:JMP L87A2 \ Redirected GBPBV \ ---------------- .L871F PHP CMP #&08:BEQ L872C :\ Pass OSGBPB 8 on via veneer CMP #&05:BCS L871B :\ Pass OSGBPB 5-7, 9+ on directly CMP #&01:BCC L871B :\ Pass OSGBPB 0 on directly .L872C PLP JSR L877E:JSR L87A2:JMP L8662 :\ Disable Plus 1, call GBPB, enable Plus 1 \ Redirected FILEV \ ---------------- .L8736 JSR L877E:JSR L8796:JMP L8662 :\ Disable Plus 1, call FILE, enable Plus 1 \ Redirected FINDV \ ---------------- .L873F JSR L877E:JSR L87A5:JMP L8662 :\ Disable Plus 1, call FIND, enable Plus 1 \ Pass FSCV on without disabling Plus 1 \ ------------------------------------- .L8748 PLP:JMP L87A8 \ Redirected FSCV \ --------------- .L874C PHP CMP #&02:BCC L8748 :\ Pass <2 on without disabling CMP #&06:BCS L8748 :\ Pass 6+ on without disabling PLP :\ Pass 2-5 via veneer JSR L877E:JSR L87A8:JMP L8662 :\ Disable Plus 1, call FSCV, enable Plus 1 \ Redirected ARGSV \ ---------------- .L875F PHP CMP #&FF:BEQ L8774 :\ Ensure buffers - pass via veneer CPY #&00:BEQ L8770 :\ Read filing info - pass on directly CMP #&01:BEQ L8774 :\ PTR= - pass on via veneer CMP #&03:BEQ L8774 :\ EXT= - pass on via veneer .L8770 PLP:JMP L8799 :\ Pass on directly .L8774 PLP JSR L877E:JSR L8799:JMP L8662 :\ Disable Plus 1, call ARGSV, enable Plus 1 \ Temporarily disable Plus 1 \ ========================== .L877E PHP:PHA JSR L8641 :\ Disable Plus 1 LDA &0249:STA L0D6C :\ Save ROM semaphore LDA #&00:STA &0249 :\ Clear ROM semaphore LDA &0D68:ORA #&08 STA &0D68 :\ Set 'disabled' flag PLA:PLP:RTS .L8796:JMP (L0D70) :\ Old FILEV .L8799:JMP (L0D72) :\ Old ARGSV .L879C:JMP (L0D74) :\ Old BGETV .L879F:JMP (L0D76) :\ Old BPUTV .L87A2:JMP (L0D78) :\ Old GBPBV .L87A5:JMP (L0D7A) :\ Old FINDV .L87A8:JMP (L0D7C) :\ Old FSCV \ Set/Clear buffer 3 busy flag \ ---------------------------- .L87AB ROR &02C6:RTS : ]:IF O%>L%:P."Code overrun":END NEXT OSCLI"Save "+file$+" "+STR$~mcode%+" "+STR$~O%+" 0 FFFBBC00" OSCLI"Stamp "+file$ ON ERROR ON ERROR OFF:END *Quit