10 REM >DumpFlex
   20 :
   30 debug%=0
   40 A%=0:X%=1:os%=((USR&FFF4)AND&FF00)DIV256
   50 DIM ctrl% 31:X%=ctrl%:Y%=X%DIV256
   60 DIM d_path$(3):d_drv%=-1:d_chn%=0
   70 DIM mem% &1FF,dmp% 15
   80 :
   90 PRINT "Flex disk image examiner"
  100 INPUT "Disk image file: "in$:IF in$="":in$="bbcflex7.dsd"
  110 d_path$(0)=in$:drv%=0
  120 PROCfdc_info(drv%):PROCcat(1)
  130 REPEAT
  140   PRINT;drv%;"> ";:REPEATK$=CHR$(GETAND&DF):UNTILINSTR("D",K$)
  150   IFK$="D":INPUT "Dump file: "fn$:PROCdump(fn$)
  160 UNTIL0
  170 END
  180 
  190 DEFPROCcat(flg%)
  200 PRINT"Filename.ext WDRC Size Tk:Sc    Date";SPC6;
  210 PRINT"Filename.ext WDRC Size Tk:Sc    Date"
  220 dir%=&0500:n%=0
  230 REPEAT
  240   sec%=dir% DIV 256:trk%=dir% AND 255
  250   A%=FNfdc_disk(&53,mem%,drv%,trk%,0,sec%,1)
  260   ptr%=16:REPEAT:IF mem%?ptr%:PROCprentry
  270   ptr%=ptr%+24:UNTILptr%>255
  280   dir%=!mem% AND &FFFF
  290 UNTIL dir%=0:IF n%:PRINT
  300 ENDPROC
  310 DEFPROCprentry
  320 PROCprname:n%=n%+1
  330 IF (flg%AND1)=1:PRINTFNpraccess(mem%?(ptr%+11));" ";FNh0(mem%?(ptr%+17),2)FNh0(mem%?(ptr%+18),2);" ";FNh0(mem%?(ptr%+13),2)":";FNh0(mem%?(ptr%+14),2);" ";FNprdate(mem%!(ptr%+21));"   ";
  340 IF (flg%AND1)=1:IFn%>1:PRINT:n%=0
  350 IF (flg%AND1)=0:IFn%>4:PRINT:n%=0
  360 ENDPROC
  370 
  380 REM  0 8 byte --- File name
  390 REM  8 3 byte --- File extension
  400 REM 11 1 byte --- Attributes WDRC---- if set, protected
  410 REM 12 1 byte --- Not used
  420 REM 13 1 byte --- Start track
  430 REM 14 1 byte --- Start sector
  440 REM 15 1 byte --- End track
  450 REM 16 1 byte --- End sector
  460 REM 17 2 byte --- Total number of sectors (high, low)
  470 REM 19 1 byte --- Random file flag
  480 REM 20 1 byte --- Not used
  490 REM 21 1 byte --- Date month
  500 REM 22 1 byte --- Date day
  510 REM 23 1 byte --- Date year
  520 
  530 DEFPROCprname
  540 FOR A%=0 TO 10:PRINTFNb(mem%?(ptr%+A%));:IF A%=7:VDU 46
  550 NEXT A%:PRINT" ";:ENDPROC
  560 DEFFNprdate(A%):A%=A%AND&FFFFFF:=FNd0((A%DIV256)AND255,2)+"/"+FNd0(A%AND255,2)+"/"+FNd0(1900+A%DIV65536,4)
  570 DEFFNpraccess(A%):=MID$("-W",2+((A%AND128)=0),1)+MID$("-D",2+((A%AND64)=0),1)+MID$("-R",2+((A%AND32)=0),1)+MID$("-C",2+((A%AND16)=0),1)
  580 :
  590 DEFPROCdump(fn$)
  600 REM out%=OPENOUT("H:\dump.bin")
  610 mem%?0=1:mem%?1=1:ptr%=0:addr0%=0
  620 REPEAT
  630   REPEAT:stx%=FNgetbyte:UNTIL stx%=2 OR stx%=22
  660   addr0%=256*FNgetbyte+FNgetbyte:leng%=0:IF stx%=2:leng%=FNgetbyte
  680   addr% =addr0%
  690   PRINT FNh0(addr%,4)"+"FNh0(leng%,2)
  700   REPEAT
  710     PRINT FNh0(trk%,2);":";FNh0(sec%,2);":";FNh0(ptr%,2);" ";FNh0(addr%,4);
  720     IF stx%=2:PRINT": "ELSE PRINT"> ";
  730     FOR B%=0 TO 15:IF leng%:IF addr%+B%<addr0%+leng%:dmp%?B%=FNgetbyte
  740     NEXT B%
  750     FOR B%=0 TO 15:IF addr%+B%<addr0%+leng%:PRINT FNh0(dmp%?B%,2);" "ELSE PRINT"   ";
  760     NEXT B%
  770     FOR B%=0 TO 15:IF addr%+B%<addr0%+leng%:PRINT FNc(dmp%?B%); ELSE VDU 32
  780     NEXT B%:PRINT
  790     REM IF (addr%AND&FE00)=&DE00:PTR#out%=addr%AND511:FOR B%=0 TO 15:BPUT#out%,dmp%?B%:NEXT
  800     addr%=addr%+16
  810   UNTIL addr%>=addr0%+leng%:addr0%=addr0%+leng%:PRINT
  820 UNTIL ptr%>255 AND ((mem%!0)AND&FFFF)=0
  830 REM CLOSE#out%
  840 ENDPROC
  850 :
  860 DEFFNgetbyte
  870 IF (ptr%AND255)=0:IF(!mem%)AND&FFFF:trk%=mem%?0:sec%=mem%?1:err%=FNfdc_disk(&53,mem%,drv%,trk%,0,sec%,1):ptr%=4
  880 ptr%=ptr%+1:=mem%?(ptr%-1)
  890 :
  900 DEFFNd(A%,N%)=RIGHT$("        "+STR$A%,N%)
  910 DEFFNd0(A%,N%)=RIGHT$("00000000"+STR$A%,N%)
  920 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
  930 DEFFNc(A%):A%=A%AND127:IF A%<32 OR A%=127:="." ELSE =CHR$A%
  940 DEFFNb(A%):A%=A%AND127:IF A%<32 OR A%=127:=" " ELSE =CHR$A%
  950 
  960 DEFPROCfdc_info(drv%)
  970 A%=FNfdc_disk(&53,mem%,drv%,0,0,0,0):IF A%:PRINT"No disk in drive ";drv%:ENDPROC
  980 PRINT"System Information Record for ";d_title$;":"
  990 PRINT"Disk shape:";FNd(d_trk%+1,5);" tracks       ";FNd(d_sec%,3);" sectors   ";d_sid%;" sides"
 1000 PRINT"Disk used: ";FNd(d_used%,5);" sectors ";FNd(d_used%*256,8);" bytes ";FNd(d_used%/4,5);"K"
 1010 PRINT"Disk free: ";FNd(d_free%,5);" sectors ";FNd(d_free%*256,8);" bytes ";FNd(d_free%/4,5);"K"
 1020 PRINT"Disk size: ";FNd(d_size%,5);" sectors ";FNd(d_size%*256,8);" bytes ";FNd(d_size%/4,5);"K"
 1030 ENDPROC
 1040 :
 1050 DEFFNfdc_disk(cmd%,add%,drv%,trk%,sid%,sec%,num%):LOCAL ptr%
 1060 IF drv%>3:drv%=(drv%DIV2)+(drv%AND1)
 1070 IF(debug%AND8):PRINT"cmd:";FNh0(cmd%,2);" add:";~add%-mem%;" ";
 1080 IF(debug%AND8):PRINT"drv:";drv%;" trk:";trk%;" sid:";sid%;" sec:";sec%;" num:";num%;" ";
 1090 IF drv%<>d_drv%:IF d_chn%:CLOSE#d_chn%:d_chn%=0        :REM Different drive, close current drive
 1100 IF d_chn%=0 THEN
 1110   IF d_path$(drv%)="":=&1E                             :REM If no mount path, return Drive not present
 1120   d_chn%=OPENUPd_path$(drv%):IF d_chn%=0:=&1E          :REM No drive, return Drive not present
 1130 ENDIF
 1140 IF drv%<>d_drv%:d_drv%=-1:IF FNfdc_exam(drv%):=&1E     :REM No info, return Drive not present
 1150 d_drv%=drv%:IF num%=0:=0                               :REM Just refresh disk info
 1160 IF d_chn%=0:=&1E
 1170 sec%=sec%-d_sec0%
 1180 IF d_sid%=1:ptr%=((sid%*80+trk%)*d_num%+sec%)*d_bps%+d_off%
 1190 IF d_sid%=2:ptr%=((trk%*2 +sid%)*d_num%+sec%)*d_bps%+d_off%
 1200 REM IF(debug%AND8):PRINT"cmd:";FNh0(cmd%,2);" add:";~add%-mem%;" ";
 1210 REM IF(debug%AND8):PRINT"drv:";drv%;" trk:";trk%;" sid:";sid%;" sec:";sec%;" num:";num%;" ";
 1220 IF(debug%AND8):PRINT"ptr:&";FNh0(ptr%,6)
 1230 IF cmd%=&4B:cmd%=1
 1240 IF cmd%=&53:cmd%=3
 1250 IF cmd%=&57:cmd%=3
 1260 IF cmd%=&5B:FOR A%=0 TO d_num%+2:add%!(A%*4)=(A%MODd_num%)*65536:NEXT:=0
 1270 REM IF(debug%AND8):PRINTd_path$(drv%)
 1280 REM IF(debug%AND8):PRINT"cmd:";cmd%;" chn:";d_chn%;" add:";~add%-mem%;" num:";num%*d_bps%;" ptr:";~ptr%
 1290 IF cmd%<5:PROCgbpb(cmd%,d_chn%,add%,num%*d_bps%,ptr%)
 1300 =0
 1310 :
 1320 DEFFNfdc_exam(drv%)
 1330 REM 16-26 Volume name in ASCII
 1340 REM 27-28 Volume number in binary
 1350 REM 29-30 Address of first data sector (Track-Sector)
 1360 REM 31-32 Address of last data sector (Track-Sector)
 1370 REM 33-34 Total number of data sectors in binary
 1380 REM 35-37 Current date (Month-Day-Year) in binary
 1390 REM 38    Highest track number on disk in binary
 1400 REM 39    Highest sector number on a track in binary
 1410 PTR#d_chn%=0
 1420 IF BGET#d_chn%+256*BGET#d_chn%=&6B64 THEN
 1430   d_off%=BGET#d_chn%+256*BGET#d_chn%
 1440   PTR#d_chn%=8
 1450   d_trk%=BGET#d_chn%
 1460   d_sid%=BGET#d_chn%
 1470   d_sec%=(EXT#d_chn%-d_off%) DIV (d_trk%*d_sid%*256)
 1480 ELSE
 1490   d_off%=0
 1500   d_trk%=EXT#d_chn% DIV 2560
 1510   d_sid%=1
 1520   d_sec%=10
 1530 ENDIF
 1540 d_num%=d_sec%:d_bps%=256:d_sec0%=1
 1550 PTR#d_chn%=&221
 1560 d_free%=256*BGET#d_chn%+BGET#d_chn%
 1570 PTR#d_chn%=&226
 1580 d_trk% =BGET#d_chn%
 1590 d_sec% =BGET#d_chn%
 1600 IF d_sec%>19:d_sid%=2 ELSE d_sid%=1
 1610 d_num% =d_sec% DIV d_sid%
 1620 d_size%=(d_trk%+1)*d_sec%
 1630 d_used%=d_size%-d_free%
 1640 PTR#d_chn%=&210:d_title$=""
 1650 REPEAT:A%=BGET#d_chn%:IF A%:d_title$=d_title$+CHR$A%
 1660 UNTILA%=0 OR LENd_title$=12
 1670 =0
 1680 :
 1690 DEFPROCgbpb(A%,chn%,addr%,num%,ptr%)
 1700 ?X%=chn%:X%!1=addr%:X%!5=num%:X%!9=ptr%:IFos%<32:CALL&FFD1:ENDPROC
 1710 IFA%=1ORA%=3:PTR#?X%=X%!9
 1720 REPEAT:IFA%=1ORA%=2:BPUT#?X%,?X%!1 ELSE IFA%=3ORA%=4:?X%!1=BGET#?X%
 1730 X%!1=X%!1+1:X%!5=X%!5-1:UNTIL(EOF#?X% AND A%>2)OR X%!5<1:ENDPROC