Sanitize allocations in the Game Boy emulator (#1105)
This adds checks for every allocation failure in the core Game Boy emulator. In addition, this replaces some magic values defined constant expressions and removes an unused function. This also removes asserts for failed allocations in GB.cpp, they now report a failure to the caller.
This commit is contained in:
parent
e91e4dcf17
commit
7005b92840
|
@ -21,4 +21,33 @@ constexpr size_t k2MiB = 2 * k1MiB;
|
|||
constexpr size_t k4MiB = 2 * k2MiB;
|
||||
constexpr size_t k8MiB = 2 * k4MiB;
|
||||
|
||||
// Game Boy BIOS Sizes.
|
||||
constexpr size_t kGBBiosSize = k256B;
|
||||
constexpr size_t kCGBBiosSize = k2KiB + k256B;
|
||||
|
||||
// Size of the buffer containing the BIOS, we alawys use the larger size.
|
||||
constexpr size_t kGBBiosBufferSize = kCGBBiosSize;
|
||||
|
||||
// Game Boy-related screen sizes.
|
||||
constexpr size_t kGBWidth = 160;
|
||||
constexpr size_t kGBHeight = 144;
|
||||
constexpr size_t kSGBWidth = 256;
|
||||
constexpr size_t kSGBHeight = 224;
|
||||
#ifdef __LIBRETRO__
|
||||
constexpr size_t kGBPixSize = 4 * kSGBWidth * kSGBHeight;
|
||||
#else
|
||||
// Some of the filters and interframe blenders write beyond the end of the line
|
||||
// or the screen, so we allocate extra space here.
|
||||
constexpr size_t kGBPixSize = 4 * (kSGBWidth + 1) * (kSGBHeight + 2);
|
||||
#endif
|
||||
|
||||
// Game Boy VRAM is 16 KiB.
|
||||
constexpr size_t kGBVRamSize = k16KiB;
|
||||
|
||||
// Game Boy WRAM is 32 KiB.
|
||||
constexpr size_t kGBWRamSize = k32KiB;
|
||||
|
||||
// A Game Boy line buffer size is the width of the screen at 2 bytes per pizel.
|
||||
constexpr size_t kGBLineBufferSize = kGBWidth * 2;
|
||||
|
||||
#endif // VBAM_COMMON_SIZES_H_
|
||||
|
|
304
src/gb/GB.cpp
304
src/gb/GB.cpp
|
@ -114,6 +114,7 @@ bool gbInitializeRom(size_t romSize) {
|
|||
switch (g_gbCartData.validity()) {
|
||||
case gbCartData::Validity::kValid:
|
||||
case gbCartData::Validity::kUninitialized:
|
||||
// Unreachable.
|
||||
assert(false);
|
||||
break;
|
||||
case gbCartData::Validity::kSizeTooSmall:
|
||||
|
@ -157,7 +158,6 @@ bool gbInitializeRom(size_t romSize) {
|
|||
if (romSize < romHeaderSize) {
|
||||
uint8_t* gbRomNew = (uint8_t*)realloc(gbRom, romHeaderSize);
|
||||
if (!gbRomNew) {
|
||||
assert(false);
|
||||
return false;
|
||||
};
|
||||
gbRom = gbRomNew;
|
||||
|
@ -227,9 +227,12 @@ bool gbInitializeRom(size_t romSize) {
|
|||
}
|
||||
|
||||
gbRamFill = 0x00;
|
||||
if (gbTAMA5ram == nullptr)
|
||||
gbTAMA5ram = (uint8_t*)malloc(kTama5RamSize);
|
||||
memset(gbTAMA5ram, 0x0, kTama5RamSize);
|
||||
if (gbTAMA5ram == nullptr) {
|
||||
gbTAMA5ram = (uint8_t*)calloc(1, kTama5RamSize);
|
||||
if (gbTAMA5ram == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
g_mapperRAM = mapperTAMA5RAM;
|
||||
g_mapperReadRAM = mapperTAMA5ReadRAM;
|
||||
|
@ -253,6 +256,9 @@ bool gbInitializeRom(size_t romSize) {
|
|||
const size_t ramSize = g_gbCartData.ram_size();
|
||||
if (ramSize > 0) {
|
||||
gbRam = (uint8_t*)malloc(ramSize);
|
||||
if (gbRam == nullptr) {
|
||||
return false;
|
||||
}
|
||||
memset(gbRam, gbRamFill, ramSize);
|
||||
}
|
||||
|
||||
|
@ -261,14 +267,19 @@ bool gbInitializeRom(size_t romSize) {
|
|||
setColorizerHack(false);
|
||||
|
||||
gbMemory = (uint8_t*)malloc(65536);
|
||||
if (gbMemory == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
pix = (uint8_t*)calloc(1, 4 * 256 * 224);
|
||||
#else
|
||||
pix = (uint8_t*)calloc(1, 4 * 257 * 226);
|
||||
#endif
|
||||
pix = (uint8_t*)calloc(1, kGBPixSize);
|
||||
if (pix == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gbLineBuffer = (uint16_t*)malloc(160 * sizeof(uint16_t));
|
||||
gbLineBuffer = (uint16_t*)malloc(kGBLineBufferSize);
|
||||
if (gbLineBuffer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -281,7 +292,7 @@ bool inBios = false;
|
|||
bool memorydebug = false;
|
||||
char gbBuffer[2048];
|
||||
|
||||
extern uint16_t gbLineMix[160];
|
||||
extern uint16_t gbLineMix[kGBWidth];
|
||||
|
||||
// registers
|
||||
gbRegister PC;
|
||||
|
@ -1436,7 +1447,7 @@ void gbWriteMemory(uint16_t address, uint8_t value)
|
|||
|
||||
// systemDrawScreen();
|
||||
|
||||
gbRegisterLYLCDCOffOn = (register_LY + 144) % 154;
|
||||
gbRegisterLYLCDCOffOn = (register_LY + kGBHeight) % 154;
|
||||
|
||||
gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 2 : 1);
|
||||
gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 1 : 0);
|
||||
|
@ -1683,7 +1694,7 @@ void gbWriteMemory(uint16_t address, uint8_t value)
|
|||
// WY
|
||||
case 0x4a:
|
||||
gbMemory[0xff4a] = register_WY = value;
|
||||
if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine >= 144))) {
|
||||
if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine >= (int)kGBHeight))) {
|
||||
gbWindowLine = -1;
|
||||
oldRegister_WY = register_WY;
|
||||
}
|
||||
|
@ -2356,7 +2367,7 @@ void gbCPUInit(const char* biosFileName, bool useBiosFile)
|
|||
|
||||
coreOptions.useBios = false;
|
||||
if (useBiosFile) {
|
||||
int expectedSize = (gbHardware & 2) ? 0x900 : 0x100;
|
||||
int expectedSize = (gbHardware & 2) ? kCGBBiosSize : kGBBiosSize;
|
||||
int size = expectedSize;
|
||||
if (utilLoad(biosFileName,
|
||||
CPUIsGBBios,
|
||||
|
@ -2494,21 +2505,28 @@ void gbReset()
|
|||
oldRegister_WY = 146;
|
||||
gbInterruptLaunched = 0;
|
||||
|
||||
if (gbCgbMode == 1) {
|
||||
if (gbVram == NULL)
|
||||
gbVram = (uint8_t*)malloc(0x4000);
|
||||
if (gbWram == NULL)
|
||||
gbWram = (uint8_t*)malloc(0x8000);
|
||||
memset(gbVram, 0, 0x4000);
|
||||
memset(gbPalette, 0, 2 * 128);
|
||||
} else {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = NULL;
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (gbWram != NULL) {
|
||||
if (gbWram == nullptr) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram != nullptr) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
free(gbWram);
|
||||
gbWram = NULL;
|
||||
gbWram = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2526,7 +2544,7 @@ void gbReset()
|
|||
// In all cases, most of the 2nd bank is filled with 00s.
|
||||
// The starting data are important for some 'buggy' games, like Buster Brothers or
|
||||
// Karamuchou ha Oosawagi!.
|
||||
if (gbMemory != NULL) {
|
||||
if (gbMemory != nullptr) {
|
||||
memset(gbMemory, 0xff, 65536);
|
||||
for (int temp = 0xC000; temp < 0xE000; temp++)
|
||||
if ((temp & 0x8) ^ ((temp & 0x800) >> 8)) {
|
||||
|
@ -2552,14 +2570,17 @@ void gbReset()
|
|||
}
|
||||
|
||||
// clean LineBuffer
|
||||
if (gbLineBuffer != NULL)
|
||||
memset(gbLineBuffer, 0, sizeof(*gbLineBuffer));
|
||||
if (gbLineBuffer != nullptr) {
|
||||
memset(gbLineBuffer, 0, kGBLineBufferSize);
|
||||
}
|
||||
// clean Pix
|
||||
if (pix != NULL)
|
||||
memset(pix, 0, sizeof(*pix));
|
||||
if (pix != nullptr) {
|
||||
memset(pix, 0, kGBPixSize);
|
||||
}
|
||||
// clean Vram
|
||||
if (gbVram != NULL)
|
||||
memset(gbVram, 0, 0x4000);
|
||||
if (gbVram != nullptr) {
|
||||
memset(gbVram, 0, kGBVRamSize);
|
||||
}
|
||||
// clean Wram 2
|
||||
// This kinda emulates the startup state of Wram on GBC (not very accurate,
|
||||
// but way closer to the reality than filling it with 00es or FFes).
|
||||
|
@ -2567,7 +2588,7 @@ void gbReset()
|
|||
// In all cases, most of the 2nd bank is filled with 00s.
|
||||
// The starting data are important for some 'buggy' games, like Buster Brothers or
|
||||
// Karamuchou ha Oosawagi!
|
||||
if (gbWram != NULL) {
|
||||
if (gbWram != nullptr) {
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (i != 2)
|
||||
memcpy((uint16_t*)(gbWram + i * 0x1000), (uint16_t*)(gbMemory + 0xC000), 0x1000);
|
||||
|
@ -2732,9 +2753,9 @@ void gbReset()
|
|||
if ((gbHardware & 7) && (bios != NULL) && coreOptions.useBios && !coreOptions.skipBios) {
|
||||
if (gbHardware & 5) {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(gbRom), 0x1000);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x100);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kGBBiosSize);
|
||||
} else {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x900);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kCGBBiosSize);
|
||||
memcpy((uint8_t*)(gbMemory + 0x100), (uint8_t*)(gbRom + 0x100), 0x100);
|
||||
}
|
||||
gbWhiteScreen = 0;
|
||||
|
@ -3541,26 +3562,7 @@ bool gbReadSaveMMM01(const char* name)
|
|||
} else
|
||||
return false;
|
||||
}
|
||||
#endif // !__LIBRETRO__
|
||||
|
||||
void gbInit()
|
||||
{
|
||||
gbGenFilter();
|
||||
gbSgbInit();
|
||||
setColorizerHack(false);
|
||||
|
||||
gbMemory = (uint8_t*)malloc(65536);
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
pix = (uint8_t*)calloc(1, 4 * 256 * 224);
|
||||
#else
|
||||
pix = (uint8_t*)calloc(1, 4 * 257 * 226);
|
||||
#endif
|
||||
|
||||
gbLineBuffer = (uint16_t*)malloc(160 * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
#ifndef __LIBRETRO__
|
||||
bool gbWriteBatteryFile(const char* file, bool extendedSave)
|
||||
{
|
||||
if (gbBattery) {
|
||||
|
@ -3870,7 +3872,7 @@ static bool gbWriteSaveState(gzFile gzFile)
|
|||
utilGzWrite(gzFile, gbTAMA5ram, kTama5RamSize);
|
||||
utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
|
||||
|
||||
utilGzWrite(gzFile, gbPalette, 128 * sizeof(uint16_t));
|
||||
utilGzWrite(gzFile, gbPalette, sizeof(gbPalette));
|
||||
|
||||
utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
|
||||
|
||||
|
@ -3880,8 +3882,8 @@ static bool gbWriteSaveState(gzFile gzFile)
|
|||
}
|
||||
|
||||
if (gbCgbMode) {
|
||||
utilGzWrite(gzFile, gbVram, 0x4000);
|
||||
utilGzWrite(gzFile, gbWram, 0x8000);
|
||||
utilGzWrite(gzFile, gbVram, kGBVRamSize);
|
||||
utilGzWrite(gzFile, gbWram, kGBWRamSize);
|
||||
}
|
||||
|
||||
gbSoundSaveGame(gzFile);
|
||||
|
@ -3983,22 +3985,29 @@ static bool gbReadSaveState(gzFile gzFile)
|
|||
utilReadData(gzFile, gbSaveGameStruct);
|
||||
|
||||
// Correct crash when loading color gameboy save in regular gameboy type.
|
||||
if (!gbCgbMode) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = NULL;
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = NULL;
|
||||
if (gbWram == nullptr) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram == NULL)
|
||||
gbVram = (uint8_t*)malloc(0x4000);
|
||||
if (gbWram == NULL)
|
||||
gbWram = (uint8_t*)malloc(0x8000);
|
||||
memset(gbVram, 0, 0x4000);
|
||||
memset(gbPalette, 0, 2 * 128);
|
||||
if (gbVram != nullptr) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (version >= GBSAVE_GAME_VERSION_7) {
|
||||
|
@ -4034,7 +4043,7 @@ static bool gbReadSaveState(gzFile gzFile)
|
|||
if (version < GBSAVE_GAME_VERSION_5) {
|
||||
utilGzRead(gzFile, pix, 256 * 224 * sizeof(uint16_t));
|
||||
}
|
||||
memset(pix, 0, 257 * 226 * sizeof(uint32_t));
|
||||
memset(pix, 0, kGBPixSize);
|
||||
|
||||
if (version < GBSAVE_GAME_VERSION_6) {
|
||||
utilGzRead(gzFile, gbPalette, 64 * sizeof(uint16_t));
|
||||
|
@ -4080,9 +4089,9 @@ static bool gbReadSaveState(gzFile gzFile)
|
|||
gbMemoryMap[0x00] = &gbMemory[0x0000];
|
||||
if (gbHardware & 5) {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(gbRom), 0x1000);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x100);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kGBBiosSize);
|
||||
} else if (gbHardware & 2) {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x900);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kCGBBiosSize);
|
||||
memcpy((uint8_t*)(gbMemory + 0x100), (uint8_t*)(gbRom + 0x100), 0x100);
|
||||
}
|
||||
|
||||
|
@ -4166,8 +4175,8 @@ static bool gbReadSaveState(gzFile gzFile)
|
|||
}
|
||||
|
||||
if (gbCgbMode) {
|
||||
utilGzRead(gzFile, gbVram, 0x4000);
|
||||
utilGzRead(gzFile, gbWram, 0x8000);
|
||||
utilGzRead(gzFile, gbVram, kGBVRamSize);
|
||||
utilGzRead(gzFile, gbWram, kGBWRamSize);
|
||||
|
||||
int value = register_SVBK;
|
||||
if (value == 0)
|
||||
|
@ -4275,8 +4284,10 @@ static bool gbReadSaveState(gzFile gzFile)
|
|||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
if (version >= 12 && utilReadInt(gzFile) != 0x12345678)
|
||||
assert(false); // fails if something read too much/little from file
|
||||
if (version >= 12 && utilReadInt(gzFile) != 0x12345678) {
|
||||
// fails if something read too much/little from file
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4310,65 +4321,65 @@ bool gbReadSaveState(const char* name)
|
|||
bool gbWritePNGFile(const char* fileName)
|
||||
{
|
||||
if (gbBorderOn)
|
||||
return utilWritePNGFile(fileName, 256, 224, pix);
|
||||
return utilWritePNGFile(fileName, 160, 144, pix);
|
||||
return utilWritePNGFile(fileName, kSGBWidth, kSGBHeight, pix);
|
||||
return utilWritePNGFile(fileName, kGBWidth, kGBHeight, pix);
|
||||
}
|
||||
|
||||
bool gbWriteBMPFile(const char* fileName)
|
||||
{
|
||||
if (gbBorderOn)
|
||||
return utilWriteBMPFile(fileName, 256, 224, pix);
|
||||
return utilWriteBMPFile(fileName, 160, 144, pix);
|
||||
return utilWriteBMPFile(fileName, kSGBWidth, kSGBHeight, pix);
|
||||
return utilWriteBMPFile(fileName, kGBWidth, kGBHeight, pix);
|
||||
}
|
||||
#endif // !__LIBRETRO__
|
||||
|
||||
void gbCleanUp()
|
||||
{
|
||||
if (gbRam != NULL) {
|
||||
if (gbRam != nullptr) {
|
||||
free(gbRam);
|
||||
gbRam = NULL;
|
||||
gbRam = nullptr;
|
||||
}
|
||||
|
||||
if (gbRom != NULL) {
|
||||
if (gbRom != nullptr) {
|
||||
free(gbRom);
|
||||
gbRom = NULL;
|
||||
gbRom = nullptr;
|
||||
}
|
||||
|
||||
if (bios != NULL) {
|
||||
if (bios != nullptr) {
|
||||
free(bios);
|
||||
bios = NULL;
|
||||
bios = nullptr;
|
||||
}
|
||||
|
||||
if (gbMemory != NULL) {
|
||||
if (gbMemory != nullptr) {
|
||||
free(gbMemory);
|
||||
gbMemory = NULL;
|
||||
gbMemory = nullptr;
|
||||
}
|
||||
|
||||
if (gbLineBuffer != NULL) {
|
||||
if (gbLineBuffer != nullptr) {
|
||||
free(gbLineBuffer);
|
||||
gbLineBuffer = NULL;
|
||||
gbLineBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (pix != NULL) {
|
||||
if (pix != nullptr) {
|
||||
free(pix);
|
||||
pix = NULL;
|
||||
pix = nullptr;
|
||||
}
|
||||
|
||||
gbSgbShutdown();
|
||||
|
||||
if (gbVram != NULL) {
|
||||
if (gbVram != nullptr) {
|
||||
free(gbVram);
|
||||
gbVram = NULL;
|
||||
gbVram = nullptr;
|
||||
}
|
||||
|
||||
if (gbWram != NULL) {
|
||||
if (gbWram != nullptr) {
|
||||
free(gbWram);
|
||||
gbWram = NULL;
|
||||
gbWram = nullptr;
|
||||
}
|
||||
|
||||
if (gbTAMA5ram != NULL) {
|
||||
if (gbTAMA5ram != nullptr) {
|
||||
free(gbTAMA5ram);
|
||||
gbTAMA5ram = NULL;
|
||||
gbTAMA5ram = nullptr;
|
||||
}
|
||||
|
||||
g_gbCartData = gbCartData();
|
||||
|
@ -4398,7 +4409,10 @@ bool gbLoadRom(const char* filename) {
|
|||
free(bios);
|
||||
bios = nullptr;
|
||||
}
|
||||
bios = (uint8_t*)calloc(1, 0x900);
|
||||
bios = (uint8_t*)calloc(1, kGBBiosBufferSize);
|
||||
if (bios == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return gbInitializeRom(romSize);
|
||||
}
|
||||
|
@ -4445,7 +4459,7 @@ void gbDrawLine()
|
|||
uint16_t* dest = (uint16_t*)pix + (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1)
|
||||
+ gbBorderColumnSkip;
|
||||
#endif
|
||||
for (int x = 0; x < 160;) {
|
||||
for (size_t x = 0; x < kGBWidth;) {
|
||||
*dest++ = systemColorMap16[gbLineMix[x++]];
|
||||
*dest++ = systemColorMap16[gbLineMix[x++]];
|
||||
*dest++ = systemColorMap16[gbLineMix[x++]];
|
||||
|
@ -4475,7 +4489,7 @@ void gbDrawLine()
|
|||
|
||||
case 24: {
|
||||
uint8_t* dest = (uint8_t*)pix + 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) + gbBorderColumnSkip);
|
||||
for (int x = 0; x < 160;) {
|
||||
for (size_t x = 0; x < kGBWidth;) {
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
|
@ -4522,7 +4536,7 @@ void gbDrawLine()
|
|||
uint32_t* dest = (uint32_t*)pix + (gbBorderLineSkip + 1) * (register_LY + gbBorderRowSkip + 1)
|
||||
+ gbBorderColumnSkip;
|
||||
#endif
|
||||
for (int x = 0; x < 160;) {
|
||||
for (size_t x = 0; x < kGBWidth;) {
|
||||
*dest++ = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = systemColorMap32[gbLineMix[x++]];
|
||||
|
@ -4770,7 +4784,7 @@ void gbEmulate(int ticksToStop)
|
|||
case 0: {
|
||||
// H-Blank
|
||||
// check if we reached the V-Blank period
|
||||
if (register_LY == 144) {
|
||||
if (register_LY == kGBHeight) {
|
||||
// Yes, V-Blank
|
||||
// set the LY increment counter
|
||||
if (gbHardware & 0x5) {
|
||||
|
@ -4845,7 +4859,7 @@ void gbEmulate(int ticksToStop)
|
|||
int tempinUseRegister_WY = inUseRegister_WY;
|
||||
int tempgbWindowLine = gbWindowLine;
|
||||
|
||||
if ((tempgbWindowLine == -1) || (tempgbWindowLine > 144)) {
|
||||
if ((tempgbWindowLine == -1) || (tempgbWindowLine > (int)kGBHeight)) {
|
||||
tempinUseRegister_WY = oldRegister_WY;
|
||||
if (register_LY > oldRegister_WY)
|
||||
tempgbWindowLine = 146;
|
||||
|
@ -4952,7 +4966,7 @@ void gbEmulate(int ticksToStop)
|
|||
if (gbWindowLine < 0)
|
||||
oldRegister_WY = register_WY;
|
||||
// check if we reached the V-Blank period
|
||||
if (register_LY == 144) {
|
||||
if (register_LY == kGBHeight) {
|
||||
// Yes, V-Blank
|
||||
// set the LY increment counter
|
||||
|
||||
|
@ -5054,7 +5068,7 @@ void gbEmulate(int ticksToStop)
|
|||
|
||||
// OAM and VRAM in use
|
||||
// next mode is H-Blank
|
||||
if ((register_LY < 144) && (register_LCDC & 0x80) && gbScreenOn) {
|
||||
if ((register_LY < kGBHeight) && (register_LCDC & 0x80) && gbScreenOn) {
|
||||
if (!gbSgbMask) {
|
||||
if (gbFrameSkipCount >= framesToSkip) {
|
||||
if (!gbBlackScreen) {
|
||||
|
@ -5064,7 +5078,7 @@ void gbEmulate(int ticksToStop)
|
|||
uint16_t color = gbColorOption ? gbColorFilter[0] : 0;
|
||||
if (!gbCgbMode)
|
||||
color = gbColorOption ? gbColorFilter[gbPalette[3] & 0x7FFF] : gbPalette[3] & 0x7FFF;
|
||||
for (int i = 0; i < 160; i++) {
|
||||
for (size_t i = 0; i < kGBWidth; i++) {
|
||||
gbLineMix[i] = color;
|
||||
gbLineBuffer[i] = 0;
|
||||
}
|
||||
|
@ -5129,7 +5143,7 @@ void gbEmulate(int ticksToStop)
|
|||
uint16_t color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
|
||||
if (!gbCgbMode)
|
||||
color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF;
|
||||
for (int i = 0; i < 160; i++) {
|
||||
for (size_t i = 0; i < kGBWidth; i++) {
|
||||
gbLineMix[i] = color;
|
||||
gbLineBuffer[i] = 0;
|
||||
}
|
||||
|
@ -5145,17 +5159,17 @@ void gbEmulate(int ticksToStop)
|
|||
while (gbLcdLYIncrementTicks <= 0) {
|
||||
register_LY = ((register_LY + 1) % 154);
|
||||
gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
|
||||
if (register_LY < 144) {
|
||||
if (register_LY < kGBHeight) {
|
||||
|
||||
uint16_t color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
|
||||
if (!gbCgbMode)
|
||||
color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF;
|
||||
for (int i = 0; i < 160; i++) {
|
||||
for (size_t i = 0; i < kGBWidth; i++) {
|
||||
gbLineMix[i] = color;
|
||||
gbLineBuffer[i] = 0;
|
||||
}
|
||||
gbDrawLine();
|
||||
} else if ((register_LY == 144) && (!systemFrameSkip)) {
|
||||
} else if ((register_LY == kGBHeight) && (!systemFrameSkip)) {
|
||||
int framesToSkip = systemFrameSkip;
|
||||
//if (coreOptions.speedup)
|
||||
// framesToSkip = 9; // try 6 FPS during speedup
|
||||
|
@ -5457,7 +5471,7 @@ bool gbLoadRomData(const char* data, size_t size) {
|
|||
|
||||
gbRom = (uint8_t*)calloc(1, size);
|
||||
if (gbRom == nullptr) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(gbRom, data, size);
|
||||
|
@ -5469,7 +5483,10 @@ bool gbLoadRomData(const char* data, size_t size) {
|
|||
bios = nullptr;
|
||||
}
|
||||
|
||||
bios = (uint8_t*)calloc(1, 0x900);
|
||||
bios = (uint8_t*)calloc(1, kGBBiosBufferSize);
|
||||
if (bios == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return gbInitializeRom(size);
|
||||
}
|
||||
|
||||
|
@ -5524,7 +5541,7 @@ unsigned int gbWriteSaveState(uint8_t* data)
|
|||
utilWriteMem(data, gbTAMA5ram, kTama5RamSize);
|
||||
utilWriteMem(data, &gbDataMMM01, sizeof(gbDataMMM01));
|
||||
|
||||
utilWriteMem(data, gbPalette, 128 * sizeof(uint16_t));
|
||||
utilWriteMem(data, gbPalette, sizeof(gbPalette));
|
||||
|
||||
utilWriteMem(data, &gbMemory[0x8000], 0x8000);
|
||||
|
||||
|
@ -5534,8 +5551,8 @@ unsigned int gbWriteSaveState(uint8_t* data)
|
|||
}
|
||||
|
||||
if (gbCgbMode) {
|
||||
utilWriteMem(data, gbVram, 0x4000);
|
||||
utilWriteMem(data, gbWram, 0x8000);
|
||||
utilWriteMem(data, gbVram, kGBVRamSize);
|
||||
utilWriteMem(data, gbWram, kGBWRamSize);
|
||||
}
|
||||
|
||||
gbSoundSaveGame(data);
|
||||
|
@ -5604,22 +5621,29 @@ bool gbReadSaveState(const uint8_t* data)
|
|||
utilReadDataMem(data, gbSaveGameStruct);
|
||||
|
||||
// Correct crash when loading color gameboy save in regular gameboy type.
|
||||
if (!gbCgbMode) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = NULL;
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = NULL;
|
||||
if (gbWram == nullptr) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram == NULL)
|
||||
gbVram = (uint8_t*)malloc(0x4000);
|
||||
if (gbWram == NULL)
|
||||
gbWram = (uint8_t*)malloc(0x8000);
|
||||
memset(gbVram, 0, 0x4000);
|
||||
memset(gbPalette, 0, 2 * 128);
|
||||
if (gbVram != nullptr) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
utilReadMem(&IFF, data, 2);
|
||||
|
@ -5644,7 +5668,7 @@ bool gbReadSaveState(const uint8_t* data)
|
|||
}
|
||||
utilReadMem(&gbDataMMM01, data, sizeof(gbDataMMM01));
|
||||
|
||||
utilReadMem(gbPalette, data, 128 * sizeof(uint16_t));
|
||||
utilReadMem(gbPalette, data, sizeof(gbPalette));
|
||||
|
||||
utilReadMem(&gbMemory[0x8000], data, 0x8000);
|
||||
|
||||
|
@ -5666,9 +5690,9 @@ bool gbReadSaveState(const uint8_t* data)
|
|||
gbMemoryMap[0x00] = &gbMemory[0x0000];
|
||||
if (gbHardware & 5) {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(gbRom), 0x1000);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x100);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kGBBiosSize);
|
||||
} else if (gbHardware & 2) {
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), 0x900);
|
||||
memcpy((uint8_t*)(gbMemory), (uint8_t*)(bios), kCGBBiosSize);
|
||||
memcpy((uint8_t*)(gbMemory + 0x100), (uint8_t*)(gbRom + 0x100), 0x100);
|
||||
}
|
||||
|
||||
|
@ -5754,8 +5778,8 @@ bool gbReadSaveState(const uint8_t* data)
|
|||
}
|
||||
|
||||
if (gbCgbMode) {
|
||||
utilReadMem(gbVram, data, 0x4000);
|
||||
utilReadMem(gbWram, data, 0x8000);
|
||||
utilReadMem(gbVram, data, kGBVRamSize);
|
||||
utilReadMem(gbWram, data, kGBWRamSize);
|
||||
|
||||
int value = register_SVBK;
|
||||
if (value == 0)
|
||||
|
@ -5795,8 +5819,10 @@ bool gbReadSaveState(const uint8_t* data)
|
|||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
if (version >= 12 && utilReadIntMem(data) != 0x12345678)
|
||||
assert(false); // fails if something read too much/little from file
|
||||
if (version >= 12 && utilReadIntMem(data) != 0x12345678) {
|
||||
// fails if something read too much/little from file
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -391,6 +391,10 @@ gbCartData::gbCartData(const uint8_t* romData, size_t romDataSize) {
|
|||
ram_size_ = k128KiB;
|
||||
break;
|
||||
case 0x05:
|
||||
// Technically, this refers to a 1 Mbit (128 KiB) RAM chip, but
|
||||
// this is only used in Pocket Monsters Crystal JP, which has a
|
||||
// mapper chip referred as "MBC30". This mapper can only address
|
||||
// half of the RAM chip. So, we set the size to 64 KiB.
|
||||
ram_size_ = k64KiB;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -8,13 +8,13 @@ int gbRomSize = 0;
|
|||
int gbRamSizeMask = 0;
|
||||
int gbRamSize = 0;
|
||||
|
||||
uint8_t* gbMemory = NULL;
|
||||
uint8_t* gbVram = NULL;
|
||||
uint8_t* gbRom = NULL;
|
||||
uint8_t* gbRam = NULL;
|
||||
uint8_t* gbWram = NULL;
|
||||
uint16_t* gbLineBuffer = NULL;
|
||||
uint8_t* gbTAMA5ram = NULL;
|
||||
uint8_t* gbMemory = nullptr;
|
||||
uint8_t* gbVram = nullptr;
|
||||
uint8_t* gbRom = nullptr;
|
||||
uint8_t* gbRam = nullptr;
|
||||
uint8_t* gbWram = nullptr;
|
||||
uint16_t* gbLineBuffer = nullptr;
|
||||
uint8_t* gbTAMA5ram = nullptr;
|
||||
|
||||
uint16_t gbPalette[128];
|
||||
uint8_t gbBgp[4] = { 0, 1, 2, 3 };
|
||||
|
|
Loading…
Reference in New Issue