NEW AUTO 3,1 *-------------------------------------- * 'detree' deallocates blocks from tree files. it is assumed that the device has * been pre-selected and the 'gbuf' may be used. * * on entry: * stortype = storage type in upper nibble, lower nibble is undisturbed. * firstbl & firstbh = first block of file (index or data). * deblock = 0 * dtree = ptr to 1st block with data to be deallocated at tree level. * dsap = ptr to 1st block at sapling level. * dseed = byte (0-511) position to be zeroed from (inclusive). * * on exit: * stortype = modified result of storage type (if applicable). * firstbl & h = modified if storage type changed. * deblock = total number of blocks freed at all levels. * dtree, dsap, deseed unchanged. * * to trim a tree to a seed file, both dtree and dsap must be zero. * to go from tree to sapling, dtree alone must be zero. *-------------------------------------- detree lda stortyp which kind of tree ? cmp #$20 is it a 'seed' ? bcc L4C46 if yes. cmp #$30 a sapling ? bcc L4C51 if yes. cmp #$40 is it at least a 'tree' ? bcc L4C59 branch if it is. lda #$0C block allocation error. jsr GP.SysDeath P8 system death vector * seedling file type - make sure first desirable block is the only * block available in a seedling file. L4C46 lda dsap ora dtree bne L4CC2 jmp seedel0 * sapling file type - make sure first desirable block is within the range of * blocks available in a sapling file L4C51 lda dtree can't have any blocks in this range bne L4CC2 if so then done jmp sapdel0 else go deallocate L4C59 lda #$80 sta topdest for tree top start at end, work backwards. L4C5E jsr drdfrst read specified first block into gbuf. bcs L4CC2 return errors. ldy topdest get current pointer to top indexes. cpy dtree have enough sapling indexes been beq L4CC3 deallocated? yes, now deallocate blocks ldx #$07 buffer up to 8 sapling index block L4C6D lda gbuf,y addresses. fetch low block address sta dealbufl,x and save it. ora gbuf+$100,y is it a real block that is allocated? beq L4C81 branch if phantom block. lda gbuf+$100,y fetch high block address sta dealbufh,x and save it. dex decrement and test for dealc buf filled. bmi L4C93 branch if 8 addresses fetched. L4C81 dey look for end of deallocation limit. cpy dtree is this the last position on tree level? bne L4C6D if not. iny L4C8A stz dealbufl,x fill rest of dealc buffer with null addresses. stz dealbufh,x dex bpl L4C8A L4C93 dey decrement to prepare for next time. sty topdest save index. ldx #$07 L4C99 stx dtmpx save index to dealc buf. lda dealbufl,x sta bloknml ora dealbufh,x finished ? beq L4C5E branch if done with this level. lda dealbufh,x complete address with high byte, sta bloknml+1 jsr XDOS.ReadGBuf read sapling level into gbuf. bcs L4CC2 return errors. jsr dealblk go free all data indexes in this block bcs L4CC2 jsr XDOS.WriteGBuf write the flipped index block bcs L4CC2 ldx dtmpx restore index to dealc buff. dex are there more to free? bpl L4C99 branch if so. bmi L4C5E branch always to get up to 8 more L4CC2 rts sapling block numbers. L4CC3 ldy dtree deallocate all sapling blocks greater iny than specified block. jsr dalblk1 (master index in gbuf) bcs L4CC2 if errors. jsr XDOS.WriteGBuf write updated master index back to disk. bcs L4CC2 ldy dtree figure out if tree can become sapling. beq L4CEB branch if it can. lda gbuf,y otherwise, continue with partial, deallocation of last sapling index. ora gbuf+$100,y is there such a sapling index block ? beq L4CC2 all done if not. lda gbuf,y ldx gbuf+$100,y read in sapling level to be modified. jsr XDOS.ReadGBufAX read highest sapling index into gbuf. bcc L4CF5 rts L4CEB jsr shrink shrink tree to sapling bcs L4CC2 sapdel0 jsr drdfrst read specified sapling level index bcs L4CC2 into gbuf. branch if error. L4CF5 ldy dsap pointer to last of desirable indexes. iny inc to 1st undesirable. beq L4D05 branch if all are desirable. jsr dalblk1 deallocate all indexes above specified. bcs L4CC2 jsr XDOS.WriteGBuf write out the index block bcs L4CC2 L4D05 ldy dsap prepare to clean up last data block. beq L4D1F branch if possibility of making a seed. L4D0A lda gbuf,y fetch low order data block address. ora gbuf+$100,y is it a real block ? beq L4CC2 if not, then done. lda gbuf,y ldx gbuf+$100,y jsr XDOS.ReadGBufAX go read data block into gbuf. bcc L4D2E branch if good read L4D1E rts or return error. L4D1F lda dtree are both tree and sap levels zero ? bne L4D0A if not. jsr shrink reduce this sap to a seed. bcs L4D1E if error. seedel0 jsr drdfrst go read data block. bcs L4D1E if error. L4D2E ldy dseed+1 check high byte for no deletion. beq L4D39 branch if all of 2nd page to be deleted. dey if dseed > $200 then all were done. bne L4D1E branch if that is the case. ldy dseed clear only bytes >= dseed. L4D39 lda #$00 L4D3B sta gbuf+$100,y zero out unwanted data iny bne L4D3B ldy dseed+1 is that all ? bne L4D4F yes. ldy dseed L4D49 sta gbuf,y iny bne L4D49 L4D4F jmp XDOS.WriteGBuf update data block to disk. L4D52 rts return error status. drdfrst lda firstbl read specified 1st block into gbuf ldx firstbh jmp XDOS.ReadGBufAX go read it * beware that dealloc may bring in a new bitmap block and may destroy * locations 46 and 47 which are used to point to the current index block. shrink ldx firstbh first deallocate top index block phx lda firstbl pha save block address of this index block. jsr XDOS.DeallocAX free it from the bitmap pla sta bloknml set master of sapling pla index block address. sta bloknml+1 bcs L4D1E report errors. lda gbuf get # of new 1st block from old index. sta firstbl lda gbuf+$100 sta firstbh ldy #$00 jsr swapme flip that one entry in old top index. sec now change file type, lda stortyp from tree to sapling, sbc #$10 or from sapling to seed. sta stortyp jmp XDOS.WriteGBuf write the (deallocated) old top index. dealblk ldy #$00 start at beginning. dalblk1 lda bloknml save disk address of gbuf's data. pha lda bloknml+1 pha L4D96 sty saptr save current index. lda gbuf,y get low address of block to deallocate. cmp #$01 test for null block into carry. ldx gbuf+$100,y get remainder of block address. bne L4DA5 branch if not null. bcc L4DB0 was the low part null too ? L4DA5 jsr XDOS.DeallocAX free it up on volume bitmap. bcs L4DB4 return any error. ldy saptr get index to sapling level index block. jsr swapme L4DB0 iny next block address. bne L4D96 if more to deallocate or test. clc no error. L4DB4 tax save error code, if any. pla restore blocknm (16 bit) sta bloknml+1 pla sta bloknml txa restore return code rts swapme lda delflag swapping or zeroing ? bne L4DC5 skip if swapping. tax make x = 0. beq L4DCB zero the index (always taken). L4DC5 ldx gbuf+$100,y index high lda gbuf,y index low L4DCB sta gbuf+$100,y save index high txa sta gbuf,y save index low rts done. *-------------------------------------- * MEMMGR memory manager * * allocate buffer in memory tables *-------------------------------------- alcbuffr ldy #$04 index to user specified buffer. alcbufr1 lda (A3L),y this buffer must be on a page boundary. tax save for validation. cmp #$08 bcc L4E1E cannot be lower than video ! cmp #$BC nor greater than $BB00 bcs L4E1E since it would wipe out globals... sta datptr+1 dey lda (A3L),y low address should be zero ! sta datptr bne L4E1E error if not page boundary. inx add 4 pages for 1k buffer. inx inx inx L4DED dex test for conflicts. jsr cmembit test for free buffer space and MEMTABL,y P8 memory bitmap bne L4E1E report memory conflict, if any. cpx datptr+1 test all 4 pages. bne L4DED inx add 4 pages again for allocation. inx inx inx L4DFE dex set proper bits to 1 jsr cmembit ora MEMTABL,y to mark it's allocation. sta MEMTABL,y cpx datptr+1 set all 4 pages bne L4DFE ldy fcbptr calculate buffer number lda FCBs,y asl buffer number = (entnum) * 2. sta FCBs+FCB.BUFID,y save it in fcb. tax use entnum * 2 as index to global lda datptr+1 buffer addr tables. get addr already sta buftbl-1,x validated as good. store hi addr clc (entnums start at 1, not 0) rts L4E1E lda #MLI.E.BADBUF buffer is in use or not legal sec rts *-------------------------------------- relbuffr tax index into global buffer table. lda buftbl-2,x sta bufaddrl lda buftbl-1,x sta bufaddrh beq relbuffr.8 branch if unallocated buffer space. stz buftbl-1,x take address out of buffer list. stz buftbl-2,x (x was set up by getbufadr) freebuf ldx bufaddrh get hi buffer address inx add 4 pages to account for 1k space. inx inx inx .1 dex drop to next lower page. jsr cmembit get bit and position to memtable of eor #$FF this page. invert mask. and MEMTABL,y mark address as free space. sta MEMTABL,y cpx bufaddrh all pages freed ? bne .1 no. relbuffr.8 clc no error. rts *-------------------------------------- * calculate memory allocation bit position. * on entry: x = high address of buffer, low address assumed zero. * on exit: acc = allocation bit mask, x = unchanged, y = pointer to memtabl byte *-------------------------------------- cmembit txa page address and #$07 which page in any 2k set ? tay use as index to determine lda whichbit,y bit position representation. pha save bit position mask for now. txa page address. lsr lsr determine 2k set lsr tay return it in y. pla restore bit mask. return bit position rts in a & y, pointer to memtabl in x. *-------------------------------------- valdbuf lda usrbuf+1 high address of user's buffer cmp #$02 must be greater than page 2. bcc L4E1E report bad buffer ldx cbytes+1 lda cbytes get cbytes-1 value. sbc #$01 (carry is set) bcs L4E76 dex L4E76 clc adc usrbuf calculate end of request address. txa do high address. adc usrbuf+1 the final address tax must be less than $BFnn (globals) cpx #$BF bcs L4E1E report bad buffer. inx loop thru all affected pages. vldbuf1 dex check next lower page. jsr cmembit and MEMTABL,y if 0 then no conflict. bne L4E1E branch if conflict. cpx usrbuf+1 was that the last (lowest) page ? bne vldbuf1 if not. clc all pages ok. rts *-------------------------------------- XDOS.GetBuf ldy #$02 give user address of file buffer referenced by refnum. lda bufaddrl sta (A3L),y iny lda bufaddrh sta (A3L),y clc no errors possible rts *-------------------------------------- XDOS.SetBuf ldy #$03 jsr alcbufr1 allocate new buffer address over old one bcs L4EC7 report any errors immediately lda bufaddrh sta usrbuf+1 lda bufaddrl sta usrbuf jsr freebuf free address space of old buffer ldy #$00 ldx #$03 .1 lda (usrbuf),y move all 4 pages of the buffer to sta (datptr),y new location. iny bne .1 inc datptr+1 inc usrbuf+1 dex bpl .1 XDOS.SetBuf.CLCRTS clc no errors L4EC7 rts *-------------------------------------- XDOS.IsValidChar cmp #'0' bcc XDOS.IsValidFirstChar cmp #'9'+1 bcc XDOS.IsValidFirstChar.RTS XDOS.IsValidFirstChar .DO ENHFILENAME=1 cmp #'.' beq XDOS.SetBuf.CLCRTS cmp #'_' beq XDOS.SetBuf.CLCRTS .FIN cmp #'A' bcc XDOS.IsValidFirstChar.SEC cmp #'Z'+1 .DO LOWERCASE=1 bcc XDOS.IsValidFirstChar.RTS cmp #'a' bcc XDOS.IsValidFirstChar.SEC cmp #'z'+1 .FIN XDOS.IsValidFirstChar.RTS rts XDOS.IsValidFirstChar.SEC sec rts *-------------------------------------- * move 3 pages of dispatcher from 'displc2' to 'dispadr' * this move routine must be resident above $E000 at all times *-------------------------------------- calldisp lda RRAMWRAMBNK2 read/write RAM bank 2 lda RRAMWRAMBNK2 stz A1L lda #$D1 sta A1L+1 stz A2L lda #$10 sta A2L+1 ldy #$00 ldx #$03 3 pages to move. .1 lda (A1L),y sta (A2L),y iny bne .1 inc A1L+1 pointers to next page inc A2L+1 dex move all pages needed bne .1 lda RRAMWRAMBNK1 read/write RAM bank 1 lda RRAMWRAMBNK1 swap mli space back in stz mliact MLI active flag stz softev lda #$10 point RESET to dispatch entry sta softev+1 eor #$A5 sta pwredup power up byte jmp $1000 *-------------------------------------- XDOS.SPREMAP ldx #$03 assume 3 parameters. lda A4L command number sta cmdnum bne .1 taken if not status call ldy #XDOS.SPStatus set up memory for the status list buffer sty buf fake up the prodos parameters ldy /XDOS.SPStatus sty buf+1 stz bloknml set statcode = 0 for simple status call .1 cmp #$03 format command ? bne .2 no. ldx #$01 format has only 1 parameter. .2 stx XDOS.SPParams set # of parms. lda unitnum DSSS0000 lsr turn unit number into an index lsr lsr lsr tax range = 1-15 lda XDOS.SPUnit-1,x get the smartport unit number and sta XDOS.SPParams.U store into smartport parm list. lda XDOS.SPVectLo-1,x sta sp_vector+1 copy smartport entry address lda XDOS.SPVectHi-1,x sta sp_vector+2 ldx #$04 copy buffer pointer and block # .3 lda buf-1,x from prodos parameters sta XDOS.SPParams.B-1,x to smartport parameter block dex bne .3 sp_vector jsr $0000 smartport call (entry address gets modified) cmdnum .HS 00 command # .DA XDOS.SPParams bcs .9 ldx cmdnum status call ? bne .9 no... ldx XDOS.SPStatus+1 else get the block count ldy XDOS.SPStatus+2 lda XDOS.SPStatus get the returned status. bit #$10 is there a disk present ? beq .8 and #$44 mask all but write allowed and write eor #$40 protected bits. if allowed and not * clc beq .9 protected, exit with carry clear lda #MLI.E.WRTPROT else return write protected error. .HS 2C BIT ABS .8 lda #MLI.E.OFFLINE return offline error. sec .9 rts *-------------------------------------- XDOS.SPParams .HS 03 # of parms (always 3 except format) XDOS.SPParams.U .HS 00 unit number XDOS.SPParams.B .HS 0000 data buffer .HS 000000 block number (3 bytes) *-------------------------------------- XDOS.TBX jmp (.1,x) .1 .DA XDOS.TBX.MemReset .DA XDOS.TBX.EnumBlk .DA XDOS.TBX.EnumNext *-------------------------------------- XDOS.TBX.MemReset ldx #$17 .1 stz MEMTABL,x P8 memory bitmap dex bne .1 inc MEMTABL+$17 protect global page lda #$CF protect zero page, stack and page 1 sta MEMTABL rts *-------------------------------------- XDOS.TBX.EnumBlk jsr XDOS.ZPT.InitA ldx h_maxent lda (zpt) cmp #$E0 bcc .2 ldy #$1F+3 ldx #3 .1 lda (zpt),y sta h_entln,x dey dex bpl .1 jsr XDOS.ZPT.Next skip header ldx h_maxent dex skip header .2 stx cntent XDOS.TBX.CheckFCnt lda h_fcnt ora h_fcnt+1 beq XDOS.TBX.SECRTS * clc rts *-------------------------------------- XDOS.TBX.EnumNext sty sos sta sos+1 jsr XDOS.TBX.CheckFCnt bcs .9 .1 dec cntent bmi XDOS.TBX.SECRTS lda (zpt) and #$0F beq .7 sta (sos) pha jsr XDOS.ZPT.Unpack ply .2 lda (zpt),y sta (sos),y dey bne .2 ldy #16 FileType lda (zpt),y pha jsr XDOS.ZPT.Next lda h_fcnt+1 bne .3 dec h_fcnt+1 .3 dec h_fcnt pla * clc .9 rts .7 jsr XDOS.ZPT.Next bra .1 *-------------------------------------- XDOS.TBX.SECRTS sec rts *-------------------------------------- XDOS.ZPT.InitGBuf lda /gbuf XDOS.ZPT.InitA sta zpt+1 lda #4 sta zpt rts *-------------------------------------- XDOS.ZPT.Unpack ldy #$1D MIN_VERSION lda (zpt),y bpl .6 no lowercase information lda (zpt) and #$0F beq .6 length=0 tay .2 cpy #8 CS if MIN_VERSION to use phy bcs .3 ldy #$1D MIN_VERSION lda (zpt),y ply and whichbit,y beq .5 bra .4 .3 ldy #$1C VERSION lda (zpt),y ply and whichbit-8,y beq .5 .4 lda (zpt),y eor #$20 to lowercase sta (zpt),y .5 dey bne .2 .6 rts *-------------------------------------- XDOS.ZPT.Next lda h_entln XDOS.ZPT.NextA clc adc zpt sta zpt bcc .8 inc zpt+1 clc .8 rts *-------------------------------------- * data tables *-------------------------------------- XDOS.CmdNums .HS D3D4D5D6 table of valid mli command numbers. .HS 40410000 .HS 808182 .HS 65 .HS C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF .HS 00 .HS D0D1D2 XDOS.ParamCnt .HS 02020202 parameter counts for the calls .HS 0201FFFF .HS 030300 .HS 04 .HS 070102070A0201010303040401010202 .HS FF .HS 020202 XDOS.CmdFlags .HS A0A1A2 .HS A384 .HS 050607 .HS 88494A4B .HS 2C2D .HS 4E4F .HS 50515253 .HS 94959697 cmdtable .DA XDOS.Create .DA XDOS.Destroy .DA XDOS.Rename .DA XDOS.SetFileInfo .DA XDOS.GetFileInfo .DA XDOS.Online .DA XDOS.SetPrefix .DA XDOS.GetPrefix .DA XDOS.Open .DA XDOS.NewLine .DA XDOS.Read .DA XDOS.Write .DA XDOS.Close .DA XDOS.Flush .DA XDOS.SetMark .DA XDOS.GetMark .DA XDOS.SetEOF .DA XDOS.GetEOF .DA XDOS.SetBuf .DA XDOS.GetBuf .DA XDOS.SetFileInfoEx .DA XDOS.GetFileInfoEx .DA XDOS.ACL dinctbl .HS 0100000200 table to increment directory usage/eof counts .DO LOWERCASE=1 XDOS.VolHdrDef .HS C3270D XDOS.VolHdrDef.Cnt .EQ *-XDOS.VolHdrDef .ELSE pass .HS 75 xdosver .HS 00 compat .HS 00 .HS C3270D000000 .FIN rootstuf .HS 0F02000400000800 whichbit .HS 8040201008040201 ofcbtbl .HS 0C0D1819151617 inftabl .HS 1E101F2080939421 .HS 22232418191A1B deathmsg .AS -"SYS ERR-$0" deathmsg.LEN .EQ *-deathmsg *-------------------------------------- XDOS.DATA .DUMMY *-------------------------------------- own_blk .HS 0000 own_ent .HS 00 own_len .HS 00 *-------------------------------------- .DO ACL=1 h_acl .BS 8 .FIN h_credt .HS 0000 directory creation date .HS 0000 directory creation time .HS 00 version under which this dir created .HS 00 earliest version that it's compatible h_attr .HS 00 attributes (protect bit, etc.) h_entln .HS 00 length of each entry in this directory h_maxent .HS 00 maximum number of entries per block h_fcnt .HS 0000 current # of files in this directory h_bmap .HS 0000 address of first allocation bitmap h_tblk .HS 0000 total number of blocks on this unit *-------------------------------------- d_dev .HS 00 device number of this directory entry d_head .HS 0000 address of directory header d_entblk .HS 0000 address of block which contains entry d_entnum .HS 00 entry number within block d_stor .BS 16 file name d_filid .HS 00 user's identification byte d_frst .HS 0000 first block of file d_usage .HS 0000 # of blocks allocated to this file d_eof .HS 000000 current end of file marker d_credt .HS 0000 file creation date .HS 0000 file creation time d_sosver .HS 00 sos version that created this file d_comp .HS 00 backward version compatibility d_attr .HS 00 attributes (protect, r/w, enable, etc.) d_auxid .HS 0000 user auxilliary identification d_moddt .HS 0000 file's last modification date .HS 0000 file's last modification time d_dhdr .HS 0000 file directory header block address *-------------------------------------- scrtch .HS 00000000 scratch area for allocation address conversion. oldeof .HS 000000 temp used in r/w oldmark .HS 000000 xvcbptr .HS 00 used in 'cmpvcb' as a temp vcbptr .HS 00 fcbptr .HS 00 fcbflg .HS 00 reql .HS 00 reqh .HS 00 levels .HS 00 totent .HS 00 entcntl .HS 00 entcnth .HS 00 cntent .HS 00 nofree .HS 00 bmcnt .HS 00 saptr .HS 00 pathcnt .HS 00 p_dev .HS 00 p_blok .HS 0000 bmptr .HS 00 basval .HS 00 half .HS 00 * bitmap info tables bmastat .HS 00 bmadev .HS 00 bmadadr .HS 0000 bmacmap .HS 00 tposll .HS 00 tposlh .HS 00 tposhi .HS 00 rwreql .HS 00 rwreqh .HS 00 nlchar .HS 00 nlmask .HS 00 ioaccess .HS 00 has a call been made to disk device handler ? cmdtemp .HS 00 bkbitflg .HS 00 used to set or clear backup bit duplflag .HS 00 vcbentry .HS 00 * xdos temporary variables namcnt .HS 00 rnptr .HS 00 namptr .HS 00 vnptr .HS 00 prfxflg .HS 00 cferr .HS 00 * deallocation temporary variables firstbl .HS 00 firstbh .HS 00 stortyp .HS 00 deblock .HS 0000 dtree .HS 00 dsap .HS 00 dseed .HS 0000 topdest .HS 00 dtmpx .HS 00 loklst .EQ * look list of recognized device numbers dealbufl .HS 0000000000000000 dealbufh .HS 0000000000000000 cbytes .HS 0000 .HS 00 cbytes+2 must = 0 bufaddrl .HS 00 bufaddrh .HS 00 delflag .HS 00 used by 'detree' to know if called from delete (destroy). *-------------------------------------- * variables used by SP remap & XRW Disk ][ to store last track used *-------------------------------------- XRW.D2Trk .EQ * XDOS.SPUnit .HS 00000000000000 14+1 for S0D2 .HS 00 .HS 00000000000000 XRW.D2VolNum .EQ * XDOS.SPVectLo .HS 00000000000000 storage for low byte of smartport entry. .HS 00 .HS 00000000000000 XRW.D2SeekTime .EQ * XDOS.SPVectHi .HS 00000000000000 storage for high byte of smartport entry. .HS 00 .HS 00000000000000 XDOS.SPStatus .HS 00000000 .LIST ON XDOS.DATA.LEN .EQ *-XDOS.DATA .LIST OFF .ED *-------------------------------------- * zero fill to page boundary - 3 ($FEFD). so that cortland flag stays within page boundary. .LIST ON XDOS.FREE .EQ $FEFD-*-XDOS.DATA.LEN (2.0.3 = $0C) .LIST OFF cortdisp .EQ $FEFD cortflag .EQ $FEFF cortland flag. 1 = Cortland system (must stay within page boundary) *-------------------------------------- XDOS.LEN .EQ *-XDOS MAN SAVE usr/src/prodos.fx/prodos.s.xdos.f LOAD usr/src/prodos.fx/prodos.s ASM