📄 romload.cpp
字号:
BlockSpeed[bank * 8 + 7] = speed;
}
for (bank = (A23 ? 0xC0 : 0x40); bank < (A23 ? 0x100 : 0x7E); bank++)
{
BlockSpeed[bank * 8 + 0] = speed;
BlockSpeed[bank * 8 + 1] = speed;
BlockSpeed[bank * 8 + 2] = speed;
BlockSpeed[bank * 8 + 3] = speed;
BlockSpeed[bank * 8 + 4] = speed;
BlockSpeed[bank * 8 + 5] = speed;
BlockSpeed[bank * 8 + 6] = speed;
BlockSpeed[bank * 8 + 7] = speed;
}
}
static void set_lower_rom_speed(void)
{
set_rom_speed(0, 0);
}
extern "C" void set_upper_rom_speed(unsigned char MEMSEL)
{
set_rom_speed(1, MEMSEL);
}
extern "C" void reset_bus_timings(void)
{
int bank, block;
/* lower ROM area - 00-3F:8000-FFFF, 40-7D:0000-FFFF; always 8 cycles */
set_lower_rom_speed();
/* upper ROM area - 80-BF:8000-FFFF, C0-FF:0000-FFFF; 6/8 cycles select */
set_upper_rom_speed(0);
/* access times in master cycles for for non-ROM areas */
/* 8 - RAM, 00-3F/80-BF:6000-7FFF */
for (bank = 0; bank < 0x40; bank++)
{
BlockSpeed[bank * 8] = 8;
BlockSpeed[bank * 8 + 3] = 8;
BlockSpeed[(bank + 0x80) * 8] = 8;
BlockSpeed[(bank + 0x80) * 8 + 3] = 8;
}
for (bank = 0x7E; bank < 0x80; bank++)
{
for (block = 0; block < 8; block++)
{
BlockSpeed[bank * 8 + block] = 8;
}
}
/* 12 - legacy CPU register area (00-3F/80-BF:4000-41FF) */
/* 6 - all remaining area (00-3F/80-BF:2000-3FFF and 4200-5FFF) */
for (bank = 0; bank < 0x40; bank++)
{
BlockSpeed[bank * 8 + 1] = 6;
BlockSpeed[bank * 8 + 2] = 6;
BlockSpeed[(bank + 0x80) * 8 + 1] = 6;
BlockSpeed[(bank + 0x80) * 8 + 2] = 6;
}
}
// SRAM is now dynamically allocated. This is to add large SRAM support
// without raising RAM requirements when using smaller SRAMs.
unsigned char *SRAM = 0;
void Free_SRAM()
{
if (SRAM) free(SRAM);
SRAM = (unsigned char *)0;
}
// SaveRamLength is bytes
int Allocate_SRAM()
{
// De-allocate any previous memory
Free_SRAM();
if (!SaveRamLength) return 0;
// We need at least 8k to use direct read
SRAM=(unsigned char *)malloc(SaveRamLength > (8 << 10) ?
SaveRamLength : (8 << 10));
if (!SRAM) return SaveRamLength;
return 0;
}
// Hack for FF6 world map glitch
// To be removed when timing improved
extern unsigned char FastROM_offset;
void Set_SNES_Map()
{
if (!strcmp(rom_name, "FINAL FANTASY 3 ") ||
!strcmp(rom_name, "FINAL FANTASY 6 "))
{
FastROM_offset = 4;
}
else
{
FastROM_offset = 5;
}
int b;
for (b = 0; b <= 0x3F; b++)
{
map_ports(b);
map_ports(b + 0x80);
}
map_wram_128k(0x7E);
}
bool Set_LoROM_Map()
{
int b;
for (b = 0; b <= 0xFF; b++)
{
map_unmapped_64k(b);
}
for (b = 0; b <= 0x3F; b++)
{
map_rom_32k_lorom(b);
map_rom_32k_lorom(b + 0x80);
map_rom_32k_lorom_40_C0(b + 0x40);
map_rom_32k_lorom_40_C0(b + 0xC0);
}
// Limit to 4Mbit/512kB SRAM
if (SaveRamLength > (512 << 10))
{
SaveRamLength = (512 << 10);
}
SRAM_Mask = SaveRamLength - 1;
if (Allocate_SRAM()) return FALSE;
/* SRAM located in banks 70 to (?) 7D, mirrored at F0 to (?) FF */
/* Complete banks mapped */
for (b = 0x70; b <= 0x7F; b++)
{
switch (SaveRamLength)
{
case 0: // No SRAM
map_no_sram_32k(b);
map_no_sram_32k(b + 0x80);
break;
case 0x800: // 16kbit/2kB SRAM
map_sram_2k_32k(b);
map_sram_2k_32k(b + 0x80);
break;
case 0x1000: // 32kbit/4kB SRAM
map_sram_4k_32k(b);
map_sram_4k_32k(b + 0x80);
break;
case 0x2000: // 64kbit/8kB SRAM
map_sram_32k(b , 0, 0, SRAM_WRITE);
map_sram_32k(b + 0x80, 0, 0, SRAM_WRITE);
break;
case 0x4000: // 128kbit/16kB SRAM
map_sram_32k(b , 0, 1, SRAM_WRITE);
map_sram_32k(b + 0x80, 0, 1, SRAM_WRITE);
break;
case 0x8000: // 256kbit/32kB SRAM
map_sram_32k(b , 0, 3, SRAM_WRITE);
map_sram_32k(b + 0x80, 0, 3, SRAM_WRITE);
break;
case 0x10000: // 512kbit/64kB SRAM
map_sram_32k(b , (b & 1) * 4, 3, SRAM_WRITE_ALT);
map_sram_32k(b + 0x80, (b & 1) * 4, 3, SRAM_WRITE_ALT);
break;
case 0x20000: // 1Mbit/128kB SRAM
map_sram_32k(b , (b & 3) * 4, 3, SRAM_WRITE_ALT);
map_sram_32k(b + 0x80, (b & 3) * 4, 3, SRAM_WRITE_ALT);
break;
case 0x40000: // 2Mbit/256kB SRAM
map_sram_32k(b , (b & 7) * 4, 3, SRAM_WRITE_ALT);
map_sram_32k(b + 0x80, (b & 7) * 4, 3, SRAM_WRITE_ALT);
break;
case 0x80000: // 4Mbit/512kB SRAM
map_sram_32k(b , (b & 15) * 4, 3, SRAM_WRITE_ALT);
map_sram_32k(b + 0x80, (b & 15) * 4, 3, SRAM_WRITE_ALT);
break;
}
}
Set_SNES_Map();
return TRUE;
}
bool Set_HiROM_Map()
{
int b;
for (b = 0; b <= 0xFF; b++)
{
map_unmapped_64k(b);
}
for (b = 0; b <= 0x3F; b++)
{
map_rom_32k_hirom(b);
map_rom_32k_hirom(b + 0x80);
map_rom_64k(b + 0x40);
map_rom_64k(b + 0xC0);
}
// Limit to 1Mbit/128kB SRAM
if (SaveRamLength > (128 << 10))
{
SaveRamLength = (128 << 10);
}
SRAM_Mask = SaveRamLength - 1;
if (Allocate_SRAM()) return FALSE;
/* SRAM located in banks 30 to (?) 3F, mirrored at B0 to (?) BF */
/* Addresses 6000-7FFF only */
for (b = 0x30; b <= 0x3F; b++)
{
switch (SaveRamLength) // Setup mapper for rest of 32k ROM banks + SRAM
{
case 0: // No SRAM
map_no_sram(b , 3);
map_no_sram(b + 0x80, 3);
break;
case 0x800: // 16kbit/2kB SRAM
map_sram_2k(b , 3);
map_sram_2k(b + 0x80, 3);
break;
case 0x1000: // 32kbit/4kB SRAM
map_sram_4k(b , 3);
map_sram_4k(b + 0x80, 3);
break;
case 0x2000: // 64kbit/8kB SRAM
map_sram(b , 3, 0, SRAM_WRITE_HIROM);
map_sram(b + 0x80, 3, 0, SRAM_WRITE_HIROM);
break;
case 0x4000: // 128kbit/16kB SRAM
map_sram(b , 3, b & 1, SRAM_WRITE_HIROM);
map_sram(b + 0x80, 3, b & 1, SRAM_WRITE_HIROM);
break;
case 0x8000: // 256kbit/32kB SRAM
map_sram(b , 3, b & 3, SRAM_WRITE_HIROM);
map_sram(b + 0x80, 3, b & 3, SRAM_WRITE_HIROM);
break;
case 0x10000: // 512kbit/64kB SRAM
map_sram(b , 3, b & 7, SRAM_WRITE_HIROM);
map_sram(b + 0x80, 3, b & 7, SRAM_WRITE_HIROM);
break;
case 0x20000: // 1Mbit/128kB SRAM
map_sram(b , 3, b & 15, SRAM_WRITE_HIROM);
map_sram(b + 0x80, 3, b & 15, SRAM_WRITE_HIROM);
break;
}
}
Set_SNES_Map();
return TRUE;
}
int ROM_has_header = Undetected;
/* Off = LoROM, On = HiROM, Undetected = autodetect */
int ROM_memory_map = Undetected;
int ROM_interleaved = Undetected;
int ROM_video_standard = Undetected;
void Load_32k(FILE *infile)
{
// Read in as 32k blocks and (de)interleave
for (int cnt = 0; cnt < rmd_64k.bank_count; cnt++) // Read first half
fread2(RomAddress + cnt * 65536 + 32768, 1, 32768, infile);
for (int cnt = 0; cnt < rmd_64k.bank_count; cnt++) // Read second half
fread2(RomAddress + cnt * 65536, 1, 32768, infile);
}
void Load_64k(FILE *infile)
{
for (int cnt = 0; cnt < rmd_64k.bank_count; cnt++) // Read in ROM
{
fread2(RomAddress + cnt * 65536, 1, 65536, infile);
}
}
unsigned check_for_header(FILE *fp, int filesize)
{
unsigned ROM_start;
// Easiest way to detect ROM header
// Improvement suggested by Gridle (implemented 22/4/99)
// check against even multiple of 1k instead of 32k
// If ROM filesize is even multiple of 1k, assume no header
// If ROM filesize is even multiple of 1k, +512, assume header
if ((((filesize % 1024) == 0) || (ROM_has_header == Off)) &&
(ROM_has_header != On)) ROM_start = 0;
else if (((filesize % 1024) == ROM_Header_Size) || (ROM_has_header == On))
ROM_start = ROM_Header_Size;
else { // Basic header detection failure
/* Gridle 04/03/1998 (dmy)
ROM header in SMC files at 0x100 - 0x1FF usually is zero. I couldn't find
any other reliable way to check if the ROM is really SMC or BIN.
Originally I checked everything from 0x10 - 0x1FF, but one of my ROMs
(Brainies) had some stupid pirate group stuff just before 0x100, so I
changed this to search from 0x100 - 0x1FF.
This is now changed to 0x100 - 0x1F9 because of the king arthur ROM.
Charles Bilyue' 06/01/1999 (dmy)
(Check was later changed to 0x110 - 0x1F9 for some reason?)
LoROM checksums at 7FDC/7FDE, 81DC/81DE with header
HiROM checksums at FFDC/FFDE, 101DC/101DE with header
*/
ROM_Header Header; // For checking if the ROM has a header
fseek2(fp,0,SEEK_SET);
fread2(&Header,ROM_Header_Size,1,fp);
ROM_start=ROM_Header_Size;
for (unsigned cnt = 0x110 - 11; cnt < 0x1FA - 11; cnt++)
if (Header.RestOfHeader[cnt] != 0){ ROM_start = 0; break; }
}
/*
if (ROM_start == ROM_Header_Size)
printf("Header detected and ignored.\n");
else
printf("No header detected.\n");
*/
return ROM_start;
}
static bool open_rom_normal(const char *Filename)
{
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);
if (ROM_start == ROM_Header_Size)
printf("Header detected and ignored.\n");
else
printf("No header detected.\n");
ROM_format = Undetected;
fseek2(infile, 0x7FC0 + ROM_start, SEEK_SET);
fread2(&RomInfoLo, sizeof(SNESRomInfoStruct), 1, infile);
fseek2(infile, 0xFFC0 + ROM_start, SEEK_SET);
fread2(&RomInfoHi, sizeof(SNESRomInfoStruct), 1, infile);
if ((RomInfoLo.Checksum ^ RomInfoLo.Complement) == 0xFFFF)
{
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;
}
}
/* *** To do: add proper type/size detection for this ROM */
/* SNES ROM header is at 01:FFC0 */
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 = (((infilesize - ROM_start) + (64 << 10) - 1)
/ (64 << 10));
rmd_32k.bank_count = (((infilesize - ROM_start) + (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)
{
case HiROM:
DisplayRomStats(&RomInfoHi);
if (!Set_HiROM_Map())
{
Free_ROM();
fclose2(infile);
return FALSE; // return false if no memory left
}
Load_64k(infile);
break;
case HiROM_Interleaved:
DisplayRomStats(&RomInfoLo);
if (!Set_HiROM_Map())
{
Free_ROM();
fclose2(infile);
return FALSE; // return false if no memory left
}
Load_32k(infile);
break;
case LoROM_Interleaved:
printf("Interleaved LoROM not supported - 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
}
Load_64k(infile);
break;
}
fclose2(infile);
return TRUE;
}
bool Load_32k_split(FILE *infile, const char *Filename, int parts, long total_size)
{
char tempname[MAXPATH];
long bytes_read = 0;
int part = 1;
int infilesize;
unsigned ROM_start;
fnsplit(Filename, fn_drive, fn_dir, fn_file, fn_ext);
// Read in as 32k blocks and interleave
for (int cnt = 0;
cnt < rmd_64k.bank_count && part <= parts; cnt++) // Read first half
{
infilesize = fread2(RomAddress + cnt * 65536 + 32768, 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
fclose2(infile);
if (++part > parts)
{
if (bytes_read != total_size) return FALSE;
else break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -