mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { word } from 'js/types';
|
|
import { ProDOSVolume } from '.';
|
|
import type { VDH } from './vdh';
|
|
|
|
const BLOCK_ENTRIES = 4096;
|
|
|
|
export class BitMap {
|
|
private vdh: VDH;
|
|
private blocks: Uint8Array[];
|
|
|
|
constructor(volume: ProDOSVolume) {
|
|
this.vdh = volume.vdh();
|
|
this.blocks = volume.blocks();
|
|
}
|
|
|
|
freeBlocks() {
|
|
const free: word[] = [];
|
|
let blockOffset = 0;
|
|
let byteOffset = 0;
|
|
let bitOffset = 0;
|
|
let bitMapBlock = this.blocks[this.vdh.bitMapPointer + blockOffset];
|
|
for (let idx = 0; idx < this.vdh.totalBlocks; idx++) {
|
|
const currentByte = bitMapBlock[byteOffset];
|
|
const mask = 1 << bitOffset;
|
|
if (currentByte & mask) {
|
|
free.push(idx);
|
|
}
|
|
bitOffset += 1;
|
|
if (bitOffset > 7) {
|
|
bitOffset = 0;
|
|
byteOffset += 1;
|
|
if (byteOffset > (BLOCK_ENTRIES >> 3)) {
|
|
byteOffset = 0;
|
|
blockOffset += 1;
|
|
bitMapBlock = this.blocks[this.vdh.bitMapPointer + blockOffset];
|
|
}
|
|
}
|
|
}
|
|
return free;
|
|
}
|
|
|
|
allocBlock() {
|
|
for (let idx = 0; idx < this.vdh.totalBlocks; idx++) {
|
|
const blockOffset = Math.floor(idx / BLOCK_ENTRIES);
|
|
const bitMapBlock = this.blocks[this.vdh.bitMapPointer + blockOffset];
|
|
const byteOffset = (idx - blockOffset * BLOCK_ENTRIES) >> 8;
|
|
const bits = bitMapBlock[byteOffset];
|
|
if (bits !== 0xff) {
|
|
let mask = 0x01;
|
|
for (let bitOffset = 0; bitOffset < 8; bitOffset++) {
|
|
if (!(bits & mask)) {
|
|
bitMapBlock[byteOffset] |= mask;
|
|
return idx;
|
|
}
|
|
mask <<= 1;
|
|
}
|
|
}
|
|
}
|
|
throw new Error('Disk full');
|
|
}
|
|
|
|
freeBlock(block: word) {
|
|
if (block >= this.vdh.totalBlocks) {
|
|
throw new Error('Block out of range');
|
|
}
|
|
const blockOffset = Math.floor(block / BLOCK_ENTRIES);
|
|
const byteOffset = (block - blockOffset * BLOCK_ENTRIES) >> 8;
|
|
const bitOffset = block & 0x7;
|
|
|
|
const bitMapBlock = this.blocks[this.vdh.bitMapPointer + blockOffset];
|
|
|
|
bitMapBlock[byteOffset] &= 0xff ^ (0x01 << bitOffset);
|
|
}
|
|
}
|