[WIP] DOS 3.2 support

This commit is contained in:
4am 2017-08-15 11:31:36 -04:00
parent 642db7e409
commit 2dcd475e08
9 changed files with 552 additions and 242 deletions

View File

@ -138,6 +138,16 @@ IDBootloader
bcs +
jmp foundea
;
; Try to identify hybrid 16-/13-sector bootloader on
; DOS 3.2 disks.
; Exit via custom trace function if found.
;
+ jsr IDDOS32
bcs +
lda #s_dos32b0
jsr PrintByID
jmp TraceDOS32
;
; Try to detect whether there is code in the boot sector
; that loads 4-and-4-encoded data. This is an early escape
; hatch for disks that are guaranteed to fail later anyway.

238
src/id/trace.a Executable file → Normal file
View File

@ -1,200 +1,38 @@
;-------------------------------
; TraceDOS33
; set up 1st-level boot trace on
; a DOS 3.3-shaped bootloader
;-------------------------------
!zone {
TraceDOS33
;
; Before we trace through the drive firmware (which --
; at least on some machines -- will loop forever looking
; for each sector), we do a pre-check to ensure that all
; the sectors we're about to trace are actually readable.
;
lda #$00
sta gTrack
lda #$09
sta gSector
lda #$00
sta $b991
precheck
ldy #<gRWTSParams
lda #>gRWTSParams
jsr $BD00
bcc +
jmp FatalError
+
dec gSector
bne precheck
;
; pre-check passed, do the trace
;
lda #<TraceDOS33b
ldx #>TraceDOS33b
jmp Trace
;-------------------------------
; TraceDOS33b
; set up 2nd boot trace at $084A
;-------------------------------
TraceDOS33b
lda #$4C
sta $084A
lda #<TraceDOS33c
sta $084B
lda #>TraceDOS33c
sta $084C
lda #$EA
ldy #9
.noppatch
sta $83E,Y ; disable calls to
dey ; TEXt/PR0/IN0
bne .noppatch ; including "Grafboot"
jmp $0801
TraceDOS33c
lda $08FE ; 2nd-level trace callback is here
sta .x6+1
clc
adc #$02
_Inspect1a
sta .x1+1
sta .x2+1
sta .x7+1
sta b4bbmodify+2
sta b4bbmodify2+2
clc
adc #$06
sta b4bbcompare+1
tax
dex
stx .x5+1
dex
stx .x3+1
stx .x4+1
stx callrwts+2
jsr ProtectedDOS ; check for a specific (encrypted)
; bootloader called "Protected DOS"
bcs .notprotdos
jmp ADStyle
.notprotdos
lda callrwts+2
ldx #$00 ; check for "STY $48;STA $49"
ldy #$04 ; at RWTS entry point
jsr CompareMemory ; (e.g. $BD00 or $3D00)
!byte $84,$48,$85,$49
bcc .x1
jmp UseUniversal
.x1 lda #$FF ; check for "SEC;RTS" at $B942
ldx #$42
ldy #$02
jsr CompareMemory
!byte $38,$60
bcc .x2
jmp UseUniversal
.x2 lda #$FF ; check for "LDA $C08C,X" at $B94F
ldx #$4F
ldy #$03
jsr CompareMemory
!byte $BD,$8C,$C0
bcc .x3
jmp UseUniversal
.x3 lda #$FF ; check for "JSR $xx00" at $BDB9
ldx #$B9
ldy #$02
jsr CompareMemory
!byte $20,00
bcc .x5
;
; Check for RWTS variant that has extra code before
; JSR $B800 e.g. Verb Viper (DLM), Advanced Analogies (Hartley)
;
.x4 lda #$FF ; check for "JSR $xx00" at $BDC5
ldx #$C5
ldy #$02
jsr CompareMemory
!byte $20,00
bcc .x5
jmp UseUniversal ; give up tracing; this RWTS is unsupported
;
; Check for RWTS variant that uses non-standard address for slot
; LDX $1FE8 e.g. Pinball Construction Set (1983)
; we don't like that one
;
.x5 lda #$FF ; check for "LDX $1FE8" at $BE43
ldx #$43
ldy #$03
jsr CompareMemory
!byte $AE,$E8,$1F
bcs .x6
jmp UseUniversal ; give up tracing; this RWTS is unsupported
;
; Check for Milliken protection routine in late-stage boot
; (affects readable/ignoreable sector map, so must ID now)
;
.x6 lda #$FF ; check for "JMP $9B03" at $B747
ldx #$47
ldy #$03
jsr CompareMemory
!byte $4C,$03,$9B
bcs .x7
jsr IDMilliken
bcs .x7
lda #s_milliken
jsr PrintByID
lda #$80
sta T02S05
;
; Check for Adventure International RWTS (sets flag for patcher)
;
.x7 lda #$FF ; check for code at $B936
ldx #$36
ldy #$0A
jsr CompareMemory
!byte $EA,$EA,$EA; NOP/NOP/NOP
!byte $BD,$8C,$C0; LDA $C08C,X
!byte $10,$FB ; BPL -$FB
!byte $C9,$00 ; CMP #$00
bcs +
lda #TRUE
sta gAdventureInternational
+ jmp ADStyle ; use this RWTS to read the disk
;-------------------------------
; Trace
; common code for all boot tracers
; in: A = lo byte of callback
; X = hi byte of callback
; never returns
;-------------------------------
Trace
pha
txa
pha
lda #$C6
ldx #$B6
ldy #$01
jsr CopyMemory
pla
tax
pla
ldy $B6F8
cpy #$4C
bne .maybe_gs
sty $B6F8 ; JMP
sta $B6F9 ; lo byte of callback
stx $B6FA ; hi byte of callback
jmp $B600
.maybe_gs
ldy $B6FB
cpy #$4C
bne .unknowndrive
sty $B6FB ; JMP
sta $B6FC ; lo byte of callback
stx $B6FD ; hi byte of callback
jmp $B600
.unknowndrive
lda #s_canttrace
jsr PrintByID
jmp UseUniversal
}
;-------------------------------
; Trace
; common code for all boot tracers
; in: A = lo byte of callback
; X = hi byte of callback
; never returns (exits via callback or UseUniversal)
;-------------------------------
!zone {
Trace
pha
txa
pha
lda #$C6
ldx #$B6
ldy #$01
jsr CopyMemory
pla
tax
pla
ldy $B6F8
cpy #$4C
bne +
sty $B6F8 ; JMP for Disk II controller
sta $B6F9 ; lo byte of callback
stx $B6FA ; hi byte of callback
jmp $B600
+ ldy $B6FB
cpy #$4C
bne +
sty $B6FB ; JMP for IIgs smart controller
sta $B6FC ; lo byte of callback
stx $B6FD ; hi byte of callback
jmp $B600
+ lda #s_canttrace ; unknown disk controller
jsr PrintByID
jmp UseUniversal
}

167
src/id/trace32.a Normal file
View File

@ -0,0 +1,167 @@
; DOS 3.2 boot tracer
; for DOS 3.2 disks with a 3.2/3.3 hybrid bootloader
; that boots automatically on 16-sector drives
; e.g. many early disks from Edu-Ware, Hartley
;-------------------------------
; IDDOS32
; returns C clear if 3.2/3.3 bootloader detected in T00,S00
;-------------------------------
!zone {
IDDOS32
lda #$00
ldx #$00
ldy #$0F
jsr compare
!byte $01
!byte $A0,$0F ; LDY #$0F
!byte $B9,$00,$08; LDA $0800,Y
!byte $99,$00,$02; STA $0200,Y
!byte $C8 ; INY
!byte $D0,$F7 ; BNE -
!byte $4C,$0F,$02; JMP $020F
bcs .exit
ldx #$33
ldy #$08
jsr compare
!byte $A6,$2B ; LDX $2B
!byte $20,$5D,$02; JSR $025D
!byte $4C,$D1,$02; JMP $02D1
bcs .exit
ldx #$F4
ldy #$08
jsr compare
!byte $CC,$00,$03; CPY $0300
!byte $D0,$03 ; BNE +
!byte $4C,$3B,$02; JMP $023B
bcs .exit
ldx #$45
ldy #$03
jsr compare
!byte $4C,$01,$03; JMP $0301
.exit rts
}
;-------------------------------
; TraceDOS32
; set up boot trace to capture 13-sector RWTS
;-------------------------------
!zone {
TraceDOS32
lda #<TraceDOS32b
ldx #>TraceDOS32b
jmp Trace
TraceDOS32b
lda #<TraceDOS32c
sta $0846
lda #>TraceDOS32c
sta $0847
jmp $0801
TraceDOS32c
lda #$03
ldx #$0D
ldy #$39
jsr CompareMemory
!byte $A6,$2B
!byte $A9,$09
!byte $85,$27
!byte $AD,$CC,$03
!byte $85,$41
!byte $84,$40
!byte $8A
!byte $4A
!byte $4A
!byte $4A
!byte $4A
!byte $A9,$02
!byte $85,$3F
!byte $A9,$5D
!byte $85,$3E
!byte $20,$43,$03
!byte $20,$46,$03
!byte $A5,$3D
!byte $4D,$FF,$03
!byte $F0,$06
!byte $E6,$41
!byte $E6,$3D
!byte $D0,$ED
!byte $85,$3E
!byte $AD,$CC,$03
!byte $85,$3F
!byte $E6,$3F
!byte $6C,$3E,$00
bcs .fail
lda $03CC
cmp #$B6
beq +
cmp #$36
bne .fail
+
; set up RWTS entry point
clc
adc #$07
sta callrwts+2
lda #$00
sta callrwts+1
; set up final trace
lda #$4C
sta $033A
lda #<TraceDOS32d
sta $033B
lda #>TraceDOS32d
sta $033C
ldy $0300
jmp $0301
TraceDOS32d
lda callrwts+2
ldx #$00 ; check for "STY $48;STA $49"
ldy #$04 ; at RWTS entry point
jsr CompareMemory ; (e.g. $BD00 or $3D00)
!byte $84,$48,$85,$49
bcs .fail
; skip sectors $0D, $0E, and $0F on all tracks
; since this is a 13-sector disk
lda #<sectormap
sta .C+1
lda #>sectormap
sta .C+2
lda #$00
ldx #$22
.A ldy #$0F
.B cpy #$03
bcs .D
.C sta $FFFF
.D inc .C+1
bne +
inc .C+2
+ dey
bpl .B
dex
bpl .A
; skip T00,S01-S0A
; since we're going to construct our own bootloader later
ldy #$0A
- sta T00,y
dey
bne -
; read the rest of the disk with the original RWTS
jmp ADStyle
; something did not match, not comfortable tracing,
; but we know enough to know that the universal RWTS won't work,
; so we're done
.fail jmp FatalError
}

165
src/id/trace33.a Executable file
View File

@ -0,0 +1,165 @@
;-------------------------------
; TraceDOS33
; set up 1st-level boot trace on
; a DOS 3.3-shaped bootloader
;-------------------------------
!zone {
TraceDOS33
;
; Before we trace through the drive firmware (which --
; at least on some machines -- will loop forever looking
; for each sector), we do a pre-check to ensure that all
; the sectors we're about to trace are actually readable.
;
lda #$00
sta gTrack
lda #$09
sta gSector
lda #$00
sta $b991
precheck
ldy #<gRWTSParams
lda #>gRWTSParams
jsr $BD00
bcc +
jmp FatalError
+
dec gSector
bne precheck
;
; pre-check passed, do the trace
;
lda #<TraceDOS33b
ldx #>TraceDOS33b
jmp Trace
;-------------------------------
; TraceDOS33b
; set up 2nd boot trace at $084A
;-------------------------------
TraceDOS33b
lda #$4C
sta $084A
lda #<TraceDOS33c
sta $084B
lda #>TraceDOS33c
sta $084C
lda #$EA
ldy #9
.noppatch
sta $83E,Y ; disable calls to
dey ; TEXt/PR0/IN0
bne .noppatch ; including "Grafboot"
jmp $0801
TraceDOS33c
lda $08FE ; 2nd-level trace callback is here
sta .x6+1
clc
adc #$02
_Inspect1a
sta .x1+1
sta .x2+1
sta .x7+1
sta b4bbmodify+2
sta b4bbmodify2+2
clc
adc #$06
sta b4bbcompare+1
tax
dex
stx .x5+1
dex
stx .x3+1
stx .x4+1
stx callrwts+2
jsr ProtectedDOS ; check for a specific (encrypted)
; bootloader called "Protected DOS"
bcs .notprotdos
jmp ADStyle
.notprotdos
lda callrwts+2
ldx #$00 ; check for "STY $48;STA $49"
ldy #$04 ; at RWTS entry point
jsr CompareMemory ; (e.g. $BD00 or $3D00)
!byte $84,$48,$85,$49
bcc .x1
jmp UseUniversal
.x1 lda #$FF ; check for "SEC;RTS" at $B942
ldx #$42
ldy #$02
jsr CompareMemory
!byte $38,$60
bcc .x2
jmp UseUniversal
.x2 lda #$FF ; check for "LDA $C08C,X" at $B94F
ldx #$4F
ldy #$03
jsr CompareMemory
!byte $BD,$8C,$C0
bcc .x3
jmp UseUniversal
.x3 lda #$FF ; check for "JSR $xx00" at $BDB9
ldx #$B9
ldy #$02
jsr CompareMemory
!byte $20,00
bcc .x5
;
; Check for RWTS variant that has extra code before
; JSR $B800 e.g. Verb Viper (DLM), Advanced Analogies (Hartley)
;
.x4 lda #$FF ; check for "JSR $xx00" at $BDC5
ldx #$C5
ldy #$02
jsr CompareMemory
!byte $20,00
bcc .x5
jmp UseUniversal ; give up tracing; this RWTS is unsupported
;
; Check for RWTS variant that uses non-standard address for slot
; LDX $1FE8 e.g. Pinball Construction Set (1983)
; we don't like that one
;
.x5 lda #$FF ; check for "LDX $1FE8" at $BE43
ldx #$43
ldy #$03
jsr CompareMemory
!byte $AE,$E8,$1F
bcs .x6
jmp UseUniversal ; give up tracing; this RWTS is unsupported
;
; Check for Milliken protection routine in late-stage boot
; (affects readable/ignoreable sector map, so must ID now)
;
.x6 lda #$FF ; check for "JMP $9B03" at $B747
ldx #$47
ldy #$03
jsr CompareMemory
!byte $4C,$03,$9B
bcs .x7
jsr IDMilliken
bcs .x7
lda #s_milliken
jsr PrintByID
lda #$80
sta T02S05
;
; Check for Adventure International RWTS (sets flag for patcher)
;
.x7 lda #$FF ; check for code at $B936
ldx #$36
ldy #$0A
jsr CompareMemory
!byte $EA,$EA,$EA; NOP/NOP/NOP
!byte $BD,$8C,$C0; LDA $C08C,X
!byte $10,$FB ; BPL -$FB
!byte $C9,$00 ; CMP #$00
bcs +
lda #TRUE
sta gAdventureInternational
;
; good to go
;
+ jmp ADStyle ; use this RWTS to read the disk
}

View File

@ -1,7 +1,7 @@
; "Special Delivery" boot tracer
; for DOS 3.3P disks
; e.g. Ernie's Quiz, Elite
;
;-------------------------------
; IDSpecDel
; returns C clear if "Special Delivery" bootloader
@ -135,10 +135,6 @@ SDsuccess
; but we should clear the rest of T00 so we're not
; writing garbage to disk on unused sectors
lda #$10
ldx #$00
ldy #$01
jsr ClearMemory
lda #$15
ldx #$00
ldy #$06
@ -146,12 +142,9 @@ SDsuccess
; copy Standard Delivery bootloader into place for T00,S00
ldy #$7E ; _SDboot0-SDboot0, but set here
; manually to work around Merlin bug
sdcopy lda SDboot0,y
sta $1000,y
dey
bpl sdcopy
lda #<SD_DOS33p
ldx #>SD_DOS33p
jsr ConstructStandardDelivery
; now manually write out track 0 with Standard Delivery
; bootloader
@ -219,26 +212,3 @@ skipsectors
lda #$03
sta gLastTrack
jmp ADStyle
; Standard Delivery bootloader with DOS 3.3P support
; https://github.com/peterferrie/standard-delivery/
; rev. a5b839d7d0fa21b0ff3a7776d9f6c9750b09ae10 of 2016-11-29
;
SDboot0
!byte $01,$a8,$ee,$06,$08,$ad,$4e,$08
!byte $c9,$c0,$f0,$40,$85,$27,$c8,$c0
!byte $10,$90,$09,$f0,$05,$20,$2f,$08
!byte $a8,$2c,$a0,$01,$84,$3d,$c8,$a5
!byte $27,$f0,$df,$8a,$4a,$4a,$4a,$4a
!byte $09,$c0,$48,$a9,$5b,$48,$60,$e6
!byte $41,$06,$40,$20,$37,$08,$18,$20
!byte $3c,$08,$e6,$40,$a5,$40,$29,$03
!byte $2a,$05,$2b,$a8,$b9,$80,$c0,$a9
!byte $30,$4c,$a8,$fc,$4c,$b3,$10
!byte $1E,$1D,$1C,$1B,$00,$00,$00,$00
!byte $00,$00,$13,$12,$11,$10,$1F,$20
!byte $2E,$2D,$2C,$2B,$2A,$29,$28,$27
!byte $26,$25,$24,$23,$22,$21,$2F,$30
!byte $3E,$3D,$3C,$3B,$3A,$39,$38,$37
!byte $36,$35,$34,$33,$32,$31,$3F,$C0
_SDboot0

View File

@ -95,7 +95,7 @@ flag = $FF ; byte
}
; Application constants (not zero addresses)
RELBASE = $5A00 ; address to move Passport code
RELBASE = $5900 ; address to move Passport code
; so that it's out of the way
LOWPOINT = $4300 ; lowest available address for code
BASEPAGE = $10 ; Special Delivery tracer assumes
@ -140,16 +140,18 @@ FirstMover
!source "analyze.a"
!source "id/inspect0.a"
!source "id/dos33.a"
!source "id/trace.a"
!source "id/trace33.a"
!source "id/trace32.a"
!source "id/trace8b3.a"
!source "id/trace33p.a"
!source "id/dos33.a"
!source "id/prodos.a"
!source "id/pascal.a"
!source "id/jsr8b3.a"
!source "id/trace8b3.a"
!source "id/mecc.a"
!source "id/datasoft.a"
!source "id/protecteddos.a"
!source "id/specdelivery.a"
!source "id/encode44.a"
!source "id/encode53.a"
!source "id/ea.a"
@ -172,6 +174,7 @@ FirstMover
!source "keys.a"
!source "cffa.a"
!source "rwts.a"
!source "standarddelivery.a"
OneTimeSetup
lda $C0E8
@ -696,6 +699,7 @@ _applyToT00
!source "patchers/laureate.a"
!source "patchers/pascalrwts.a"
!source "patchers/micrograms.a"
!source "patchers/dos32.a"
_applyToAll
!source "patchers/universale7.a"
!source "patchers/a6bc95.a" ; gIsPascal only

37
src/patchers/dos32.a Normal file
View File

@ -0,0 +1,37 @@
;-------------------------------
; #DOS32
; construct new bootloader and RWTS
; for converted DOS 3.2 disks
;-------------------------------
!zone {
jsr IDDOS32
bcs .exit
bcc +
.sectors
!byte $00,$00,$02,$02,$02,$02,$02,$02,$02,$02
.offsets
!byte $02,$5C,$0A,$0E,$10,$20,$25,$CA,$CE,$D2
.values
!byte $C7,$B7,$BC,$BC,$00,$BC,$BC,$00,$BC,$BC
+ lda #$09
sta .loop+1
ldx #$B8
ldy #$10
jsr modify
!byte $00,$0D,$0B,$09,$07,$05,$03,$01
!byte $0E,$0C,$0A,$08,$06,$04,$02,$0F
.loop ldy #$d1
lda .values,y
sta .value
lda .sectors,y
ldx .offsets,y
ldy #$01
jsr modify
.value !byte $d1
dec .loop+1
bpl .loop
.exit
}

115
src/standarddelivery.a Normal file
View File

@ -0,0 +1,115 @@
; Standard Delivery bootloader
; https://github.com/peterferrie/standard-delivery/
; rev. a5b839d7d0fa21b0ff3a7776d9f6c9750b09ae10 of 2016-11-29
;-------------------------------
; ConstructStandardDelivery
; in: A = low byte of Standard Delivery parameter table (see below)
; X = high byte of Standard Delivery parameter table
; out: $1000..$10FF replaced with Standard Delivery bootloader
; all registers clobbered
; A,X clobbered
; Y preserved
;-------------------------------
!zone {
ConstructStandardDelivery
sta .A+1
stx .A+2
ldx #$00
txa
- sta $1000,x
inx
bne -
ldx #$4C
- lda .code,x
sta $1000,x
dex
bpl -
- inx
.A lda $FFFF,x
sta $104D,x
cmp #$C0
bne -
rts
.code
!byte $01,$a8,$ee,$06,$08,$ad,$4e,$08
!byte $c9,$c0,$f0,$40,$85,$27,$c8,$c0
!byte $10,$90,$09,$f0,$05,$20,$2f,$08
!byte $a8,$2c,$a0,$01,$84,$3d,$c8,$a5
!byte $27,$f0,$df,$8a,$4a,$4a,$4a,$4a
!byte $09,$c0,$48,$a9,$5b,$48,$60,$e6
!byte $41,$06,$40,$20,$37,$08,$18,$20
!byte $3c,$08,$e6,$40,$a5,$40,$29,$03
!byte $2a,$05,$2b,$a8,$b9,$80,$c0,$a9
!byte $30,$4c,$a8,$fc,$4c
}
;
; Format for Standard Delivery parameter table
;
; - word: entry point of next boot phase (Standard Delivery bootloader will JMP to this address)
; - byte array: high byte of target address of each sector, in the following order
; T00,S0E
; T00,S0D
; T00,S0C
; T00,S0B
; T00,S0A
; T00,S09
; T00,S08
; T00,S07
; T00,S06
; T00,S05
; T00,S04
; T00,S03
; T00,S02
; T00,S01
; T00,S0F
; T01,S00
; T01,S0E
; T01,S0D
; T01,S0C
; T01,S0B
; T01,S0A
; T01,S09
; T01,S08
; T01,S07
; T01,S06
; T01,S05
; T01,S04
; T01,S03
; T01,S02
; T01,S01
; T01,S0F
; &c. (all other tracks are the same order as track 1)
; - byte: $C0 (end of data)
;
; Unused sectors are marked as $00.
;
; Address array does NOT include T00,S00. This sector holds the Standard Delivery
; code and can not be reloaded at another address (unlike DOS 3.3).
; Currently, all parameter tables are the same length (loading T00,S01-T02,S0F),
; but this is not required. Standard Delivery can load an arbitrary number of
; sectors and will move to the next track automatically.
;
SD_DOS33p
!byte $b3,$10 ; exit via JMP $10B3
!byte $1E,$1D,$1C,$1B,$00,$00,$00,$00
!byte $00,$00,$13,$12,$11,$10,$1F,$20
!byte $2E,$2D,$2C,$2B,$2A,$29,$28,$27
!byte $26,$25,$24,$23,$22,$21,$2F,$30
!byte $3E,$3D,$3C,$3B,$3A,$39,$38,$37
!byte $36,$35,$34,$33,$32,$31,$3F
!byte $C0
SD_DOS32
!byte $00,$B7 ; exit via JMP $B700 (TODO: could be $3700)
!byte $00,$00,$9E,$9D,$00,$BF,$BE,$BD
!byte $BC,$BB,$BA,$B9,$B8,$B7,$00,$9F
!byte $00,$00,$AB,$AA,$A9,$A8,$A7,$A6
!byte $A5,$A4,$A3,$A2,$A1,$A0,$00,$AC
!byte $00,$00,$00,$00,$00,$B5,$B4,$B3
!byte $B2,$B1,$B0,$AF,$AE,$AD,$00
!byte $C0

View File

@ -104,7 +104,8 @@ s_cmpbne0 = $55
s_writeram = $56
s_d5timing = $57
s_advint = $58
STRINGCOUNT = $59
s_dos32b0 = $59
STRINGCOUNT = $5A
!zone {
StringTable
@ -143,7 +144,7 @@ StringTable
!word .reset
!word .modify
!word .modifyto
!word .dosboot0
!word .dos33boot0
!word .prodosboot0
!word .pascalboot0
!word .mecc
@ -197,6 +198,7 @@ StringTable
!word .writeram
!word .d5timing
!word .advint
!word .dos32boot0
;
; Text can contain substitution strings, which
; are replaced by current values at runtime. Each
@ -222,7 +224,7 @@ StringTable
; can be set directly before calling PrintByID.
;
.header
!text "Passport by 4am 2017-08-13",$00
!text "Passport by 4am 2017-08-15",$00
.mainmenu
!text "________________________________________",$8D,$8D,$8D,$8D,$8D,$8D,$8D
!text " "
@ -355,8 +357,10 @@ StringTable
!text "T%t,S%0,$%1: ",$00
.modifyto
!text " -> ",$00
.dosboot0
.dos33boot0
!text "T00,S00 Found DOS 3.3 bootloader",$8D,$00
.dos32boot0
!text "T00,S00 Found DOS 3.2 bootloader",$8D,$00
.prodosboot0
!text "T00,S00 Found ProDOS bootloader",$8D,$00
.pascalboot0