a bit more speedup

This commit is contained in:
2025-10-12 00:33:48 +02:00
parent fc9e85aea0
commit a3b837f329
2 changed files with 38 additions and 19 deletions

View File

@@ -568,7 +568,6 @@ union cart_rtc
} reg; } reg;
uint8_t bytes[5]; uint8_t bytes[5];
}; };
extern "C" uint8_t gb_rom_read(struct gb_s*, const uint_fast32_t);
/** /**
* Emulator context. * Emulator context.
@@ -730,9 +729,14 @@ struct gb_s
/* Implementation defined data. Set to NULL if not required. */ /* Implementation defined data. Set to NULL if not required. */
void *priv; void *priv;
const uint8_t* rom;
} direct; } direct;
}; };
__attribute__((always_inline)) inline uint8_t gb_rom_read(struct gb_s* s, const uint_fast32_t addr) {
return s->direct.rom[addr];
}
#ifndef PEANUT_GB_HEADER_ONLY #ifndef PEANUT_GB_HEADER_ONLY
#define IO_JOYP 0x00 #define IO_JOYP 0x00
@@ -3687,7 +3691,7 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
uint8_t (*gb_cart_ram_read)(struct gb_s*, const uint_fast32_t), uint8_t (*gb_cart_ram_read)(struct gb_s*, const uint_fast32_t),
void (*gb_cart_ram_write)(struct gb_s*, const uint_fast32_t, const uint8_t), void (*gb_cart_ram_write)(struct gb_s*, const uint_fast32_t, const uint8_t),
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t), void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t),
void *priv) void *priv, const uint8_t* rom_data)
{ {
const uint16_t mbc_location = 0x0147; const uint16_t mbc_location = 0x0147;
const uint16_t bank_count_location = 0x0148; const uint16_t bank_count_location = 0x0148;
@@ -3726,6 +3730,7 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
gb->gb_cart_ram_write = gb_cart_ram_write; gb->gb_cart_ram_write = gb_cart_ram_write;
gb->gb_error = gb_error; gb->gb_error = gb_error;
gb->direct.priv = priv; gb->direct.priv = priv;
gb->direct.rom = rom_data;
/* Initialise serial transfer function to NULL. If the front-end does /* Initialise serial transfer function to NULL. If the front-end does
* not provide serial support, Peanut-GB will emulate no cable connected * not provide serial support, Peanut-GB will emulate no cable connected
@@ -3879,7 +3884,7 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
uint8_t (*gb_cart_ram_read)(struct gb_s*, const uint_fast32_t), uint8_t (*gb_cart_ram_read)(struct gb_s*, const uint_fast32_t),
void (*gb_cart_ram_write)(struct gb_s*, const uint_fast32_t, const uint8_t), void (*gb_cart_ram_write)(struct gb_s*, const uint_fast32_t, const uint8_t),
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t), void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t),
void *priv); void *priv, const uint8_t* rom_data);
/** /**
* Executes the emulator and runs for the duration of time equal to one frame. * Executes the emulator and runs for the duration of time equal to one frame.

View File

@@ -76,6 +76,29 @@ static constexpr LUTFull buildNibbleLUT() {
inline constexpr LUTFull kNibbleLUT = buildNibbleLUT(); inline constexpr LUTFull kNibbleLUT = buildNibbleLUT();
static constexpr LUTFull buildFullHeightWideByteLUT() {
LUTFull L{};
for (int yp = 0; yp < 2; ++yp)
for (int xp = 0; xp < 2; ++xp)
for (int p = 0; p < 256; ++p) {
const uint8_t p0 = static_cast<uint8_t>(p & 0x03);
const uint8_t p1 = static_cast<uint8_t>((p >> 2) & 0x03);
const uint8_t p2 = static_cast<uint8_t>((p >> 4) & 0x03);
const uint8_t p3 = static_cast<uint8_t>((p >> 6) & 0x03);
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 uint8_t n0 = makeNibble(p4a, xp, yp);
const uint8_t n1 = makeNibble(p4b, xp, yp);
L[yp][xp][p] = static_cast<uint8_t>((n0 << 4) | (n1 & 0x0F));
}
return L;
}
inline constexpr LUTFull kFullHeightWideByteLUT = buildFullHeightWideByteLUT();
namespace apps { namespace apps {
namespace { namespace {
@@ -869,8 +892,8 @@ private:
} }
std::memset(&gb, 0, sizeof(gb)); std::memset(&gb, 0, sizeof(gb));
const auto initResult = const auto initResult = gb_init(&gb, &GameboyApp::cartRamRead, &GameboyApp::cartRamWrite,
gb_init(&gb, &GameboyApp::cartRamRead, &GameboyApp::cartRamWrite, &GameboyApp::errorCallback, this); &GameboyApp::errorCallback, this, romDataView);
if (initResult != GB_INIT_NO_ERROR) { if (initResult != GB_INIT_NO_ERROR) {
setStatus(initErrorToString(initResult)); setStatus(initErrorToString(initResult));
romData.clear(); romData.clear();
@@ -1276,23 +1299,17 @@ private:
CARDBOY_CHECK(yEnd > yStart); CARDBOY_CHECK(yEnd > yStart);
CARDBOY_CHECK((kFullHeightWideOffsetX % 8) == 0); CARDBOY_CHECK((kFullHeightWideOffsetX % 8) == 0);
const int xParityBase = kFullHeightWideOffsetX & 1;
for (int dstY = yStart; dstY < yEnd; ++dstY) { for (int dstY = yStart; dstY < yEnd; ++dstY) {
const int yParity = dstY & 1; const int yParity = dstY & 1;
int dstX = kFullHeightWideOffsetX; int dstX = kFullHeightWideOffsetX;
for (int srcX = 0; srcX < LCD_WIDTH; srcX += 4) { for (int srcX = 0; srcX < LCD_WIDTH; srcX += 4) {
const uint8_t p0 = pixels[srcX + 0]; const uint8_t packIndex = static_cast<uint8_t>((pixels[srcX + 0]) | ((pixels[srcX + 1]) << 2) |
const uint8_t p1 = pixels[srcX + 1]; ((pixels[srcX + 2]) << 4) | ((pixels[srcX + 3]) << 6));
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 pack = kFullHeightWideByteLUT[yParity][xParityBase][packIndex];
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); fb.drawBits8(dstX, dstY, pack);
dstX += 8; dstX += 8;
@@ -1403,9 +1420,6 @@ private:
} }
}; };
extern "C" __attribute__((always_inline)) uint8_t gb_rom_read(struct gb_s* gb, const uint_fast32_t addr) {
return GameboyApp::romRead(gb, addr);
}
class GameboyAppFactory final : public cardboy::sdk::IAppFactory { class GameboyAppFactory final : public cardboy::sdk::IAppFactory {
public: public:
const char* name() const override { return kGameboyAppName; } const char* name() const override { return kGameboyAppName; }