; ; HFS boot. Boot block. ; This is stage 0 of the bootloader. It will find a file named ; '!' in the root directory of an HFS volume, load it, and execute it ; in full 16-bit mode, with a = prodos block call vector. ; ; this currently only works with 512-byte blocks (max volume size = 32M) ; but there's enough room to support variable block sizes. include 'hfs.aii' string asis blanks on ; smartport doesn't currently work ($28 no drive error because the unit isn't setup correctly?) __smartport__ set 0 zp record 0 slot ds.w 1 ;vector ds.w 1 offset ds.w 1 bnum ds.w 1 count ds.w 1 extents ds.b 3*HFSExtentDescriptor.sizeof endr if __smartport__ then sp record $20 ReadBlock equ $01 pcount ds.b 1 unit ds.b 1 buffer ds.w 1 block ds.l 1 ; actually 24-bit endr else pro record $42 cmd ds.b 1 unit ds.b 1 buffer ds.b 2 block ds.b 2 endr endif data record $2000 ds.b 512 endr entry read_block, read_block_abs, read_extent_block entry vector boot proc longi off longa off with zp dc.b $01 ; prodos boot id :D if __smartport__ then stx sp.unit else stx pro.unit endif txa lsr a lsr a lsr a lsr a ora #$c0 sta vector+1 sta slot+1 stz slot ; check for prodos block-device signature bytes ; todo -- switch to extended smartport? needed for second stage. ; xx $20 xx $00 xx $03 [xx $00 - smarport ] ldy #1 lda (slot),y cmp #$20 bne noboot ldy #3 lda (slot),y bne noboot ldy #5 lda (slot),y cmp #$03 bne noboot if __smartport__ then ldy #7 lda (slot),y bne noboot ; ,$fb = smartport id byte which indicates if extended. not needed (yet) endif ldy #$ff lda (slot),y if __smartport__ then inc a inc a inc a endif sta vector bra ok ; not a prodos/smartport device. noboot brk $ea ok if __smartport__ then lda #3 sta sp.pcount else lda #1 ; prodos read block sta pro.cmd endif clc xce rep #$30 longi on longa on stz offset stz bnum stz count lda #data if __smartport__ then sta sp.buffer ; stz sp.block ; will overwrite stz sp.block+2 else sta pro.buffer endif lda #2 jsr read_block_abs ; ; assumes 512-byte blocks (max size = 64MB) ; ; wait a minute... max 65535 blocks, therefore high word of allocation block, etc, always 0. ; i assume hfs use 32-bit links in the btree for in-memory use (24-bit or 32 pointers) ; ; search for a file named ! in the root directory. ; ! is ascii char $21 so it should sort early. ; ; with HFSMasterDirectoryBlock lda data+drAlBlSt xba sta offset ldx #3*HFSExtentDescriptor.sizeof-2 @cloop lda data+drCTExtRec,x xba sta extents,x dex dex bpl @cloop endwith ; lda offset ; clc ; adc extents lda extents jsr read_block ; ; block should be a btree header block. find the first leaf node. ; with BTHeaderRec ; lda data+BTNodeDescriptor.sizeof+firstLeafNode ; xba ; sta leaf+2 lda data+BTNodeDescriptor.sizeof+firstLeafNode+2 xba ; sta bnum endwith ; ; assert leaf < # allocated lbocks? ; ;lda leaf ; s/b leaf + cat extent + offset; todo - this offset is in terms of the catalog extent jsr read_extent_block lda data+BTNodeDescriptor.numRecords ; # of records beq advance xba sta count again ldx #512-2 ; last entry @loop lda data,x ; entry offset xba tay lda data+HFSCatalogKey.parentID,y ; parent id bne notfound lda data+HFSCatalogKey.parentID+2,y xba cmp #2 blt @next beq @name bge notfound @name ; name is a p-string. lda data+HFSCatalogKey.nodeName,y cmp #$2101 ; pstr ! beq found bge notfound @next dex dex dec count bne @loop advance ; next block! lda data+BTNodeDescriptor.fLink+2 beq notfound xba jsr read_extent_block bra again notfound brk $ea found ; y = offset in block ; ; only works with contiguous files.... ; first block? ; 8 is magic offset for a key named ! ; assume < 65535 bytes :) with HFSCatalogFile lda data+8+recordType,y and #$00ff cmp #kHFSFileRecord bne notfound lda data+8+dataPhysicalSize+2,y ; xba lsr a ; >>9 since already xba and #%01111111 beq notfound sta count ; todo -- all extents... lda data+8+dataExtents,y xba sta extents lda data+8+dataExtents+2,y xba sta extents+2 ; now load the blocks and lda #$2000 if __smartport__ then sta sp.buffer else sta pro.buffer endif stz bnum @loop lda bnum jsr read_extent_block inc bnum lda #512 clc if __smartport__ then adc sp.buffer sta sp.buffer else adc pro.buffer sta pro.buffer endif dec count bne @loop ldx slot ldy vector if __smartport__ then lda sp.unit else lda pro.unit endif and #$00ff jmp $2000 ; kiss of life. endp read_block proc entry read_block_abs entry vector ; input ; a = hfs block # ; will be adjusted for allocation block offset ; with zp clc adc offset read_block_abs ; ; based on testing, this drops into emulation mode, so do it and recover. ; if __smartport__ then sta sp.block else sta pro.block endif php sec xce dc.b $20 ; jsr vector dc.w $ffff if __smartport__ then dc.b sp.ReadBlock dc.w sp endif bcs @fail xce plp rts @fail brk $ea endp read_extent_block proc ; a = block # ; This doesn't check beyond the 3rd extent with zp,HFSExtentDescriptor @0 cmp extents+0+blockCount bcs @1 ; clc adc extents+0+startBlock bra read_block @1 sbc extents+0+blockCount cmp extents+4+blockCount bcs @2 ; clc adc extents+4+startBlock bra read_block @2 sbc extents+4+blockCount cmp extents+8+blockCount bcs @3 adc extents+8+startBlock bra read_block @3 brk $ea endp end