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

📄 romload.cpp

📁 NES game Emulator in Linux.c and asm codes.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*

SNEeSe, an Open Source Super NES emulator.


Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.

This is free software.  See 'LICENSE' for details.
You must read and accept the license prior to use.

*/

/*  ROM IMAGE LOADING MECHANISM
    Original code by Savoury SnaX & Santeri Saarimaa
    New development by Charles Bilyue'

    Supports (with or without header):
     Single-part non-interleaved ROMs (LoROM and HiROM)
     Single-part interleaved HiROMs
     Multi-part non-interleaved ROMs (LoROM and HiROM, *.1-style)
     Multi-part interleaved HiROMs (*.1-style)

    If a header exists, it is ignored

       Single-part ROM extensions
        SFC = Super FamiCom
        FIG = Pro Fighter
        SMC = Super MagiCom
        SWC = Super WildCard

        BIN = Binary

       Multi-part ROM extensions
        SF*a.058,SF*a.078 = Game Doctor
        *.1 = Other miscellaneous multi-part ROM

    TO DO:
        Interleaved LoROM loading (??? need info)
        Other memory maps
*/

#include "wrapaleg.h"

#include <iostream>

using namespace std;


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "romload.h"
#include "helper.h"
#include "cpu/cpu.h"
#include "apu/spc.h"
#include "cpu/mem.h"
#include "snes.h"
#include "platform.h"
#include "multiio.h"


char *rom_romfile = 0;
char *rom_romhilo = 0;
char *rom_romtype = 0;
char *rom_romsize = 0;
char *rom_romname = 0;
char *rom_sram = 0;
char *rom_country = 0;
char rom_name[22];

extern "C" unsigned char BlockSpeed[256*8];

unsigned char BlockSpeed[256*8];

unsigned char *RomAddress;      // Address of SNES ROM

// Used to determine size of file for saving/loading, and to restrict writes
//  to non-existant SRAM
unsigned SaveRamLength = 0;

int Allocate_ROM();
int ROM_format;

typedef struct {
 int bank_count;
 unsigned char overflow_mask;
 unsigned char bank_lookup[256];
} ROM_MIRRORING_DATA;

ROM_MIRRORING_DATA rmd_32k, rmd_64k;

void setup_rom_mirroring(ROM_MIRRORING_DATA *rmd)
{
    int copycount, missing, count, next, banks_mirror_size;

    /* Compute a mask used to wrap invalid ROM bank numbers.
     */
    if (((rmd->bank_count * 2 - 1) & (rmd->bank_count - 1)) ==
     (rmd->bank_count - 1))
    /* compute mask for even power of two */
    {
        banks_mirror_size = rmd->bank_count;
    }
    else
    /* compute mask */
    {
        int i;

        /* compute the smallest even power of 2 greater than
           ROM bank count, and use that to compute the mask */
        for (i = 0; (rmd->bank_count >> i) > 0; i++);

        banks_mirror_size = (1 << i);
    }

    rmd -> overflow_mask = banks_mirror_size - 1;


    /* identity-map all the present banks */
    for (copycount = 0; copycount < rmd->bank_count; copycount++)
    {
        rmd -> bank_lookup [copycount] = copycount;
    }


    /* mirror-map all the not-present banks */
    for (next = rmd->bank_count, missing = banks_mirror_size - rmd->bank_count,
        count = 1; missing; count <<= 1, missing >>= 1)
    {
        if (missing & 1)
        {
            for (copycount = count; copycount; copycount--, next++)
            {
                rmd -> bank_lookup[next] =
                    rmd -> bank_lookup[next - count];
            }
        }
    }
}


SNESRomInfoStruct RomInfoLo, RomInfoHi;

int LoadSRAM(char *SRAM_filename)
{
 if (!snes_rom_loaded || !SaveRamLength) return 0;   // No SRAM

 // Return if we can't get SRAM filename
 if (CreateSRAMFilename(ROM_filename)) return 0;

 FILE *Infile = fopen(SRAM_filename, "rb");
 if (!Infile) return 0;         // Can't open file

 fread(SRAM, 1, SaveRamLength, Infile); // Read Save Ram

 /* Apply mirroring for small SRAMs, for reads */
 switch (SaveRamLength)
 {
  case (2 << 10):
   memcpy(SRAM + (2 << 10), SRAM, (2 << 10));
  case (4 << 10):
   memcpy(SRAM + (4 << 10), SRAM, (4 << 10));
 }

 fclose(Infile);
 return -1;
}

int SaveSRAM(char *SRAM_filename)
{
 if (!snes_rom_loaded || !SaveRamLength) return 0;   // No SRAM

 // Return if we can't get SRAM filename
 if (CreateSRAMFilename(ROM_filename)) return 0;

 FILE *Outfile = fopen(SRAM_filename, "wb");
 if (!Outfile) return 0;        // Can't open file

 fwrite(SRAM, 1, SaveRamLength, Outfile);   // Write Save Ram

 fclose(Outfile);
 return -1;
}

char *ROM_filename = 0;
char fn_drive[MAXDRIVE], fn_dir[MAXDIR], fn_file[MAXFILE], fn_ext[MAXEXT];
char SRAM_filename[MAXPATH];
char save_dir[MAXPATH];
char save_extension[MAXEXT];

ROMFileType GetROMFileType(const char *ROM_filename)
{
 fnsplit(ROM_filename, fn_drive, fn_dir, fn_file, fn_ext);
 if (!fn_ext) return ROMFileType_normal;
 if (!strcmp(fn_ext, ".1")) return ROMFileType_split;
/*
 if (fn_file)
 {
  if (!strnicmp(fn_file, "SF", 2)
   && (!strcmp(fn_ext, ".058") || !strcmp(fn_ext, ".078")))
  {
   printf("Game Doctor ROM detected.\n");
   return ROMFileType_gamedoctor;
  }
 }

 if (!stricmp(fn_ext, ".zip"))
 {
  printf("Compressed ROM detected.\n");
  return ROMFileType_compressed;
 }

 if (!stricmp(fn_ext, ".rar"))
 {
  printf("Compressed ROM detected.\n");
  return ROMFileType_compressed;
 }*/
 return ROMFileType_normal;
}

bool CreateSRAMFilename(char *ROM_filename)
{
 int length, slength;

 SRAM_filename[0] = 0;

 length = 1;    // 1 for the null
 fnsplit(ROM_filename, fn_drive, fn_dir, fn_file, fn_ext);
 if (!fn_file) return TRUE;
 length += strlen(fn_file);

 if (strlen(save_extension))
 {
  length += strlen(save_extension);
  if (save_extension[0] != '.') ++length; // One for leading period
 }

 slength = strlen(save_dir);
 if (slength)
 {
  length += slength;
  if (save_dir[slength - 1] != '/' && save_dir[slength - 1] != '\\')
   ++length;    // One for trailing slash
 } else {
  if (strlen(fn_drive))
  {
   length += strlen(fn_drive);
  }

  slength = strlen(fn_dir);
  if (slength)
  {
   length += slength;
   if (fn_dir[slength - 1] != '/' && fn_dir[slength - 1] != '\\')
    ++length;    // One for trailing slash
  }
 }

 if (length > MAXPATH) return TRUE;

 if (strlen(save_dir))
 {
  strcat(SRAM_filename, save_dir);
  if (save_dir[slength - 1] != '/' && save_dir[slength - 1] != '\\')
   strcat(SRAM_filename, "/");  // Add missing trailing slash
 } else {
  if (strlen(fn_drive))
  {
   strcat(SRAM_filename, fn_drive);
  }

  if (strlen(fn_dir))
  {
   strcat(SRAM_filename, fn_dir);
   if (fn_dir[slength - 1] != '/' && fn_dir[slength - 1] != '\\')
    strcat(SRAM_filename, "/");  // Add missing trailing slash
  }
 }

 strcat(SRAM_filename, fn_file);

 if (strlen(save_extension))
 {
  if (save_extension[0] != '.')
   strcat(SRAM_filename, ".");  // Add missing leading period
  strcat(SRAM_filename, save_extension);
 }

 return FALSE;
}

void DisplayRomStats(SNESRomInfoStruct *RomInfo);

// ROM is now dynamically allocated. This is to add large ROM support
// without raising RAM requirements when using smaller ROMs.
static unsigned char *AllocROMAddress = 0;

void Free_ROM()
{
 if (AllocROMAddress) free(AllocROMAddress);
 AllocROMAddress = (unsigned char *)0;
}

int Allocate_ROM()
{
 // De-allocate any previous memory
 Free_ROM();

 AllocROMAddress =
  (unsigned char *) malloc (rmd_64k.bank_count * (64 << 10) + (12 << 10));
 if (!AllocROMAddress) return rmd_64k.bank_count * (64 << 10) + (12 << 10);

 RomAddress =   // Force 4k alignment/8k misalignment
  (unsigned char *)(((unsigned)
   ((AllocROMAddress + ((8 << 10) - 1))) & ~((8 << 10) - 1)) + (4 << 10));
 memset(RomAddress, 0xFF, rmd_64k.bank_count * (64 << 10));

 return 0;
}

unsigned SRAM_Mask;

inline void set_block_read_handler(int bank, int block, void (*read)(void))
{
 Read_Bank8Mapping [bank * 8 + block] = (void (*)(void)) read;
 Read_Bank8Offset [bank * 8 + block] = (void *) 0;
}

inline void set_block_read_pointer(int bank, int block, void *read)
{
 Read_Bank8Mapping [bank * 8 + block] =
  (void (*)(void)) Read_Direct_Safeguard;
 Read_Bank8Offset [bank * 8 + block] = (void *) read;
}

inline void set_block_write_handler(int bank, int block, void (*write)(void))
{
 Write_Bank8Mapping[bank * 8 + block] = (void (*)(void)) write;
 Write_Bank8Offset[bank * 8 + block] = (void *) 0;
}

inline void set_block_write_pointer(int bank, int block, void *write)
{
 Write_Bank8Mapping[bank * 8 + block] =
  (void (*)(void)) Write_Direct_Safeguard;
 Write_Bank8Offset[bank * 8 + block] = (void *) write;
}

inline void set_block_handlers(int bank, int block, void (*read)(void), void (*write)(void))
{
 set_block_read_handler(bank, block, read);
 set_block_write_handler(bank, block, write);
}

inline void set_block_pointers(int bank, int block, void *read, void *write)
{
 set_block_read_pointer(bank, block, read);
 set_block_write_pointer(bank, block, write);
}

inline void map_wram(int bank, int block)
{
 set_block_pointers(bank, block, (void *) (WRAM - (bank << 16)), (void *) (WRAM - (bank << 16)));
}

inline void map_wram_128k(int bank)
{
 for (int i = 0; i < 8; i++)
 {
  set_block_pointers(bank, i, (void *) (WRAM - (bank << 16)), (void *) (WRAM - (bank << 16)));
  set_block_pointers(bank + 1, i, (void *) (WRAM - (bank << 16)), (void *) (WRAM - (bank << 16)));
 }
}

inline void map_unmapped(int bank, int block)
{
 set_block_handlers(bank, block, &CPU_OPEN_BUS_READ, &IGNORE_WRITE);
}

inline void map_unmapped_32k(int bank)
{
 for (int i = 4; i < 8; i++) map_unmapped(bank, i);
}

inline void map_unmapped_64k(int bank)
{
 for (int i = 0; i < 8; i++) map_unmapped(bank, i);
}

inline void map_blank(int bank, int block)
{
 set_block_pointers(bank, block, (void *) 0, (void *) (Dummy - (bank << 16)));
 map_unmapped(bank, block);
}

inline void map_blank_32k(int bank)
{
 for (int i = 4; i < 8; i++) map_blank(bank, i);
}

inline void map_blank_64k(int bank)
{
 for (int i = 0; i < 8; i++) map_blank(bank, i);
}

inline void map_sram(int bank, int block, int sram_block,
 void (*sram_write_handler)(void))
{
 set_block_read_pointer(bank, block,
  SRAM + (sram_block << 13) - (bank << 16) - (block << 13));
// set_block_write_pointer(bank, block,
//  SRAM + (sram_block << 13) - (bank << 16) - (block << 13));
 set_block_write_handler(bank, block, sram_write_handler);
}

inline void map_no_sram(int bank, int block)
{
 map_blank(bank, block);
}

inline void map_sram_2k(int bank, int block)
{
 set_block_read_pointer(bank, block, SRAM - (bank << 16) - (block << 13));
 set_block_write_handler(bank, block, &SRAM_WRITE_2k);
}

inline void map_sram_4k(int bank, int block)
{
 set_block_read_pointer(bank, block, SRAM - (bank << 16) - (block << 13));
 set_block_write_handler(bank, block, &SRAM_WRITE_4k);
}

inline void map_sram_32k(int bank, int sram_block, int mask,
 void (*sram_write_handler)(void))
{
 for (int i = 0; i < 4; i++) map_sram(bank, i, sram_block + (i & mask),
  sram_write_handler);
}

inline void map_no_sram_32k(int bank)
{
 for (int i = 0; i < 4; i++) map_no_sram(bank, i);
}

inline void map_sram_2k_32k(int bank)
{
 for (int i = 0; i < 4; i++) map_sram_2k(bank, i);
}

inline void map_sram_4k_32k(int bank)
{
 for (int i = 0; i < 4; i++) map_sram_4k(bank, i);
}

inline void map_rom_32k_lorom(int bank)
{
 int needed_bank;

 needed_bank = rmd_32k.bank_lookup [(bank ^ 0x80) & rmd_32k.overflow_mask];

 for (int i = 4; i < 8; i++)
 {
  set_block_pointers(bank, i, (void *) (RomAddress - ((bank - needed_bank) << 16) - (needed_bank + 1) * 0x8000), (void *) (Dummy - (bank << 16)));
 }
}

inline void map_rom_32k_lorom_40_C0(int bank)
{
 int needed_bank;

 needed_bank = rmd_32k.bank_lookup [(bank ^ 0x80) & rmd_32k.overflow_mask];

 for (int i = 0; i < 4; i++)
 {
  set_block_pointers(bank, i, (void *) (RomAddress - ((bank - needed_bank) << 16) - (needed_bank & 0x7F) * 0x8000), (void *) (Dummy - (bank << 16)));
 }

 map_rom_32k_lorom(bank);
}

inline void map_rom_32k_hirom(int bank)
{
 int needed_bank;

 needed_bank = rmd_64k.bank_lookup [
  ((bank & 0x80 ? 0 : 0x40) + (bank & 0x3F)) & rmd_64k.overflow_mask];

 for (int i = 4; i < 8; i++)
 {
  set_block_pointers(bank, i, (void *) (RomAddress - ((bank - needed_bank) << 16)), (void *) (Dummy - (bank << 16)));
 }
}

inline void map_rom_64k(int bank)
{
 int needed_bank;

 needed_bank = rmd_64k.bank_lookup [
  ((bank & 0x80 ? 0 : 0x40) + (bank & 0x3F)) & rmd_64k.overflow_mask];

 for (int i = 0; i < 8; i++)
 {
  set_block_pointers(bank, i, (void *) (RomAddress - ((bank - needed_bank) << 16)), (void *) (Dummy - (bank << 16)));
 }
}

inline void map_ports(int bank)
{
 map_wram(bank, 0);
 set_block_handlers(bank, 1, &PPU_READ, &PPU_WRITE);
 set_block_handlers(bank, 2, &PPU_READ, &PPU_WRITE);
}

static inline void set_rom_speed(int A23, unsigned char MEMSEL)
{
 int bank, speed;

 speed = (MEMSEL & 1) ? 6 : 8;

 for (bank = (A23 ? 0x80 : 0); bank < (A23 ? 0xC0 : 0x40); bank++)
 {
  BlockSpeed[bank * 8 + 4] = speed;
  BlockSpeed[bank * 8 + 5] = speed;
  BlockSpeed[bank * 8 + 6] = speed;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -