add Strategic Craps (1987)

This commit is contained in:
4am 2025-04-07 10:51:23 -04:00
parent 817f6ac1aa
commit e4a160a2db
35 changed files with 6302 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
#
# Attract mode for STRATEGIC.CRAPS
# This file is automatically generated
#
STRATEGIC.CRAPS=A

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -94,6 +94,7 @@
011000,SS.FOOTBALL=Street Sports Football/1988
011001,SS.SOCCER=Street Sports Soccer/1988
100000,STUNT.CAR.RACER=Stunt Car Racer/2023
000000,STRATEGIC.CRAPS=Strategic Craps/1987
000000,SUDOKU=Sudoku/2018
000001,SUMMER.GAMES=Summer Games/1984
000001,SUMMER.GAMES.II=Summer Games II/1985

View File

@ -1,6 +1,7 @@
# Lounge games action slideshow
POOL
SHUFFLEBOARD
STRATEGIC.CRAPS
VIDEO.VEGAS
CMPTR.FOOSBALL
POOL2=POOL

View File

@ -4,6 +4,7 @@ SPDWAY.CLASSIC
SKI.CRAZED
STUNT.CAR.RACE2=STUNT.CAR.RACER
SLIDE.GLIDE
STRATEGIC.CRAPS
SPDWAY.CLASSIC2=SPDWAY.CLASSIC
SHUFFLEBOARD
SUMMER.GAMES

View File

@ -2,6 +2,7 @@
SHUFFLEBOARD
CRAPS
VIDEO.VEGAS
STRATEGIC.CRAPS
ROULETTE
CMPTR.FOOSBALL
POOL

View File

@ -3,6 +3,7 @@ SEEGA
SUMMER.GAMES.II
STUNT.CAR.RACER
SOLO.FLIGHT
STRATEGIC.CRAPS
SLIDE.GLIDE
SUDOKU
SUPER.ICEHOCKEY

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,90 @@
# default configuration inherited from Improbable engine
# adapted for Strategic Craps
# 1, 2, or 3 correspond to Apple Pascal v1.1, v1.2, or v1.3
# note that 0 is an invalid value
version=3
# boolean, 0 or 1 (normally 1, use 0 for 48K Pascal e.g. Wizardry)
is_64kb=1
# boolean, 0 or 1 (normally 0, use 1 for 128K Pascal e.g. Widespread)
# use 0 for disks that boot 64K Pascal then manually use auxmem e.g. Jostens Learning
is_128kb=0
# boolean, 0 or 1 (normally 1, use 0 if you need write support)
read_only=1
# boolean, 0 or 1 (normally 1, use 0 if you know in advance that game clobbers auxmem)
backup_prodos=1
# integer, 1+ (number of disks)
# multi-disk games will only work OOTB if they support 2 drives
# otherwise the disk images will need to be patched to support 'swapping' disks
# see Angelsoft adventures for examples of magic swapping
disks=1
# boolean, 0 or 1 (normally 0, use 1 for Pascal v1.2 variant used by Reading Workshop)
is_reading=0
# boolean, 0 or 1 (normally 0, use 1 for Pascal v1.1 variant used by Apple Presents Apple)
is_apa=0
# boolean, 0 or 1 (normally 0, use 1 for Pascal v1.1 variant used by The Dark Heart of Uukrul)
is_uukrul=0
# boolean, 0 or 1 (normally 0, use 1 for Pascal v1.2 variant used by Sundog Frozen Legacy)
is_sundog=0
#-----------------------------------------------------------------------
# https://sourceforge.net/projects/acme-crossass/
ACME=acme
# https://github.com/mach-kernel/cadius
CADIUS=cadius
BUILDDIR=build
SOURCES=$(wildcard src/*.a)
EXE=$(BUILDDIR)/STRATEGIC.CRAPS\#FF2000
DATA=$(wildcard res/*)
DISKVOLUME=STRATEGIC.CRAPS
BUILDDISK=$(BUILDDIR)/$(DISKVOLUME).po
.PHONY: clean mount all
$(BUILDDISK): $(DATA) $(EXE)
$(EXE): $(SOURCES) | $(BUILDDIR)
$(ACME) -r build/improbable.lst \
-Dversion=$(version) \
-Dis_64kb=$(is_64kb) \
-Dis_128kb=$(is_128kb) \
-Dread_only=$(read_only) \
-Dbackup_prodos=$(backup_prodos) \
-Ddisks=$(disks) \
-Dis_reading=$(is_reading) \
-Dis_apa=$(is_apa) \
-Dis_uukrul=$(is_uukrul) \
-Dis_sundog=$(is_sundog) \
src/improbable.a
$(CADIUS) REPLACEFILE "$(BUILDDISK)" "/$(DISKVOLUME)/" "$(EXE)" -C
@touch "$@"
$(DATA): $(BUILDDIR)
$(CADIUS) REPLACEFILE "$(BUILDDISK)" "/$(DISKVOLUME)/" "$@" -C
@touch "$@"
mount: $(BUILDDISK)
@open "$(BUILDDISK)"
clean:
rm -rf "$(BUILDDIR)"
$(BUILDDIR):
mkdir -p "$@"
$(CADIUS) CREATEVOLUME "$(BUILDDISK)" "$(DISKVOLUME)" 800KB -C
all: clean mount
.NOTPARALLEL:

Binary file not shown.

View File

@ -0,0 +1,352 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020
;zpage usage, arbitrary selection except for the "ProDOS constant" ones
;feel free to move them around
!if read_only=0 {
sparseblk = $50 ;(internal) last-read block was sparse
}
sizelo = $52 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking
sizehi = $53 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking
reqcmd = $54 ;set (read/write/seek) if enable_write=1 or enable_seek=1
;if allow_multi=1, bit 7 selects floppy drive in current slot (clear=drive 1, set=drive 2) during open call
;bit 7 must be clear for read/write/seek on opened file
ldrlo = $55 ;set to load address if override_adr=1
ldrhi = $56 ;set to load address if override_adr=1
namlo = $57 ;name of file to access
namhi = $58 ;name of file to access
command = $42 ;ProDOS constant
unit = $43 ;ProDOS constant
adrlo = $44 ;ProDOS constant
adrhi = $45 ;ProDOS constant
bloklo = $46 ;ProDOS constant
blokhi = $47 ;ProDOS constant
scratchlo = $48 ;(internal)
scratchhi = $49 ;(internal)
entries = $3f ;(internal) total number of entries in directory
treeidx = $59 ;(internal) index into tree block
treeblklo = $5a
treeblkhi = $5b
blkidx = $5c ;(internal) index into sapling block list
!set last_zp = $5c ;highest address to save if swap_zp enabled (max 127 entries later)
;constants
cmdseek = 0 ;requires enable_seek=1
cmdread = 1 ;requires enable_write=1
cmdwrite = 2 ;requires enable_write=1
SETKBD = $fe89
SETVID = $fe93
DEVNUM = $bf30
MLI = $bf00
NAME_LENGTH = $4 ;ProDOS constant
MASK_SUBDIR = $d0 ;ProDOS constant
MASK_ALL = $f0 ;ProDOS constant
KEY_POINTER = $11 ;ProDOS constant
EOF_LO = $15 ;ProDOS constant
EOF_HI = $16 ;ProDOS constant
AUX_TYPE = $1f ;ProDOS constant
ENTRY_SIZE = $27 ;ProDOS constant
NEXT_BLOCK_LO = $2 ;ProDOS constant
NEXT_BLOCK_HI = $3 ;ProDOS constant
SAPLING = $20 ;ProDOS constant
FILE_COUNT = $25 ;ProDOS constant
DEVADR01HI = $bf11 ;ProDOS constant
LCBANK1RO = $c080
ROMIN = $c081
LCBANK1 = $c083
LCBANK2 = $c089
first_zp = $40 ;lowest address to save if swap_zp enabled
;last_zp is calculated automatically
.init lda DEVNUM
sta .x80_parms + 1
sta .unrunit1 + 1
and #$70
pha
lda #1
sta namlo
lda #$80
sta namhi
;fetch path, if any
jsr MLI
!byte $c7
!word .c7_parms
ldx $8000
dex
stx sizelo
sec
bmi +++
;find current directory name in directory
php
.readblock jsr MLI
!byte $80
!word .x80_parms
lda #<(.readbuff + NAME_LENGTH)
sta scratchlo
lda #>(.readbuff + NAME_LENGTH)
sta scratchhi
.inextent ldy #0
lda (scratchlo), y
pha
and #$0f
tax
-- iny
lda (scratchlo), y
cmp (namlo), y
beq .ifoundname
;match failed, move to next directory in this block, if possible
- pla
.skiphdr clc
lda scratchlo
adc #ENTRY_SIZE
sta scratchlo
bcc +
;there can be only one page crossed, so we can increment instead of adc
inc scratchhi
+ cmp #<(.readbuff + $1ff) ;4 + ($27 * $0d)
lda scratchhi
sbc #>(.readbuff + $1ff)
bcc .inextent
;read next directory block when we reach the end of this block
lda .readbuff + NEXT_BLOCK_LO
ldx .readbuff + NEXT_BLOCK_HI
bcs +
.ifoundname dex
bne --
;parse path until last directory is seen
iny
lda (namlo), y
cmp #$2f ;'/'
bne -
pla
and #$20 ;Volume Directory Header XOR subdirectory
beq .adjpath
pla
clc
php
lsr
bcc .skiphdr
inx
.adjpath tya
eor #$ff
adc sizelo
sta sizelo
clc
tya
adc namlo
sta namlo
dex
beq ++
;cache block number of current directory
;as starting position for subsequent searches
ldy #(KEY_POINTER + 1)
lda (scratchlo), y
tax
dey
lda (scratchlo), y
sta .unrhddblocklo + 1
stx .unrhddblockhi + 1
+ sta .x80_parms + 4
stx .x80_parms + 5
++ lda sizelo
bne .readblock
pla
;unit to slot for ProDOS interface
+++ pla
lsr
lsr
lsr
tay
ldx DEVADR01HI, y
cpx #$c8
bcc .set_slot1
php
;find SmartPort device for basic MicroDrive support
ldx #$c8
- dex
stx scratchhi
ldy #0
sty scratchlo
iny
lda (scratchlo), y
cmp #$20
bne -
iny
iny
lda (scratchlo), y
bne -
iny
iny
lda (scratchlo), y
cmp #3
bne -
ldy #$ff
lda (scratchlo), y
beq -
.set_slot plp
.set_slot1 stx .slot + 2
stx .unrentry + 2
.slot ldx $cfff
stx .unrentry + 1
bcs ++
+ jmp .bankram
++ ldy #$8c ;STY
!if read_only=0 {
sty .unrcommand1
}
sty .unrcommand3
lda #<.pcommand
!if read_only=0 {
sta .unrcommand1 + 1
}
sta .unrcommand3 + 1
lda #>.pcommand
!if read_only=0 {
sta .unrcommand1 + 2
}
sta .unrcommand3 + 2
iny ;STA
sty .unrblokhi1
sty .unrunit1 + 2
iny ;STX
sty .unrbloklo1
;;lda #>.pblock
sta .unrbloklo1 + 2
!if read_only=0 {
sta .unrbloklo2 + 2
}
;;lda #>(.pblock + 1)
sta .unrblokhi1 + 2
!if read_only=0 {
sta .unrblokhi2 + 2
sta .unrblokhi3 + 2
}
;;lda #>.paddr
sta .unrunit1 + 4
ldy #<.pblock
sty .unrbloklo1 + 1
!if read_only=0 {
sty .unrbloklo2 + 1
}
iny
sty .unrblokhi1 + 1
!if read_only=0 {
sty .unrblokhi2 + 1
sty .unrblokhi3 + 1
}
lda #$a5 ;LDA
sta .unrunit1
!if read_only=0 {
lda #$ee ;INC
sta .unrblokhi2
ldy #$ad ;LDA
sty .unrblokhi3
iny ;LDX
sty .unrbloklo2
}
lda #adrlo
sta .unrunit1 + 1
lda #<.paddr
sta .unrunit1 + 3
;use SmartPort entrypoint instead
inx
inx
inx
stx .unrentry + 1
ldx #2
stx .x80_parms + 4
lda #0
sta .x80_parms + 5
jsr MLI
!byte $80
!word .x80_parms
sta .readbuff + $205
lda #cmdread
sta .unrpcommand
lda #$ea
sta .hackstar
.iterunit inc .unrunit2
jsr .unrentry
bcs .iterunit
+ ldy #$10
- lda .readbuff + 3, y
cmp .readbuff + $203, y
bne .iterunit
dey
bne -
lda #$68
sta .hackstar
lda #<.packet
sta .unrppacket
lda #>.packet
sta .unrppacket + 1
.bankram
!if is_sundog=1 {
ldx #>(.hddcodeend + $ff - .patch_jsr_swap_zpg)
ldy #0
.multicopy
- lda .unrelochdd, y
sta .reloc, y
iny
bne -
inc .multicopy + 2
inc .multicopy + 5
dex
bne .multicopy
}
!if disks>2 {
lda #disks
.find_vols
pha
}
jsr .hddopendir
!if disks>1 {
inc filename_e - 1
!if disks=2 {
jsr .hddopendir
} else {
pla
sec
sbc #1
bne .find_vols
}
}

View File

@ -0,0 +1,89 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020
;read volume directory key block
;self-modified by init code
.hddopendir
.unrhddblocklo = *
ldx #2
.unrhddblockhi = *
lda #0
.hddreaddir1 jsr .hddreaddirsel
.hddfirstent lda #NAME_LENGTH
sta scratchlo
lda #>(pas_hdddirbuf - 1)
sta scratchhi
;there can be only one page crossed, so we can increment here
.hddnextent1 inc scratchhi
.hddnextent ldy #0
;match name lengths before attempting to match names
lda (scratchlo), y
and #$0f
tax
inx
- cmp filename, y
beq .hddfoundname
;match failed, move to next entry in this block, if possible
+ clc
lda scratchlo
adc #ENTRY_SIZE
sta scratchlo
bcs .hddnextent1
cmp #$ff ;4 + ($27 * $0d)
bne .hddnextent
;read next directory block when we reach the end of this block
ldx pas_hdddirbuf + NEXT_BLOCK_LO
lda pas_hdddirbuf + NEXT_BLOCK_HI
bcs .hddreaddir1
.hddfoundname iny
lda (scratchlo), y
dex
bne -
stx .zp_array + treeidx - first_zp
stx .zp_array + blkidx - first_zp
;fetch KEY_POINTER
!if disks>1 {
ldx .vol_idx
inc .vol_idx
}
ldy #KEY_POINTER
lda (scratchlo), y
!if disks=1 {
sta .zp_array + treeblklo - first_zp
} else {
sta .blokloarray, x
}
iny
lda (scratchlo), y
!if disks=1 {
sta .zp_array + treeblkhi - first_zp
} else {
sta .blokhiarray, x
}
ldy #>pas_hddtreebuf
jmp .hddreaddirsect
!if disks>1 {
.vol_idx !byte 0
}
.c7_parms !byte 1
!word $8000
.x80_parms !byte 3, $d1
!word .readbuff, 2

View File

@ -0,0 +1,121 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020
.hddrdfile
.hddrdwrfile
.hddrdwrfilei
.hddrdwrloop
!if read_only=0 {
ldy #0
sty sparseblk
}
;fetch tree data block and read it
ldx treeblklo
lda treeblkhi
.patch_jsr_hddreaddirsel
jsr .hddreaddirsel
ldy treeidx
.patch_ldx_hdddirbuf1
ldx pas_hdddirbuf, y
.patch_lda_hdddirbuf1
lda pas_hdddirbuf + 256, y
.patch_jsr_hddseekrd2
jsr .hddseekrd
;fetch data block and read/write it
.hddskiptree ldy blkidx
.patch_ldx_hdddirbuf2
ldx pas_hdddirbuf, y
.patch_lda_hdddirbuf2
lda pas_hdddirbuf + 256, y
pha
.patch_ora_hdddirbuf
ora pas_hdddirbuf, y
cmp #1
pla
!if read_only=0 {
ldy reqcmd
bcs .hddseekrdwr
} else {
bcs .hddseekrd
}
.savebyte
tay
.hddissparse
- sta (adrlo), y
inc adrhi
sta (adrlo), y
dec adrhi
iny
bne -
!if read_only=0 {
inc sparseblk
}
.skipblk rts
.hddreaddirsel
ldy #0
sty adrlo
.hddreaddirsec
.patch_ldy_hdddirbuf
ldy #>pas_hdddirbuf
.hddreaddirsect
sty adrhi
.hddseekrd ldy #cmdread
.hddseekrdwr
.unrcommand3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
.unrbloklo1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
stx bloklo
nop ;allow replacing "stx bloklo" with "stx pblock" in extended SmartPort mode
.unrblokhi1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sta blokhi
nop ;allow replacing "sta blokhi" with "sta pblock + 1" in extended SmartPort mode
.unrunit1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda #$d1
sta unit
nop ;allow replacing "lda #$d1/sta unit" with "lda adrlo/sta paddr" in extended SmartPort mode
.hddwriteimm lda adrhi ;for Trackstar support
pha
.patch_sta_paddr
sta .paddr + 1
.unrentry = .unrelochdd + (* - .patch_jsr_swap_zpg)
jsr $d1d1
.unrpcommand = .unrelochdd + (* - .patch_jsr_swap_zpg)
.pcommand !byte $2c ;hide packet in non-SmartPort mode
.unrppacket = .unrelochdd + (* - .patch_jsr_swap_zpg)
!word .unrelochdd + (.packet - .patch_jsr_swap_zpg)
.hackstar = .unrelochdd + (* - .patch_jsr_swap_zpg)
pla
sta adrhi ;Trackstar does not preserve adrhi
rts
.unrpacket = .unrelochdd + (* - .patch_jsr_swap_zpg)
.packet !byte 3
.unrunit2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
!byte 0
.paddr !word .readbuff + $200
.pblock !byte 2, 0, 0
.hddcodeend
!if disks>1 {
.blokloarray
.blokhiarray = .blokloarray + disks
.zp_array = .blokhiarray + disks
} else {
.zp_array
}
zp_array = .zp_array
.hdddataend = .zp_array + 1 + last_zp - first_zp

View File

@ -0,0 +1,609 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($AFE8 + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($AFE8 + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($AFE8 + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $AFE8 + $23, y
lda .reloc + $100, y
sta $AFE8 + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $b6ad, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $b734, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($befe) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
.patch_sta_curvolidx
sta .curvolidx + 1
jmp $927B
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $b6ad-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$92
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #$bf
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "RTSTRP.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,625 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
lda ROMIN
lda ROMIN
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
lda $CD
cmp #$10
bne +
inc $3a4
lda #0
+ sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0E8 + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0E8 + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0E8 + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0E8 + $23, y
lda .reloc + $100, y
sta $D0E8 + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $d6ad, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $d72c, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d23B
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $d6ad-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "SYSTEM.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_lda_hddencbuf_29 + 1)
!byte <(.patch_lda_hddencbuf_2a + 1)
!byte <(.patch_ldx_hddencbuf_27 + 1)
!byte <(.patch_lda_hddencbuf_28 + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 1)
!byte <(.patch_sta_hdddirbuf2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_lda_hddencbuf_29 + 1)
!byte >(.patch_lda_hddencbuf_2a + 1)
!byte >(.patch_ldx_hddencbuf_27 + 1)
!byte >(.patch_lda_hddencbuf_28 + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 1)
!byte >(.patch_sta_hdddirbuf2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,329 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
;user-defined driver load address
ldx #0
stx $3A8 ;adrlo
inx
stx $3AC ;read
lda ROMIN
lda ROMIN
ldx #6
lda #0
jsr .loadpascal
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0E8 + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0E8 + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0E8 + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0E8 + $23, y
lda .reloc + $100, y
sta $D0E8 + $23 + $100, y
iny
bne -
.banklc1 lda $C083 ;varies by version
ldx #2
- lda .hook_wipe, x
sta $d6ad, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $d72c, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
.patch_jsr lda .unhook-1, x
sta $d6ad-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte <(.patch_jsr_swap_zpg + 1)
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte >(.patch_jsr_swap_zpg + 1)
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
bne .loopsect
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,551 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
;user-defined driver load address
ldx #0
stx $3A8 ;adrlo
inx
stx $3AC ;read
lda ROMIN
lda ROMIN
ldx #$10
lda #0
jsr .loadpascal
sta .endadr + 1
ldx #$FE
stx .startadr + 1
ldx #$23
jsr .loadpascal
lda LCBANK2
lda #$D0
sta .startadr + 1
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0E8 + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0E8 + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0E8 + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0E8 + $23, y
lda .reloc + $100, y
sta $D0E8 + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $d6ad, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $d72c, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.magic_b
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d23B
.magic_e
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
.patch_jsr lda .unhook-1, x
sta $d6ad-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #$f6
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte <(.patch_sta_curvolidx + 1)
!byte <(.patch_jsr_swap_zpg + 1)
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte >(.patch_sta_curvolidx + 1)
!byte >(.patch_jsr_swap_zpg + 1)
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
lda $3AC
lsr
bne .runinit
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
ldy #cmdread
sty reqcmd
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,635 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
lda ROMIN
lda ROMIN
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0EC + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0EC + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0EC + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0EC + $23, y
lda .reloc + $100, y
sta $D0EC + $23 + $100, y
iny
bne -
ldx #2
lda $f28c
cmp #$e6
bne + ;other variant, wipe address moved, the rest is the same
- lda .hook_wipe, x
sta $f28c, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $f314, x ;varies by version
dex
bpl -
bmi ++
+
- lda .hook_wipe, x
sta $f72c, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $f7b6, x ;varies by version
dex
bpl -
++
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d27B
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $680f-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "SYSTEM.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,609 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($B0EC + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($B0EC + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($B0EC + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $B0EC + $23, y
lda .reloc + $100, y
sta $B0EC + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $927a, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $930c, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($befe) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
.patch_sta_curvolidx
sta .curvolidx + 1
jmp $997B
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $680f-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$92
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #$bf
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "RTSTRP.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,621 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
lda ROMIN
lda ROMIN
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0EC + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0EC + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0EC + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0EC + $23, y
lda .reloc + $100, y
sta $D0EC + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $f29f, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $f329, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d27B
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $680f-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "SYSTEM.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,584 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
lda ROMIN
lda ROMIN
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0EC + $23 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0EC + $23 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0EC + $23 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0EC + $23, y
lda .reloc + $100, y
sta $D0EC + $23 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $f29f, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $f329, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
inc $cbe
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d27B
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $680f-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "SYSTEM.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte <(.patch_sta_curvolidx + 1)
!byte <(.patch_jsr_swap_zpg + 1)
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!byte >(.patch_sta_curvolidx + 1)
!byte >(.patch_jsr_swap_zpg + 1)
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
lda $3AC
lsr
bne .runinit
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
ldy #cmdread
sty reqcmd
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,621 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!src "src/bootstar/boot.common.2.inc"
.pascal_dir = $8000
ldx #$ff
stx $BF ;partial sector (force mismatch)
inx
stx $BE ;byte count for partial sector
stx $fe
stx $3A4 ;track
stx $3A8 ;adrlo
inx
stx $3A2 ;drive
stx $3AC ;read
lda #4
sta $BD ;block number
asl
sta $C3 ;sector count
lda #>.pascal_dir
sta $ff
sta $3A9 ;adrhi
jsr .reloc
-- ldy #7
ldx #.startup_e - .startup_b
- lda .startup_b - 7, y
cmp ($fe), y
beq +
clc
lda $fe
adc #$1a
sta $fe
bcc --
inc $ff
bne -- ;always taken
+ iny
dex
bne -
lda ROMIN
lda ROMIN
ldy #0
lda ($fe), y
tax
iny
lda ($fe), y
jsr .loadpascal
lda $CD
sta $BD
lda #$E0
sta .endadr + 1
lda LCBANK2
jsr .startadr
bit LCBANK1
tax
tay
.reloc_code1
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #>(((($D0EA + $25 + .hdddataend - .patch_jsr_swap_zpg) + $ff) & -256) - pas_hddencbuf)
sta ($fe), y
inx
bne .reloc_code1 ;always
+
lda .unrcommand3
cmp #$8c ;STY
.reloc_more
php
.reloc_code2
inx
lda .patch_tbl_hi, x
beq +
sta $ff
lda .patch_tbl_lo, x
sta $fe
clc
lda ($fe), y
adc #<($D0EA + $25 - .unrelochdd)
sta ($fe), y
iny
lda ($fe), y
adc #>($D0EA + $25 - .unrelochdd)
sta ($fe), y
dey
beq .reloc_code2 ;always
+ pla
and #1 ;check for carry set previously
bne .reloc_more ;carry is clear now
ldy #0
- lda .reloc, y
sta $D0EA + $25, y
lda .reloc + $100, y
sta $D0EA + $25 + $100, y
iny
bne -
ldx #2
- lda .hook_wipe, x
sta $f2d9, x
dex
bpl -
ldx #(.hidedrive_e-.hidedrive)-1
- lda .hidedrive, x
sta $f398, x ;varies by version
dex
bpl -
txs
.jmpindirect jmp ($fff8) ;varies by version
.hook_wipe jsr .callback
.hidedrive asl
sta $BF2C
sta $BF2E
ldy #2
sty $BF2D
.hidedrive_e
.magic_b
!if disks>1 {
iny
lda ($58), y ;get volume number
bit $c083
.patch_sta_curvolidx
sta .curvolidx + 1
bit $c08b
jmp $d293
}
.magic_e
.callback lda #$f2
sta $BD
!if backup_prodos=1 {
ldy #$1e + $25 + 3 ;3 = preserve size
} else {
ldy #$1e + 3 ;3 = preserve size
}
txa
beq .skippage
cpx #3
bne .nextpage
!if (.magic_e-.magic_b)>0 {
ldy #(.magic_e-.magic_b) - 1
- lda .magic_b, y
sta $100, y
dey
bpl -
}
.patch_jsr lda .unhook-1, x
sta $680f-1, x ;varies by version
dex
bne .patch_jsr
stx $BD
ldx #7
stx $BE
.nextpage ldy #0
tya
.unhook inc $BE
.skippage inx
rts
.loadpascal lsr
txa
ror
lsr
lsr
sta $3A4
txa
and #7
asl
sta $BD
.startadr lda #$d0
sta $3A9
eor #$ff
sec
adc .endadr + 1
cmp #$10
bcc +
lda #$10
sec
sbc $BD
+
- sta $C3
jsr .reloc
lda #0
sta $BD
lda $CF
sta $3A9
sec
.endadr lda #0
sbc $3A9
beq +
inc $3A4
cmp #$10
bcc -
lda #$10
bne -
+ rts
.startup_b !text "SYSTEM.APPLE"
.startup_e
.patch_tbl_lo
!byte <(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte <(.patch_lda_hddencbuf_29 + 2)
!byte <(.patch_lda_hddencbuf_2a + 2)
!byte <(.patch_ldx_hddencbuf_27 + 2)
!byte <(.patch_lda_hddencbuf_28 + 2)
!byte <(.patch_ldy_hddencbuf + 1)
!byte <(.patch_cmp_hddencbuf_2 + 1)
!byte <(.patch_sta_hdddirbuf1 + 2)
!byte <(.patch_sta_hdddirbuf2 + 2)
!byte <(.patch_lda_hddencbuf2 + 1)
}
!byte <(.patch_ldx_hdddirbuf1 + 2)
!byte <(.patch_lda_hdddirbuf1 + 2)
!byte <(.patch_ldx_hdddirbuf2 + 2)
!byte <(.patch_lda_hdddirbuf2 + 2)
!byte <(.patch_ora_hdddirbuf + 2)
!byte <(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte <(.patch_sta_curvolidx + 1)
}
!byte <(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte <(.patch_lda_blokloarray + 1)
!byte <(.patch_lda_blokhiarray + 1)
}
!byte <(.patch_ora_secttbl + 1)
!byte <(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte <(.patch_jmp_loopsect1 + 1)
!byte <(.patch_jsr_hddwriteenc1 + 1)
}
!byte <(.patch_ldy_zp_array + 1)
!byte <(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte <(.patch_jsr_hddreaddirsec + 1)
!byte <(.patch_jsr_hddseekrd1 + 1)
!byte <(.patch_jsr_hddwriteenc2 + 1)
!byte <(.patch_sta_hddskiptree1_2 + 1)
!byte <(.patch_jsr_hddrdfile + 1)
!byte <(.patch_sta_hddskiptree2_2 + 1)
!byte <(.patch_jsr_hddwritedir + 1)
!byte <(.patch_jsr_savebyte + 1)
!byte <(.patch_jsr_hddseekrdwr + 1)
!byte <(.patch_jmp_loopsect2 + 1)
}
!byte <(.patch_jsr_hddreaddirsel + 1)
!byte <(.patch_jsr_hddseekrd2 + 1)
!byte <(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte <(.unrbloklo2 + 1)
!byte <(.unrblokhi2 + 1)
!byte <(.unrblokhi3 + 1)
!byte <(.unrcommand1 + 1)
}
!byte <(.unrcommand3 + 1)
!byte <(.unrbloklo1 + 1)
!byte <(.unrblokhi1 + 1)
!byte <(.unrunit1 + 3)
!byte <.unrppacket
!byte 0
.patch_tbl_hi
!byte >(.patch_lda_hddencbuf1 + 1)
!if read_only=0 {
!byte >(.patch_lda_hddencbuf_29 + 2)
!byte >(.patch_lda_hddencbuf_2a + 2)
!byte >(.patch_ldx_hddencbuf_27 + 2)
!byte >(.patch_lda_hddencbuf_28 + 2)
!byte >(.patch_ldy_hddencbuf + 1)
!byte >(.patch_cmp_hddencbuf_2 + 1)
!byte >(.patch_sta_hdddirbuf1 + 2)
!byte >(.patch_sta_hdddirbuf2 + 2)
!byte >(.patch_lda_hddencbuf2 + 1)
}
!byte >(.patch_ldx_hdddirbuf1 + 2)
!byte >(.patch_lda_hdddirbuf1 + 2)
!byte >(.patch_ldx_hdddirbuf2 + 2)
!byte >(.patch_lda_hdddirbuf2 + 2)
!byte >(.patch_ora_hdddirbuf + 2)
!byte >(.patch_ldy_hdddirbuf + 1)
!byte 0
!if disks>1 {
!byte >(.patch_sta_curvolidx + 1)
}
!byte >(.patch_jsr_swap_zpg + 1)
!if disks>1 {
!byte >(.patch_lda_blokloarray + 1)
!byte >(.patch_lda_blokhiarray + 1)
}
!byte >(.patch_ora_secttbl + 1)
!byte >(.patch_jsr_seek1 + 1)
!if read_only=0 {
!byte >(.patch_jmp_loopsect1 + 1)
!byte >(.patch_jsr_hddwriteenc1 + 1)
}
!byte >(.patch_ldy_zp_array + 1)
!byte >(.patch_sta_zp_array + 1)
!if read_only=0 {
!byte >(.patch_jsr_hddreaddirsec + 1)
!byte >(.patch_jsr_hddseekrd1 + 1)
!byte >(.patch_jsr_hddwriteenc2 + 1)
!byte >(.patch_sta_hddskiptree1_2 + 1)
!byte >(.patch_jsr_hddrdfile + 1)
!byte >(.patch_sta_hddskiptree2_2 + 1)
!byte >(.patch_jsr_hddwritedir + 1)
!byte >(.patch_jsr_savebyte + 1)
!byte >(.patch_jsr_hddseekrdwr + 1)
!byte >(.patch_jmp_loopsect2 + 1)
}
!byte >(.patch_jsr_hddreaddirsel + 1)
!byte >(.patch_jsr_hddseekrd2 + 1)
!byte >(.patch_sta_paddr + 1)
!byte 0
!if read_only=0 {
!byte >(.unrbloklo2 + 1)
!byte >(.unrblokhi2 + 1)
!byte >(.unrblokhi3 + 1)
!byte >(.unrcommand1 + 1)
}
!byte >(.unrcommand3 + 1)
!byte >(.unrbloklo1 + 1)
!byte >(.unrblokhi1 + 1)
!byte >(.unrunit1 + 3)
!byte >.unrppacket
!byte 0
.c5_parms
!byte 2
!byte 0
!word $281
!byte $d1
!src "src/bootstar/boot.common.3.inc"
.unrelochdd
.reloc = .unrelochdd ;no need to move
!pseudopc .reloc {
.patch_jsr_swap_zpg
jsr .swap_zpg
lda $BD
sta $CD
lda $3A8
sta $CE
lda $3A9
sta $CF
!if disks>1 {
.curvolidx
ldx #0 ;SMC
.patch_lda_blokloarray
lda .blokloarray, x
sta treeblklo
.patch_lda_blokhiarray
lda .blokhiarray, x
sta treeblkhi
}
lda #9
sta $3AD ;error (drive not ready)
lda $3a2
cmp #2
bcs .swap_zpgi
.loopsect
lda #0
sta sizehi
lda $CD
and #$0f
tay
lda $3A4
asl
asl
asl
rol sizehi
asl
rol sizehi
.patch_ora_secttbl
ora .secttbl, y
tax
lda sizehi
lsr
sta treeidx
txa
ror
php
.patch_jsr_seek1
jsr .seek1
plp
ldy #0
tya
.patch_lda_hddencbuf1
adc #>pas_hddencbuf
sta adrhi
!if read_only=0 {
lda $3AC
lsr
bne .runinit
}
lda $BE
beq .copysect
ldx $C3
dex
bne .copysect
ldx $CD
inx
txa
sec
sbc $BD
cmp $BF
bne .copysect
lda $CF
sta $C5
sty $CE
lda #2
sta $CF
.copysect lda (adrlo),y
sta ($CE),y
iny
bne .copysect
.nextsect inc $CD
inc $CF
dec $C3
!if read_only=0 {
beq .swap_zpg
.patch_jmp_loopsect1
jmp .loopsect
.runinit
lda sparseblk
bne .writesparse
- lda ($CE),y
sta (adrlo),y
iny
bne -
.patch_jsr_hddwriteenc1
jsr .hddwriteenc
bne .nextsect
} else {
bne .loopsect
}
.swap_zpg
clc
.swap_zpgi ldx #(last_zp - first_zp)
- lda first_zp,x
.patch_ldy_zp_array
ldy .zp_array,x
.patch_sta_zp_array
sta .zp_array,x
sty first_zp,x
dex
bpl -
rts
!if read_only=0 {
.writesparse ldx #2
tya
.patch_jsr_hddreaddirsec
jsr .hddreaddirsec
lda #0
sta namlo
sta namhi
;round up to block count
.patch_lda_hddencbuf_29
lda pas_hddencbuf + $29
adc #$ff
.patch_lda_hddencbuf_2a
lda pas_hddencbuf + $2A
adc #1
lsr
sta ldrhi
.patch_ldx_hddencbuf_27
ldx pas_hddencbuf + $27
.patch_lda_hddencbuf_28
lda pas_hddencbuf + $28
.patch_ldy_hddencbuf
--- ldy #>pas_hddencbuf
sty adrhi
.patch_jsr_hddseekrd1
jsr .hddseekrd
ldy #0
;scan for a free block
-- lda #$80
sta ldrlo
- lda (adrlo), y
and ldrlo
bne .foundbit
lsr ldrlo
inc namlo
bcc -
bne +
inc namhi
+ iny
bne --
inc adrhi
lda adrhi
.patch_cmp_hddencbuf_2
cmp #(>pas_hddencbuf) + 2
bne --
.unrbloklo2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
ldx bloklo
nop ;allow replacing "ldx bloklo" with "ldx pblock" in extended SmartPort mode
inx
bne +
.unrblokhi2 = .unrelochdd + (* - .patch_jsr_swap_zpg)
inc blokhi
nop ;allow replacing "inc blokhi" with "inc pblock + 1" in extended SmartPort mode
+
.unrblokhi3 = .unrelochdd + (* - .patch_jsr_swap_zpg)
lda blokhi
nop ;allow replacing "lda blokhi" with "lda pblock + 1" in extended SmartPort mode
dec ldrhi
bne ---
;disk full
beq .swap_zpg
;allocate block and update bitmap
.foundbit lda (adrlo), y
eor ldrlo
sta (adrlo), y
.patch_jsr_hddwriteenc2
jsr .hddwriteenc
lda #$60 ;RTS
.patch_sta_hddskiptree1_2
sta .hddskiptree + 2
.patch_jsr_hddrdfile
jsr .hddrdfile
lda #$be ;LDX ,Y
.patch_sta_hddskiptree2_2
sta .hddskiptree + 2
lda namlo
.patch_sta_hdddirbuf1
sta pas_hdddirbuf, y
lda namhi
.patch_sta_hdddirbuf2
sta pas_hdddirbuf + 256, y
.patch_jsr_hddwritedir
jsr .hddwritedir
lda #0
.patch_jsr_savebyte
jsr .savebyte
ldx namlo
lda namhi
ldy #cmdwrite
.patch_jsr_hddseekrdwr
jsr .hddseekrdwr
.patch_jmp_loopsect2
jmp .loopsect
.hddwriteenc
.patch_lda_hddencbuf2
lda #>pas_hddencbuf
sta adrhi
.hddwritedir ldy #cmdwrite
.unrcommand1 = .unrelochdd + (* - .patch_jsr_swap_zpg)
sty command
nop ;allow replacing "sty command" with "sty pcommand" in extended SmartPort mode
bne .hddwriteimm
}
.secttbl !byte $00, $0e, $0d, $0c, $0b, $0a, $09, $08, $07, $06, $05, $04, $03, $02, $01, $0f
.seek1 sta blkidx
!if read_only=0 {
ldy #cmdread
sty reqcmd
}
!src "src/bootstar/boot.common.5.inc"
} ;reloc
;[music] you can't touch this [music]
;math magic to determine ideal loading address, and information dump
!ifdef PAS_PASS2 {
} else { ;PAS_PASS2 not defined
!set PAS_PASS2=1
!pseudopc ((.hdddataend + $ff) & -256) {
pas_hdddirbuf = *
}
pas_hddencbuf = pas_hdddirbuf ;writes come from cache
pas_hddtreebuf = pas_hdddirbuf
} ;PAS_PASS2
.readbuff
!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE

View File

@ -0,0 +1,125 @@
;license:BSD-3-Clause
;extended open/read/write binary file in ProDOS filesystem, with random access
;copyright (c) Peter Ferrie 2013-2020, 2025
!ct "src/rcase.ct"
!if is_64kb=1 and is_128kb=1 {
!error "set only one of is_64kb or is_128kb"
}
!if (is_apa=1 and (is_uukrul=1 or is_sundog=1 or is_reading=1)) or (is_uukrul=1 and (is_sundog=1 or is_reading=1)) or (is_sundog=1 and is_reading=1) {
!error "set at most one of is_apa and is_uukrul and is_sundog and is_reading"
}
!if is_apa=1 {
!if version != 1 {
!error "is_apa requires version=1"
}
!if is_64kb=0 {
!error "is_apa requires is_64kb=1"
}
!if read_only=0 {
!error "is_apa requires read_only=1"
}
!if disks>1 {
!error "is_apa requires disks=1"
}
}
!if is_uukrul=1 {
!if version != 1 {
!error "is_uukrul requires version=1"
}
!if is_64kb=0 {
!error "is_uukrul requires is_64kb=1"
}
!if read_only=1 {
!error "is_uukrul requires read_only=0"
}
!if disks!=2 {
!error "is_uukrul requires disks=2"
}
}
!if is_sundog=1 {
!if version != 2 {
!error "is_sundog requires version=2"
}
!if is_64kb=0 {
!error "is_sundog requires is_64kb=1"
}
!if read_only=1 {
!error "is_sundog requires read_only=0"
}
!if disks!=1 {
!error "is_sundog requires disks=1"
}
}
!if is_reading=1 {
!if version != 2 {
!error "is_reading requires version=2"
}
!if is_64kb=0 {
!error "is_reading requires is_64kb=1"
}
!if read_only=1 {
!error "is_reading requires read_only=0"
}
!if disks!=2 {
!error "is_reading requires disks=2"
}
}
!if version=1 {
!if is_64kb=0 {
!if is_128kb=0 {
!src "src/bootstar/boot.pascal.11_48kb.a"
} else {
!src "src/bootstar/boot.pascal.11_128kb.a"
}
} else {
!if is_apa=1 {
!src "src/bootstar/boot.pascal.11_64kb_apa.a"
} else {
!if is_uukrul=1 {
!src "src/bootstar/boot.pascal.11_64kb_uukrul.a"
} else {
!src "src/bootstar/boot.pascal.11_64kb.a"
}
}
}
} else {
!if version=2 {
!if is_64kb=0 {
!if is_128kb=0 {
!src "src/bootstar/boot.pascal.12_48kb.a"
} else {
!src "src/bootstar/boot.pascal.12_128kb.a"
}
} else {
!if is_sundog=1 {
!src "src/bootstar/boot.pascal.12_64kb_sundog.a"
} else {
!if is_reading=1 {
!src "src/bootstar/boot.pascal.12_64kb_reading.a"
} else {
!src "src/bootstar/boot.pascal.12_64kb.a"
}
}
}
} else {
!if is_64kb=0 {
!if is_128kb=0 {
!error "no known sample of 1.3 48kb"
;;!src "src/bootstar/boot.pascal.13_48kb.a"
} else {
!error "no known sample of 1.3 128kb"
;;!src "src/bootstar/boot.pascal.13_128kb.a"
}
} else {
!src "src/bootstar/boot.pascal.13_64kb.a"
}
}
}

View File

@ -0,0 +1,32 @@
;license:MIT
;(c) 2025 by 4am
;
SELF_MODIFIED_BYTE = $FD
SELF_MODIFIED_WORD = $FDFD
; ProDOS
PRODOS_MLI = $BF00
PRODOS_MACHID = $BF98
CMD_QUIT = $65
; ROM routines and addresses
ROM_MACHID = $FBB3
ROM_FINALIZE_RESET = $FB6F
; soft switches
STOREOFF = $C000
CLEARKBD = $C010
READMAINMEM = $C002
READAUXMEM = $C003
WRITEMAINMEM = $C004
WRITEAUXMEM = $C005
RWMAINZPSTACK = $C008
RWAUXZPSTACK = $C009
; application-specific addresses
!if is_reading=1 {
OnReset = $0113
} else {
OnReset = $0110
}

View File

@ -0,0 +1,211 @@
;license:MIT
;(c) 2025 by 4am
;
!cpu 6502
!ct "src/lcase.ct"
!to "build/STRATEGIC.CRAPS#FF2000",plain
*=$2000
!src "src/macros.a"
!ifndef version {
!serious "version is not defined"
}
!if version<>1 and version<>2 and version<>3 {
!serious "version must be 1, 2, or 3"
}
!ifndef disks {
!serious "disks is not defined"
}
!if disks<1 {
!serious "disks must be greater than 0"
}
+REQUIRE_BOOL is_64kb, "is_64kb"
+REQUIRE_BOOL is_128kb, "is_128kb"
+REQUIRE_BOOL read_only, "read_only"
+REQUIRE_BOOL backup_prodos,"backup_prodos"
;Mindscape Reading Workshop stores keypresses in a variable prior to disk-swap
+REQUIRE_BOOL is_reading, "is_reading"
; Apple Presents Apple is a v1.1 64kb variant with reversed LC bank accesses
+REQUIRE_BOOL is_apa, "is_apa"
; The Dark Heart of Uukrul is a v1.1 64kb variant that bypasses the startup file
+REQUIRE_BOOL is_uukrul, "is_uukrul"
;;--support next update--
; SunDog is a v1.2 64kb variant that has custom startup code
+REQUIRE_BOOL is_sundog, "is_sundog"
!src "src/constants.a"
jmp Start
filename +PSTRING "STRATCRAPS" ; if disks>1, last character will be incremented for each disk
filename_e
!if backup_prodos=1 {
onResetMove
!pseudopc OnReset {
sta RWAUXZPSTACK ; runs from $0110/main
; the rest of this routine runs from aux
; (it's copied to main and aux stacks)
sei
cld
sta READAUXMEM
sta WRITEMAINMEM
jsr CopyProgramAndProDOS
sta READMAINMEM
jmp ReenterCold
CopyProgramAndProDOS
; this routine is relocated to auxmem and called (by OnReset)
; but also called from its original location in mainmem (by BackupMemory)
ldy #0
- lda $BF00, y
sta $BF00, y
lda $2000, y
sta $2000, y
iny
bne -
rts
}
onResetMoveLength=*-onResetMove
;------------------------------------------------------------------------------
; CopyLC10/CopyLC30
; Copies language card banks from main LC to aux LC
; (or, after modification, from aux LC to main LC)
;
; Routine runs from somewhere in $0200-$BFFF/main, so we can switch
; RWMAINZPSTACK/RWAUXZPSTACK freely. Despite the name, this is the softswitch
; that switches between main LC and aux LC.
;
; out: X = 0
; Y = 0
; Z = 1
; all other registers and flags clobbered
; RWMAINZPSTACK
;------------------------------------------------------------------------------
CopyLC10
ldx #$10
stx $03F2
+HIDE_NEXT_2_BYTES
CopyLC30
ldx #$30
ldy #$00
lda #$D0
sta copyLCSrcPage
sta copyLCDstPage
-
copyLCSrcBank=*+1
sta RWMAINZPSTACK ; [SMC by caller, might be RWALTZPSTACK]
copyLCSrcPage=*+2
lda $FD00, y ; [SMC high byte]
copyLCDstBank=*+1
sta RWAUXZPSTACK ; [SMC by caller, might be RWMAINZPSTACK]
copyLCDstPage=*+2
sta $FD00, y ; [SMC high byte]
iny
bne -
inc copyLCSrcPage
inc copyLCDstPage
dex
bne -
sta RWMAINZPSTACK ; always
rts
;------------------------------------------------------------------------------
; ReenterCold
; Restore ProDOS and quit-to-ProDOS gracefully after user presses Ctrl-Reset
;
; in: READMAINMEM / WRITEMAINMEM
; RWAUXZPSTACK
; out: does not return, exits via ProDOS MLI Quit
;------------------------------------------------------------------------------
ReenterCold
sta RWMAINZPSTACK ; switch back to main stack before any JSR
+READ_RAM2_WRITE_RAM2
jsr CopyLC30
backupf800=*+1
lda #SELF_MODIFIED_BYTE
sta $F800 ; clobbered by Pascal runtime
backupfc00=*+1
lda #SELF_MODIFIED_BYTE
sta $FC00 ; clobbered by Pascal runtime
+READ_RAM1_WRITE_RAM1
jsr CopyLC10
cli
} ; backup_prodos
Quit
jsr PRODOS_MLI
!byte CMD_QUIT
!if backup_prodos=1 {
!word byte_4
} else {
!word +
+ !byte 4
} ; backup_prodos=0
!if (* > $20FF) { !serious "ReenterCold routine is too large" }
!if backup_prodos=1 {
;------------------------------------------------------------------------------
; BackupMemory
; Copies both language card banks and selected contents of
; main memory to auxiliary memory.
; Copies code to $0110/main to jump to $0113/aux.
; Copies code to $0113/aux to jump to RestoreCold.
; Sets reset vector to $0110.
;
; in: READMAINMEM / WRITEMAINMEM
; out: all registers and flags clobbered
; Read ROM / No Write
; READMAINMEM / WRITEMAINMEM
;------------------------------------------------------------------------------
BackupMemory
+READ_RAM2_WRITE_RAM2
lda $F800 ; clobbered by Pascal runtime in aux-LC later
sta backupf800
lda $FC00 ; clobbered by Pascal runtime in aux-LC later
sta backupfc00
jsr CopyLC30 ; copy $D000..$FFFF/main-LC2 to $D000/aux-LC2
+READ_RAM1_WRITE_RAM1_1
jsr CopyLC10 ; copy $D000..$DFFF/main-LC1 to $D000/aux-LC1
+READ_ROM_NO_WRITE
inc copyLCSrcBank ; modify CopyLC routine so RestoreCold
dec copyLCDstBank ; will copy from aux LC to main LC
sta WRITEAUXMEM ; copy ReenterCold and ProDOS global page BF to auxmem
jsr CopyProgramAndProDOS+onResetMove-OnReset
sta WRITEMAINMEM
ldy #onResetMoveLength
- lda onResetMove-1, y
sta RWAUXZPSTACK ; copy bootstrap routines into aux and main stacks
sta OnReset-1, y
sta RWMAINZPSTACK
sta OnReset-1, y
dey
bne -
iny
sty $03F3 ; set reset vector to bootstrap routine in main stack
jmp ROM_FINALIZE_RESET
} ; backup_prodos=1
Start
inc $03F4 ; reboot on reset unless we set up a better reset later
lda PRODOS_MACHID ; requires 64K, supports 128K
!if backup_prodos=1 {
and #%00110000
cmp #%00110000 ; 128K?
byte_4=*+1
!if (* > $20FF) { !serious "code is too large for byte_4 hack" }
bne no128k
jsr BackupMemory ; copy ProDOS and some application code to auxmem for later
!byte $AD
no128k
;!if (*-byte_4-1 <> 4) { !serious "byte_4 is not 4" }
} ; backup_prodos=1
and #%00100000 ; 64K?
beq Quit ; can't continue without at least 64K
!src "src/bootstar/boot.pascal.a"

View File

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

View File

@ -0,0 +1,86 @@
;license:MIT
;(c) 2025 by 4am
;
; common assembler macros (6502 compatible)
;
!macro REQUIRE_BOOL .var, .name {
!ifndef .var {
!serious .name," is not defined"
}
!if .var<>0 and .var<>1 {
!serious .name," must be 0 or 1"
}
}
!macro PSTRING .string {
!byte +-*-1
!raw .string
+
}
; load the address of .ptr into A (low) and Y (high)
!macro LDADDR .ptr {
lda #<.ptr
ldy #>.ptr
}
; load a 16-bit value into A (low) and Y (high)
!macro LD16 .ptr {
lda .ptr
ldy .ptr+1
}
; store a 16-bit value from A (low) and Y (high)
!macro ST16 .ptr {
sta .ptr
sty .ptr+1
}
; use BIT to swallow the following 1-byte opcode
!macro HIDE_NEXT_BYTE {
!byte $24
}
; use BIT to swallow the following 2-byte opcode
!macro HIDE_NEXT_2_BYTES {
!byte $2C
}
; various language card configurations
!macro READ_RAM1_NO_WRITE {
sta $C088
}
!macro READ_RAM1_WRITE_RAM1_1 { ; when the other bank is in already
; just one access is needed
bit $C08B
}
!macro READ_RAM1_WRITE_RAM1 {
bit $C08B
bit $C08B
}
!macro READ_RAM2_NO_WRITE {
sta $C080
}
!macro READ_RAM2_WRITE_RAM2 {
bit $C083
bit $C083
}
!macro READ_ROM_WRITE_RAM1 {
bit $C089
bit $C089
}
!macro READ_ROM_WRITE_RAM2 {
bit $C081
bit $C081
}
!macro READ_ROM_NO_WRITE {
sta $C082
}

Binary file not shown.