10REM This is the source of the FORK utility 20REM which saves the entire machine context including registers 30REM for later resumption of execution. 40 50REM The two resumed environments differ only in the return code 60REM from the FX which invoked the save. 70 80EditNo=6 90ReleaseNo=0 100VerNo=2 110SaveServ = &31 120LoadServ = &32 130ServiceNo = &30 140ToSWcode = 1 150FromSWcode=0 160nop = &EA 170zp0=0 180zp1=1 190zp2=2 200zp3=3 210OsCli=&FFF7 220OsByte = &FFF4 230DIM Code &400 240FOR Pass = 4 TO 6 STEP 2 250P%=&8000:O%=Code 260[OPT Pass 270.RomStart 280 JMP &DEAD 290 Jmp Service 300 EQUB &82 310 EQUB CopyR-RomStart 320 EQUB ReleaseNo 330 EQUS "Oops!":EQUB 0 340 EQUS "V"+STR$(VerNo)+"."+STR$(ReleaseNo)+"."+STR$(EditNo) 350.CopyR EQUB 0 360 EQUS "(C) E.S.P. 1987" 370 EQUB 0 380.Service 390 PHP 400 CMP #1:BEQ RELOAD 410 Cmp #ServiceNo 420 Beq OurService 430 Cmp #SaveServ 440 Beq InitSAVE 450 Cmp #LoadServ 460 Beq InitLOAD 470 PLP 480 Rts 490.RELOAD 500 Lda OneTime:Cmp #0:Beq nogo 510 Lda &28D 520 Cmp #2:Bne InitLOAD 530.nogo 540 Lda #1 550 Plp 560 Rts 570.InitSAVE 580 PLP 590 Jsr save 600 \****************** THE RE-LOAD CODE WILL EFFECTIVELY RETURN TO HERE!!! 610 Lda #0 620 Rts 630.InitLOAD 640 PLP 650 Jsr load 660 Lda #0 670 Rts \ In actual fact it will never get here... 680.OurService \ Copy our 8K in or out of Ram at the appropriate address 690 \ this call is invoked by rom #15 which preserves zp0..3 for the others 700 \ and takes care not to copy over those variables when copying s/w ram. 710\ A = Service No 720\ X = Rom No (Used to calculate address) 730\ Y = Direction (0 = Read, 1 = Write) 740\ NOTE! MUST NOT claim the call 750 760 PLP \ Balance up stack 770 Tya:And #254:Pha 780 Tya:And #1:Tay 790 Pla: Sta RamAddr 800 \ A now contains RAM address. 810 Cpy #ToSWcode:Beq ReadMainRam 820.WriteMainRam \ i.e. load from s/w 830 \ The first RamRom to get the RELOAD command has tweaked the data of 840 \ the Lda # commands at patch1 & patch2 below, therefore does not 850 \ overwrite the loop variables while using them... 860 870 Clc 880.load1 Adc #0 890 Sta zp1 900 Lda #0:Sta zp0 910 Lda #&A0 920 Clc 930.load2 Adc #0 940 Sta zp3:Clc:Adc #&40:Tax 950 Lda #0:Sta zp2 960 Ldy #0 970.ToRam 980 Lda (zp2),Y 990 Sta (zp0),Y 1000 Iny:Bne ToRam:Inc zp3:Inc zp1 1010 Inx:Bmi ToRam 1020 1030 LDX &F4 1040 1050 1060 1070 1080 1090 Lda #ServiceNo 1100 \ X remains same 1110 Ldy #FromSWcode 1120 PHA:Tya:Ora RamAddr:CLC:ADC #&20:Tay:PLA 1130 \ CC irrelevant 1140 Rts \ Unclaimed 1150.ReadMainRam \ i.e. save to s/w 1160 Sta zp1 1170 Lda #0:Sta zp0 1180 Lda #&A0:Sta zp3 1190 Lda #0:Sta zp2 1200 Ldy #0:Ldx #&C0 1210.FromRom 1220 Lda (zp0),Y 1230 Sta (zp2),Y 1240 Iny:Bne FromRom:Inc zp1:Inc zp3 1250 Inx:Bmi FromRom 1260 \ Done 1270 \ X unchanged 1280 Lda RamAddr:Clc:Adc #&20 1290 Ora #ToSWcode 1300 Tay 1310 Lda #ServiceNo 1320 \ CC irrelevant 1330 Rts \ Unclaimed 1340 1350 1360.load 1370 Lda OneTime:Cmp #0:Bne oklod:Rts:.oklod \ Nothing in yet... 1380\ Copy into RAM from s/w RAM 1390 Lda #2:Sta load1+1:Sta load2+1 \ Don't load stack or zero-page yet 1400 Lda &E7:Sta PrivE7 1410 Lda &EC:Sta PrivEC 1420 Lda &ED:Sta PrivED 1430 Lda &EE:Sta PrivEE 1440 Lda &2B1:Sta Priv2B1 1450 Lda &2B2:Sta Priv2B2 1460 Lda &2CA:Sta Priv2CA 1470 Lda &2CB:Sta Priv2CB 1480 Lda &2CC:Sta Priv2CC 1490 Lda &2CD:Sta Priv2CD 1500 Lda #143:Ldx #ServiceNo:Ldy #FromSWcode:Jsr OsByte 1510 \ RECOVER STACK HERE... 1520 \\ SEI 1530 Ldx PrivS:Txs \ PARANOIA 1540 Ldy #0 1550.stklp 1560 Lda &A100,Y:Sta &100,Y:Iny 1570 Bne stklp 1580 Lda &F4:Sta TMP0 1590 Ldy #0 1600.zpfetch 1610 Cpy #&F4:Beq skipincase 1620 Lda &A000,Y:Sta &00,Y 1630.skipincase \ mega-paranoia 1640 Iny 1650 Bne zpfetch 1660 Lda TMP0:Sta &F4 1670 Jsr Restore \ BEFORE restoring zp0..3 therefore can still use them. 1680 \ The below values are the ones last saved when 'save' was entered 1690 Lda PrivZP0:Sta zp0 1700 Lda PrivZP1:Sta zp1 1710 Lda PrivZP2:Sta zp2 1720 Lda PrivZP3:Sta zp3 1730 Ldx PrivS:Txs 1740 Ldx PrivX 1750 Ldy PrivY:LDY#0\FORKED FLAG 1760 Lda PrivCC:Pha 1770 Lda PrivE7:Sta &E7 1780 Lda PrivEC:Sta &EC 1790 Lda PrivED:Sta &ED 1800 Lda PrivEE:Sta &EE 1810 Lda Priv2B1:Sta &2B1 1820 Lda Priv2B2:Sta &2B2 1830 Lda Priv2CA:Sta &2CA 1840 Lda Priv2CB:Sta &2CB 1850 Lda Priv2CC:Sta &2CC 1860 Lda Priv2CD:Sta &2CD 1870 Lda &A0F4:Sta &F4 \ Plug s/w no. last. 1880 Lda PrivA 1890 Plp \ INTS NOW ENABLES 1900Rts \ Return to suspended context 1910.B4 EQUB 0+4:EQUB 4:EQUB 8+4:EQUB 8+4 1920.B5 EQUB 8+5:EQUB 5:EQUB 8+5:EQUB 5 1930.Restore \ Restore hardware to software copies. 1940 \ Soft copy of paging latch should be set to this rom!!! 1950 \ addressible latch... screen base 1960 \ p419. 1970 \ Lda #15:\ Sta &FE42 \ Select PB0 to PB3 as output bits 1980 Ldy &356 \ Screen size look up -> magic bit. 1990 \Select B4 2000 Lda B4,Y 2010 Sta &FE40 \ Write data (bit 3) to B4 (bits 0..2) 2020 \ now B5 2030 Lda B5,Y 2040 Sta &FE40 \ Write data (bit 3) to B5 (bits 0..2) 2050 Ldy &356 \ Memory map type 2060 Lda regtabidx,Y 2070 Tax 2080 Ldy #0 2090.set6845 2100 Sty &FE00 2110 Lda &C400,X:Inx 2120 Sta &FE01 2130 Iny:Cpy #12 2140 Bne set6845 \ registers 0 - 11 reset to defaults 2150 Lda &355:And #7:Cmp #7:Bne EasyR12R13 2160 Lda #13: Sta &FE00 2170 Lda &350: Sta &FE01 \ low byte as is. 2180 Lda #12: Sta &FE00 2190 Lda &351: Sec:Sbc #&74:Eor #&20 \ high byte fiddled 2200 Sta &FE01 2210 Lda #15: Sta &FE00 2220 Lda &34A: Sta &FE01 \ low byte as is. 2230 Lda #14: Sta &FE00 2240 Lda &34B: Sec:Sbc #&74:Eor #&20 \ high byte fiddled 2250 Sta &FE01 2260 Jmp ScradDone 2270 \ Do cursor later 2280.EasyR12R13 2290 Lda &350:Sta zp0 2300 Lda &351:BPL QQ1:Sec:Sbc #&50:.QQ1:Sta zp1 \debug bodge 2310 Lsr zp1:Ror zp0 2320 Lsr zp1:Ror zp0 2330 Lsr zp1:Ror zp0 \ screen start address DIV 8 2340 Lda #13:Sta &FE00 2350 Lda zp0:Sta &FE01 2360 Lda #12:Sta &FE00 2370 Lda zp1:Sta &FE01 \ set screen start address 2380 \ r14,15 cursor address - 34a,34b 2390 LDA &34A:STA zp0 2400 Lda &34B:Bpl QQ2:Sec:Sbc #&50:.QQ2:Sta zp1 2410 Lsr zp1:Ror zp0 2420 Lsr zp1:Ror zp0 2430 Lsr zp1:Ror zp0 2440 Lda #15:Sta &FE00 2450 Lda zp0:Sta &FE01 2460 Lda #14:Sta &FE00 2470 Lda zp1:Sta &FE01 \ high/low ok? 2480.ScradDone 2490 \ VIDEO ULA 2500 Lda &355 \ Mode: And #7 2510 Tay: Lda &C3F7,Y 2520 Sta &FE20 \ Write video ULA control reg 2530 \ Write pallette - table[0..15] at &36F 2540 \ Store at &FE21 or call OSWORD &0C (easiest!) 2550 Lda &360:STA TMP0 \ NOT OF COLOURS IN MODE - 1 2560.pal 2570 Ldy TMP0 2580 Lda &36F,Y 2590 StY osw:StA osw+1 2600 LDX #osw MOD 256:LDY #osw DIV 256:LDA #&C 2610 Jsr &FFF1 2620 DEC TMP0 2630 LDA TMP0 2640 Cmp #&FF:BNE pal 2650\ RESTORE KEYBOARD INTS 2660LDA #&81:STA &FE4E 2670Rts 2680.osw BRK:BRK:BRK:BRK:BRK 2690.regtabidx 2700EQUB &6E 2710EQUB &7A 2720EQUB &86 2730EQUB &92 2740EQUB &9E 2750 .PrivE7 NOP 2760.PrivEC NOP 2770.PrivED NOP 2780.PrivEE NOP 2790.Priv2B1 NOP 2800.Priv2B2 NOP 2810.Priv2CA NOP 2820.Priv2CB NOP 2830.Priv2CC NOP:.Priv2CD NOP 2840.save \ main ram to s/w slots 2850 Php 2860 Sta PrivA 2870 Pla:Sta PrivCC 2880 Stx PrivX 2890 Sty PrivY 2900 Tsx:Stx PrivS 2910\*******THIS IS THE CONTEXT WHICH IS LATER RESTORED SO IT IS THIS 2920\ STACK FROM WHICH THE RETURN ADDRESS WILL BE POPPED, i.e. 2930\ BACK TO THE CALLER OF THIS... (Marked loudly) 2940 \\ SEI \ want consistent image while saving 2950 Lda zp0:Sta PrivZP0 2960 Lda zp1:Sta PrivZP1 2970 Lda zp2:Sta PrivZP2 2980 Lda zp3:Sta PrivZP3 2990\ Copy into s/w RAM from RAM 3000 Lda #143:Ldx #ServiceNo:Ldy #ToSWcode:Jsr OsByte 3010 Lda #1:Sta OneTime \ Set 'loaded' flag 3020 Lda PrivZP0:Sta zp0 3030 Lda PrivZP1:Sta zp1 3040 Lda PrivZP2:Sta zp2 3050 Lda PrivZP3:Sta zp3 3060Rts 3070.PrivZP0 NOP 3080.PrivZP1 NOP 3090.PrivZP2 NOP 3100.PrivZP3 NOP 3110 .PrivCC NOP 3120 .PrivA NOP 3130 .PrivX NOP 3140 .PrivY NOP 3150 .PrivS NOP 3160.TMP0 NOP 3170.OneTime EQUB 0 3180.RamAddr 3190] 3200NEXT Pass 3210OSCLI("SAVE R.Backup "+STR$~(Code)+" "+STR$~(O%))