10 REM > HDInit/src 1.16 J.G.Harston
   20 REM Initialise IDE hard drive
   30 REM v1.02 - Drives 0-7 all allowed
   40 REM v1.03 - Drive reversably initialised, selects drive 0
   50 REM v1.04 - Allows drive size to be set explicitly
   60 REM v1.05 - Displays sizes in M as well as K
   70 REM v1.06 - Wipes full root if 'safe' turned off
   80 REM v1.07 - Full drive investigation
   90 REM v1.08 - Partitions
  100 REM v1.09 - New FNsum routine
  110 REM v1.10 - Displays full firmware info and device type
  120 REM v1.11 - Allows ADFS/HADFS partitions
  130 REM v1.12 - Display full info by default, Randomise made safe
  140 REM v1.13 - Attempts to use SCSI call before direct hardware access
  150 REM v1.14 - 4G HADFS partitions
  160 REM v1.15 - ADFS partition size selectable
  170 REM v1.16 - Detects ADFS device hardware and revision
  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:REM IFhadfs%:fs%=16
  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 REM IFadfs%:IF(hd%AND6)=4:PRINT" (Floppy ";hd%-4;")";
  720 REM IFadfs%:IF(hd%AND6)=6:PRINT" (Unknown ";hd%-6;")";
  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:REM hdsz%=(256*info%?&6D+info%?&6C)*info%?&6E*info%?&70
 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:REM Get today's date
 1430 FORA%=0TO6:X%?A%=(X%?A%AND15)+10*(X%?A%DIV16):NEXT:REM BCD->BIN
 1440 IF?X%<81:?X%=19+?X% ELSE ?X%=?X%-81:REM Offset from 1981
 1450 today%=(?X%DIV16)+8*X%?2+256*X%?1+4096*(?X%AND15)
 1460 start%=2:IFpart%:start%=7:IFsize%>&FFFF:start%=part%:REM Start free space after ADFS
 1470 dskID%=RND(65535):IFsize%=&10000:size%=&FFFF
 1480 :
 1490 PROCclear                      :REM Clear sector
 1500 IFsafe%:PROCread(&46,hd%)      :REM Read sector &46
 1510 $mem%="IDEDISK"+STR$~hd%+"        ":REM Disk title
 1520 $(mem%+16)=CHR$0+"(C)JGH"+CHR$0:REM Disk ID string
 1530 mem%!24=dskID%                 :REM Disk ID number
 1540 mem%!26=today%                 :REM Disk format date
 1550 mem%!28=size%                  :REM Disk size and flags
 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        :REM Empty free space map
 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%)             :REM Write sector &46
 1620 :
 1630 PROCclear                      :REM Clear sector
 1640 IFsafe%:PROCread(&47,hd%)      :REM Read sector &47
 1650 $mem%="$         "             :REM Directory name
 1660 mem%!10=&47:mem%!14=0          :REM Parent directory
 1670 mem%!16=dskID%:mem%!20=0       :REM Disk ID number
 1680 IFsize%>&FFFF:mem%!10=0:mem%!24=0:mem%!28=&47:mem%?12=&80:REM BigDir
 1690 PROCwrite(&47,hd%)             :REM Write sector &47
 1700 :
 1710 PROCclear                      :REM Clear sector
 1720 IFNOTsafe%:PROCwrite(&48,hd%)  :REM Write sector &48
 1730 IFNOTsafe%:PROCwrite(&49,hd%)  :REM Write sector &49
 1740 :
 1750 PRINT"Drive ";~hd%;" initialised to ";FNsz(size%):PROCdelay(200)
 1760 ENDPROC
 1770 :
 1780 DEFPROCInitADFS
 1790 PROCclear                 :REM Clear sector
 1800 mem%!0=7                  :REM Start of first free space
 1810 IFpart%:mem%!3=&4A        :REM Start of second free space
 1820 mem%!252=size%            :REM Total number of sectors on disk
 1830 mem%?255=0:mem%?255=FNsum :REM FSM checksum
 1840 PROCwrite(0,hd%)          :REM Write sector 0
 1850 :
 1860 PROCclear                 :REM Clear sector
 1870 mem%!0=size%-7                      :REM Length of first free space
 1880 IFpart%:mem%!0=&3F:mem%!3=size%-&4A :REM Length of second free space
 1890 mem%!251=RND(65535)       :REM Disk ID
 1900 mem%?253=0                :REM Disk boot option
 1910 mem%?254=3-3*(part%<>0)   :REM End of free space map
 1920 mem%?255=1:mem%?255=FNsum :REM FSM checksum
 1930 PROCwrite(1,hd%)          :REM Write sector 1
 1940 :
 1950 FORS%=2TO6:PROCclear                       :REM Clear sector
 1960   IFsafe%:PROCread(S%,hd%):PROCclrdir(S%*4-3):REM Read sector, clear entries
 1970   IFS%=2:$mem%=CHR$0+"Hugo":mem%?5=0         :REM Directory identifier
 1980   IFS%=6:$(mem%+204)="$":mem%!214=2          :REM Dir name, parent
 1990   IFS%=6:$(mem%+217)="$":$(mem%+227)=""      :REM Directory title
 2000   IFS%=6:$(mem%+250)=CHR$0+"Hugo":mem%?255=0 :REM Directory identifier
 2010 PROCwrite(S%,hd%):NEXT                     :REM Write sector
 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 REM &80/&81 = addr
 2560 REM &82/&83 = addr.hi
 2570 REM &84     = drv (0,4-B,&80)
 2580 REM &85     = drv-sect.hi (0-3)
 2590 REM &86     =     sect.mid
 2600 REM &87     =     sect.lo
 2610 REM &88     = num
 2620 REM &89     = data width
 2630 REM &8A     = cmd
 2640 REM &8B     = tmp
 2650 REM &8E/F   =>control block
 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