Squashed 'deps/nostalgia/' changes from 5e90f8d4..3b874c6e
3b874c6e [turbine] Fix refresh logic to handle default refresh within value 6cf7bf96 [ox/std] Hopefully fix MSVC build e34df255 [nostalgia] Update developer-handbook non-error return 7eab2f92 [studio/modlib] Comment out logging in configio 3824788a [ox/std] Add non-const operator[] to Pair 1eac7e1e [ox/std] Add Pair 8798d2d7 [nostalgia/core] Fix getTileIdx(TileSheet, SubSheetId) f82db690 [nostalgia/core] Make load TileSheet functions take CompactTileSheet, in addition to FileAddresses 0dfa7c30 [studio/modlib] Make TaskRunner check that task is not null 2afade24 Merge commit 'fc2dec64389824a251fb258f6fd0a9074e521cc2' 3635702e [nostalgia] Cleanup config IO 6cbafc75 [nostalgia,keel] Make repair return ox::Error 0d7b89a0 [turbine] Add TimeMs alias to uint64_t e8f5c911 [studio/applib] Change updateHandler to 10 second interval 3cb3bc12 [nostalgia/core] Add valid and repair functions for PaletteV3 a2cec10c [keel] Add valid and repair functions for AssetManager git-subtree-dir: deps/nostalgia git-subtree-split: 3b874c6e6aa0b80783fc9d712c31bc837326337c
This commit is contained in:
		@@ -11,6 +11,7 @@
 | 
			
		||||
 | 
			
		||||
#include "context.hpp"
 | 
			
		||||
#include "palette.hpp"
 | 
			
		||||
#include "tilesheet.hpp"
 | 
			
		||||
 | 
			
		||||
namespace nostalgia::core {
 | 
			
		||||
 | 
			
		||||
@@ -134,12 +135,23 @@ ox::Error loadBgTileSheet(
 | 
			
		||||
		unsigned cbb,
 | 
			
		||||
		TileSheetSet const&set) noexcept;
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		unsigned cbb,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank) noexcept;
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		unsigned cbb,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank = {}) noexcept;
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		bool loadDefaultPalette) noexcept;
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
 
 | 
			
		||||
@@ -74,6 +74,15 @@ constexpr bool valid(Palette const&p) noexcept {
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[nodiscard]]
 | 
			
		||||
constexpr ox::Error repair(Palette &p) noexcept {
 | 
			
		||||
	auto const colors = p.colorInfo.size();
 | 
			
		||||
	for (auto &page : p.pages) {
 | 
			
		||||
		page.resize(colors);
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[nodiscard]]
 | 
			
		||||
constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept {
 | 
			
		||||
	if (page < pal.pages.size() && idx < pal.pages[page].size()) [[likely]] {
 | 
			
		||||
 
 | 
			
		||||
@@ -296,9 +296,10 @@ using TileSheetV4 = TileSheet;
 | 
			
		||||
struct CompactTileSheetV1 {
 | 
			
		||||
	static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
 | 
			
		||||
	static constexpr auto TypeVersion = 1;
 | 
			
		||||
	static constexpr auto Preloadable = true;
 | 
			
		||||
	int8_t bpp = 0;
 | 
			
		||||
	ox::FileAddress defaultPalette;
 | 
			
		||||
	ox::Vector<uint8_t> pixels = {};
 | 
			
		||||
	ox::Vector<uint8_t> pixels;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using CompactTileSheet = CompactTileSheetV1;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,104 +24,6 @@ namespace nostalgia::core {
 | 
			
		||||
 | 
			
		||||
constexpr auto SpriteCount = 128;
 | 
			
		||||
 | 
			
		||||
struct GbaTileMapTarget {
 | 
			
		||||
	static constexpr auto TypeName = CompactTileSheet::TypeName;
 | 
			
		||||
	static constexpr auto TypeVersion = CompactTileSheet::TypeVersion;
 | 
			
		||||
	unsigned &bpp;
 | 
			
		||||
	ox::FileAddress defaultPalette;
 | 
			
		||||
	volatile uint16_t *tileMap = nullptr;
 | 
			
		||||
	// the following values are not actually in CompactTileSheet,
 | 
			
		||||
	// and only exist to communicate with the loading process
 | 
			
		||||
	size_t tileWriteIdx = 0;
 | 
			
		||||
	unsigned targetBpp = 0;
 | 
			
		||||
	TileSheetSetEntry const*setEntry = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[nodiscard]]
 | 
			
		||||
static bool loadPixel(TileSheetSetEntry const&setEntry, size_t §ionIdx, int tileIdx) noexcept {
 | 
			
		||||
	if (setEntry.sections.size() <= sectionIdx) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	auto §ion = setEntry.sections[sectionIdx];
 | 
			
		||||
	if (tileIdx < section.begin) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	if (tileIdx > section.end()) {
 | 
			
		||||
		if (sectionIdx >= setEntry.sections.size()) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		++sectionIdx;
 | 
			
		||||
		return tileIdx > section.begin && tileIdx <= section.end();
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t) noexcept {
 | 
			
		||||
	oxReturnError(io->template setTypeInfo<CompactTileSheet>());
 | 
			
		||||
	oxReturnError(io->field("bpp", &t->bpp));
 | 
			
		||||
	oxReturnError(io->field("defaultPalette", &t->defaultPalette));
 | 
			
		||||
	if (t->targetBpp == 0) {
 | 
			
		||||
		t->targetBpp = t->bpp;
 | 
			
		||||
	}
 | 
			
		||||
	if (t->targetBpp != t->bpp && t->bpp == 8) {
 | 
			
		||||
		return OxError(1, "Cannot load an 8 BPP tilesheet into a 4 BPP CBB");
 | 
			
		||||
	}
 | 
			
		||||
	ox::Error out{};
 | 
			
		||||
	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.
 | 
			
		||||
		size_t sectionIdx = 0;
 | 
			
		||||
		if (t->targetBpp == t->bpp) {
 | 
			
		||||
			uint16_t intermediate = 0;
 | 
			
		||||
			size_t const fourBpp = t->bpp == 4;
 | 
			
		||||
			const auto handleTileMap = [t, &intermediate, §ionIdx, fourBpp]
 | 
			
		||||
					(std::size_t i, uint8_t const*tile) {
 | 
			
		||||
				auto const tileIdx = static_cast<int>((i * (2 * fourBpp)) / PixelsPerTile);
 | 
			
		||||
				if (!loadPixel(*t->setEntry, sectionIdx, tileIdx)) {
 | 
			
		||||
					return ox::Error{};
 | 
			
		||||
				}
 | 
			
		||||
				if (i & 1) { // i is odd
 | 
			
		||||
					intermediate |= static_cast<uint16_t>(*tile) << 8;
 | 
			
		||||
					t->tileMap[t->tileWriteIdx] = 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, §ionIdx](std::size_t i, uint8_t const*tile) {
 | 
			
		||||
				auto constexpr BytesPerTile4Bpp = 32;
 | 
			
		||||
				auto const tileIdx = static_cast<int>(i / BytesPerTile4Bpp);
 | 
			
		||||
				if (!loadPixel(*t->setEntry, sectionIdx, tileIdx)) {
 | 
			
		||||
					return ox::Error{};
 | 
			
		||||
				}
 | 
			
		||||
				uint16_t const px1 = *tile & 0xf;
 | 
			
		||||
				uint16_t const px2 = *tile >> 4;
 | 
			
		||||
				t->tileMap[t->tileWriteIdx] = static_cast<uint16_t>(px1 | (px2 << 8));
 | 
			
		||||
				++t->tileWriteIdx;
 | 
			
		||||
				return ox::Error{};
 | 
			
		||||
			};
 | 
			
		||||
			out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		uint16_t intermediate = 0;
 | 
			
		||||
		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;
 | 
			
		||||
			} else { // i is even
 | 
			
		||||
				intermediate = *tile & 0x00ff;
 | 
			
		||||
			}
 | 
			
		||||
			return ox::Error{};
 | 
			
		||||
		};
 | 
			
		||||
		out = io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
 | 
			
		||||
	}
 | 
			
		||||
	return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error initGfx(Context&, InitParams const&) noexcept {
 | 
			
		||||
	for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
 | 
			
		||||
		teagba::bgSetSbb(*bgCtl, 28);
 | 
			
		||||
@@ -181,21 +83,48 @@ static ox::Error loadTileSheetSet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		uint16_t *tileMapTargetMem,
 | 
			
		||||
		TileSheetSet const&set) noexcept {
 | 
			
		||||
	auto &rom = ctx.rom();
 | 
			
		||||
	size_t tileWriteIdx = 0;
 | 
			
		||||
	for (auto const&entry : set.entries) {
 | 
			
		||||
		oxRequire(tsStat, rom.stat(entry.tilesheet));
 | 
			
		||||
		oxRequire(ts, rom.directAccess(entry.tilesheet));
 | 
			
		||||
		unsigned tilesheetBpp{};
 | 
			
		||||
		GbaTileMapTarget target{
 | 
			
		||||
			.bpp = tilesheetBpp,
 | 
			
		||||
			.defaultPalette = {},
 | 
			
		||||
			.tileMap = tileMapTargetMem + tileWriteIdx,
 | 
			
		||||
			.targetBpp = static_cast<unsigned>(set.bpp),
 | 
			
		||||
			.setEntry = &entry,
 | 
			
		||||
		};
 | 
			
		||||
		oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
 | 
			
		||||
		tileWriteIdx += target.tileWriteIdx;
 | 
			
		||||
		oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), entry.tilesheet));
 | 
			
		||||
		if (set.bpp != ts->bpp && ts->bpp == 8) {
 | 
			
		||||
			return OxError(1, "cannot load an 8 BPP tilesheet into a 4 BPP CBB");
 | 
			
		||||
		}
 | 
			
		||||
		for (auto const&s : entry.sections) {
 | 
			
		||||
			auto const cnt = (static_cast<size_t>(s.tiles) * PixelsPerTile) / (1 + (set.bpp == 4));
 | 
			
		||||
			for (size_t i = 0; i < cnt; ++i) {
 | 
			
		||||
				auto const srcIdx = static_cast<size_t>(s.begin) + i * 2;
 | 
			
		||||
				auto const v = static_cast<uint16_t>(
 | 
			
		||||
						static_cast<uint16_t>(ts->pixels[srcIdx]) |
 | 
			
		||||
				        (static_cast<uint16_t>(ts->pixels[srcIdx + 1]) << 8));
 | 
			
		||||
				tileMapTargetMem[tileWriteIdx + i] = v;
 | 
			
		||||
			}
 | 
			
		||||
			tileWriteIdx += cnt;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		unsigned cbb,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank) noexcept {
 | 
			
		||||
	auto const cnt = (ts.pixels.size() * PixelsPerTile) / (1 + (ts.bpp == 4));
 | 
			
		||||
	for (size_t i = 0; i < cnt; ++i) {
 | 
			
		||||
		auto const srcIdx = i * 2;
 | 
			
		||||
		auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]);
 | 
			
		||||
		auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]);
 | 
			
		||||
		MEM_BG_TILES[cbb][i] = static_cast<uint16_t>(p1 | (p2 << 8));
 | 
			
		||||
	}
 | 
			
		||||
	// update bpp of all bgs with the updated cbb
 | 
			
		||||
	auto const bpp = ctx.cbbData[cbb].bpp;
 | 
			
		||||
	teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
 | 
			
		||||
		if (teagba::bgCbb(bgCtl) == cbb) {
 | 
			
		||||
			teagba::bgSetBpp(bgCtl, bpp);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
	if (paletteBank.has_value() && ts.defaultPalette) {
 | 
			
		||||
		oxReturnError(loadBgPalette(ctx, *paletteBank, ts.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
@@ -205,26 +134,8 @@ ox::Error loadBgTileSheet(
 | 
			
		||||
		unsigned cbb,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank) noexcept {
 | 
			
		||||
	auto &rom = ctx.rom();
 | 
			
		||||
	oxRequire(tsStat, rom.stat(tilesheetAddr));
 | 
			
		||||
	oxRequire(ts, rom.directAccess(tilesheetAddr));
 | 
			
		||||
	GbaTileMapTarget target{
 | 
			
		||||
		.bpp = ctx.cbbData[cbb].bpp,
 | 
			
		||||
		.defaultPalette = {},
 | 
			
		||||
		.tileMap = MEM_BG_TILES[cbb].data(),
 | 
			
		||||
	};
 | 
			
		||||
	oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
 | 
			
		||||
	// update bpp of all bgs with the updated cbb
 | 
			
		||||
	const auto bpp = ctx.cbbData[cbb].bpp;
 | 
			
		||||
	teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
 | 
			
		||||
		if (teagba::bgCbb(bgCtl) == cbb) {
 | 
			
		||||
			teagba::bgSetBpp(bgCtl, bpp);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
	if (paletteBank.has_value() && target.defaultPalette) {
 | 
			
		||||
		oxReturnError(loadBgPalette(ctx, *paletteBank, target.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
	oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
 | 
			
		||||
	return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
@@ -252,25 +163,28 @@ static void setSpritesBpp(unsigned const bpp) noexcept {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		bool loadDefaultPalette) noexcept {
 | 
			
		||||
	for (size_t i = 0; i < ts.pixels.size(); i += 2) {
 | 
			
		||||
		uint16_t v = ts.pixels[i];
 | 
			
		||||
		v |= static_cast<uint16_t>(ts.pixels[i + 1] << 8);
 | 
			
		||||
		MEM_SPRITE_TILES[i] = v;
 | 
			
		||||
	}
 | 
			
		||||
	if (loadDefaultPalette && ts.defaultPalette) {
 | 
			
		||||
		oxReturnError(loadSpritePalette(ctx, ts.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	setSpritesBpp(static_cast<unsigned>(ts.bpp));
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		bool loadDefaultPalette) noexcept {
 | 
			
		||||
	auto &rom = ctx.rom();
 | 
			
		||||
	oxRequire(tsStat, rom.stat(tilesheetAddr));
 | 
			
		||||
	oxRequire(ts, rom.directAccess(tilesheetAddr));
 | 
			
		||||
	unsigned bpp{};
 | 
			
		||||
	GbaTileMapTarget target{
 | 
			
		||||
		.bpp = bpp,
 | 
			
		||||
		.defaultPalette = {},
 | 
			
		||||
		.tileMap = MEM_SPRITE_TILES,
 | 
			
		||||
	};
 | 
			
		||||
	oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
 | 
			
		||||
	if (loadDefaultPalette && target.defaultPalette) {
 | 
			
		||||
		oxReturnError(loadSpritePalette(ctx, target.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	setSpritesBpp(bpp);
 | 
			
		||||
	return {};
 | 
			
		||||
	oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
 | 
			
		||||
	return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
 
 | 
			
		||||
@@ -572,20 +572,28 @@ static ox::Result<TileSheetData> buildSetTsd(
 | 
			
		||||
	return setTsd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		uint_t cbb,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank) noexcept {
 | 
			
		||||
	oxRequire(tsd, normalizeTileSheet(ts));
 | 
			
		||||
	oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbb, tsd.width, tsd.height);
 | 
			
		||||
	ctx.cbbs[cbb].tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
 | 
			
		||||
	if (paletteBank.has_value() && ts.defaultPalette) {
 | 
			
		||||
		oxReturnError(loadBgPalette(ctx, *paletteBank, ts.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		uint_t cbb,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		ox::Optional<unsigned> const&paletteBank) noexcept {
 | 
			
		||||
	auto &kctx = keelCtx(ctx.turbineCtx);
 | 
			
		||||
	oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
 | 
			
		||||
	oxRequire(tsd, normalizeTileSheet(*tilesheet));
 | 
			
		||||
	oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbb, tsd.width, tsd.height);
 | 
			
		||||
	ctx.cbbs[cbb].tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
 | 
			
		||||
	if (paletteBank.has_value() && tilesheet->defaultPalette) {
 | 
			
		||||
		oxReturnError(loadBgPalette(ctx, *paletteBank, tilesheet->defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
	oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
 | 
			
		||||
	return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadBgTileSheet(
 | 
			
		||||
@@ -599,19 +607,26 @@ ox::Error loadBgTileSheet(
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		CompactTileSheet const&ts,
 | 
			
		||||
		bool loadDefaultPalette) noexcept {
 | 
			
		||||
	auto &kctx = keelCtx(ctx.turbineCtx);
 | 
			
		||||
	oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
 | 
			
		||||
	oxRequire(tsd, normalizeTileSheet(*tilesheet));
 | 
			
		||||
	oxRequire(tsd, normalizeTileSheet(ts));
 | 
			
		||||
	oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
 | 
			
		||||
	ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
 | 
			
		||||
	if (loadDefaultPalette) {
 | 
			
		||||
		oxReturnError(loadSpritePalette(ctx, tilesheet->defaultPalette));
 | 
			
		||||
		oxReturnError(loadSpritePalette(ctx, ts.defaultPalette));
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		ox::FileAddress const&tilesheetAddr,
 | 
			
		||||
		bool loadDefaultPalette) noexcept {
 | 
			
		||||
	auto &kctx = keelCtx(ctx.turbineCtx);
 | 
			
		||||
	oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
 | 
			
		||||
	return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error loadSpriteTileSheet(
 | 
			
		||||
		Context &ctx,
 | 
			
		||||
		TileSheetSet const&set) noexcept {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,16 +15,6 @@ namespace nostalgia::core {
 | 
			
		||||
 | 
			
		||||
namespace ig = studio::ig;
 | 
			
		||||
 | 
			
		||||
static ox::String configName(ox::StringView str) noexcept {
 | 
			
		||||
	auto out = ox::String{str};
 | 
			
		||||
	for (auto &c : out) {
 | 
			
		||||
		if (c == '/' || c == '\\') {
 | 
			
		||||
			c = '%';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TileSheetEditorConfig {
 | 
			
		||||
	static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfig";
 | 
			
		||||
	static constexpr auto TypeVersion = 1;
 | 
			
		||||
@@ -35,16 +25,6 @@ oxModelBegin(TileSheetEditorConfig)
 | 
			
		||||
	oxModelFieldRename(activeSubsheet, active_subsheet)
 | 
			
		||||
oxModelEnd()
 | 
			
		||||
 | 
			
		||||
struct TileSheetEditorConfigs {
 | 
			
		||||
	static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfigs";
 | 
			
		||||
	static constexpr auto TypeVersion = 1;
 | 
			
		||||
	ox::HashMap<ox::String, TileSheetEditorConfig> configs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
oxModelBegin(TileSheetEditorConfigs)
 | 
			
		||||
	oxModelField(configs)
 | 
			
		||||
oxModelEnd()
 | 
			
		||||
 | 
			
		||||
static ox::Vector<uint32_t> normalizePixelSizes(
 | 
			
		||||
		ox::Vector<uint8_t> const&inPixels,
 | 
			
		||||
		int const bpp) noexcept {
 | 
			
		||||
@@ -120,7 +100,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::Stri
 | 
			
		||||
	m_model.paletteChanged.connect(this, &TileSheetEditorImGui::setPaletteSelection);
 | 
			
		||||
	// load config
 | 
			
		||||
	auto const&config = studio::readConfig<TileSheetEditorConfig>(
 | 
			
		||||
			keelCtx(m_sctx), configName(itemPath()));
 | 
			
		||||
			keelCtx(m_sctx), itemPath());
 | 
			
		||||
	if (config.ok()) {
 | 
			
		||||
		m_model.setActiveSubsheet(validateSubSheetIdx(m_model.img(), config.value.activeSubsheet));
 | 
			
		||||
	}
 | 
			
		||||
@@ -537,9 +517,9 @@ ox::Error TileSheetEditorImGui::setPaletteSelection() noexcept {
 | 
			
		||||
 | 
			
		||||
void TileSheetEditorImGui::setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept {
 | 
			
		||||
	m_model.setActiveSubsheet(path);
 | 
			
		||||
	studio::editConfig<TileSheetEditorConfig>(keelCtx(m_sctx), configName(itemPath()),
 | 
			
		||||
		[&path](TileSheetEditorConfig *config) {
 | 
			
		||||
			config->activeSubsheet = std::move(path);
 | 
			
		||||
	studio::editConfig<TileSheetEditorConfig>(keelCtx(m_sctx), itemPath(),
 | 
			
		||||
		[&path](TileSheetEditorConfig &config) {
 | 
			
		||||
			config.activeSubsheet = std::move(path);
 | 
			
		||||
		});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id)
 | 
			
		||||
static ox::Optional<size_t> getPixelIdx(
 | 
			
		||||
		TileSheet::SubSheet const&ss,
 | 
			
		||||
		SubSheetId const id,
 | 
			
		||||
		size_t idx,
 | 
			
		||||
		size_t &idx,
 | 
			
		||||
		int8_t const bpp) noexcept {
 | 
			
		||||
	for (auto const&child: ss.subsheets) {
 | 
			
		||||
		if (child.id == id) {
 | 
			
		||||
@@ -63,11 +63,12 @@ static ox::Optional<size_t> getPixelIdx(
 | 
			
		||||
		}
 | 
			
		||||
		idx += pixelCnt(child, bpp);
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
	return ox::Optional<size_t>{};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
 | 
			
		||||
	auto const out = getPixelIdx(ts.subsheet, id, 0, ts.bpp);
 | 
			
		||||
	size_t idx{};
 | 
			
		||||
	auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp);
 | 
			
		||||
	return out.or_value(0) / PixelsPerTile;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user