a2-rana-elite/rana-31.asm

560 lines
8.6 KiB
NASM

; Reverse-engineered firmware of Rana Elite floppy disk
; controller for Apple II.
; Assembly source code copyright 2014, 2016 Eric Smith <spacewar@gmail.com>
; The author of this assembly source code does not claim copyright on the
; executable object code as found in the EPROM chip of the Rana Elite
; floppy disk controller.
; 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
Z00 equ $00
bufptr equ $26
denib_counter equ $2a
slot16 equ $2b
temp equ $3c
sector equ $3d
Z40 equ $40
Z41 equ $41
D0100 equ $0100
D02d6 equ $02d6
D0300 equ $0300
L0301 equ $0301
D0356 equ $0356
tramp_0801 equ $0376 ; trampoline for 16-sector boot
D0399 equ $0399
D03c6 equ $03c6
D03c7 equ $03c7
D03cc equ $03cc
D03ce equ $03ce
D0800 equ $0800 ; 16-sector boot: additional sector count
L0801 equ $0801 ; 16-sector boot: jump address
tramp_0301 equ $08e0 ; trampoline for 13-sector boot
D08e3 equ $08e3
D08e6 equ $08e6
D08e7 equ $08e7
; Woz controller addresses (index by slot * 16)
phoff equ $c080 ; phase off
phon equ $c081 ; phase on
mtroff equ $c088 ; motor off
mtron equ $c089 ; motor on
drv0en equ $c08a ; drive 0 enable
drv1en equ $c08b ; drive 1 enable
q6l equ $c08c ; set Q6 low
q6h equ $c08d ; set Q6 high
q7l equ $c08e ; set Q7 low
q7h equ $c08f ; set Q7 high
seld12 equ $c800 ; write to select drive bank for drives 1 and 2
seld34 equ $c801 ; write to select drive bank for drives 3 and 4
romoff equ $cfff ; access to turn off shared ROM
monwait equ $fca8 ; monitor wait subroutine
org $c800
fillto $cc00
Lcc00: jmp Lcde2
; build 13-sector denibblization table - D0800[nib] = 5-bit data
; starting with ($08ff) = $1f, and descending to ($08ab) = $00
; duplicates code in Apple 13-sector boot ROM stating at Cx00
Lcc03: ldx #$20
ldy #$00
Lcc07: lda #$03
sta temp
clc
dey
tya
Lcc0e: bit temp
beq Lcc07
rol temp
bcc Lcc0e
cpy #$d5 ; skip $d5, used for marks
beq Lcc07
dex ; Y is a valid nibble, set table[Y] to index
txa
sta D0800,y
bne Lcc07
; Copy two instruction trampoline (six bytes) from tramp_0301_rom to tramp_0301.
Lcc21: ldy #tramp_0301_len-1
Lcc23: lda tramp_0301_rom,y
sta tramp_0301,y
dey
bpl Lcc23
lda #$40
sta D08e6
lda #$03
sta bufptr+1
lda #$ff
sta D0300
sta D08e7
ldx slot16
Lcc3f: ldy D08e6
iny
beq read_sector_13
dec D08e6
beq Lcc00
read_sector_13:
clc ; flag clear, look for address mark
read_something_13:
php ; save flag
; read first byte of mark
Lcc4c: lda q6l,x ; read disk
bpl Lcc4c
Lcc51: eor #$d5 ; first byte of mark?
bne Lcc4c ; no
; read second byte of mark
Lcc55: lda q6l,x
bpl Lcc55
cmp #$aa
bne Lcc51
nop
; read third byte of mark
Lcc5f: lda q6l,x
bpl Lcc5f
cmp #$b5 ; address mark?
beq found_address_mark_13
plp ; retrieve flag - looking for address mark?
bcc Lcc3f ; yes, try again
; check for a data mark
eor #$ad
beq found_data_mark_13
bne Lcc3f
found_address_mark_13:
ldy #$03 ; read volume, track, sector
; volume and track ignored, presumed OK
; checksum not read
Lcc73: lda q6l,x
bpl Lcc73
rol ; save upper slice
sta temp
Lcc7b: lda q6l,x
bpl Lcc7b
and temp ; merge slices
dey ; 3rd byte yet?
bne Lcc73 ; no, get another
plp ; throw away flag
cmp sector ; correct sector?
bne Lcc3f ; no, get another
bcs read_something_13 ; yes. carry is set, go back and look for data mark
found_data_mark_13:
; read 154 nibbles, denibblize with running xor,
; and store from $0899 down to $0800
ldy #$9a
Lcc8e: sty temp
Lcc90: ldy q6l,x
bpl Lcc90
eor D0800,y
ldy temp
dey
sta D0800,y
bne Lcc8e
; Y now zero
; read 256 nibbles, denibblize with running xor,
; and store in buffer in ascending order
Lcca0: sty temp
Lcca2: ldy q6l,x
bpl Lcca2
eor D0800,y
ldy temp
sta (bufptr),y
iny
bne Lcca0
; read checksum nibble, xor, and verify zero
Lccb1: ldy q6l,x
bpl Lccb1
eor D0800,y
bne Lcc3f ; checksum fail?
lda D08e7
beq Lcced
lda #$03
sta denib_counter
; special 13-sector boot sector denibblize, equivalent to
; 13-sector boot ROM code at $cnd1
ldy #$00
Lccc6: ldx #$00
Lccc8: lda D0800,y
lsr
rol D03cc,x
lsr
rol D0399,x
sta temp
lda (bufptr),y ; merge in the extra bits
asl
asl
asl
ora temp
sta (bufptr),y
iny
inx
cpx #$33
bne Lccc8
dec denib_counter
bne Lccc6
cpy D0300
bne Lccf0
Lcced: jmp tramp_0301 ; jump via trampoline to $0301
Lccf0: jmp Lcde2
; The following two instruction trampoline (six bytes) is copied to tramp_0301
; by loop at Lcc21.
tramp_0301_rom:
bit romoff ; turn off shared ROM
jmp L0301 ; jump into 13-sector stage 2 boot
tramp_0301_len equ *-tramp_0301_rom
fillto $cd00
Scd00: jsr Scd4e
ldx slot16
lda #$40
sta D03ce
lda #$00
sta bufptr
sta sector
sta Z41
lda #$08
sta bufptr+1
rts
Scd17: tsx
inx
inx
lda D0100,x
asl
asl
asl
asl
sta slot16
tax
sta seld12 ; select drive bank for drives 1 and 2
lda q7l,x ; set up to read drive
lda q6l,x
lda drv0en,x
lda mtron,x
jsr Scd00
; move to track 0 (assume worst case
; initial position of track 40)
ldy #80 ; 80 half tracks
Lcd38: lda phoff,x ; stepper motor phase off
tya ; compute next phase
and #$03 ; yields 3,2,1,0
asl ; yields 6,4,2,0
ora slot16 ; merge with slot*16
tax
lda phon,x ; stepper motoro phase on
lda #$56 ; wait (13 sector boot rom had $86)
jsr monwait
dey
bpl Lcd38
rts
; generate 16-sector post-nybble conversion table
; From 16-sector boot ROM, c602..??
; See 16-sector ROM disassembly in Apple Assembly Line V1N11, August 1981
Scd4e: ldx #$03
ldy #$00
Lcd52: stx temp
txa
asl
bit temp
beq Lcd6a
ora temp
eor #$ff
and #$7e
Lcd60: bcs Lcd6a
lsr
bne Lcd60
tya
sta D0356,x
iny
Lcd6a: inx
bpl Lcd52
; Copy two instruction trampoline (six bytes) from tramp_0801_rom to tramp_0801.
Lcd6d: ldy #tramp_0801_len-1
Lcd6f: lda tramp_0801_rom,y
sta tramp_0801,y
dey
bpl Lcd6f
lda #$40
sta D03ce
Scd7d: ldy #$55
lda #$00
Lcd81: sta D0300,y
dey
bpl Lcd81
rts
Lcd88: bcs Lcda1
lda #$ff
sta D03ce
lda #Lc64c & $ff
Lcd91: sta D03c6
txa
lsr
lsr
lsr
lsr
ora #$c0
sta D03c7
jmp (D03c6)
Lcda1: jmp tramp_0801
; The following two instruction trampoline (six bytes) is copied to tramp_0801
; by loop at Lcd6d.
tramp_0801_rom:
bit romoff ; turn off shared ROM
jmp L0801 ; jump into 16-sector stage 2 boot
tramp_0801_len equ *-tramp_0801_rom
Scdaa: lda #$00
ldy #$55
Lcdae: ora D0300,y
dey
bpl Lcdae
and #$f0
bne Lcdbe
lda #$ff
sta D03ce
rts
Lcdbe: pla
pla
pla
ldy #$60
sty D08e3
ldy #$00
sty D08e7
dey
sty D08e6
jmp read_sector_13
Scdd2: ldy D03ce
iny
beq Lcddd
dec D03ce
beq Lcddf
Lcddd: clc
rts
Lcddf: jmp Lcc03
Lcde2: jsr Scd00
lda #$25
bne Lcd91
fillto $cec2
fcb "COPYR. 1982 RANA SYSTEMS - KSB"
fcstrm "COPYR. 1982 RANA SYSTEMS - KSB"
fcb $01,$03
org $cf00
phase $c600
Pc600: ldx #$20
ldy #$00
ldx #$03
ldx #$3c
bit romoff
jsr Scd17
bne Lc625
Lc610: bit romoff
jsr Scdaa
bne Lc627
Lc618: jsr Scdd2
bcc Lc625
fcb $00,$00,$00,$00,$00
Lc622: jsr Scd7d
Lc625: clc
Lc626: php
Lc627: lda q6l,x
bpl Lc627
Lc62c: eor #$d5 ; first byte of mark
bne Lc627
Lc630: lda q6l,x
bpl Lc630
cmp #$aa ; second byte of mark
bne Lc62c
nop
Lc63a: lda q6l,x
bpl Lc63a
cmp #$96 ; third byte of address mark (16-sector)
beq Lc683
plp
bcc Lc618
eor #$ad ; third byte of data mark
beq Lc6a6
bne Lc618
Lc64c: ldy D03ce
iny
beq Lc622
dec D03ce
bne Lc622
jmp Lcddf
; DOS 3.3 boot reenters the PROM via jmp to $Cn5C
; DOS 3.2.1 boot reenters the PROM via jsr (effectively) to $Cn5D
fillto $c65c
Pc65c: clc
Pc65d: php
sec
bcs Lc610
bpl Lc627
Lc663: eor #$d5 ; first byte of mark
bne Lc627
Lc667: lda q6l,x
bpl Lc667
cmp #$aa ; second byte of mark
bne Lc663
nop
Lc671: lda q6l,x
bpl Lc671
cmp #$96 ; third byte of address mark
beq Lc683
plp
bcc Lc618
eor #$ad ; third byte of data mark
beq Lc6a6
Lc681: bne Lc618
Lc683: ldy #$03
Lc685: sta Z40
Lc687: lda q6l,x
bpl Lc687
rol
sta temp
Lc68f: lda q6l,x
bpl Lc68f
and temp
dey
bne Lc685
plp
cmp sector
bne Lc681
lda Z40
cmp Z41
Lc6a2: bne Lc64c
bcs Lc626
Lc6a6: ldy #$56
Lc6a8: sty temp
Lc6aa: ldy q6l,x
bpl Lc6aa
eor D02d6,y
ldy temp
dey
sta D0300,y
bne Lc6a8
Lc6ba: sty temp
Lc6bc: ldy q6l,x
bpl Lc6bc
eor D02d6,y
ldy temp
sta (bufptr),y
iny
bne Lc6ba
Lc6cb: ldy q6l,x
bpl Lc6cb
eor D02d6,y
bne Lc6a2
ldy #$00
Lc6d7: ldx #$56
Lc6d9: dex
bmi Lc6d7
lda (bufptr),y
lsr D0300,x
rol
lsr D0300,x
rol
sta (bufptr),y
iny
bne Lc6d9
inc bufptr+1
inc sector
lda sector
cmp D0800
ldx slot16
nop
nop
bit romoff
jmp Lcd88
fillto $c700
dephase