/* * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #pragma once #include #include #include #include #include "color.hpp" #include "context.hpp" #include "ptidxconv.hpp" namespace nostalgia::core { extern char charMap[128]; class Drawer { public: virtual ~Drawer() = default; virtual void draw(Context*) noexcept = 0; }; enum class TileSheetSpace { Background, Sprite }; struct NostalgiaPalette { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette"; static constexpr auto TypeVersion = 1; ox::Vector colors; }; struct NostalgiaGraphic { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic"; static constexpr auto TypeVersion = 1; int8_t bpp = 0; // rows and columns are really only used by TileSheetEditor int rows = 1; int columns = 1; ox::FileAddress defaultPalette; NostalgiaPalette pal; ox::Vector pixels; [[nodiscard]] constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept { oxAssert(bpp == 4, "NostalgiaGraphic::getPixel4Bpp: wrong bpp"); const auto idx = ptToIdx(pt, this->columns); if (idx & 1) { return this->pixels[idx / 2]; } else { return this->pixels[idx / 2]; } } [[nodiscard]] constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept { oxAssert(bpp == 8, "NostalgiaGraphic::getPixel8Bpp: wrong bpp"); const auto idx = ptToIdx(pt, this->columns); return this->pixels[idx]; } [[nodiscard]] constexpr auto getPixel(const geo::Point &pt) const noexcept { if (this->bpp == 4) { return getPixel4Bpp(pt); } else { return getPixel8Bpp(pt); } } constexpr void setPixel(const geo::Point &pt, uint8_t palIdx) noexcept { const auto idx = ptToIdx(pt, this->columns); if (bpp == 4) { if (idx & 1) { pixels[idx / 2] &= 0b0000'1111 | (palIdx << 4); } else { pixels[idx / 2] &= 0b1111'0000 | (palIdx); } } else { this->pixels[idx] = palIdx; } } }; oxModelBegin(NostalgiaPalette) oxModelField(colors) oxModelEnd() oxModelBegin(NostalgiaGraphic) oxModelField(bpp) oxModelField(rows) oxModelField(columns) oxModelField(defaultPalette) oxModelField(pal) oxModelField(pixels) oxModelEnd() struct Sprite { unsigned idx = 0; unsigned x = 0; unsigned y = 0; unsigned tileIdx = 0; unsigned spriteShape = 0; unsigned spriteSize = 0; unsigned flipX = 0; }; ox::Error initGfx(Context *ctx) noexcept; void addCustomDrawer(Context *ctx, Drawer *cd) noexcept; void removeCustomDrawer(Context *ctx, Drawer *cd) noexcept; void setWindowTitle(Context *ctx, const char *title) noexcept; void focusWindow(Context *ctx) noexcept; [[nodiscard]] int getScreenWidth(Context *ctx) noexcept; [[nodiscard]] int getScreenHeight(Context *ctx) noexcept; [[nodiscard]] geo::Size getScreenSize(Context *ctx) noexcept; [[nodiscard]] uint8_t bgStatus(Context *ctx) noexcept; void setBgStatus(Context *ctx, uint32_t status) noexcept; bool bgStatus(Context *ctx, unsigned bg) noexcept; void setBgStatus(Context *ctx, unsigned bg, bool status) noexcept; ox::Error initConsole(Context *ctx) noexcept; /** * @param section describes which section of the selected TileSheetSpace to use (e.g. MEM_PALLETE_BG[section]) */ ox::Error loadBgTileSheet(Context *ctx, int section, const ox::FileAddress &tilesheet, const ox::FileAddress &palette = nullptr) noexcept; ox::Error loadSpriteTileSheet(Context *ctx, int section, const ox::FileAddress &tilesheetAddr, const ox::FileAddress &paletteAddr) noexcept; void puts(Context *ctx, int column, int row, const char *str) noexcept; void setTile(Context *ctx, int layer, int column, int row, uint8_t tile) noexcept; void clearTileLayer(Context *ctx, int layer) noexcept; void hideSprite(Context *ctx, unsigned) noexcept; void setSprite(Context *ctx, unsigned idx, unsigned x, unsigned y, unsigned tileIdx, unsigned spriteShape = 0, unsigned spriteSize = 0, unsigned flipX = 0) noexcept; void setSprite(Context *ctx, const Sprite &s) noexcept; }