> OswFFv136/src 3 Source for OSWORD &FF in Z80 Tube client 1.36 : H( OSWORD &FF transfers blocks of memory between I/O and CoPro memory 2 XY?0 =&0D < XY?1 =&01 F XY!2 =I/O address P XY!6 =CoPro address )Z XY!10=Number of bytes to transfer %d XY?12=0 for C->H, =1 for H->C n: Jx Note: the default code does not work on the Electron as the Tube I/O ; port on the Electron is at &FCE5 instead of at &FEE5. : USERV=&200 @ctrl=&70:saveA=&72:unused=&73:addr=&74:count=&76:countLO=&77 : 5run%=&FFFF2500:load%=&FFFF0900:fname$="OswFFv136"  mcode% &180 P=0 1 P%=run%:O%=mcode% 9[OPT P*3+4:\ \v1.20 :\ v1.36 .L2500 BCLC:BCC L2505 \JMP L2505 :\ New USER entry .OldUSERV OEQUW &E310 \EQUW L2500:\ Swapped with USERV to claim .L2505 QCMP #&FF:BEQ L250C :\ If my OSWORD, jump to respond I"JMP (OldUSERV) :\ Continue via OldUSERV ,: 6.L250C J@STX ctrl+0:STY ctrl+1:PHA \STA saveA :\ Save OSWORD parameters J.L2511 CTLDA #&C0+7:JSR &0406 \new :\ Claim with ID=7 F^BCC L2511 \new :\ Loop until claimed HhLDY #&02:LDA (ctrl),Y:STA addr+0 :\ I/O address low byte IrINY:LDA (ctrl),Y:STA addr+1 :\ I/O address high byte B|: \JSR L259C :\ Claim the Tube FLDY #&0A:LDA (ctrl),Y:STA countLO \TAX :\ Get count low byte GINY:LDA (ctrl),Y:STA count \new :\ Get count high byte @A countLO:BNE L2534:BEQ L257F \new :\ Nothing to do .L2534 SLDA countLO \TXA :\ Jump forward if multiple of 256 WBEQ L253A:INC count \ :\ Inc high byte to balance DECs later .L253A /INY \LDY #&0C JLDA (ctrl),Y:PHA :\ Get read/write command FLDA ctrl+0:CLC:ADC #&06:TAX :\ Point to Control+6 VLDA #&00:ADC ctrl+1:TAY :\ XY->CoPro address in control block MPLA:PHA:JSR &406 :\ Initiate specified action HLDX countLO \new :\ Get vount low into X DPLA :\ Get command back JLDY #0 \new :\ Zero offset for (zp),Y GCMP #0:BEQ L2567 \new :\ Transfer bytes C->H G&CMP #1:BEQ L2581 \new :\ Transfer bytes H->C G0CMP #2:BEQ L2598 \new :\ Transfer pairs C->H G:CMP #3:BEQ L25C2 \new :\ Transfer pairs H->C :DLDA #0:BEQ L257F \new :\ Ignore N: X\ 1-byte CoPro->Host b\ ------------------ l.L2567 IvJSR L25F6 :\ Delay before starting J: \LDY #&00 :\ Zero offset for (zp),Y .L256A HLDA &FEE5:STA (addr),Y :\ Transfer a byte C->H GJSR L25F6 :\ Delay between bytes 0: \JSR L259B 0: \JSR L259B FINC addr+0:BNE L2578:INC addr+1 :\ Update I/O address .L2578 LDEX:BNE L256A :\ Loop for up to 256 bytes PDEC count:BNE L256A :\ Loop for each 256-byte chunk .L257F NBEQ L25EB :\ Jump to exit when finished : \ 1-byte Host->CoPro  \ ------------------ J: \LDY #&00 :\ Zero offset for (zp),Y .L2581 F*LDA (addr),Y:STA &FEE5 :\ Transfer byte H->C G4JSR L25F6 :\ Delay between bytes 0>: \JSR L259B 0H: \JSR L259B FRINC addr+0:BNE L258F:INC addr+1 :\ Update I/O address \.L258F LfDEX:BNE L2581 :\ Loop for up to 256 bytes PpDEC count:BNE L2581 :\ Loop for each 256-byte chunk NzBEQ L25EB :\ Jump to exit when finished : :\ 2-byte CoPro->Host - must be an even number of bytes :\ ---------------------------------------------------- .L2598 IJSR L25F6 \new :\ Delay before starting *.L259B \new HLDA &FEE5:STA (addr),Y \new :\ Transfer a byte C->H FINC addr+0:BNE L25A6:INC addr+1 \new :\ Update I/O address *.L25A6 \new LNOP:NOP \new :\ Sort delay between bytes HLDA &FEE5:STA (addr),Y \new :\ Transfer a byte C->H FINC addr+0:BNE L25B3:INC addr+1 \new :\ Update I/O address *.L25B3 \new GJSR L25F5 \new :\ Delay between bytes LNOP:NOP \new :\ Sort delay between bytes LDEX:DEX:BNE L259B \new :\ Loop for up to 256 bytes P$DEC count:BNE L259B \new :\ Loop for each 256-byte chunk N.BEQ L25EB \new :\ Jump to exit when finished 8: :B\ 2-byte Host->CoPro - must be an even number of bytes :L\ ---------------------------------------------------- V.L25C2 F`LDA (addr),Y:STA &FEE5 \new :\ Transfer byte H->C FjINC addr+0:BEQ L25CE \new :\ Update I/O address MtNOP:BNE L25D0 \new :\ Short delay between bytes *~.L25CE \new *INC addr+1 \new *.L25D0 \new OLDA unused \new :\ Another delay between bytes FLDA (addr),Y:STA &FEE5 \new :\ Transfer byte H->C FINC addr+0:BEQ L25DE \new :\ Update I/O address MNOP:BNE L25E0 \new :\ Short delay between bytes *.L25DE \new *INC addr+1 \new *.L25E0 \new GJSR L25F5 \new :\ Delay between bytes LDEX:DEX:BNE L25C2 \new :\ Loop for up to 256 bytes PDEC count:BNE L25C2 \new :\ Loop for each 256-byte chunk : .L25EB ELDA #&80+7:JSR &0406 \JSR L25A4 :\ Release with ID=7 KLDX ctrl+0:LDY ctrl+1:PLA \LDA saveA :\ Restore entry registers J(.L25F5 :\ Call here to delay 6us >2RTS :\ And return <: F.L25F6 >PJSR L25F5:JSR L25F5:RTS \new :\ Delay 18us Z: -d: \.L259C 1n: \LDA #&C0+7 Cx: \JSR &0406 :\ Claim with ID=7 F: \BCC L259C :\ Loop until claimed *: \RTS : -: \.L25A4 1: \LDA #&80+7 E: \JSR &0406 :\ Release with ID=7 *: \RTS .end% : 1]:P%=P%-run%+load%:off%=run%-load%:[OPT P*3+4 : @\ This code allows OSWORD &FF to live in a *runnable program : .exec% DBIT &27A:BPL SetupExit :\ No Tube present JLDA USERV+0:CMP OldUSERV-off%+0:BNE Setup :\ Vector diff, claim it J"LDA USERV+1:CMP OldUSERV-off%+1:BEQ SetupExit :\ Same, already claimed ,.Setup X6PHP:SEI:LDY #0 :\ Prevent IRQs while changing vectors @.SetupLp MJLDA load%,Y:STA run%,Y:INY :\ Copy code to main memory $TCPY #(end%-run%)&FF:BNE SetupLp @^LDA USERV+0:LDX OldUSERV+0 :\ Claim USERV hSTX USERV+0:STA OldUSERV+0 rLDA USERV+1:LDX OldUSERV+1 |STX USERV+1:STA OldUSERV+1 >PLP :\ Restore IRQs and exit .SetupExit RTS : ] GA$=fname$+" "+~mcode%+" "+~O%+" "+~(exec%&FFFF0000)+" "+~load% "Saving ";A$: "SAVE "+A$: