ramfactor/ramfactor14.asm

2702 lines
45 KiB
NASM

; Applied Engineering RamFactor firmware version 1.4
; Partially reverse-engineered by Eric Smith <spacewar@gmail.com>
; Cross-assemble with Macro Assembler AS:
; http://john.ccac.rwth-aachen.de:8000/as/
; Depends on AS "section" pseudo-op to provide separate namespaces
; for each slot ROM, and for diagnostics and partition manager
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
fcsm macro s
irpc c,s
fcb 'c'|$80
endm
endm
; skip macros - NOTE: these alter the Z, N, and V flags
skip1 macro
fcb $24 ; BIT zero page opcoe
endm
skip2 macro
fcb $2c ; BIT absolute opcode
endm
; macro for command table, used in partition manager
cmd_ent macro char,addr
fcb char+$80
fdb addr-1 ; -1 because RTS will do the jump
endm
; macros to handle the text compression
enc_nib macro nibval
if nib_msb
nib_save set nibval
else
fcb (nib_save<<4)|nibval
endif
nib_msb set 1-nib_msb
endm
enc_ch macro ch
idx set strstr(tbl1,ch)
if idx >= 0
enc_nib idx
else
idx set strstr(tbl2,ch)
if idx >= 0
enc_nib 0
enc_nib idx
else
error "unable to encode character"
endif
endif
endm
enc_end macro
idx set strstr(tbl1,"\xff")
if idx >= 0
enc_nib idx
else
error "no zero entry in tbl1"
endif
idx set strstr(tbl2,"\xff")
if idx >= 0
enc_nib idx
else
error "no zero entry in tbl2"
endif
if nib_msb == 0
enc_nib 9 ; if there's a leftover nibble at the end, fill with 9
endif
endm
;encode2 macro arg
; if "arg"<>""
; irpc char,arg
; enc_ch "char"
; endm
; shift
; encode2 ALLARGS
; endif
; endm
;encode macro arg
;nib_msb set 1
; encode2 allargs
; enc_end
; endm
encode macro arg
nib_msb set 1
irpc char,arg
enc_ch "char"
endm
enc_end
endm
char_bs equ $08
char_lf equ $0a
char_vt equ $0b
char_cr equ $0d
char_nak equ $15
char_esc equ $1b
key_left equ char_bs
key_right equ char_nak
key_up equ char_vt
key_down equ char_lf
; zero page locations
L00 equ $00
; Apple II monitor zero page locations
ch equ $24
CV equ $25
invflg equ $32 ; $
kswl equ $38
; ProDOS and disk driver zero page locations
Z3e equ $3e
Z3f equ $3f
Z41 equ $41
Z42 equ $42 ; ProDOS interface command
Z43 equ $43 ; ProDOS interface unit number
Z44 equ $44 ; ProDOS interface buffer pointer (two bytes)
Z45 equ $45
Z46 equ $46 ; ProDOS interface block number (two bytes)
Z47 equ $47
Z48 equ $48
Z49 equ $49
Z4a equ $4a
Z4b equ $4b
rwtsiob equ Z48
rwtsbuf equ Z3e
rwts_iob_idx_slot equ $01
rwts_iob_idx_drive equ $02
rwts_iob_idx_volume equ $03
rwts_iob_idx_track equ $04
rwts_iob_idx_sector equ $05
rwts_iob_idx_buffer equ $08
rwts_iob_idx_command equ $0c
rwts_iob_idx_result equ $0d
rwts_iob_idx_prev_vol equ $0e
rwts_iob_idx_prev_slot equ $0f
rwts_iob_idx_prev_drive equ $10
rwts_err_none equ $00
rwts_err_init equ $08
rwts_err_write_prot equ $10
rwts_err_vol_mismatch equ $20
rwts_err_drive equ $40
rwts_err_read equ $80 ; Obsolete according to Beneath Apple DOS
D010b equ $010b
D010c equ $010c
D01a9 equ $01a9
klinbuf equ $0200
D0400 equ $0400
; card HW regs typically would be addressed using a
; base address of $c00r or $c084, with an index
; register value of $n0, where n is the slot number,
; or the slot number + $80. However, with the 6502
; this would result in false reads of
; Apple IIe/IIc/IIgs soft switches or Language Card
; soft switches (integral to the IIe/IIc/IIgs).
;
; Instead, we use base addresses at the end of Apple DRAM
; the $88 offset is used so that the "false read"
; of an indexed address will be to DRAM, and not
; screw up the Language Card switches.
;
; For example for a card in slot 4, with a register
; at $coc3:
;
; base index register false read
; ----- ----- -------- ----------
; $c003 $c0 $c0c3 $c003 RDCARDRAM
; $c083 $40 $c0c3 $c083 LCBANK2
; $bffb $c8 $c0c3 $bffb (no problem)
hw_reg_offset equ $88
; screen holes, global (not indexed)
; Since these are not slot-specific, they are only suitable for scratch
; use.
; BEWARE: Even scratch use is questionable if interrupts are in use,
; because an interrupt hander might use these.
shg_0478 equ $0478
shg_04f8 equ $04f8
shg_0578 equ $0578
shg_05f8 equ $05f8
mslot1088 equ $0778 ; stores (slot*$10)+hw_reg_offset
; mslot appears to be the only global screen hole for which Apple
; has defined a function.
mslot equ $07f8 ; stores $Cn, where n is the slot number
; screen holes, indexed by $Cn, where n is slot number (1 through 7)
shs_card_block_count equ $0478-$c0 ; # blocks of whole card, divided by 256
shs_idx_part_data equ $04f8-$c0 ; index to partition data
shs_part_base_high equ $0578-$c0 ; partition base address, high bbyte
shs_part_base_mid equ $05f8-$c0 ; partition base address, mid byte
shs_cur_part_size_high equ $0678-$c0 ; current partition size, pages, high byte
shs_cur_part_size_low equ $06f8-$c0 ; current partition size, pages, low byte
shs_os_code equ $0778-$c0 ; operating system code
shs_os_check equ $07f8-$c0 ; operating system check code
bootstrap_load_addr equ $0800
bootstrap_entry_addr equ bootstrap_load_addr+1
ram_application_base equ $0a00
rwts_patch equ $bd12 ; RWTS patch loc, three bytes
proflag equ $bf00 ; used to detect OS
os_pascal equ $00
os_prodos equ $4c
os_dos equ $33
os_cpm equ $cd
kbd equ $c000 ; read keyboard
rdmainram equ $c002 ; IIe read main RAM
rdauxram equ $c003 ; IIe read auxilliary RAM
wrmainram equ $c004 ; IIe write main RAM
wrauxmem equ $c005 ; IIe write auxilliary RAM
clr80vid equ $c00c ; IIe disable 80col
clraltchar equ $c00e ; IIe disable altchar
kbdstrb equ $c010 ; clea rkeyboard strobe
rdramrd equ $c013 ; IIe MSB reads 1 if aux RAM read enabled
rdramwrt equ $c014 ; IIe MSB reads 1 if aux RAM write enabled
; hardware registers
hw_reg_addr_low equ $c080 ; low byte of hardware RAM address, add slot*$10
hw_reg_addr_mid equ $c081 ; low byte of hardware RAM address, add slot*$10
hw_reg_addr_high equ $c082 ; low byte of hardware RAM address, add slot*$10
hw_reg_data equ $c083 ; low byte of hardware RAM address, add slot*$10
hw_reg_rom_bank equ $c08f ; bank select, add slot*$10
Dcfff equ $cfff ; turn off C800 shared ROM space
sloop equ $faba
init equ $fb2f
bell12 equ $fbe2
clreop equ $fc42
home equ $fc58
rdkey equ $fd0c
crout equ $fd8e
prbyte equ $fdda
cout equ $fded
setkbd equ $fe89
setvid equ $fe93
resetvec equ $fffc
err_bad_cmd equ $01
err_bad_pcnt equ $04
err_bus_err equ $06
err_bad_unit_num equ $11
err_bad_ctl equ $21
err_bad_ctl_param equ $22
err_io_error equ $27
err_no_drive equ $28
err_no_write equ $2b ; write-protected
err_bad_block_num equ $2d
err_offline equ $2f
; Protocol Converter error codes $30..$3f are device-specific errors
; Protocol Converter error codes $50..$7f are device-specific non-fatal errors
check_xor_val equ $5a ; value XORed with various things to generate a check byte
irp banknum,0,1
org $c000+(banknum*$1000)
fcb "COPYRIGHT (C) 1986-89 APPLIED ENGINEERING",$00
fcb "BOB SANDER-CEDERLOF",$00
fcb "MICHAEL WILKS",$00
fcb "STEVEN MALECHEK",$00
fillto $c100+(banknum*$1000),$ae
irp slotnum,1,2,3,4,5,6,7
; per-slot ROM code
section bank_banknum_slot_slotnum
org $c000+(banknum*$1000)+(slotnum*$0100)
phase $c000+(slotnum*$0100)
; 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
slot0: cmp #$20 ; $Cn01 = $20
cmp #$00 ; $Cn03 = $00
cmp #$03 ; $Cn05 = $03
cmp #$00 ; $cn07 = $00
bcs boot4 ; always taken
; cn0a - RamFactor diagnostic (same entry point as Apple's Slinky memory test)
jsr Scn16
jmp Lcn9b
; cn10 - RamFactor Partion Manager
jsr Scn16
jmp Lcn9f
Scn16: sta clr80vid
sta kbd
sta clraltchar
jsr init
jsr setvid
jsr setkbd
romsel: ldy #$c0+slotnum
ldx Dcfff ; turn off all shared (c800) ROMs, except our
asl hw_reg_rom_bank+(slotnum*$10) ; set bank 0
ldx #(slotnum*$10)+hw_reg_offset
sty mslot
stx mslot1088
jmp Lc9df
boot4: lda #$c0+slotnum ; did we get here from IN# or equiv?
cmp kswl+1
php
jsr Scn16
plp
bne Lcn60
; we got here from IN# or equivalent
jsr Scdec ; are we running Pascal or ProDOS?
beq Lcn60 ; yes
; not Pascal or ProDOS, so patch RWTS
lda #$20
sta rwts_patch
lda #slot_rwts&$ff
sta rwts_patch+1
sty rwts_patch+2
ldx #$00
lda #char_cr+$80 ; return with CR, and also store in input buffer
sta klinbuf
rts
; IN# or equivalent, but running Pascal or ProDOS
Lcn60: lda L00
bne Lcn6e
cpy L00+1
bne Lcn6e
jsr Scn7b
jmp sloop
Lcn6e: lda shs_idx_part_data,y
cmp #$01
bne Lcn9f
jsr Scn7b
clc
bcc Lcn9f
Scn7b: jsr Sca9a
jsr Scaeb
ldy #$c0+slotnum ; high byte of slot ROM base c100
lda bootstrap_entry_addr
beq Lcn9a
lda shs_os_check,y
eor #check_xor_val
cmp shs_os_code,y
bne Lcn9a
sta proflag
ldx #(slotnum*$10)
jmp bootstrap_entry_addr
Lcn9a: rts
; diagnostic
Lcn9b: ldy #$03
bne Lcna1
; partition managere
Lcn9f: ldy #$05
; copy four bytes from table to Z42..Z45
; gets download routine start address in Z42, end+1 in Z44
Lcna1: ldx #$03
Lcna3: lda Dcnd5,y
sta Z42,x
dey
dex
bpl Lcna3
php
sei
stx hw_reg_rom_bank+(slotnum*$10) ; set bank 1
ldx #(slotnum*$10)+hw_reg_offset
ldy #$00 ; set Z3e to point to RAM where diag/partmgr load
sty Z3e
lda #$0a
sta Z3f
Lcnbb: lda (Z42),y ; copy down to RAM
sta (Z3e),y
iny
bne Lcnc6
inc Z3f
inc Z43
Lcnc6: cpy Z44
lda Z43
sbc Z45
bcc Lcnbb
asl hw_reg_rom_bank+(slotnum*$10) ; set bank 0
plp
jmp ram_application_base
; table of bank 1 regions
Dcnd5: fdb b1_diag ; start of diag code
fdb b1_partmgr ; end of diag, start of partition manager
fdb b1_partmgr_end ; end of partition manager
slot_prodos:
clv
bvc slot_prodos_x
slot_protocol_converter
jsr romsel
jmp pconv
slot_prodos_x:
jsr romsel
jmp prodos
; on entry, RWTS code has stored IOB pointer into ?, and has loaded
; the requested slot*$10 into A
slot_rwts:
cmp #(slotnum*$10) ; A = our slot * 10?
beq Lcnf2 ; yes
tax ; no, execute the instructions the
ldy #$0f ; patch overwrote
rts ; and return
Lcnf2: pla ; discard the patch return address
pla
jsr romsel
jmp rwts
fcb $ae ; distinguishes vendor of mem exp card
; $ae = Applied Engineering
fcb $01 ; low bit set = ramdisk
fdb $0000 ; block count (must be obtained by a STATUS request)
fcb $4f ; status byte
; 7 = 0: non-removable
; 6 = 1: interruptible
; 5..4 = 0: 0 volumes on device
; 3 = 1: supports format
; 2 = 1: supports write
; 1 = 1: supports read
; 0 = 1: supports status
fcb slot_prodos & $db ; ProDOS entry point pointer
dephase
endsection bank_banknum_slot_slotnum
endm ; irp slotnum,...
endm ; irp banknum,...
section common
; C800 shared ROM code
org $c800
public pconv ; referenced from slot
pconv:
jsr Scd99
ldx #$09 ; save ten bytes from Z42 on stack
Lc805: lda Z42,x
pha
dex
bpl Lc805
tsx
lda D010c,x
sta Z46
lda D010b,x
sta Z45
ldy #$03
Lc818: lda (Z45),y
sta Z41,y
inc D010b,x
bne Lc825
inc D010c,x
Lc825: dey
bne Lc818
sty shg_04f8
sty shg_0578
sty shg_05f8
tax
cmp #$0a
bcs ret_err_bad_cmd
lda Dc887,x
cmp (Z43),y
bne ret_err_bad_pcnt
ldy #$08
Lc83f: lda (Z43),y
sta Z43,y
dey
bne Lc83f
lsr ; first param is unit num, only allow 0 and 1
bne ret_err_bad_unit_num
ldx mslot1088
ldy Z42 ; protocol converter command
lda #$c8
pha
lda Dc87d,y
pha
lsr Z44
lda Z47
rts
ret_err_bad_unit_num:
lda #$11
skip2
ret_err_bad_cmd:
lda #err_bad_cmd
skip2
ret_err_bad_pcnt:
lda #err_bad_pcnt
LC863: sta shg_04f8
Lc866: ldx #$00
Lc868: pla
sta Z42,x
inx
cpx #$0a
bcc Lc868
ldy shg_05f8
ldx shg_0578
lda shg_04f8
bne Lc87c
clc
Lc87c: rts
; dispatch table for Protocol Converter calls
Dc87d: fcb (pc_cmd_status-1)&$ff ; status
fcb (pc_cmd_read_block-1)&$ff ; read block
fcb (pc_cmd_write_block-1)&$ff ; write block
fcb (pc_cmd_format_init-1)&$ff ; format (no-op)
fcb (pc_cmd_control-1)&$ff ; control
fcb (pc_cmd_format_init-1)&$ff ; init
fcb (pc_cmd_rw_char-1)&$ff ; open character
fcb (pc_cmd_rw_char-1)&$ff ; close character
fcb (pc_cmd_read_bytes-1)&$ff ; read bytes
fcb (pc_cmd_write_bytes-1)&$ff ; write bytes
; parameter count for Protocol Converter calls
Dc887: fcb 3 ; status
fcb 3 ; read block
fcb 3 ; write block
fcb 1 ; format
fcb 3 ; control
fcb 1 ; init
fcb 1 ; open character
fcb 1 ; close character
fcb 4 ; read bytes
fcb 4 ; write bytes
pc_cmd_format_init:
jmp Lc866
pc_cmd_rw_char:
jmp ret_err_bad_cmd
pc_cmd_write_bytes:
bcs Lc8c5
pc_cmd_read_bytes:
bcs Lc8b3
bcc pc_cmd_rw_char
pc_cmd_control:
beq pc_cmd_format_init
Lc89f: lda #$21
jmp Lc863
pc_cmd_read_block:
bcc pc_cmd_rw_char
jsr Sc90c
bcs Lc8c8
lda rdramrd
asl Z4b
asl
ror Z4b
Lc8b3: jmp Lc923
pc_cmd_write_block:
bcc pc_cmd_rw_char
jsr Sc90c
bcs Lc8c8
lda rdramwrt
asl Z4b
asl
ror Z4b
Lc8c5: jmp Lc982
Lc8c8: jmp Lc97d
pc_cmd_status:
bcs Lc8e0
bne Lc89f
ldy #$08
sty shg_0578
Lc8d4: dey
sta (Z45),y
bne Lc8d4
lda #$01
sta (Z45),y
jmp Lc866
Lc8e0: beq Lc8e9
ldy #$19
cmp #$03
bne Lc89f
skip2
Lc8e9: ldy #$04
sty shg_0578
dey
Lc8ef: lda Dc9c6,y
cpy #$02
bne Lc904
ldx mslot
lda shs_cur_part_size_high,x
lsr
sta (Z45),y
dey
lda shs_cur_part_size_low,x
ror
Lc904: sta (Z45),y
dey
bpl Lc8ef
jmp Lc866
Sc90c: asl
sta Z4a
lda Z48
rol
bcs Lc922
sta Z4b
lda Z49
cmp #$01
bcs Lc922
sta Z47
lda #$02
sta Z48
Lc922: rts
Lc923: jsr Sc964
bcs Lc97d
bit rdramwrt
php
asl
bcc Lc932
sta wrauxmem
Lc932: lda Z48
sta shg_05f8
beq Lc947
Lc939: lda hw_reg_data-hw_reg_offset,x
sta (Z45),y
iny
bne Lc939
inc Z46
dec Z48
bne Lc939
Lc947: lda Z47
beq Lc958
sta shg_0578
Lc94e: lda hw_reg_data-hw_reg_offset,x
sta (Z45),y
iny
cpy Z47
bne Lc94e
Lc958: sta wrmainram
plp
bpl Lc961
sta wrauxmem
Lc961: jmp Lc866
Sc964: lda Z49
sta hw_reg_addr_low-hw_reg_offset,x
lda Z4a
sta hw_reg_addr_mid-hw_reg_offset,x
lda Z4b
and #$7f
sta hw_reg_addr_high-hw_reg_offset,x
jsr Sca9d
ldy #$00
lda Z4b
rts
Lc97d: lda #$2d
jmp Lc863
Lc982: jsr Sc964
bcs Lc97d
bit rdramrd
php
sta rdmainram
asl
bcc Lc994
sta rdauxram
Lc994: lda Z48
sta shg_05f8
beq Lc9a9
Lc99b: lda (Z45),y
sta hw_reg_data-hw_reg_offset,x
iny
bne Lc99b
inc Z46
dec Z48
bne Lc99b
Lc9a9: lda Z47
sta shg_0578
beq Lc9ba
Lc9b0: lda (Z45),y
sta hw_reg_data-hw_reg_offset,x
iny
cpy Z47
bne Lc9b0
Lc9ba: sta rdmainram
plp
bpl Lc9c3
sta rdauxram
Lc9c3: jmp Lc866
Dc9c6: fcb $f8,$00,$00,$00
fcb $07,"RAMCARD"
fcb " "
fcb $00,$00,$00,$00
public Lc9df ; referenced by slot, partmgr
Lc9df: ldy mslot
jsr clear_ram_ptr
lda hw_reg_data-hw_reg_offset,x
cmp #$ae
bne Lca31
eor hw_reg_data-hw_reg_offset,x
cmp #check_xor_val
bne Lca31
lda hw_reg_data-hw_reg_offset,x
sta shs_idx_part_data,y
eor #check_xor_val
cmp hw_reg_data-hw_reg_offset,x
bne Lca31
lda hw_reg_data-hw_reg_offset,x
sta shs_card_block_count,y
lda shs_idx_part_data,y
sta hw_reg_addr_low-hw_reg_offset,x
lda hw_reg_data-hw_reg_offset,x
sta shs_part_base_high,y
lda hw_reg_data-hw_reg_offset,x
sta shs_part_base_mid,y
lda hw_reg_data-hw_reg_offset,x
sta shs_cur_part_size_high,y
lda hw_reg_data-hw_reg_offset,x
sta shs_cur_part_size_low,y
lda hw_reg_data-hw_reg_offset,x
sta shs_os_code,y
lda hw_reg_data-hw_reg_offset,x
sta shs_os_check,y
rts
Lca31: lda shs_os_code,y ; is the OS code valid?
eor shs_os_check,y
cmp #check_xor_val
beq Lca73 ; yes, don't have to probe
jsr clear_ram_ptr
lda #$04
sta hw_reg_addr_mid-hw_reg_offset,x
lda hw_reg_data-hw_reg_offset,x
eor hw_reg_data-hw_reg_offset,x
eor hw_reg_data-hw_reg_offset,x
eor hw_reg_data-hw_reg_offset,x
ldx #os_prodos
cmp #$03
beq Lca61
ldx #os_pascal
cmp #$06
beq Lca61
ldx #os_dos
cmp #$be
bne Lca6a
Lca61: txa ; store OS code
sta shs_os_code,y
eor #check_xor_val
sta shs_os_check,y
Lca6a: jsr Scb00
ldy mslot
sta shs_card_block_count,y
Lca73: lda shs_card_block_count,y
asl
sta shs_cur_part_size_high,y
lda #$00
sta shs_cur_part_size_low,y
sta shs_part_base_mid,y
sta shs_part_base_high,y
lda #$01
sta shs_idx_part_data,y
rts
public Sca8b ; referenced from diag, pmgr
Sca8b: ldx mslot1088
public clear_ram_ptr ; referenced from diag, pmgr
; apparently X reg must contain (slot*$10)+$88
clear_ram_ptr:
lda #$00
sta hw_reg_addr_low-hw_reg_offset,x
sta hw_reg_addr_mid-hw_reg_offset,x
sta hw_reg_addr_high-hw_reg_offset,x
rts
public Sca9a ; referenced from slot
Sca9a: jsr clear_ram_ptr
Sca9d: ldy mslot
lda shs_card_block_count,y
cmp #$09
lda hw_reg_addr_high-hw_reg_offset,x
bcs Lcaac
and #$0f
Lcaac: pha
bne Lcacd
lda shs_idx_part_data,y
cmp #$08
bne Lcacd
lda hw_reg_addr_mid-hw_reg_offset,x
cmp #$02
bcs Lcacd
ora #$fe
sta hw_reg_addr_mid-hw_reg_offset,x
lda shs_card_block_count,y
sbc #$00
rol
sta hw_reg_addr_high-hw_reg_offset,x
Lcacb: pla
rts
Lcacd: lda hw_reg_addr_mid-hw_reg_offset,x
cmp shs_cur_part_size_low,y
pla
pha
sbc shs_cur_part_size_high,y
bcs Lcacb
lda hw_reg_addr_mid-hw_reg_offset,x
adc shs_part_base_mid,y
sta hw_reg_addr_mid-hw_reg_offset,x
pla
adc shs_part_base_high,y
sta hw_reg_addr_high-hw_reg_offset,x
rts
public Scaeb ; referenced from slot, pmgr
Scaeb: ldy #$00
Lcaed: lda hw_reg_data-hw_reg_offset,x
sta bootstrap_load_addr,y
iny
bne Lcaed
Lcaf6: lda hw_reg_data-hw_reg_offset,x
sta bootstrap_load_addr+$0100,y
iny
bne Lcaf6
rts
public Scb00 ; referenced from diag
Scb00: jsr Sca8b
tay
cmp hw_reg_addr_high-hw_reg_offset,x
bne Lcb0b
ldy #$02
Lcb0b: ora Dcb95,y
Lcb0e: sta Z3f
sta Z3e
sta hw_reg_addr_high-hw_reg_offset,x
lda hw_reg_data-hw_reg_offset,x
dec hw_reg_addr_low-hw_reg_offset,x
pha
lda Z3f
sta hw_reg_data-hw_reg_offset,x
dec hw_reg_addr_low-hw_reg_offset,x
and Dcb95,y
beq Lcb3d
lda Z3f
sec
sbc Dcb98,y
jmp Lcb0e
Lcb32: clc
lda Z3f
adc Dcb98,y
sta Z3f
sta hw_reg_addr_high-hw_reg_offset,x
Lcb3d: lda hw_reg_data-hw_reg_offset,x
cmp Z3f
bne Lcb83
eor #$ff
dec hw_reg_addr_low-hw_reg_offset,x
sta hw_reg_data-hw_reg_offset,x
dec hw_reg_addr_low-hw_reg_offset,x
cmp hw_reg_data-hw_reg_offset,x
bne Lcb83
dec hw_reg_addr_low-hw_reg_offset,x
lda Z3f
and Dcb95,y
cmp Dcb95,y
bne Lcb32
Lcb61: lda Z3e
sta hw_reg_addr_high-hw_reg_offset,x
pla
sta hw_reg_data-hw_reg_offset,x
dec hw_reg_addr_low-hw_reg_offset,x
clc
lda Z3e
adc Dcb98,y
sta Z3e
and Dcb95,y
bne Lcb61
lda Z3f
dey
bpl Lcb0b
lsr
adc #$02
rts
Lcb83: dec hw_reg_addr_low-hw_reg_offset,x
sec
lda Z3f
beq Lcb61
sbc Dcb98,y
sta Z3f
jmp Lcb61
fcb $ea,$ea
Dcb95: fcb $0c,$30,$c0
Dcb98: fcb $04,$10,$40
public Scb9b ; referenced from diag, pmgr
Scb9b: ldx #$04
ldy #$00
Lcb9f: lda #$00
Lcba1: pha
sec
lda Z3e
sbc Dcbde,x
pha
lda Z3f
sbc Dcbe3,x
bcc Lcbba
sta Z3f
pla
sta Z3e
pla
adc #$00
bne Lcba1
Lcbba: pla
pla
bne Lcbc6
dey
bpl Lcbc6
txa
beq Lcbc6
lda #$10
Lcbc6: iny
eor #$b0
jsr cout
dex
bpl Lcb9f
lda #$cb
jmp cout
; cbd4:
fcb $08,$08,$20,$38,$50,$68,$80,$98
fcb $b0,$c8
Dcbde: fcb $04,$28,$90,$a0,$40
Dcbe3: fcb $00,$00,$01,$0f,$9c
public prodos ; reference from slot
prodos:
ldy Z42
iny
beq Scc58
jsr Scd99
ldy #$2b
bcs Lcc0c
ldy #$28
lda Z43
bmi Lcc0c
ldy Z42
beq prodos_status
dey
beq prodos_read
dey
beq prodos_write
dey
beq prodos_format
ldy #err_bad_cmd
skip2
lcc0a: ldy #err_io_error
Lcc0c: tya
sec
rts
prodos_status:
ldy mslot
jsr copy_s2g_part_size
ldy shg_0478
ldx shg_04f8
prodos_format
: lda #$00
clc
rts
prodos_read:
jsr Scc58
bcs Lcc0a
ldy #$00
Lcc26: lda hw_reg_data-hw_reg_offset,x
sta (Z44),y
iny
bne Lcc26
inc Z45
Lcc30: lda hw_reg_data-hw_reg_offset,x
sta (Z44),y
iny
bne Lcc30
Lcc38: dec Z45
tya
clc
rts
prodos_write:
jsr Scc58
bcs Lcc0a
ldy #$00
Lcc44: lda (Z44),y
sta hw_reg_data-hw_reg_offset,x
iny
bne Lcc44
inc Z45
Lcc4e: lda (Z44),y
sta hw_reg_data-hw_reg_offset,x
iny
bne Lcc4e
beq Lcc38
Scc58: lda #$00
sta hw_reg_addr_low-hw_reg_offset,x
lda Z46
asl
sta hw_reg_addr_mid-hw_reg_offset,x
lda Z47
rol
bcs Lcc6e
sta hw_reg_addr_high-hw_reg_offset,x
jsr Sca9d
Lcc6e: rts
; The RWTS IOB pointer is in Z48
public rwts ; referenced from slot
rwts: jsr Scd56
ldy #$10
bcs Lcce0
jsr dos_check_partition_size
ldy #rwts_iob_idx_drive
lda (rwtsiob),y
sta Z3e
eor #$01
beq Lcc88
bcc rwts_bad_cmd
jsr Scd16
Lcc88: ldy #rwts_iob_idx_prev_vol
lda #$fe
sta (rwtsiob),y
ldy #rwts_iob_idx_track ; check track number against maximum
sty Z3f
lda (rwtsiob),y
cmp dos_max_track,x
bcs rwts_bad_cmd
lsr
ror Z3f
lsr
ror Z3f
lsr
ror Z3f
cpx #$01
beq Lcca9
lsr
ror Z3f
Lcca9: pha
iny ; check sector number
lda (rwtsiob),y
cmp dos_max_sector,x
bcs rwts_bad_cmd
ora Z3f
pha
jsr Sca8b
pla
sta hw_reg_addr_mid-hw_reg_offset,x
pla
sta hw_reg_addr_high-hw_reg_offset,x
jsr Sca9d
bcs rwts_bad_cmd
ldy #rwts_iob_idx_buffer ; copy buffer address to ZP
lda (rwtsiob),y
sta Z3e
iny
lda (rwtsiob),y
sta Z3f
ldy #rwts_iob_idx_command
lda (rwtsiob),y
tay
beq rwts_seek
dey
beq rwts_read
dey
beq rwts_write
rwts_bad_cmd:
sec
ldy #rwts_err_read
Lcce0: bne rwts_done
rwts_write:
lda (Z3e),y
sta hw_reg_data-hw_reg_offset,x
iny
bne rwts_write
beq rwts_seek
rwts_read:
lda hw_reg_data-hw_reg_offset,x
sta (Z3e),y
iny
bne rwts_read
rwts_seek:
clc
rwts_done:
tya
ldy #rwts_iob_idx_result
sta (rwtsiob),y
rts
; check DOS parition size
; returns with 0 in X for 140 KiB drive(s), 1 in X for 400 KiB drive(s)
dos_check_partition_size:
ldy mslot
ldx #$03
Lcd00: lda shs_cur_part_size_low,y
cmp valid_dos_part_size_low,x
lda shs_cur_part_size_high,y
sbc valid_dos_part_size_high,x
bcs Lcd12
dex
bpl Lcd00
rts
Lcd12: txa
lsr
tax
rts
Scd16: clc
ldy mslot
lda shs_part_base_mid,y
adc Dcd3b,x
sta shs_part_base_mid,y
lda shs_part_base_high,y
adc Dcd39,x
sta shs_part_base_high,y
rts
; valid DOS parition sizes
valid_dos_part_size_high:
fcb (140*4)>>8 ; one 140 KiB
fcb (280*4)>>8 ; two 140 KiB
fcb (400*4)>>8 ; one 400 KiB
fcb (800*4)>>8 ; two 400 KiB
valid_dos_part_size_low:
fcb (140*4)&$ff ; one 140 KiB
fcb (280*4)&$ff ; two 140 KiB
fcb (400*4)&$ff ; one 400 KiB
fcb (800*4)&$ff ; two 400 KiB
dos_max_track:
fcb 35 ; for 140 KiB drives
fcb 50 ; for 400 KiB drives
dos_max_sector:
fcb 16 ; for 140 KiB drives
fcb 32 ; for 400 KiB drives
Dcd39: fcb $02,$06
Dcd3b: fcb $30,$40
Scd3d:
; is partition size at least 4KB?
; return:
; carry clear if paritition too small
; carry set, zero clear if size OK but unknwon OS
; carry set, zero set if size and OS both OK, A = OS
ldy mslot
jsr copy_s2g_part_size
cmp #$10
bcs Lcd4c
lda shg_0478
beq Lcd55
Lcd4c: lda shs_os_check,y
eor #check_xor_val
cmp shs_os_code,y
sec
Lcd55: rts
Scd56: jsr Scd3d ; check parition size and OS
bcc Lcd97 ; parititon too small
bne Lcd63 ; parition size OK, but OS unknown
cmp #os_dos
bne Lcd97 ; not a DOS partition
clc
rts
Lcd63: lda #os_dos ; set OS to DOS (but don't yet set OS check)
sta shs_os_code,y
jsr dos_check_partition_size
bmi Lcd97
bcc Lcd91
lda shs_part_base_mid,y
pha
lda shs_part_base_high,y
pha
stx shg_04f8
jsr Scd16
ldy Dcfe2,x
jsr Scdfb
ldx shg_04f8
ldy mslot
pla
sta shs_part_base_high,y
pla
sta shs_part_base_mid,y
Lcd91: ldy Dcfe2,x
jmp Lcdc1
Lcd97: sec
rts
Scd99: jsr Scd3d
bcc Lcdb0
bne Lcdb2
cmp #$cd
bne Lcda6
Lcda4: clc
rts
Lcda6: jsr Scdec
bne Lcdb0
cmp shs_os_code,y
beq Lcda4
Lcdb0: sec
rts
Lcdb2: jsr Scdec
bne Lcdb0
sta shs_os_code,y
ldy #$00
asl
bne Lcdc1
ldy #$87
Lcdc1: jsr Scdfb
jsr clear_ram_ptr
ldy mslot
lda shs_idx_part_data,y
cmp #$01
beq Lcde2
clc
adc #$04
sta hw_reg_addr_low-hw_reg_offset,x
lda shs_os_code,y
sta hw_reg_data-hw_reg_offset,x
eor #check_xor_val
sta hw_reg_data-hw_reg_offset,x
Lcde2: lda shs_os_code,y
eor #check_xor_val
sta shs_os_check,y
clc
rts
public Scdec ; referenced from slot
Scdec: lda proflag
beq Lcdf3 ; Pascal
cmp #os_prodos
Lcdf3: rts
Lcdf4: ldx mslot1088
jsr Sce67
iny
public Scdfb ; referenced from pmgr
Scdfb: lda Dcf30,y
bne Lcdf4
rts
Lce01: and #$0f
sta hw_reg_data-hw_reg_offset,x
Sce06: lda #$00
sta hw_reg_data-hw_reg_offset,x
rts
Lce0c: tya
pha
lda shg_04f8
cmp #$01
lda shg_0478
sbc #$00
lsr
lsr
lsr
lsr
tay
lda #$ff
sta Z3e
lda #$03
Lce23: lsr
ror Z3e
dey
bpl Lce23
sta hw_reg_data-hw_reg_offset,x
lda Z3e
sta hw_reg_data-hw_reg_offset,x
pla
tay
rts
Lce34: jsr Sce53
lda #$01
Lce39: pha
jsr Sce06
lda #$11
sta hw_reg_data-hw_reg_offset,x
pla
pha
sta hw_reg_data-hw_reg_offset,x
jsr Sce53
pla
clc
adc #$01
cmp #$1f
bcc Lce39
rts
Sce53: lda #$00
skip2
Lce56: lda #$ff
Lce58: sta hw_reg_data-hw_reg_offset,x
cmp hw_reg_addr_low-hw_reg_offset,x
bne Lce58
ror
bcc Lce66
sta hw_reg_data-hw_reg_offset,x
Lce66: rts
Sce67: cmp #$40
bcs Lce8e
cmp #$30
bcs Lcead
cmp #$20
bcs Lce01
cmp #$10
bcs Lce0c
cmp #$04
beq Lcec5
bcs Lce85
cmp #$02
bcc Lced9
beq Sce53
bcs Lce56
Lce85: cmp #$06
bcc Lced2
beq Lce34
jmp Lcef4
Lce8e: pha
and #$3f
beq Lceab
pla
pha
and #$c0
asl
beq Lcea2
lda #$ff
bcs Lcea2
iny
lda Dcf30,y
Lcea2: sta hw_reg_data-hw_reg_offset,x
pla
sec
sbc #$01
bne Lce8e
Lceab: pla
rts
Lcead: and #$0f
Lceaf: pha
lda #$ff
sta hw_reg_data-hw_reg_offset,x
sta hw_reg_data-hw_reg_offset,x
jsr Sce06
sta hw_reg_data-hw_reg_offset,x
pla
sec
sbc #$01
bne Lceaf
rts
Lcec5: lda shg_04f8
sta hw_reg_data-hw_reg_offset,x
lda shg_0478
Lcece: sta hw_reg_data-hw_reg_offset,x
rts
Lced2: lda mslot
eor #$f0
bne Lcece
Lced9: lda #$00
sta hw_reg_addr_low-hw_reg_offset,x
iny
lda Dcf30,y
sta hw_reg_addr_mid-hw_reg_offset,x
iny
lda Dcf30,y
sta hw_reg_addr_high-hw_reg_offset,x
tya
pha
jsr Sca9d
pla
tay
rts
Lcef4: tya
pha
ldy shg_0478
beq Lcf08
nop
Lcefc: tya
pha
ldy #$20
jsr Scf27
pla
tay
dey
bne Lcefc
Lcf08: lda shg_04f8
pha
lsr
lsr
lsr
beq Lcf15
tay
jsr Scf27
Lcf15: pla
and #$07
tay
lda #$00
Lcf1b: sec
ror
dey
bpl Lcf1b
asl
sta hw_reg_data-hw_reg_offset,x
pla
tay
rts
Scf27: lda #$ff
Lcf29: sta hw_reg_data-hw_reg_offset,x
dey
bne Lcf29
rts
Dcf30: fcb $01,$00,$00,$02,$02,$01,$02,$00
fcb $02,$02,$20,$23,$44,$f4
fcb "RAM"
fcb $05,$99,$43,$c3,$27,$0d,$20
fcb $26,$04,$02,$02,$22,$24,$02,$02
fcb $23,$25,$02,$02,$24,$20,$02,$02
fcb $07,$02,$02,$01,$0c,$00,$10,$00
fcb $01,$00,$00,$02,$01,$04,$00,$44
fcb $02,$0f,$20,$93,$01,$10,$01,$47
fcb $33,$11,$0f,$04,$00,$00,$fe,$a0
fcb $41,$7a,$88,$48,$11,$01,$00,$00
fcb $23,$10,$00,$01,$88,$3f,$84,$3f
fcb $32,$02,$06,$00,$01,$00,$00,$02
fcb $01,$04,$00,$44,$02,$0f,$20,$93
fcb $01,$20,$02,$47,$33,$11,$1f,$04
fcb $00,$00,$fe,$a0,$41,$7a,$88,$48
fcb $11,$01,$00,$00,$32,$20,$00,$01
fcb $84,$c8,$f8,$84,$03,$06,$00,$01
fcb $00,$00,$02,$02,$01,$02,$00,$02
fcb $02,$82,$41,$06,$83,$44,$04
fcb "RAM"
fcb $05,$83,$04,$02,$02,$02
fcb $02,$02,$02,$02,$02,$02,$02,$02
fcb $02,$00,$44,$ae,$f4,$08,$52,$02
fcb $02,$00
Dcfe2: fcb $30,$5c
copy_s2g_part_size:
lda shs_cur_part_size_high,y
lsr
sta shg_0478
lda shs_cur_part_size_low,y
ror
sta shg_04f8 ; leaves part_size_low in A
rts
fillto $d000,$ff
endsection common
; bank 1 common space ($c800-$cfff)
org $d800
b1_diag equ *-$1000
section diag
phase ram_application_base
ch equ $24
Z28 equ $28
Z29 equ $29
diag: stx dD0d2b
jsr home
ldy #d_msg_idx_banner
jsr d_msgout
jsr Scb00
sta dD0d2a
ldy #$00
sty dD0d2f
asl
bcc dL0a1b
dey
tya
dL0a1b: sty Z3e
sta Z3f
jsr Scb9b
ldy #d_msg_idx_bytes
jsr d_msgout
jsr Sca8b
sta hw_reg_data-hw_reg_offset,x
lda #$04
sta hw_reg_addr_mid-hw_reg_offset,x
lda #$ff
sta hw_reg_data-hw_reg_offset,x
ldy mslot
sta shs_os_code,y
dL0a3d: lda #$00
sta ch
ldy #d_msg_idx_pass
jsr d_msgout
lda dD0d2f
jsr prbyte
ldy #d_msg_idx_testing
jsr d_msgout
lda ch
clc
adc Z28
sta dS0ae4+1
lda #$00
adc Z29
sta dS0ae4+2
ldy #$08
dL0a62: dey
dey
sty dD0d29
jsr dS0ae4
jsr dS0ae8
bcs dL0a80
ldy dD0d29
bne dL0a62
inc dD0d2f
lda kbd
bpl dL0a3d
sta kbdstrb
rts
dL0a80: tya
pha
ldy #d_msg_idx_card_failure
jsr d_msgout
lda #$08
sec
sbc dD0d29
lsr
tay
ora #$b0
jsr cout
cpy #$03
bcs dL0a9a
pla
rts
dL0a9a: ldy #d_msg_idx_address
jsr d_msgout
ldx mslot1088
lda hw_reg_addr_low-hw_reg_offset,x
dec hw_reg_addr_low-hw_reg_offset,x
and #$7f
bne dL0ab9
lda hw_reg_addr_mid-hw_reg_offset,x
dec hw_reg_addr_mid-hw_reg_offset,x
and #$7f
bne dL0ab9
dec hw_reg_addr_high-hw_reg_offset,x
dL0ab9: lda hw_reg_addr_high-hw_reg_offset,x
ldy dD0d2a
cpy #$09
bcs dL0ac5
and #$0f
dL0ac5: jsr prbyte
lda hw_reg_addr_mid-hw_reg_offset,x
jsr prbyte
lda hw_reg_addr_low-hw_reg_offset,x
jsr prbyte
lda #$ad
jsr cout
pla
eor hw_reg_data-hw_reg_offset,x
jsr prbyte
jsr crout
rts
dS0ae4: inc D0400
rts
dS0ae8: lda dD0af4+1,y
pha
lda dD0af4,y
pha
ldx dD0d2b
rts
dD0af4: fdb dL0be4-1
fdb dL0b81-1
fdb dL0b1e-1
fdb dL0afc-1
dL0afc: ldy #$00
dL0afe: tya
jsr dS0b0a
eor hw_reg_addr_high-hw_reg_offset,x
and #$0f
bne dL0b1c
tya
cmp hw_reg_addr_mid-hw_reg_offset,x
bne dL0b1c
cmp hw_reg_addr_low-hw_reg_offset,x
bne dL0b1c
jsr dS0ae4
iny
bne dL0afe
clc
rts
dL0b1c: sec
rts
dL0b1e: lda #$00
ldy #$f0
jsr dS0b0a
dL0b25: lda dD0d28
jsr dS0b6b
sta dD0d28
lda dD0d27
jsr dS0b6b
sta dD0d27
jsr dS0d13
inc dD0d28
bne dL0b4b
inc dD0d27
bne dL0b4b
inc dD0d26
bne dL0b4b
clc
rts
dL0b4b: jsr dS0ae4
lda hw_reg_data-hw_reg_offset,x
lda hw_reg_addr_high-hw_reg_offset,x
eor dD0d26
bne dL0b69
lda hw_reg_addr_mid-hw_reg_offset,x
cmp dD0d27
bne dL0b69
lda hw_reg_addr_low-hw_reg_offset,x
cmp dD0d28
beq dL0b25
dL0b69: sec
rts
dS0b6b: cmp #$10
bcc dL0b75
cmp #$70
bcs dL0b76
lda #$70
dL0b75: rts
dL0b76: cmp #$90
bcc dL0b75
cmp #$f0
bcs dL0b75
lda #$f0
rts
dL0b81: lda dD0d2a
beq dL0b94
lda #$00
sta dD0d30
jsr dS0b96
jsr dS0b96
jsr dS0b96
dL0b94: clc
rts
dS0b96: jsr clear_ram_ptr
tay
dL0b9a: tya
sta hw_reg_data-hw_reg_offset,x
jsr dS0bbe
bne dL0b9a
jsr dS0ae4
tya
jsr dS0b0a
dL0baa: tya
cmp hw_reg_data-hw_reg_offset,x
bne dL0bba
jsr dS0bbe
bne dL0baa
sec
ror dD0d30
rts
dL0bba: pla
pla
sec
rts
dS0bbe: bit dD0d30
bpl dL0bdb
inc dD0d26
inc hw_reg_addr_high-hw_reg_offset,x
lda dD0d26
lsr
cmp dD0d2a
bcc dL0bdb
ldy #$00
rts
fcb $ee,$27,$0d,$fe,$f9,$bf
dL0bdb: inc dD0d28
iny
rts
dD0be0: fcb $00,$55,$aa,$ff
dL0be4: lda dD0d2a
beq dL0bfc
ldy #$03
dL0beb: lda dD0be0,y
sta dD0d2c
jsr dS0bfe
jsr dS0c2e
bcs dL0bfd
dey
bpl dL0beb
dL0bfc: clc
dL0bfd: rts
dS0bfe: jsr dS0c6d
dL0c01: jsr dS0c0a
dec dD0d2d
bne dL0c01
rts
dS0c0a: tya
pha
lda dD0d2c
ldy #$00
sty dD0d2e
dL0c14: sta hw_reg_data-hw_reg_offset,x
sta hw_reg_data-hw_reg_offset,x
sta hw_reg_data-hw_reg_offset,x
sta hw_reg_data-hw_reg_offset,x
iny
bne dL0c14
jsr dS0ae4
inc dD0d2e
bne dL0c14
pla
tay
rts
dS0c2e: jsr dS0c6d
dL0c31: jsr dS0c3c
bcs dL0c3b
dec dD0d2d
bne dL0c31
dL0c3b: rts
dS0c3c: tya
pha
lda dD0d2c
ldy #$00
sty dD0d2e
dL0c46: cmp hw_reg_data-hw_reg_offset,x
bne dL0c69
cmp hw_reg_data-hw_reg_offset,x
bne dL0c69
cmp hw_reg_data-hw_reg_offset,x
bne dL0c69
cmp hw_reg_data-hw_reg_offset,x
bne dL0c69
iny
bne dL0c46
jsr dS0ae4
inc dD0d2e
bne dL0c46
pla
tay
clc
rts
dL0c69: tay
pla
sec
rts
dS0c6d: lda dD0d2a
lsr
sta dD0d2d
jmp clear_ram_ptr
; d_msgout decompresses and outputs a message
; Y indexes d_msgtab, carry alternates 0 = high nibble, 1 = low nibble
dL0c77: php
jsr cout
plp
skip1
d_msgout:
clc ; start with high nibble
jsr d_getnib ; get nibble
lda d_msg_dec_tab_1,x ; index first table
bne dL0c77 ; if table content non-zero, it's a char
jsr d_getnib ; get nibble
lda d_msg_dec_tab_2,x ; index second table
bne dL0c77 ; if table content non-zero, it's a char
rts ; if both table entries were zero, end of message
; get one nibble
d_getnib:
lda d_msgtab,y ; get byte from message table
bcs dL0c9b ; carry clear?
lsr ; yes, get high nibble
lsr
lsr
lsr
tax
sec ; set carry so next call will get low nibble
rts
; carry was set,
dL0c9b: iny ; advance pointer
and #$0f
tax
clc ; clear carry so next call will get high nibble
rts
; nibble to character decode table 1
; note that this table includes the first byte of decode table 2
; table includes all but three of the letters ETAOINSHRDLC, the 13
; most common letters of the English language, in an arbitrary
; permutation that might be intended to confuse reverse-engineers.
d_msg_dec_tab_1:
fcb $00 ; escabe to second table
fcb char_cr+$80 ; carriage return
fcsm "RAM.TIS GOLDE"
; mibble to character decode table 2
d_msg_dec_tab_2:
fcsm "N"
fcb $00 ; end of message
fcsm "BCFHPYZMQUV14:"
; Strings used at assembly time to perform the encoding
; These MUST match the decoding tables defined above
; \xff is a placeholder for a zero entry in the table, because AS doesn't support
; null bytes in strings
; \x01 is a special value that expands to two spaces
tbl1 set "\xff\x0dRAM.TIS GOLDEN"
tbl2 set "N\xffBCFHPYZMQUV14:"
; compressed message table
d_msgtab:
d_msg_idx_banner equ *-d_msgtab
encode "APPLIED ENGINEERING RAMFACTOR TEST V1.4\x0d\x0dMEMORY SIZE: "
d_msg_idx_bytes equ *-d_msgtab
encode " BYTES\x0d\x0d"
d_msg_idx_pass equ *-d_msgtab
encode "PASS: "
d_msg_idx_testing equ *-d_msgtab
encode " TESTING ..."
d_msg_idx_card_failure equ *-d_msgtab
encode "\x0d\x0dCARD FAILURE. ID: "
d_msg_idx_address equ *-d_msgtab
encode " ADDRESS: "
dS0b0a: sta dD0d28
sta dD0d27
sty dD0d26
dS0d13: lda dD0d28
sta hw_reg_addr_low-hw_reg_offset,x
lda dD0d27
sta hw_reg_addr_mid-hw_reg_offset,x
lda dD0d26
sta hw_reg_addr_high-hw_reg_offset,x
rts
dD0d26: equ *
dD0d27: equ *+1
dD0d28: equ *+2
dD0d29: equ *+3
dD0d2a: equ *+4
dD0d2b: equ *+5
dD0d2c: equ *+6
dD0d2d: equ *+7
dD0d2e: equ *+8
dD0d2f: equ *+9
dD0d30: equ *+10
dephase
endsection diag
b1_diag_end equ *-$1000
b1_partmgr equ *-$1000
section partmgr
phase ram_application_base
; parition table buffer
pt_buffer equ $0800
D0802 equ pt_buffer+$02
D0803 equ pt_buffer+$03
part_table_entry_size equ $18
; partition table entry addresses, must be indexed
pte_ofs_base_addr_high equ $00 ; parition base address high
pte_ofs_base_addr_mid equ $01 ; parition base address mid
pte_ofs_size_high equ $02 ; partition size high
pte_ofs_size_mid equ $03 ; parititon size mid
pte_ofs_os_code equ $04 ; OS code
pte_ofs_os_check equ $05 ; OS check
pte_ofs_name equ $08 ; partition name
D0900 equ $0900
D0901 equ $0901
D0902 equ $0902
D0903 equ $0903
D0904 equ $0904
D0905 equ $0905
D0906 equ $0906
D0907 equ $0907
D0908 equ $0908
partition_table_entry_size equ 24
partmgr:
; check for valid parition table
jsr Sca8b
lda hw_reg_data-hw_reg_offset,x
cmp #$ae
bne pL0a1b
eor hw_reg_data-hw_reg_offset,x
cmp #$5a
bne pL0a1b
lda hw_reg_data-hw_reg_offset,x
eor hw_reg_data-hw_reg_offset,x
cmp #$5a
beq pL0a6b
; no valid partition table found, will need to create a partition table
pL0a1b: ldy mslot ; are the screen holes valid?
lda shs_os_code,y
eor shs_os_check,y
cmp #$5a
bne pL0a3f ; screen holes were not valid
; screen holes were valid, ask user if partition table should be installed
jsr home
ldy #p_msg_idx_warning_installing
jsr p_msgout
lda #'?'+$80
jsr cout
jsr rdkey_uc
cmp #'Y'+$80
beq pL0a3f
jmp pL0e06 ; user says no; reboot?
; install a parititon table
pL0a3f: jsr Sca8b
ldy #$aa
jsr Scdfb
jsr Sca8b
lda #$04
sta hw_reg_addr_low-hw_reg_offset,x
ldy mslot
lda shs_card_block_count,y
pha
sta hw_reg_data-hw_reg_offset,x
lda #$0a
sta hw_reg_addr_low-hw_reg_offset,x
pla
asl
sec
sbc #$01
sta hw_reg_data-hw_reg_offset,x
lda #$fc
sta hw_reg_data-hw_reg_offset,x
pL0a6b: jsr clear_ram_ptr
jsr Scaeb
lda D0802
sta D0901
jsr home
pL0a7a: lsr D0900
pm_main_loop: lda #$00 ; home the cursor without clearing the screen
sta ch
sta Cv
ldy #p_msg_idx_heading
jsr p_msgout
lda mslot
eor #$70
jsr cout
jsr crout
jsr crout
ldy #$00
pL0a98: jsr pS0c03
iny
cpy #$09
bcc pL0a98
ldy #p_msg_idx_help_1
jsr p_msgout
ldy #$59
bit D0900
bpl pL0aee
ldy #p_msg_idx_help_2
pL0aee: jsr p_msgout
jsr clreop
jsr rdkey_uc
cmp #'1'+$80
bcc pL0acf ; not a digit
cmp #'9'+1+$80
bcs pL0acf ; not a digit
sbc #$b0 ; ASCII to binary digit
jsr part_num_to_part_table_offset
sta D0901
bit D0900
bmi pm_main_loop
jmp pL0df6
pL0acf: sta D0902
ldy #$06
bit D0900
bpl pL0adb
ldy #$fd ; 253 }
pL0adb: iny
iny
iny
lda pD0af7,y
beq pL0af1
cmp D0902
bne pL0adb
lda pD0af7+2,y
pha
lda pD0af7+1,y
pha
rts
pL0af1: jsr bell12
jmp pm_main_loop
pD0af7: cmd_ent 'N',p_cmd_name
cmd_ent 'C',p_cmd_clear ; Clear a partition
cmd_ent 'S',p_cmd_size ; change Size of a partition
cmd_ent char_cr,p_cmd_boot ; boot partition
cmd_ent key_left,p_cmd_up
cmd_ent key_up,p_cmd_up
cmd_ent key_down,p_cmd_down
cmd_ent key_right,p_cmd_down
cmd_ent char_esc,p_cmd_exit ; quit
cmd_ent 'R',p_cmd_reconfigure ; Reconfigure
fcb $00 ; end of table
p_cmd_boot:
bit D0900
bmi pL0b1e
jmp pL0df6
pL0b1e: jsr pS0de8
jmp pL0a7a
p_cmd_reconfigure:
sec
ror D0900
jmp pm_main_loop
p_cmd_exit:
bit D0900
bpl pL0b33
jmp ram_application_base
pL0b33: jsr pS0dd7
jmp pL0e36
p_cmd_up:
lda D0901
sec
sbc #partition_table_entry_size
pL0b3f: cmp #$e0
bcs L0b46
sta D0901
L0b46: jmp pm_main_loop
p_cmd_down:
lda D0901
clc
adc #partition_table_entry_size
bcc pL0b3f
p_cmd_name:
ldy #p_msg_idx_new_name
jsr p_msgout
ldx #$10
jsr pS0e4f
bcs pL0b6e
ldx #$00
ldy D0901
pL0b62: lda D0908,x
sta pt_buffer+pte_ofs_name,y
iny
inx
cpx #$10
bcc pL0b62
pL0b6e: jmp pm_main_loop
p_cmd_size:
jsr pS0e43
beq pL0bea
tya
clc
adc #partition_table_entry_size
tay
cpy #$e0
bcs pL0bea
jsr pS0e46
beq pL0bea
ldy #p_msg_idx_new_size
jsr p_msgout
ldx #$06
jsr pS0e4f
jsr pS0ea1
asl D0904
rol D0905
asl D0904
rol D0905
clc
ldy D0901
lda pt_buffer+pte_ofs_size_mid,y
adc pt_buffer+part_table_entry_size+pte_ofs_size_mid,y
sta D0906
lda pt_buffer+pte_ofs_size_high,y
adc pt_buffer+part_table_entry_size+pte_ofs_size_high,y
sta D0907
sec
lda D0906
sbc D0904
pha
lda D0907
sbc D0905
bcc pL0be6
sta pt_buffer+part_table_entry_size+pte_ofs_size_high,y
pla
sta pt_buffer+part_table_entry_size+pte_ofs_size_mid,y
clc
lda D0904
sta pt_buffer+pte_ofs_size_mid,y
adc pt_buffer+pte_ofs_base_addr_mid,y
sta pt_buffer+part_table_entry_size+pte_ofs_base_addr_mid,y
lda D0905
sta pt_buffer+pte_ofs_size_high,y
adc pt_buffer+pte_ofs_base_addr_high,y
sta pt_buffer+part_table_entry_size+pte_ofs_base_addr_high,y
jmp pm_main_loop
pL0be6: pla
ldy #$d5
skip2
pL0bea: ldy #$c9
jsr p_msgout
jsr rdkey
jmp pm_main_loop
p_cmd_clear:
jsr pS0e43
bne pL0c00
ldx D0901
inc pt_buffer+pte_ofs_os_check,x
pL0c00: jmp pm_main_loop
; display one parition table entry
pS0c03: tya
pha
jsr part_num_to_part_table_offset
pha
; set inverse if this parition is active
ldx #$ff
cmp D0901
bne pL0c12
ldx #$3f
pL0c12: stx invflg
; indent two spaces
jsr print_two_spaces
; output paritition number, two more spaces
tya
clc
adc #$b1
jsr cout
jsr print_two_spaces
pla
; output paritition name, followed by two spaces
pha
tay
ldx #$10
pL0c26: lda pt_buffer+pte_ofs_name,y
bne pL0c2d
lda #' '+$80 ; NUL chars converted to spaces
pL0c2d: jsr cout
iny
dex
bne pL0c26
jsr print_two_spaces
pla
; output partition size in KiB, followed by two spaces
pha
tay
lda pt_buffer+pte_ofs_size_high,y
sta Z3f
lda pt_buffer+pte_ofs_size_mid,y
sta Z3e
jsr Scb9b
lda #$ff
sta invflg
jsr print_two_spaces
pla
; output paritition type
tay
lda pt_buffer+pte_ofs_os_check,y
eor #$5a
cmp pt_buffer+pte_ofs_os_code,y
beq pL0c5c
lda #$01 ; if the parition type is invalid (code xor check != 0x5a), consider it clear ($01 not in table)
pL0c5c: ldy #$04 ; search paritiion type table for the code
pL0c5e: cmp parition_type_code_table-1,y
beq pL0c66
dey
bne pL0c5e
; if we fall through here, Y=00, which means that there was no match, and that the parititon is "clear"
pL0c66: lda partition_type_msg_idx_table,y
tay
jsr p_msgout
pla
tay
rts
parition_type_code_table:
fcb os_prodos
fcb os_pascal
fcb os_dos
fcb os_cpm
partition_type_msg_idx_table:
fcb p_msg_idx_clear
fcb p_msg_idx_prodos
fcb p_msg_idx_pascal
fcb p_msg_idx_dos
fcb p_msg_idx_cpm
print_two_spaces:
lda #' '+$80
jsr cout
jmp cout
; get offset into first RAMdisk page of a parition table entry
part_num_to_part_table_offset:
sta D0902
asl
adc D0902
asl
asl
asl
adc #$08
rts
; Decompress and output a message
; Y indexes p_msgtab, carry alternates 0 = high nibble, 1 = low nibble
p_msgout:
clc
pL0c8f: jsr p_getnib ; get nibble
lda pD0cbe,x ; index first table
bne pL0ca0 ; if table content non-zero, it's a char
jsr p_getnib ; it was zero, get next nibble
lda pD0ccd,x ; index second table
bne pL0ca0 ; if table content non-zero, it's a char
rts ; if both table entries were zero, end of message
; output a decoded character, except if MSB is zero, output two spaces
pL0ca0: php
bmi pL0ca6
jsr print_two_spaces
pL0ca6: jsr cout
plp
bne pL0c8f
; get one nibble
p_getnib:
lda p_msgtab,y ; get byte from message table
bcs pL0cb8 ; carry clear?
lsr ; yes, get high nibble
lsr
lsr
lsr
tax
sec ; set carry so next call will get low nibble
rts
; carry was set, getting low nibble
pL0cb8: iny ; advance pointer
and #$0f
tax
clc ; clear carry so next call will get high nibble
rts
; nibble to character decode table 1
; note that this table includes the first byte of decode table 2
; table includes all but one of the letters ETAOINSHRDLC, the 13
; most common letters of the English language, in an arbitrary
; permutation that might be intended to confuse reverse-engineers.
pD0cbe: fcb $00 ; escape to second table
fcb char_cr+$80 ; carriage return
fcb $01 ; two spaces
fcsm "GLITCH REASO"
; nibble to character decode table 2
pD0ccd: fcsm "N"
fcb $00 ; end of message
fcsm "FPUDM-19=BQWZY"
; Strings used at assembly time to perform the encoding
; These MUST match the decoding tables defined above
; \xff is a placeholder for a zero entry in the table, because AS doesn't support
; null bytes in strings
; \x01 is a special value that expands to two spaces
tbl1 set "\xff\x0d\x01GLITCH REASON"
tbl2 set "N\xffFPUDM-19=BQWZY"
; compressed message table
p_msgtab:
p_msg_idx_heading equ *-p_msgtab
encode "\x0dRAMFACTOR PARTITIONS\x01\x01\x01 SLOT = "
p_msg_idx_help_1 equ *-p_msgtab
encode "\x0dUSE ARROWS OR 1-9 TO SELECT\x0d\x0d"
p_msg_idx_help_2 equ *-p_msgtab
encode "N=NAME CHANGE\x01\x01 RET=INSTALL CHANGES\x0dS=SIZE CHANGE\x01\x01 ESC=FORGET CHANGES\x0dC=CLEAR PARTITION"
; XXX referenced from where?
p_msg_idx_help_3 equ *-p_msgtab
encode "RET=BOOT THE PARTITION\x01 R=RECONFIGURE\x0dESC=QUIT"
p_msg_idx_new_name equ *-p_msgtab
encode "\x0d\x0dNEW NAME = "
p_msg_idx_new_size equ *-p_msgtab
encode "\x0d\x0dNEW SIZE = "
; fcb $11,$fb,$0d,$9d,$50,$eb,$90,$a9
; fcb $01
; "NEW SIZE = "
p_msg_idx_warning_installing equ *-p_msgtab
encode "\x0dWARNING- INSTALLING PARTITIONS DESTROYS\x0dTHE DIRECTORY- GO AHEAD"
p_msg_idx_cannot_boot equ *-p_msgtab
encode "\x0d\x0dCANNOT BOOT THAT PARTITION\x0dBOOT FROM SLOT = "
; XXX referenced from where?
p_msg_idx_cannot_change_size equ *-p_msgtab
encode "\x0d\x0dCANNOT CHANGE SIZE"
; XXX referenced from where?
p_msg_idx_size_too_large equ *-p_msgtab
encode "\x0d\x0dSIZE TOO LARGE"
p_msg_idx_clear equ *-p_msgtab
encode "CLEAR \x0d"
p_msg_idx_dos equ *-p_msgtab
encode "DOS \x0d"
p_msg_idx_prodos equ *-p_msgtab
encode "PRODOS\x0d"
p_msg_idx_cpm equ *-p_msgtab
encode "CP-M \x0d"
p_msg_idx_pascal equ *-p_msgtab
encode "PASCAL\x0d"
pS0dd7: lda D0901
sta D0802
eor #$5a
sta D0803
jsr pS0de8
jmp Lc9df
; write parition table back to card memory
pS0de8: jsr Sca8b
tay
pL0dec: lda pt_buffer+pte_ofs_base_addr_high,y
sta hw_reg_data-hw_reg_offset,x
iny
bne pL0dec
rts
pL0df6: jsr pS0dd7
jsr pS0e43
bne pL0e09
lda pt_buffer+pte_ofs_size_high,y
ora pt_buffer+pte_ofs_size_mid,y
beq pL0e09
pL0e06: jsr pS0e27
pL0e09: ldy #p_msg_idx_cannot_boot
jsr p_msgout
pL0e0e: ldx #$01
jsr pS0e4f
bcs pL0e36
lda D0908
cmp #$b1
bcc pL0e0e
cmp #$b8
bcs pL0e0e
adc #$10
tay
lda #$00
beq pL0e2f
pS0e27: ldx mslot1088
ldy mslot
lda #$7b
pL0e2f: sty L00+1
sta L00
jmp (L00)
pL0e36: ldx #$02
lda #$00
pL0e3a: sta pt_buffer+pte_ofs_base_addr_high,x
dex
bpl pL0e3a
jmp (resetvec)
pS0e43: ldy D0901
pS0e46: lda pt_buffer+pte_ofs_os_code,y
eor pt_buffer+pte_ofs_os_check,y
cmp #$5a
rts
pS0e4f: stx D0903
lda #$a0
pL0e54: sta D0908,x
dex
bpl pL0e54
inx
pL0e5b: jsr rdkey_uc
cmp #$88
beq pL0e84
cmp #char_cr+$80
beq pL0e82
cmp #char_esc+$80
beq pL0e83
cmp #' '+$80
bcs pL0e74
pL0e6e: jsr bell12
jmp pL0e5b
pL0e74: cpx D0903
bcs pL0e6e
sta D0908,x
jsr cout
inx
bne pL0e5b
pL0e82: clc
pL0e83: rts
pL0e84: txa
beq pL0e5b
dex
dec ch
lda #$a0
sta D0908,x
jsr cout
dec ch
jmp pL0e5b
rdkey_uc:
jsr rdkey
cmp #$e0 ; lower case?
bcc pL0ea0 ; no
and #$df ; yes, convert to upper case
pL0ea0: rts
pS0ea1: lda #$00
tay
tax
pL0ea5: sta D0904
stx D0905
lda #$0a
sta D0902
ldx #$00
lda D0908,y
eor #$b0
cmp #$0a
bcc pL0ebc
rts
pL0ebc: adc D0904
pha
txa
adc D0905
tax
pla
dec D0902
bne pL0ebc
iny
bne pL0ea5
dephase
endsection partmgr
b1_partmgr_end equ *-$1000
fillto $dfff,$ff