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; }