> HDBIOS/src v1.24 . Patch BBC BIOS to add hard drive support K Patched BIOS can be stored on system tracks with 'PUTBIOS HDBIOS.SYS' G( Drive C image file and filing system configurable in head of BIOS I2ver$="1.20": Warm Boot checks *fx63 for a CCP before calling LoadCCP 4<ver$="1.21": Slight rearrangement of code areas NFver$="1.22": Uses 512-byte block access, selects DFS during floppy access TPver$="1.23": Tests for presence of Drive C, selects and boots from C if present gZver$="1.24": DISKACC passed to OSGBPB as DirRead reads 10 sectors instead of 2, moved DISKSP d: Kn We can't use MOVCPM as the Client ROM /always/ jumps to BIOS at &EA00 9x So we have to find space for buffers in high memory :  Read BIOS into buffer: 8 mcode% &8FF: A%=0 &7FF 4:mcode%!A%=A%!&EA00: :  BIOS variable locations: 3currDRIVE=&F1E1:currTRACK=&F1E2:currBLOCK=&F1E3 :  MOS locations: +DISKACC=&FFA4:LoadCCP=&FFA7:PRHEX=&FFAA 7OSFIND=&FFCE:OSGBPB=&FFD1:OSARGS=&FFDA:OSBYTE=&FFF4 : Lݤchk(A%): P%>A%: P:"**** WARNING: CODE OVERFLOW AT &";~A%: =P*3+4 -ݤorg(A%):P%=A%:O%=P%-&EA00+mcode%:=P*3+4  P=0 1:[OPT org(&EA00) ; Move disk definitions ; --------------------- "OPT org(&EA33) ,: F6.DriveCfs:B 8 ; Drive C filing system (8=ADFS) 6@.DriveC :M "$.CPMDISK":B 13 ; Drive C filename JM "*******" T: ^.DPH_Base 9hW &0000:W &0000:W &0000:W &0000 ; DPH for drive A -rW &F1F2:W DPB_Acorn400k:W csvA:W alvA |: 9W &0000:W &0000:W &0000:W &0000 ; DPH for drive B -W &F1F2:W DPB_Acorn400k:W csvB:W alvB : .DPH_C 9W &0000:W &0000:W &0000:W &0000 ; DPH for drive C @W &F1F2:W DPB_HardDrive:W &000:W &0000 ; Set on ColdBoot ; 1.DPB_Acorn400k ; DPB for AcornCPM 400K disk /W &0014 ; SPT=20 Sectors Per Track )B &04 ; BSH=4 Block Shift (B &0F ; BLM=15 Block Mask )B &01 ; EXM=1 Extent Mask -W &00C3 ; DSM=195 Disk Sector Max <W &007F ; DRM=127 Maximum directory entry number 0B &C0 ; AL0=&C0 Directory occupies 0B &00 ; AL1=&00 first two blocks ?&W &0020 ; CKS=32 Size of directory checksum vector H0W &0003 ; =3 Reserved tracks before logical start of disk 1:; Total disk size is 128*(BLM+1)*(DSM+1)=392K @D; Physical disk size is 128*SPT*+128*(BLM+1)*(DSM+1)=399.5K N; ,X.DPB_HardDrive ; DPB for 8M Hard Drive /bW &0100 ; SPT=256 Sectors Per Track )lB &05 ; BSH=5 Block Shift (vB &1F ; BLM=31 Block Mask )B &01 ; EXM=1 Extent Mask -W &07FF ; DSM=2047 Disk Sector Max <W &03FF ; DRM=1023 Maximum directory entry number 0B &FF ; AL0=&FF Directory occupies 2B &00 ; AL1=&00 first eight blocks ?W &0000 ; CKS=0 Size of directory checksum vector HW &0000 ; =0 Reserved tracks before logical start of disk 2; Total disk size is 128*(BLM+1)*(DSM+1)=8192K ?; Physical disk size is 128*SPT*+128*(BLM+1)*(DSM+1)=8192K ; 'OPT chk(&EA93) ; Check not overrun ; ; Hook into existing code ; ----------------------- OPT org(&EB0D):LD (LF167),A OPT org(&EB24):LD HL,LF167  OPT org(&EB46):LD HL,LF167 !*OPT org(&EBE3):LD (LF168),HL !4OPT org(&EC69):LD HL,(LF168) >OPT org(&EA00):JP ColdBoot !HOPT org(&EA1B):JP SelectDisk &ROPT org(&EA30):JP SectorTranslate \OPT org(&ECD7): GetCCP %fOPT org(&EDAB):LD (DISKSP0+1),SP %pOPT org(&EDC6):LD (DISKSP0+1),SP (zOPT org(&EEB5):.DISKSP0:LD SP,0:NOP OPT org(&EF4E): DiskPatch ; ; Modify WarmBoot ; --------------- =OPT org(&ECE6) ; &ECE6-&ED31 - 75 bytes MLD A,(4): SelectTest:JP &D403 ; Enter CCP with validated user+drive in C ; ; Add extra code ; -------------- .SelectTest PUSH AF ; 15:LD C,A: SelectDisk ; Try to select this drive 6POP AF:LD C,A ; Get drive back DLD A,H: L:RET NZ ; If valid, return C=user+drive BLD C,A:RET ; If not valid, return C=0+0 ; >$.DiskPatch ; &ECFD-&ED31 - 53 bytes .; (HL+1)=address (8; (HL+6)=&4B for write, &53 for read B; (HL+9)=num &20 L; currDRIVE=drive V; currTRACK=track `; currBLOCK=block .j; all registers trashable, return A=result t; 9~LD A,(currDRIVE) ; Get current drive DCP 2:JR NC,HDAccess ; Jump to do hard drive access BPUSH HL:LD A,4: EnsureFS ; Ensure DFS selected if needed IPOP HL:PUSH AF: DISKACC ; Save previous FS, do the disk access CPOP HL:PUSH AF:LD A,H ; Get oldFS back, save result Q RestoreFS:POP AF:RET ; Reselect oldFS if needed, return with result ; 0.HDAccess ; 27 bytes \LD DE,GBPBchn:LD BC,9:LDIR ; Copy address to GBPBaddr, BC now &0000, HL=>num 32 5LD (GBPBnum+2),BC ; num=&0000xxxx +LD A,(HL): 31:LD B,A ; B=num /DEC HL:DEC HL:DEC HL ; HL=>cmd PRLD:ADD A,A:SUB 7 ; &4B/&53 -> &04/&05 -> &08/&0A -> &01/&03 JP DiskPatch2 $ OPT chk(&ED32):M &ED32-P%,0) ; ; Modify SelectDisk (; ----------------- 2OPT org(&ED8F) <.SelectDisk ?FLD A,C:CP 2: Z,DiskTest ; Test if hard drive present GPLD HL,0:RET NC ; Exit with HL=0 if no hard drive HZLD BC,DPH_Base ; Point to Drive Parameter Headers d; n; Move sector interleave x; ---------------------- OPT org(&EFAF) LD HL,&EFCB OPT org(&EFCB) /B 0:B 4:B 8:B 2:B 6 ; Interleave table ; %; Continue to look for hard drive %; ------------------------------- D.DiskTest ; &EFD0-&EFFE - 47 spare bytes @XOR A ; Prepare 'no disk access' .DiskPatch2 RLD (GBPBnum+0),BC:LD B,A ; num=&0000nn00, B=0 test, =1 write, =3 read HLD DE,(currTRACK):LD D,C ; D=0, E=TRACK, B=cmd, C=0, HL=xxx >LD A,(currBLOCK):ADD A,A:ADD A,A ; A=BLOCK moved up to b7 bSRL E:RRA:LD H,A:LD L,C ; DE=<0-TRACK>, A= -> DE=&00, HL=<00> fINC H:JR NZ,P%+3:INC DE ; DEHL=<00000000>+256 - index into MyZ80 disk image 'LD (GBPBptr+0),HL:LD (GBPBptr+2),DE "; J,LD A,(DriveCfs): EnsureFS ; Select DriveC filing system if needed h6PUSH AF:LD C,&FF ; Save previous FS, prepare C=&FF for not found (no drive present) @LD HL,DriveC:JP DiskPatch3 $JOPT chk(&EFFF):M &EFFF-P%,0) T; ^; Trim BootFiles messages h; ----------------------- >rOPT org(&F08E):LD C,14 ; Change to 'Select Disk' !|OPT org(&F093):LD DE,strBOOT !OPT org(&F0B3):LD HL,cmdBOOT !OPT org(&F0BF):LD DE,subBOOT #OPT org(&F0C9):LD DE,strSUBMIT ,OPT org(&F0EC):LD HL,cmdSUBMIT:JR &F0B6 ';; &EC8E:;M "No SUBMIT.COM":;B 0 RET #.cmdBOOT :B 4:M "BOOT":B 0 *.cmdSUBMIT:B 11:M "SUBMIT BOOT":B 0 *.strSUBMIT:B 0:M "SUBMIT COM":B 0 *.subBOOT :B 0:M "BOOT SUB":B 0 *.strBOOT :B 0:M "BOOT COM":B 0 ; ; Updated ColdBoot ; ---------------- Q.ColdBoot ; 23 bytes will be overwritten by BootFiles 1M 20,0) ; Metadata for BOOT.COM :&.LF167:B &00 ; CONST countdown flag 30.LF168:W &0000 ; , for PRNST :; MDOPT org(ColdBoot) ; Put once-used code on top of variables NNLD SP,&F4E0: &ED32 ; Get 8-bit checksum of BDOS code in memory ;XLD (&ED43),A ; Store this checksum Hb &ED44: &EA93 ; Initialise vectors, initialise console ElLD HL,(&EA04):LD (&EA01),HL ; ColdBoot now goes to WarmBoot LvLD HL,alvC_Z80Tube+256 ; DriveC allocation vector for Z80Tube ; ; &F144-&F1DB - 152 bytes ; ----------------------- BLD A,(HL) ; Check for Z80Tube at &F800 ?DEC H:CP &C3:JR Z,ColdALV ; Use Z80Tube-256 as alvC SLD HL,alvC_CoPro ; DriveC allocation vector for hardware CoPro .ColdALV GLD (DPH_C+14),HL ; Set up DriveC allocation vector : &EC8E ; Print startup message 7B 13:M "Acorn CP/M 2.2 - HDBIOS "+ver$:B 13:B 0 0LD C,13: &DC06 ; Reset disks ELD A,2: SelectTest ; See if drive C present, C=2 or 0 8PUSH BC:LD A,C:LD (4),A ; Set system drive GLD E,C: &F08E ; Check for boot files on this drive > POP BC:JP &D400 ; Enter CCP with C=drive ;  .DiskPatch3 :*LD A,(HL):CP "!" ; Is filename present? 94JR C,NoImageFile ; No image filename ?>LD A,&C0: OSFIND ; Open hard drive image file @H A:JR Z,NoImageFile ; Skip past if no image file KRLD HL,GBPBchn:LD (HL),A:PUSH AF ; Point to control block, set channel Q\LD A,B: A: NZ,OSGBPB ; Save channel, do disk data transfer if nonzero @fPOP HL:XOR A:LD C,A: OSFIND ; Close channel, C=&00 for Ok p.NoImageFile =zPOP AF: RestoreFS ; Reselect oldFS if needed KLD A,B: A:LD A,C:RET NZ ; If disk access done, return A=&00/&FF `CP &FF:LD A,2:RET ; If disk test done, return A=2 (drive C), C=ok, NC=absent ; .RestoreFS 7 A:LD H,A:JR NZ,SelectFS ; A<>&00, select FS .EnsureFS 9 A:RET Z:LD H,A ; Nothing to reselect BXOR A:LD E,A: OSARGS ; A=FS, wantedFS in H preserved NXOR H:RET Z:XOR H ; If currentFS=wantedFS, return with A=0 .SelectFS 6PUSH AF:LD L,18:LD A,143 ; Select FS in H C OSBYTE:POP AF:RET ; Return previous FS or &00 in A ;  .SectorTranslate 6 LD H,B:LD L,C:RET ; No translation  ; $ .GetCCP =. LD A,63: OSBYTE:INC L:RET NZ ; Ask for a CCP with *fx63 =8 JP LoadCCP ; Otherwise, use Z80MOS B ; L ; 5 bytes left over $V OPT chk(&F1DE):M &F1E0-P%,0) ` ; &F1DE=DRIVE j ; &F1DF=TRACK (t ; Final point saved on system tracks ~ ; &F1E0=SECTOR  ; &F1E1=currDRIVE  ; &F1E2=currTRACK  ; &F1E3=currBLOCK  : - M "HDBIOS "+ver$+" (12 Sep 2010) (C)JGH"  :  OPT org(&F1F0) :.dma  OPT org(&F1F2) :.dirbuf OPT org(&F272) :.diskbuf 4 OPT org(&F472) ; ; bottom of disk stack 1 OPT org(&F4E0) :.csvA ; top of disk stack  OPT org(&F500) :.csvB  OPT org(&F520) :.alvA ) OPT org(&F5AE) ; BASIC patch area  OPT org(&F5C6) :.alvB  OPT org(alvB+&19) :.GBPBchn ( OPT org(GBPBchn+1):.GBPBadr 2 OPT org(GBPBchn+5):.GBPBnum < OPT org(GBPBchn+9):.GBPBptr 1F OPT org(&F60E) ; Top of BASIC patch stack %P OPT org(&F800-256):.alvC_Z80Tube #Z OPT org(&FDDE-256):.alvC_CoPro d : n ] x : ' "SAVE HDBIOS.SYS "+~mcode%+"+800"