10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180 :
190 MODE&87:IFFNfx(0,1)<6:IFFNfx(130,0)=&FFFF ELSE PRINT"Must run on BBC I/O processor":END
200 fs%=FNfs:ver$="1.16"
210 adfs%=TRUE:ON ERROR adfs%=FALSE
220 IFadfs%:IFFNfs<>8:*FADFS
230 hadfs%=TRUE:ON ERROR hadfs%=FALSE
240 IFhadfs%:IFFNfs<>16:*HADFS
250 IFfs%<>8:IFfs%<>16:fs%=8:
260 ok%=TRUE:ON ERROR ok%=FALSE
270 IFok%:OSCLI"FX143,18,"+STR$fs%:IFfs%=8:MOUNT 0
280 fs%=FNfs:hd%=(fs%-8)/2:PROCinit
290 ON ERROR IFFNerr:PROCend:END
300 MODE&87:REPEATUNTILFNmenu:PROCend:END
310 :
320 DEFPROCend:END:ENDPROC
330 :
340 DEFFNerr:PRINT:REPORT:A%=INKEY(100):=INKEY-1
350 :
360 DEFPROCinit
370 DIM ctrl%31,mem%511,info%512:X%=ctrl%:Y%=X%DIV256
380 safe%=TRUE:full%=TRUE:PROCasm:PROCinfo:*FX219,9
390 ENDPROC
400 :
410 DEFPROCinfo
420 big%=0:hdsz%=0:rv%=0:FORA%=0TO511STEP4:info%!A%=0:NEXT:dev$="IDE":IFhd%>3:ENDPROC
430 OSCLI"FADFS":Y%=?&DBC:!&F6=&BFFF:rv%=(USR&FFB9)AND255:!&F6=&8002:d4%=((USR&FFB9)AND128)/64+2:!&F6=&8008:A%=((USR&FFB9)AND6)/2:Y%=X%DIV256:IFA%<>1:scsz%=256
440 dev$=MID$("SCSIIDE --- MMC ",A%*4+1,4+(A%>0)):ENDPROC
450 :
460 DEFFNmenu
470 A$=" BBC "+dev$+LEFT$("r"+STR$~rv%,rv%>0)+" Hard Drive Initialiser "+ver$
480 CLS:PRINTA$'STRING$(LENA$+1,"=");CHR$8:PROCDriveInfo
490 PRINT'"D: Select drive I: Investigate drive"
500 PRINT"S: Scan for size Z: Set drive size"
510 PRINT"F: Format drive W: Wipe data (";LEFT$("on",NOTsafe%);LEFT$("off",safe%);")"
520 IFfull%:IFsafe%:PRINTSPC17; ELSE IFfull%:PRINT"R: Randomise data";
530 IFfull%:PRINT" <TAB> Toggle width"
540 PRINT'SPC6"Press a key or X to exit:";
550 REPEAT A$=GET$:UNTIL INSTR(CHR$9+"*DdIiFfWwRrSsXxZz",A$):PRINTCHR$13;SPC32;CHR$13;:IFA$="*"REPEAT INPUT LINE"*"A$:OSCLI A$:UNTIL A$="":A$="*"
560 A$=CHR$(ASC A$AND&DF)
570 IFA$="D":PROCDrive:=0
580 IFA$="F":PROCFormat:=0
590 IFA$="I":PROCInvest:=0
600 IFA$="S":PROCScan:=0
610 IFA$="W":safe%=NOTsafe%:=0
620 IFA$="R":IFNOTsafe%:PROCRandom:=0
630 IFA$="Z":PROCSetSize:=0
640 IFA$=CHR$9:IFNOTINKEY-1:scsz%=768-scsz%
650 IFA$=CHR$9:IFINKEY-1:full%=NOTfull%
660 =A$="X"
670 :
680 DEFPROCDriveInfo
690 IFhd%<4:dev%=hd%DIVd4% ELSE dev%=hd%DIV8:d4%=4
700 PRINT" Current drive: ";~hd%;" ("dev$" device ";dev%;")";
710
720
730 PRINT'" Device width: ";scsz%DIV32;" bits"
740 IFfull%:PRINT" Model: "FNstr(info%+54,20)'SPC11;FNstr(info%+74,20)
750 IFfull%:PRINT" Firmware: "FNstr(info%+46,8)
760 IFfull%:PRINT" Serial: "FNstr(info%+20,20)
770 PRINT'" Total sectors: &";FNh0(hdsz%,8)" (";INT(hdsz%/204.8)/10;"M)"
780 PRINT" Physical size: C:&";FNh0(info%!&02,4);" H:";FNd(info%?&06,2);" S:";info%?&0C
790 PRINT" Logical size: C:&";FNh0(info%!&6C,4);" H:";FNd(info%?&6E,2);" S:";info%?&70
800 PRINT" 8-bit Size: ";FNd(hdsz%DIV4,8);"K (";INT(hdsz%/409.6)/10;"M)"
810 IFhd%<4:PROCInfo(hd%,16-d4%,&200000,"ADFS") ELSE PROCInfo(hd%,12,&1000000,"HADFS")
820 PRINTSTRING$(34+LENdev$,"="):ENDPROC
830 :
840 DEFPROCInfo(d%,m%,sz%,fs$):d%=d%ANDm%
850 PRINT" ";fs$;" drives:";:hsz%=hdsz%:REPEAT
860 A%=sz%:IFhsz%<A%:A%=hsz%
870 PRINTTAB(16);~d%;": ";INT(A%/409.6)/10;"M";:hsz%=hsz%-A%
880 A%=sz%:IFhsz%<A%:A%=hsz%
890 PRINTTAB(27);~d%+1;": ";INT(A%/409.6)/10;"M":hsz%=hsz%-A%
900 d%=d%+2:UNTILd%=d4% OR (d%AND3)=0
910 ENDPROC
920 :
930 DEFPROCDrive
940 INPUT"Enter logical drive (0-B) :"A$:IFA$>"`":A$=CHR$(ASCA$-32)
950 IFINSTR("0123456789AB",A$):hd%=EVAL("&"+A$):PROCinfo
960 ENDPROC
970 :
980 DEFPROCInvest
990 FORA%=0TO511STEP4:mem%!A%=0:NEXT:big%=FALSE
1000 IFdev$="SCSI":IFhd%<4:A%=FNscsi(&1A,mem%,22,0,hd%):info%?2=mem%?14:info%!3=mem%?13:info%?6=mem%?15:info%?12=33:info%!&6C=info%!2:info%!&6E=info%?6:info%!&70=info%?12:hdsz%=info%!2*info%?6*info%?12:OSCLI"MOUNT":ENDPROC
1010 IFdev$="IDE":!addr%=mem%:A%=dev%*16:nm%?1=scsz%DIV256-1:CALL id%
1020 FORA%=0TO255:info%?(A%*2)=mem%?A%:info%?(A%*2+1)=mem%?(A%+256):NEXT
1030 IFinfo%?3+info%?109+info%?115=0:info%?109=info%?116:info%?115=info%?108:A%=(256*info%?109+info%?108)*info%?110*info%?112:info%?3=(A%DIV((info%?6)*(info%?12)))DIV256
1040 IFinfo%?&74=0:big%=TRUE:info%?&74=info%?&72:info%?&72=0
1050 IFinfo%?&79=0:info%?&79=info%?&6C
1060 hdsz%=info%!&78:
1070 ENDPROC
1080 :
1090 DEFPROCScan
1100 PRINT"Scanning drive ";hd%:sec%=&800:PROCinfo
1110 REPEAT sec%=sec%+sec%:UNTIL FNscan(sec%)<>0 OR sec%>&1FFFFF
1120 step%=sec%DIV2:dir%=-1:REPEAT
1130 sec%=sec%+step%*dir%:A%=FNscan(sec%)
1140 step%=step%DIV2:IFA%=0:dir%=1 ELSE dir%=-1
1150 UNTIL step%<1:hdsz%=sec%-1:PRINT
1160 ENDPROC
1170 :
1180 DEFFNscan(sec%):PRINTCHR$13;"Drive size: ";sec%DIV4;"K ";
1190 IFadfs%:=FNscsi(&08,mem%,1,sec%-1,hd%) ELSE =-1
1200 :
1210 DEFPROCSetSize
1220 INPUT"Enter drive size, use <size>, &<size>, <size>K or <size>M :"A$
1230 PROCinfo:big%=0:hdsz%=FNrdsz(A$):ENDPROC
1240 :
1250 DEFPROCFormat:IFhdsz%<1:PROCInvest
1260 size%=hdsz%:max%=&200000:IFhd%>3:max%=&1000000
1270 IF d4%=2:A%=hd%=1 OR hd%=3 ELSE A%=hd%=1 OR hd%=2 OR hd%=3 OR hd%>5
1280 IF A%:A%=hd%:REPEATsize%=size%-max%:A%=A%-1:UNTIL(A%AND3)=0 OR A%=d4%
1290 IFsize%>max%:size%=max%
1300 IFsize%<0:PRINT"No space for drive ";~hd%;:PROCdelay(200):ENDPROC
1310 IFsize%<&1000:PRINT"This appears to be a floppy"
1320 PRINT"Format ";LEFT$("H",hd%>3);"ADFS drive ";~hd%;" to ";FNsz(size%);CHR$8
1330 A$="":IF(hd%AND(7-d4%))=0:PRINT"Leave space for ";LEFT$("H",hd%<4);"ADFS system? ";:INPUT""A$
1340 part%=(LEFT$(A$,1)="Y" OR LEFT$(A$,1)="y") AND &400000:IFpart%>hdsz%:part%=hdsz%
1350 IFpart%:IFhd%>3:PRINT"ADFS space (";FNsz(part%);"): ";:INPUT""A$:IFA$<>"":part%=FNrdsz(A$)
1360 INPUT"Format? Enter YES to confirm: "A$:IFA$<>"YES":PRINT"Not formatted";:PROCdelay(200):ENDPROC
1370 IFhd%<4:PROCInitADFS
1380 IFhd%>3:PROCInitHADFS:IFpart%:hdsz%=part%
1390 ENDPROC
1400 :
1410 DEFPROCInitHADFS
1420 !X%=1:A%=14:CALL&FFF1:
1430 FORA%=0TO6:X%?A%=(X%?A%AND15)+10*(X%?A%DIV16):NEXT:
1440 IF?X%<81:?X%=19+?X% ELSE ?X%=?X%-81:
1450 today%=(?X%DIV16)+8*X%?2+256*X%?1+4096*(?X%AND15)
1460 start%=2:IFpart%:start%=7:IFsize%>&FFFF:start%=part%:
1470 dskID%=RND(65535):IFsize%=&10000:size%=&FFFF
1480 :
1490 PROCclear :
1500 IFsafe%:PROCread(&46,hd%) :
1510 $mem%="IDEDISK"+STR$~hd%+" ":
1520 $(mem%+16)=CHR$0+"(C)JGH"+CHR$0:
1530 mem%!24=dskID% :
1540 mem%!26=today% :
1550 mem%!28=size% :
1560 IFsize%<&10000:mem%?30=&11:msz%=2 ELSE mem%?31=&80:msz%=3
1570 mem%!(32+0*msz%)=&02:mem%!(32+1*msz%)=&44 :
1580 mem%!(32+2*msz%)=&4A:mem%!(32+3*msz%)=size%-&4A
1590 mem%!(32+4*msz%)=&00:mem%!(32+5*msz%)=0
1600 IFpart%:mem%?31=mem%?31OR&41:mem%!32=start%:mem%!(32+msz%)=size%-start%:mem%!(32+2*msz%)=0:mem%!(32+3*msz%)=0
1610 PROCwrite(&46,hd%) :
1620 :
1630 PROCclear :
1640 IFsafe%:PROCread(&47,hd%) :
1650 $mem%="$ " :
1660 mem%!10=&47:mem%!14=0 :
1670 mem%!16=dskID%:mem%!20=0 :
1680 IFsize%>&FFFF:mem%!10=0:mem%!24=0:mem%!28=&47:mem%?12=&80:
1690 PROCwrite(&47,hd%) :
1700 :
1710 PROCclear :
1720 IFNOTsafe%:PROCwrite(&48,hd%) :
1730 IFNOTsafe%:PROCwrite(&49,hd%) :
1740 :
1750 PRINT"Drive ";~hd%;" initialised to ";FNsz(size%):PROCdelay(200)
1760 ENDPROC
1770 :
1780 DEFPROCInitADFS
1790 PROCclear :
1800 mem%!0=7 :
1810 IFpart%:mem%!3=&4A :
1820 mem%!252=size% :
1830 mem%?255=0:mem%?255=FNsum :
1840 PROCwrite(0,hd%) :
1850 :
1860 PROCclear :
1870 mem%!0=size%-7 :
1880 IFpart%:mem%!0=&3F:mem%!3=size%-&4A :
1890 mem%!251=RND(65535) :
1900 mem%?253=0 :
1910 mem%?254=3-3*(part%<>0) :
1920 mem%?255=1:mem%?255=FNsum :
1930 PROCwrite(1,hd%) :
1940 :
1950 FORS%=2TO6:PROCclear :
1960 IFsafe%:PROCread(S%,hd%):PROCclrdir(S%*4-3):
1970 IFS%=2:$mem%=CHR$0+"Hugo":mem%?5=0 :
1980 IFS%=6:$(mem%+204)="$":mem%!214=2 :
1990 IFS%=6:$(mem%+217)="$":$(mem%+227)="" :
2000 IFS%=6:$(mem%+250)=CHR$0+"Hugo":mem%?255=0 :
2010 PROCwrite(S%,hd%):NEXT :
2020 :
2030 PRINT"Drive ";hd%;" initialised to ";FNsz(size%)
2040 PRINT"**WARNING** You *MUST* reset ADFS to"'"prevent disk corruption."
2050 PROCdelay(200):ENDPROC
2060 :
2070 DEFPROCclear:FORA%=0TO255STEP4:mem%!A%=0:NEXT:ENDPROC
2080 DEFPROCclrdir(O%):FORA%=O%TO255STEP26:mem%?A%=0:NEXT:ENDPROC
2090 :
2100 DEFFNsum:LOCALsum%:sum%=255
2110 FORA%=254TO0STEP-1:sum%=(sum%+sum%DIV256)AND255:sum%=sum%+mem%?A%:NEXT:=sum%AND255
2120 :
2130 DEFPROCRandom
2140 PRINT"Randomise contents of drive ";hd%;"?"
2150 INPUT"Enter YES to confirm: "A$:IFA$<>"YES":PRINT"Not randomised";:PROCdelay(200):ENDPROC
2160 PRINT"Press ESCAPE to terminate ";
2170 sec%=0:REPEATPRINTSTRING$(6,CHR$8);FNh0(sec%,6);
2180 FORA%=0TO255:mem%?A%=RND(255):NEXT:PROCwrite(sec%,hd%)
2190 sec%=sec%+1:UNTIL0:ENDPROC
2200 :
2210 DEFPROCwrite(sec%,drv%):cmd%=wr%:IFdrv%<4:IFFNscsi(&0A,mem%,1,sec%,drv%)=0:ENDPROC
2220 DEFPROCread(sec%,drv%):cmd%=rd%:IFdrv%<4:IFFNscsi(&08,mem%,1,sec%,drv%)=0:ENDPROC
2230 !addr%=mem%:!sc%=sec%:A%=sc%?2:sc%?2=sc%?0:sc%?0=A%:?dv%=(d4%*32)AND128:?nm%=1:nm%?1=0:IFdrv%>3:?dv%=drv%
2240 A%=USRcmd%:ENDPROC
2250 :
2260 DEFPROCdelay(T%):T%=TIME+T%:REPEAT UNTIL TIME>T%:ENDPROC
2270 :
2280 DEFFNscsi(cmd%,addr%,num%,sect%,drv%):IFsect%>&1EFFFF:=&21
2290 LOCALfs%:fs%=FNfs:IFfs%<>8:*FADFS
2300 X%?0=0:X%!1=addr%:X%?5=cmd%:X%?6=drv%*32+((sect%AND&1F0000)DIV65536)
2310 X%?7=((sect%AND&FF00)DIV256):X%?8=sect%:X%!9=num%:X%!11=0
2320 A%=114:CALL&FFF1:A%=?X%:IFfs%<>8:OSCLI"FX143,18,"+STR$fs%
2330 =A%
2340 :
2350 DEFFNfs:LOCAL A%,Y%,E%:=(USR&FFDA)AND&FF
2360 DEFFNfx(A%,X%):LOCAL Y%:Y%=X%DIV256:=((USR&FFF4)AND&FFFF00)DIV256
2370 :
2380 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
2390 DEFFNd(A%,N%)=RIGHT$(" "+STR$A%,N%)
2400 DEFFNstr(A%,N%):LOCAL A$:REPEAT
2410 IFA%?1>31:A$=A$+CHR$A%?1 ELSE A$=A$+"."
2420 IF?A%>31:A$=A$+CHR$?A% ELSE A$=A$+"."
2430 A%=A%+2:N%=N%-2:UNTILN%<1:=A$
2440 DEFFNsz(A%):=STR$(A%DIV4)+"K ("+STR$(A%DIV4096)+"M)"
2450 DEFFNrdsz(A$):IFLEFT$(A$,1)="&":=EVALA$
2460 IFRIGHT$(A$,1)="K" OR RIGHT$(A$,1)="k":=VALA$*4
2470 IFRIGHT$(A$,1)="M" OR RIGHT$(A$,1)="m":=VALA$*4096
2480 =VALA$DIV256
2490 :
2500 DEFPROCasm:mc%=mc%:IFmc%:ENDPROC
2510 DIMmc%409:addr%=&80:dv%=&84:sc%=&85:nm%=&88:cmd%=&8A:tmp=&8B
2520 IDEdata=&FC40:IDEerror=&FC41:IDEcount=&FC42:IDEsector=&FC43
2530 IDEcylinder=&FC44:IDEhead=&FC46:IDEstatus=&FC47:IDEcommand=&FC47
2540 scsz%=256:IF!IDEdata<>IDEdata!8:scsz%=512
2550
2560
2570
2580
2590
2600
2610
2620
2630
2640
2650
2660 FORP=0TO1:P%=mc%:[OPT P*2
2670 .id%:TAY:.idlp:LDA &FF:BMI idescape:LDA IDEstatus:BMI idlp
2680 TYA:AND #16:STA IDEhead:LDA #&EC:STA IDEcommand :\ &EC=Identify
2690 LDY #0:LDX #1:STX nm%:CLC:BCC TransferLoop:.idescape:RTS
2700 .WaitForData
2710 LDA &FC47:AND #8:BEQ WaitForData:LDA &FC47:RTS
2720 .WaitNotBusy
2730 PHP:JSR L806F:AND #&80:BNE WaitNotBusy+1:PLP:RTS
2740 .L806F
2750 PHP:LDA &FC47:STA &8D:LDA &FC47:CMP &8D:BNE L806F+1:PLP:RTS
2760 .rd%:LDA #&08:STA &8A:CLC:BCC CommandStart
2770 .wr%:LDA #&0A:STA &8A:SEC:BCS CommandStart
2780 .CommandStart :\ C=R/W, &8E/F=>block
2790 LDA #&7F:STA &8E:LDA #0:STA &8F :\ &8E/F=>block
2800 PHP:JSR SetGeometry:PLP
2810 .CommandLoop
2820 LDX #2:.Twice:JSR SetSector:LDY #0:\ Set sector, count, command
2830 .TransferLoop
2840 JSR WaitForData:AND #&21:BNE TransError
2850 BCC IORead
2860 .IOWrite
2870 LDA (&80),Y:STA &FC40:LDA nm%+1:BEQ TransferByte
2880 INC &81:LDA (&80),Y:STA &FC48:DEC &81:JMP TransferByte
2890 .IORead
2900 LDA &FC40:STA (&80),Y:LDA nm%+1:BEQ TransferByte
2910 INC &81:LDA &FC48:STA (&80),Y:DEC &81:JMP TransferByte
2920 .TransferByte
2930 LDA &FC47:AND #8:BEQ TransError:INY:BNE TransferLoop
2940 LDA &FC47:AND #&21:BNE TransError:DEX:BNE Twice
2950 INC &87:BNE TransCount:INC &86:BNE TransCount:INC &85
2960 .TransCount
2970 DEC &88:BNE CommandLoop:LDA #0:TAX:RTS
2980 .TransError
2990 LDA &FC47:LDX &FC41:RTS
3000 .SetGeometry
3010 JSR WaitNotBusy:LDA #64:STA &FC42:STA &FC43:\ 64 sectors per track
3020 LDA dv%:BMI SetGeo8:BNE SetGeo16:LDA sc%:LSR A:LSR A
3030 .SetGeo8:ORA #3:AND #&13:BNE SetGeo:\ 4 heads per cylinder
3040 .SetGeo16:ASL A:ASL A:ASL A:ASL A:ORA #15:AND #&1F:\ 16 heads per cylinder
3050 .SetGeo:STA &FC46:LDA #&91:STA &FC47:RTS
3060 :
3070 .SetSector
3080 PHP:JSR WaitNotBusy :\ Save CC/CS Read/Write
3090 LDAdv%:BMI SetSector8:BNE SetSector16 :\ Set 16-head sector
3100 LDAsc%+0:PHA:AND #&3F:STA &FC45 :\ Set sector b16-b20
3110 PLA:ROL A:ROL A:ROL A:ROL A :\ Get Drive 0/1
3120 EORsc%+2:AND #&02:EOR sc%+2 :\ Merge Drive and Head
3130 .SetSectorX
3140 ROL A:ROL A:ROL A:AND #&13:STA &FC46 :\ Set device + sector b6-b7
3150 LDAsc%+1:STA &FC44 :\ Set sector b8-b15
3160 LDAsc%+2:CLC:AND #63:ADC #1:STA &FC43 :\ Set sector b0-b5
3170 LDA#1:STA &FC42 :\ One sector
3180 .SetCommand
3190 LDA&8A:AND #2:PHA:EOR #2:LSR A:LSR A :\ Copy ~b1 into Cy
3200 PLA:ASL A:ASL A:ASL A:ORA #&20 :\ Translate CS->&20 or CC->&30
3210 STA &FC47:PLP:RTS :\ Set command &08 or &0A
3220 .SetSector8
3230 LDAsc%+0:STA &FC45 :\ Set sector b16-b20
3240 LDAsc%+2:AND #&C0:JMP SetSectorX
3250 .SetSector16
3260 LDAsc%+2:ROL A:ROL A:ROL A:AND #&03:STA tmp
3270 LDAsc%+1:ASL A:ASL A:AND #&0C:ORA tmp:STA tmp
3280 LDAdv%:LSR A:LDA tmp:BCC P%+4:ORA #&10:STA &FC46 :\ Head = sector b6-b9
3290 LDAsc%+1:LSR A:LSR A:STA tmp
3300 LDAsc%+0:ROR A:ROR A:ROR A:AND #&C0:ORA tmp:STA &FC44 :\ Cylinder.lo=sector b10-b17
3310 LDAsc%+0:LSR A:LSR A:STA tmp
3320 LDAdv%:ROR A:ROR A:ROR A:ROR A:AND #&C0:EOR #&80:ORA tmp:STA &FC45
3330 JMP SetCommand
3340 ]NEXT:ENDPROC