Files
super6502/sw/bios/boot2.s
2023-08-26 08:10:20 -07:00

314 lines
6.5 KiB
ArmAsm

.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, sreg, data_start
.autoimport on
.export fatbuf
.feature string_escapes
.MACPACK generic
fatbuf = $A000
filebuf = $B000
.zeropage
tbase: .res 2
tlen: .res 2
dbase: .res 2
dlen: .res 2
olen: .res 1
otype: .res 1
userptr: .res 2
.segment "BOOTLOADER"
sectors_per_cluster = $800D
reserved_sectors = $800E
fat_count = $8010
sectors_per_fat = $8024
O65_NO_C65 = $00
O65_MAGIC = $02
O65_VERSION = $05
O65_MODE = $06
O65_TBASE = $08
O65_TLEN = $0a
O65_DBASE = $0c
O65_DLEN = $0e
O65_BBASE = $10
O65_BLEN = $12
O65_ZBASE = $14
O65_ZLEN = $16
O65_STACK = $18
O65_OPT_START = $1A
_start:
lda #<str
ldx #>str
jsr _cputs
; Read root directory entry into fatbuf
lda data_start
ldx data_start + 1
jsr pushax
stz sreg
stz sreg+1
jsr pusheax
lda #<fatbuf
ldx #>fatbuf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda #<fatbuf
ldx #>fatbuf
jsr _SD_printBuf
lda #$20 ; Start at first directory entry (first is a disk label)
sta ptr3
lda #>fatbuf
sta ptr3 + 1
ldy #$0b ; look for attributes
@1: lda (ptr3),y
cmp #$0f ; if attribute is 0xf, this is a lfn
bne @2 ; if not an lfn, then try to read filename
@next: clc ; otherwise, go to the next entry (+0x20)
lda ptr3
adc #$20
sta ptr3
bcc @4
inc ptr3 + 1
@4: lda #<word_str
ldx #>word_str
jsr pushax
lda ptr3
ldx ptr3 + 1
pha
phx
jsr pushax
phy
ldy #$4
jsr _cprintf
ply
plx
stx ptr3 + 1
pla
sta ptr3
bra @1
@2: ldy #11 ; ignore the attributes. Write null to make a string
lda #$00
sta (ptr3),y
lda ptr3 ; store address of the filename string on the stack
pha
ldx ptr3 + 1
phx
jsr _cputs ; print out short filenames as we read them
lda #$0d
jsr _cputc
lda #$0a
jsr _cputc
lda #<kernel_str ; load the string "KERNEL O65"
ldx #>kernel_str
jsr pushax
plx ; then push the string we read earlier
pla
jsr _strcmp
bne @next ; if they are not equal then try next entry
lda #<_good ; print match if we found it
ldx #>_good
jsr _cputs ; otherwise continue on
lda #<word_str
ldx #>word_str
jsr pushax
lda ptr3
pha
lda ptr3 + 1
pha
ldy #$1d ; load file size (256)
lda (ptr3),y
lsr ; divide by 2 to get file size (512)
sta filesiz
jsr pusha0
ldy #$4
jsr _cprintf
pla
sta ptr3 + 1
pla
sta ptr3
ldy #$1b ; load high byte of low first cluster
lda (ptr3),y
tax
dey
lda (ptr3),y ; load low byte of low first cluster
sec
sbc #$02 ; don't handle carry, assume low byte is not 0 or 1
ldx data_start + 1 ; load x as high data start
asl ; multiply cluster num (minus 2) by 8
asl
asl
clc
adc data_start ; add that to low data start
bcc @5 ; handle carry
inx
@5: sta cluster
stx cluster + 1
lda #<filebuf
ldx #>filebuf
sta userptr
stx userptr + 1
@read_sd:
lda cluster
ldx cluster + 1
stz sreg
stz sreg+1
jsr pusheax
lda userptr
ldx userptr + 1
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda userptr
ldx userptr + 1
jsr _SD_printBuf
dec filesiz
bmi @doneload
inc cluster
inc userptr + 1
inc userptr + 1
bra @read_sd
@doneload:
ldy #O65_TBASE
lda filebuf,y
sta tbase
iny
ldx filebuf,y
stx tbase + 1
ldy #O65_TLEN
lda filebuf,y
sta tlen
iny
ldx filebuf,y
stx tlen + 1
ldy #O65_DBASE
lda filebuf,y
sta dbase
iny
ldx filebuf,y
stx dbase + 1
ldy #O65_DLEN
lda filebuf,y
sta dlen
iny
ldx filebuf,y
stx dlen + 1
ldy #O65_OPT_START
phy
@opt_len:
lda #<opt_str
ldx #>opt_str
jsr pushax
ply
lda filebuf,y
beq @opt_end
sta olen
phy
jsr pusha0
ply
iny
lda filebuf,y
sta otype
phy
jsr pusha0
ldy #$6
jsr _cprintf
lda #<word_str
ldx #>word_str
jsr pushax
pla
adc olen
dec
dec
pha
bra @opt_len
@opt_end:
iny ; account for reading size
phy
lda #<opt_done
ldx #>opt_done
jsr pushax
pla
pha
jsr pusha0
ldy #$4
jsr _cprintf
pla
ldx #>filebuf
adc #<filebuf
bcc @6
inx
@6: sta userptr
stx userptr + 1
lda #<word_str
ldx #>word_str
jsr pushax
lda userptr
ldx userptr + 1
jsr pushax
ldy #$4
jsr _cprintf
;void* __fastcall__ memcpy (void* dest, const void* src, size_t count);
lda tbase
ldx tbase + 1
jsr pushax
lda userptr
ldx userptr + 1
jsr pushax
lda tlen
ldx tlen + 1
jsr _memcpy
lda #<$1000
ldx #>$1000
jsr _SD_printBuf
@end: bra @end
filesiz: .res 1
cluster: .res 2
str: .asciiz "boot2\r\n"
kernel_str: .asciiz "KERNEL O65"
_good: .asciiz "Found KERNEL\r\n"
word_str: .asciiz "Word Value: %x\r\n"
opt_str: .asciiz "Opt Len: %x, Opt Type: %x\r\n"
opt_done: .asciiz "Options done. total option length: %x\r\n"