⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 romload.cpp

📁 NES game Emulator in Linux.c and asm codes.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  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 + -