10
20
30 :
40
50
60
70
80
90
100
110 :
120
130
140 :
150 OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE
160 OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0
170 USERV=&200
180 :
190 ctrl=&70:saveA=&72:unused=&73:addr=&74:count=&76
200 :
210 run%=&FFFF2500:load%=&FFFF0900
220 DIM mcode% &100
230 FOR P=0 TO 1
240 P%=run%:O%=mcode%
250 [OPT P*3+4
260 .L2500
270 JMP L2505 :\ New USER entry
280 .OldUSERV
290 EQUW L2500 :\ Swapped with USERV to claim
300 .L2505
310 CMP #&FF:BEQ L250C :\ If my OSWORD, jump to respond
320 JMP (OldUSERV) :\ Continue via OldUSERV
330
340 .L250C
350 STX ctrl+0:STY ctrl+1:STA saveA :\ Save OSWORD parameters
360 LDY #&02:LDA (ctrl),Y:STA addr+0 :\ I/O address low byte
370 INY:LDA (ctrl),Y:STA addr+1 :\ I/O address high byte
380 JSR L259C :\ Claim the Tube
390 LDY #&0C:LDA (ctrl),Y:PHA :\ Get read/write command
400 LDA ctrl+0:CLC:ADC #&06:TAX :\ Point to Control+6
410 LDA #&00:ADC ctrl+1:TAY :\ XY->CoPro address in control block
420 PLA:PHA:JSR &406 :\ Initiate specified action
430 LDY #&0A:LDA (ctrl),Y:TAX :\ Get count low byte
440 INY:LDA (ctrl),Y:STA count :\ Get count high byte
450 BNE L2544 :\ Jump forward if >255 bytes to do
460 TXA:BEQ L2592 :\ Jump to exit if no bytes left
470 .L2544
480 TXA:BEQ L2549 :\ Jump forward if multiple of 256 bytes
490 INC count :\ Inc high byte to balance DECs later
500 .L2549
510 PLA:ROR A:BCS L2575 :\ Get command back, jump if H->C
520 :
530 JSR L259B:JSR L259B:JSR L259B :\ Delay before starting
540 LDY #&00 :\ Zero offset for (zp),Y
550 .L2558
560 LDA &FEE5:STA (addr),Y :\ Transfer a byte C->H
570 JSR L259B:JSR L259B:JSR L259B :\ Delay between bytes
580 INC addr+0:BNE L256C:INC addr+1 :\ Update I/O address
590 .L256C
600 DEX:BNE L2558 :\ Loop for up to 256 bytes
610 DEC count:BNE L2558 :\ Loop for each 256-byte chunk
620 BEQ L2592 :\ Jump to exit when finished
630 :
640 .L2575
650 LDY #&00
660 .L2577
670 LDA (addr),Y:STA &FEE5 :\ Transfer byte H->C
680 JSR L259B:JSR L259B:JSR L259B :\ Delay between bytes
690 INC addr+0:BNE L258B:INC addr+1 :\ Update I/O address
700 .L258B
710 DEX:BNE L2577 :\ Loop for up to 256 bytes
720 DEC count:BNE L2577 :\ Loop for each 256-byte chunk
730 :
740 .L2592
750 JSR L25A4 :\ Release Tube
760 LDX ctrl+0:LDY ctrl+1:LDA saveA :\ Restore entry registers
770 .L259B :\ Call here to delay 6us
780 RTS :\ And return
790
800 .L259C
810 LDA #&C0+7:JSR &0406 :\ Claim with ID=7
820 BCC L259C:RTS :\ Loop until claimed
830
840 .L25A4
850 LDA #&80+7:JSR &0406 :\ Release with ID=7
860 RTS
870 .end%
880
890 ]:P%=P%-run%+load%:off%=run%-load%:[OPT P*3+4
900 :
910 \ This code allows OSWORD &FF to live in a *runnable program
920 :
930 .exec%
940 BIT &27A:BPL SetupExit :\ No Tube present
950 LDA USERV+0:CMP OldUSERV-off%+0:BNE Setup :\ Vector diff, claim it
960 LDA USERV+1:CMP OldUSERV-off%+1:BEQ SetupExit :\ Same, already claimed
970 .Setup
980 PHP:SEI:LDY #0 :\ Prevent IRQs while changing vectors
990 .SetupLp
1000 LDA load%,Y:STA run%,Y:INY :\ Copy code to main memory
1010 CPY #end%-run%:BNE SetupLp
1020 LDA USERV+0:LDX OldUSERV+0 :\ Claim USERV
1030 STX USERV+0:STA OldUSERV+0
1040 LDA USERV+1:LDX OldUSERV+1
1050 STX USERV+1:STA OldUSERV+1
1060 PLP :\ Restore IRQs and exit
1070 .SetupExit
1080 RTS
1090 :
1100 ]NEXT
1110 PRINT "*SAVE OSWFF ";~mcode%;" ";~O%;" ";~exec%OR&FFFF0000;" ";~load%