#include #include #include "prodos.h" extern int debug; /* Note: PRODOS seems to label things this way */ /* block 0123 4567 */ /* 0x0f = 0000 1111 */ static int ones_lookup[16]={ /* 0x0 = 0000 */ 0, /* 0x1 = 0001 */ 1, /* 0x2 = 0010 */ 1, /* 0x3 = 0011 */ 2, /* 0x4 = 0100 */ 1, /* 0x5 = 0101 */ 2, /* 0x6 = 0110 */ 2, /* 0x7 = 0111 */ 3, /* 0x8 = 1000 */ 1, /* 0x9 = 1001 */ 2, /* 0xA = 1010 */ 2, /* 0xB = 1011 */ 3, /* 0xC = 1100 */ 2, /* 0xD = 1101 */ 3, /* 0xE = 1110 */ 3, /* 0xF = 1111 */ 4, }; /* could be replaced by "find leading 1" instruction */ /* Note we are reverse from usual, wanting MSB first */ /* if available */ static int find_first_one(unsigned char byte) { int i=0; if (byte==0) return -1; while((byte & (0x80>>i))==0) { i++; } return i; } /* Return how many bytes free in the filesystem */ /* by reading the VTOC_FREE_BITMAP */ int prodos_voldir_free_space(struct voldir_t *voldir) { int volblocks; unsigned char temp_block[PRODOS_BYTES_PER_BLOCK]; int i,j,blocks_free=0; volblocks=1+voldir->total_blocks/(PRODOS_BYTES_PER_BLOCK*8); for(j=0;jbit_map_pointer); for(i=0;i>4)&0xf]; } } return blocks_free; } /* free a block from the block bitmap */ int prodos_voldir_free_block(struct voldir_t *voldir, int block) { /* each volblock holds 512*8=4k entries */ /* block location = block%4096 */ /* which byte=remainder/8 */ int volblock; unsigned char temp_block[PRODOS_BYTES_PER_BLOCK]; unsigned char bitmap; int which_bitmap; volblock=block/(PRODOS_BYTES_PER_BLOCK*8); prodos_read_block(voldir,temp_block,volblock+voldir->bit_map_pointer); which_bitmap=(block%(PRODOS_BYTES_PER_BLOCK*8))/8; bitmap=temp_block[which_bitmap]; if (debug) { printf("Free: $%X Using volblock %d (%d), flip b[%d]#%d $%X ", block,volblock,volblock+voldir->bit_map_pointer, which_bitmap,block&7,bitmap); } /* set bit to 1 to mark free */ bitmap|=(0x80>>(block&7)); if (debug) { printf("-> $%X\n",bitmap); } temp_block[which_bitmap]=bitmap; prodos_write_block(voldir,temp_block,volblock+voldir->bit_map_pointer); return 0; } /* reserve a block in the block bitmap */ int prodos_voldir_reserve_block(struct voldir_t *voldir, int block) { /* each volblock holds 512*8=4k entries */ /* block location = block%4096 */ /* which byte=remainder/8 */ int volblock; unsigned char temp_block[PRODOS_BYTES_PER_BLOCK]; unsigned char bitmap; int which_bitmap; volblock=block/(PRODOS_BYTES_PER_BLOCK*8); prodos_read_block(voldir,temp_block,volblock+voldir->bit_map_pointer); which_bitmap=(block%(PRODOS_BYTES_PER_BLOCK*8))/8; bitmap=temp_block[which_bitmap]; if (debug) { printf("Reserve: $%X Using volblock %d (%d), flip b[%d]#%d $%X ", block,volblock,volblock+voldir->bit_map_pointer, which_bitmap,block&7,bitmap); } /* clear bit to 0 to mark used */ bitmap&=~(0x80>>(block&7)); if (debug) { printf("-> $%X\n",bitmap); } temp_block[which_bitmap]=bitmap; prodos_write_block(voldir,temp_block,volblock+voldir->bit_map_pointer); return 0; } void prodos_voldir_dump_bitmap(struct voldir_t *voldir) { int volblocks; unsigned char temp_block[PRODOS_BYTES_PER_BLOCK]; int i,j,k; volblocks=1+voldir->total_blocks/(PRODOS_BYTES_PER_BLOCK*8); for(k=0;kbit_map_pointer,k+1,volblocks); printf("\tU=used, .=free\n"); printf("\tBlock 01234567 89ABCDEF\n"); prodos_read_block(voldir,temp_block,k+voldir->bit_map_pointer); for(i=0;i<(512/16);i++) { printf("\t $%03X: %02X %02X : ",i, temp_block[(i*2)], temp_block[(1+i*2)]); for(j=0;j<8;j++) { if ((temp_block[i*2]>>(7-j))&0x1) { printf("."); } else { printf("U"); } } printf(" "); for(j=0;j<8;j++) { if ((temp_block[(1+i*2)]>>(7-j))&0x1) { printf("."); } else { printf("U"); } } printf("\n"); } } } /* find a free block in the block bitmap */ /* FIXME: for speed, remember last found block and start from there */ int prodos_voldir_find_free_block(struct voldir_t *voldir) { int volblocks; unsigned char temp_block[PRODOS_BYTES_PER_BLOCK]; int i,k,result; volblocks=1+voldir->total_blocks/(PRODOS_BYTES_PER_BLOCK*8); for(k=0;kbit_map_pointer); for(i=0;i<(512/16);i++) { result=find_first_one(temp_block[i*2]); if (result>=0) { if (debug) printf("Found free block %x\n", (k<<12)+(i<<4)+result); return (k<<12)+(i<<4)+result; } result=find_first_one(temp_block[(1+i*2)]); if (result>=0) { if (debug) printf("Found free block %x\n", (k<<12)+(i<<4)+result+8); return (k<<12)+(i<<4)+result+8; } } } /* no room */ return -1; }