diff --git a/Info.plist b/Info.plist
index 3ae5a7b..67f939b 100644
--- a/Info.plist
+++ b/Info.plist
@@ -17,7 +17,7 @@
CFBundleSignature
????
CFBundleVersion
- 0.8.1
+ 0.8.2
NSPrincipalClass
OEGameCoreController
OEGameCoreClass
diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h
index f8b705e..1934ed8 100644
--- a/include/mgba-util/common.h
+++ b/include/mgba-util/common.h
@@ -121,7 +121,7 @@ typedef intptr_t ssize_t;
// newlib doesn't support %z properly by default
#define PRIz ""
#elif defined(_WIN64)
-#define PRIz "ll"
+#define PRIz "I64"
#elif defined(_WIN32)
#define PRIz ""
#else
diff --git a/include/mgba/internal/arm/arm.h b/include/mgba/internal/arm/arm.h
index a1f040c..b326891 100644
--- a/include/mgba/internal/arm/arm.h
+++ b/include/mgba/internal/arm/arm.h
@@ -70,7 +70,7 @@ struct ARMCore;
union PSR {
struct {
-#if defined(__POWERPC__) || defined(__PPC__)
+#if defined(__BIG_ENDIAN__)
unsigned n : 1;
unsigned z : 1;
unsigned c : 1;
diff --git a/include/mgba/internal/gba/sio.h b/include/mgba/internal/gba/sio.h
index df4cd2f..7a4e3ec 100644
--- a/include/mgba/internal/gba/sio.h
+++ b/include/mgba/internal/gba/sio.h
@@ -47,7 +47,7 @@ DECL_BIT(GBASIOMultiplayer, Slave, 2);
DECL_BIT(GBASIOMultiplayer, Ready, 3);
DECL_BITS(GBASIOMultiplayer, Id, 4, 2);
DECL_BIT(GBASIOMultiplayer, Error, 6);
-DECL_BIT(GBASIOMultiplayer, Busy, 8);
+DECL_BIT(GBASIOMultiplayer, Busy, 7);
DECL_BIT(GBASIOMultiplayer, Irq, 14);
struct GBASIODriverSet {
diff --git a/src/arm/debugger/debugger.c b/src/arm/debugger/debugger.c
index 11df366..7449ece 100644
--- a/src/arm/debugger/debugger.c
+++ b/src/arm/debugger/debugger.c
@@ -171,7 +171,7 @@ ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, uint32_t a
ssize_t id = debugger->nextId;
++debugger->nextId;
breakpoint->d.id = id;
- breakpoint->d.address = address;
+ breakpoint->d.address = address & ~1; // Clear Thumb bit since it's not part of a valid address
breakpoint->d.segment = -1;
breakpoint->d.condition = NULL;
breakpoint->d.type = BREAKPOINT_SOFTWARE;
@@ -187,6 +187,7 @@ static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struc
ssize_t id = debugger->nextId;
++debugger->nextId;
breakpoint->d = *info;
+ breakpoint->d.address &= ~1; // Clear Thumb bit since it's not part of a valid address
breakpoint->d.id = id;
if (info->type == BREAKPOINT_SOFTWARE) {
// TODO
diff --git a/src/arm/decoder.c b/src/arm/decoder.c
index 02dc09d..b95ff11 100644
--- a/src/arm/decoder.c
+++ b/src/arm/decoder.c
@@ -343,15 +343,25 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
case ARM_MN_ADD:
case ARM_MN_ADC:
case ARM_MN_AND:
+ case ARM_MN_ASR:
case ARM_MN_BIC:
case ARM_MN_EOR:
+ case ARM_MN_LSL:
+ case ARM_MN_LSR:
+ case ARM_MN_MLA:
case ARM_MN_MOV:
+ case ARM_MN_MUL:
case ARM_MN_MVN:
case ARM_MN_ORR:
+ case ARM_MN_ROR:
case ARM_MN_RSB:
case ARM_MN_RSC:
case ARM_MN_SBC:
+ case ARM_MN_SMLAL:
+ case ARM_MN_SMULL:
case ARM_MN_SUB:
+ case ARM_MN_UMLAL:
+ case ARM_MN_UMULL:
if (info->affectsCPSR && info->execMode == MODE_ARM) {
flags = "s";
}
diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c
index 15f845a..edd15fe 100644
--- a/src/arm/isa-thumb.c
+++ b/src/arm/isa-thumb.c
@@ -157,6 +157,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSL2,
cpu->gprs[rd] = 0;
}
}
+ ++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2,
@@ -174,6 +175,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(LSR2,
cpu->gprs[rd] = 0;
}
}
+ ++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
@@ -191,6 +193,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ASR2,
}
}
}
+ ++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd]))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC,
@@ -215,6 +218,7 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ROR,
cpu->cpsr.c = ARM_SIGN(cpu->gprs[rd]);
}
}
+ ++currentCycles;
THUMB_NEUTRAL_S( , , cpu->gprs[rd]);)
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(TST, int32_t aluOut = cpu->gprs[rd] & cpu->gprs[rn]; THUMB_NEUTRAL_S(cpu->gprs[rd], cpu->gprs[rn], aluOut))
DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(NEG, THUMB_SUBTRACTION(cpu->gprs[rd], 0, cpu->gprs[rn]))
diff --git a/src/core/core.c b/src/core/core.c
index 79723c4..e6b7b5c 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -370,7 +370,7 @@ bool mCoreLoadELF(struct mCore* core, struct ELF* elf) {
Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i);
void* block = mCoreGetMemoryBlock(core, phdr->p_paddr, &bsize);
char* bytes = ELFBytes(elf, &esize);
- if (block && bsize >= phdr->p_filesz && bsize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) {
+ if (block && bsize >= phdr->p_filesz && esize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) {
memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz);
} else {
return false;
diff --git a/src/gb/gb.c b/src/gb/gb.c
index 1d73937..461b574 100644
--- a/src/gb/gb.c
+++ b/src/gb/gb.c
@@ -478,6 +478,7 @@ void GBReset(struct SM83Core* cpu) {
void GBSkipBIOS(struct GB* gb) {
struct SM83Core* cpu = gb->cpu;
+ const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
int nextDiv = 0;
switch (gb->model) {
@@ -539,9 +540,15 @@ void GBSkipBIOS(struct GB* gb) {
cpu->a = 0x11;
cpu->f.packed = 0x80;
cpu->c = 0;
- cpu->e = 0x08;
cpu->h = 0;
- cpu->l = 0x7C;
+ if (cart->cgb & 0x80) {
+ cpu->d = 0xFF;
+ cpu->e = 0x56;
+ cpu->l = 0x0D;
+ } else {
+ cpu->e = 0x08;
+ cpu->l = 0x7C;
+ }
gb->timer.internalDiv = 0x1EA;
nextDiv = 0xC;
break;
diff --git a/src/gb/io.c b/src/gb/io.c
index 155c2c6..ecfa648 100644
--- a/src/gb/io.c
+++ b/src/gb/io.c
@@ -203,7 +203,7 @@ void GBIOReset(struct GB* gb) {
GBIOWrite(gb, REG_UNK4C, 0);
GBIOWrite(gb, REG_JOYP, 0xFF);
GBIOWrite(gb, REG_VBK, 0);
- GBIOWrite(gb, REG_BCPS, 0);
+ GBIOWrite(gb, REG_BCPS, 0x80);
GBIOWrite(gb, REG_OCPS, 0);
GBIOWrite(gb, REG_SVBK, 1);
GBIOWrite(gb, REG_HDMA1, 0xFF);
diff --git a/src/gb/mbc.c b/src/gb/mbc.c
index 6efe8b6..be03f15 100644
--- a/src/gb/mbc.c
+++ b/src/gb/mbc.c
@@ -518,7 +518,7 @@ static uint8_t _GBMBC2Read(struct GBMemory* memory, uint16_t address) {
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
- int bank = value & 0x7F;
+ int bank = value;
switch (address >> 13) {
case 0x0:
switch (value) {
@@ -536,6 +536,9 @@ void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
}
break;
case 0x1:
+ if (gb->memory.romSize < GB_SIZE_CART_BANK0 * 0x80) {
+ bank &= 0x7F;
+ }
if (!bank) {
++bank;
}
diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c
index 661a436..4d3f8b2 100644
--- a/src/gb/renderers/software.c
+++ b/src/gb/renderers/software.c
@@ -705,7 +705,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
case SGB_PAL_TRN:
case SGB_CHR_TRN:
case SGB_PCT_TRN:
- if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
+ case SGB_ATRC_EN:
+ case SGB_MASK_EN:
+ if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) {
// Make sure every buffer sees this if we're multibuffering
_regenerateSGBBorder(softwareRenderer);
}
diff --git a/src/gba/bios.c b/src/gba/bios.c
index a264354..3045fb4 100644
--- a/src/gba/bios.c
+++ b/src/gba/bios.c
@@ -177,6 +177,9 @@ static void _RegisterRamReset(struct GBA* gba) {
cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0);
cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0);
}
+ if (registers & 0x9C) {
+ gba->video.renderer->reset(gba->video.renderer);
+ }
}
static void _BgAffineSet(struct GBA* gba) {
diff --git a/src/gba/core.c b/src/gba/core.c
index 5d027c0..cf402e2 100644
--- a/src/gba/core.c
+++ b/src/gba/core.c
@@ -526,7 +526,7 @@ static void _GBACoreReset(struct mCore* core) {
if (gbacore->renderer.outputBuffer) {
renderer = &gbacore->renderer.d;
}
- int fakeBool;
+ int fakeBool ATTRIBUTE_UNUSED;
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
renderer = &gbacore->glRenderer.d;
@@ -616,7 +616,8 @@ static void _GBACoreReset(struct mCore* core) {
static void _GBACoreRunFrame(struct mCore* core) {
struct GBA* gba = core->board;
int32_t frameCounter = gba->video.frameCounter;
- while (gba->video.frameCounter == frameCounter) {
+ uint32_t startCycle = mTimingCurrentTime(&gba->timing);
+ while (gba->video.frameCounter == frameCounter && mTimingCurrentTime(&gba->timing) - startCycle < VIDEO_TOTAL_LENGTH + VIDEO_HORIZONTAL_LENGTH) {
ARMRunLoop(core->cpu);
}
}
diff --git a/src/gba/gba.c b/src/gba/gba.c
index 769e85b..43fe7cc 100644
--- a/src/gba/gba.c
+++ b/src/gba/gba.c
@@ -433,7 +433,7 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) {
bool GBALoadSave(struct GBA* gba, struct VFile* sav) {
GBASavedataInit(&gba->memory.savedata, sav);
- return true;
+ return sav;
}
void GBAYankROM(struct GBA* gba) {
@@ -445,6 +445,10 @@ void GBAYankROM(struct GBA* gba) {
void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
gba->biosVf = vf;
+ if (vf->size(vf) != SIZE_BIOS) {
+ mLOG(GBA, WARN, "Incorrect BIOS size");
+ return;
+ }
uint32_t* bios = vf->map(vf, SIZE_BIOS, MAP_READ);
if (!bios) {
mLOG(GBA, WARN, "Couldn't map BIOS");
diff --git a/src/gba/io.c b/src/gba/io.c
index 65cf1e6..a5e7656 100644
--- a/src/gba/io.c
+++ b/src/gba/io.c
@@ -971,16 +971,13 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
for (i = 0; i < 4; ++i) {
LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
- if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
- // Overwrite invalid values in savestate
- gba->timers[i].lastEvent = 0;
- } else {
- LOAD_32(when, 0, &state->timers[i].lastEvent);
- gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
- }
+ LOAD_32(when, 0, &state->timers[i].lastEvent);
+ gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
LOAD_32(when, 0, &state->timers[i].nextEvent);
- if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
+ if ((i < 1 || !GBATimerFlagsIsCountUp(gba->timers[i].flags)) && GBATimerFlagsIsEnable(gba->timers[i].flags)) {
mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
+ } else {
+ gba->timers[i].event.when = when + mTimingCurrentTime(&gba->timing);
}
LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
diff --git a/src/gba/overrides.c b/src/gba/overrides.c
index 675b2d4..a8e21ca 100644
--- a/src/gba/overrides.c
+++ b/src/gba/overrides.c
@@ -66,6 +66,13 @@ static const struct GBACartridgeOverride _overrides[] = {
// Koro Koro Puzzle - Happy Panechu!
{ "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
+ // Legendz - Yomigaeru Shiren no Shima
+ { "BLJJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
+ { "BLJK", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
+
+ // Legendz - Sign of Nekuromu
+ { "BLVJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
+
// Mega Man Battle Network
{ "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E, false },
diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c
index 7f55333..7376b6d 100644
--- a/src/gba/renderers/gl.c
+++ b/src/gba/renderers/gl.c
@@ -1651,10 +1651,6 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
unsigned charBase = (BASE_TILE >> 1) + (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x10;
int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> 3) : (0x20 >> GBAObjAttributesAGet256Color(sprite->a));
- if (spriteY + height >= 256) {
- spriteY -= 256;
- }
-
int totalWidth = width;
int totalHeight = height;
if (GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesAIsDoubleSize(sprite->a)) {
@@ -1662,6 +1658,10 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
totalHeight <<= 1;
}
+ if (spriteY + totalHeight >= 256) {
+ spriteY -= 256;
+ }
+
const struct GBAVideoGLShader* shader = &renderer->objShader[GBAObjAttributesAGet256Color(sprite->a)];
const GLuint* uniforms = shader->uniforms;
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]);
@@ -1721,7 +1721,9 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
glUniform4i(uniforms[GBA_GL_OBJ_MOSAIC], 0, 0, 0, 0);
}
glStencilFunc(GL_ALWAYS, 1, 1);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ if (GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN || GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
shader = &renderer->objShader[2];
uniforms = shader->uniforms;
diff --git a/src/gba/renderers/software-mode0.c b/src/gba/renderers/software-mode0.c
index 9c5697e..6196e1e 100644
--- a/src/gba/renderers/software-mode0.c
+++ b/src/gba/renderers/software-mode0.c
@@ -329,8 +329,56 @@
}
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \
+ x = inX & 7; \
+ if (mosaicWait) { \
+ int baseX = x - (mosaicH - mosaicWait); \
+ if (baseX < 0) { \
+ int disturbX = (16 + baseX) >> 3; \
+ inX -= disturbX << 3; \
+ localX = tileX * 8 + inX; \
+ BACKGROUND_TEXT_SELECT_CHARACTER; \
+ localY = inY & 0x7; \
+ if (GBA_TEXT_MAP_VFLIP(mapData)) { \
+ localY = 7 - localY; \
+ } \
+ baseX -= disturbX << 3; \
+ inX += disturbX << 3; \
+ } else { \
+ localX = tileX * 8 + inX; \
+ BACKGROUND_TEXT_SELECT_CHARACTER; \
+ localY = inY & 0x7; \
+ if (GBA_TEXT_MAP_VFLIP(mapData)) { \
+ localY = 7 - localY; \
+ } \
+ } \
+ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
+ if (UNLIKELY(charBase >= 0x10000)) { \
+ carryData = 0; \
+ } else { \
+ LOAD_32(tileData, charBase, vram); \
+ if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
+ if (x >= 4) { \
+ LOAD_32(tileData, charBase + 4, vram); \
+ tileData >>= (x - 4) * 8; \
+ } else { \
+ LOAD_32(tileData, charBase, vram); \
+ tileData >>= x * 8; \
+ } \
+ } else { \
+ if (x >= 4) { \
+ LOAD_32(tileData, charBase, vram); \
+ tileData >>= (7 - x) * 8; \
+ } else { \
+ LOAD_32(tileData, charBase + 4, vram); \
+ tileData >>= (3 - x) * 8; \
+ } \
+ } \
+ tileData &= 0xFF; \
+ carryData = tileData; \
+ } \
+ } \
localX = tileX * 8 + inX; \
- for (; tileX < tileEnd; ++tileX) { \
+ for (; length; ++tileX) { \
mapData = background->mapCache[(localX >> 3) & 0x3F]; \
localX += 8; \
localY = inY & 0x7; \
@@ -339,7 +387,7 @@
} \
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
tileData = carryData; \
- for (x = 0; x < 8; ++x) { \
+ for (x = 0; x < 8 && length; ++x, --length) { \
if (!mosaicWait) { \
if (UNLIKELY(charBase >= 0x10000)) { \
carryData = 0; \
diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c
index d49142e..4202112 100644
--- a/src/gba/renderers/software-obj.c
+++ b/src/gba/renderers/software-obj.c
@@ -9,7 +9,6 @@
SPRITE_YBASE_ ## DEPTH(inY); \
unsigned tileData; \
for (; outX < condition; ++outX, inX += xOffset) { \
- renderer->spriteCyclesRemaining -= 1; \
SPRITE_XBASE_ ## DEPTH(inX); \
SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(inX); \
}
@@ -33,7 +32,6 @@
unsigned widthMask = ~(width - 1); \
unsigned heightMask = ~(height - 1); \
for (; outX < condition; ++outX, ++inX) { \
- renderer->spriteCyclesRemaining -= 2; \
xAccum += mat.a; \
yAccum += mat.c; \
int localX = xAccum >> 8; \
@@ -55,7 +53,6 @@
int localX = xAccum >> 8; \
int localY = yAccum >> 8; \
for (; outX < condition; ++outX, ++inX) { \
- renderer->spriteCyclesRemaining -= 2; \
xAccum += mat.a; \
yAccum += mat.c; \
\
@@ -168,7 +165,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
int variant = (renderer->target1Obj || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) &&
GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) &&
(renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
- if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT || objwinSlowPath) {
+ if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT || (renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || objwinSlowPath) {
int target2 = renderer->target2Bd;
target2 |= renderer->bg[0].target2;
target2 |= renderer->bg[1].target2;
@@ -224,7 +221,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
int mosaicH = 1;
if (GBAObjAttributesAIsMosaic(sprite->a)) {
mosaicH = GBAMosaicControlGetObjH(renderer->mosaic) + 1;
- if (condition % mosaicH) {
+ if (condition != end && condition % mosaicH) {
condition += mosaicH - (condition % mosaicH);
}
}
@@ -272,7 +269,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
if (outX < start || outX >= condition) {
return 0;
}
- renderer->spriteCyclesRemaining -= 10;
if (!GBAObjAttributesAIs256Color(sprite->a)) {
palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4];
@@ -306,9 +302,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
SPRITE_TRANSFORMED_LOOP(256, NORMAL);
}
}
- if (end == GBA_VIDEO_HORIZONTAL_PIXELS && x + totalWidth > GBA_VIDEO_HORIZONTAL_PIXELS) {
- renderer->spriteCyclesRemaining -= (x + totalWidth - GBA_VIDEO_HORIZONTAL_PIXELS) * 2;
- }
} else {
int outX = x >= start ? x : start;
int condition = x + width;
@@ -366,9 +359,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
SPRITE_NORMAL_LOOP(256, NORMAL);
}
}
- if (end == GBA_VIDEO_HORIZONTAL_PIXELS && x + width > GBA_VIDEO_HORIZONTAL_PIXELS) {
- renderer->spriteCyclesRemaining -= x + width - GBA_VIDEO_HORIZONTAL_PIXELS;
- }
}
return 1;
}
diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c
index 00a76cf..9705d84 100644
--- a/src/gba/renderers/video-software.c
+++ b/src/gba/renderers/video-software.c
@@ -845,12 +845,10 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
}
}
for (w = 0; w < renderer->nWindows; ++w) {
- if (renderer->spriteCyclesRemaining <= 0) {
- break;
- }
renderer->currentWindow = renderer->windows[w].control;
renderer->start = renderer->end;
renderer->end = renderer->windows[w].endX;
+ // TODO: partial sprite drawing
if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed) && !GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
continue;
}
@@ -858,6 +856,12 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, sprite->index, localY);
spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c);
}
+ int cycles = GBAVideoObjSizes[GBAObjAttributesAGetShape(sprite->obj.a) * 4 + GBAObjAttributesBGetSize(sprite->obj.b)][0];
+ if (GBAObjAttributesAIsTransformed(sprite->obj.a)) {
+ cycles <<= GBAObjAttributesAGetDoubleSize(sprite->obj.a) + 1;
+ cycles += 10;
+ }
+ renderer->spriteCyclesRemaining -= cycles;
if (renderer->spriteCyclesRemaining <= 0) {
break;
}
diff --git a/src/gba/serialize.c b/src/gba/serialize.c
index 60b8524..64104ba 100644
--- a/src/gba/serialize.c
+++ b/src/gba/serialize.c
@@ -6,6 +6,7 @@
#include
#include
+#include
#include
#include
@@ -99,7 +100,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
mLOG(GBA_STATE, WARN, "Savestate created using a different version of the BIOS: expected %08X, got %08X", gba->biosChecksum, ucheck);
uint32_t pc;
LOAD_32(pc, ARM_PC * sizeof(state->cpu.gprs[0]), state->cpu.gprs);
- if (pc < SIZE_BIOS && pc >= 0x20) {
+ if ((ucheck == GBA_BIOS_CHECKSUM || gba->biosChecksum == GBA_BIOS_CHECKSUM) && pc < SIZE_BIOS && pc >= 0x20) {
error = true;
}
}
diff --git a/src/gba/sio.c b/src/gba/sio.c
index 95e8603..a153cb1 100644
--- a/src/gba/sio.c
+++ b/src/gba/sio.c
@@ -75,10 +75,13 @@ void GBASIODeinit(struct GBASIO* sio) {
}
void GBASIOReset(struct GBASIO* sio) {
- GBASIODeinit(sio);
+ if (sio->activeDriver && sio->activeDriver->unload) {
+ sio->activeDriver->unload(sio->activeDriver);
+ }
sio->rcnt = RCNT_INITIAL;
sio->siocnt = 0;
sio->mode = -1;
+ sio->activeDriver = NULL;
_switchMode(sio);
}
diff --git a/src/util/table.c b/src/util/table.c
index 20f4e15..f4a8555 100644
--- a/src/util/table.c
+++ b/src/util/table.c
@@ -187,7 +187,9 @@ void HashTableInsert(struct Table* table, const char* key, void* value) {
struct TableList* list;
TABLE_LOOKUP_START(HASH_TABLE_COMPARATOR, list, hash) {
if (value != lookupResult->value) {
- table->deinitializer(lookupResult->value);
+ if (table->deinitializer) {
+ table->deinitializer(lookupResult->value);
+ }
lookupResult->value = value;
}
return;
diff --git a/src/util/vfs/vfs-lzma.c b/src/util/vfs/vfs-lzma.c
index d56883c..a1c259e 100644
--- a/src/util/vfs/vfs-lzma.c
+++ b/src/util/vfs/vfs-lzma.c
@@ -105,6 +105,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
if (res != SZ_OK) {
SzArEx_Free(&vd->db, &vd->allocImp);
File_Close(&vd->archiveStream.file);
+ free(vd->lookStream.buf);
free(vd);
return 0;
}