📄 romload.cpp
字号:
sprintf(fn_ext, ".%d", part);
fnmerge(tempname, fn_drive, fn_dir, fn_file, fn_ext);
FILE *infile=fopen2(tempname,"rb");
if (!infile) return FALSE;
fseek2(infile, 0, SEEK_END);
infilesize = ftell2(infile);
ROM_start = check_for_header(infile, infilesize);
total_size -= ROM_start;
fseek2(infile,ROM_start,SEEK_SET);
infilesize =
fread2(RomAddress + cnt * 65536 + 32768 + (bytes_read % 32768), 1,
32768 - (bytes_read % 32768), infile);
if (infilesize != EOF) bytes_read += infilesize;
}
}
for (int cnt = 0;
cnt < rmd_64k.bank_count && part <= parts; cnt++) // Read second half
{
infilesize = fread2(RomAddress + cnt * 65536, 1, 32768, infile);
if (infilesize != EOF) bytes_read += infilesize;
while ((bytes_read % 32768) || (infilesize < 1))
{
// partial bank read, must complete (or nothing read, go to next file)
// next file
if (++part > parts)
{
if (bytes_read != total_size) return FALSE;
else break;
}
fclose2(infile);
sprintf(fn_ext, ".%d", part);
fnmerge(tempname, fn_drive, fn_dir, fn_file, fn_ext);
FILE *infile=fopen2(tempname,"rb");
if (!infile) return FALSE;
fseek2(infile, 0, SEEK_END);
infilesize = ftell2(infile);
ROM_start = check_for_header(infile, infilesize);
total_size -= ROM_start;
fseek2(infile,ROM_start,SEEK_SET);
infilesize =
fread2(RomAddress + cnt * 65536 + (bytes_read % 32768), 1,
32768 - (bytes_read % 32768), infile);
if (infilesize != EOF) bytes_read += infilesize;
}
}
fclose2(infile);
return TRUE;
}
static bool open_rom_split(const char *Filename)
{
char tempname[MAXPATH];
int parts;
long total_size = 0;
fnsplit(Filename, fn_drive, fn_dir, fn_file, fn_ext);
for (parts = 1; parts < 1000; parts++)
{
sprintf(fn_ext, ".%d", parts + 1);
fnmerge(tempname, fn_drive, fn_dir, fn_file, fn_ext);
FILE *infile=fopen2(tempname,"rb");
if (!infile) break;
fseek2(infile, 0, SEEK_END);
total_size += ftell2(infile);
fclose2(infile);
}
if (parts == 1) return open_rom_normal(Filename);
printf("Split ROM image detected - %d parts found.\n", parts);
FILE *infile=fopen2(Filename,"rb");
if (!infile) return FALSE; // File aint there m8
unsigned ROM_start; // This is where the ROM code itself starts.
fseek2(infile, 0, SEEK_END);
int infilesize = ftell2(infile);
ROM_start = check_for_header(infile, infilesize);
total_size += infilesize - ROM_start;
ROM_format = Undetected;
unsigned RomInfoHi_Read;
fseek2(infile,0x7FC0+ROM_start,SEEK_SET);
if (fread2(&RomInfoLo,sizeof(SNESRomInfoStruct),1,infile) != 1)
{
fclose2(infile);
return FALSE;
}
fseek2(infile,0xFFC0+ROM_start,SEEK_SET);
RomInfoHi_Read = fread2(&RomInfoHi,sizeof(SNESRomInfoStruct),1,infile);
// if checksum and complement match, or HiROM info block couldn't be read
if ((RomInfoLo.Checksum^RomInfoLo.Complement) == 0xFFFF ||
RomInfoHi_Read != 1)
{
if ((RomInfoLo.ROM_makeup&0x0F)==1)
{
strcpy(rom_romhilo,"Interleaved HiROM detected");
ROM_format = HiROM_Interleaved;
} else {
strcpy(rom_romhilo,"LoROM detected");
ROM_format = LoROM;
}
} else {
if (((RomInfoHi.Checksum^RomInfoHi.Complement) == 0xFFFF))
{
strcpy(rom_romhilo,"HiROM detected");
ROM_format = HiROM;
} else {
strcpy(rom_romhilo,"Detection failed, using LoROM");
ROM_format = LoROM;
}
}
if (!strcmp(rom_name, "BATMAN--REVENGE JOKER"))
{
ROM_format = LoROM;
}
switch (ROM_memory_map)
{
case HiROM:
if (ROM_format & HiROM) break;
ROM_format = HiROM;
strcpy(rom_romhilo, "HiROM forced"); break;
case LoROM:
if (!(ROM_format & HiROM)) break;
ROM_format = LoROM;
strcpy(rom_romhilo, "LoROM forced"); break;
}
switch (ROM_interleaved)
{
case On: ROM_format |= Interleaved; break;
case Off: ROM_format &= ~Interleaved; break;
}
rmd_64k.bank_count = ((total_size + (64 << 10) - 1) / (64 << 10));
rmd_32k.bank_count = ((total_size + (32 << 10) - 1) / (32 << 10));
// Maximum 64Mbit ROM size for LoROM
if (rmd_64k.bank_count > 128)
{
rmd_64k.bank_count = 128;
rmd_32k.bank_count = 256;
}
if (Allocate_ROM()) // Dynamic allocation of ROM
{
fclose2(infile);
return FALSE; // return false if no memory left
}
setup_rom_mirroring(&rmd_32k);
setup_rom_mirroring(&rmd_64k);
fseek2(infile,ROM_start,SEEK_SET);
switch(ROM_format)
{
long bytes_read;
case HiROM:
DisplayRomStats(&RomInfoHi);
if (!Set_HiROM_Map())
{
Free_ROM();
fclose2(infile);
return FALSE; // return false if no memory left
}
bytes_read = fread2(RomAddress,1,total_size,infile);
fclose2(infile);
fnsplit(Filename, fn_drive, fn_dir, fn_file, fn_ext);
for (int part = 2; part <= parts; part++)
{
sprintf(fn_ext, ".%d", part);
fnmerge(tempname, fn_drive, fn_dir, fn_file, fn_ext);
FILE *infile=fopen2(tempname,"rb");
if (!infile) break;
fseek2(infile, 0, SEEK_END);
infilesize = ftell2(infile);
ROM_start = check_for_header(infile, infilesize);
total_size -= ROM_start;
fseek2(infile,ROM_start,SEEK_SET);
infilesize =
fread2(RomAddress + bytes_read, 1, total_size - bytes_read, infile);
fclose2(infile);
if (infilesize == EOF) break;
if (total_size == bytes_read) break;
bytes_read += infilesize;
}
if (infilesize == EOF) return FALSE;
if (!infile) return FALSE;
break;
case HiROM_Interleaved:
DisplayRomStats(&RomInfoLo);
if (!Set_HiROM_Map())
{
Free_ROM();
fclose2(infile);
return FALSE; // return false if no memory left
}
return Load_32k_split(infile, Filename, parts, total_size);
break;
case LoROM_Interleaved:
printf("Split interleaved LoROM not supported - split basic LoROM loader used\n");
case LoROM:
default:
DisplayRomStats(&RomInfoLo);
if (!Set_LoROM_Map())
{
Free_ROM();
fclose2(infile);
return FALSE; // return false if no memory left
}
bytes_read = fread2(RomAddress,1,total_size,infile);
fclose2(infile);
fnsplit(Filename, fn_drive, fn_dir, fn_file, fn_ext);
for (int part = 2; part <= parts; part++)
{
sprintf(fn_ext, ".%d", part);
fnmerge(tempname, fn_drive, fn_dir, fn_file, fn_ext);
FILE *infile=fopen2(tempname,"rb");
if (!infile) break;
fseek2(infile, 0, SEEK_END);
infilesize = ftell2(infile);
ROM_start = check_for_header(infile, infilesize);
total_size -= ROM_start;
fseek2(infile,ROM_start,SEEK_SET);
infilesize =
fread2(RomAddress + bytes_read, 1, total_size - bytes_read, infile);
fclose2(infile);
if (infilesize == EOF) break;
if (total_size == bytes_read) break;
bytes_read += infilesize;
}
if (infilesize == EOF) return FALSE;
if (!infile) return FALSE;
break;
}
return TRUE;
}
/* Filename must contain a full path */
int open_rom(const char *Filename)
{
ROMFileType filetype;
SaveSRAM(SRAM_filename); // Ensures SRAM saved before loading new ROM
snes_rom_loaded = FALSE;
SaveRamLength = 0;
filetype = GetROMFileType(Filename);
if (!ROM_filename) ROM_filename = (char *) malloc(MAXPATH);
if (!rom_romfile) rom_romfile = (char *) malloc(MAXPATH);
if (!rom_romhilo) rom_romhilo = (char *) malloc(100);
if (!rom_romtype) rom_romtype = (char *) malloc(50);
if (!rom_romsize) rom_romsize = (char *) malloc(50);
if (!rom_romname) rom_romname = (char *) malloc(50);
if (!rom_sram) rom_sram = (char *) malloc(50);
if (!rom_country) rom_country = (char *) malloc(50);
if (!ROM_filename || !rom_romfile || !rom_romhilo
|| !rom_romtype || !rom_romsize || !rom_romname
|| !rom_sram || !rom_country)
return FALSE;
strcpy(ROM_filename, Filename);
strcpy(rom_romfile, Filename);
switch (filetype)
{
case ROMFileType_split: snes_rom_loaded = open_rom_split(Filename); break;
case ROMFileType_normal:
default: snes_rom_loaded = open_rom_normal(Filename);
}
if (snes_rom_loaded == FALSE) return FALSE;
Reset_Memory();
Reset_SRAM();
snes_reset();
LoadSRAM(SRAM_filename); // This loads in the Save RAM
printf("RES: %04X\n"
"NMI N,E: %04X,%04X\n"
"IRQ N,E: %04X,%04X\n"
"BRK N,E: %04X,%04X\n"
"COP N,E: %04X,%04X\n",
cpu_65c816_PC,
NMI_Nvector, NMI_Evector,
IRQ_Nvector, IRQ_Evector,
BRK_Nvector, IRQ_Evector,
COP_Nvector, COP_Evector);
FILE *memmap_dmp = fopen("memmap.dmp", "wb");
if (memmap_dmp)
{
fwrite(Read_Bank8Offset, sizeof(Read_Bank8Offset), 1, memmap_dmp);
fwrite(Write_Bank8Offset, sizeof(Write_Bank8Offset), 1, memmap_dmp);
fwrite(Read_Bank8Mapping, sizeof(Read_Bank8Mapping), 1, memmap_dmp);
fwrite(Write_Bank8Mapping, sizeof(Write_Bank8Mapping), 1, memmap_dmp);
fwrite(&SRAM, sizeof(SRAM), 1, memmap_dmp);
fclose(memmap_dmp);
}
return TRUE;
}
char *TypeTable[]={
"ROM",
"ROM+RAM",
"ROM+SRAM",
"ROM+DSP1",
"ROM+RAM+DSP1",
"ROM+SRAM+DSP1",
"Unknown",
"Unknown FX chip",
"FX-V1",
"FX(Argonaut)",
"FX-V2",
"FX(SA-1)",
"FX(?KSS?)",
"FX(Capcom)",
"FX(S-DD1)",
"FX(PLGS)",
"FX(Gameboy)",
"FX(BS-X)",
"FX(Capcom C4)",
"FX(SETA) (DSP2?)",
"FX(OBC1)"
};
char *CountryTable[]={
"Japan",
"USA",
"Europe, Oceania, Asia", // Australia is part of Oceania
"Sweden",
"Finland",
"Denmark",
"France",
"Holland",
"Spain",
"Germany, Austria, Switzerland",
"Italy",
"Hong Kong, China",
"Indonesia",
"South Korea"
};
void DisplayRomStats(SNESRomInfoStruct *RomInfo)
{
// ROM Type
switch(RomInfo->ROM_type)
{
case 0: // ROM
case 1: // ROM/RAM
case 2: // ROM/SRAM
case 3: // ROM/DSP1
case 4: // ROM/RAM/DSP1
case 5: // ROM/SRAM/DSP1
strcpy(rom_romtype, TypeTable[RomInfo->ROM_type]); break;
case 0x10 ... 0x12: case 0x16:
case 0x20 ... 0x24: case 0x26:
case 0x30 ... 0x34:
case 0x40 ... 0x42: case 0x44: case 0x46:
case 0x50 ... 0x54: case 0x56:
case 0x60 ... 0x66: case 0x70 ... 0x76:
case 0x80 ... 0x86: case 0x90 ... 0x96:
case 0xA0 ... 0xA6: case 0xB0 ... 0xB6:
case 0xC0 ... 0xC6: case 0xD0 ... 0xD6:
case 0xE0 ... 0xE2: case 0xE4: case 0xE6:
case 0xF0 ... 0xF2: case 0xF4 ... 0xF5:
// Unknown FX chip
strcpy(rom_romtype, TypeTable[7]);
case 0x13: // FX-V1
strcpy(rom_romtype, TypeTable[8]); break;
case 0x14: // FX(Argonaut)
strcpy(rom_romtype, TypeTable[9]); break;
case 0x15: // FX-V2
strcpy(rom_romtype, TypeTable[10]); break;
case 0x35: // FX(SA-1)
strcpy(rom_romtype, TypeTable[11]); break;
case 0x36: // FX(?KSS?)
strcpy(rom_romtype, TypeTable[12]); break;
case 0x43: // FX(Capcom)
strcpy(rom_romtype, TypeTable[13]); break;
case 0x45: // FX(S-DD1)
strcpy(rom_romtype, TypeTable[14]); break;
case 0x55: // FX(PLGS)
strcpy(rom_romtype, TypeTable[15]); break;
case 0xE3: // FX(Gameboy)
strcpy(rom_romtype, TypeTable[16]); break;
case 0xE5: // FX(BS-X)
strcpy(rom_romtype, TypeTable[17]); break;
case 0xF3: // FX(Capcom C4)
strcpy(rom_romtype, TypeTable[18]); break;
case 0xF6: // FX(SETA) (DSP2?)
strcpy(rom_romtype, TypeTable[19]); break;
case 0x25: // OBC1, used by Metal Combat
strcpy(rom_romtype, TypeTable[20]); break;
default: // Unknown
strcpy(rom_romtype, TypeTable[6]);
}
// ROM Size
sprintf(rom_romsize, "%dMbits", 1 << ((RomInfo->ROM_size) - 7));
// ROM SRAM size
SaveRamLength = RomInfo->SRAM_size;
if (((RomInfo->ROM_type) == 2) || ((RomInfo->ROM_type) >= 5) &&
SaveRamLength)
{
SaveRamLength = 1024 << SaveRamLength;
sprintf(rom_sram, "%dKbits", SaveRamLength * 8 / 1024);
} else {
SaveRamLength = 0;
strcpy(rom_sram,"No SRAM");
}
// ROM Country
if (RomInfo->Country_code <= 13)
{
strcpy(rom_country, CountryTable[ RomInfo->Country_code ]);
/* Japan, USA, Korea == NTSC */
if ((((RomInfo->Country_code < 2) || (RomInfo->Country_code == 13)
) && (ROM_video_standard != PAL_video))
|| (ROM_video_standard == NTSC_video))
{
strcat(rom_country,
(ROM_video_standard != NTSC_video) ? " (NTSC)" : " (NTSC forced)");
set_snes_ntsc();
}
else if (((RomInfo->Country_code < 14) && (ROM_video_standard != NTSC_video))
|| (ROM_video_standard == PAL_video))
{
strcat(rom_country,
(ROM_video_standard != PAL_video) ? " (PAL)" : " (PAL forced)");
set_snes_pal();
}
} else {
switch (ROM_video_standard)
{
case PAL_video:
strcpy(rom_country, "Unknown (PAL forced)");
set_snes_pal();
break;
case NTSC_video:
strcpy(rom_country, "Unknown (NTSC forced)");
set_snes_ntsc();
break;
default:
strcpy(rom_country, "Unknown (Using NTSC)");
set_snes_ntsc();
}
}
// ROM Name
for (int i = 0; i < 21; i++)
rom_name[i] = RomInfo->ROM_Title[i];
rom_name[21] = 0;
strcpy(rom_romname,rom_name);
// Print information
printf("\nROM title: %s\n", rom_romname);
printf("ROM type: %s\n",rom_romtype);
if ((RomInfo->ROM_type) > 2)
printf("Some extra hardware used by this ROM is not yet supported!\n");
printf("%s\n",rom_romhilo);
printf("ROM size: %s\n",rom_romsize);
printf("SRAM size: %s\n",rom_sram);
printf("Country: %s\n",rom_country);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -