10 REM > ROMList
   20 :
   30 PRINT
   40 *Dir :System.ROMs
   50 *Access list/txt wr/r
   60 *Spool list/txt
   70 ON ERROR REPORT:PROCClose_All:PRINT:END
   80 DIM ctrl% 31,name% 80,data% 255:X%=ctrl%:Y%=X%DIV256
   90 PROCScan("")
  100 *Spool
  110 *SetType list/txt FFF
  120 *Access list/txt r/r
  130 END
  140 :
  150 DEFPROCScan(p$)
  160 LOCAL num%,idx%,f$,type%
  170 REPEAT
  180     f$=FNgbpb8(idx%):idx%=X%!9:IF f$<>"":PROCObject
  190 UNTIL f$=""
  200 ENDPROC
  210 :
  220 DEFPROCObject
  230 IF f$="index/htm" OR LEFT$(f$,1)="_":ENDPROC
  240 type%=FNfile(f$,5):IF type%=2:OSCLI"Dir "+f$:PROCScan(p$+LEFT$(".",p$<>"")+f$):OSCLI"Dir ^":ENDPROC
  250 IF type%<>1:ENDPROC ELSE type%=X%!3 AND &FFF
  260 IF type%=&FC0:in%=OPENIN(f$):A$=FNrd(in%):CLOSE#in%:in%=0:A$=LEFT$(A$,INSTR(A$+CHR$0,CHR$0)-1):A%=FNfile(A$,5):type%=X%!3 AND &FFF
  270 IF X%!10<100 OR type%<>&BBC:ENDPROC
  280 in%=OPENIN(f$):mem%=data%:base%=&8000
  290 PROCgbpb(3,in%,data%,256,base% AND &3FFF)
  300 REPEAT
  310     PROCROMHeader:PROCROMList
  320     base%=data%!4 AND &FFFF
  330     IF ?data%=&20:IF data%?5=&4C:base%=data%!6 AND &FFFF
  340     IF (base% AND &C000)<>&8000 OR (base% AND &3FFF)>EXT#in%:base%=0
  350     IF base%:PROCgbpb(3,in%,data%,256,base% AND &3FFF)
  360     IF base%:mem%=data%:IF mem%!(mem%?7)<>&29432800:mem%=data%+2
  370     IF base%:IF mem%!(mem%?7)<>&29432800:base%=0
  380 UNTIL base%=0
  390 CLOSE#in%:in%=0
  400 ENDPROC
  410 :
  420 DEFPROCROMHeader
  430 REM Get ROM title:
  440 A%=9:title$="":REPEAT:IF mem%?A%>31 AND mem%?A%<127:title$=title$+CHR$mem%?A%
  450 A%=A%+1:UNTIL mem%?A%<32 OR mem%?A%>126 OR A%>63:title$=FNs(title$)
  460 A%=A%-1:REPEATA%=A%+1:UNTILmem%?(A%-1)=0
  470 :
  480 REM Get any embedded ROM version string:
  490 ver$="":REPEAT:IF mem%?A%>31 AND mem%?A%<127:ver$=ver$+CHR$mem%?A%
  500 A%=A%+1:UNTIL mem%?A%<32 OR mem%?A%>126 OR A%>127:ver$=FNs(ver$)
  510 :
  520 REM Get ROM language type and entry addresses:
  530 rtype%=mem%?6:load%=base%:exec%=base%:lang%=rtype% AND &4F
  540 IF (rtype% AND &60)=&60:A%=mem%?7:REPEATA%=A%+1:UNTILmem%?A%=0:load%=mem%!(A%+1):exec%=load%
  550 IF lang%=&47 OR lang%=&49:exec%=mem%!(A%+5)
  560 :
  570 REM Get ROM copyright string:
  580 vbyte%=mem%?8
  590 A%=mem%?7:copy$="":REPEAT:IF mem%?A%>31 AND mem%?A%<127:copy$=copy$+CHR$mem%?A%
  600 A%=A%+1:UNTIL mem%?A%<32 OR mem%?A%>126 OR A%>255:copy$=FNs(copy$)
  610 IF LEFT$(copy$,3)<>"(C)":A%=0:REPEATA%=A%+1:UNTIL(MID$(f$,A%,1)>="0"ANDMID$(f$,A%,1)<="9")ORA%>LENf$:IFA%<LENf$:ver$=MID$(f$,A%,3)
  620 :
  630 REM Validate header data:
  640 IF mem%!(mem%?7)<>&29432800:title$="":rtype%=0:load%=0:exec%=0:ver$="":copy$=""
  650 :
  660 REM Try and normalise ROM version:
  670 IF ver$=copy$:ver$=""
  680 version$=ver$
  690 IF ver$="":A%=INSTR(title$,"."):ver$=MID$(title$,A%-1,4):title$=LEFT$(title$,A%-2)
  700 IF ver$="":IFbase%=&8000:IFVALRIGHT$(f$,3)ORVAL(RIGHT$(f$,2)):ver$=RIGHT$(f$,3):IFVALRIGHT$(f$,4):ver$=RIGHT$(f$,4)
  710 IF ver$="":ver$=LEFT$(STR$~mem%?8+"00",3)
  720 A%=INSTR(ver$," v"):IF A%=0:A%=INSTR(ver$," V")
  730 IF A%:ver$=MID$(ver$,A%+1)
  740 IF FNuc(LEFT$(ver$,7))="VERSION":ver$=FNs(MID$(ver$,8))
  750 IF FNuc(LEFT$(ver$,2))="V.":ver$=FNs(MID$(ver$,3))
  760 IF FNuc(LEFT$(ver$,1))="V":ver$=FNs(MID$(ver$,2))
  770 IF LEFT$(ver$,1)>"9":A%=INSTR(ver$,"."):IFA%:ver$=MID$(ver$,A%-1,4)
  780 IF LEFT$(ver$,1)>"9":ver$=MID$(ver$,2)
  790 IF MID$(ver$,2,1)="-":ver$=LEFT$(ver$,1)+"."+MID$(ver$,3)
  800 IF MID$(ver$,2,1)>"9":ver$=LEFT$(ver$,1)+MID$(ver$,3)
  810 ver$=FNs(ver$)
  820 IF MID$(ver$,2,1)<>".":ver$=LEFT$(ver$,1)+"."+MID$(ver$,2)
  830 IF LENver$<5:ver$=LEFT$(ver$+"00",4)
  840 IF MID$(ver$,3,1)<"0" AND MID$(ver$,3,1)>"0":ver$=LEFT$(ver$,2)+"0"+MID$(ver$,3)
  850 IF MID$(ver$,4,1)<"0" AND MID$(ver$,4,1)>"0":ver$=LEFT$(ver$,3)+"0"+MID$(ver$,3)
  860 copy$=LEFT$(copy$,3)+FNs(MID$(copy$,4))
  870 IF LENtitle$<3:title$=f$:IFINSTR("_/",MID$(title$,2,1)):title$=MID$(title$,3)
  880 ENDPROC
  890 :
  900 DEFPROCROMList
  910 title$=LEFT$(title$,24):PRINT title$;SPC(24-LENtitle$);"|";
  920 ver$  =LEFT$(ver$,4)   :PRINT ver$;SPC(4-LENver$);"|";
  930 A$=""
  940 IF (rtype%AND&80):A$=A$+"S" ELSE A$=A$+"-"
  950 IF (rtype%AND&40):A$=A$+"L" ELSE A$=A$+"-"
  960 IF (rtype%AND&20):A$=A$+"R" ELSE A$=A$+"-"
  970 IF (rtype%AND&10):A$=A$+"K" ELSE A$=A$+"-"
  980 A$=A$+" "+MID$("BASICTurbo65x2 68xx CPU4 CPU5 CPU6 PDP11Z80  32000CPU1080x86CPU12ARM  CPU14CPU15",(rtype%AND15)*5+1,5)+"|"+FNh0(load%,4)+"|"
  990 A$=A$+FNh0(vbyte%,2)+"|"
 1000 IF rtype%=0:A$="          |    |  |"
 1010 PRINT A$;
 1020 version$=LEFT$(version$,18):PRINT version$;SPC(18-LENversion$);"|";
 1030 copy$   =LEFT$(copy$,27):PRINT copy$;SPC(27-LENcopy$);"|";
 1040 PRINT p$;".";f$;CHR$10;
 1050 OSCLI "FX3,16":PRINT:*FX3
 1060 ENDPROC
 1070 :
 1080 DEFFNs(A$):IFLEFT$(A$,1)=" ":REPEATA$=MID$(A$,2):UNTILLEFT$(A$,1)<>" "
 1090 IFRIGHT$(A$,1)=" ":REPEATA$=LEFT$(A$,LENA$-1):UNTILRIGHT$(A$,1)<>" "
 1100 =A$
 1110 DEFFNuc(A$):LOCAL B$:IFA$="":=""
 1120 REPEATB$=B$+CHR$(ASCA$AND((A$<"@")OR&DF)):A$=MID$(A$,2):UNTILA$="":=B$
 1130 DEFFNlc(A$):LOCAL B$:IFA$="":=""
 1140 REPEATB$=B$+CHR$(ASCA$OR((A$<"_")AND&20)):A$=MID$(A$,2):UNTILA$="":=B$
 1150 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
 1160 :
 1170 DEFPROCClose_All:*Spool
 1180 in%=in%:IFin%:A%=in%:in%=0:CLOSE#A%
 1190 out%=out%:IFout%:A%=out%:out%=0:CLOSE#A%
 1200 ENDPROC
 1210 :
 1220 DEFFNrd(i%):LOCALA$:REPEAT
 1230   A%=BGET#i%:IFA%<>10 AND A%<>13:A$=A$+CHR$A%
 1240 UNTILA%=10 OR A%=13 OR EOF#i%:=A$
 1250 DEFFNfile(A$,A%):$name%=A$:?X%=name%:X%?1=name%DIV256:=(USR&FFDD)AND&FF
 1260 DEFPROCgbpb(A%,ch%,X%!1,X%!5,X%!9):?X%=ch%:CALL &FFD1:ENDPROC
 1270 DEFFNgbpb8(ptr%):X%!1=name%:X%!5=1:X%!9=ptr%:A%=8:CALL&FFD1:IFX%!5=1:=""
 1280 A%=name%+1:A%!(A%?-1)=&D20:A%?(INSTR($A%," ")-1)=13:=$A%
 1290 DEFFNfs:LOCALA%,Y%,E%:=(USR&FFDA)AND&FF