; ; ; loader ; include 'hfs.aii' include 'macros.aii' string asis blanks on __smartport__ set 0 buffer equ $3000 file_not_found equ $46 dp record 0 _dp ds.w 1 ptr ds.1 1 path ds.l 1 ; readfile eof ds.l 1 ft ds.w 1 at ds.w 1 st ds.w 1 file_id ds.l 1 endr header proc import readfile, getbootname, getfstname, startup entry auxtype jmp startup nop dc.w readfile dc.w getbootname dc.w getfstname dc.w startup-header ; size of permanent code auxtype dc.w 0 endp data record ; store catalog info slot ds.w 0 unit ds.w 0 vector ds.w 0 block_offset ds.w 0 cat_extents ds.w 6 file_extents ds.w 6 cat_root dc.w 0 system_id dc.l 0 fsts_id dc.l 0 driver_id dc.l 0 ; ctree lookup target_parent dc.l 0 target_str_len dc.w 0 target_str ds.b 32 cat_str_len dc.w 0 cat_str ds.b 32 endr getbootname proc ; getbootname(GSString *) with dp tcd ; save pea fakedp pld plx ; rts ply sty ptr ply sty ptr+2 phx pha ; saved d phb phk plb ; get the volume name from the HFS MDB.... lda #buffer sta pro.buffer lda #2 jsr read_block_abs bcs exit with HFSMasterDirectoryBlock lda buffer+drVN and #$ff sta [ptr] inc a lsr a tax ; count ldy #2 @loop lda buffer+drVN-1,y sta [ptr],y iny iny dex bpl @loop clc lda #0 exit plb pld rts endp getfstname proc ; getfstname(GSString *) with dp tcd ; save pea fakedp pld plx ; rts ply sty ptr ply sty ptr+2 phx pha ; save d phb phk plb ldy #10-2 ; 7 + 2 + 1 byte to round up. @loop lda name,y sta [ptr],y dey dey bpl @loop plb pld clc lda #0 rts name dc.w 7 dc.b 'hfs.fst' dc.b 0 endp readfile proc ; (eof, aux type, file type) readfile(GSString *, void *) with dp tcd ; save pea fakedp pld plx ; rts ply sty ptr ; data buffer ply sty ptr+2 ply sty path ; pathname ply sty path+2 phx pha ; save d phb phk plb lda [path] cmp #8 blt notfound ; ... ; stack: b, d, rts, lda ft sta 3+3,s lda at sta 5+3,s lda eof sta 7+3,s lda eof+2 sta 9+3,s lda #0 clc exit plb pld rts endp find_parent proc with dp ; optimism stz offset lda system_id sta parent_id lda [path] cmp #8 blt err ; SYSTEM ? ldx #3 @loop lda [path],y cmp s1,y bne err iny iny dex bne @loop lda [path],y iny sty offset cmp #'D:' beq d cmp #'F:' beq f and #$ff cmp #':' beq s err lda #file_not_found sec rts s clc rts ; check for more ':' ? d ; check for a driver folder. lda [path] cmp #16 blt s ldx #4 @loop lda [path],y cmp s2,y bne s iny iny dex bne @loop ; match! sty offset lda driver_id sta parent_id clc rts f ; check for FSTs folder lda [path] cmp #13 blt s ldx #2 @loop lda [path],y cmp s3,y bne s iny iny dex bne @loop lda [path],y and #$ff cmp #':' bne s iny sty offset lda fsts_id sta parent_id clc rts s1 dc.b 'xxSYSTEM:' s2 dc.b 'xxSYSTEM:DRIVERS:' s3 dc.b 'xxSYSTEM:FSTS:' endp read_block proc entry read_block_abs entry vector ; input ; a = hfs block # ; will be adjusted for allocation block offset ; with dp clc adc data.block_offset read_block_abs ; todo -- need to save/restore dp and stack 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 clc xce plp sec rts endp cat_lookup proc ; search for a file and a parent directory. lda cat_root sta bnum ix ldx #-1 stx prev lda bnum jsr read_cat_block bcc @ok rts ; uhoh @ok lda buffer+BTNodeDescriptor.numRecords beq advance sta count ldx #512-2 ; last entry eloop lda buffer,x ; entry offset xba tay lda data+HFSCatalogKey.parentID,y xba cmp target_parent+2 beq @p2 blt lt bge gt @p2 lda data+HFSCatalogKey.parentID+2,y xba cmp target_parent+2 beq @nm blt lt bge gt @gt ; if this is an index node, ; we overshot, so follow the tree via prev ; to the next level. lda buffer+BTNodeDescriptor.kind-1 bmi nope ; index map lda prev bmi nope sta bnum bra ix ; now do a name check.... ; target_name is UPPER CASE jsr name_check cmp #0 beq @found bmi @lt bra @gt @found ; a match! if this is an index node, ; descend.... lda buffer+BTNodeDescriptor.kind-1 bmi @leaf lda data+38+2,y xba sta bnum bra ix @leaf jmp match ; if this is an index node, keep it for later @lt lda data+38+2,y xba sta prev @next dex dex dec count bne eloop advance lda data+BTNodeDescriptor.fLink beq nope xba sta bnum bra ix nope lda #file_not_found sec rts name_check ; copy into catstr and upper case it. phx phy ; save ; ; we need to handle 0-length strings (folder threads) ; ldx #30 @zloop stz cat_str,x dex dex bpl @zloop stz cat_str_len ldx #0 short m lda data+HFSCatalogKey.nodeName,y sta cat_str_len @loop lda data+HFSCatalogKey.nodeName+1,y sta cat_str,x iny inx cpx cat_str_len blt @loop upper ; now uppercase it ldy #0 ldx cat_str_len dex @loop lda cat_str,y cmp #'z'+1 bge @next cmp #'a' blt @next and #$20 sta cat_str,y @next iny dex bpl @loop cmp ldx target_str_len cpx cat_str_len bge @ok ldx cat_str_len @ok dex ldy #0 @loop lda target_str,y cmp cat_str,y beq @next blt lt bge gt @next iny bpl @loop long m lda #0 bra exit lt long m lda #-1 bra exit gt long m lda #1 exit ply plx match ; a match! ; store the file type, aux type, eof, and extent pointers. ; a match! lda buffer+HFSCatalogKey.keyLength,y and #$ff inc a ; doesn't include itself clc adc buffer,x ; x still valid tay lda buffer+HFSCatalogFile.recordType xba cmp #kHFSFolderRecord beq folder cmp #kHFSFileRecord beq file ; folder thread, file thread.... invalid for us. lda #file_not_found sec rts folder with HFSCatalogFolder stz eof stz eof+2 stz at lda #$f sta ft lda #$0d sta st ; storage type ldx #12-2 @eloop stz file_extents,x dex dex bpl @eloop lda data+folderID+2,y xba sta file_id lda data+folderID,y xba sta file_id+2 lda #0 clc rts endwith file with HFSCatalogFile lda buffer+dataLogicalSize+2,y xba sta eof lda buffer+dataLogicalSize,y xba sta eof+2 lda #1 sta st ; storage type lda buffer+dataExtents+0,y xba stz file_extents+0 lda buffer+dataExtents+2,y xba stz file_extents+2 lda buffer+dataExtents+4,y xba stz file_extents+4 lda buffer+dataExtents+6,y xba stz file_extents+6 lda buffer+dataExtents+8,y xba stz file_extents+8 lda buffer+dataExtents+10,y xba stz file_extents+10 lda data+fileID+2,y xba sta file_id lda data+fileID,y xba sta file_id+2 ; file type aux type logic. ; only support pdos encoding, nothing fancy. ; 'p' filetype aux type pdos ; where filetype = 80bit, aux type = 16 bit big endian stz ft stz at lda data+userInfo+4,y cmp #'dp' bne @noft lda data+userInfo+4+2,y cmp #'so' bne @noft pdos lda data+userInfo,y tax and #$ff cmp #'p' bne @noft txa xba and #$ff sta ft lda data+userInfo+2,y xba sta at @noft lda #0 clc rts endwith endp ; ; everything below here will be clobbered. ; startup proc ; ; load the catalog extents ; lookup :system, :system:driver, :system:fsts, system:system:setup folders to save time later? ; ; ; read :system:start.gsos, load into memory @ $6800 ; aux type is stored in auxtype with dp, data ; assume 16-bit, etc. stx slot sty vector sta unit pea fakedp pld with HFSMasterDirectoryBlock lda #2 jsr read_block_abs ; can't really fail... lda buffer+drAlBlSt xba sta block_offset ldx #3*HFSExtentDescriptor.sizeof-2 @cloop lda buffer+drCTExtRec,x xba sta cat_extents,x dex dex bpl @cloop ; save the volume name while we're at it? endwith ; find the root node. lda cat_extents jsr read_block with BTHeaderRec lda data+BTNodeDescriptor.sizeof+rootNode+2 xba sta cat_root ; ; lookup SYSTEM ; lda #kHFSRootFolderID sta target_parent lda #kHFSRootFolderID>>16 stz target_parent+2 ldx #30 @zloop stz target_str,x dex dex bpl @zloop ldx #14-2 @sloop lda sys,x sta target_str_len,x dex dex bpl @sloop jsr cat_lookup bcs bad ; also check if dir? lda file_id sta system_id sta target_parent lda file_id+2 sta system_id+2 sta target_parent+2 ; lookup System:FSTs ldx #14-2 @floop lda fsts,x sta target_str_len,x dex dex bpl @floop jsr cat_lookup bcs bad ; also check if dir? lda file_id sta fsts_id lda file_id+2 sta fsts_id+2 ; lookup System:Drivers ldx #14-2 @dloop lda drv,x sta target_str_len,x dex dex bpl @dloop jsr cat_lookup bcs bad ; also check if dir? lda file_id sta driver_id lda file_id+2 sta driver_id+2 ; lookup System:Start.GS.OS ldx #14-2 @gloop lda gsos,x sta target_str_len,x dex dex bpl @gloop jsr cat_lookup bcs bad lda at sta auxtype ; lda #$1000 ; drivers:boot.driver support ; ldx #0 ; ldy #0 jmp $6800 sys str.w 'SYSTEM' dcb.b 6,0 fsts str.w 'FSTS' dcb. 8,0 drv str.w 'DRIVERS' dcb.b 5,0 gsos str.w 'START.GS.OS' dcb.b 1,0 endp fakedp proc end end