I recently did an article on the Cromix Boot sector to show how it adapts to the disk type. However, it didn’t. So, here’s the same article again, but with CDOS 2.58 – which does.
The boot sector looks like:
Display of File CDOS0258-8DSDD.DSK 000000: 3E 01 D3 40 38 04 97 08 16 31 1E 7F 21 00 01 01 >..@8....1..!... 000010: 0F 02 7B D3 04 CB 4B 28 15 7A D3 34 79 D3 30 97 ..{...K(.z.4y.0. 000020: 3D 20 FD DB 34 1F 30 FB DB 30 E6 98 20 D2 78 D3 = ..4.0..0.. .x. 000030: 32 7A F6 80 D3 34 0E 33 3E 9C D3 30 DB 34 1F 38 2z...4.3>..0.4.8 000040: 04 ED A2 18 F7 DB 30 CB 67 28 B5 3E 04 95 3E 1A ......0.g(.>..>. 000050: 9C 38 2D 3A FC 00 FE 44 20 02 CB F2 06 01 3A FA .8-:...D .....:. 000060: 00 FE 44 20 04 7B EE 02 5F 0E 5F 18 A5 00 00 00 ..D .{.._._..... 000070: 00 00 00 00 00 00 00 00 4C 47 44 53 44 44 E5 E5 ........LGDSDD..
That is for an 8″ double sided, double density disk.
The single sided, single density equivalent is identical except for most of the last 8 bytes. They look like:
000070: 00 00 00 00 00 00 00 00 E5 E5 E5 E5 E5 E5 E5 E5 ................
E5 is what init or format writes as empty sectors when it creates a disk. It is also what marks an empty or deleted File Control Block in a CP/M or CDOS directory. On early disks where the bootstrap program was less than 128 bytes long, E5 was what was left at the end of the boot sector. In our case, for the 8″ SSSD disk, they signify “not LGDSDD” and the bootstrap does change its behaviour. Here’s the source code:
; z80dasm 1.1.2 ; command line: z80dasm -a -l -g 0x80 bootdsdd.bin USE_RDOS EQU 0 org 00080h l0080h: ld a,001h ; disable RDOS out (040h),a IFEQ USE_RDOS,1 jr c,l008ah ; if CY use supplied ELSE nop nop ENDIF sub a ; default disk=0 ex af,af' ; save for later ld d,031h ; default cmd=motor+8"+A l008ah: ld e,07fh ; start with side0 ld hl,00100h ; load to 100H ld bc,0020fh ; B=sector 2, C=restore l0092h: ld a,e ; select side out (004h),a bit 1,e ; if we're on 2nd side jr z,l00aeh ; skip changing track (already here) ld a,d ; 31=motor+8"+A (or supplied) out (034h),a ld a,c ; cmd. 0F=restore+verify+slow out (030h),a sub a ; wait 256 l00a0h: dec a jr nz,l00a0h l00a3h: in a,(034h) ; wait for end of job, EOJ rra jr nc,l00a3h in a,(030h) ; check result and 098h ; notRdy+notFound+busy jr nz,l0080h ; problem. try again. l00aeh: ld a,b ; set sector (2 at start) out (032h),a ld a,d ; motor+8"+A (or supplied) or 080h ; turn on autowait out (034h),a ld c,033h ; 33H is the disk data port ld a,09ch ; read records, head load out (030h),a ; send the command l00bch: in a,(034h) ; check for EOJ rra jr c,l00c5h ; have read all sectors to track end ini ; read byte to HL++ jr l00bch ; loop until EOJ l00c5h: in a,(030h) ; check result bit 4,a ; the "not found" bit jr z,l0080h ; error. try again ; extra ; ; if HL > 01A04H, run loaded prog ; ie if we've loaded all of the program, run it. ld a,004h sub l ld a,01ah sbc a,h jr c,0100H ; where we loaded the program ; There's more to load. ld a,(ddens) ; are we a "DD" disk? cp 'D' jr nz,l00dch ; no. skip this set 6,d ; yes. turn on DD (31->71) l00dch: ld b,001h ; nxt track. start sector=1 ld a,(dsides) ; are we a "DS" disk? cp 'D' jr nz,l00e9h ; no. skip this ld a,e ; toggle the side bit xor 002h ; eg 7F->7D->7F... ld e,a l00e9h: ld c,05fh ; cmd=step in (was restore) jr l0092h ; read next track l00edh: nop nop ... nop nop dsiz: db 'LG' ;00f8 dsides: db 'DS' ;00fa ddens: db 'DD' ;00fc db 0e5h, 0e5h ;00fe end
It is longer than the cromix one (less 00H bytes towards the end).
It still checks the CY flag at the start and uses whatever happens to be in D and A’ if it is set. (In this example, you can see conditional code where I patch out the “JR C,…” line if I’m creating something that doesn’t USE_RDOS.)
It is mostly the same as the cromix one, up to the line labelled “; extra”. At that point, the rest of track 0 has been loaded into memory (at 100H, just like cromix). Cromix just does a “JP 0100H” at that point. We have more to load and that’s where the disk type becomes important.
From here on, if we’re a double density disk, we switch to double density. This means 512 byte sectors after track 0 side 0.
If we do have sides, we swap to the other side of the current track. We also replace the restore command in the C register with a “step in” one instead.
The “mostly the same as the cromix one” I mentioned above is because we also have some extra lines just after “l0092h:” that checks which side of the disk we are on. If we’re single sided, we’re only ever on side 0 and every time through the “l0092h:” loop, we restore to track 0 or step in to the next track. However, if we’re a “DS” disk, and now on the second side, we skip changing tracks as we’re just on the other side of the current one.
It is pretty neat.
The use of “read sectors” instead of “read sector” means they don’t need an extra loop that works its way through each sector (and needs to know how many sectors per track).
The SCF override is still annoying as you can’t boot with just the boot sector; but their reasoning makes sense.
The disk size (‘LG’ in our case) is ignored. Given that you need different commands to select an 8″ or a 5″ drive, it is a pity that they didn’t squeeze that in too. It would have meant that, aside from the disk type in bytes 120-127, the boot sector of all floppies could have been the same. As it is, copying the boot sector from 5″ to 8″ or vice versa with WRTSYS will seem to work but give an unbootable result.
One of the other “gotcha”s is copying the full boot sector from one disk type to another. This will put the wrong type in 120-127 and the boot sector will try to change (or keep) sides and/or change density (or not) on a disk that needs to keep (or change) sides and/or keep (or change) density. The matching versions of the Cromemco tools will understand and adjust for this. You’ll need to manually check and adjust if you use anything else (or only copy system tracks from matching disk types).
I hope this clears up the issues.
This is part of the CP/M topic.