10 'GR8NET Micro-SD browsing and 20 'file loading program (FAT32) 30 'Copyleft 2011-2015 Eugeny Brychkov 40 'Please refer to license supplied 50 'with this software 60 '-------------------------------- 70 'IMPORTANT: uses 32-bit mathematics in software emulated floating point mode and GR8NET built-in match features 80 DEFDBLA-Z:CLEAR 512,(PEEK(&HFC4A)+PEEK(&HFC4B)*256)-&H200:'reserving space for sector data 90 PRINT"Micro-SD reader program for GR8NET" 100 PRINT"Copyleft (cl) 2015 Eugeny Brychkov":PRINT 110 DIM DC(128):'directory/file cluster chain; DC=chain length 120 DIM DN$(32):'directory names in hierarchy 130 DIM DH(32):'directory hierarchy of starting clusters, DD=directory depth (0=root) 140 DIM PN(12):'card properties 150 H=PEEK(&HFC4A)+PEEK(&HFC4B)*256:'512 byte Buffer address 160 CALLNETGETMEM(255,&H5FC0,A):IF(AAND128)=0THENPRINT"Insert SD-card and press any key":A$=INPUT$(1):GOTO160 170 CALLNETGETMEM(255,&H5FC0,A):IF(AAND2)<>0THENPRINT"Card initialized with error":END 180 IF(AAND1)=0THEN170 190 CALLNETGETMEM(&HC9,&H600C,PN(0),PN(1),PN(2),PN(3)):CALLNETGETMEM(&HC9,&H6010,PN(4),PN(5),PN(6),PN(7)):CALLNETGETMEM(&HC9,&H6014,PN(8),PN(9),PN(10),PN(11)) 200 PRINT"Vendor: ";:FORI=0TO6:PRINTCHR$(PN(I));:NEXTI:PRINTCHR$(9);"Rev: ";:S=PN(7):GOSUB 1070:PRINTCHR$(9);"S/N: ";:FORI=11TO8STEP-1:S=PN(I):GOSUB1070:NEXTI:PRINT 210 ' ### Reading MBR ### 220 PRINT"Reading MBR... "; 230 CALLNETSDCRD(0,H,0#,1,A):IFA<>1THENPRINT"MBR read error":END 240 IF PEEK(H+510)=&H55 AND PEEK(H+511)=&HAA THEN PRINT"valid" ELSE PRINT"invalid":STOP 250 PRINT" # Type Start Length":O=&H1BE:F=0 260 FOR I=0 TO 3 270 S=PEEK(H+O+4):IF S=0 THEN 310 280 F=F+1:PRINT I;" ";:GOSUB 1070:PRINT" "; 290 FOR J=0 TO 3:S=PEEK(H+O+11-J):GOSUB 1070:NEXT J:PRINT" "; 300 FOR J=0 TO 3:S=PEEK(H+O+15-J):GOSUB 1070:NEXT J:PRINT 310 O=O+16 320 NEXT I 330 IF F=0 THEN PRINT" > No partitions found":STOP 340 IF F=1 THEN C=&H30:GOTO 370 350 PRINT " > ";F;"partitions found":PRINT "Select partition: "; 360 A$=INPUT$(1):C=ASC(A$):IF C<&H30 OR C>F+&H2F THEN GOTO 360 370 C=C-&H30 380 PRINT"Partition is "; 390 A=PEEK(H+&H1BE+C*16+4):IF A=&HB OR A=&HC THEN PRINT"supported" ELSE PRINT"not supported":STOP 400 ' ### Reading boot sector ### 410 PRINT"Getting config... "; 420 'BO boot sector sector# 430 AR=H+&H1BE+C*16+8:CALLNETGETMD(0,AR,BO):CALLNETSETDM(&HC9,&H6024,BO):'Set volume starting LBA 440 CALLNETSDCRD(0,H,BO,1,A):IFA<>1THENPRINT"Boot sector read error":END 450 FE=0:'0=FAT32 standard mode 460 ' ### Getting volume configuration ### 470 ' !!! does not count hidden sectors !!! 480 'BS=bytes per sector, SC=sectors per cluster, NF=num of FATs 490 'DE=dir entries, FS=sectors per FAT, RS=reserved sectors, MI=media ID 500 A=PEEK(H):IF(A<>&HEB AND A<>&HE9) OR PEEK(H+2)<>&H90 THEN PRINT"invalid":STOP ELSE PRINT"valid" 510 PRINT"SecSize = ";:CALLNETGETMEM(0,H+11,S0,S1):BS=S1*256+S0:GOSUB1100 520 PRINTCHR$(9);"SecClu = ";:S=PEEK(H+13):CALLNETSETMEM(&HC9,&H6020,S):SC=S:GOSUB 1070:PRINT 530 PRINT"FATs = ";:S=PEEK(H+16):CALLNETSETMEM(&HC9,&H6023,S):NF=S:GOSUB 1070 540 PRINTCHR$(9);"DirEnt = ";:CALLNETGETMEM(0,H+17,S0,S1):DE=S1*256+S0:GOSUB1100:PRINT 550 PRINT"SecFAT = ";:CALLNETGETMEM(0,H+22,S0,S1):FS=S1*256+S0:GOSUB1100:CALLNETSETMEM(&HC9,&H6028,S0,S1,0,0) 560 PRINTCHR$(9);"ResSec = ";:CALLNETGETMEM(0,H+14,S0,S1):RS=S1*256+S0:GOSUB1100::PRINT:CALLNETSETMEM(&HC9,&H6021,S0,S1) 570 PRINT"MediaID = ";:S=PEEK(H+21):MI=S:GOSUB 1070:PRINT 580 IF BS<>512 OR SC=0 OR SC>64 OR NF<>2 THEN PRINT"FS is not supported":STOP:'sector should be 512 bytes 590 IF DE=0 OR FS=0 THEN PRINT" > FAT32 EBPB detected" ELSE PRINT" > FAT32 not detected":STOP 600 'FAT32 EBPB processing: FS=sectors per FAT, DF=root dir cluster# 610 FE=1:CALLNETGETMD(0,H+&H24,FS):CALLNETSETDM(&HC9,&H6028,FS) 620 CALLNETGETMD(0,H+&H2C,DF) 630 PRINT"SecFat = ";:AR=FS:GOSUB 1030:PRINT" DirClu = ";:AR=DF:GOSUB 1030:PRINT 640 CALLNETGETMD(&HC9,&H602C,FO):CALLNETGETMD(&HC9,&H6034,CO):'FO=first FAT sector#, CO=cluster 2 sector# 650 PRINT"FAToff = ";:AR=FO:GOSUB 1030:PRINT" CL2off = ";:AR=CO:GOSUB 1030:PRINT 660 DD=0:DH(0)=DF:'initialize dir hierarchy 670 ' ### Displaying the menu ### 680 PRINT" ":PRINT"1. DIR";CHR$(9);CHR$(9);"2. Load file into RAM" 690 PRINT"3. CHDIR";CHR$(9);"4. Display sector":PRINT"5. Exit":PRINT"> "; 700 A$=INPUT$(1):A=ASC(A$):IF A<&H31 OR A>&H35 THEN 700 710 PRINT CHR$(A):A=A-&H30 720 N$="":GOSUB 1450:'build current directory cluster chain 730 ON A GOTO 750,830,770,900,740 740 STOP 750 ' ### Display directory contents ### 760 GOSUB 1120:GOTO 680:'display directory contents 770 ' ### Change directory ### 780 NM$="":INPUT"Name";NM$:IF NM$="" THEN 680 790 IF NM$="." THEN DD=0:GOTO 680:'go to root dir 800 IF NM$=".." THEN IF DD>0 THEN DD=DD-1:GOTO 680 ELSE PRINT"Already at root level":GOTO 680 810 GOSUB 1820:GOSUB 1120:IF FC=0 THEN PRINT"Directory not found":GOTO 680 820 GOSUB 1590:DD=DD+1:DH(DD)=FC:DN$(DD)=NM$:GOTO 680:'next dir level 830 ' ### Load the file ### 840 NM$="":INPUT"Name";NM$:IF NM$="" THEN 680 850 GOSUB 1820:GOSUB 1120:IF FC=0 THEN PRINT"File not found":GOTO 680 ELSE GOSUB 1590 860 DD=DD+1:DH(DD)=FC:GOSUB 1450:'go to next depth level, and build cluster chain for file 870 PRINT"Occupies";DC;"clusters":IF SI=0 OR DC=0 THEN PRINT"Unable to load":GOTO 890 880 GOSUB 1620:'copy the file 890 DD=DD-1:GOTO 680:'back to prev hierarchy level 900 ' ### Display sector contents ### 910 A$="":INPUT"Sector# (decimal)";A$:IF A$="" THEN 680 920 AR=VAL(A$):CALLNETSDCRD(0,H,AR,1,O):IFO<>1THENPRINT"Sector read error":END 930 S=PEEK(&HF3B0):IF S<70 THEN S=8 ELSE S=16:'number of bytes per row 940 A=0:DS=0 950 S$=HEX$(A):S$=STRING$(3-LEN(S$),"0")+S$:PRINT S$;": "; 960 FOR I=0 TO S-1:S$=HEX$(PEEK(H+A+I)):S$=STRING$(2-LEN(S$),"0")+S$+" ":PRINT S$;:NEXT I 970 FOR I=0 TO S-1:C=PEEK(H+A+I):IF C<32 OR C=127 THEN PRINT"."; ELSE PRINTCHR$(C); 980 NEXT I 990 A=A+S:PRINT 1000 DS=DS+1:IF DS=16 AND A<512 THEN DS=0:PRINT"Press SPACE to continue":A$=INPUT$(1):IF A$<>" " THEN 1020 ELSE PRINT 1010 IF A<512 THEN 950 1020 GOTO 680 1030 ' **** Print number in 32-bit format **** arg is in AR 1040 S=FIX(AR/16777216#):GOSUB 1070:AR=AR-S*16777216#:S=FIX(AR/65536!):GOSUB 1070 1050 AR=AR-S*65536!:S=FIX(AR/256):GOSUB 1070:S=AR-S*256:GOSUB 1070 1060 RETURN 1070 ' **** Prints HEX of S in 2 pos **** 1080 S$=HEX$(S):IF LEN(S$)=1 THEN PRINT"0"; 1090 PRINTS$;:RETURN 1100 ' **** Prints HEX of S1/S0 in 4 pos **** 1110 S=S1:GOSUB1070:S=S0:GOSUB1070:RETURN 1120 ' **** Read and scan dir for name in N$, if N$="" then display dir **** 1130 'if N$<>"", return FC=file first cluster, SI=file size in bytes 1140 PRINT"Path: /"; 1150 IF DD>0 THEN FOR I=1 TO DD:PRINTDN$(I);"/";:NEXT I 1160 PRINT:DS=0:'line display counter 1170 FOR I=0 TO DC-1 1180 CALLNETSETDM(&HC9,&H6038,DC(I)):CALLNETGETMD(&HC9,&H603C,SE):'getting cluster starting sector # 1190 FOR J=1 TO SC 1200 CALLNETSDCRD(0,H,SE,1,A):IFA<>1THENPRINT"Error reading data sector":END 1210 FOR K=0 TO 480 STEP 32:'16 dir entries 1220 GOSUB 1770:'display progress indicator 1230 A=PEEK(H+K):IF A=&HE5 OR A=0 THEN 1390:'unused entries 1240 A=PEEK(H+K+11):IF A=15 THEN1390:'long fname 1250 NA$="":DN$="":FOR L=0 TO 10:C=PEEK(H+K+L):IF C>&H60 AND C<&H7B THEN C=(C AND &HDF):'toupper 1260 IF L=8 THEN DN$=DN$+" ":'DN$ is display name 1270 NA$=NA$+CHR$(C):DN$=DN$+CHR$(C):NEXT L 1280 IF N$<>"" AND NA$<>N$ THEN 1340 1290 PRINT DN$; 1300 CALLNETGETMD(0,H+K+&H1C,SI) 1310 FC=PEEK(H+K+&H1A)+PEEK(H+K+&H1B)*256+PEEK(H+K+&H14)*65536!+PEEK(H+K+&H15)*16777216# 1320 IF (A AND 16)<>0 THEN PRINT" " ELSE PRINTUSING"##########,";SI 1330 DS=DS+1 1340 IF NA$=N$ THEN 1430:'N$ file was found 1350 IF DS<16 THEN 1390 1360 PRINT"Press SPACE to continue":DS=0 1370 IF INKEY$<>"" THEN 1370:'clear kbd buffer 1380 A$=INPUT$(1):IF A$<>" " THEN 1430 ELSE PRINT 1390 NEXT K 1400 SE=SE+1 1410 NEXT J 1420 NEXT I 1430 IF N$<>"" AND NA$<>N$ THEN SI=0:FC=0:'file not found 1440 RETURN 1450 ' **** Build cluster chain **** 1460 'input: DD=dir depth level, DH()=dir hierarchy start clusters array, FO=first FAT sector# 1470 'output: DC(0-...)=cluster chain, DC(0)=start cluster, DC=number of clusters 1480 'corrupt: CF=current FAT sector#, CL=entry# in FAT sector 1490 DC=1:DC(0)=DH(DD) 1500 'reading respective FAT sector 1510 CALLNETSETDM(&HC9,&H6038,DC(DC-1)):CALLNETGETMD(&HC9,&H6040,AR):CALLNETSDCRD(0,H,AR,1,O):IFO<>1THENPRINT"FAT sector read error":END 1520 'getting next cluster# 1530 CALLNETGETMEM(&HC9,&H6044,S0,S1):S=S1*256+S0:CALLNETGETMD(0,H+S,DC(DC)):CALLNETGETMEM(0,H+S,S0,S1,S2,S3) 1540 'checking for last cluster in chain 1550 IF (S0 AND 248)=248 AND S1=255 AND S2=255 AND (S3 AND 15)=15 THEN 1580 1560 GOSUB 1770:'display progress indicator 1570 DC=DC+1:GOTO1510 1580 RETURN 1590 ' **** Display file/dir start cluster and cluster count **** 1600 PRINT"Cluster = ";:AR=FC:GOSUB 1030:PRINT" Size = ";:AR=SI:GOSUB 1030:PRINT 1610 RETURN 1620 ' **** Load file to buffer RAM **** 1630 'input: DC()=cluster chain, DC=number of clusters, SI=file size 1640 'input: DR$=target drive name. N$=file name 1650 IF SC<8 THEN ST=SC ELSE ST=8 1660 P=0:AD=24576:IF ST=3 OR (ST>4 AND ST<8) THEN PRINT"Invalid sector count":END 1670 FOR I=1 TO DC:'per cluster 1680 CALLNETSETDM(&HC9,&H6038,DC(I-1)):CALLNETGETMD(&HC9,&H603C,AR):'AR=cluster starting sector 1690 FOR J=1 TO SC STEP ST:'per sector 1700 CALLNETSDCRD(P,AD,AR,ST,A):IFA<>ST THEN PRINT"Sector read error":END 1710 AD=AD+ST*512:AR=AR+ST:IF AD=32768! THEN AD=24576:P=P+1:IF P=&H80 THEN PRINT"File too big":END 1720 NEXT J 1730 PRINTUSING"###%";I/DC*100;:PRINTCHR$(13); 1740 NEXT I 1750 PRINT"Complete" 1760 RETURN 1770 ' **** Show that operation is in progress **** 1780 IF PR>3 THEN PR=0 1790 IF PR=0 THEN PR$="|" ELSE IF PR=1 THEN PR$="/" ELSE IF PR=2 THEN PR$="-" ELSE IF PR=3 THEN PR$="\" 1800 PR=PR+1:PRINT PR$;CHR$(13); 1810 RETURN 1820 ' **** Convert X.X file name to 8:3 DIR format **** 1830 'input: NM$=X.X file name, output N$=8:3 file name 1840 'corrupt: EX,S,A$,C 1850 N$="":S=LEN(NM$):EX=0:'EX=processing extension flag 1860 FOR I0=1 TO S 1870 A$=MID$(NM$,I0,1) 1880 C=ASC(A$):IF C>&H60 AND C<&H7B THEN A$=CHR$(C AND &HDF):'toupper 1890 IF LEN(N$)=8 AND EX=0 AND A$<>"." THEN 1920:'skip name if longer than 8 chars 1900 IF LEN(N$)=11 AND EX=1 THEN 1920:'skip extension if longer than 3 1910 IF A$="." THEN N$=N$+SPACE$(8-LEN(N$)):EX=1 ELSE N$=N$+A$ 1920 NEXT I0 1930 N$=N$+SPACE$(11-LEN(N$)) 1940 RETURN