mirror of
https://github.com/OpenEmu/mGBA-Core.git
synced 2025-11-01 11:06:53 +00:00
Update to mGBA 0.8.2
This commit is contained in:
+1
-1
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.8.1</string>
|
||||
<string>0.8.2</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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]))
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+9
-2
@@ -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;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+4
-1
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -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");
|
||||
|
||||
+5
-8
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@
|
||||
#include <mgba/internal/gba/serialize.h>
|
||||
|
||||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/bios.h>
|
||||
#include <mgba/internal/gba/io.h>
|
||||
#include <mgba/internal/gba/rr/rr.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user