> OswFFv2/src ! Source for OSWORD &FF v1.02 5 Accesses sideways ROMs and shadow screen memory (( Adapts to Electron ROMSEL and Tube 2: H, =1 for H->C :  I/O address can be:  &FFxRxxxx for ROM R " &FF8xxxxx for workspace RAM  &FFFFxxxx for I/O memory + &FFFExxxx for current display memory * &FFFDxxxx for shadow display memory : 7OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE 7OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0 USERV=&200 : 4ctrl=&70:saveA=&72:unused=&73:addr=&74:count=&76 : "run%=&FFFF2500:load%=&FFFF0900  mcode% &180 " P=0 1 ,P%=run%:O%=mcode% 6[OPT P*3+4 @ .L2500 J6JMP L2505 :\ New USER entry T .OldUSERV ^CEQUW L2500 :\ Swapped with USERV to claim h .L2505 rECMP #&FF:BEQ L250C :\ If my OSWORD, jump to respond |=JMP (OldUSERV) :\ Continue via OldUSERV :  .L250C >STX ctrl+0:STY ctrl+1:PHA :\ Save OSWORD parameters 8LDA &F4:PHA :\ Save current ROM HLDA &FFB2: #&BC :\ Check for Electron, has to be done ICMP #&FC:BNE GetAddress :\ inline as no initialisation call ASTA TUBEIO1+2:STA TUBEIO2+2 :\ Change to Electron TUBEIO ALDA #5:STA ROMSEL+1 :\ Change to Electron ROMSEL : .GetAddress INX:BEQ GetIOMem :\ &FFFFxxxx - I/O memory &BINX:BEQ GetDisplay :\ &FFFExxxx - current screen 0AINX:BEQ GetShadow :\ &FFFDxxxx - shadow memory :BNE GetIOMem D: N.GetDisplay XLDA #&84:JSR OSBYTE bCTYA:BPL GetIOMem :\ Not shadow screen displayed l.GetShadow vLDA #1:JSR vramSelect :  .GetIOMem .TubeClaim @LDA #&C0+7:JSR &0406 :\ Claim the Tube with ID=7 :BCC TubeClaim :\ Loop until claimed >LDY #&0C:LDA (ctrl),Y:PHA :\ Get read/write command :LDA ctrl+0:CLC:ADC #&06:TAX :\ Point to Control+6 JLDA #&00:ADC ctrl+1:TAY :\ XY->CoPro address in control block APLA:PHA:JSR &406 :\ Initiate specified action 255 bytes to do FTXA:BEQ L2592 :\ Jump to exit if no bytes to do  .L2544  MTXA:BEQ L2549 :\ Jump forward if multiple of 256 bytes KINC count :\ Inc high byte to balance DECs later  .L2549 *FLDY #&00 :\ Prepare zero offset for (zp),Y 4FPLA:ROR A:BCS L2577 :\ Get command back, jump if H->C >: H\ Copy from Client to Host R\ ------------------------ \ .L2558 fLJSR TubeDelay :\ Delay before start and between bytes p .TUBEIO1 zH :INC addr+0:BNE L256C:INC addr+1 :\ Update I/O address  .L256C CDEX:BNE L2558 :\ Loop for sub-256 byte count DDEC count:BNE L2558 :\ Loop for each 256-byte chunk BBEQ L2592 :\ Jump to exit when finished : \ Copy from Host to Client \ ------------------------  .L2577 LDA (addr),Y  .TUBEIO2 :STA &FEE5 :\ Transfer byte H->C ;JSR TubeDelay :\ Delay between bytes :INC addr+0:BNE L258B:INC addr+1 :\ Update I/O address  .L258B CDEX:BNE L2577 :\ Loop for sub-256 byte count $DDEC count:BNE L2577 :\ Loop for each 256-byte chunk .: 8\ Release and return B\ ------------------ L .L2592 V>LDA #&80+7:JSR &0406 :\ Release Tube with ID=7 `@LDA #0:JSR vramSelect :\ Page main memory back in j3PLA:JSR ROMSelect :\ Restore ROM t?LDX ctrl+0:LDY ctrl+1:PLA :\ Restore entry registers ~2RTS :\ And return : B.TubeDelay :JSR TubeDelay2 :\ 24us between Tube accesses .TubeDelay2:JSR TubeDelay3 .TubeDelay3:RTS : .ROMSelect BPHA:LDA #12:JSR ROMSelect2:PLA :\ Double select for Electron .ROMSelect2  STA &F4  .ROMSEL  STA &FE30  .vramOk RTS  : .vramSelect ;PHA:TAX :\ A=0 main RAM, A=1 video RAM (BLDA #108:JSR OSBYTE :\ Attempt to select Master video RAM 22PLA:INX:BNE vramOk :\ X<>255, successful <9 #1:TAX :\ A=1 main RAM, A=0 video RAM FCLDA #111:JMP OSBYTE :\ Attempt to select Aries/Watford RAM P .end% Z d1]:P%=P%-run%+load%:off%=run%-load%:[OPT P*3+4 n: x@\ This code allows OSWORD &FF to live in a *runnable program A\ Can be * on top of itself or on top of other code at &2500 :  .exec% TPHP:SEI :\ Prevent IRQs while changing vectors @BIT &27A:BPL SetupExit :\ No Tube present KLDA USERV+1:CMP OldUSERV-off%+1:BNE Setup :\ Not linked to me, claim it KLDA USERV+0:CMP OldUSERV-off%+0:BNE Setup :\ Not linked to me, claim it NLDA OldUSERV+1:STA USERV+1 :\ Already linked, restore USERV DLDA OldUSERV+0:STA USERV+0 :\ And then reclaim it  .Setup  LDY #0  .SetupLp ILDA load%,Y:STA run%,Y:INY:BNE SetupLp :\ Copy code to main memory