a2bubble/a2bubble.asm

1445 lines
21 KiB
NASM

; Helix Apple II bubble memory card firmware version 3.40.
; Partially reverse-engineered by Eric Smith <spacewar@gmail.com>
; Cross-assemble with Macro Assembler AS:
; http://john.ccac.rwth-aachen.de:8000/as/
fillto macro endaddr,value,{noexpand}
ifnb value
v set value
else
v set $00
endif
while *<endaddr
if (endaddr-*)>1024
fcb [1024] v
else
fcb [endaddr-*] v
endif
endm
endm
fcstrm macro s
irpc c,s
fcb 'c'|$80
endm
endm
; ProDOS disk drivers are allowed to use zero page locations
; 00-01, 3a-46
Z18 equ $18
boot_buf_ptr equ $26
bubble_track equ $2a
Z2b equ $2b
Z2c equ $2c ; DOS: pointer to BMC data register (two bytes)
Z2e equ $2e
Z2f equ $2f
Z35 equ $35
cswl equ $36 ; monitor: character output vector (two bytes)
Z3e equ $3e
Z3f equ $3f
; boot ROM variables
boot_sector_num equ $3d
boot_track_num equ $41
boot_retry_count equ $47
; DOS variables
dos_slot_16 equ $2b ; slot * 16
rwts_dct equ $3c
rwts_iopb equ $48
; DOS RWTS IOPB offsets
rwts_iopb_table_type equ $00
rwts_iopb_slot_num_16 equ $01 ; slot number times 16
rwts_iopb_drive_num equ $02
rwts_iopb_volume_num equ $03
rwts_iopb_track equ $04
rwts_iopb_sector equ $05
rwts_iopb_dct_ptr equ $06
rwts_iopb_buf_ptr equ $08
; byte at offset 0a not used
rwts_iopb_byte_count equ $0b
rwts_iopb_command equ $0c
rwts_iopb_return_code equ $0d
rwts_iopb_prev_volume equ $0e
rwts_iopb_prev_slot_16 equ $0f
rwts_iopb_prev_drive equ $10
; prodos variables
prodos_buf_ptr equ $3a
prodos_bmc_ptr equ $3c ; pointer to BMC data register (two bytes)
prodos_slot_16 equ $3e ; slot * 16
prodos_cmd equ $42
prodos_unit equ $43
prodos_buf equ $44
prodos_block equ $46 ; two bytes
Zbd equ $bd
Zbe equ $be
Zbf equ $bf
Zc3 equ $c3
Zc5 equ $c5
Zcb equ $cb
stack equ $0100
D03a1 equ $03a1
D03a2 equ $03a2
D03a4 equ $03a4
D03a8 equ $03a8
D03a9 equ $03a9
D03ac equ $03ac
D03ad equ $03ad
D03af equ $03af
; Apple DOS
get_dos_fm_parm equ $03dc ; locate file manager input parameter list
D03e0 equ $03e0
D03e1 equ $03e1
D03e2 equ $03e2
; Apple DOS: locate input parameter list for RWTS
D03e3 equ $03e3
D03e4 equ $03e4
D03e5 equ $03e5
D03e6 equ $03e6
D03e7 equ $03e7
D03e8 equ $03e8
D03e9 equ $03e9
; Apple DOS: JMP to subroutine to reconnect DOS keyboard and screen intercepts
D03ea equ $03ea
D03eb equ $03eb
D05f8 equ $05f8
D0800 equ $0800
L0801 equ $0801
Sbfd0 equ $bfd0 ; ProDOS irqxit?
; Apple II hardware
spkr equ $c030
c8xx_rom_disable equ $cfff
; Applesoft entry point
Sd382 equ $d382
; Apple II BASIC entry points (Integer or Applesoft)
basic_cold_start equ $e000
; Apple II monitor ROM entry points
cout equ $fded
cout1 equ $fdf0 ; output char to screen
monrts equ $ff58 ; guaranteed to be an RTS instruction
; ProDOS variable
prodos_prev_unit equ $fb59 ; in Language Card RAM
; NOTE: won't work right with Prodos on 48K Apple II or II+
; card-specific hardware
; Intel 7220-1 Bubble Memory Controller hardware registers
bmc_data equ $c080 ; but data reg only addressed indirectly
bmc_cmd equ $c081
bmc_status equ $c081
; unknown card hardware
led_off equ $c088
led_on equ $c089
Dc08c equ $c08c
Dc08e equ $c08e
; BMC internal register addresses
; These registers are accessed by writing the register address to the
; bmc_cmd register, then reading/writing the bmc_data register
bmc_reg_fifo equ $00 ; RW, doesn't advance
bmc_reg_utility equ $0a ; RW
bmc_reg_block_length equ $0b ; two bytes, little-endian, WO
bmc_reg_enable equ $0d ; WO
bmc_reg_address equ $0e ; two bytes, RW
; BMC commands
bmc_cmd_initialize equ $11
bmc_cmd_read_data equ $12
bmc_cmd_write_data equ $13
bmc_cmd_abort equ $19
bmc_cmd_reset_fifo equ $1d
org $cf00
phase $c600
; Bytes at Cn0{1,3,5,7} = $20, $00, $03, $3C identify card as bootable by
; original Autostart ROM monitor. Later models only check the first
; three of those. Result is that SmartPort are not automatically bootable
; with original Autostart monitor.
; Bytes at Cn0{1,3,5} = $20, $00, $03 identify card as a block device
; Byte at Cn07 = $3C for Disk II,
; $00 for SmartPort interface supported
; Byte at CnFF = $00 for 16-sector Disk II, $ff for 13-sector Disk II,
; other value $xx = ProDOS block device, entry point = Cnxx, in this case
; $Cn2A
; For ProDOS block device:
; word at CnFC = device size in blocks,
; byte at CnFE = STATUS byte
ldx $20 ; $Cn01 = $20
ldy #$00 ; $Cn03 = $00
ldx #$03 ; $Cn05 = $03
stx $3c ; $Cn07 = $3C, bootable by original Autostart ROM,
; no SmartPort support
; get the slot number we're running in
jsr monrts
tsx
lda stack,x
sta Z3f ; $Cn for slot n
asl
asl
asl
asl
sta dos_slot_16 ; $n0, slot number * 16
tax
lda led_on,x
lda #$00
sta boot_buf_ptr
sta boot_sector_num
sta boot_track_num
lda #$08
sta boot_buf_ptr+1
clc
bcc boot ; always taken
prodos_entry_x:
lda c8xx_rom_disable ; disable any other C800 ROMs
jmp prodos_entry_xx
fcstrm "COPR. HELIX LABORATORIES INC. 1984"
fillto $c65c,$ff
; DOS 3.3 boot sector reenters ROM bootstrap here
boot: lda c8xx_rom_disable
jsr click
ldx dos_slot_16
lda #$00
sta Z2f
lda boot_track_num
sec
sbc #$03
bpl Lc671
lda boot_track_num
Lc671: sta boot_track_num
clc
asl
asl
asl
asl
rol Z2f
sta Z2e
ldy boot_track_num
bne Lc687
ldy boot_sector_num
lda Dcae8,y
bpl Lc697
Lc687: ldy boot_sector_num
lda Dcad8,y
ldy boot_track_num
cpy #$0e
bne Lc697
clc
adc #$01
and #$0f
Lc697: clc
adc Z2e
asl
rol Z2f
asl
rol Z2f
sta Z2e
lda c8xx_rom_disable
jsr initchk
bcc Lc6b3
lda #$04
sta boot_retry_count
Lc6ae: jsr initial
bcs Lc6cb
Lc6b3: jsr rdbub
bcs Lc6cb
lda spkr ; click speaker
inc boot_buf_ptr+1
inc boot_sector_num
lda boot_sector_num
jsr Sce83
ldx dos_slot_16
bcc boot
jmp L0801 ; proceed to next stage of boot sequence
Lc6cb: dec boot_retry_count
bne Lc6ae
lda led_off,x
; output IO error message to screen
lda #(cout1 & $ff) ; disconnect any alternate character output
sta cswl
lda #(cout1 >> 8)
sta cswl+1
lda #msg_io_error & $ff
sta Z3e
ldy #$00
msg_loop:
lda (Z3e),y
jsr cout
iny
cpy #msg_len_io_error
bne msg_loop
jmp basic_cold_start
msg_io_error: fcb $87,$8d,$8a ; bell, return, linefeed
fcb $be,$c9,$cf,$a0,$c5,$d2,$d2,$cf,$d2 ; >IO ERROR
msg_len_io_error equ *-msg_io_error
fillto $c6fb,$ff
; CnFB would be SmartPort ID Type Byte, SmartPort Interface was supported,
; but it's not.
fcb $ff
; must be at CnFC here!
fdb $0100 ; total number of 512-byte blocks on device
fcb $4f ; ProDOS block device STATUS byte
; not removable
; interruptable
; 1 volume
; supports formatting, write, read, status
fcb prodos_entry_x & $ff
dephase
org $c800
; Jump table, first 12 entries described in Appendix E of manual
jmp bubrwts
jmp initchk
jmp cmdwait
jmp ldrdrac
jmp ldwrrac
jmp initial
jmp wptest
jmp rdbub
jmp wrbub
jmp inbitmap
jmp click
jmp bubpasc
jmp Lcbd2 ; XXX may be CP/M entry point
prodos_entry_xx:
jmp prodos_entry
; reserved room for a few additional jumps for future expansion
fillto $c830, $ff
; Bubble RWTS, called by the patch to DOS 3.3
bubrwts:
pla ; discard return address for DOS patch
sta rwts_dct
pla
sta rwts_dct+1
lda #$04 ; put retry count on stack
pha
stx dos_slot_16
stx D05f8
txa
ldy #rwts_iopb_prev_slot_16 ; slot matches prev slot?
cmp (rwts_iopb),y
beq Lc860 ; yes, don't have to do anything special
txa ; turn off prev slot Disk II motor?
pha
lda (rwts_iopb),y
tax
pla
pha
sta (rwts_iopb),y
lda Dc08e,x
Lc851: ldy #$08
lda Dc08c,x
Lc856: cmp Dc08c,x
bne Lc851
dey
bne Lc856
pla
tax
Lc860: lda led_on,x
jsr click
ldy #rwts_iopb_buf_ptr ; copy buf ptr from RWTS IOPB to boot_buf_ptr
lda (rwts_iopb),y
sta boot_buf_ptr
iny
lda (rwts_iopb),y
sta boot_buf_ptr+1
ldy #rwts_iopb_prev_volume ; set volume of last access to 254
lda #254
sta (rwts_iopb),y
ldy #rwts_iopb_drive_num ; set drive number of last access
lda (rwts_iopb),y
ldy #rwts_iopb_prev_drive
sta (rwts_iopb),y
ror
ror
sta Z35
ldy #rwts_iopb_track ; get logical track number from RWTS IOPB
lda (rwts_iopb),y
sta bubble_track ; save as bubble track number
sec ; if track > 3, subtract 3 from bubble track
sbc #$03
bpl Lc890
lda bubble_track
Lc890: sta bubble_track
tay ; bubble track >= 32?
sec
sbc #$20
bpl rwts_finish
clc
lda #$00
sta Z2f
tya
asl
asl
asl
asl
rol Z2f
sta Z2e
ldy #rwts_iopb_sector ; get sector number from RWTS IOPB
lda (rwts_iopb),y
tay ; deinterleave
lda Dcac8,y
ldy bubble_track
bne Lc8b8
tay
lda Dcae8,y
bpl Lc8c7
Lc8b8: tay
lda Dcad8,y
ldy bubble_track
cpy #$0e
bne Lc8c7
clc
adc #$01
and #$0f
Lc8c7: clc
adc Z2e
asl
rol Z2f
asl
rol Z2f
sta Z2e
jsr initchk
bcc Lc8dc
rwts_retry:
jsr initial
bcs rwts_check_status
Lc8dc: ldy #rwts_iopb_command ; get IOPB command code
lda (rwts_iopb),y
beq rwts_finish ; cmd 0 = SEEK, handle as no-op
lsr
bcc Lc8eb ; cmd 2 or 4
; cmd 1 = READ
jsr rdbub
jmp rwts_check_status
Lc8eb: lsr
bcc rwts_finish ; cmd 4 = FORMAT, handle as no-op
; cmd 2 = WRITE
jsr wptest
bcc Lc8f7 ; if write protected, error
lda #$10
bne rwts_done_err
Lc8f7: jsr inbitmap
jsr wrbub
rwts_check_status:
bcc rwts_finish ; if no error, done
pla ; decrement retry count on stack
sec
sbc #$01
pha
bne rwts_retry ; if retry count hasn't hit 0, retry
beq rwts_drive_error ; otherwise report drive error
rwts_finish:
ldy #rwts_iopb_dct_ptr ; copy IOPB DCT ptr
lda (rwts_iopb),y ; (presumably for RWTS compatibility)
sta rwts_dct
iny
lda (rwts_iopb),y
sta rwts_dct+1
jsr click
lda #$00
beq rwts_done_ok
rwts_drive_error:
lda #$40 ; drive error
bne rwts_done_err
rwts_done_ok:
clc
fcb $24 ; bit instr to skip sec
rwts_done_err:
sec
ldy #rwts_iopb_return_code
sta (rwts_iopb),y
lda led_off,x
pla ; pop retry count from stack
rts
; check whether 7220 BMC needs initializing
initchk:
lda #bmc_cmd_reset_fifo
sta bmc_cmd,x
jsr cmdwait
rts
; wait for BMC to go busy, then idle
cmdwait:
lda #$00
pha
Lc936: lda bmc_status,x
bmi Lc940
dey
beq Lc94f
bne Lc936
Lc940: lda bmc_status,x
bpl Lc951
dey
bne Lc940
pla
sec
sbc #$01
pha
bne Lc940
Lc94f: sec
fcb $24 ; bit instr to skip clc
Lc951: clc
pla
rts
; send block length and address to BMC for read data command
; with error correction
; used for DOS
; (enables MFBTR, can't be used for commands other than read data)
; on entry, Y = number of 64-byte pages for block length
ldrdrac:
lda #bmc_reg_block_length
sta bmc_cmd,x
ldx #$00
tya
sta (Z2c,x) ; write to block length LSB
lda #$10 ; two FSA channels
sta (Z2c,x) ; write to block length MSB
lda #$28 ; enable RCD (read corrected data)
; and MFBTR (max FSA-BMC transfer rate)
sta (Z2c,x) ; write to enable register
lda Z2e
sta (Z2c,x) ; write to address register LSB
lda Z2f
sta (Z2c,x) ; write to address register MSB
ldx dos_slot_16
rts
; send block length and address to BMC for commands other than read data,
; including write with error correction
; used for DOS
; (disables MFBTR)
; on entry, Y = number of 64-byte pages for block length
ldwrrac:
lda #bmc_reg_block_length
sta bmc_cmd,x
ldx #$00
tya
sta (Z2c,x) ; write to block length LSB
lda #$10 ; two FSA channels
sta (Z2c,x) ; write to block length MSB
lda #$20 ; enable RCD (read corrected data) only
sta (Z2c,x) ; write to enable register
lda Z2e
sta (Z2c,x) ; write to address register LSB
lda Z2f
sta (Z2c,x) ; write to address register MSB
ldx dos_slot_16
rts
; DOS: set Z2c to point to data reg
dos_setup_data_reg_ptr:
lda dos_slot_16
clc
adc #$80
sta Z2c
lda #$c0
sta Z2c+1
rts
; initialize: tell BMC to abort, twice
initial:
lda #bmc_cmd_abort
sta bmc_cmd,x
jsr cmdwait
bcs Lc9dc
lda #bmc_cmd_abort
sta bmc_cmd,x
jsr cmdwait
bcs Lc9dc
lda bmc_status,x
cmp #$40
bne Lc9dc
; delay
sec
ldy #$64
Lc9b8: lda #$ff
Lc9ba: sbc #$01
bne Lc9ba
dey
bne Lc9b8
jsr dos_setup_data_reg_ptr
ldy #$04 ; 4*64 = 256 byte block
jsr ldwrrac
lda #bmc_cmd_initialize
sta bmc_cmd,x
jsr cmdwait
bcs Lc9dc
lda bmc_status,x
cmp #$40
bne Lc9dc
clc
fcb $24 ; bit instr to skip sec
Lc9dc: sec
rts
Sc9de: lda #$ff
pha
Lc9e1: lda bmc_status,x
bmi Lc9ef
pla
sec
sbc #$01
pha
bne Lc9e1
sec
fcb $24 ; bit instr to skip clc
Lc9ef: clc
pla
rts
Sc9f2: lda #$ff
pha
pha
Lc9f6: lda bmc_status,x
bpl Lca13
lsr
bcs Lca15
pla
sec
sbc #$01
pha
bne Lc9f6
pla
pla
sec
sbc #$01
pha
beq Lca12
lda #$ff
pha
bne Lc9f6
Lca12: pha
Lca13: sec
fcb $24 ; bit instr to skip clc
Lca15: clc
pla
pla
rts
; test write-protect switch
; returns carry set if write-protected, clear if not
wptest:
lda Dc08c,x
bpl Lca20
clc
fcb $24 ; bit instr to skip sec
Lca20: sec
rts
; Read one sector (256 bytes), used for DOS
rdbub:
jsr dos_setup_data_reg_ptr
ldy #$04 ; 4*64 = 256 byte block
jsr ldrdrac
ldy #$00
lda #bmc_cmd_read_data
sta bmc_cmd,x
jsr Sc9de
bcs Lca52
; read data loop
Lca36: jsr Sc9f2
bcs Lca47
ldx #$00
lda (Z2c,x)
ldx dos_slot_16
sta (boot_buf_ptr),y
iny
jmp Lca36
Lca47: beq Lca52
lda bmc_status,x
and #$3c
bne Lca52
clc
fcb $24 ; bit instr to skip sec
Lca52: sec
rts
; Write one sector (256 bytes), used for DOS
wrbub: jsr dos_setup_data_reg_ptr
ldy #$04 ; 4*64 = 256 byte block
jsr ldwrrac
ldy #$00
lda #bmc_cmd_write_data
sta bmc_cmd,x
jsr Sc9de
bcs Lca84
; write data loop
Lca68: jsr Sc9f2
bcs Lca79
lda (boot_buf_ptr),y
iny
ldx #$00
sta (Z2c,x)
ldx dos_slot_16
jmp Lca68
Lca79: beq Lca84
lda bmc_status,x
and #$3c
bne Lca84
clc
fcb $24 ; bit instr to skip clc
Lca84: sec
rts
; Change the DOS VTOC bitmap to protect tracks 3-5 to prevent
; DOS from allocating those to files. Necessary when initializing
; bubble as a bootable DOS disk, because tracks 0-2 (used for DOS)
; and tracks 3-5 (used for files) map to the same portion of the
; bubble device.
inbitmap:
lda bubble_track ; is VTOC track (17, adjusted for bubble)?
cmp #17-3
bne inbitmap_done
ldy #rwts_iopb_sector ; VTOC sector (0)?
lda (rwts_iopb),y
cmp #$00
bne inbitmap_done
jsr get_dos_fm_parm
sty Z2c
sta Z2c+1
ldy #$00
lda (Z2c),y
cmp #$0b
bne inbitmap_done
lda Z35
bpl inbitmap_done
lda #$fe
ldy #$06
sta (boot_buf_ptr),y
lda #$00
ldy #$44
Lcab1: sta (boot_buf_ptr),y
iny
cpy #$4c
bne Lcab1
iny
lda #$e0
sta (boot_buf_ptr),y
inbitmap_done:
rts
; toggle speaker if enabled by switch
click: lda Dc08c,x
asl
bpl Lcac7
lda spkr
Lcac7: rts
; interleave tables?
Dcac8: fcb $00,$0d,$0b,$09,$07,$05,$03,$01
fcb $0e,$0c,$0a,$08,$06,$04,$02,$0f
Dcad8: fcb $0f,$08,$01,$09,$02,$0a,$03,$0b
fcb $04,$0c,$05,$0d,$06,$0e,$07,$00
Dcae8: fcb $00,$08,$01,$09,$02,$0a,$03,$0b
fcb $04,$0c,$05,$0d,$06,$0e,$07,$0f
; disk access from Apple Pascal 1.1 patch
bubpasc:
lda #$04
pha
ldx D03a1
stx Z2b
cpx D03af
beq Lcb16
ldx D03af
Lcb08: jsr Sbfd0
jsr Sd382
bne Lcb08
ldx D03a1
stx D03af
Lcb16: lda D03a2
lsr
bcs Lcb21
lda #$09
jmp Lcbc9
Lcb21: lda led_on,x
lda D03a4
tay
sec
sbc #$20
bmi Lcb32
lda #$08
jmp Lcbc9
Lcb32: clc
lda #$00
sta Z2f
tya
asl
asl
asl
asl
rol Z2f
sta Z2e
lda Zbd
sta Zcb
clc
adc Z2e
asl
rol Z2f
asl
rol Z2f
sta Z2e
Lcb4f: jsr Sbfd0
jsr click
lda Zcb
sec
sbc Zbd
tay
clc
adc D03a9
iny
cpy Zbf
bcc Lcb77
beq Lcb6b
lda #$40
jmp Lcbc9
Lcb6b: ldy Zbe
beq Lcb77
sta Zc5
ldy #$00
lda #$02
bcs Lcb7a
Lcb77: ldy D03a8
Lcb7a: sty boot_buf_ptr
sta boot_buf_ptr+1
sty Z3e
sta Z3e+1
jsr initchk
bcc Lcb8c
Lcb87: jsr initial
bcs Lcba6
Lcb8c: lda D03ac
cmp #$02
bne Lcba3
jsr wptest
bcc Lcb9d
lda #$10
jmp Lcbc9
Lcb9d: jsr wrbub
jmp Lcba6
Lcba3: jsr rdbub
Lcba6: bcc Lcbb4
pla
sec
sbc #$01
pha
bne Lcb87
lda #$40
jmp Lcbc9
Lcbb4: inc Zcb
lda #$04
clc
adc Z2e
sta Z2e
lda #$00
adc Z2f
sta Z2f
dec Zc3
bne Lcb4f
clc
fcb $24 ; bit instr to skip sec
Lcbc9: sec
sta D03ad
lda led_off,x
pla
rts
Lcbd2: lda #$04
pha
lda D03e6
tax
cmp D03e7
beq Lcbfb
txa
tay
lda D03e7
tax
tya
pha
sta D03e7
lda Dc08e,x
Lcbec: ldy #$08
lda Dc08c,x
Lcbf1: cmp Dc08c,x
bne Lcbec
dey
bne Lcbf1
pla
tax
Lcbfb: lda led_on,x
jsr click
stx Z2b
lda D03e4
sta D03e5
cmp #$01
beq Lcc12
lda #$40
jmp Lcca0
Lcc12: lda D03e8
sta boot_buf_ptr
lda D03e9
sta boot_buf_ptr+1
lda D03e2
sta D03e3
lda D03e0
tay
sec
sbc #$20
bpl Lcc93
clc
lda #$00
sta Z2f
tya
asl
asl
asl
asl
rol Z2f
sta Z2e
lda D03e1
tay
lda Dcca9,y
ldy D03e0
bne Lcc4b
tay
lda Dcae8,y
bpl Lcc4f
Lcc4b: tay
lda Dcad8,y
Lcc4f: clc
adc Z2e
asl
rol Z2f
asl
rol Z2f
sta Z2e
jsr initchk
bcc Lcc64
Lcc5f: jsr initial
bcs Lcc88
Lcc64: lda D03eb
beq Lcc7c
cmp #$01
beq Lcc76
cmp #$02
beq Lcc7c
lda #$40
jmp Lcca0
Lcc76: jsr rdbub
jmp Lcc88
Lcc7c: jsr wptest
bcc Lcc85
lda #$10
bne Lcca0
Lcc85: jsr wrbub
Lcc88: bcc Lcc93
pla
sec
sbc #$01
pha
bne Lcc5f
beq Lcc9a
Lcc93: jsr click
lda #$00
beq Lcc9e
Lcc9a: lda #$40 ; 64 @
bne Lcca0
Lcc9e: clc
fcb $24 ; bit instr to skip sec
Lcca0: sec
sta D03ea
lda led_off,x
pla
rts
; interleave table?
Dcca9: fcb $00,$02,$04,$06,$08,$0a,$0c,$0e
fcb $01,$03,$05,$07,$09,$0b,$0d,$0f
prodos_entry:
cld
lda prodos_cmd ; is the command format?
eor #$03
beq Lccf2 ; yes, do nothing and report success
lda prodos_block
pha
lda prodos_block+1
pha
beq Lcccf
lda #$27
sta Z3f
jmp Lcce6
Lcccf: asl prodos_block
rol prodos_block+1
asl prodos_block
rol prodos_block+1
asl prodos_block
rol prodos_block+1
lda prodos_buf
sta prodos_buf_ptr
lda prodos_buf+1
sta prodos_buf_ptr+1
jsr Sccf4
Lcce6: pla
sta prodos_block+1
pla
sta prodos_block
lda Z3f
beq Lccf2
sec
fcb $24 ; bit instr to skip clc
Lccf2: clc
rts
Sccf4: lda #$00
sta Z3f
lda prodos_unit
and #$70
sta prodos_slot_16
jsr Scd5e
lda prodos_unit
sta prodos_prev_unit
lda #$04
pha
ldx Z3e
lda led_on,x
jsr click
jsr initchk
bcc Lcd1b
Lcd16: jsr Scdcd
bcs Lcd45
Lcd1b: lda prodos_cmd
beq Lcd52 ; status request
cmp #$03
beq Lcd52 ; format request
lsr
bcs Lcd37 ; read request
; write request here
jsr wptest
bcc Lcd31
lda #$2b
sta Z3f
bne Lcd52
Lcd31: jsr Sce49
jmp Lcd45
Lcd37: lsr
bcs Lcd40
jsr Sce13
jmp Lcd45
Lcd40: sec
jmp Lcd45
fcb $18
Lcd45: bcc Lcd52
pla
sec
sbc #$01
pha
bne Lcd16
lda #$27
sta Z3f
Lcd52: lda led_off,x
jsr click
ldx #$00
ldy #$01
pla
rts
Scd5e: eor prodos_prev_unit
and #$7f
beq Lcd84
lda prodos_prev_unit
and #$0f
bne Lcd84
lda prodos_prev_unit
and #$70
tax
beq Lcd84
lda Dc08e,x
Lcd77: ldy #$08
lda Dc08c,x
Lcd7c: cmp Dc08c,x
bne Lcd77
dey
bne Lcd7c
Lcd84: rts
; send block length and address to BMC for read data command
; (enables MFBTR, can't be used for commands other than read data)
setup_prodos_read:
lda #bmc_reg_block_length
sta bmc_cmd,x
ldx #$00
lda #$08 ; 8*64 = 512 byte block
sta (prodos_bmc_ptr,x) ; write to block length LSB
lda #$10 ; two FSA channels
sta (prodos_bmc_ptr,x) ; write to block length MSB
lda #$28 ; enable RCD (read corrected data)
; and MFBTR (max FSA-BMC transfer rate)
sta (prodos_bmc_ptr,x) ; write to enable register
lda prodos_block
sta (prodos_bmc_ptr,x) ; write to address register LSB
lda prodos_block+1
sta (prodos_bmc_ptr,x) ; write to address register MSB
ldx prodos_slot_16
rts
; send block length and address to BMC for commands other than read data
; (disables MFBTR)
setup_prodos_nonread:
lda #bmc_reg_block_length
sta bmc_cmd,x
ldx #$00
lda #$08 ; 8*64 = 512 byte block
sta (prodos_bmc_ptr,x) ; write to block length LSB
lda #$10 ; two FSA channels
sta (prodos_bmc_ptr,x) ; write to block length MSB
lda #$20
sta (prodos_bmc_ptr,x) ; write to enable register
lda prodos_block
sta (prodos_bmc_ptr,x) ; write to address register LSB
lda prodos_block+1
sta (prodos_bmc_ptr,x) ; write to address register MSB
ldx prodos_slot_16
rts
; set prodos_bmc_ptr to point to BMC data reg
prodos_setup_data_reg_ptr:
lda prodos_slot_16
clc
adc #$80
sta prodos_bmc_ptr
lda #$c0
sta prodos_bmc_ptr+1
rts
Scdcd: sei
lda #bmc_cmd_abort
sta bmc_cmd,x
jsr cmdwait
bcs Lce11
lda #bmc_cmd_abort
sta bmc_cmd,x
jsr cmdwait
cli
bcs Lce11
lda bmc_status,x
cmp #$40
bne Lce11
sec
ldy #$64
Lcded: lda #$ff
Lcdef: sbc #$01
bne Lcdef
dey
bne Lcded
jsr prodos_setup_data_reg_ptr
jsr setup_prodos_nonread
sei
lda #bmc_cmd_initialize
sta bmc_cmd,x
jsr cmdwait
cli
bcs Lce11
lda bmc_status,x
cmp #$40
bne Lce11
clc
fcb $24 ; bit instr to skip sec
Lce11: sec
rts
Sce13: jsr prodos_setup_data_reg_ptr
jsr setup_prodos_read
ldy #$00
sei
lda #bmc_cmd_read_data
sta bmc_cmd,x
jsr Sc9de
bcs Lce46
; read data loop
Lce26: jsr Sc9f2
bcs Lce3b
ldx #$00
lda (prodos_bmc_ptr,x)
ldx Z3e
sta (prodos_buf_ptr),y
iny
bne Lce26
inc prodos_buf_ptr+1
jmp Lce26
Lce3b: beq Lce46
lda bmc_status,x
and #$3c
bne Lce46
clc
fcb $24 ; bit instr to skip sec
Lce46: sec
cli
rts
Sce49: jsr prodos_setup_data_reg_ptr
jsr setup_prodos_nonread
ldy #$00
sei
lda #bmc_cmd_write_data
sta bmc_cmd,x
jsr Sc9de
bcs Lce7c
; write data loop
Lce5c: jsr Sc9f2
bcs Lce71
lda (prodos_buf_ptr),y
iny
bne Lce68
inc prodos_buf_ptr+1
Lce68: ldx #$00
sta (prodos_bmc_ptr,x)
ldx prodos_slot_16
jmp Lce5c
Lce71: beq Lce7c
lda bmc_status,x
and #$3c
bne Lce7c
clc
fcb $24 ; bit instr to skip sec
Lce7c: sec
cli
rts
Dce7f: fcb $01,$38,$b0,$03 ; ".8.."
Sce83: cmp #$01
bne Lce99
ldx #$03
Lce89: lda Dce7f,x
cmp D0800,x
bne Lce99
dex
bpl Lce89
inc boot_sector_num
clc
bcc Lce9e
Lce99: lda boot_sector_num
cmp D0800
Lce9e: rts
fillto $cef1,$ff
fcstrm "11/24/84 VER340"