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:
|
||||
enum class Mode { Browse, Running };
|
||||
enum class ScaleMode { Original, FullHeight };
|
||||
enum class ScaleMode { Original, FullHeight, FullHeightWide };
|
||||
|
||||
struct PerfTracker {
|
||||
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;
|
||||
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(kFullHeightOffsetX % 8 == 0);
|
||||
static_assert(kOriginalOffsetX % 8 == 0);
|
||||
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 {
|
||||
std::array<int, LCD_WIDTH + 1> bounds{};
|
||||
@@ -704,12 +710,21 @@ private:
|
||||
}
|
||||
|
||||
void toggleScaleMode() {
|
||||
if (scaleMode == ScaleMode::Original)
|
||||
scaleMode = ScaleMode::FullHeight;
|
||||
else
|
||||
scaleMode = ScaleMode::Original;
|
||||
switch (scaleMode) {
|
||||
case ScaleMode::Original:
|
||||
scaleMode = ScaleMode::FullHeight;
|
||||
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;
|
||||
setStatus(scaleMode == ScaleMode::FullHeight ? "Scale: Full height" : "Scale: Original");
|
||||
}
|
||||
|
||||
void handleBrowserInput(const InputState& input) {
|
||||
@@ -980,11 +995,23 @@ private:
|
||||
char fpsValueBuf[16];
|
||||
std::snprintf(fpsValueBuf, sizeof(fpsValueBuf), "%u", static_cast<unsigned>(fpsCurrent));
|
||||
const std::string fpsValue(fpsValueBuf);
|
||||
const std::string fpsLabel = "FPS";
|
||||
const std::string fpsText = fpsValue + " FPS";
|
||||
const std::string scaleHint = (scaleMode == ScaleMode::FullHeight) ? "START+B NORMAL" : "START+B SCALE";
|
||||
const std::string fpsLabel = "FPS";
|
||||
const std::string fpsText = fpsValue + " FPS";
|
||||
|
||||
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 screenHeight = framebuffer.height();
|
||||
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:
|
||||
static uint8_t romRead(struct gb_s* gb, const uint_fast32_t addr) {
|
||||
@@ -1297,10 +1358,18 @@ private:
|
||||
Framebuffer& fb = self->framebuffer;
|
||||
fb.frameReady();
|
||||
|
||||
if (self->scaleMode == ScaleMode::FullHeight)
|
||||
drawLineFullHeight(*self, pixels, static_cast<int>(line));
|
||||
else
|
||||
drawLineOriginal(*self, pixels, static_cast<int>(line));
|
||||
switch (self->scaleMode) {
|
||||
case ScaleMode::FullHeight:
|
||||
drawLineFullHeight(*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) {
|
||||
|
||||
Reference in New Issue
Block a user