mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 23:27:49 +01:00
fast wide scale
This commit is contained in:
@@ -245,7 +245,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Mode { Browse, Running };
|
enum class Mode { Browse, Running };
|
||||||
enum class ScaleMode { Original, FullHeight };
|
enum class ScaleMode { Original, FullHeight, FullHeightWide };
|
||||||
|
|
||||||
struct PerfTracker {
|
struct PerfTracker {
|
||||||
enum class CallbackKind { RomRead, CartRamRead, CartRamWrite, LcdDraw, Error };
|
enum class CallbackKind { RomRead, CartRamRead, CartRamWrite, LcdDraw, Error };
|
||||||
@@ -492,10 +492,16 @@ private:
|
|||||||
(((LCD_WIDTH * cardboy::sdk::kDisplayHeight + LCD_HEIGHT / 2) / LCD_HEIGHT) + 7) & ~7;
|
(((LCD_WIDTH * cardboy::sdk::kDisplayHeight + LCD_HEIGHT / 2) / LCD_HEIGHT) + 7) & ~7;
|
||||||
static constexpr int kFullHeightOffsetX = (((cardboy::sdk::kDisplayWidth - kFullHeightScaledWidth) / 2) / 8) * 8;
|
static constexpr int kFullHeightOffsetX = (((cardboy::sdk::kDisplayWidth - kFullHeightScaledWidth) / 2) / 8) * 8;
|
||||||
|
|
||||||
|
static constexpr int kFullHeightWideWidth = LCD_WIDTH * 2;
|
||||||
|
static constexpr int kFullHeightWideOffsetX = (((cardboy::sdk::kDisplayWidth - kFullHeightWideWidth) / 2) / 8) * 8;
|
||||||
|
|
||||||
static_assert(kFullHeightScaledWidth % 8 == 0);
|
static_assert(kFullHeightScaledWidth % 8 == 0);
|
||||||
static_assert(kFullHeightOffsetX % 8 == 0);
|
static_assert(kFullHeightOffsetX % 8 == 0);
|
||||||
static_assert(kOriginalOffsetX % 8 == 0);
|
static_assert(kOriginalOffsetX % 8 == 0);
|
||||||
static_assert(kFullHeightOffsetX + kFullHeightScaledWidth <= cardboy::sdk::kDisplayWidth);
|
static_assert(kFullHeightOffsetX + kFullHeightScaledWidth <= cardboy::sdk::kDisplayWidth);
|
||||||
|
static_assert(kFullHeightWideWidth % 8 == 0);
|
||||||
|
static_assert(kFullHeightWideOffsetX % 8 == 0);
|
||||||
|
static_assert(kFullHeightWideOffsetX + kFullHeightWideWidth <= cardboy::sdk::kDisplayWidth);
|
||||||
|
|
||||||
inline static constexpr std::array<int, LCD_WIDTH + 1> kFullHeightColumnBounds = []() constexpr {
|
inline static constexpr std::array<int, LCD_WIDTH + 1> kFullHeightColumnBounds = []() constexpr {
|
||||||
std::array<int, LCD_WIDTH + 1> bounds{};
|
std::array<int, LCD_WIDTH + 1> bounds{};
|
||||||
@@ -704,12 +710,21 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void toggleScaleMode() {
|
void toggleScaleMode() {
|
||||||
if (scaleMode == ScaleMode::Original)
|
switch (scaleMode) {
|
||||||
scaleMode = ScaleMode::FullHeight;
|
case ScaleMode::Original:
|
||||||
else
|
scaleMode = ScaleMode::FullHeight;
|
||||||
scaleMode = ScaleMode::Original;
|
setStatus("Scale: Full height");
|
||||||
|
break;
|
||||||
|
case ScaleMode::FullHeight:
|
||||||
|
scaleMode = ScaleMode::FullHeightWide;
|
||||||
|
setStatus("Scale: Full height 2x");
|
||||||
|
break;
|
||||||
|
case ScaleMode::FullHeightWide:
|
||||||
|
scaleMode = ScaleMode::Original;
|
||||||
|
setStatus("Scale: Original");
|
||||||
|
break;
|
||||||
|
}
|
||||||
frameDirty = true;
|
frameDirty = true;
|
||||||
setStatus(scaleMode == ScaleMode::FullHeight ? "Scale: Full height" : "Scale: Original");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleBrowserInput(const InputState& input) {
|
void handleBrowserInput(const InputState& input) {
|
||||||
@@ -980,11 +995,23 @@ private:
|
|||||||
char fpsValueBuf[16];
|
char fpsValueBuf[16];
|
||||||
std::snprintf(fpsValueBuf, sizeof(fpsValueBuf), "%u", static_cast<unsigned>(fpsCurrent));
|
std::snprintf(fpsValueBuf, sizeof(fpsValueBuf), "%u", static_cast<unsigned>(fpsCurrent));
|
||||||
const std::string fpsValue(fpsValueBuf);
|
const std::string fpsValue(fpsValueBuf);
|
||||||
const std::string fpsLabel = "FPS";
|
const std::string fpsLabel = "FPS";
|
||||||
const std::string fpsText = fpsValue + " FPS";
|
const std::string fpsText = fpsValue + " FPS";
|
||||||
const std::string scaleHint = (scaleMode == ScaleMode::FullHeight) ? "START+B NORMAL" : "START+B SCALE";
|
|
||||||
|
|
||||||
if (scaleMode == ScaleMode::FullHeight) {
|
std::string scaleHint;
|
||||||
|
switch (scaleMode) {
|
||||||
|
case ScaleMode::Original:
|
||||||
|
scaleHint = "START+B FULL";
|
||||||
|
break;
|
||||||
|
case ScaleMode::FullHeight:
|
||||||
|
scaleHint = "START+B WIDE";
|
||||||
|
break;
|
||||||
|
case ScaleMode::FullHeightWide:
|
||||||
|
scaleHint = "START+B NORMAL";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaleMode == ScaleMode::FullHeight || scaleMode == ScaleMode::FullHeightWide) {
|
||||||
const int textScale = 1;
|
const int textScale = 1;
|
||||||
const int screenHeight = framebuffer.height();
|
const int screenHeight = framebuffer.height();
|
||||||
const int screenWidth = framebuffer.width();
|
const int screenWidth = framebuffer.width();
|
||||||
@@ -1241,6 +1268,40 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawLineFullHeightWide(GameboyApp& self, const uint8_t pixels[160], int srcLine) {
|
||||||
|
Framebuffer& fb = self.framebuffer;
|
||||||
|
const int yStart = kFullHeightRowBounds[static_cast<std::size_t>(srcLine)];
|
||||||
|
const int yEnd = kFullHeightRowBounds[static_cast<std::size_t>(srcLine) + 1];
|
||||||
|
|
||||||
|
CARDBOY_CHECK(yEnd > yStart);
|
||||||
|
CARDBOY_CHECK((kFullHeightWideOffsetX % 8) == 0);
|
||||||
|
|
||||||
|
for (int dstY = yStart; dstY < yEnd; ++dstY) {
|
||||||
|
const int yParity = dstY & 1;
|
||||||
|
int dstX = kFullHeightWideOffsetX;
|
||||||
|
|
||||||
|
for (int srcX = 0; srcX < LCD_WIDTH; srcX += 4) {
|
||||||
|
const uint8_t p0 = pixels[srcX + 0];
|
||||||
|
const uint8_t p1 = pixels[srcX + 1];
|
||||||
|
const uint8_t p2 = pixels[srcX + 2];
|
||||||
|
const uint8_t p3 = pixels[srcX + 3];
|
||||||
|
|
||||||
|
const uint8_t p4a = static_cast<uint8_t>(p0 | (p0 << 2) | (p1 << 4) | (p1 << 6));
|
||||||
|
const uint8_t p4b = static_cast<uint8_t>(p2 | (p2 << 2) | (p3 << 4) | (p3 << 6));
|
||||||
|
|
||||||
|
const int xParity = dstX & 1;
|
||||||
|
const uint8_t n0 = kNibbleLUT[yParity][xParity][p4a];
|
||||||
|
const uint8_t n1 = kNibbleLUT[yParity][xParity][p4b];
|
||||||
|
const uint8_t pack = static_cast<uint8_t>((n0 << 4) | (n1 & 0x0F));
|
||||||
|
|
||||||
|
fb.drawBits8(dstX, dstY, pack);
|
||||||
|
dstX += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
CARDBOY_CHECK(dstX == kFullHeightWideOffsetX + kFullHeightWideWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static uint8_t romRead(struct gb_s* gb, const uint_fast32_t addr) {
|
static uint8_t romRead(struct gb_s* gb, const uint_fast32_t addr) {
|
||||||
@@ -1297,10 +1358,18 @@ private:
|
|||||||
Framebuffer& fb = self->framebuffer;
|
Framebuffer& fb = self->framebuffer;
|
||||||
fb.frameReady();
|
fb.frameReady();
|
||||||
|
|
||||||
if (self->scaleMode == ScaleMode::FullHeight)
|
switch (self->scaleMode) {
|
||||||
drawLineFullHeight(*self, pixels, static_cast<int>(line));
|
case ScaleMode::FullHeight:
|
||||||
else
|
drawLineFullHeight(*self, pixels, static_cast<int>(line));
|
||||||
drawLineOriginal(*self, pixels, static_cast<int>(line));
|
break;
|
||||||
|
case ScaleMode::FullHeightWide:
|
||||||
|
drawLineFullHeightWide(*self, pixels, static_cast<int>(line));
|
||||||
|
break;
|
||||||
|
case ScaleMode::Original:
|
||||||
|
default:
|
||||||
|
drawLineOriginal(*self, pixels, static_cast<int>(line));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* initErrorToString(enum gb_init_error_e err) {
|
static const char* initErrorToString(enum gb_init_error_e err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user