1000 REM ReHead 2.8 TNFS by Simon N Goodwin 2020 1010 CLEAR 32499 1020 LET dpok=1420 1030 LET plus3header=32600: REM Liebensraum 1040 LET header=32704: REM TAP 24 byte prefix here 1050 LET headLen=128: REM +3DOS prefix length 1060 LET checker=32500: REM byte XOR checksum loop 1070 RESTORE : FOR i=checker TO checker+18 1080 READ d: POKE i,d: NEXT i 1090 DATA 1,0,0,33,0,0,17,0,0,122,179,200,126,169,79,35,27,24,246 1100 PRINT "ZX BASIC file header converter" 1110 INPUT "File ";f$ 1120 POKE header,0 1130 %aload f$ CODE header 1150 PRINT 'f$;" loaded.": LET form=0: REM 1=TAP, 3=+3DOS 1170 LET p$="": FOR i=header TO header+7 1180 LET p$=p$+ CHR$ PEEK i: NEXT i 1190 IF p$="PLUS3DOS" THEN PRINT p$;" header found": GO SUB 2320: LET form=3 1200 IF PEEK header=19 AND PEEK (header+1)=0 AND ( PEEK (header+2)=0 OR PEEK (header+2)=255) THEN PRINT "TAP header found": GO SUB 1630: LET form=1: GO SUB 1320 1210 IF form=0 THEN PRINT "Unknown file header.": STOP 1220 PRINT "Convert to ";p$ AND form=1;".TAP" AND form=3;" "; 1230 INPUT "Y/N? ";q$: PRINT 1240 IF q$="" THEN GO TO 1230 1250 LET q$=q$(1): IF q$="N" OR q$="n" THEN STOP 1260 IF q$(1)<>"Y" AND q$<>"y" THEN GO TO 1230 1270 IF form=1 THEN GO SUB 2010: REM SAVE in Plus3 format 1280 IF form=3 THEN GO SUB 2080: REM SAVE in TAP format 1290 STOP 1300 1310 REM Display type, length, start (var name, vars size) 1320 PRINT 'dlen;"-byte ";"ZX type ";type;" "; 1330 PRINT "BASICARRAYARRAYCODE "(1+type*5 TO 5+type*5);" file" 1340 IF type=3 OR (type=0 AND start<32768) THEN PRINT "Starts at ";start 1350 IF type=1 OR type=2 THEN PRINT "Array name "; CHR$ name; 1360 IF type=2 THEN PRINT "$" 1370 IF type=1 THEN PRINT 1380 IF type=0 THEN PRINT vars;" BASIC bytes, ";dlen-vars;" variables" 1390 RETURN 1400 : 1410 REM dpok, 16-bit POKE i,t 1420 POKE i+1, INT (t/256): POKE i,t- PEEK (i+1)*256: RETURN 1430 REM 16-bit unsigned PEEK, like % DPEEK on Next 1440 DEF FN d(p)= PEEK p+ 256* PEEK (p+1) 1450 : 1460 REM Validate .TAP data at header 1470 LET i=checker+4: LET t=header+2: GO SUB dpok: REM Start address 1480 LET i=checker+7: LET t=18: GO SUB dpok: REM Number of bytes to XOR 1490 IF USR checker<> PEEK (header+20) THEN PRINT "Header block check failed": STOP 1500 LET p$="": FOR i=13 TO 4 STEP -1: LET q$= CHR$ PEEK (i+header) 1510 IF LEN p$ OR q$<>" " THEN LET p$=q$+p$ 1520 NEXT i: REM Strip trailing spaces 1530 IF FN d(header+21)<>dlen+2 THEN PRINT "Data block length mismatch": STOP 1540 PRINT "TAP filename ";p$ 1550 IF PEEK (header+23)<>255 THEN PRINT "Data block marker missing": STOP 1560 LET i=checker+7: LET t=dlen+1: GO SUB dpok: REM include flag byte in checksum 1570 LET i=checker+4: LET t=header+23: GO SUB dpok 1580 IF USR checker<> PEEK (header+24+dlen) THEN PRINT "Data block check failed": STOP 1590 PRINT "TAP file verified" 1600 RETURN 1610 : 1620 REM Parse and verify TAP header and following data block 1630 LET type= PEEK (header+3) 1640 IF type>3 THEN PRINT "Not a ZX block file!": STOP 1650 PRINT "TAP file type is "; 1660 PRINT "BASICARRAYARRAYCODE "(1+type*5 TO 5+type*5) 1670 LET length= FN d(header) 1680 LET dlen= FN d(header+14) 1690 LET start= FN d(header+16) 1700 LET vars= FN d(header+18) 1710 LET p= PEEK (header+17): GO SUB 1750 1720 GO TO 1470: REM TapCheck 1730 : 1740 REM Convert code in p to ASCII array name 1750 IF p>127 THEN LET p=p-128 1760 IF p>63 THEN LET p=p-64 1770 IF p>31 THEN LET p=p-32 1780 LET name=p+64 1790 RETURN 1800 : 1810 REM Populate +3 header with ZX tape header 1820 LET p$="PLUS3DOS"+ CHR$ 26+ CHR$ 1+ CHR$ 0+ CHR$ 0+ CHR$ 0 1830 FOR i=1 TO LEN p$ 1840 POKE i+plus3header-1, CODE p$(i) 1850 NEXT i 1860 REM All PLUS3DOS files seem to be issue 1 version 0 1870 LET i=plus3header+11: LET t=headLen+dlen: GO SUB dpok 1880 POKE plus3header+15,type 1890 LET i=plus3header+16: LET t=dlen: GO SUB dpok 1900 LET i=plus3header+18: LET t=start: GO SUB dpok 1910 LET i=plus3header+20: LET t=vars: GO SUB dpok 1920 FOR i=plus3header+22 TO plus3header+126: POKE i,0: NEXT i 1930 LET s=0: REM Additive checksum of non-zero header bytes 1940 FOR i=plus3header TO plus3header+21 1950 LET s=s+ PEEK i: IF s>255 THEN LET s=s-256 1960 NEXT i 1970 POKE plus3header+headLen-1,s 1980 RETURN 1990 : 2000 REM Replace TAP header with +3 one and write out 2010 LET e$=p$+"."+"BASNUMSTRBIN"(1+type*3 TO 3+type*3) 2020 GO SUB 1820: REM SetHeader 2030 %asave e$ CODE plus3header,dlen+headlen 2035 REM slow test LET i=plus3header: LET t=dlen+headLen: GO SUB 3000 2040 PRINT e$;" written out" 2050 RETURN 2060 : 2070 REM Overwrites +3 header with a TAP one, adding checksums 2080 LET tap=header+headLen-24: REM TAP over end of PLUS3DOS header 2090 POKE tap,19: POKE tap+1,0: POKE tap+2,0 2100 POKE tap+3,type: REM 19 byte ZX header follows 2110 FOR i=2 TO LEN f$: IF f$(i)="." THEN LET f$=f$( TO i-1): LET i=9999 2120 NEXT i: REM Discard anything from a full stop onwards 2130 DIM j$(10): LET j$=f$: REM Pad or truncate to 10 bytes 2140 FOR i=1 TO 10: POKE tap+3+i, CODE j$(i): NEXT i 2150 LET i=tap+14: LET t=dlen: GO SUB dpok 2160 LET i=tap+16: LET t=start: GO SUB dpok 2170 LET i=tap+18: LET t=vars: GO SUB dpok 2180 LET i=checker+4: LET t=tap+2: GO SUB dpok 2190 LET i=checker+7: LET t=18: GO SUB dpok 2200 POKE tap+20, USR checker: REM Header checksum 2210 LET i=tap+21: LET t=dlen+2: GO SUB dpok 2220 POKE tap+23,255: REM Data block start marker 2230 LET i=checker+4: LET t=tap+23: GO SUB dpok 2240 LET i=checker+7: LET t=dlen+1: GO SUB dpok 2250 POKE tap+24+dlen, USR checker 2255 %asave f$+".TAP" CODE tap,dlen+25 2260 REM SLOW method for +3e/next only LET e$=f$+".tap": LET i=tap: LET t=dlen+25: GO SUB 3000 2270 PRINT f$+".TAP written out" 2280 RETURN 2290 : 2300 REM Read +3 header, NB file may exceed 64K 2310 REM Sets length, type, dlen, start, vars, name 2320 LET length= FN d(header+11) 2330 LET length=length+ FN d(header+13)*2^16 2340 PRINT "File length = ";length;" bytes" 2350 LET type= PEEK (header+15) 2360 PRINT "ZX type = "; type;" "; 2370 IF type>3 THEN GO TO 2400 2380 PRINT "BASICARRAYARRAYCODE "(1+type*5 TO 5+type*5) 2390 LET dlen = FN d(header+16) 2400 PRINT "Data length = ";dlen;" bytes" 2410 IF type>0 THEN GO TO 2470 2420 LET start= FN d(header+18) 2430 LET vars= FN d(header+20) 2440 PRINT vars;" BASIC bytes, ";dlen-vars;" variables" 2450 IF start<32768 THEN PRINT "Start line = ";start 2460 RETURN 2470 LET vars= FN d(header+20) 2480 LET start= FN d(header+18) 2490 IF type=3 THEN GO TO 2550 2500 LET p= PEEK (header+19) 2510 GO SUB 1750 2520 PRINT "Array name = "; CHR$ name; 2530 PRINT "$" AND type=2 2540 RETURN 2550 PRINT "Default load address = ";start;" P32K= ";vars 2560 RETURN 2570 : 2660 STOP 2680 %save"Rehead-tnfs.bas" 2690 STOP 2980 : 2990 REM Placeholder +3e raw SAVE e$ CODE i,t 3000 CLOSE # 5: OPEN # 5,"O>"+e$ 3010 FOR i=i TO i+t-1: PRINT #5; CHR$ PEEK i;: NEXT i 3020 CLOSE # 5: RETURN