mirror of
https://github.com/encounter/aurora.git
synced 2026-03-30 10:57:39 -07:00
18cdf141cb
Original repository: https://github.com/AxioDL/kabufuda Cleaned up & converted to `aurora::card`, with SDL3 file I/O. --------- Co-authored-by: Phillip Stephens <antidote.crk@gmail.com> Co-authored-by: Jack Andersen <jackoalan@gmail.com> Co-authored-by: Lioncash <mathew1800@gmail.com> Co-authored-by: Luke Street <luke@street.dev>
107 lines
3.0 KiB
C++
107 lines
3.0 KiB
C++
#include "BlockAllocationTable.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
#include "../internal.hpp"
|
|
#include "Util.hpp"
|
|
|
|
namespace aurora::card {
|
|
void BlockAllocationTable::swapEndian() {
|
|
m_checksum = bswap(m_checksum);
|
|
m_checksumInv = bswap(m_checksumInv);
|
|
m_updateCounter = bswap(m_updateCounter);
|
|
m_freeBlocks = bswap(m_freeBlocks);
|
|
m_lastAllocated = bswap(m_lastAllocated);
|
|
std::for_each(std::begin(m_map), std::end(m_map), [](uint16_t& val) { val = bswap(val); });
|
|
}
|
|
|
|
void BlockAllocationTable::updateChecksum() {
|
|
swapEndian();
|
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(raw.data() + 4), 0xFFE, &m_checksum, &m_checksumInv);
|
|
swapEndian();
|
|
}
|
|
|
|
bool BlockAllocationTable::valid() const {
|
|
uint16_t ckSum = 0;
|
|
uint16_t ckSumInv = 0;
|
|
const_cast<BlockAllocationTable&>(*this).swapEndian();
|
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(raw.data() + 4), 0xFFE, &ckSum, &ckSumInv);
|
|
bool res = ckSum == m_checksum && ckSumInv == m_checksumInv;
|
|
const_cast<BlockAllocationTable&>(*this).swapEndian();
|
|
return res;
|
|
}
|
|
|
|
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
|
|
: m_checksum{0}
|
|
, m_checksumInv{0}
|
|
, m_updateCounter{0}
|
|
, m_freeBlocks{static_cast<uint16_t>(blockCount - FSTBlocks)}
|
|
, m_lastAllocated{4}
|
|
, m_map{{}} {
|
|
updateChecksum();
|
|
}
|
|
|
|
uint16_t BlockAllocationTable::getNextBlock(uint16_t block) const {
|
|
if ((block < FSTBlocks) || (block > (BATSize - FSTBlocks)))
|
|
return 0xFFFF;
|
|
|
|
return m_map[block - FSTBlocks];
|
|
}
|
|
|
|
uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const {
|
|
if (m_freeBlocks > 0) {
|
|
maxBlock = std::min(maxBlock, static_cast<uint16_t>(BATSize));
|
|
for (uint16_t i = startingBlock; i < maxBlock; ++i)
|
|
if (m_map[i - FSTBlocks] == 0)
|
|
return i;
|
|
|
|
for (uint16_t i = FSTBlocks; i < startingBlock; ++i)
|
|
if (m_map[i - FSTBlocks] == 0)
|
|
return i;
|
|
}
|
|
|
|
return 0xFFFF;
|
|
}
|
|
|
|
bool BlockAllocationTable::clear(uint16_t first, uint16_t count) {
|
|
std::vector<uint16_t> blocks;
|
|
while (first != 0xFFFF && first != 0) {
|
|
blocks.push_back(first);
|
|
first = getNextBlock(first);
|
|
}
|
|
if (first > 0) {
|
|
size_t length = blocks.size();
|
|
if (length != count)
|
|
return false;
|
|
|
|
for (size_t i = 0; i < length; ++i)
|
|
m_map[blocks.at(i) - FSTBlocks] = 0;
|
|
m_freeBlocks += count;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks) {
|
|
uint16_t firstBlock = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
|
|
uint16_t freeBlock = firstBlock;
|
|
if (freeBlock != 0xFFFF) {
|
|
uint16_t tmpCount = count;
|
|
while ((count--) > 0 && freeBlock != 0xFFFF) {
|
|
m_map[(freeBlock - FSTBlocks)] = 0xFFFF;
|
|
if (count != 0) {
|
|
m_map[(freeBlock - FSTBlocks)] = nextFreeBlock(maxBlocks - FSTBlocks, freeBlock + 1);
|
|
freeBlock = m_map[(freeBlock - FSTBlocks)];
|
|
}
|
|
}
|
|
if (freeBlock == 0xFFFF)
|
|
return 0xFFFF;
|
|
|
|
m_lastAllocated = freeBlock;
|
|
m_freeBlocks -= tmpCount;
|
|
}
|
|
return firstBlock;
|
|
}
|
|
} // namespace aurora::card
|