[nostalgia/core] Get TileSheetSet working
This commit is contained in:
@@ -41,6 +41,7 @@ struct GbaTileMapTarget {
|
||||
// and only exist to communicate with the loading process
|
||||
size_t tileWriteIdx = 0;
|
||||
unsigned targetBpp = 0;
|
||||
TileSheetSetEntry const*setEntry = nullptr;
|
||||
};
|
||||
|
||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaPaletteTarget> auto *t) noexcept {
|
||||
@@ -63,7 +64,6 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t)
|
||||
oxReturnError(io->template setTypeInfo<CompactTileSheet>());
|
||||
oxReturnError(io->field("bpp", &t->bpp));
|
||||
oxReturnError(io->field("defaultPalette", &t->defaultPalette));
|
||||
uint16_t intermediate = 0;
|
||||
if (t->targetBpp == 0) {
|
||||
t->targetBpp = t->bpp;
|
||||
}
|
||||
@@ -71,32 +71,75 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t)
|
||||
return OxError(1, "Cannot load an 8 BPP tilesheet into a 4 BPP CBB");
|
||||
}
|
||||
ox::Error out{};
|
||||
if (t->targetBpp == t->bpp) {
|
||||
const auto handleTileMap = [t, &intermediate](std::size_t i, uint8_t const*tile) {
|
||||
uint16_t intermediate = 0;
|
||||
if (t->setEntry) {
|
||||
// The following code is atrocious, but it works.
|
||||
// It might be possible to clean it up a little, but it probably
|
||||
// cannot be seriously optimized without preloading TileSheets.
|
||||
// Consider building an array of bitmaps (Array<uint64_t, 4>)
|
||||
// so this can be done with a single bitmap look up.
|
||||
if (t->targetBpp == t->bpp) {
|
||||
TileSheetSetEntrySection const*section = &t->setEntry->sections[0];
|
||||
size_t sectionIdx = 1;
|
||||
size_t writeIt = 0;
|
||||
size_t const fourBpp = t->bpp == 4;
|
||||
const auto handleTileMap = [t, &intermediate, §ion, §ionIdx, &writeIt, fourBpp]
|
||||
(std::size_t i, uint8_t const *tile) {
|
||||
if (!section) {
|
||||
return ox::Error{};
|
||||
}
|
||||
auto const tileIdx = static_cast<int>((i * (2 * fourBpp)) / PixelsPerTile);
|
||||
if (tileIdx < section->begin) {
|
||||
return ox::Error{};
|
||||
}
|
||||
if (tileIdx > section->end()) {
|
||||
if (sectionIdx >= t->setEntry->sections.size()) {
|
||||
section = nullptr;
|
||||
return ox::Error{};
|
||||
}
|
||||
section = &t->setEntry->sections[sectionIdx];
|
||||
++sectionIdx;
|
||||
if (tileIdx < section->begin || tileIdx > section->end()) {
|
||||
return ox::Error{};
|
||||
}
|
||||
}
|
||||
if (writeIt & 1) { // writeIt is odd
|
||||
intermediate |= static_cast<uint16_t>(*tile) << 8;
|
||||
t->tileMap[writeIt / 2] = intermediate;
|
||||
++t->tileWriteIdx;
|
||||
} else { // writeIt is even
|
||||
intermediate = *tile & 0x00ff;
|
||||
}
|
||||
++writeIt;
|
||||
return ox::Error{};
|
||||
};
|
||||
out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
} else if (t->targetBpp > t->bpp) { // 4 -> 8 bits
|
||||
const auto handleTileMap = [t, &intermediate](std::size_t i, uint8_t const *tile) {
|
||||
if (i & 1) { // i is odd
|
||||
intermediate |= static_cast<uint16_t>(*tile) << 8;
|
||||
// write 4 pixels from intermediate
|
||||
t->tileMap[i - 3] = (intermediate & 0b0000'0000'0000'1111) >> 0;
|
||||
t->tileMap[i - 2] = (intermediate & 0b0000'0000'1111'0000) >> 4;
|
||||
t->tileMap[i - 1] = (intermediate & 0b0000'1111'0000'0000) >> 8;
|
||||
t->tileMap[i - 0] = (intermediate & 0b1111'0000'0000'0000) >> 14;
|
||||
++t->tileWriteIdx;
|
||||
} else { // i is even
|
||||
intermediate = *tile & 0x00ff;
|
||||
}
|
||||
return ox::Error{};
|
||||
};
|
||||
out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
}
|
||||
} else {
|
||||
const auto handleTileMap = [t, &intermediate](std::size_t i, const uint8_t *tile) {
|
||||
if (i & 1) { // i is odd
|
||||
intermediate |= static_cast<uint16_t>(*tile) << 8;
|
||||
t->tileMap[i / 2] = intermediate;
|
||||
++t->tileWriteIdx;
|
||||
} else { // i is even
|
||||
intermediate = *tile & 0x00ff;
|
||||
}
|
||||
return ox::Error{};
|
||||
};
|
||||
out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
} else if (t->targetBpp > t->bpp) { // 4 -> 8 bits
|
||||
const auto handleTileMap = [t, &intermediate](std::size_t i, uint8_t const*tile) {
|
||||
if (i & 1) { // i is odd
|
||||
intermediate |= static_cast<uint16_t>(*tile) << 8;
|
||||
// write 4 pixels from intermediate
|
||||
t->tileMap[i - 3] = (intermediate & 0b0000'0000'0000'1111) >> 0;
|
||||
t->tileMap[i - 2] = (intermediate & 0b0000'0000'1111'0000) >> 4;
|
||||
t->tileMap[i - 1] = (intermediate & 0b0000'1111'0000'0000) >> 8;
|
||||
t->tileMap[i - 0] = (intermediate & 0b1111'0000'0000'0000) >> 14;
|
||||
++t->tileWriteIdx;
|
||||
} else { // i is even
|
||||
intermediate = *tile & 0x00ff;
|
||||
}
|
||||
return ox::Error{};
|
||||
return OxError(0);
|
||||
};
|
||||
out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
}
|
||||
@@ -150,6 +193,7 @@ static ox::Error loadTileSheetSet(
|
||||
.bpp = bpp,
|
||||
.defaultPalette = {},
|
||||
.tileMap = tileMapTargetMem + tileWriteIdx,
|
||||
.setEntry = &entry,
|
||||
};
|
||||
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
|
||||
tileWriteIdx += target.tileWriteIdx;
|
||||
|
Reference in New Issue
Block a user