GBA Memory: Use a dynamically sized mask for ROM memory

This commit is contained in:
Jeffrey Pfau 2015-08-18 23:23:45 -07:00
parent 76663c41cd
commit 003a21b13d
5 changed files with 54 additions and 1 deletions

View File

@ -5,6 +5,7 @@ Bugfixes:
Misc:
- Qt: Window size command line options are now supported
- Qt: Increase usability of key mapper
- GBA Memory: Use a dynamically sized mask for ROM memory
0.3.0: (2015-08-16)
Features:

View File

@ -17,6 +17,7 @@
#include "util/crc32.h"
#include "util/memory.h"
#include "util/math.h"
#include "util/patch.h"
#include "util/vfs.h"
@ -156,6 +157,7 @@ void GBAReset(struct ARMCore* cpu) {
if (gba->yankedRomSize) {
gba->memory.romSize = gba->yankedRomSize;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
gba->yankedRomSize = 0;
}
GBAMemoryReset(gba);
@ -403,6 +405,7 @@ void GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char
gba->memory.rom = gba->pristineRom;
gba->activeFile = fname;
gba->memory.romSize = gba->pristineRomSize;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
GBASavedataInit(&gba->memory.savedata, sav);
GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]);
@ -412,6 +415,7 @@ void GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char
void GBAYankROM(struct GBA* gba) {
gba->yankedRomSize = gba->memory.romSize;
gba->memory.romSize = 0;
gba->memory.romMask = 0;
GBARaiseIRQ(gba, IRQ_GAMEPAK);
}
@ -452,6 +456,7 @@ void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
return;
}
gba->memory.romSize = patchedSize;
gba->memory.romMask = SIZE_CART0 - 1;
gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
}

View File

@ -50,6 +50,7 @@ void GBAMemoryInit(struct GBA* gba) {
gba->memory.iwram = 0;
gba->memory.rom = 0;
gba->memory.romSize = 0;
gba->memory.romMask = 0;
gba->memory.hw.p = gba;
int i;
@ -269,7 +270,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
case REGION_CART2:
case REGION_CART2_EX:
cpu->memory.activeRegion = memory->rom;
cpu->memory.activeMask = SIZE_CART0 - 1;
cpu->memory.activeMask = memory->romMask;
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
break;
}
@ -893,6 +894,7 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o
_pristineCow(gba);
if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
}
LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
@ -960,6 +962,7 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o
_pristineCow(gba);
if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
}
LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
@ -1017,6 +1020,7 @@ void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old)
_pristineCow(gba);
if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
}
oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;

View File

@ -118,6 +118,7 @@ struct GBAMemory {
struct GBACartridgeHardware hw;
struct GBASavedata savedata;
size_t romSize;
uint32_t romMask;
uint16_t romID;
int fullBios;

View File

@ -14,4 +14,46 @@ static inline uint32_t popcount32(unsigned bits) {
return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
}
static inline unsigned clz32(uint32_t bits) {
#if defined(__GNUC__) || __clang__
return __builtin_clz(bits);
#else
static const int table[256] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (bits & 0xFF000000) {
return table[bits >> 24];
} else if (bits & 0x00FF0000) {
return table[bits >> 16] + 8;
} else if (bits & 0x0000FF00) {
return table[bits >> 8] + 16;
}
return table[bits] + 24;
#endif
}
static inline uint32_t toPow2(uint32_t bits) {
if (!bits) {
return 0;
}
unsigned lz = clz32(bits - 1);
return 1 << (32 - lz);
}
#endif