10 REM ----------------------------------------------
   20 REM RESCUE : disk recovery
   30 REM ----------------------------------------------
   40 MODE 7
   50 DIM cat 511   :REM catalogue
   60 DIM param 13  :REM OSWORD parameter block
   70 DIM fnam$(32) :REM filenames
   80 DIM load%(32) :REM load addresses
   90 DIM exec%(32) :REM exec addresses
  100 DIM strt%(32) :REM start sectors
  110 DIM leng%(32) :REM lengths
  120 DIM fini%(32) :REM end sectors
  130 DIM colr$(32) :REM colours
  140 
  150 PROCinit      :REM which drive, etc.
  160 PROCreadcat   :REM read catalogue
  170 PROCextract   :REM extract from catalogue
  180 PROCeof       :REM check eof
  190 PROCnewfiles  :REM revise files
  200 PROCprintcat  :REM print catalogue
  210 PROCnewcat    :REM make new catalogue
  220 PROCwritecat  :REM write catalogue
  230 END
  240 
  250 DEFPROCeof
  260 IF fini%(1)=snum%-1:ENDPROC
  270 PROCinsert(1)
  280 fini%(1)=snum%-1
  290 leng%(1)=fini%(1)-strt%(1)+1
  300 leng%(1)=256*leng%(1)
  310 ENDPROC
  320 
  330 DEFPROCextract
  340 REM extract fields from the catalogue
  350 REM get number of files
  360 fnum%=cat?&105 DIV 8
  370 REM get number of sectors
  380 snum%=cat?&107 + 256*(cat?&106 AND 3)
  390 REM if no files, leave
  400 IF fnum%=0:ENDPROC
  410 REM get file details
  420 FOR I%=1 TO fnum%
  430     fnst% = cat+8*I%     :REM start of filename
  440     adst% = fnst%+&100   :REM start of addresses
  450     REM get file name
  460     FOR J%=0 TO 7
  470         fnam$(I%)=fnam$(I%)+CHR$(fnst%?J%)
  480     NEXT
  490     REM get load address
  500     load%(I%)=adst%!0 AND &FFFF
  510     load%(I%)=load%(I%) + &10000*((adst%?6 AND &C) DIV 4)
  520     REM get exec address
  530     exec%(I%)=adst%!2 AND &FFFF
  540     exec%(I%)=exec%(I%) + &10000*((adst%?6 AND &C0) DIV 64)
  550     REM get length
  560     leng%(I%)=adst%!4 AND &FFFF
  570     leng%(I%)=leng%(I%) + &10000*((adst%?6 AND &30) DIV 16)
  580     REM get start sector
  590     strt%(I%)=adst%?7
  600     strt%(I%)=strt%(I%) + &100*(adst%?6 AND &3)
  610     REM calculate end sector
  620     fini%(I%)=strt%(I%)+(leng%(I%)-1) DIV 256
  630 NEXT
  640 ENDPROC
  650 
  660 DEFPROChead
  670 REM screen title
  680 CLS
  690 PRINT TAB(15,2);CHR$141;CHR$131;"RESCUE"
  700 PRINT TAB(15,3);CHR$141;CHR$131;"RESCUE"
  710 ENDPROC
  720 
  730 DEFPROCinit
  740 REM initialise num of dummy files
  750 dumm%=0
  760 REM initials DIMs
  770 FOR I%=0 TO 31
  780     colr$(I%)=CHR$130 :REM green
  790     fnam$(I%)=""      :REM initial filename
  800 NEXT
  810 
  820 REM which drive
  830 PROChead
  840 REPEAT
  850     PRINT TAB(4,8);STRING$(35," ")
  860     PRINT TAB(4,8);CHR$134;"which drive (0-3) ";
  870     INPUT "> " drive%
  880 UNTIL drive%>-1 AND drive%<4
  890 OSCLI "DRIVE "+STR$drive%
  900 
  910 REM get user ready
  920 PROChead
  930 PRINT TAB(4,8);CHR$134;"insert disk in drive ";drive%
  940 PRINT TAB(4,9);CHR$134;"press SPACE when ready to go";
  950 REPEAT UNTIL INKEY(100)=32
  960 ENDPROC
  970 
  980 DEFPROCinsert(J%)
  990 PROCmakeroom(J%+1)
 1000 dumm%=dumm%+1
 1010 dumm$=RIGHT$("0"+STR$dumm%,2)
 1020 fnam$(J%)="DUMMY"+dumm$+"$"
 1030 fini%(J%)=strt%(J%-1)-1
 1040 strt%(J%)=fini%(J%+1)+1
 1050 leng%(J%)=fini%(J%)-strt%(J%)+1
 1060 leng%(J%)=leng%(J%)*256
 1070 colr$(J%)=CHR$129
 1080 load%(J%)=&31900
 1090 exec%(J%)=0
 1100 ENDPROC
 1110 
 1120 DEFPROCnewcat
 1130 cat?&105=fnum%*8    :REM number of files * 8
 1140 FOR I%=1 TO fnum%
 1150     fnst%=cat + 8*I%  :REM start of filename
 1160     adst%=fnst%+&100  :REM start of addresses
 1170     FOR J%=1 TO LEN fnam$(I%)
 1180         fnst%?(J%-1)=ASCMID$(fnam$(I%),J%,1)
 1190     NEXT
 1200     adst%!0 = load%(I%)
 1210     adst%!2 = exec%(I%)
 1220     adst%!4 = leng%(I%)
 1230     adst%?7 = strt%(I%)
 1240     lo%     = load%(I%) DIV &10000
 1250     ex%     = exec%(I%) DIV &10000
 1260     le%     = leng%(I%) DIV &10000
 1270     st%     = strt%(I%) DIV &100
 1280     adst%?6 = 64*ex% + 16*le% + 4*lo% + st%
 1290 NEXT
 1300 ENDPROC
 1310 
 1320 DEFPROCnewfiles
 1330 IF fnum%=0:ENDPROC
 1340 I%=1
 1350 REPEAT
 1360     I%=I%+1
 1370     gap%=strt%(I%-1) - fini%(I%) - 1
 1380     IF gap%<>0:PROCinsert(I%)
 1390 UNTIL I%=fnum% OR I%>31
 1400 ENDPROC
 1410 
 1420 DEFPROCmakeroom(J%)
 1430 REM shift filenames up to make room
 1440 fnum%=fnum%+1
 1450 FOR K%=fnum% TO J% STEP -1
 1460     fnam$(K%)=fnam$(K%-1)
 1470     load%(K%)=load%(K%-1)
 1480     exec%(K%)=exec%(K%-1)
 1490     leng%(K%)=leng%(K%-1)
 1500     strt%(K%)=strt%(K%-1)
 1510     fini%(K%)=fini%(K%-1)
 1520     colr$(K%)=colr$(K%-1)
 1530 NEXT
 1540 ENDPROC
 1550 
 1560 DEFPROCosword
 1570 A%=&7F
 1580 X%=param
 1590 Y%=X% DIV 256
 1600 CALL &FFF1
 1610 ENDPROC
 1620 
 1630 DEFPROCprintcat
 1640 CLS
 1650 PROChead
 1660 PRINT
 1670 IF fnum%=0:ENDPROC
 1680 FOR I%=1 TO fnum%
 1690     PRINT colr$(I%);
 1700     dir$=RIGHT$(fnam$(I%),1)
 1710     dir%=ASC(dir$) AND &7F
 1720     lok%=ASC(dir$) AND &80
 1730     dir$=CHR$(dir%)
 1740     lok$="L"
 1750     IF lok%=0:lok$=" "
 1760     nam$=LEFT$(fnam$(I%),7)
 1770     PRINT dir$;".";
 1780     PRINT nam$;" ";
 1790     PRINT lok$;" ";
 1800     @%=5
 1810     PRINT ~load%(I%);" ";
 1820     PRINT ~exec%(I%);" ";
 1830     @%=3
 1840     PRINT ~strt%(I%);" - ";
 1850     PRINT ~fini%(I%);" ";
 1860     @%=5
 1870     PRINT ~leng%(I%);CHR$8;CHR$8
 1880 NEXT
 1890 ENDPROC
 1900 
 1910 DEFPROCreadcat
 1920 REM read two catalogue sectors into cat
 1930 param?0 = drive%   :REM drive number
 1940 param!1 = cat      :REM buffer address
 1950 param?5 = 3        :REM num of parameters
 1960 param?6 = &53      :REM read command
 1970 param?7 = 0        :REM track number
 1980 param?8 = 0        :REM sector number
 1990 param?9 = &22      :REM 2 sectors x 256 bytes
 2000 PROCosword         :REM read the disk sectors
 2010 IF param?10=0:ENDPROC
 2020 PRINT TAB(4,10);CHR$129;
 2030 PRINT "error reading catalogue = &";~param?10:END
 2040 ENDPROC
 2050 
 2060 DEFPROCwritecat
 2070 REM update two catalogue sectors
 2080 param?0 = drive%   :REM drive number
 2090 param!1 = cat      :REM buffer address
 2100 param?5 = 3        :REM num of parameters
 2110 param?6 = &4B      :REM write command
 2120 param?7 = 0        :REM track number
 2130 param?8 = 0        :REM sector number
 2140 param?9 = &22      :REM 2 sectors x 256 bytes
 2150 PROCosword         :REM write the disk sectors
 2160 IF param?10=0:ENDPROC
 2170 PRINT 'CHR$129;"error writing catalogue = &";~param?10:END
 2180 ENDPROC