10Debug=TRUE 30nl$=CHR$&0D 40A=&103:X=&102:Y=&101: REM FNPush'ed offsets 50Handle=4 60TooManyOpen=&C0 70CantFileOpen=&C2 71DataLost=&CA 80BadName=&CC 90OsWrch=&FFEE 100OsAscii=&FFE3 110OsNewl=&FFE7 120OsByte=&FFF4 130OsArgs=&FFDA 140OsFind=&FFCE 150OsFileV=&212 160OsFindV=&21C 170OsBputV=&218 180RFSFile=&1234 190RFSFind=&1234 200RFSBput=&1234 210Header=&1234 220HeadCRC=&1234+5 230RomEnd=&9FFF 240zTemp=&70 250zWritePointer=zTemp+2 260zFileName=zWritePointer+2 270zParameter=zFileName+2 280zNewBlock=zParameter+2 290zp0=zNewBlock+2 300zp1=zp0+1 310CodeSize=&600 320PROCassemble 330PROCloadrom 340END 350. 360DEFPROCassemble 370DIM Code CodeSize 380FOR Pass = 4 TO 6 STEP 2 390P%=&8000 400O%=Code 410[OPT Pass 420 BRK:BRK:BRK 430 Jmp Service 440 EQUB &82 \ &C2 450 EQUB CopyR-&8000 460.version EQUB 1 470.RomName 480 EQUS "Rom/Ram Filing System":EQUB 0 490.VersString 500 EQUS "V1.0.1" 510.CopyR 520 EQUB 0 530 EQUS "(C) GT+KDR 1986" 540 EQUB 0 550.OldFileV EQUW 0 560.OldFindV EQUW 0 570.OldBputV EQUW 0 580.Hi EQUB 0 590.Lo EQUB 0 600.NewBlock EQUW DataStart 610.NewBlockIndex EQUB 0 620.FileNameNull EQUB 0 630.ParameterIndex EQUB 0 640.Temp EQUW 0 650.EndAddress EQUW 0 660.BytesCopied EQUW 0 670.WritePointer EQUW 0 680.FileOpen EQUB 0 690.RomEnd EQUB &A000 DIV 256 700 710.Service 720 OPT FNPush 730 OPT FNLdStack(A) 740 Cmp #&0F 750 Beq VectorClaim 760 Cmp #&0D 770 Bne NotRomInit: Jmp RomFSInitialiseRead 780.NotRomInit 790 Cmp #&0E 800 Bne Exit:Jmp RdByte 810.Exit 820 OPT FNPop 830 Rts 840 850.ExitYA0 860 Tya:OPT FNStStack(Y) 870.ExitA0 880 Lda #0:OPT FNStStack(A) 890 Jmp Exit 900 910.VectorClaim 920 Lda #0:Tay 930 Jsr OsArgs 940 Cmp #3 950 Bne Exit 960 OPT FNSetExpandedVector(OsFileV, OldFileV, RFSFile) 970 OPT FNSetExpandedVector(OsFindV, OldFindV, RFSFind) 980 OPT FNSetExpandedVector(OsBputV, OldBputV, RFSBput) 990 Jmp Exit 1000 1010.RomFSInitialiseRead 1020 Tya:Eor #&0F 1030 Cmp &F4 1040 Bcc NotUs 1050 OPT FNLd`XY(DataStart):OPT FNStXY(&F6) 1060 Lda &F4:Eor #&0F:Sta &F5 1070 Jmp ExitA0 1080 1090.NotUs 1100 Jmp Exit 1110 1120.RdByte 1130 Lda &F5 1140 Eor #&0F 1150 Cmp &F4 1160 Bne NotUs 1170 Ldy #0 1180 Lda (&F6),Y 1190 Tay 1200 OPT FNIncW(&F6) 1210 Jmp ExitYA0 1220 1230.RFSFile 1240 OPT FNPush 1250 OPT FNLdStack(A) 1260 Cmp #0:Beq SaveFile 1270 OPT FNPop 1280 Jmp (OldFileV) 1290 1300.SaveFile 1310 Lda FileOpen:Beq SaveOk 1320 OPT FNLdXY(NewBlock) 1330 Inx:Bne ninc12:Iny:.ninc12 1340 OPT FNBrkParam(CantFileOpen,"Can't save: file '","' open") 1350.SaveOk 1360 OPT FNLdXY(NewBlock):OPT FNStXY(zNewBlock) 1370 OPT FNLdStack(X):Sta zParameter 1380 OPT FNLdStack(Y):Sta zParameter+1 1390 Ldy #0:OPT FNLdXYzp(zParameter):OPT FNStXY(zFileName) 1400 Jsr CopyFileName 1410 Ldy #2:Sty ParameterIndex 1420 Ldx #8 1430.CopyParams 1440 Ldy ParameterIndex:Lda (zParameter),Y:Inc ParameterIndex 1450 Ldy NewBlockIndex:Sta (zNewBlock),Y:Inc NewBlockIndex 1460 Dex:Bne CopyParams 1470 Ldx #2+2+1+4+2:Jsr ZapHeader \ Also sets up zWritePointer -> Data area 1480 Ldy #&0A:OPT FNLdXYzp(zParameter):OPT FNStXY(zTemp) 1490 Ldy #&0E:OPT FNLdXYzp(zParameter):OPT FNStXY(EndAddress) 1500 Ldy #0:Sty BytesCopied:Sty BytesCopied+1:Beq TestZeroLength 1510.CopyDataLoop 1520 Lda (zTemp),Y:Sta (zWritePointer),Y 1530 OPT FNIncW(BytesCopied) 1540 OPT FNIncW(zWritePointer) 1550 OPT FNIncW(zTemp) 1560.TestZeroLength 1570 Lda zTemp:Cmp EndAddress:Bne CopyDataLoop 1580 Lda zTemp+1:Cmp EndAddress+1:Bne CopyDataLoop 1590.CloseFile 1600 OPT FNLdXY(NewBlock):OPT FNStXY(zTemp) 1610 Ldy #0:Lda #ASC"*":Sta (zTemp),Y \ Make header real, not end of ROM 1620 OPT FNIncW(zTemp) \ Point at first byte of header - after the '*' 1630 Lda FileNameNull:Clc:Adc #4+4+2:Tay 1640 Lda BytesCopied:Sta (zTemp),Y:Iny 1650 Lda BytesCopied+1:Sta (zTemp),Y:Iny 1660 Lda #&80 1670.StoreFlag 1680 Sta (zTemp),Y:Iny \ Flag byte 1690\ Calculate end of ROM marker - 2 bytes after last data byte 1700 Lda zWritePointer:Clc:Adc #2:Sta (zTemp),Y:Iny:Sta NewBlock 1710 Lda zWritePointer+1:Adc #0:Sta (zTemp),Y:Sta NewBlock+1 1720\ Calculate length of header 1730 Lda FileNameNull:Clc:Adc #4+4+2+2+1+4:Sta Temp:Lda #0:Sta Temp+1 1740 Jsr Crc 1750 OPT FNLdXY(BytesCopied):OPT FNStXY(Temp) 1760 Jsr Crc 1770 Ldy #0:Lda #ASC"+":Sta (zTemp),Y 1780 Sty FileOpen 1790 Jmp Exit 1800 1810.CopyFileName 1820 Ldy #0 1830.CopyFileNameLoop 1840 Lda (zFileName),Y:Cmp #32+1:Bcc FileNameDone 1850 Iny:Sta (zNewBlock),Y:Bne CopyFileNameLoop 1860 \ BRK 1870.FileNameDone Iny:Lda #0:Sta (zNewBlock),Y:Sty FileNameNull 1880 Iny:Sty NewBlockIndex 1890 Rts 1900 1910.ZapHeader 1920 Lda #0:Ldy NewBlockIndex 1930.CopyZerosLoop 1940 Sta (zNewBlock),Y:Iny 1950 Dex:Bne CopyZerosLoop 1960 Tya 1970 OPT FNLdXY(zNewBlock):OPT FNStXY(zWritePointer) 1980 Clc:Adc zWritePointer:Sta zWritePointer 1990 Bcc nInc:Inc zWritePointer+1:.nInc 2000 Rts 2010 2020 2030.RFSFind 2040 OPT FNPush 2050 OPT FNLdStack(A):Bne NotClose 2060 OPT FNLdStack(Y) \ Get Handle 2070 Cmp #Handle:Beq CloseWrite 2080 OPT FNPop:Jsr OldOsFindLabel:OPT FNPush 2090.CloseWrite 2100 Lda FileOpen:Beq NoFileOpen 2110 OPT FNLdStack(Y) \ Get Handle 2120 Cmp #Handle:Beq MustClose 2130 Cmp #0:Beq MustClose 2140.NoFileOpen 2150 Jmp Exit 2160 2170.MustClose 2180 OPT FNLdXY(WritePointer):OPT FNStXY(zWritePointer) 2190 Jmp CloseFile 2200 2210.OldOsFindLabel 2220 Jmp (OldFindV) 2230 2240.NotClose 2250 Cmp #&80:Beq FindOutput 2260 OPT FNPop 2270 Jmp (OldFindV) 2280.FindOutput 2290 Lda FileOpen:Beq FindOutputOk 2300 OPT FNLdXY(NewBlock) 2310 Inx:Bne ninc11:Iny:.ninc11 2320 OPT FNBrkParam(TooManyOpen,"Open: file '", "' already open") 2330.FindOutputOk 2340 OPT FNLdXY(NewBlock):OPT FNStXY(zNewBlock) 2350 OPT FNLdStack(X):Sta zFileName 2360 OPT FNLdStack(Y):Sta zFileName+1 2370 Jsr CopyFileName 2380 Ldx #4+4+2+2+1+4+2:Jsr ZapHeader \ Also sets up WritePointer -> Data area 2390 OPT FNLdXY(zWritePointer):OPT FNStXY(WritePointer) 2400 Lda #0:Sta BytesCopied:Sta BytesCopied+1 2410 Lda #Handle:OPT FNStStack(A):Sta FileOpen 2420 Jmp Exit 2421 2422.WrongChannel 2430 OPT FNPop 2440 Jmp (OldBputV) 2450 2460.RFSBput 2470 OPT FNPush 2480 Lda FileOpen:Beq WrongChannel 2490 OPT FNLdStack(Y):Cmp #Handle:Bne WrongChannel 2500 OPT FNLdXY(WritePointer):OPT FNStXY(zWritePointer) 2510 Cpy RomEnd:Bne NotEof 2520 OPT FNLdXY(NewBlock) \ get file name 2530 Inx:Bne ninc13:Iny:.ninc13 2540 Txa:Pha:Tya:Pha 2550 OPT FNAdd`W(WritePointer, (-3) AND &FFFF) 2551 OPT FNAdd`W(BytesCopied, (-3) AND &FFFF) 2560 Ldy #Handle:Lda #0:Jsr OsFind \ Close the file 2570 Pla:Tay:Pla:Tax 2571 OPT FNBrkParam(DataLost,"Rom full: '", "' closed") 2580.NotEof 2590 Ldy #0 2600 OPT FNLdStack(A):Sta (zWritePointer),Y 2610 OPT FNIncW(WritePointer) 2620 OPT FNIncW(BytesCopied) 2630 Jmp Exit 2670 2680.Write 2690 Php:Sta OldA 2700 Pla:Sta OldCC 2710 Sty OldY 2720 Stx OldX 2730 Pla:Sta zp0 2740 Pla:Sta zp1 2750 Ldy #1 2760 Php 2770 Dey 2780.s1 2790 OPT FNIncW(zp0) 2800 Plp:Beq exitstr 2810 Lda (zp0),Y 2820 Php 2830 Jsr OsAscii 2840 Jmp s1 2850.exitstr 2860 Ldx OldX 2870 Ldy OldY 2880 Lda OldCC:Pha 2890 Lda OldA 2900 Plp 2910 Jmp (zp0) 2920.OldCC NOP 2930.OldA NOP 2940.OldX NOP 2950.OldY NOP 2960 2970.InitBrk 2980 Sta &101 2990 Lda #2:Sta &100 \ Next byte offset 3000 Rts 3010 3020.CopyStr 3030 Stx OldX 3040 Sty OldY 3050 Pla:Sta zp0 3060 Pla:Sta zp1 3070 Ldy #1 3080 Php 3090 Dey 3100.b1 3110 OPT FNIncW(zp0) 3120 Plp:Beq ExitBrk1 3130 Lda (zp0),Y 3140 Php 3150 Ldx &100:Sta &100,X:Inc &100 3160 Jmp b1 3170.ExitBrk1 3180 Dec &100 3190 Ldx OldX 3200 Ldy OldY 3210 Jmp (zp0) 3220 3230.CopyXY 3240 OPT FNStXY(zp0) 3250 Ldx &100 3260 Ldy #0 3270.cpxy1 3280 Lda (zp0),Y:Sta &100,X 3290 Cmp #32:Bcc cpxyExit 3300 Inx:Iny 3310 Bne cpxy1 3320.cpxyExit 3330 Stx &100 3340 Rts 3350 3360.DoBrk 3370 Lda #0:Sta &100 3380 Jmp &100 3390 3400.WrHexCh 3410 Php:Pha 3420 And #&0F 3430 Clc:Adc #ASC"0" 3440 Cmp #ASC"9"+1 3450 Bcc was0_9 3460 Clc:Adc #(ASC"A"-ASC"0"-10) 3470.was0_9 3480 Jsr OsWrch 3490 Pla:Plp 3500 Rts 3510 3520.WrHexSP 3530 Jsr WrHex:Php:Pha:Lda #ASC" ":Jsr OsAscii:Pla:Plp:Rts 3540 3550.WrHex 3560 Php:Pha 3570 Ror A:Ror A:Ror A:Ror A 3580 Jsr WrHexCh 3590 Pla 3600 Jsr WrHexCh 3610 Plp 3620 Rts 3630 3640.WrHexX 3650 Php:Pha:Txa:Jsr WrHex:Pla:Plp:Rts 3660 3670.WrHexY 3680 Php:Pha:Tya:Jsr WrHex:Pla:Plp:Rts 3690 3700.Crc \ Calculate CRC of data pointer at by zTemp,zTemp+1 3710 \ and length in Temp,Temp+1 3720 Lda #0 3730 Sta Hi:Sta Lo 3740 Tay 3750 Beq ZeroCrcTest 3760.nbyt 3770 Lda Hi 3780 Eor (zTemp),Y 3790 Sta Hi 3800 Ldx #8 3810.crcLoop 3820 Lda Hi 3830 Rol A 3840 Bcc b7z 3850 Lda Hi 3860 Eor #8 3870 Sta Hi 3880 Lda Lo 3890 Eor #&10 3900 Sta Lo 3910.b7z 3920 Rol Lo 3930 Rol Hi 3940 Dex 3950 Bne crcLoop 3960 OPT FNIncW(zTemp) 3970 OPT FNDecW(Temp) 3980.ZeroCrcTest 3990 Lda Temp:Ora Temp+1:Bne nbyt 4000 Lda Hi:Sta (zTemp),Y:Iny 4010 Lda Lo:Sta (zTemp),Y 4020 OPT FNAdd`W(zTemp,2) 4030 Rts 4040 4050.DataStart 4060 EQUB ASC"+" 4070 ] 4080 NEXT Pass 4090PRINT"Size = &";~O%-Code 4100free=(Code+CodeSize)-O% 4110IF free<0 THEN PRINT "Program ";-free;" bytes too long":STOP 4120PRINT "Bytes free = &";~free 4130ENDPROC 4140. 4150 DEF FNSetExpandedVector(Vector, OldV, Routine) 4160 LOCAL VectorNumber,VectorAddress 4170 VectorNumber=(Vector-&200)/2 4180 VectorAddress=&D9F+(3*VectorNumber) 4190 [ OPT Pass 4200 Lda Vector:Sta OldV 4210 Lda Vector+1:Sta OldV+1 4220 Lda #(&FF00+(3*VectorNumber)) MOD 256 4230 Sta Vector+0 4240 Lda #(&FF00+(3*VectorNumber)) DIV 256 4250 Sta Vector+1 4260 Lda #Routine MOD 256 4270 Sta VectorAddress+0 4280 Lda #Routine DIV 256 4290 Sta VectorAddress+1 4300 Lda &F4 4310 Sta VectorAddress+2 4320 ] 4330 =Pass 4340. 4350 DEF FNIncW(Loc) 4360 LOCAL Size 4370 IF Loc>254 THEN Size=2 ELSE Size=1 4380[ OPT Pass 4390 Inc Loc:Bne P%+2+1+Size:Inc Loc+1 4400] 4410=Pass 4420. 4430 DEF FNDecW(Loc) 4440 LOCAL Size 4450 IF Loc>254 THEN Size=2 ELSE Size=1 4460[ OPT Pass 4470 Lda Loc:Bne P%+2+1+Size:Dec Loc+1:Dec Loc 4480] 4490=Pass 4500. 4510 DEF FNPush 4520[ OPT Pass 4530 Php:Pha:Txa:Pha:Tya:Pha 4540] 4550=Pass 4560. 4570 DEF FNPop 4580[ OPT Pass 4590 Pla:Tay:Pla:Tax:Pla:Plp 4600] 4610=Pass 4620. 4630 DEF FNLdStack(reg) 4640[ OPT Pass 4650 Tsx:Lda reg,X 4660] 4670=Pass 4680. 4690 DEF FNStStack(reg) 4700[ OPT Pass 4710 Tsx:Sta reg,X 4720] 4730=Pass 4740. 4750 DEF FNLdXY(Loc) 4760[ OPT Pass 4770 Ldx Loc:Ldy Loc+1 4780] 4790=Pass 4800. 4810 DEF FNStXY(Loc) 4820[ OPT Pass 4830 Stx Loc:Sty Loc+1 4840] 4850=Pass 4860. 4870 DEF FNLd`XY(Addr) 4880[ OPT Pass 4890 Ldx #Addr MOD 256:Ldy #Addr DIV 256 4900] 4910=Pass 4920. 4930 DEF FNLdXYzp(zLoc) 4940[ OPT Pass 4950 Lda (zLoc),Y:Tax:Iny 4960 Lda (zLoc),Y:Tay 4970] 4980=Pass 4990. 5000 DEF FNAdd`W(Loc,n) 5010[ OPT Pass 5020 Lda Loc:Clc:Adc #n MOD 256:Sta Loc 5030 Lda Loc+1:Adc #n DIV 256:Sta Loc+1 5040] 5050=Pass 5060. 5070 DEF FNDebug(s$) 5080 IF NOT Debug THEN =Pass 5090[ OPT Pass 5100 Jsr Write:EQUS s$:EQUB 0 5110] 5120=Pass 5130. 5140 DEF FNBrk(BrkNum,str$) 5150[ OPT Pass 5160 Lda #BrkNum 5170 Jsr InitBrk 5180 Jsr CopyStr 5190 EQUS str$ 5200 EQUB 0 5210 Jmp DoBrk 5220] 5230=Pass 5240. 5250 DEF FNBrkParam(BrkNum,Left$,Right$) 5260[ OPT Pass 5270 Lda #BrkNum 5280 Jsr InitBrk 5290 Jsr CopyStr 5300 EQUS Left$ 5310 EQUB 0 5320 Jsr CopyXY 5330 Jsr CopyStr 5340 EQUS Right$ 5350 EQUB 0 5360 Jmp DoBrk 5370] 5380=Pass 5390. 5400DEFPROCloadrom 5410DIM Loader &200 5420FOR Pass=0 TO 2 STEP 2 5430P%=Loader 5440[OPT Pass 5450PHP:SEI 5460Lda &F4:PHA 5470Lda #12:Sta &F4:Sta &FE30 5480Ldx #0 5490.Loop 5500 Lda Code,X 5510 Sta &8000,X 5520 Lda Code+&100,X 5530 Sta &8100,X 5540 Lda Code+&200,X 5550 Sta &8200,X 5560 Lda Code+&300,X 5570 Sta &8300,X 5580 Lda Code+&400,X 5590 Sta &8400,X 5600 Lda Code+&500,X 5610 Sta &8500,X 5620 Inx 5630 Bne Loop 5640PLA:Sta &F4:Sta &FE30 5650PLP 5660Rts 5670] 5680NEXT Pass 5690CALL Loader 5700ENDPROC