10
20
30 :
40
50
60
70
80
90
100
110
120
130
140 :
150
160
170
180
190
200 :
210
220
230
240
250
260
270 :
280 OSBYTE=&FFF4
290 ctrl=&70:rom=&72:shadow=&73:addr=&74:numHI=&76:numLO=&77
300 :
310 load%=&FFFF2500:exec%=load%:fname$="OswFA"
320 DIM mcode% &1FF
330 FOR P=0 TO 1
340 P%=load%:O%=mcode%
350 [OPT P*3+4
360 .L2500
370 CLC:BCC L2505 :\ New USER entry
380 .OldUSERV
390 EQUW &E310 :\ Holds old USERV entry
400 .L2505
410 CMP #&FA:BEQ L250C :\ If my OSWORD, jump to respond
420 JMP (OldUSERV) :\ Continue via OldUSERV
430 :
440 .L250C
450 STX ctrl+0:STY ctrl+1:PHA :\ Save OSWORD parameters, can't use &F0/&F1
460 LDA #&FB:LDX #&00:LDY #&FF :\ as OSBYTE calls will overwrite them
470 JSR OSBYTE:STX shadow :\ Get shadow screen setting (Master only)
480 LDA &FE34:PHA :\ Save current ACCCON setting (Master only)
490 .L2520
500 LDA #&C0+7:JSR &0406 :\ Claim with ID=7
510 BCC L2520 :\ Loop until claimed
520 LDY #&00:LDA (ctrl),Y :\ Read number of parameters
530 CMP #&0D:PHP :\ Save EQ/NE for memory access byte supplied
540 LDA &F4:STA rom :\ Save current ROM
550 LDY #&0D:LDA (ctrl),Y:TAX :\ Get ROM access value
560 LDY #&02:LDA (ctrl),Y:STA addr+0 :\ I/O address low byte
570 INY:LDA (ctrl),Y:STA addr+1 :\ I/O address high byte
580 PLP:BEQ L2585 :\ Skip past if no memory access byte supplied
590 TXA :\ Get memory access byte
600 PHA:AND #&40:BNE L255E :\ b6 set, use shadow memory
610 TXA:AND #&20:BNE L2554 :\ b5 set, use current screen memory
620 :
630 \ Use I/O memory (equivalent to &FFFFxxxx)
640 \ ----------------------------------------
650 .L2550
660 LDX #&00:BEQ L2556 :\ Jump to select I/O memory
670 :
680 \ Use current screen memory (equivlent to &FFFExxxx)
690 \ --------------------------------------------------
700 .L2554
710 LDX #&01 :\ X=1 to select screen memory
720 .L2556
730 LDA #&6C:JSR OSBYTE :\ Select specified screen memory
740 JMP L2577 :\ Jump forward to test ROM number
750 :
760 \ Use shadow screen memory (&FFFDxxxx)
770 \ ------------------------------------
780 .L255E
790 \ The following tests if a shadow screen is selected
800 LDA #&84:JSR OSBYTE :\ Read top of I/O memory
810 CPY #&80:BNE L256F :\ If Y<>&80, not shadow screen
820 :
830 \ Shadow screen selected
840 \ ----------------------
850 LDA #&01:CMP shadow:BNE L2554 :\ Jump to select shadow memory
860 BEQ L2550 :\ Jump to select I/O memory
870 :
880 \ Non-shadow screen selected
890 \ --------------------------
900 .L256F
910 LDA #&02:CMP shadow:BNE L2550 :\ Jump to select I/O memory
920 BEQ L2554 :\ Jump to select screen memory
930 :
940 \ Test supplied ROM number
950 \ ------------------------
960 .L2577
970 PLA:TAX:AND #&10:BNE L2585 :\ b4 set, use current ROM
980 TXA:AND #&0F :\ Reduce to 0-15
990 STA &F4:STA &FE30 :\ Set ROMCOPY and select ROM
1000 :
1010 \ Prepare to do the transfer
1020 \ --------------------------
1030 .L2585
1040 LDY #&0A:LDA (ctrl),Y:STA numLO :\ Get count low byte
1050 INY:LDA (ctrl),Y:STA numHI :\ Get count high byte
1060 ORA numLO:BNE L2596:BEQ L2604 :\ Jump to finish if count=zero
1070 .L2596
1080 LDA numLO:BEQ L259C:INC numHI :\ Inc high byte to balance DECs later
1090 .L259C
1100 INY:LDA (ctrl),Y :\ Get transfer function
1110 :
1120 \ Loop to do multiple transfers
1130 \ -----------------------------
1140 .L259F
1150 PHA:LDA numLO:BEQ L25B5 :\ Count=&xx00, jump past
1160 LDA numHI:CMP #&01:BNE L25B5 :\ More than 256 bytes to transfer, jump past
1170 :
1180 \ If <256 bytes to transfer, convert 256-byte function to 1-byte function
1190 \ -----------------------------------------------------------------------
1200 PLA:PHA:CMP #&06:BCC L25B5 :\ Jump with <256-byte transfers
1210 PLA:SEC:SBC #&06:PHA :\ Convert 256-byte transfer to 1-byte transfer
1220 .L25B5
1230 LDA ctrl+0:CLC:ADC #&06:TAX :\ Point to Control+6
1240 LDA #&00:ADC ctrl+1:TAY :\ XY->CoPro address in control block
1250 PLA:PHA:JSR &0406 :\ Initiate specified action
1260 LDX numLO:PLA:LDY #&00
1270 CMP #&00:BEQ L25EC :\ Jump with 1-byte CoPro->I/O
1280 CMP #&01:BEQ L2607 :\ Jump with 1-byte I/O->CoPro
1290 CMP #&02:BEQ L261F :\ Jump with 2-byte CoPro->I/O
1300 CMP #&03:BEQ L264A :\ Jump with 2-byte I/O->CoPro
1310 CMP #&06:BEQ L25E6 :\ Jump with 256-byte CoPro->I/O
1320 CMP #&07:BEQ L25E9 :\ Jump with 256-byte I/O->CoPro
1330 LDA #&00:BEQ L2604 :\ Anything else, jump to release and finish
1340 .L25E6:JMP L2675 :\ Jump ahead with 256-byte transfer
1350 .L25E9:JMP L26A3 :\ Jump ahead with 256-byte transfer
1360 :
1370 \ 1-byte CoPro->I/O
1380 \ -----------------
1390 .L25EC
1400 JSR L26F4 :\ Delay before starting
1410 .L25EF
1420 LDA &FEE5:STA (addr),Y :\ Transfer a byte to I/O memory
1430 JSR L26F4 :\ Delay between bytes
1440 INC addr+0:BNE L25FD:INC addr+1 :\ Update I/O address
1450 .L25FD
1460 DEX:BNE L25EF :\ Loop for up to 256 bytes
1470 DEC numHI:BNE L25EF :\ Loop for each 256-byte chunck
1480 .L2604
1490 JMP L26DA :\ Jump to exit when finished
1500 :
1510 \ 1-byte I/O->CoPro
1520 \ -----------------
1530 .L2607
1540 LDA (addr),Y:STA &FEE5 :\ Transfer a byte from I/O memory
1550 JSR L26F4 :\ Delay between bytes
1560 INC addr+0:BNE L2615:INC addr+1 :\ Update I/O address
1570 .L2615
1580 DEX:BNE L2607 :\ Loop for up to 256 bytes
1590 DEC numHI:BNE L2607 :\ Loop for each 256-byte chunk
1600 JMP L26DA :\ Jump to exit when finished
1610 :
1620 \ 2-byte CoPro->I/O
1630 \ -----------------
1640 .L261F
1650 JSR L26F4 :\ Delay before starting
1660 .L2622
1670 LDA &FEE5:STA (addr),Y :\ Transfer a byte to I/O memory
1680 INC addr+0:BNE L262D:INC addr+1 :\ Update I/O address
1690 .L262D
1700 NOP:NOP :\ Delay between bytes
1710 LDA &FEE5:STA (addr),Y :\ Transfer a byte to I/O memory
1720 INC addr+0:BNE L263A:INC addr+1 :\ Update I/O address
1730 .L263A
1740 JSR L26F3:NOP:NOP :\ Delay
1750 DEX:DEX:BNE L2622 :\ Loop for up to 256 bytes
1760 DEC numHI:BNE L2622 :\ Loop for each 256-byte chunk
1770 JMP L26DA :\ Jump to exit when finished
1780 :
1790 \ 2-byte I/O->CoPro
1800 \ -----------------
1810 .L264A
1820 LDA (addr),Y:STA &FEE5 :\ Transfer a byte from I/O memory
1830 INC addr+0 :\ Update I/O address low byte
1840 BEQ L2656:NOP:BNE L2658 :\ Delay between bytes
1850 .L2656
1860 INC addr+1 :\ Update I/O address high byte
1870 .L2658
1880 LDA shadow :\ Delay by loading a byte
1890 LDA (addr),Y:STA &FEE5 :\ Transfer a byte from I/O memory
1900 INC addr :\ Update I/O address low byte
1910 BEQ L2666:NOP:BNE L2668 :\ Another delay added
1920 .L2666
1930 INC addr+1
1940 .L2668
1950 JSR L26F3 :\ Delay
1960 DEX:DEX:BNE L264A :\ Loop for up to 256 bytes
1970 DEC numHI:BNE L264A :\ Loop for each 256-byte chunk
1980 BEQ L26DA :\ Jump to exit when finished
1990 :
2000 \ 256-byte CoPro->I/O
2010 \ -------------------
2020 .L2675
2030 JSR L26F4 :\ Delay before starting
2040 .L2678
2050 LDA &FEE5:STA (addr),Y :\ Transfer a byte to I/O
2060 NOP:NOP:NOP:INY:BNE L2678 :\ Delay and loop for 256 bytes
2070 CPX #&00:BNE L2693 :\
2080 DEC numHI:BEQ L26DA :\ Loop for each 256-byte chunk
2090 .L268B
2100 JSR L26CE :\ Add 256 to I/O address in control block
2110 LDA #&06:JMP L259F :\ Jump back to do another 256-byte transfer
2120 :
2130 .L2693
2140 DEC numHI:LDA numHI :\ Decrement 256-byte counter
2150 CMP #&01:BNE L268B :\ If 256 bytes or more left, loop back
2160 JSR L26CE :\ Update I/O transfer address
2170 LDA #&00:JMP L259F :\ Do final bytes with 1-byte transfer
2180 :
2190 \ 256-byte I/O->CoPro
2200 \ -------------------
2210 .L26A3
2220 LDA (addr),Y:STA &FEE5 :\ Transfer a byte from I/O
2230 NOP:NOP:NOP:INY:BNE L26A3 :\ Delay and loop for 256 bytes
2240 CPX #&00:BNE L26BE
2250 DEC numHI:BEQ L26DA :\ Loop for each 256-byte chunk
2260 .L26B6
2270 JSR L26CE :\ Add 256 to I/O address in control block
2280 LDA #&07:JMP L259F :\ Jump back to do another 256-byte transfer
2290 :
2300 .L26BE
2310 DEC numHI:LDA numHI :\ Decrement 256-byte counter
2320 CMP #&01:BNE L26B6 :\ If 256 bytes or more left, loop back
2330 JSR L26CE :\ Update I/O transfer address
2340 LDA #&01:JMP L259F :\ Do final bytes with 1-byte transfer
2350 :
2360 \ Add 256 to I/O address in control block
2370 \ ---------------------------------------
2380 .L26CE
2390 INC addr+1 :\ Update I/O address
2400 LDY #&07:LDA (ctrl),Y :\ Get I/O address from control block
2410 CLC:ADC #&01:STA (ctrl),Y :\ Add 256 to it, store back
2420 RTS
2430 :
2440 \ Finished, release Tube and return
2450 \ ---------------------------------
2460 .L26DA
2470 LDA #&80+7:JSR &0406 :\ Release with ID=7
2480 LDA rom:CMP &F4:BEQ L26EA :\ Skip if previous ROM = current ROM
2490 STA &F4:STA &FE30 :\ Restore previous ROM
2500 .L26EA
2510 PLA:STA &FE34 :\ Restore ACCON
2520 LDX ctrl+0:LDY ctrl+1:PLA :\ Restore registers
2530 .L26F3
2540 RTS
2550 :
2560 \ Delay for 36 clock cycles
2570 \ -------------------------
2580 .L26F4
2590 JSR L26F3:JSR L26F3:RTS
2600 :
2610 ]NEXT
2620 A$=fname$+" "+STR$~mcode%+" "+STR$~O%+" "+STR$~(exec%OR&FFFF0000)+" "+STR$~load%
2630 PRINT"Saving ";A$:OSCLI "SAVE "+A$:PRINT