UNIF: Ensure that used memory are freed on errors

- removes "goto" jumps
- frees ROM and VROM if necessary
This commit is contained in:
negativeExponent
2020-10-23 10:17:38 +08:00
parent c542204651
commit 71daae412e

View File

@@ -138,6 +138,11 @@ static void ResetUNIF(void) {
VROM_size = 0;
}
static void Cleanup(void) {
FreeUNIF();
ResetUNIF();
}
static uint8 exntar[2048];
static void MooMirroring(void) {
@@ -727,8 +732,8 @@ static void UNIFGI(int h) {
int UNIFLoad(const char *name, FCEUFILE *fp) {
struct md5_context md5;
uint32 x = 0;
uint64 PRGptr = 0, CHRptr = 0;
uint64 prg_size_bytes = 0, chr_size_bytes = 0;
int x = 0;
FCEU_fseek(fp, 0, SEEK_SET);
FCEU_fread(&unhead, 1, 4, fp);
@@ -739,12 +744,18 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
ResetExState(0, 0);
ResetUNIF();
if (!FCEU_read32le(&unhead.info, fp))
goto aborto;
if (FCEU_fseek(fp, 0x20, SEEK_SET) < 0)
goto aborto;
if (!LoadUNIFChunks(fp))
goto aborto;
if (!FCEU_read32le(&unhead.info, fp)) {
Cleanup();
return 0;
}
if (FCEU_fseek(fp, 0x20, SEEK_SET) < 0) {
Cleanup();
return 0;
}
if (!LoadUNIFChunks(fp)) {
Cleanup();
return 0;
}
ROM_size = (UNIF_PRGROMSize / 0x1000) + ((UNIF_PRGROMSize % 0x1000) ? 1 : 0);
ROM_size = (ROM_size >> 2) + ((ROM_size & 3) ? 1: 0);
@@ -753,48 +764,63 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
VROM_size = (VROM_size >> 3) + ((VROM_size & 7) ? 1: 0);
}
UNIFCart.PRGRomSize = UNIF_PRGROMSize;
UNIFCart.CHRRomSize = UNIF_CHRROMSize;
UNIF_PRGROMSize = FixRomSize(UNIF_PRGROMSize, 2048);
if (UNIF_CHRROMSize)
UNIF_CHRROMSize = FixRomSize(UNIF_CHRROMSize, 8192);
ROM = (uint8*)malloc(UNIF_PRGROMSize);
if (UNIF_CHRROMSize)
VROM = (uint8*)malloc(UNIF_CHRROMSize);
/* Note: Use rounded size for memory allocations and board mapping */
if (!(ROM = (uint8*)malloc(UNIF_PRGROMSize))) {
Cleanup();
return 0;
}
if (UNIF_CHRROMSize) {
if (!(VROM = (uint8*)malloc(UNIF_CHRROMSize))) {
Cleanup();
return 0;
}
}
/* combine multiple prg/chr blocks into single blocks and free memory used. */
for (x = 0; x < 16; x++) {
unsigned p = prg_idx[x];
unsigned c = 16 + chr_idx[x];
int p = prg_idx[x];
int c = 16 + chr_idx[x];
if (malloced[p]) {
memcpy(ROM + PRGptr, malloced[p], mallocedsizes[p]);
PRGptr += mallocedsizes[p];
memcpy(ROM + prg_size_bytes, malloced[p], mallocedsizes[p]);
prg_size_bytes += mallocedsizes[p];
free(malloced[p]);
malloced[p] = 0;
}
if (malloced[c]) {
memcpy(VROM + CHRptr, malloced[c], mallocedsizes[c]);
CHRptr += mallocedsizes[c];
memcpy(VROM + chr_size_bytes, malloced[c], mallocedsizes[c]);
chr_size_bytes += mallocedsizes[c];
free(malloced[c]);
malloced[c] = 0;
}
}
UNIFCart.PRGCRC32 = CalcCRC32(0, ROM, PRGptr);
UNIFCart.CHRCRC32 = CalcCRC32(0, VROM, CHRptr);
UNIFCart.CRC32 = CalcCRC32(UNIFCart.PRGCRC32, VROM, CHRptr);
/* Note: Use raw size in bytes for checksums */
UNIFCart.PRGRomSize = prg_size_bytes;
UNIFCart.CHRRomSize = chr_size_bytes;
UNIFCart.PRGCRC32 = CalcCRC32(0, ROM, prg_size_bytes);
UNIFCart.CHRCRC32 = CalcCRC32(0, VROM, chr_size_bytes);
UNIFCart.CRC32 = CalcCRC32(UNIFCart.PRGCRC32, VROM, chr_size_bytes);
md5_starts(&md5);
md5_update(&md5, ROM, PRGptr);
if (UNIF_CHRROMSize)
md5_update(&md5, VROM, CHRptr);
md5_update(&md5, ROM, prg_size_bytes);
if (chr_size_bytes)
md5_update(&md5, VROM, chr_size_bytes);
md5_finish(&md5, UNIFCart.MD5);
memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5));
CheckHashInfo();
/* Note: Use rounded size for board mappings */
SetupCartPRGMapping(0, ROM, UNIF_PRGROMSize, 0);
if (UNIF_CHRROMSize)
SetupCartCHRMapping(0, VROM, UNIF_CHRROMSize, 0);
@@ -803,8 +829,10 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
FCEU_printf(" PRG+CHR CRC32: 0x%08X\n", UNIFCart.CRC32);
FCEU_printf(" PRG+CHR MD5 : 0x%s\n", md5_asciistr(UNIFCart.MD5));
if (!InitializeBoard())
goto aborto;
if (!InitializeBoard()) {
Cleanup();
return 0;
}
FCEU_printf(" [UNIF] PRG ROM: %u KiB\n", UNIFCart.PRGRomSize / 1024);
FCEU_printf(" [UNIF] CHR ROM: %u KiB\n", UNIFCart.CHRRomSize / 1024);
@@ -814,12 +842,6 @@ int UNIFLoad(const char *name, FCEUFILE *fp) {
GameInterface = UNIFGI;
return 1;
aborto:
FreeUNIF();
ResetUNIF();
return 0;
}
int CopyFamiLoad() {
@@ -827,15 +849,11 @@ int CopyFamiLoad() {
ResetExState(0, 0);
sboardname = (uint8_t*)"COPYFAMI";
if (!InitializeBoard())
goto aborto;
if (!InitializeBoard()) {
Cleanup();
return 0;
}
GameInterface = UNIFGI;
return 1;
aborto:
FreeUNIF();
ResetUNIF();
return 0;
}