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

📄 memmap.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and *                           Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code  * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and *                           Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include <string.h>#include <ctype.h>#ifdef __linux#include <unistd.h>#endif#include "snes9x.h"#include "memmap.h"#include "cpuexec.h"#include "ppu.h"#include "display.h"#include "cheats.h"#include "apu.h"#include "sa1.h"#include "srtc.h"#ifndef ZSNES_FX#include "fxemu.h"extern struct FxInit_s SuperFX;#elseSTART_EXTERN_Cextern uint8 *SFXPlotTable;END_EXTERN_C#endifstatic uint8 bytes256 [256];extern char *rom_filename;bool8 CMemory::AllASCII (uint8 *b, int size){    for (int i = 0; i < size; i++)    {	if (b[i] < 32 || b[i] > 126)	    return (FALSE);    }    return (TRUE);}int CMemory::ScoreHiROM (bool8 skip_header){    int score = 0;    int o = skip_header ? 0xff00 + 0x200 : 0xff00;    if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +	 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)	score += 2;    if (Memory.ROM [o + 0xda] == 0x33)	score += 2;    if ((Memory.ROM [o + 0xd5] & 0xf) < 4)	score += 2;    if (!(Memory.ROM [o + 0xfd] & 0x80))	score -= 4;    if (CalculatedSize > 1024 * 1024 * 3)	score += 4;    if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)	score -= 1;    if (!AllASCII (&Memory.ROM [o + 0xb0], 6))	score -= 1;    if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))	score -= 1;    return (score);}int CMemory::ScoreLoROM (bool8 skip_header){    int score = 0;    int o = skip_header ? 0x7f00 + 0x200 : 0x7f00;    if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +	 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)	score += 2;    if (Memory.ROM [o + 0xda] == 0x33)	score += 2;    if ((Memory.ROM [o + 0xd5] & 0xf) < 4)	score += 2;    if (CalculatedSize <= 1024 * 1024 * 16)	score += 2;    if (!(Memory.ROM [o + 0xfd] & 0x80))	score -= 4;    if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)	score -= 1;    if (!AllASCII (&Memory.ROM [o + 0xb0], 6))	score -= 1;    if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))	score -= 1;    return (score);}	char *CMemory::Safe (const char *s){    static char *safe = NULL;    static int safe_len = 0;    int len = strlen (s);    if (!safe || len + 1 > safe_len)    {	delete safe;	safe = new char [safe_len = len + 1];    }    for (int i = 0; i < len; i++)    {	if (s [i] >= 32 && s [i] < 127)	    safe [i] = s[i];	else	    safe [i] = '?';    }    safe [len] = 0;    return (safe);}/**********************************************************************************************//* Init()                                                                                     *//* This function allocates all the memory needed by the emulator                              *//**********************************************************************************************/bool8 CMemory::Init (){    RAM	    = new uint8 [0x20000];    SRAM    = new uint8 [0x20000];    VRAM    = new uint8 [0x10000];    ROM     = new uint8 [MAX_ROM_SIZE + 0x200 + 0x8000];    FillRAM = NULL;    IPPU.TileCache [TILE_2BIT] = new uint8 [MAX_2BIT_TILES * 128];    IPPU.TileCache [TILE_4BIT] = new uint8 [MAX_4BIT_TILES * 128];    IPPU.TileCache [TILE_8BIT] = new uint8 [MAX_8BIT_TILES * 128];        IPPU.TileCached [TILE_2BIT] = new uint8 [MAX_2BIT_TILES];    IPPU.TileCached [TILE_4BIT] = new uint8 [MAX_4BIT_TILES];    IPPU.TileCached [TILE_8BIT] = new uint8 [MAX_8BIT_TILES];        if( !RAM || !SRAM || !VRAM || !ROM || !IPPU.TileCache [TILE_2BIT] ||	!IPPU.TileCache [TILE_4BIT] || !IPPU.TileCache [TILE_8BIT] ||	!IPPU.TileCached [TILE_2BIT] || !IPPU.TileCached [TILE_4BIT] ||	!IPPU.TileCached [TILE_8BIT])	return (FALSE);	    // FillRAM uses first 32K of ROM image area, otherwise space just    // wasted. Might be read by the SuperFX code.    FillRAM = ROM;    // Add 0x8000 to ROM image pointer to stop SuperFX code accessing    // unallocated memory (can cause crash on some ports).    ROM += 0x8000;    C4RAM    = ROM + 0x400000 + 8192 * 8;    ::ROM    = ROM;    ::SRAM   = SRAM;    ::RegRAM = FillRAM;#ifdef ZSNES_FX    SFXPlotTable = ROM + 0x400000;#else    SuperFX.pvRegisters = &Memory.FillRAM [0x3000];    SuperFX.nRamBanks = 1;    SuperFX.pvRam = ::SRAM;    SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);    SuperFX.pvRom = (uint8 *) ROM;#endif    ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES);    ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES);    ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES);        return (TRUE);}void CMemory::Deinit (){    ROM -= 0x8000;    delete RAM;    delete SRAM;    delete VRAM;    delete ROM;    delete IPPU.TileCache [TILE_2BIT];    delete IPPU.TileCache [TILE_4BIT];    delete IPPU.TileCache [TILE_8BIT];    delete IPPU.TileCached [TILE_2BIT];    delete IPPU.TileCached [TILE_4BIT];    delete IPPU.TileCached [TILE_8BIT];}/**********************************************************************************************//* LoadROM()                                                                                  *//* This function loads a Snes-Backup image                                                    *//**********************************************************************************************/bool8 CMemory::LoadROM (const char *filename){    unsigned long FileSize = 0;    int retry_count = 0;    STREAM ROMFile;    bool8 Interleaved = FALSE;    bool8 Tales = FALSE;    char dir [_MAX_DIR + 1];    char drive [_MAX_DRIVE + 1];    char name [_MAX_FNAME + 1];    char ext [_MAX_EXT + 1];    char fname [_MAX_PATH + 1];    int i;    CPU.TriedInterleavedMode2 = FALSE;    CalculatedSize = 0;again:    _splitpath (filename, drive, dir, name, ext);    _makepath (fname, drive, dir, name, ext);#ifdef __WIN32__    memmove (&ext [0], &ext[1], 4);#endif    int32 TotalFileSize = 0;#ifdef UNZIP_SUPPORT    if (strcasecmp (ext, "zip") == 0)    {	bool8 LoadZip (const char *, int32 *, int32 *);	if (!LoadZip (fname, &TotalFileSize, &HeaderCount))	    return (FALSE);	strcpy (ROMFilename, fname);    }    else#endif    {	if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL)	    return (FALSE);	strcpy (ROMFilename, fname);	HeaderCount = 0;	uint8 *ptr = ROM;	bool8 more = FALSE;	do	{	    FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - ROM), ROMFile);	    CLOSE_STREAM (ROMFile);	    int calc_size = (FileSize / 0x2000) * 0x2000;	    if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||		Settings.ForceHeader)	    {		memmove (ptr, ptr + 512, calc_size);		HeaderCount++;		FileSize -= 512;	    }	    ptr += FileSize;	    TotalFileSize += FileSize;	    int len;	    if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&		(isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9'))	    {		more = TRUE;		ext [0]++;#ifdef __WIN32__                memmove (&ext [1], &ext [0], 4);                ext [0] = '.';#endif		_makepath (fname, drive, dir, name, ext);	    }	    else	    if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&		(((len = strlen (name)) == 7 || len == 8) &&		 strncasecmp (name, "sf", 2) == 0 &&		 isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) &&		 isdigit (name [5]) && isalpha (name [len - 1])))	    {		more = TRUE;		name [len - 1]++;#ifdef __WIN32__                memmove (&ext [1], &ext [0], 4);                ext [0] = '.';#endif		_makepath (fname, drive, dir, name, ext);	    }	    else		more = FALSE;	} while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL);    }    if (HeaderCount == 0)	S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");    else    {	if (HeaderCount == 1)	    S9xMessage (S9X_INFO, S9X_HEADERS_INFO,			"Found ROM file header (and ignored it).");	else	    S9xMessage (S9X_INFO, S9X_HEADERS_INFO,			"Found multiple ROM file headers (and ignored them).");    }    CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize);    ZeroMemory (ROM + TotalFileSize, MAX_ROM_SIZE - TotalFileSize);    CalculatedSize = (TotalFileSize / 0x2000) * 0x2000;    int orig_hi_score, orig_lo_score;    int hi_score, lo_score;    orig_hi_score = hi_score = ScoreHiROM (FALSE);    orig_lo_score = lo_score = ScoreLoROM (FALSE);        if (HeaderCount == 0 &&	((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) ||	 (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score)))    {	S9xMessage (S9X_INFO, S9X_HEADER_WARNING, 		    "Try specifying the -hd command line option if the game doesn't work\n");    }    Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2;    if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))    {	LoROM = TRUE;	HiROM = FALSE;	// Ignore map type byte if not 0x2x or 0x3x	if ((ROM [0x7fd5] & 0xf0) == 0x20 || (ROM [0x7fd5] & 0xf0) == 0x30)	{	    switch (ROM [0x7fd5] & 0xf)	    {	    case 1:		if (strncmp ((char *) &ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0)		    Interleaved = TRUE;		break;	    case 2:#if 0		if (!Settings.ForceLoROM &&		    strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 &&		    strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0)		{		    LoROM = FALSE;		    HiROM = TRUE;		}#endif		break;	    case 5:		Interleaved = TRUE;		Tales = TRUE;		break;	    }	}    }    else    {	if ((ROM [0xffd5] & 0xf0) == 0x20 || (ROM [0xffd5] & 0xf0) == 0x30)	{	    switch (ROM [0xffd5] & 0xf)	    {	    case 0:	    case 3:		Interleaved = TRUE;		break;	    }	}	LoROM = FALSE;	HiROM = TRUE;    }    if (!Settings.ForceNotInterleaved && Interleaved)    {	CPU.TriedInterleavedMode2 = TRUE;	S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,		    "ROM image is in interleaved format - converting...");	int nblocks = CalculatedSize >> 16;#if 0	int step = 64;	while (nblocks <= step)	    step >>= 1;	    	nblocks = step;#endif	uint8 blocks [256];	if (Tales)	{	    nblocks = 0x60;	    for (i = 0; i < 0x40; i += 2)	    {		blocks [i + 0] = (i >> 1) + 0x20;		blocks [i + 1] = (i >> 1) + 0x00;	    }	    for (i = 0; i < 0x80; i += 2)	    {		blocks [i + 0x40] = (i >> 1) + 0x80;		blocks [i + 0x41] = (i >> 1) + 0x40;	    }	    LoROM = FALSE;	    HiROM = TRUE;	}	else	if (Settings.ForceInterleaved2)	{	    for (i = 0; i < nblocks * 2; i++)	    {		blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |			     ((i & 8) >> 2) | ((i & 16) >> 2);	    }	}	else	{	    bool8 t = LoROM;	    LoROM = HiROM;	    HiROM = t;	    for (i = 0; i < nblocks; i++)	    {		blocks [i * 2] = i + nblocks;		blocks [i * 2 + 1] = i;	    }	}	uint8 *tmp = new uint8 [0x8000];	for (i = 0; i < nblocks * 2; i++)	{	    for (int j = i; j < nblocks * 2; j++)	    {		if (blocks [j] == i)		{		    memmove (tmp, &ROM [blocks [j] * 0x8000], 0x8000);		    memmove (&ROM [blocks [j] * 0x8000], 			     &ROM [blocks [i] * 0x8000], 0x8000);		    memmove (&ROM [blocks [i] * 0x8000], tmp, 0x8000);		    uint8 b = blocks [j];		    blocks [j] = blocks [i];		    blocks [i] = b;		    break;		}	    }	}	delete tmp;	hi_score = ScoreHiROM (FALSE);	lo_score = ScoreLoROM (FALSE);	if ((HiROM &&	     (lo_score >= hi_score || hi_score < 0)) ||	    (LoROM && 	     (hi_score > lo_score || lo_score < 0)))	{	    if (retry_count == 0)	    {		S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO,			    "ROM lied about its type! Trying again.");		Settings.ForceNotInterleaved = TRUE;		Settings.ForceInterleaved = FALSE;		retry_count++;		goto again;	    }	}    }    InitROM (Tales);	    S9xApplyCheats ();    S9xReset ();    return (TRUE);}void S9xDeinterleaveMode2 (){    S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,		"ROM image is in interleaved format - converting...");    int nblocks = Memory.CalculatedSize >> 15;    int step = 64;    while (nblocks <= step)	step >>= 1;	    nblocks = step;    uint8 blocks [256];    int i;    for (i = 0; i < nblocks * 2; i++)    {	blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |		    ((i & 8) >> 2) | ((i & 16) >> 2);    }    uint8 *tmp = new uint8 [0x8000];    for (i = 0; i < nblocks * 2; i++)    {	for (int j = i; j < nblocks * 2; j++)	{	    if (blocks [j] == i)	    {		memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000);		memmove (&Memory.ROM [blocks [j] * 0x8000], 			 &Memory.ROM [blocks [i] * 0x8000], 0x8000);		memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000);		uint8 b = blocks [j];		blocks [j] = blocks [i];		blocks [i] = b;		break;	    }	}    }    delete tmp;    Memory.InitROM (FALSE);    S9xReset ();}void CMemory::InitROM (bool8 Interleaved){#ifndef ZSNES_FX    SuperFX.nRomBanks = CalculatedSize >> 15;#endif    Settings.MultiPlayer5Master = Settings.MultiPlayer5;    Settings.MouseMaster = Settings.Mouse;    Settings.SuperScopeMaster = Settings.SuperScope;    Settings.DSP1Master = Settings.ForceDSP1;    Settings.SuperFX = FALSE;    Settings.SA1 = FALSE;    Settings.C4 = FALSE;    Settings.SDD1 = FALSE;    Settings.SRTC = FALSE;    ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS);

⌨️ 快捷键说明

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