diff --git a/Bitmap.cpp b/Bitmap.cpp new file mode 100644 index 0000000..3767539 --- /dev/null +++ b/Bitmap.cpp @@ -0,0 +1,66 @@ +#include "Bitmap.h" + +#include + +namespace ProDOS { + +/* + * + * + * + */ + +Bitmap::Bitmap(unsigned blocks) : + _bitmap(NULL), _blocks(blocks), + _bitmapSize((blocks + 4096 - 1) >> 12) +{ + // 1 block = 512 bytes = 4096 bits + _bitmap = new uint8_t[_bitmapSize]; + + // mark every requested block as free. + unsigned bytes = blocks >> 3; + std::memset(_bitmap, 0xff, bytes); + + // all trailing blocks are marked as used. + std::memset(_bitmap + bytes, 0x00, _bitmapSize - bytes); + + // and handle the edge case... + /* + * 0 -> 0 0 0 0 0 0 0 0 + * 1 -> 1 0 0 0 0 0 0 0 + * 2 -> 1 1 0 0 0 0 0 0 + * 3 -> 1 1 1 0 0 0 0 0 + * ... + * 7 -> 1 1 1 1 1 1 1 0 + */ + //unsigned tmp = (1 << (8 - (blocks & 0x07))) - 1; + //_bitmap[bytes] = ~tmp & 0xff; + + _bitmap[bytes] = 0 - (1 << (8 - (blocks & 0x07))); + + //_bitmap[bytes] = (0xff00 >> (blocks & 0x07)) & 0xff; +} + +Bitmap::~Bitmap() +{ + delete[] _bitmap; +} + + +bool Bitmap::markBlock(unsigned block, bool inUse) +{ + if (block >= _blocks) return false; + + unsigned index = BlockIndex(block); + unsigned mask = BlockMask(block); + uint8_t data = _bitmap[index]; + + if (inUse) data &= ~mask; + else data |= mask; + + _bitmap[index] = data; + + return true; +} +} // namespace + diff --git a/Bitmap.h b/Bitmap.h new file mode 100644 index 0000000..d5e6b08 --- /dev/null +++ b/Bitmap.h @@ -0,0 +1,57 @@ +#ifndef __PRODOS_BITMAP_H__ +#define __PRODOS_BITMAP_H__ + +#include + +namespace ProDOS { + +class Bitmap { +public: + Bitmap(unsigned blocks); + ~Bitmap(); + + bool blockFree(unsigned block) const; + bool markBlock(unsigned block, bool inUse); + + unsigned blocks() const; + unsigned bitmapBlocks() const; + +private: + static unsigned BlockMask(unsigned block); + static unsigned BlockIndex(unsigned block); + + uint8_t *_bitmap; + unsigned _blocks; + unsigned _bitmapSize; +}; + +inline unsigned Bitmap::blocks() const +{ + return _blocks; +} + +inline unsigned Bitmap::bitmapBlocks() const +{ + return _bitmapSize >> 12; +} + +inline unsigned Bitmap::BlockMask(unsigned block) +{ + return 0x80 >> (block & 0x07); +} + +inline unsigned Bitmap::BlockIndex(unsigned block) +{ + return block >> 3; +} + +inline bool Bitmap::blockFree(unsigned block) const +{ + if (block >= _blocks) return false; + return (_bitmap[BlockIndex(block)] & BlockMask(block)) != 0; +} + +} // namespace + +#endif +