.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 .bss tbase: .res 2 tlen: .res 2 dbase: .res 2 dlen: .res 2 olen: .res 1 otype: .res 1 filesiz: .res 1 cluster: .res 2 .zeropage 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 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 jsr pushax lda #ptr1 jsr _SD_readSingleBlock ; lda #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 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 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 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 clc sta tmp1 ldx data_start + 1 ; load x as high data start phx ldx sectors_per_cluster ; multiply cluster num (minus 2) by sectors_per_cluster lda #$00 @8: adc tmp1 dex bne @8 plx clc adc data_start ; add that to low data start bcc @5 ; handle carry inx @5: sta cluster stx cluster + 1 lda #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 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 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 jsr pushax pla clc adc olen dec pha bra @opt_len @opt_end: iny ; account for reading size phy lda #opt_done jsr pushax pla pha jsr pusha0 ldy #$4 jsr _cprintf clc pla ldx #>filebuf adc #word_str jsr pushax lda userptr ldx userptr + 1 jsr pushax ldy #$4 jsr _cprintf 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 clc lda userptr + 1 adc tlen + 1 tax lda userptr adc tlen bcc @7 inx @7: sta userptr stx userptr + 1 lda #word_str jsr pushax lda userptr ldx userptr + 1 jsr pushax ldy #$4 jsr _cprintf lda dbase ldx dbase + 1 jsr pushax lda userptr ldx userptr + 1 jsr pushax lda dlen ldx dlen + 1 jsr _memcpy jmp $1000 @end: bra @end str: .asciiz "boot2\n" kernel_str: .asciiz "KERNEL O65" _good: .asciiz "Found KERNEL\n" word_str: .asciiz "Word Value: %x\n" opt_str: .asciiz "Opt Len: %x, Opt Type: %x\n" opt_done: .asciiz "Options done. total option length: %x\n"