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

📄 romload.cpp

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