The CDOS 2.58 Boot Sector

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.

It's only fair to share...Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUponDigg thisPin on PinterestEmail this to someone

Leave a Reply

Your email address will not be published. Required fields are marked *