Compare commits
No commits in common. "3824788a1a178f297e88123da4e532be44956364" and "5e90f8d45434fa36b6e113357cf05a6cf53bfae5" have entirely different histories.
3824788a1a
...
5e90f8d454
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -113,7 +113,6 @@ install(
|
|||||||
memory.hpp
|
memory.hpp
|
||||||
new.hpp
|
new.hpp
|
||||||
optional.hpp
|
optional.hpp
|
||||||
pair.hpp
|
|
||||||
point.hpp
|
point.hpp
|
||||||
random.hpp
|
random.hpp
|
||||||
ranges.hpp
|
ranges.hpp
|
||||||
|
19
deps/ox/src/ox/std/pair.hpp
vendored
19
deps/ox/src/ox/std/pair.hpp
vendored
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 - 2024 gary@drinkingtea.net
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace ox {
|
|
||||||
|
|
||||||
template<typename T, typename U = T>
|
|
||||||
struct Pair {
|
|
||||||
T a{};
|
|
||||||
U b{};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
4
deps/ox/src/ox/std/span.hpp
vendored
4
deps/ox/src/ox/std/span.hpp
vendored
@ -228,10 +228,6 @@ class Span {
|
|||||||
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
|
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T &operator[](std::size_t i) noexcept {
|
|
||||||
return m_items[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const T &operator[](std::size_t i) const noexcept {
|
constexpr const T &operator[](std::size_t i) const noexcept {
|
||||||
return m_items[i];
|
return m_items[i];
|
||||||
}
|
}
|
||||||
|
1
deps/ox/src/ox/std/std.hpp
vendored
1
deps/ox/src/ox/std/std.hpp
vendored
@ -35,7 +35,6 @@
|
|||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
#include "new.hpp"
|
#include "new.hpp"
|
||||||
#include "optional.hpp"
|
#include "optional.hpp"
|
||||||
#include "pair.hpp"
|
|
||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
#include "random.hpp"
|
#include "random.hpp"
|
||||||
#include "realstd.hpp"
|
#include "realstd.hpp"
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "palette.hpp"
|
#include "palette.hpp"
|
||||||
#include "tilesheet.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
@ -135,23 +134,12 @@ ox::Error loadBgTileSheet(
|
|||||||
unsigned cbb,
|
unsigned cbb,
|
||||||
TileSheetSet const&set) noexcept;
|
TileSheetSet const&set) noexcept;
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
unsigned cbb,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
ox::Optional<unsigned> const&paletteBank) noexcept;
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
unsigned cbb,
|
unsigned cbb,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
|
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
bool loadDefaultPalette) noexcept;
|
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
ox::Error loadSpriteTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
|
@ -74,15 +74,6 @@ 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]]
|
[[nodiscard]]
|
||||||
constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept {
|
constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept {
|
||||||
if (page < pal.pages.size() && idx < pal.pages[page].size()) [[likely]] {
|
if (page < pal.pages.size() && idx < pal.pages[page].size()) [[likely]] {
|
||||||
|
@ -296,10 +296,9 @@ using TileSheetV4 = TileSheet;
|
|||||||
struct CompactTileSheetV1 {
|
struct CompactTileSheetV1 {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
static constexpr auto Preloadable = true;
|
|
||||||
int8_t bpp = 0;
|
int8_t bpp = 0;
|
||||||
ox::FileAddress defaultPalette;
|
ox::FileAddress defaultPalette;
|
||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
using CompactTileSheet = CompactTileSheetV1;
|
using CompactTileSheet = CompactTileSheetV1;
|
||||||
|
@ -24,6 +24,104 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
constexpr auto SpriteCount = 128;
|
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 {
|
ox::Error initGfx(Context&, InitParams const&) noexcept {
|
||||||
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
||||||
teagba::bgSetSbb(*bgCtl, 28);
|
teagba::bgSetSbb(*bgCtl, 28);
|
||||||
@ -83,48 +181,21 @@ static ox::Error loadTileSheetSet(
|
|||||||
Context &ctx,
|
Context &ctx,
|
||||||
uint16_t *tileMapTargetMem,
|
uint16_t *tileMapTargetMem,
|
||||||
TileSheetSet const&set) noexcept {
|
TileSheetSet const&set) noexcept {
|
||||||
|
auto &rom = ctx.rom();
|
||||||
size_t tileWriteIdx = 0;
|
size_t tileWriteIdx = 0;
|
||||||
for (auto const&entry : set.entries) {
|
for (auto const&entry : set.entries) {
|
||||||
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), entry.tilesheet));
|
oxRequire(tsStat, rom.stat(entry.tilesheet));
|
||||||
if (set.bpp != ts->bpp && ts->bpp == 8) {
|
oxRequire(ts, rom.directAccess(entry.tilesheet));
|
||||||
return OxError(1, "cannot load an 8 BPP tilesheet into a 4 BPP CBB");
|
unsigned tilesheetBpp{};
|
||||||
}
|
GbaTileMapTarget target{
|
||||||
for (auto const&s : entry.sections) {
|
.bpp = tilesheetBpp,
|
||||||
auto const cnt = (static_cast<size_t>(s.tiles) * PixelsPerTile) / (1 + (set.bpp == 4));
|
.defaultPalette = {},
|
||||||
for (size_t i = 0; i < cnt; ++i) {
|
.tileMap = tileMapTargetMem + tileWriteIdx,
|
||||||
auto const srcIdx = static_cast<size_t>(s.begin) + i * 2;
|
.targetBpp = static_cast<unsigned>(set.bpp),
|
||||||
auto const v = static_cast<uint16_t>(
|
.setEntry = &entry,
|
||||||
static_cast<uint16_t>(ts->pixels[srcIdx]) |
|
};
|
||||||
(static_cast<uint16_t>(ts->pixels[srcIdx + 1]) << 8));
|
oxReturnError(ox::readMC({ts, static_cast<std::size_t>(tsStat.size)}, target));
|
||||||
tileMapTargetMem[tileWriteIdx + i] = v;
|
tileWriteIdx += target.tileWriteIdx;
|
||||||
}
|
|
||||||
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -134,8 +205,26 @@ ox::Error loadBgTileSheet(
|
|||||||
unsigned cbb,
|
unsigned cbb,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
ox::Optional<unsigned> const&paletteBank) noexcept {
|
ox::Optional<unsigned> const&paletteBank) noexcept {
|
||||||
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
|
auto &rom = ctx.rom();
|
||||||
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
@ -163,28 +252,25 @@ 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(
|
ox::Error loadSpriteTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
bool loadDefaultPalette) noexcept {
|
bool loadDefaultPalette) noexcept {
|
||||||
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
|
auto &rom = ctx.rom();
|
||||||
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
ox::Error loadSpriteTileSheet(
|
||||||
|
@ -572,28 +572,20 @@ static ox::Result<TileSheetData> buildSetTsd(
|
|||||||
return setTsd;
|
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(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
uint_t cbb,
|
uint_t cbb,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
ox::Optional<unsigned> const&paletteBank) noexcept {
|
ox::Optional<unsigned> const&paletteBank) noexcept {
|
||||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||||
oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||||
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
@ -605,26 +597,19 @@ ox::Error loadBgTileSheet(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
bool loadDefaultPalette) noexcept {
|
|
||||||
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, ts.defaultPalette));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
ox::Error loadSpriteTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
ox::FileAddress const&tilesheetAddr,
|
ox::FileAddress const&tilesheetAddr,
|
||||||
bool loadDefaultPalette) noexcept {
|
bool loadDefaultPalette) noexcept {
|
||||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||||
oxRequire(ts, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||||
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
|
oxRequire(tsd, normalizeTileSheet(*tilesheet));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadSpriteTileSheet(
|
ox::Error loadSpriteTileSheet(
|
||||||
|
@ -15,6 +15,16 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
namespace ig = studio::ig;
|
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 {
|
struct TileSheetEditorConfig {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfig";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfig";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
@ -25,6 +35,16 @@ oxModelBegin(TileSheetEditorConfig)
|
|||||||
oxModelFieldRename(activeSubsheet, active_subsheet)
|
oxModelFieldRename(activeSubsheet, active_subsheet)
|
||||||
oxModelEnd()
|
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(
|
static ox::Vector<uint32_t> normalizePixelSizes(
|
||||||
ox::Vector<uint8_t> const&inPixels,
|
ox::Vector<uint8_t> const&inPixels,
|
||||||
int const bpp) noexcept {
|
int const bpp) noexcept {
|
||||||
@ -100,7 +120,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::Stri
|
|||||||
m_model.paletteChanged.connect(this, &TileSheetEditorImGui::setPaletteSelection);
|
m_model.paletteChanged.connect(this, &TileSheetEditorImGui::setPaletteSelection);
|
||||||
// load config
|
// load config
|
||||||
auto const&config = studio::readConfig<TileSheetEditorConfig>(
|
auto const&config = studio::readConfig<TileSheetEditorConfig>(
|
||||||
keelCtx(m_sctx), itemPath());
|
keelCtx(m_sctx), configName(itemPath()));
|
||||||
if (config.ok()) {
|
if (config.ok()) {
|
||||||
m_model.setActiveSubsheet(validateSubSheetIdx(m_model.img(), config.value.activeSubsheet));
|
m_model.setActiveSubsheet(validateSubSheetIdx(m_model.img(), config.value.activeSubsheet));
|
||||||
}
|
}
|
||||||
@ -517,9 +537,9 @@ ox::Error TileSheetEditorImGui::setPaletteSelection() noexcept {
|
|||||||
|
|
||||||
void TileSheetEditorImGui::setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept {
|
void TileSheetEditorImGui::setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept {
|
||||||
m_model.setActiveSubsheet(path);
|
m_model.setActiveSubsheet(path);
|
||||||
studio::editConfig<TileSheetEditorConfig>(keelCtx(m_sctx), itemPath(),
|
studio::editConfig<TileSheetEditorConfig>(keelCtx(m_sctx), configName(itemPath()),
|
||||||
[&path](TileSheetEditorConfig &config) {
|
[&path](TileSheetEditorConfig *config) {
|
||||||
config.activeSubsheet = std::move(path);
|
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(
|
static ox::Optional<size_t> getPixelIdx(
|
||||||
TileSheet::SubSheet const&ss,
|
TileSheet::SubSheet const&ss,
|
||||||
SubSheetId const id,
|
SubSheetId const id,
|
||||||
size_t &idx,
|
size_t idx,
|
||||||
int8_t const bpp) noexcept {
|
int8_t const bpp) noexcept {
|
||||||
for (auto const&child: ss.subsheets) {
|
for (auto const&child: ss.subsheets) {
|
||||||
if (child.id == id) {
|
if (child.id == id) {
|
||||||
@ -63,12 +63,11 @@ static ox::Optional<size_t> getPixelIdx(
|
|||||||
}
|
}
|
||||||
idx += pixelCnt(child, bpp);
|
idx += pixelCnt(child, bpp);
|
||||||
}
|
}
|
||||||
return ox::Optional<size_t>{};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
|
size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
|
||||||
size_t idx{};
|
auto const out = getPixelIdx(ts.subsheet, id, 0, ts.bpp);
|
||||||
auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp);
|
|
||||||
return out.or_value(0) / PixelsPerTile;
|
return out.or_value(0) / PixelsPerTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,17 +21,6 @@ class AssetManager;
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class AssetRef;
|
class AssetRef;
|
||||||
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(auto const&) noexcept {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr ox::Error repair(auto const&) noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class AssetContainer {
|
class AssetContainer {
|
||||||
@ -226,9 +215,6 @@ class AssetManager {
|
|||||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
||||||
auto &p = m_cache[assetId];
|
auto &p = m_cache[assetId];
|
||||||
oxRequireM(obj, m_loader(assetId));
|
oxRequireM(obj, m_loader(assetId));
|
||||||
if (!valid(obj) && repair(obj)) {
|
|
||||||
return OxError(1, "asset is invalid state and could not be repaired");
|
|
||||||
}
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,8 +200,8 @@ void StudioUI::drawTabs() noexcept {
|
|||||||
if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
|
if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
|
||||||
if (m_activeEditor != e.get()) {
|
if (m_activeEditor != e.get()) {
|
||||||
m_activeEditor = e.get();
|
m_activeEditor = e.get();
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
config.activeTabItemName = m_activeEditor->itemPath();
|
config->activeTabItemName = m_activeEditor->itemPath();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (m_activeEditorUpdatePending == e.get()) {
|
if (m_activeEditorUpdatePending == e.get()) {
|
||||||
@ -255,8 +255,8 @@ void StudioUI::loadModules() noexcept {
|
|||||||
|
|
||||||
void StudioUI::toggleProjectExplorer() noexcept {
|
void StudioUI::toggleProjectExplorer() noexcept {
|
||||||
m_showProjectExplorer = !m_showProjectExplorer;
|
m_showProjectExplorer = !m_showProjectExplorer;
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
config.showProjectExplorer = m_showProjectExplorer;
|
config->showProjectExplorer = m_showProjectExplorer;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,9 +339,9 @@ ox::Error StudioUI::openProjectPath(ox::CRStringView path) noexcept {
|
|||||||
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
||||||
m_openFiles.clear();
|
m_openFiles.clear();
|
||||||
m_editors.clear();
|
m_editors.clear();
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
config.projectPath = ox::String(m_project->projectPath());
|
config->projectPath = ox::String(m_project->projectPath());
|
||||||
config.openFiles.clear();
|
config->openFiles.clear();
|
||||||
});
|
});
|
||||||
return m_projectExplorer.refreshProjectTreeModel();
|
return m_projectExplorer.refreshProjectTreeModel();
|
||||||
}
|
}
|
||||||
@ -392,9 +392,9 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
|||||||
m_activeEditorUpdatePending = editor;
|
m_activeEditorUpdatePending = editor;
|
||||||
}
|
}
|
||||||
// save to config
|
// save to config
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
if (!config.openFiles.contains(path)) {
|
if (!config->openFiles.contains(path)) {
|
||||||
config.openFiles.emplace_back(path);
|
config->openFiles.emplace_back(path);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
@ -406,8 +406,8 @@ ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept {
|
|||||||
}
|
}
|
||||||
std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path));
|
std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path));
|
||||||
// save to config
|
// save to config
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path));
|
std::ignore = config->openFiles.erase(std::remove(config->openFiles.begin(), config->openFiles.end(), path));
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -17,25 +17,13 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
inline ox::String slashesToPct(ox::StringView str) noexcept {
|
|
||||||
auto out = ox::String{str};
|
|
||||||
for (auto&c: out) {
|
|
||||||
if (c == '/' || c == '\\') {
|
|
||||||
c = '%';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::String configPath(keel::Context const&ctx) noexcept;
|
ox::String configPath(keel::Context const&ctx) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> readConfig(keel::Context &ctx, ox::CRStringView name) noexcept {
|
ox::Result<T> readConfig(keel::Context &ctx, ox::CRStringView name) noexcept {
|
||||||
oxAssert(name != "", "Config type has no TypeName");
|
oxAssert(name != "", "Config type has no TypeName");
|
||||||
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
|
auto const path = ox::sfmt("/{}.json", name);
|
||||||
ox::PassThroughFS fs(configPath(ctx));
|
ox::PassThroughFS fs(configPath(ctx));
|
||||||
auto const [buff, err] = fs.read(path);
|
auto const [buff, err] = fs.read(path);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -52,15 +40,15 @@ ox::Result<T> readConfig(keel::Context &ctx) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T const&data) noexcept {
|
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T *data) noexcept {
|
||||||
oxAssert(name != "", "Config type has no TypeName");
|
oxAssert(name != "", "Config type has no TypeName");
|
||||||
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
|
auto const path = ox::sfmt("/{}.json", name);
|
||||||
ox::PassThroughFS fs(configPath(ctx));
|
ox::PassThroughFS fs(configPath(ctx));
|
||||||
if (auto const err = fs.mkdir("/", true)) {
|
if (auto const err = fs.mkdir("/", true)) {
|
||||||
oxErrf("Could not create config directory: {}\n", toStr(err));
|
oxErrf("Could not create config directory: {}\n", toStr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
oxRequireM(buff, ox::writeOC(data));
|
oxRequireM(buff, ox::writeOC(*data));
|
||||||
*buff.back().value = '\n';
|
*buff.back().value = '\n';
|
||||||
if (auto const err = fs.write(path, buff.data(), buff.size())) {
|
if (auto const err = fs.write(path, buff.data(), buff.size())) {
|
||||||
oxErrf("Could not read config file: {}\n", toStr(err));
|
oxErrf("Could not read config file: {}\n", toStr(err));
|
||||||
@ -70,7 +58,7 @@ ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T const&data) n
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error writeConfig(keel::Context &ctx, T const&data) noexcept {
|
ox::Error writeConfig(keel::Context &ctx, T *data) noexcept {
|
||||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||||
return writeConfig(ctx, TypeName, data);
|
return writeConfig(ctx, TypeName, data);
|
||||||
}
|
}
|
||||||
@ -80,7 +68,7 @@ void openConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
|
|||||||
oxAssert(name != "", "Config type has no TypeName");
|
oxAssert(name != "", "Config type has no TypeName");
|
||||||
auto const [c, err] = readConfig<T>(ctx, name);
|
auto const [c, err] = readConfig<T>(ctx, name);
|
||||||
oxLogError(err);
|
oxLogError(err);
|
||||||
f(c);
|
f(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Func>
|
template<typename T, typename Func>
|
||||||
@ -94,8 +82,8 @@ void editConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
|
|||||||
oxAssert(name != "", "Config type has no TypeName");
|
oxAssert(name != "", "Config type has no TypeName");
|
||||||
auto [c, err] = readConfig<T>(ctx, name);
|
auto [c, err] = readConfig<T>(ctx, name);
|
||||||
oxLogError(err);
|
oxLogError(err);
|
||||||
f(c);
|
f(&c);
|
||||||
oxLogError(writeConfig(ctx, name, c));
|
oxLogError(writeConfig(ctx, name, &c));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Func>
|
template<typename T, typename Func>
|
||||||
|
@ -10,7 +10,6 @@ namespace studio {
|
|||||||
|
|
||||||
void TaskRunner::update(turbine::Context &ctx) noexcept {
|
void TaskRunner::update(turbine::Context &ctx) noexcept {
|
||||||
std::ignore = m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(), [&](ox::UPtr<studio::Task> &t) {
|
std::ignore = m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(), [&](ox::UPtr<studio::Task> &t) {
|
||||||
if (!t) { return true; }
|
|
||||||
auto const done = t->update(ctx) == TaskState::Done;
|
auto const done = t->update(ctx) == TaskState::Done;
|
||||||
if (done) {
|
if (done) {
|
||||||
t->finished.emit();
|
t->finished.emit();
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
namespace turbine {
|
namespace turbine {
|
||||||
|
|
||||||
using TimeMs = uint64_t;
|
|
||||||
|
|
||||||
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept;
|
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept;
|
||||||
|
|
||||||
ox::Error run(Context &ctx) noexcept;
|
ox::Error run(Context &ctx) noexcept;
|
||||||
@ -23,7 +21,7 @@ ox::Error run(Context &ctx) noexcept;
|
|||||||
// Returns the number of milliseconds that have passed since the start of the
|
// Returns the number of milliseconds that have passed since the start of the
|
||||||
// program.
|
// program.
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
TimeMs ticksMs(Context const&ctx) noexcept;
|
uint64_t ticksMs(Context const&ctx) noexcept;
|
||||||
|
|
||||||
void requestShutdown(Context &ctx) noexcept;
|
void requestShutdown(Context &ctx) noexcept;
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <keel/keel.hpp>
|
#include <keel/keel.hpp>
|
||||||
#include <turbine/context.hpp>
|
#include <turbine/context.hpp>
|
||||||
#include <turbine/gfx.hpp>
|
#include <turbine/gfx.hpp>
|
||||||
#include <turbine/turbine.hpp>
|
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "turbine.hpp"
|
#include "turbine.hpp"
|
||||||
@ -72,7 +71,7 @@ ox::Result<ContextUPtr> init(
|
|||||||
void shutdown(Context&) noexcept {
|
void shutdown(Context&) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeMs ticksMs(Context const&) noexcept {
|
uint64_t ticksMs(Context const&) noexcept {
|
||||||
return g_timerMs;
|
return g_timerMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <turbine/context.hpp>
|
#include <turbine/context.hpp>
|
||||||
#include <turbine/gfx.hpp>
|
#include <turbine/gfx.hpp>
|
||||||
#include <turbine/event.hpp>
|
#include <turbine/event.hpp>
|
||||||
#include <turbine/turbine.hpp>
|
|
||||||
|
|
||||||
namespace turbine {
|
namespace turbine {
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ class Context {
|
|||||||
struct GLFWwindow *window = nullptr;
|
struct GLFWwindow *window = nullptr;
|
||||||
int refreshWithinMs = 0;
|
int refreshWithinMs = 0;
|
||||||
ox::Vector<gl::Drawer*, 5> drawers;
|
ox::Vector<gl::Drawer*, 5> drawers;
|
||||||
TimeMs startTime = 0;
|
int64_t startTime = 0;
|
||||||
uint64_t wakeupTime = 0;
|
uint64_t wakeupTime = 0;
|
||||||
uint64_t keysDown = 0;
|
uint64_t keysDown = 0;
|
||||||
uint64_t prevFpsCheckTime = 0;
|
uint64_t prevFpsCheckTime = 0;
|
||||||
|
@ -45,8 +45,7 @@ ox::Result<ContextUPtr> init(
|
|||||||
auto ctx = ox::make_unique<Context>();
|
auto ctx = ox::make_unique<Context>();
|
||||||
oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName));
|
oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName));
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
ctx->startTime = static_cast<TimeMs>(
|
ctx->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
|
|
||||||
glfwInit();
|
glfwInit();
|
||||||
oxReturnError(initGfx(*ctx));
|
oxReturnError(initGfx(*ctx));
|
||||||
glfwSetWindowSizeCallback(ctx->window, draw);
|
glfwSetWindowSizeCallback(ctx->window, draw);
|
||||||
@ -109,10 +108,10 @@ void shutdown(Context &ctx) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeMs ticksMs(Context const&ctx) noexcept {
|
uint64_t ticksMs(Context const&ctx) noexcept {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto const now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
auto const now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
return static_cast<TimeMs>(now) - ctx.startTime;
|
return static_cast<uint64_t>(now - ctx.startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool buttonDown(Context const&ctx, Key key) noexcept {
|
bool buttonDown(Context const&ctx, Key key) noexcept {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user