migrate from 2016-12-30 Merlin source

This commit is contained in:
4am 2017-01-07 22:35:35 -05:00
parent c206b0aac0
commit e9e63efd94
72 changed files with 7875 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store
/build/

32
Makefile Normal file
View File

@ -0,0 +1,32 @@
#
# Passport Makefile
# assembles source code, optionally builds a disk image and mounts it
#
# original by Quinn Dunki on 2014-08-15
# One Girl, One Laptop Productions
# http://www.quinndunki.com/blondihacks
#
# adapted by 4am on 2017-01-07
#
# third-party tools required to build
# https://sourceforge.net/projects/acme-crossass/
ACME=/usr/local/bin/acme
# https://sourceforge.net/projects/applecommander/
AC=bin/AppleCommander.jar
BUILDDISK=build/passport.po
asm:
mkdir -p build
cd src && $(ACME) passport.a && cd -
cp res/work.po $(BUILDDISK)
java -jar $(AC) -p $(BUILDDISK) "PASSPORT.SYSTEM" sys 0x2000 < build/PASSPORT.SYSTEM
clean:
rm -rf build/
mount:
osascript bin/V2Make.scpt "`pwd`" $(BUILDDISK)
all: clean asm mount

BIN
bin/AppleCommander.jar Normal file

Binary file not shown.

BIN
bin/V2Make.scpt Normal file

Binary file not shown.

1
res/readme.txt Executable file

File diff suppressed because one or more lines are too long

BIN
res/work.po Normal file

Binary file not shown.

293
src/analyze.a Executable file
View File

@ -0,0 +1,293 @@
;-------------------------------
; IsF7
; check for a specific nibble sequence
; ("F7 F6 EF EE AB") that is used by a
; whole-track protection scheme
;
; in slot 6, drive 1 is on track to test
; out C clear if sequence was found
; C set if sequence was not found
;-------------------------------
IsF7
lda $C0E9
lda #$00
jsr WAIT
lda #$20
sta nibcount
ldy #$00
- lda $C0EC
bpl -
cmp #$F7
beq +
restart iny
bne -
dec nibcount
bne -
beq F7fail
-
+ lda $C0EC
bpl -
cmp #$F6
bne restart
- lda $C0EC
bpl -
cmp #$EF
bne restart
- lda $C0EC
bpl -
cmp #$EE
bne restart
- lda $C0EC
bpl -
cmp #$AB
bne restart
clc
!byte $24 ; hides SEC
F7fail sec
lda $C0E8
rts
;-------------------------------
; IsSyncBytes
; check if track is mostly $FF bytes
;
; in slot 6, drive 1 is on track to test
; out C clear if track is mostly just $FF bytes
; C set otherwise
;-------------------------------
IsSyncBytes
lda #$FD
sta nibtableff
jsr IsUnformatted
lda #$3F
sta nibtableff
rts
;-------------------------------
; IsUnformatted
; check if track is unformatted
;
; in slot 6, drive 1 is on track to test
; out C clear if track is unformatted
; C set if track is formatted
;-------------------------------
IsUnformatted
lda $C0E9
lda #$00
sta unform
sta unform+1
jsr WAIT
lda #$20
sta nibcount
ldy #$00
nibloop ldx $C0EC
bpl nibloop
lda nibtable,x
bpl +
inc unform
bne +
inc unform+1
+ iny
bne nibloop
dec nibcount
bne nibloop
lda $C0E8
lda #$18
cmp unform+1
rts
;-------------------------------
; xHeredityDog
; check for a protection check at $BB00
; which implies an unreadable T00,S0A
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if protection code was found
; C set if protection code was not found
;-------------------------------
xHeredityDog
lda $08FE
clc
adc #$04
pha
ldx #$16
ldy #$0B
jsr CompareMemory
!byte $F0,05,$A2,$B2,$4C,$F0,$BB,$BD,$8C,$C0,$A9
pla
bcc analyze_maybe
jmp no1
; don't check byte at $BB21 because it can vary
analyze_maybe
ldx #$22
ldy #$3E
jsr CompareMemory
!byte $8D,00,02,$BD,$8C,$C0,$10,$FB,$C9,$EB,$D0,$F7,$BD,$8C
!byte $C0,$10,$FB,$C9,$D5,$D0,$EE,$BD,$8C,$C0,$10,$FB,$C9,$AA,$D0,$E5
!byte $A9,$4C,$A0,00,$99,00,$95,$88,$D0,$FA,$CE,$46,$BB,$AD,$46,$BB
!byte $C9,07,$D0,$EC,$A9,$18,$8D,$42,$B9,$A9,$0A,$8D,$ED,$B7,$D0,05
bcs no1
yes1
lda #$80
sta T00S0A
no1
rts
;-------------------------------
; xSunburst
; check for a Sunburst RWTS
; which implies an unreadable T11,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if Sunburst RWTS was found
; C set otherwise
;-------------------------------
xSunburst
lda $08FE
clc
adc #$03
ldx #$69
ldy #$2C
jsr CompareMemory
!byte $48,$A5,$2A,$4A,$A8,$B9,$29,$BA
!byte $8D,$6A,$B9,$8D,$84,$BC,$B9,$34
!byte $BA,$8D,$FC,$B8,$8D,$5D,$B8,$C0
!byte $11,$D0,03,$A9,02,$AC,$A9,$0E
!byte $8D,$C0,$BF,$68,$69,00,$48,$AD
!byte $78,04,$90,$2B
bcs no2
yes2
lda #$80
sta T11S0F
no2
rts
;-------------------------------
; xOptimumRes
; check if disk has Optimum Resource bootloader
; which implies an unreadable T01,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if OptimumRes bootloader was found
; C set otherwise
;-------------------------------
xOptimumRes
lda #$08
ldx #$5D
ldy #$0C
jsr CompareMemory
!byte $68,$85,$F0,$68,$85,$F1,$A0,01
!byte $B1,$F0,$85,$54
bcc yes3
lda #$08
ldx #$5D
ldy #$0C
jsr CompareMemory
!byte $68,$85,$A0,$68,$85,$A1,$A0,01
!byte $B1,$A0,$85,$54
bcs no3
yes3
lda #$80
sta T01S0F
no3
rts
;-------------------------------
; xB4BB
; check if disk changes RWTS in
; late boot after a nibble check
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if RWTS was modified in this routine
; C set otherwise
;-------------------------------
xB4BB
lda gTrack
pha
lda gSector
pha
b4bbcompare
lda #$FF ; modified at runtime (in Inspect1)
ldx #$00
ldy #$20
jsr CompareMemory
!byte $D8,$A9,$DF,$48,$A9,$FF,$48,$A9
!byte 08,$85,$3D,$85,$43,$A9,$BF,$85
!byte $3F,$A9,00,$85,$3C,$85,$42,$E6
!byte $42,$A9,$FE,$85,$3E,$A0,00,$AD
bcs _b4bbexit
lda #$00
sta gTrack
sta gAddress
lda #$0C
sta gSector
lda #$0C
clc
adc #BASEPAGE
sta gAddress+1
jsr ReadSector
bcs _b4bbexit
lda #$0C
ldx #$84
ldy #$03
jsr compare
!byte $4C,$BB,$B4
bcs _b4bbexit
lda #$02
sta gTrack
sta gSector
jsr ReadSector
bcs _b4bbexit
lda #$0C
clc
adc #BASEPAGE
sta x0+2
x0 lda $FFC2 ; modified at runtime (above)
b4bbmodify
sta $FF55 ; modified at runtime (in Inspect1)
lda #$DE
b4bbmodify2
sta $FF91 ; modified at runtime (in Inspect1)
_b4bbexit
pla
sta gSector
pla
sta gTrack
rts
;-------------------------------
; xB660
; Check if RWTS calls an extra routine at $B660
; after matching the first two data prologue
; nibbles. This routine can hang in an infinite
; loop if it's used to read an unprotected sector,
; so we need to force-switch to the built-in RWTS
; after reading all the protected sectors.
; (T00,S00-S09 are unprotected because they are
; read by the drive firmware.)
;
; in: $0800..$08FF contains boot0
; out: C clear if $B660 routine was found
; C set otherwise
;-------------------------------
xB660
lda #$08
ldx #$60
ldy #$1A
jsr CompareMemory
!byte $BD,$8C,$C0,$10,$FB,$C9,$AD,$D0
!byte $F4,$A9,$F8,$3D,$8C,$C0,$D0,02
!byte $EA,$EA,$EA,$EA,$BD,$8C,$C0,$2A
!byte $30,02
bcs no4
yes4
lda #$FE
sta T00S09
no4
rts

128
src/applyglobals.a Executable file
View File

@ -0,0 +1,128 @@
;
; initialize some variables that are used by many
; other patchers on track $00
;
ApplyGlobals
lda #$00
ldx #$00
ldy #$4A
jsr compare ; if T00,S00,$00 ==
; This needs to be pretty strict because, if it matches,
; we're going to patch the sector and trace it to capture
; the RWTS.
!byte 01,$A5,$27,$C9,09,$D0,$18,$A5
!byte $2B,$4A,$4A,$4A,$4A,09,$C0,$85
!byte $3F,$A9,$5C,$85,$3E,$18,$AD,$FE
!byte 08,$6D,$FF,08,$8D,$FE,08,$AE
!byte $FF,08,$30,$15,$BD,$4D,08,$85
!byte $3D,$CE,$FF,08,$AD,$FE,08,$85
!byte $27,$CE,$FE,08,$A6,$2B,$6C,$3E
!byte 00,$EE,$FE,08,$EE,$FE,08,$20
!byte $89,$FE,$20,$93,$FE,$20,$2F,$FB
!byte $A6,$2B
ldx #TRUE
bcc boot0
ldx #FALSE
boot0
stx gIsBoot0
lda #$01
ldx #$00
ldy #$38
jsr compare ; if T00,S01,$00 ==
!byte $8E,$E9,$B7,$8E,$F7,$B7,$A9,01
!byte $8D,$F8,$B7,$8D,$EA,$B7,$AD,$E0
!byte $B7,$8D,$E1,$B7,$A9,02,$8D,$EC
!byte $B7,$A9,04,$8D,$ED,$B7,$AC,$E7
!byte $B7,$88,$8C,$F1,$B7,$A9,01,$8D
!byte $F4,$B7,$8A,$4A,$4A,$4A,$4A,$AA
!byte $A9,00,$9D,$F8,04,$9D,$78,04
ldx #TRUE
bcc boot1
ldx #FALSE
:boot1
stx gIsBoot1
lda #$01
ldx #$00
ldy #$38
jsr compare ; if T00,S01,$00 ==
!byte $8E,$E9,$37,$8E,$F7,$37,$A9,01
!byte $8D,$F8,$37,$8D,$EA,$37,$AD,$E0
!byte $37,$8D,$E1,$37,$A9,02,$8D,$EC
!byte $37,$A9,04,$8D,$ED,$37,$AC,$E7
!byte $37,$88,$8C,$F1,$37,$A9,01,$8D
!byte $F4,$37,$8A,$4A,$4A,$4A,$4A,$AA
!byte $A9,00,$9D,$F8,04,$9D,$78,04
ldx #TRUE
bcc master
ldx #FALSE
master
stx gIsMaster
lda #$07
ldx #$00
ldy #$40
jsr compare ; if T00,S07,$00 ==
!byte $84,$48,$85,$49,$A0,02,$8C,$F8
!byte 06,$A0,04,$8C,$F8,04,$A0,01
!byte $B1,$48,$AA,$A0,$0F,$D1,$48,$F0
!byte $1B,$8A,$48,$B1,$48,$AA,$68,$48
!byte $91,$48,$BD,$8E,$C0,$A0,08,$BD
!byte $8C,$C0,$DD,$8C,$C0,$D0,$F6,$88
!byte $D0,$F8,$68,$AA,$BD,$8E,$C0,$BD
!byte $8C,$C0,$A0,08,$BD,$8C,$C0,$48
ldx #TRUE
bcc rwts
ldx #FALSE
rwts
stx gIsRWTS
lda #$00
ldx #$00
ldy #$05
jsr compare ; if T00,S00,$00 ==
; This abbreviated signature matches all ProDOS disks
; I can find, with no false positives.
; Some disks jump to $08FF at $0804 (SOS entry point).
; Others have a modified T00,S00 but eventually load
; ProDOS (e.g. 1-2-3 Sequence Me, Alge-Blaster Plus,
; Dazzle Draw, SuperPrint II)
!byte 01,$38,$B0,$03,$4C
ldx #TRUE
bcc prodos
ldx #FALSE
prodos
stx gIsProDOS
lda #$00
ldx #$00
ldy #$08
jsr compare ; if T00,S00,$00 ==
; Apple Pascal signature (version < 1.3)
; The wildcard in 7th position catches alternate jump
; addresses (e.g. Wizardry I, Sundog Frozen Legacy)
!byte 01,$E0,$60,$F0,03,$4C,$97,$08
ldx #TRUE
bcc pascal
lda #$00
ldx #$00
ldy #$08
jsr compare ; or if T00,S00,$00 ==
; Pascal 1.3 signature [thanks Marco V.]
!byte 01,$E0,$07,$B0,04,$E0,$40,$B0
ldx #TRUE
bcc pascal
ldx #FALSE
pascal
stx gIsPascal
rts

202
src/compare.a Executable file
View File

@ -0,0 +1,202 @@
WILDCARD = $97
;-------------------------------
; SearchTrack subroutine
; written by qkumba
; search for a string occurring anywhere
; in the data buffer for the current track
; #WILDCARD in search string matches any 1 byte
; (like "." character in regular expressions)
; in: Y = string length
; stack = string to find
; out: C clear if string found
; or set if not found
; If C is clear, then
; A = sector where string was found
; X = starting offset where string was found
; all other registers and flags clobbered
;-------------------------------
SearchTrack
pla
sta match_buffer1+1
sta match_all+1
pla
sta match_buffer1+2
sta match_all+2
tax
sty match_size1+1
sty match_size2+1
; fetch last byte to improve search speed
match_buffer1
lda $d1d1,y ; modified at runtime
sta check_byte1+1
sta check_byte2+1
; set low part of initial search position
tya
dey
sty cont_search+1
; set return address
clc
adc match_buffer1+1
tay
bcc plus01
inx
plus01
txa
pha
tya
pha
; set match position
inc match_all+1
bne plus02
inc match_all+2
plus02
; set high part of initial search position
lda #BASEPAGE
sta search+2
lda #<cont_search-branch_cont-2
sta branch_cont+1
; search...
cont_search
ldy #$d1 ; modified at runtime
search
lda $d100,y ; modified at runtime
iny
beq check_end
check_byte1
cmp #$d1 ; modified at runtime
bne search
; point to first byte
sty cont_search+1
check_match
tya
match_size1
sbc #$d1 ; modified at runtime
sta match_buffer2+1
ldx search+2
bcs plus03
dex
plus03
stx match_buffer2+2
ldy #$00
match_all
lda $d1d1,y ; modified at runtime
cmp #WILDCARD
beq found_wild
match_buffer2
cmp $d1d1,y ; modified at runtime
branch_cont
bne cont_search
found_wild
iny
match_size2
cpy #$d1 ; modified at runtime
bne match_all
; point to start of match
ldx match_buffer2+1
lda match_buffer2+2
sec
sbc #BASEPAGE
clc
rts
; cold path
check_end
inc search+2
ldx search+2
cpx #BASEPAGE+$10
bne check_byte1
ldx #<all_done_set-branch_cont-2
stx branch_cont+1
check_byte2
cmp #$d1 ; modified at runtime
beq check_match
all_done_set
sec
rts
;-------------------------------
; compare subroutine
; in: A = sector
; X = offset
; Y = string length
; stack = string to compare
; #WILDCARD in search string matches any 1 byte
; (like "." character in regular expressions)
; out: C clear if string matches
; or set if not matched
; A,X unchanged
; Y clobbered
; $tmp zero page clobbered
; $cmp1 zero page clobbered
; $cmp2 zero page clobbered
; stack set to first instruction after string
;-------------------------------
compare
clc
adc #BASEPAGE
CompareMemory
sta cmp1+1
stx cmp1
pla
sta cmp2
pla
sta cmp2+1
tax
tya
clc
adc cmp2
bcc +
inx
+ sta tmp
txa
pha
lda tmp
pha
xcmp
lda (cmp2),y
dey
bmi success
cmp (cmp1),y
beq xcmp
cmp #WILDCARD
beq xcmp
sec
!byte $24 ; hide CLC
success clc
php
lda cmp1+1
sec
sbc #BASEPAGE
ldx cmp1
plp
rts

32
src/id/datasoft.a Executable file
View File

@ -0,0 +1,32 @@
;-------------------------------
; IDDatasoft
; identify Datasoft encrypted bootloader
;
; in: track buffer contains T00,S00
; out: C clear if Datasoft encrypted bootloader found
; C set otherwise
; all registers clobbered
; all other flags clobbered
;-------------------------------
IDDatasoft
lda #$00
ldx #$00
ldy #$7E
jsr compare
!byte 01,$4C,$7E,08,04,$8A,$0C,$B8
!byte 00,$56,$10,$7A,00,00,$1A,$16
!byte $12,$0E,$0A,06,$53,$18,$9A,02
!byte $10,$1B,02,$10,$4D,$56,$15,$0B
!byte $BF,$14,$14,$54,$54,$54,$92,$81
!byte $1B,$10,$10,$41,06,$73,$0A,$10
!byte $33,$4E,00,$73,$12,$10,$33,$7C
!byte 00,$11,$20,$E3,$49,$50,$73,$1A
!byte $10,$41,00,$23,$80,$5B,$0A,$10
!byte $0B,$4E,$9D,$0A,$10,$9D,$0C,$10
!byte $60,$1E,$53,$10,$90,$53,$BC,$90
!byte $53,00,$90,$D8,$52,00,$D8,$7C
!byte 00,$53,$80,$0B,06,$41,00,09
!byte 04,$45,$0C,$63,04,$90,$94,$D0
!byte $D4,$23,04,$91,$A1,$EB,$CD,06
!byte $95,$A1,$E1,$98,$97,$86
rts

91
src/id/dos33.a Executable file
View File

@ -0,0 +1,91 @@
;-------------------------------
; IDDOS33
; identify DOS 3.3 bootloader or some variation
; that can be safely boot traced
;
; in: $0800..$08FF contains T00,S00
; first page of track buffer also contains T00,S00
; out: C clear if traceable DOS 3.3-style bootloader found
; C set otherwise
; all registers clobbered
; all other flags clobbered
;-------------------------------
IDDOS33
lda $08FE ; $08FE must be either $36 or $B6
cmp #$36 ; (prevents matching on some
beq match0 ; Infocom disks that would
cmp #$B6 ; otherwise match but then load
beq match0 ; boot1 over program space and crash)
jmp notd33boot0
match0
lda #$00 ; match first $1C bytes of T00S00
ldx #$00 ; against standard DOS 3.3 boot0
ldy #$1C
jsr compare
!byte 01,$A5,$27,$C9,09,$D0,$18,$A5
!byte $2B,$4A,$4A,$4A,$4A,09,$C0,$85
!byte $3F,$A9,$5C,$85,$3E,$18,$AD,$FE
!byte 08,$6D,$FF,08
bcc maybe_d33_1
jmp notd33boot0
maybe_d33_1
lda #$00 ; match more bytes of T00S00
ldx #$1F ; against standard DOS 3.3 boot0
ldy #$2B
jsr compare
!byte $AE
!byte $FF,08,$30,$15,$BD,$4D,08,$85
!byte $3D,$CE,$FF,08,$AD,$FE,08,$85
!byte $27,$CE,$FE,08,$A6,$2B,$6C,$3E
!byte 00,$EE,$FE,08,$EE,$FE,08,$20
!byte $89,$FE,$20,$93,$FE,$20,$2F,$FB
!byte $A6,$2B
bcc maybe_d33_2
jmp notd33boot0
maybe_d33_2
lda #$00 ; check sector order map
ldx #$4D
ldy #$10
jsr compare
!byte 00,$0D,$0B,09,07,05,03,01
!byte $0E,$0C,$0A,08,06,04,02,$0F
bcc maybe_d33_3
jmp notd33boot0
maybe_d33_3
lda #$00 ; match 3 final bytes of T00S00
ldx #$1C ; against standard DOS 3.3 boot0
ldy #$03
jsr compare
!byte $8D,$FE,08
bcs maybe_d33_4
jmp founddos33
maybe_d33_4
lda #$00 ; minor variation (e.g. Terrapin
ldx #$1C ; Logo 3.0) jumps to $08F0 and
ldy #$03 ; back, but still safe to trace
jsr compare
!byte $4C,$F0,08
bcc maybe_d33_5
jmp notd33boot0
maybe_d33_5
lda #$00
ldx #$F0
ldy #$09
jsr compare
!byte $8D,$FE,08,$EE,$F3,03,$4C,$1F
!byte 08
bcs notd33boot0
founddos33
clc
!byte $24 ; hide next SEC
notd33boot0
sec
rts

19
src/id/encode44.a Executable file
View File

@ -0,0 +1,19 @@
;-------------------------------
; IDEncoded44
; identify bootloader that loads
; 4-4-encoded data from track 0
; (these disks are unsupported)
;
; in: track buffer contains T00,S00
; out: C clear if 4-4-encoding loader found
; C set otherwise
; all registers clobbered
; all other flags clobbered
;-------------------------------
IDEncoded44
ldy #$07
jsr SearchTrack
!byte $BD,$8C,$C0,$10,$FB,$38,$2A
bcs encoded44_exit
encoded44_exit
rts

20
src/id/encode53.a Executable file
View File

@ -0,0 +1,20 @@
;-------------------------------
; IDEncoded53
; identify bootloader that loads
; 5-3-encoded data from track 0
; (these disks are unsupported)
;
; in: track buffer contains T00,S00
; out: C clear if 5-3-encoding loader found
; C set otherwise
; all registers clobbered
; all other flags clobbered
;-------------------------------
IDEncoded53
ldy #$10
jsr SearchTrack
!byte $BD,$8C,$C0,$10,$FB,$C9,$B5,$F0
!byte 09,$28,$90,$DF,$49,$AD,$F0,$1F
bcs encoded53_exit
encoded53_exit
rts

146
src/id/inspect0.a Executable file
View File

@ -0,0 +1,146 @@
;-------------------------------
; CheckT00S00
; main entry point to identify the bootloader
; based on T00,S00 (currently in memory at $0800)
;-------------------------------
CheckT00S00
lda #FALSE
sta gIsBoot0
sta gIsBoot1
sta gIsMaster
sta gIsRWTS
sta gIsProDOS
sta gIsPascal
sta gIsDatasoft
sta gIsProtDOS
lda #$00
sta gLastTrack
; Quick sanity check -- only recognized values for $0800
; are 1 or 2.
lda $0800
beq +
cmp #$03
bcc ++
+
jmp UseUniversal
++
;
; Copy the boot sector from $0800 to the track/sector buffer
; so we can reuse our standard compare functions.
; (TODO: this is probably unnecessary but I haven't ever
; refactored it since the Post-Demuffin Patcher days.)
;
lda #$08
ldx #BASEPAGE
ldy #$01
jsr CopyMemory
jsr ApplyGlobals
;
; Try to identify DOS 3.3-shaped bootloader, which
; we can maybe trace to capture the RWTS in memory.
;
jsr IDDOS33
bcs notdos33
lda #s_dosb0
jsr PrintByID
jmp TraceDOS33
notdos33
;
; Try to identify a variant bootloader that calls to $08B3
; early to munge the nibble tables used by the drive firmware.
;
jsr ID8b3
bcs not8b3
jmp found8b3
not8b3
;
; Try to identify all the different MECC fastloader variants.
;
jsr IDMECC
bcs notmecc
jsr IDMECCM8
bcs notmeccm8
jmp foundmeccm8
notmeccm8
jsr IDMECCM7
bcs notmeccm7
jmp foundmeccm7
notmeccm7
notmecc
;
; Try to identify the encrypted Datasoft bootloader.
;
jsr IDDatasoft
bcs notdatasoft
lda #s_datasoftb0
jsr PrintByID
lda #TRUE
sta gIsDatasoft
jmp useuniv
:notdatasoft
;
; Try to identify ProDOS bootloader.
;
lda gIsProDOS
bne notprodos
lda #s_prodosb0
jsr PrintByID
jmp useuniv
notprodos
;
; Try to identify Apple Pascal bootloader (all variants).
;
lda gIsPascal
bne notpascal
lda #s_pascalb0
jsr PrintByID
notpascal
jsr IDSpecDel
bcs notspecdel
lda #s_specdel
jsr PrintByID
jmp TraceSpecDel
notspecdel
;
; 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.
;
jsr IDEncoded44
bcs notencoded44
lda #s_encoded44
jsr PrintByID
jmp TheEnd
notencoded44
;
; Try to detect whether there is code in the boot sector
; that loads 5-and-3-encoded data (like DOS 3.2 disks with
; a hybrid boot sector that loads on 16-sector drives).
; Passport has no support for converting DOS 3.2 disks, so
; this serves as an early escape hatch for disks that are
; guaranteed to fail later anyway.
;
jsr IDEncoded53
bcs notencoded53
lda #s_encoded53
jsr PrintByID
jmp TheEnd
notencoded53
useuniv
;
; We didn't recognize the boot sector, so use the universal
; (built-in) RWTS and hope for the best
;
jmp UseUniversal

77
src/id/jsr8b3.a Executable file
View File

@ -0,0 +1,77 @@
;-------------------------------
; ID8b3
; identify a bootloader that JSRs to $08B3
; to alter the nibble translate table used
; by the drive firmware at $C600
;
; in: track buffer contains T00,S00
; out: C clear if this bootloader was found
; C set otherwise
; all other flags clobbered
; all registers clobbered
;-------------------------------
ID8b3
lda #$00
ldx #$00
ldy #$5A
jsr compare
!byte 01,$20,$B3,08,$D0,$19,$EA,$A5
!byte $2B,$4A,$4A,$4A,$4A,09,$C0,$85
!byte $3F,$A9,$5C,$85,$3E,$18,$AD,$FE
!byte 08,$6D,$FF,08,$8D,$FE,08,$AE
!byte $FF,08,$F0,$15,$8A,$EA,$EA,$85
!byte $3D,$CE,$FF,08,$AD,$FE,08,$85
!byte $27,$CE,$FE,08,$A6,$2B,$6C,$3E
!byte 00,$EE,$FE,08,$EE,$FE,08,$20
!byte $89,$FE,$20,$93,$FE,$20,$2F,$FB
!byte $A2,$FF,$BD,00,08,$9D,00,$B6
!byte $CA,$E0,$FF,$D0,$F5,$20,$CC,08
!byte $A6,$2B
bcc jsr8b3_maybe
rts
jsr8b3_maybe
lda #$00
ldx #$B3
ldy #$36
jsr compare
!byte $A9,$3F,$8D,$6C,03
!byte $A9,$1C,$8D,$CC,03,$A9,00,$8D
!byte $D5,03,$A9,$37,$8D,$A3,03,$A5
!byte $27,$C9,09,$60,$A9,00,$85,00
!byte $A9,$B5,$85,01,$A0,$FF,$C8,$B9
!byte 00,$F0,$91,00,$C0,$FF,$D0,$F6
!byte $C6,01,$A9,08,$C5,01,$D0,$EC
!byte $60
rts
found8b3
tya
pha
ldy #$0F
lda #$00
A8b3 sta T00,y
dey
bpl A8b3
ldy #$0B
B8b3 sta T02,y
iny
cpy #$10
bne B8b3
pla
tay
lda #$4C
sta $085A
lda #<Inspect1_8b3
sta $085B
lda #>Inspect1_8b3
sta $085C
lda #$60
sta $08CC
lda #$2C
sta $083F
sta $0842
sta $0845
pla
plp
jmp $0801

230
src/id/mecc.a Executable file
View File

@ -0,0 +1,230 @@
;-------------------------------
; IDMECC
; identify MECC custom bootloader
; note: there are several MECC RWTSes that share
; the same bootloader, so further checks will be
; required to distinguish between them
;
; in: track buffer contains T00,S00
; out: C clear if MECC bootloader was found
; C set if not found
; all other flags clobbered
; all registers clobbered
;-------------------------------
IDMECC
lda #$00
ldx #$00
ldy #$17
jsr compare
!byte 01,$4C,$1A,08,$17,$0F,00,00
!byte $0D,$0B,09,07,05,03,01,$0E
!byte $0C,$0A,08,06,04,02,$0F
rts
;-------------------------------
; IDMECCM8
; identify MECC "M8" bootloader
;
; in: track buffer contains T00,S00
; out: C clear if MECC "M8" bootloader was found
; C set if not found
; all other flags clobbered
; all registers clobbered
;-------------------------------
IDMECCM8
lda #$00
sta gTrack
sta gAddress
lda #$0B
sta gSector
clc
adc #BASEPAGE
sta gAddress+1
jsr ReadSector
bcc +
mecc_no1
rts
+
lda #$0B
ldx #$02
ldy #$06
jsr compare ; IF T00,S0B,$02 ==
!byte $BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no1
lda #$0B
ldx #$09
ldy #$09
jsr compare ; AND T00,S0B,$09 ==
!byte $D0,$EF,$EA,$BD,$8C,$C0,$10,$FB
!byte $C9
bcs mecc_no1
lda #$0B
ldx #$13
ldy #$0A
jsr compare ; AND T00,S0B,$13 ==
!byte $D0,$E5,$A0,03,$BD,$8C,$C0,$10
!byte $FB,$C9
bcs mecc_no1
lda #$0B
ldx #$89
ldy #$06
jsr compare ; AND T00,S0B,$89 ==
!byte $BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no1
lda #$0B
ldx #$90
ldy #$09
jsr compare ; AND T00,S0B,$90 ==
!byte $D0,$F4,$EA,$BD,$8C,$C0,$10,$FB
!byte $C9
bcs mecc_no1
lda #$0B
ldx #$9A
ldy #$09
jsr compare ; AND T00,S0B,$9A ==
!byte $D0,$F2,$EA,$BD,$8C,$C0,$10,$FB
!byte $C9
rts
foundmeccm8
;
; We found an "M8" MECC bootloader. Now we create
; an RWTS that can read the rest of the disk.
; Starting with our built-in RWTS, we modify address
; and data prologues based on the parameters of the
; original disk.
;
lda #s_meccb0
jsr PrintByID
jsr CopyUniversal
lda #$00
sta modsrc
lda #$0B
clc
adc #BASEPAGE
sta modsrc+1
ldy #$08
lda (modsrc),y
lsr
sta $B956
ldy #$12
lda (modsrc),y
sta $B966
ldy #$1D
lda (modsrc),y
sta $B96F
ldy #$8F
lda (modsrc),y
sta $B8E7
ldy #$99
lda (modsrc),y
sta $B8F1
ldy #$A3
lda (modsrc),y
sta $B8FC
pla
plp
jmp ADStyle
;-------------------------------
; IDMECCM7
; identify MECC "M7" bootloader
;
; in: track buffer contains T00,S00
; out: C clear if MECC "M7" bootloader was found
; C set if not found
; all other flags clobbered
; all registers clobbered
;-------------------------------
IDMECCM7
lda #$00
sta gTrack
sta gAddress
lda #$07
sta gSector
clc
adc #BASEPAGE
sta gAddress+1
jsr ReadSector
bcc +
mecc_no2
rts
+
lda #$07
ldx #$7D
ldy #$06
jsr compare ; IF T00,S07,$7D ==
!byte $BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no2
lda #$07
ldx #$84
ldy #$09
jsr compare ; AND T00,S07,$84 ==
!byte $D0,$F0,$EA,$BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no2
lda #$07
ldx #$8E
ldy #$0A
jsr compare ; and T00,S07,$8E ==
!byte $D0,$F2,$A0,03,$BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no2
lda #$07
ldx #$0F
ldy #$06
jsr compare ; and T00,S07,$0F ==
!byte $BD,$8C,$C0,$10,$FB,$49
bcs mecc_no2
lda #$07
ldx #$18
ldy #$07
jsr compare ; and T00,S07,$18 ==
!byte $EA,$BD,$8C,$C0,$10,$FB,$C9
bcs mecc_no2
lda #$07
ldx #$20
ldy #$0A
jsr compare ; and T00,S07,$20 ==
!byte $D0,$F2,$A0,$56,$BD,$8C,$C0,$10,$FB,$C9
rts
foundmeccm7
;
; We found an "M7" MECC bootloader. Now we create
; an RWTS that can read the rest of the disk.
; Starting with our built-in RWTS, we modify address
; and data prologues based on the parameters of the
; original disk.
;
lda #s_meccm7
jsr PrintByID
jsr CopyUniversal
lda #$00
sta modsrc
lda #$07
clc
adc #BASEPAGE
sta modsrc+1
ldy #$83
lda (modsrc),y
lsr
sta $B956
ldy #$8D
lda (modsrc),y
sta $B966
ldy #$98
lda (modsrc),y
sta $B96F
ldy #$15
lda (modsrc),y
sta $B8E7
ldy #$1F
lda (modsrc),y
sta $B8F1
ldy #$2A
lda (modsrc),y
sta $B8FC
pla
plp
jmp ADStyle

54
src/id/protecteddos.a Executable file
View File

@ -0,0 +1,54 @@
;-------------------------------
; ProtectedDOS
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if "Protected DOS" was found
; C set if "Protected DOS" was not found
; gProtectedDOS is set to TRUE or FALSE
;-------------------------------
ProtectedDOS
lda #$B7
ldx #$00
ldy #$1A
jsr CompareMemory
!byte $A0,$1A,$B9,00,$B7,$49,$97,$99
!byte 00,$B7,$C8,$D0,$F5,$EE,04,$B7
!byte $EE,09,$B7,$AD,09,$B7,$C9,$C0
!byte $D0,$E8
bcs protecteddos_exit
lda $B706 ; decryption key
sta key+1
sta gDisplayBytes
lda #s_protdos
jsr PrintByID
;
; decrypt RWTS in memory
;
lda #$B7
sta decrypt+2
sta store+2
ldy #$1A
decrypt lda $B700,y
key eor #$FF ; set at runtime
store sta $B700,y
iny
bne decrypt
inc decrypt+2
inc store+2
lda store+2
cmp #$C0
bne decrypt
;
; this RWTS swaps the A/Y hi/lo parameter table address
; when calling the RWTS entry point, so we need to
; set a flag so we can call it properly later
; (in ReadSector)
;
lda #TRUE
sta gIsProtDOS
clc
protecteddos_exit
rts

244
src/id/specdelivery.a Executable file
View File

@ -0,0 +1,244 @@
; "Special Delivery" boot tracer
; for DOS 3.3P disks
; e.g. Ernie's Quiz, Elite
;
;-------------------------------
; IDSpecDel
; returns C clear if "Special Delivery" bootloader
; detected in T00,S00
;-------------------------------
IDSpecDel
lda #$00
ldx #$00
ldy #$58
jsr compare
!byte 02,$90,$4A,$C6,$27,$BD,$31,09
!byte $49,$B0,$48,$C6,$3D,$98,$C8,$48
!byte $CE,00,08,$A9,$20,$C6,$27,$48
!byte $51,$26,$91,$26,$AA,$A5,$27,$85
!byte $32,$CE,00,08,$A8,$B5,$33,$84
!byte $29,$84,$21,$8A,$A2,$17,$86,$31
!byte $D5,$33,$A6,$2B,$5D,$31,09,$85
!byte $29,$5D,$32,09,$C6,$3D,$85,$28
!byte $5D,$33,09,$85,$48,$A0,$2B,$84
!byte $20,$C6,$40,$30,$3E,$24,$40,$30
!byte $33,$24,$24,$24,$24,$40,$40,$40
rts
;-------------------------------
; TraceSpecDel
; set up boot trace to capture the bootloader and DOS
; of "Special Delivery" disks (stored in non-sector
; format on tracks 0-2)
;-------------------------------
TraceSpecDel
jsr ClearTSBuffer
lda #$00 ; set a marker to see if entire
sta $3FFF ; RWTS loads successfully later
lda #$00 ; save zero page before trace
ldx #$0A
ldy #$01
jsr CopyMemory
lda #<TraceSpecDel2
ldx #>TraceSpecDel2
jmp Trace
TraceSpecDel2
lda #$4C
sta $0855
lda #<TraceSpecDel3
sta $0856
lda #>TraceSpecDel3
sta $0857
lda #$02
sec
jmp $0801
TraceSpecDel3
lda $1212
cmp #$D8
bne SDfail
lda #$4C
sta $10D5
lda #<TraceSpecDel4
sta $10D6
lda #>TraceSpecDel4
sta $10D7
lda #$4C
sta $10F0
lda #<TraceSpecDel4
sta $10F1
lda #>TraceSpecDel4
sta $10F2
jmp $1212
TraceSpecDel4
lda $C0E8 ; turn off source drive
lda #$0A ; restore zero page from before trace
ldx #$00
ldy #$01
jsr CopyMemory
lda $3FFF
cmp #$EA
bne SDfail
lda #$0B
ldx #$00
ldy #$03
jsr compare ; if $1B00 ==
!byte $4C,$4D,$2A
bcc SDsuccess
SDfail
jmp UseUniversal
SDsuccess
;
; Restore the original code in memory before writing.
;
lda #$A2
sta $10D5
lda #$FF
sta $10D6
lda #$9A
sta $10D7
lda #$A5
sta $10F0
lda #$2B
sta $10F1
lda #$4A
sta $10F2
;
; move $1000-$13FF to $1100-$14FF to align it as we need it
; for writing to disk with the Standard Delivery bootloader
; in T00,S00
;
lda #$13
ldx #$14
ldy #$01
jsr CopyMemory
lda #$12
ldx #$13
ldy #$01
jsr CopyMemory
lda #$11
ldx #$12
ldy #$01
jsr CopyMemory
lda #$10
ldx #$11
ldy #$01
jsr CopyMemory
; $1B00-$1FFF is real code and in the right place
; 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
jsr ClearMemory
; 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
; now manually write out track 0 with Standard Delivery
; bootloader
jsr IncProgress
lda #$00
sta gTrack
jsr WriteTrackNA
; manually write out track 1
jsr IncProgress
inc gTrack
lda #$20
ldx #$10
ldy #$10
jsr CopyMemory
jsr WriteTrackNA
; manually write out track 2 with a patched RWTS
jsr IncProgress
inc gTrack
lda #$30
ldx #$10
ldy #$10
jsr CopyMemory
lda #$08
ldx #$B6
ldy #$04
jsr modify
!byte $C9,$AD,$90,$E5
lda #$18
ldx #$38
ldy #$01
jsr CopyMemory
jsr WriteTrackNA
lda #$C9
sta $38B6
lda #$AD
sta $38B7
lda #$90
sta $38B8
lda #$E5
sta $38B9
; mark tracks 0-2 as "skip" in sector map
ldy #$2F
lda #$00
skipsectors
sta T00,y
dey
bpl skipsectors
; set up RWTS entry point
lda #$D5
sta callrwts+1
lda #$36
sta callrwts+2
; read the rest of the disk with the original RWTS
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

156
src/id/trace.a Executable file
View File

@ -0,0 +1,156 @@
;-------------------------------
; TraceDOS33
; set up 1st-level boot trace on
; a DOS 3.3-shaped bootloader
;-------------------------------
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
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 #$2C ; disable calls to
sta $083F ; TEXt/PR0/IN0
sta $0842
sta $0845
jmp $0801
TraceDOS33c
lda $08FE ; 2nd-level trace callback is here
clc
adc #$02
_Inspect1a
sta x1+1
sta x2+1
sta b4bbmodify+2
sta b4bbmodify2+2
clc
adc #$06
sta b4bbcompare+1
sec
sbc #$02
sta x3+1
sta x4+1
sta 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 +
;
; 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 +
jmp UseUniversal ; give up tracing; this RWTS is unsupported
+ jmp ADStyle ; use this RWTS to read the disk
; TODO this doesn't belong here
Inspect1_8b3
jsr WriteTrack
lda $08FE
clc
adc #$01
jmp _Inspect1a
;-------------------------------
; 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

20
src/keys.a Executable file
View File

@ -0,0 +1,20 @@
KEY = $C000
STROBE = $C010
WaitForKey
bit STROBE
k lda KEY
bpl k
bit STROBE
cmp #"*"
bne noast
jsr TEXT
lda #s_reset
jsr PrintByID
jmp $FF59
noast
cmp #$E1
bcc +
and #$DF ; force uppercase
+
rts

4
src/lcase.a Executable file
View File

@ -0,0 +1,4 @@
!to "lcase.ct", plain
*=0
!for i, 128 {!byte i+127}
!for i, 256-128 {!byte i+127}

1
src/lcase.ct Executable file
View File

@ -0,0 +1 @@
€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<EFBFBD><EFBFBD><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<EFBFBD><EFBFBD><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

126
src/memory.a Executable file
View File

@ -0,0 +1,126 @@
;-------------------------------
; CopyMemory
; in: A = source address (high)
; X = destination address (high)
; Y = number of pages to copy
; out: all flags and registers clobbered
;-------------------------------
CopyMemory
sta source1+2
stx dest1+2
ldx #$00
source1 lda $FF00,x
dest1 sta $FF00,x
inx
bne source1
inc source1+2
inc dest1+2
dey
bne source1