Merge remote-tracking branch 'upstream/0.6'

This commit is contained in:
Sérgio Benjamim 2017-12-07 22:55:22 -02:00
commit 17ba655edd
15 changed files with 209 additions and 53 deletions

View File

@ -3,6 +3,14 @@ Bugfixes:
- GBA Video: Force align 256-color tiles
- GBA DMA: ROM reads are forced to increment
- GB Video: Only trigger STAT write IRQs when screen is on (fixes mgba.io/i/912)
- GBA Cheats: Fix PARv3 slide codes (fixes mgba.io/i/919)
- GBA Video: OBJWIN can change blend params after OBJ is drawn (fixes mgba.io/i/921)
- GBA Savedata: Fix crash when resizing flash
- GB Memory: HDMAs should not start when LCD is off (fixes mgba.io/i/310)
- GBA Cheats: Fix slide codes not initializing properly
Misc:
- GBA: Improve multiboot image detection
- GB MBC: Remove erroneous bank 0 wrapping
0.6.1: (2017-10-01)
Bugfixes:

View File

@ -177,7 +177,7 @@ int GBCurrentSegment(struct LR35902Core* cpu, uint16_t address);
uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment);
void GBMemoryDMA(struct GB* gb, uint16_t base);
void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value);
uint8_t GBMemoryWriteHDMA5(struct GB* gb, uint8_t value);
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old, int segment);

View File

@ -63,7 +63,7 @@ enum GBAActionReplay3Condition {
PAR3_COND_GT = 0x20000000,
PAR3_COND_ULT = 0x28000000,
PAR3_COND_UGT = 0x30000000,
PAR3_COND_LAND = 0x38000000,
PAR3_COND_AND = 0x38000000,
};
enum GBAActionReplay3Width {

View File

@ -410,8 +410,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
// Handled transparently by the registers
break;
case REG_HDMA5:
GBMemoryWriteHDMA5(gb, value);
value &= 0x7F;
value = GBMemoryWriteHDMA5(gb, value);
break;
case REG_BCPS:
gb->video.bcpIndex = value & 0x3F;

View File

@ -39,9 +39,6 @@ void GBMBCSwitchBank(struct GB* gb, int bank) {
mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
bankStart &= (gb->memory.romSize - 1);
bank = bankStart / GB_SIZE_CART_BANK0;
if (!bank) {
++bank;
}
}
gb->memory.romBank = &gb->memory.rom[bankStart];
gb->memory.currentBank = bank;

View File

@ -449,7 +449,7 @@ void GBMemoryDMA(struct GB* gb, uint16_t base) {
gb->memory.dmaRemaining = 0xA0;
}
void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
uint8_t GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
gb->memory.hdmaSource = gb->memory.io[REG_HDMA1] << 8;
gb->memory.hdmaSource |= gb->memory.io[REG_HDMA2];
gb->memory.hdmaDest = gb->memory.io[REG_HDMA3] << 8;
@ -457,7 +457,7 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
gb->memory.hdmaSource &= 0xFFF0;
if (gb->memory.hdmaSource >= 0x8000 && gb->memory.hdmaSource < 0xA000) {
mLOG(GB_MEM, GAME_ERROR, "Invalid HDMA source: %04X", gb->memory.hdmaSource);
return;
return value | 0x80;
}
gb->memory.hdmaDest &= 0x1FF0;
gb->memory.hdmaDest |= 0x8000;
@ -471,7 +471,10 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
}
gb->cpuBlocked = true;
mTimingSchedule(&gb->timing, &gb->memory.hdmaEvent, 0);
} else if (gb->memory.isHdma && !GBRegisterLCDCIsEnable(gb->memory.io[REG_LCDC])) {
return 0x80 | ((value + 1) & 0x7F);
}
return value & 0x7F;
}
void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesLate) {

View File

@ -171,6 +171,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
cheat->address = op2 & 0x0FFFFFFF;
cheat->operand = op1 & 0xFFFF;
cheat->repeat = (op1 >> 16) & 0xFF;
cheat->negativeRepeat = 0;
return true;
case GSA_HOOK:
if (cheats->hook) {
@ -187,6 +188,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
}
cheat->operand = op2;
cheat->repeat = 1;
cheat->negativeRepeat = 0;
return true;
}

View File

@ -132,8 +132,8 @@ static bool _addPAR3Cond(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2)
case PAR3_COND_UGT:
cheat->type = CHEAT_IF_UGT;
break;
case PAR3_COND_LAND:
cheat->type = CHEAT_IF_LAND;
case PAR3_COND_AND:
cheat->type = CHEAT_IF_AND;
break;
}
return true;
@ -190,20 +190,23 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) {
return false;
case PAR3_OTHER_FILL_1:
cheat = mCheatListAppend(&cheats->d.list);
cheat->type = CHEAT_ASSIGN;
cheat->address = _parAddr(op2);
cheat->width = 1;
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
break;
case PAR3_OTHER_FILL_2:
cheat = mCheatListAppend(&cheats->d.list);
cheat->type = CHEAT_ASSIGN;
cheat->address = _parAddr(op2);
cheat->width = 2;
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
break;
case PAR3_OTHER_FILL_4:
cheat = mCheatListAppend(&cheats->d.list);
cheat->type = CHEAT_ASSIGN;
cheat->address = _parAddr(op2);
cheat->width = 3;
cheat->width = 4;
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
break;
}
@ -219,8 +222,8 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin
if (cheats->incompleteCheat != COMPLETE) {
struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat);
incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - incompleteCheat->width) * 8));
incompleteCheat->addressOffset = op2 >> 24;
incompleteCheat->repeat = (op2 >> 16) & 0xFF;
incompleteCheat->operandOffset = op2 >> 24;
incompleteCheat->repeat = ((op2 >> 16) & 0xFF) + 1;
incompleteCheat->addressOffset = (op2 & 0xFFFF) * incompleteCheat->width;
cheats->incompleteCheat = COMPLETE;
return true;
@ -341,7 +344,7 @@ int GBACheatProActionReplayProbability(uint32_t op1, uint32_t op2) {
return 0x100;
}
if (!op1) {
probability += 0x20;
probability += 0x40;
uint32_t address = _parAddr(op2);
switch (op2 & 0xFE000000) {
case PAR3_OTHER_FILL_1:
@ -362,8 +365,8 @@ int GBACheatProActionReplayProbability(uint32_t op1, uint32_t op2) {
case PAR3_OTHER_BUTTON_4:
case PAR3_OTHER_ENDIF:
case PAR3_OTHER_ELSE:
if (op2 & 0x01FFFFFF) {
probability -= 0x20;
if (op2 & 0x01000000) {
probability -= 0x40;
}
break;
default:

View File

@ -509,16 +509,49 @@ bool GBAIsMB(struct VFile* vf) {
LOAD_32(opcode, 0, &signature);
struct ARMInstructionInfo info;
ARMDecodeARM(opcode, &info);
if (info.branchType != ARM_BRANCH) {
return false;
if (info.branchType == ARM_BRANCH) {
if (info.op1.immediate <= 0) {
return false;
} else if (info.op1.immediate == 28) {
// Ancient toolchain that is known to throw MB detection for a loop
return false;
} else if (info.op1.immediate != 24) {
return true;
}
}
if (info.op1.immediate <= 0) {
return false;
} else if (info.op1.immediate == 28) {
// Ancient toolchain that is known to throw MB detection for a loop
return false;
} else if (info.op1.immediate != 24) {
return true;
uint32_t pc = GBA_MB_MAGIC_OFFSET;
int i;
for (i = 0; i < 80; ++i) {
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
break;
}
pc += 4;
LOAD_32(opcode, 0, &signature);
ARMDecodeARM(opcode, &info);
if (info.mnemonic != ARM_MN_LDR) {
continue;
}
if ((info.operandFormat & ARM_OPERAND_MEMORY) && info.memory.baseReg == ARM_PC && info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
uint32_t immediate = info.memory.offset.immediate;
if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
immediate = -immediate;
}
immediate += pc + 8;
if (vf->seek(vf, immediate, SEEK_SET) < 0) {
break;
}
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
break;
}
LOAD_32(immediate, 0, &signature);
if (vf->seek(vf, pc, SEEK_SET) < 0) {
break;
}
if ((immediate & ~0x7FF) == BASE_WORKING_RAM) {
return true;
}
}
}
// Found a libgba-linked cart...these are a bit harder to detect.
return false;

View File

@ -1499,9 +1499,11 @@ int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
int32_t previousLoads = 0;
// Don't prefetch too much if we're overlapping with a previous prefetch
uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]) >> 1;
if (dist < 8) {
previousLoads = dist;
uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]);
int32_t maxLoads = 8;
if (dist < 16) {
previousLoads = dist >> 1;
maxLoads -= previousLoads;
}
int32_t s = cpu->memory.activeSeqCycles16;
@ -1511,12 +1513,9 @@ int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
int32_t stall = s;
int32_t loads = 1;
if (stall < wait) {
int32_t maxLoads = 8 - previousLoads;
while (stall < wait && loads < maxLoads) {
stall += s;
++loads;
}
while (stall < wait && loads < maxLoads) {
stall += s;
++loads;
}
if (stall > wait) {
// The wait cannot take less time than the prefetch stalls

View File

@ -156,26 +156,26 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
return 0;
}
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed);
int variant = renderer->target1Obj &&
GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) &&
(renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) {
int target2 = renderer->target2Bd << 4;
target2 |= renderer->bg[0].target2 << (renderer->bg[0].priority);
target2 |= renderer->bg[1].target2 << (renderer->bg[1].priority);
target2 |= renderer->bg[2].target2 << (renderer->bg[2].priority);
target2 |= renderer->bg[3].target2 << (renderer->bg[3].priority);
if ((1 << GBAObjAttributesCGetPriority(sprite->c)) <= target2) {
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT || objwinSlowPath) {
int target2 = renderer->target2Bd;
target2 |= renderer->bg[0].target2;
target2 |= renderer->bg[1].target2;
target2 |= renderer->bg[2].target2;
target2 |= renderer->bg[3].target2;
if (target2) {
flags |= FLAG_REBLEND;
variant = 0;
} else if (!target2) {
} else {
flags &= ~FLAG_TARGET_1;
}
}
color_t* palette = &renderer->normalPalette[0x100];
color_t* objwinPalette = palette;
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed);
if (variant) {
palette = &renderer->variantPalette[0x100];

View File

@ -43,7 +43,7 @@ static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* render
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
} else {
color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN));
}
} else {
color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN);
@ -59,7 +59,7 @@ static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* rend
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
} else {
color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN));
}
} else {
color = color & ~FLAG_TARGET_2;
@ -73,7 +73,7 @@ static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* rend
if (color < current) {
color |= (current & FLAG_OBJWIN);
} else {
color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN));
}
*pixel = color;
}
@ -82,7 +82,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
uint32_t current) {
UNUSED(renderer);
if (color >= current) {
color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN));
}
*pixel = color;
}

View File

@ -568,6 +568,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
}
if (softwareRenderer->target1Obj && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) {
x = 0;
uint32_t mask = 0xFF000000 & ~FLAG_OBJWIN;
uint32_t match = FLAG_REBLEND;
if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
mask |= FLAG_OBJWIN;
if (GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed)) {
match |= FLAG_OBJWIN;
}
}
for (w = 0; w < softwareRenderer->nWindows; ++w) {
if (!GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
continue;
@ -576,14 +584,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
if (softwareRenderer->blendEffect == BLEND_DARKEN) {
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if ((color & 0xFF000000) == FLAG_REBLEND) {
if ((color & mask) == match) {
softwareRenderer->row[x] = _darken(color, softwareRenderer->bldy);
}
}
} else if (softwareRenderer->blendEffect == BLEND_BRIGHTEN) {
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if ((color & 0xFF000000) == FLAG_REBLEND) {
if ((color & mask) == match) {
softwareRenderer->row[x] = _brighten(color, softwareRenderer->bldy);
}
}

View File

@ -576,9 +576,15 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
if (bank > 0 && savedata->type == SAVEDATA_FLASH512) {
mLOG(GBA_SAVE, INFO, "Updating flash chip from 512kb to 1Mb");
savedata->type = SAVEDATA_FLASH1M;
if (savedata->vf && savedata->vf->size(savedata->vf) == SIZE_CART_FLASH512) {
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
if (savedata->vf) {
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
if (savedata->vf->size(savedata->vf) == SIZE_CART_FLASH512) {
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, MAP_WRITE);
memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
} else {
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, MAP_WRITE);
}
}
}
}

View File

@ -75,6 +75,93 @@ M_TEST_DEFINE(doPARv3Assign) {
set->deinit(set);
}
M_TEST_DEFINE(doPARv3Slide1) {
struct mCore* core = *state;
struct mCheatDevice* device = core->cheatDevice(core);
assert_non_null(device);
struct mCheatSet* set = device->createSet(device, NULL);
assert_non_null(set);
GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
assert_true(set->addLine(set, "00000000 80300000", GBA_CHEAT_PRO_ACTION_REPLAY));
assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY));
core->reset(core);
assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
mCheatRefresh(device, set);
assert_int_equal(core->rawRead8(core, 0x03000000, -1), 1);
assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000002, -1), 2);
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3Slide2) {
struct mCore* core = *state;
struct mCheatDevice* device = core->cheatDevice(core);
assert_non_null(device);
struct mCheatSet* set = device->createSet(device, NULL);
assert_non_null(set);
GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
assert_true(set->addLine(set, "00000000 82300000", GBA_CHEAT_PRO_ACTION_REPLAY));
assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY));
core->reset(core);
assert_int_equal(core->rawRead16(core, 0x03000000, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000002, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000004, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000006, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000008, -1), 0);
assert_int_equal(core->rawRead16(core, 0x0300000A, -1), 0);
mCheatRefresh(device, set);
assert_int_equal(core->rawRead16(core, 0x03000000, -1), 1);
assert_int_equal(core->rawRead16(core, 0x03000002, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000004, -1), 2);
assert_int_equal(core->rawRead16(core, 0x03000006, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000008, -1), 0);
assert_int_equal(core->rawRead16(core, 0x0300000A, -1), 0);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3Slide4) {
struct mCore* core = *state;
struct mCheatDevice* device = core->cheatDevice(core);
assert_non_null(device);
struct mCheatSet* set = device->createSet(device, NULL);
assert_non_null(set);
GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
assert_true(set->addLine(set, "00000000 84300000", GBA_CHEAT_PRO_ACTION_REPLAY));
assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY));
core->reset(core);
assert_int_equal(core->rawRead32(core, 0x03000000, -1), 0);
assert_int_equal(core->rawRead32(core, 0x03000004, -1), 0);
assert_int_equal(core->rawRead32(core, 0x03000008, -1), 0);
assert_int_equal(core->rawRead32(core, 0x0300000C, -1), 0);
assert_int_equal(core->rawRead32(core, 0x03000010, -1), 0);
assert_int_equal(core->rawRead32(core, 0x03000014, -1), 0);
mCheatRefresh(device, set);
assert_int_equal(core->rawRead16(core, 0x03000000, -1), 1);
assert_int_equal(core->rawRead16(core, 0x03000004, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000008, -1), 2);
assert_int_equal(core->rawRead16(core, 0x0300000C, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000010, -1), 0);
assert_int_equal(core->rawRead16(core, 0x03000014, -1), 0);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3If1) {
struct mCore* core = *state;
struct mCheatDevice* device = core->cheatDevice(core);
@ -334,6 +421,7 @@ M_TEST_DEFINE(doPARv3IfX) {
mCheatRefresh(device, set);
assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXxX) {
@ -396,6 +484,7 @@ M_TEST_DEFINE(doPARv3IfXxX) {
assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXElse) {
@ -430,6 +519,7 @@ M_TEST_DEFINE(doPARv3IfXElse) {
assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXElsexX) {
@ -500,6 +590,7 @@ M_TEST_DEFINE(doPARv3IfXElsexX) {
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXElsexXElse) {
@ -577,6 +668,7 @@ M_TEST_DEFINE(doPARv3IfXElsexXElse) {
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXContain1) {
@ -638,6 +730,7 @@ M_TEST_DEFINE(doPARv3IfXContain1) {
assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXContain1Else) {
@ -707,6 +800,7 @@ M_TEST_DEFINE(doPARv3IfXContain1Else) {
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXElseContain1) {
@ -776,6 +870,7 @@ M_TEST_DEFINE(doPARv3IfXElseContain1) {
assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
set->deinit(set);
}
M_TEST_DEFINE(doPARv3IfXContain1ElseContain1) {
@ -927,6 +1022,9 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBACheats,
cmocka_unit_test(createSet),
cmocka_unit_test(addRawPARv3),
cmocka_unit_test(doPARv3Assign),
cmocka_unit_test(doPARv3Slide1),
cmocka_unit_test(doPARv3Slide2),
cmocka_unit_test(doPARv3Slide4),
cmocka_unit_test(doPARv3If1),
cmocka_unit_test(doPARv3If1x1),
cmocka_unit_test(doPARv3If2),