> OswFB-FF/src > Source for OSWORD &FB-&FF in 80x86 6502.SYS support file H Commentary based on the disassembly in Master 512 Reference Manual (: 2 ZERO PAGE MOS VARIABLES < ----------------------- ,Fkey1 = &EC : new key press in zero page ,Pkey2 = &ED : old key press in zero page Z: *d MOS CALLS & VECTORS USED BY THE CODE *n ------------------------------------ 4xkeyvec = &0228 : Keyboard status and control )oswrch = &FFEE : Character output /osbyte = &FFF4 : General MOS call entry : $ ADDRESS OF INTERCEPTED VECTORS $ ------------------------------ $userv = &200 : user vector ,irqv1 = &204 : Interrupt request 1 )eventvec = &220 : The event vector : ENTRY TO TUBE SUPPORT CODE -------------------------- 4tube_entry = &406 : Tube claim/release/transfer : $ SHEILA MEMORY MAPPED ADDRESSES $ ------------------------------ 'userport = &FE60 : user-port data ": !, 1770 FDC OFFSETS FROM &FE00 !6 --------------------------- @Master_fdc_base=&24 JMaster_fdn_stat=&28 TMaster_fdc_data=&2B ^BBC_fdc_base =&80 hBBC_fdc_stat =&84 rBBC_fdc_data =&87 |: $ TUBE STATUS AND DATA REGISTERS $ ------------------------------ +tubeR1stat = &FEE0 : Register 1 status )tubeR1data = &FEE1 : Register 1 data +tubeR2stat = &FEE2 : Register 2 status )tubeR2data = &FEE3 : Register 2 data +tubeR3stat = &FEE4 : Register 3 status )tubeR3data = &FEE5 : Register 3 data +tubeR4stat = &FEE6 : Register 4 status )tubeR4data = &FEE7 : Register 4 data :  OSWORD TYPE DECLERATIONS  ------------------------ +OSW_GRAPH = &FF : Fast graphics update ;OSW_HDD = &FE : Hard disk read/write (unimplemented) 3OSW_TEXT = &FD : Text control (unimplemented) 5&OSW_CRTC = &FC : Cursor, soft scroll, mouse etc -0OSW_FDC = &FB : MFM floppy disk access *:OSW_FAD = &FA : Block data transfer D: 1Nload%=&FFFF2800:exec%=load%:fname$="OswFB-FF" X mcode% &57F b P=0 1 lP%=load%:O%=mcode% v[OPT P*3+4 .L2800 IJMP &2800 :\ Jumps to OSWORD &FA code, loader changes to &2500 : .\ Main entry point, USERV directed to here .\ ======================================== .L2803 =CMP #OSW_GRAPH:BEQ oswFFjmp :\ OSWORD &FF graphics update :CMP #OSW_CRTC :BEQ oswFCjmp :\ OSWORD &FC CRTC control 7CMP #OSW_HDD :BEQ oswFEjmp :\ OSWORD &FE hard disk DCMP #OSW_FDC :BEQ oswFBjmp :\ OSWORD &FB floppy disk controller HJMP L2800 :\ Else default code to go to OSWORD &FA &\ E - Doesn't test for OSWORD &FD : &\ Memory used as transient storage & \ -------------------------------- \ Storage for FDC operations < .fdc_dma :EQUD 0 :\ FDC data transfer address <*.fdc_status :EQUB 0 :\ FDC status when completed 84.tube_cmd :EQUB 0 :\ Tube transfer command 4>.sector_count:EQUB 0 :\ Number of sectors .oswFFjmp:JMP osword_graph :\ OSWORD &FF - Graphics output A.oswFBjmp:JMP osword_fdc :\ OSWORD &FB - Floppy disk access 7.newevent:JMP eventcode :\ Jump to event handler 7.newirq :JMP newirq1 :\ Jump to IRQ1V handler : : "\ General Tube access routines "\ ============================ : '$\ Get one byte from Tube register 2 '.\ --------------------------------- 8.getR2data EBLDA tubeR2stat:BPL tube_oswrch :\ Wait for data present in TubeR2 ;LLDA tubeR2data:RTS :\ Read data from TubeR2 V: ?`\ Check if TubeR1 data present, if not wait for TubeR2 data j.tube_oswrch OtLDA tubeR1stat:BPL getR2data :\ If nothing in TubeR1, jump to check TubeR2 D~LDA tubeR1data:JSR oswrch :\ Read R1 data and send to OSWRCH 6JMP tube_oswrch :\ Loop back to wait : "\ Write one byte to register 2 "\ ---------------------------- \ Not called from anywhere .write_R2 @BIT tubeR2stat:BVC write_R2 :\ Wait until TubeR2 available 9STA tubeR2data:RTS :\ Write data to TubeR2 : "\ Get one byte from register 4 "\ ---------------------------- .read_R4 DBIT tubeR4stat:BPL read_R4 :\ Wait for data present in TubeR4 : LDA tubeR4data:RTS :\ Read data from TubeR4 : "\ Write one byte to register 4 "(\ ---------------------------- 2\ Not called from anywhere <.write_R4 @FBIT tubeR4stat:BVC write_R4 :\ Wait until TubeR4 available 9PSTA tubeR4data:RTS :\ Write data to TubeR4 Z: "d\ Write one byte to register 1 "n\ ---------------------------- x.write_R1 ?BIT tubeR1stat:BVC write_R1 :\ Wait until TubeR1 available 8STA tubeR1data:RTS :\ Write data to TubeR1 : : -\ OSWORD &FB for WD1770 floppy controller -\ ======================================= D\ The floppy controller uses five registers, pointed to by (&A0) \ 0 drive control latch \ 4 command/status \ 5 track register \ 6 sector register &\ 7 data register, track for SEEK : 0\ WARNING! - POSITION-DEPENDENT CODE FOLLOWS 0\ ------------------------------------------ .fdc_exec 3"LDA #&00:STA fdc_status :\ Set result=Ok P,LDY #&07:LDA (&A0),Y :\ Read FDC data reg to clear any pending DRQ 96JSR getR2data:STA error_mask :\ Get FDC status mask 6@JSR getR2data:STA sector_count :\ Get sector count 5JJSR getR2data:STA fdc_cmd :\ Get FDC command FDC status register .fdc_e1 ODEX:BNE fdc_e1 :\ Wait 256 loops to allow status to go busy .fdc_e2 =LDA #&01: (&A0),Y :\ Test FDC status BUSY flag \ 7\ WARNING! - the following instruction must not lie 3\ on an address where the bottom 3 bits are set 7\ ------------------------------------------------- E\ (why? I haven't found anything position-dependent in this code) : 7BEQ fdc_e4 :\ No longer busy... ?&DEC watchdog2:BNE fdc_e1 :\ Loop back to keep waiting ?0DEC watchdog1:BNE fdc_e1 :\ Loop back to keep waiting 8:LDA #&FF:BNE fdc_e5 :\ Return &FF=timeout D: N.fdc_e4 4XLDY #&04:LDA (&A0),Y :\ Get FDC status b.fdc_e5 =lSTA fdc_status :\ Set the returned status v.fdc_e6 8SEI:JSR fdc_event:CLI :\ Generate FDC event RTS : $\ Not Group 3 or Group 4 command $\ ------------------------------ .fdc_e7 =BPL fdc_e9 :\ Group 1 command, return ILDY #&00:LDX #&00 :\ Group 2 command, wait for interupts .fdc_e8 ALDA status_pending:BNE fdc_e6 :\ NMI finished, return status ;DEX:BNE fdc_e8 :\ Loop and keep testing IDEY:BNE fdc_e8 :\ Loop 256*256 times and keep testing .fdc_e9 JRTS :\ Return &00/<>&00 from status_pending  : &\ OSWORD &FB - FDC and I/O control & \ ================================ G*\ Commands are transfered via TubeR2 within the OSWORD transaction: 4\ &00 no more commands >\ &01 FDC action on Master H\ &02 FDC action on Master )R\ Command block for &01 and &02: F\\ addr0,addr1,addr2,addr3,tube_cmd,rdwr,errmask,count,fdc_cmd If\ Drive, track and sector must be set beforehand by subcode &05+ p\ &03 claim NMI and Tube z\ &04 release NMI and Tube \ otherwise ,\ &nn,&mm write &mm to I/O at &FE00+&nn \ .osword_fdc 2CLI:CLD :\ Enable IRQs, ensure binary 9JSR getR2data :\ Read tube R2 data - get a command ABNE tube_call_1 :\ If non-zero, jump to test for tube_call_1 .osword_fdc_ret RTS :\ Done : I\ These routines claim or release the tube, set up the l770 addresses I\ for the host machine, or write data to memory mapped I/O in SHEILA. I\ ===================================================================  .tube_call_1 , CMP #&01 :\ Master FDC command? 3 BNE tube_call_2 :\ No, try tube_call_2 (B/B+) >$ JSR tube_setup :\ Get FDC parameters, store at tube_cmd 3. JSR copy_NMI_data :\ Copy and adapt NMI routine 88 JSR Master_setup :\ Set up FDC addresses for Master 0B JSR fdc_exec :\ Get and execute command 6L JMP osword_fdc :\ Loop back for another command V : ` .tube_call_2 0j CMP #&02 :\ BBC (B/B+) FDC command? ,t BNE tube_call_3 :\ No, try tube_call_3 >~ JSR tube_setup :\ Get FDC parameters, store at tube_cmd 3 JSR copy_NMI_data :\ Copy and adapt NMI routine 5 JSR BBC_setup :\ Set up FDC addresses for BBC 0 JSR fdc_exec :\ Get and execute command 6 JMP osword_fdc :\ Loop back for another command  :  .tube_call_3 , CMP #&03 :\ Claim tube and NMI? , BNE tube_call_4 :\ No, try tube_call_4 # JSR nmi_claim :\ Claim NMIs ' JSR tube_claim :\ Claim the Tube 6 JMP osword_fdc :\ Loop back for another command  :  .tube_call_4 . CMP #&04 :\ Release tube and NMI? 5 BNE other_output :\ No, branch to do generic I/O % JSR tube_release :\ Release tube %( JSR nmi_release :\ Release NMIs 62 JMP osword_fdc :\ Loop back for another command < : F .other_output 0P TAX :\ Offset into SHEILA in X :Z JSR getR2data :\ Read tube R2 data - get data byte 9d STA &FE00,X :\ Store in SHEILA,X - write to I/O 6n JMP osword_fdc :\ Loop back for another command x : 0 \ Set up offsets into SHEILA to FDC hardware 0 \ ------------------------------------------  .BBC_setup . LDX #&84 :\ BBC_fdc_stat at &FE84 . LDY #&87 :\ BBC_fdc_data at &FE87 . LDA #&80 :\ BBC_fdc_base at &FE80  BNE setup1  .Master_setup 1 LDX #&28 :\ Master_fdc_stat at &FE28 1 LDY #&2B :\ Master_fdc_data at &FE2B 1 LDA #&24 :\ Master_fdc_base at &FE24  : .setup1 / STA &A0 :\ Offset to FDC hardware / LDA #&FE:STA &A1 :\ (&A0),Y=>FDC registers : STX &0D02 :\ Patch NMI status register address /" JSR getR2data :\ Get read/write setting 1, BEQ setup2 :\ &00 - set up for reading ;6 STY &0D0E:RTS :\ <>&00 - patch NMI code for writing @ .setup2 3J STY &0D0B:RTS :\ Patch NMI code for writing T : ^ .tube_claim 6h LDA #&C0+1:JSR tube_entry :\ Claim Tube with ID=1 4r BCC tube_claim:RTS :\ Loop until claimed | : # \ Fill in data transfer address # \ -----------------------------  .tube_setup LDX #&00 .fdc_dma1 ; JSR getR2data:STA fdc_dma,X :\ Read address from R2data 5 INX:CPX #&04:BNE fdc_dma1 :\ Four bytes to read A JSR getR2data:STA tube_cmd :\ Read R2data, store Tube action  RTS  :  .tube_program 3 LDA tube_cmd :\ A=Tube transfer command . LDX #fdc_dma 255 :\ XY=>transfer address  LDY #fdc_dma 256 2 JSR tube_entry :\ Initiate Tube transfer  RTS & : 0 .tube_release 9: LDA #&80+1:JSR tube_entry :\ Release Tube with ID=1 D RTS N : HX \ These routines claim or release NMI ownership according to whether Hb \ tube data transfer is to take place or disc access is required. In Il \ practical terms only one of three facilities can be the current NMI Hv \ owner, the disc system, the network handler (econet), or the tube. H \ A copy of this routine's NMI code is kept at nmi_image (&29DB) and I \ transferred to page &D when NMI ownership is required. The routines ; \ are called by the code in tube_call_1 to tube_call_4. I \ ===================================================================  .nmi_claim + LDA #&8F:LDX #&0C :\ Service call &0C % LDY #&FF:JSR osbyte :\ Claim NMIs 3 STY nmi_owner:RTS :\ Store previous NMI owner  :  .nmi_release 1 LDY nmi_owner :\ Get previous NMI owner + LDA #&8F:LDX #&0B :\ Service call &0B  JMP osbyte  : - .nmi_owner:EQUB 0 :\ Previous NMI owner  :  .copy_NMI_data C* LDX #&1F :\ Copy 32 bytes (more than needed) 4 .nmi_lp1 <> LDA nmi_image,X:STA &0D00,X :\ Copy NMI code to NMi area 6H DEX:BPL nmi_lp1:RTS :\ Loop until all done R : ?\ \ This routine is called from the NMI code in the NMI area. Ef \ NMI occured with no data transfer, will be either an error or a Bp \ transfer completion. Decide to abort or step to next sector. Ez \ ---------------------------------------------------------------  .nmi_next_sect 6 LDY #&04:LDA (&A0),Y :\ Get FDC status from FDC+4 5 STA fdc_status :\ Save for returned status 5 error_mask :\ Mask for any error bits on ; BNE nmi_next_exit :\ Error occured, abort operation . LDA fdc_cmd :\ Check FDC command < BPL nmi_next_exit :\ b7=0, Restore/Seek, so finished 5 LDA sector_count :\ Get current sector count 2 CMP #&01 :\ Is this the last one? 8 BEQ nmi_next_exit :\ Final sector done, finished 0 DEC sector_count :\ Decre. sector count ? LDY #&06:LDA (&A0),Y :\ Get FDC sector register from FDC+6 4 CLC:ADC #&01 :\ Increment sector number 4STA (&A0),Y :\ Set FDC sector register ?LDA fdc_cmd: #&F3 :\ Get FDC command without settle delay ILDY #&04:STA (&A0),Y :\ Write to FDC command register to start again $RTS ..nmi_next_exit >8LDA #&FF:STA status_pending :\ Set that NMI has completed BRTS L: 2V\ FDC NMI routine, copied to NMI area at &0D00 2`\ -------------------------------------------- j.nmi_image ItPHA:LDA &FE00 :\ &0D00 Get FDC status, address set up earlier 0~ #&1F :\ &0D04 Keep error bits BCMP #&03:BNE nmi_exit :\ &0D06 If not DRQ+BSY, final NMI, exit BLDA tubeR3data :\ &0D0A Either this or next instruction HSTA tubeR3data :\ &0D0D patched to point to FDC data register 5PLA:RTI :\ &0D11 Restore and return .nmi_exit .TYA:PHA :\ &0D12 Also save Y BJSR nmi_next_sect :\ &0D14 Check for next sector or finish ,PLA:TAY :\ &0D17 Restore Y 5PLA:RTI :\ &0D19 Restore and return .nmi_end : E.status_pending:EQUB 0 :\ &00=NMI in progress, <>&00=NMI finished :  : &\ OSWORD &FF - Write graphics data ?\ ========================================================= 5(\ Bit patterns are sent to write to screen memory A2\ Commands are sent via TubeR2 within the OSWORD transaction: <\ &00 - no more commands 6F\ Otherwise high,low - address to start transfer =P\ Then data is sent via TubeR1 with subcommand in TubeR2: =Z\ &00 - read 8 bytes from TubeR1 for next 8 addresses data : =\ Writing to the screen is optimised for maximum possible <\ speed, hence these routines are written 'longhand' and ="\ so avoid the use of counters, instructions to decrement <,\ them and the tests to check when the loop is complete. <6\ Spaces are further optimised because they are the most 9@\ frequently written character and only need a single ;J\ fill byte. They are therefore the easiest to write as ?T\ no reading of tubeR1data is required between bytes. Also, ?^\ the data address is assumed to always be a multiple of 8. h: r.transfer_loop1 @|LDA tubeR2stat:BPL transfer_loop1 :\ Wait for data in TubeR2 NLDA tubeR2data:BEQ transfer_loop2 :\ Get data, if &00 jump to read 8 bytes FCMP #&FF:BEQ next_addr_hi :\ &FF, go back for next command : &\ Write single byte to 8 locations &\ -------------------------------- ;LDA tubeR1data :\ Get byte from TubeR1 FSTA (&70),Y:INY :\ Write to screen RAM eight times :STA (&70),Y:INY :\ as fast as possible STA (&70),Y:INY STA (&70),Y:INY STA (&70),Y:INY STA (&70),Y:INY STA (&70),Y:INY STA (&70),Y:INY FBNE transfer_loop1 :\ Not next page, go back for more >INC &71 :\ Incr. address high byte M&BPL transfer_loop1 :\ If not wrapped round, go back for more H0LDA #&40:STA &71 :\ Reset to start of screen at &4000 8:BNE transfer_loop1 :\ And back for more D: "N\ Write 8 bytes to 8 locations "X\ ---------------------------- b.transfer_loop2 :lLDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :vLDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory :LDA tubeR1data:STA (&70),Y:INY :\ Copy byte to memory FBNE transfer_loop1 :\ Not next page, go back for more >INC &71 :\ Incr. address high byte MBPL transfer_loop1 :\ If not wrapped round, go back for more HLDA #&40:STA &71 :\ Reset to start of screen at &4000 8BNE transfer_loop1 :\ And back for more : : B\ OSWORD &FC - program CRTC controller, initialise mouse, etc. B \ ============================================================ A\ Commands are sent via TubeR2 within the OSWORD transaction: ( \ <&80,&mm - Write to CRTC register *\ &FF - No more commands %4\ &FE - Initialise mouse handler ">\ &FD - Initialise event code H\ &FC - Write to mouse port R\ Otherwise, exit \\ f.osword_crtc @pJSR getR2data:BMI &2A90 :\ Set up or exit if >&7F received AzSTA &FE00 :\ Write 6845 CRTC address register >JSR getR2data:STA &FE01 :\ Write 6845 CRTC data register .JMP osword_crtc :\ Loop for more : .osword_fc_1 5TAX:INX:BEQ osword_fc_exit :\ &FF - finished ?INX:BNE osword_fc_2 :\ Not &FE, try osword_fc_2 : )\ Command &FE - initialise Mouse code )\ ----------------------------------- ISEI :\ Disable IQRs while changing vector 6LDA irqv1+0:STA oldirq1+1 :\ Store old IQR1V LDA irqv1+1:STA oldirq1+2 2LDA #newirq 256:STA irqv1+0 :\ Set new IRQ1V CLDA #newirq 256:STA irqv1+1 :\ Store in IRQ1 vector high byte ;CLI :\ re-enable interrupts =LDA #0:STA &FE62 :\ Set UserData as inputs ?$LDA #&98:STA &FE6E :\ Enable CB1+CB2 interupts P.LDA &FE6B: #1:STA &FE6B :\ Enable PA latching, disable everything else 68LDA &FE6C: #&0F:STA &FE6C :\ Clear CB1 and CB2 =BJMP osword_crtc :\ Loop for more commands L: )V\ Command &FD - initialise Event code )`\ ----------------------------------- j.osword_fc_2 ?tINX:BNE osword_fc_3 :\ Not &FD, try osword_fc_3 7~LDA eventvec+0:STA oldevent+1 :\ Store old EventV !LDA eventvec+1:STA oldevent+2 9LDA #newevent 256:STA eventvec+0 :\ Set new EventV &LDA #newevent 256:STA eventvec+1 =JMP osword_crtc :\ Loop for more commands : '\ Command &FC - write to mouse port )\ ----------------------------------- \ Not implemented .osword_fc_3 4INX:BNE osword_fc_exit :\ Not &FC, exit =JMP osword_crtc :\ Loop for more commands : .osword_fc_exit  RTS : : (\ EVENT ESSING 2\ ================ ><\ On VSync event every 20cs, do some background processing F\ P.fdc_event 6ZLDX fdc_status :\ Get the FDC status >dLDY #0:STY status_pending :\ Clear the FDC pending flag LnLDA #&0A :\ Pass on as Event 10 - FDC result waiting x.oldevent 9JMP &0000 :\ Pass on to old EVENTV : 5\ Two-key rollover processing done on VSync event 5\ ----------------------------------------------- .eventcode ECMP #4:BNE oldevent :\ Not Event 4 (VSync), pass on ELDA status_pending:BEQ eventcode1 :\ Skip if no FDC event pending 9JSR fdc_event :\ Do the FDC event .eventcode1 =JSR keyscan :\ Test SHIFT/CTRL keys GPHP:LDA key1: #&7F:PLP:PHP :\ Get current key with bit 7 clear ABPL no_ctrl:A #&80 :\ Set bit 7 is CTRL pressed .no_ctrl HTAX:LDA key2: #&7F:PLP :\ Get previous key with bit 7 clear BBVC no_shift:A #&80 :\ Set bit 7 if SHIFT pressed .no_shift M"TAY :\ X=CTRL+current key, Y=SHIFT+last key A,LDA #4:JSR oldevent :\ Call old EVENTV claimant 6: >@\ The current key (if any in now in X - The top bit is set AJ\ if CONTROL was pressed, even when no other key was pressed. AT\ The previous key, (if any) is now in Y - The top bit is set E^\ if SHIFT was pressed, even when there is no previous key press. Dh\ This results in VSync Event handler being passed keypresses in Ar\ X and Y and thence passed over the Tube to the coprocessor. |: .async_command GJSR read_R4:BEQ async_exit :\ Read from TubeR4, exit if zero ITAX:DEX:BNE async_mouse :\ Not &01, skip to try async_mouse : \ Update 6845 CRTC registers \ -------------------------- TJSR read_R4:STA &FE00 :\ Get data from TubeR4, write as CRTC address QJSR read_R4:STA &FE01 :\ Get data from TubeR4, write as CRTC data FJMP async_command :\ Go back for any more commands : *\ Read mouse button state and position *\ ------------------------------------ .async_mouse 9DEX:BNE async_leds :\ Not &02, skip to try async_leds 3LDA amx:PHP :\ Set flags from mouse type /LDA userport :\ Read mouse data lines 2&PLP:BEQ &2B4F :\ Not AMX, skip adjustment @0ROL A:ROL A:ROL A :\ AMX buttons are top bits, so move them 9:ROL A :\ Buttons are now in bits 0, 1, 2 D.async_mouse_1 5N #7: #7 :\ Mask off and invert the buttons 9XJSR write_R1 :\ Send the button state to TubeR1 DbLDX #3 :\ Prepare to send four bytes of mouse coords l.async_mouse_2 AvLDA mouse_y_hi,X:JSR write_R1 :\ Send mouse coords to TubeR1 DEX:BPL async_mouse_2 CJMP async_command :\ Go back for any more commands : )\ Set keyboard status and update LEDs )\ ----------------------------------- .async_leds ?DEX:BNE async_command :\ Not &03, go back for more commands 2JSR read_R4:TAX :\ Read data from TubeR4 6LDA #&CA :\ *FX 202 - keyboard status 0LDY #0:JSR osbyte :\ Set keyboard status 8LDA #&76:JSR osbyte :\ Update LEDs to match status :JMP async_command :\ Go back for any more commands : .async_exit  RTS :  \ Test SHIFT and CTRL keys *\ ------------------------ 4.keyscan 7>CLC:CLV:JMP (keyvec) :\ CC+CV=Test SHIFT+CTRL H: R: $\\ WARNING! MASKABLE ERRUPT CODE Af\ =========================================================== @p\ X and Y must be preserved here. The original contents of A ?z\ are preserved by the MOS, in zero page location &FC. This A\ must be reloaded before exiting - with an RTI if we process A\ the interrupt, or if we jump to the original vector because \ we're not interested. : .newirq1 <LDA &FE6D :\ Get Interupt Flag register @ #&18:BNE new_irq_code :\ Branch if CB1 or CB2 active edge HLDA &FC :\ Not CB1 or CB2, restore A and continue .oldirq1 6JMP &0000 :\ Pass on to old IRQ1V : .new_irq_code =STA ifr_copy :\ Save CB1/CB2 interupt flags 0LDA userport:STA orb_copy :\ Get PortB data 3 #&18 :\ Check for AMX mouse ACMP #&18:BEQ new_irq_code2 :\ Will be %xxx11xxx for AMX mouse <$LDA #0:STA amx :\ Set amx=0 for tracker ball M.LDA #&08:STA mouse_y_quad :\ Set data bit for tracker ball y_quad signal M8LDA #&10:STA mouse_x_quad :\ Set data bit for tracker ball x_quad signal B: L\ Check for X movement V\ -------------------- `.new_irq_code2 LDA x_edge :\ Get get edge triggering mode ) #&FF:STA x_edge :\ Invert it 8 orb_copy :\ Invert with edge trigger 4 mouse_y_quad :\ Test X direction bit <BNE new_irq_code3 :\ Xdir set, decrease X coord >INC mouse_x_lo :\ Xdir clear, increase X coord FBNE new_irq_code5 :\ No rollover, jump to check Ymovement 7INC mouse_x_hi :\ Increase X coordinate =JMP new_irq_code5 :\ And jump to check Ymovement  .new_irq_code3 2LDA mouse_x_lo :\ Decrement Xcoord 7BNE new_irq_code4 :\ Do a 16-bit decrement 6(DEC mouse_x_hi :\ Decrement mouse_x_hi 2.new_irq_code4 6<DEC mouse_x_lo :\ Decrement mouse_x_lo F: P\ Check for Y movement Z\ -------------------- d.new_irq_code5 INC mouse_y_lo :\ Ydir cler, increment Y coord 3BNE new_irq_code8 :\ No rollover, exit 3INC mouse_y_hi :\ Increment Y coord 4JMP new_irq_code8 :\ And jump to finish .new_irq_code6 3LDA mouse_y_lo :\ Decrement Y coord 7"BNE new_irq_code7 :\ Do a 16-bit decrement 6,DEC mouse_y_hi :\ Decrement mouse_y_hi 6.new_irq_code7 6@DEC mouse_y_lo :\ Decrement mouse_y_lo J: T.new_irq_code8 G^LDA &FE6C: #&0F :\ Get peripheral control register CA bits ChA pcr_copy:STA &FE6C :\ Update with stored CB control bits =rLDA #&18:STA &FE6D :\ Clear CB1 and CB2 interupts D|LDA &FC:RTI :\ Recover A and return from interupt : =.amx :EQUB &FF :\ default is AMX, 0 = Tracker 8.mouse_y_quad:EQUB 1 :\ 01 = AMX, 08 = Tracker 8.mouse_x_quad:EQUB 4 :\ 04 = AMX, 10 = Tracker 7.ifr_copy :BRK :\ RAM copy of IFR state 9.orb_copy :BRK :\ RAM copy of user port B A.x_edge :BRK :\ defines pos/neg edge triggering A.y_edge :BRK :\ defines pos/neg edge triggering 3.pcr_copy :BRK :\ Local copy of PCR : ;\ E A local copy of the peripheral control register is =\ maintained at pcr_copy because someone is reprogramming ?\ the VIA when they shouldn't be, leading to mouse reversal 2\ - suspect a Master 128 hardware problem (??) : #\ OSWORD &FE - HARD DISK ACCESS #&\ ============================= 0.osword_fe $:RTS :\ not implemented D: N: )X.pad :\ Pad to page boundary !bEQUS ((P%+256)&FF00)-P%,0) l] GvA$=fname$+" "+~mcode%+" "+~O%+" "+~(exec%&FFFF0000)+" "+~load% "Saving ";A$: "SAVE "+A$: