mirror of
https://github.com/libretro/mgba.git
synced 2025-02-17 06:07:46 +00:00
Merge remote-tracking branch 'upstream/0.6'
This commit is contained in:
commit
17ba655edd
8
CHANGES
8
CHANGES
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user