10
20
30
40
50
60
70 :
80
90
100
110
120
130
140
150 :
160
170
180
190
200
210
220 :
230 OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE
240 OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0
250 USERV=&200
260 :
270 ctrl=&70:addr=ctrl+2:tube=ctrl+6:count=ctrl+10:action=ctrl+12
280 :
290 run%=&FFFF2500:load%=&FFFF0900:fname$="OswFFv3"
300 DIM mcode% &180
310 FOR P=0 TO 1
320 P%=run%:O%=mcode%
330 [OPT P*3+4
340 .L2500
350 JMP L2505 :\ New USER entry
360 .OldUSERV
370 EQUW L2500 :\ Swapped with USERV to claim
380 .L2505
390 CMP #&FF:BEQ L250C :\ If my OSWORD, jump to respond
400 JMP (OldUSERV) :\ Continue via OldUSERV
410 :
420 .L250C
430 PHP:CLI :\ Enable IRQs, allow clock, etc to run
440 STX ctrl+0:STY ctrl+1:PHA :\ Save OSWORD parameters
450 LDA &F4:PHA :\ Save current ROM
460 LDA &FFB2:EOR #&BC :\ Check for Electron, has to be done
470 CMP #&FC:BNE GetAddress :\ inline as no initialisation call
480 STA TUBEIO1+2:STA TUBEIO2+2 :\ Change to Electron TUBEIO
490 :
500 .GetAddress
510 LDY #12
520 .GetAddrLp
530 LDA (ctrl),Y:STA ctrl,Y :\ Copy control block
540 DEY:CPY #2:BCS GetAddrLp
550 STY &F7 :\ (&F6)=>&02xx, safe ROMSEL access
560 LDA addr+2:ADC #&40 :\ Allow &0x and &Fx for ROMs
570 AND #&8F:JSR ROMSelect :\ Page in ROM
580 LDX addr+2 :\ Get screen byte
590 INX:BEQ GetIOMem :\ &FFFFxxxx - I/O memory
600 INX:BEQ GetDisplay :\ &FFFExxxx - current screen
610 INX:BEQ GetShadow :\ &FFFDxxxx - shadow memory
620 BNE GetIOMem
630 :
640 .GetDisplay
650 LDA #&84:JSR OSBYTE
660 TYA:BPL GetIOMem :\ Not shadow screen displayed
670 .GetShadow
680 LDA #1:JSR vramSelect
690 :
700 .GetIOMem
710 .TubeClaim
720 LDA #&C0+7:JSR &0406 :\ Claim the Tube with ID=7
730 BCC TubeClaim :\ Loop until claimed
740 LDX #addr+4:LDY #0 :\ XY=>CoPro address
750 LDA action:PHA:JSR &406 :\ Initiate specified action
760 LDX count+1:INX :\ Get X=count high byte
770 LDY #&00 :\ Prepare zero offset for (zp),Y
780 PLA:ROR A:BCS L2585 :\ Get command back, jump if H->C
790 SEC:BCS L2568 :\ Jump to do C->H
800 :
810 \ Copy from Client to Host
820 \ ------------------------
830 .L2558
840 JSR L259B:JSR L259B:JSR L259B :\ Delay before starting and between bytes
850 .TUBEIO1
860 LDA &FEE5:STA (addr),Y :\ Transfer a byte C->H
870 INY:BCC L2570 :\ Skip for last few bytes
880 BNE L2558 :\ Loop for 256 bytes
890 INC addr+1
900 .L2568
910 DEX:BNE L2558 :\ Loop for each block of 256 bytes
920 CLC:LDX count:INX :\ Get count of remaining bytes
930 .L2570
940 DEX:BNE L2558 :\ Loop for remaining bytes
950 BEQ L2592 :\ Jump to exit when finished
960 :
970 \ Copy from Host to Client
980 \ ------------------------
990 .L2577
1000 LDA (addr),Y:.TUBEIO2:STA &FEE5 :\ Transfer byte H->C
1010 JSR L259B:JSR L259B:JSR L259B :\ Delay between bytes
1020 INY:BCC L258F :\ Skip for last few bytes
1030 BNE L2577 :\ Loop for 256 bytes
1040 INC addr+1
1050 .L2585
1060 DEX:BNE L2577 :\ Loop for each block of 256 bytes
1070 CLC:LDX count:INX :\ Get count of remaining bytes
1080 .L258F
1090 DEX:BNE L2577 :\ Loop for remaining bytes
1100 :
1110 \ Release and return
1120 \ ------------------
1130 .L2592
1140 LDA #&80+7:JSR &0406 :\ Release Tube with ID=7
1150 LDA #0:JSR vramSelect :\ Page main memory back in
1160 PLA:JSR ROMSelect :\ Restore ROM
1170 LDX ctrl+0:LDY ctrl+1:PLA :\ Restore entry registers
1180 PLP :\ Restore IRQs and return
1190 .L259B :\ Call here to delay 6us
1200 .vramOk
1210 RTS
1220 :
1230 .vramSelect
1240 PHA:TAX :\ A=0 main RAM, A=1 video RAM
1250 LDA #108:JSR OSBYTE :\ Attempt to select Master video RAM
1260 PLA:INX:BNE vramOk :\ X<>255, successful
1270 EOR #1:TAX :\ A=1 main RAM, A=0 video RAM
1280 LDA #111:JMP OSBYTE :\ Attempt to select Aries/Watford RAM
1290 :
1300 .ROMSelect
1310 STA &F4:JMP &FFB9 :\ Page ROM in via OSRDRM
1320 .end%
1330 :
1340 ]:P%=P%-run%+load%:off%=run%-load%:[OPT P*3+4
1350 :
1360 \ This code allows OSWORD &FF to live in a *runnable program
1370 \ Can be *RUN on top of itself or on top of other code at &2500
1380 :
1390 .exec%
1400 PHP:SEI :\ Prevent IRQs while changing vectors
1410 BIT &27A:BPL SetupExit :\ No Tube present
1420 LDA USERV+1:CMP OldUSERV-off%+1:BNE Setup :\ Not linked to me, claim it
1430 LDA USERV+0:CMP OldUSERV-off%+0:BNE Setup :\ Not linked to me, claim it
1440 LDA OldUSERV+1:STA USERV+1 :\ Already linked, restore USER V
1450 LDA OldUSERV+0:STA USERV+0 :\ And then reclaim it
1460 .Setup
1470 LDY #0
1480 .SetupLp
1490 LDA load%,Y:STA run%,Y:INY:BNE SetupLp :\ Copy code to main memory
1500 LDA USERV+1:LDX OldUSERV+1 :\ Claim USERV
1510 STX USERV+1:STA OldUSERV+1
1520 LDA USERV+0:LDX OldUSERV+0
1530 STX USERV+0:STA OldUSERV+0
1540 .SetupExit
1550 PLP:RTS :\ Exit
1560 :
1570 ]NEXT
1580 A$=fname$+" "+STR$~mcode%+" "+STR$~O%+" "+STR$~(exec%OR&FFFF0000)+" "+STR$~load%
1590 PRINT"Saving ";A$:OSCLI "SAVE "+A$:PRINT