fileman.cpp

来自「SNES game emulator. C and asm files.」· C++ 代码 · 共 1,123 行 · 第 1/3 页

CPP
1,123
字号
/*	FILEMAN.CPP - File manager
*/

#include "Common.hpp"
#include <io.h>
#include <sys\stat.h>
#include <direct.h>
#include <i86.h>
#include <ASSERT.H>
#include "GrEngine.hpp"
#include "CPU.hpp"
#include "FileMan.hpp"
#include "GUI.hpp"
#include "SPC700.hpp"

char romdir [80] = "..", sramdir [80] = "..", instdir [80] = "", sshotdir [80] = "";
char exedir [80];

byte gameres = 1, guires = 4;
byte addsubmethod = 0;
byte soundkhz = 8, soundchannels = 0xFF;
boolean stereosound = false;
byte pcontrol[4] = { 0, 1, 3, 3 };
boolean autobacktrack = true, disallowinst = false;
word backtracktime = 30, backtracknum = 3;
struct windowsettings ws [NUMWINDOWS];

extern struct filemap fm[FTAGS] = {
	"CheatDesc", FCHEAT, FSTRINGALLOC, offsetof (cheatpatchset, desc),     // 0
	"AutoRegOn", FROMSETTING, FBYTE, offsetof (gamesettings, autoreg),
	"FrameSkip", FROMSETTING, FBYTE, offsetof (gamesettings, frameskip),
	"Regulate%", FROMSETTING, FBYTE, offsetof (gamesettings, regpercent),
	"GrSpeedup", FROMSETTING, FBYTE, offsetof (gamesettings, grspeedup),
	"65c816%",   FROMSETTING, FBYTE, offsetof (gamesettings, cpupercent),  // 5
	"SPC700%",   FROMSETTING, FBYTE, offsetof (gamesettings, spcpercent),
	"SoundChs",  FROMSETTING, FWORD, offsetof (gamesettings, soundch),
	"BGs",       FROMSETTING, FBYTE, offsetof (gamesettings, bgs),
	"ForceROM",  FROMSETTING, FBYTE, offsetof (gamesettings, forcerom),
	"ForceCtry", FROMSETTING, FBYTE, offsetof (gamesettings, forcecountry), // 10
	"Interl",    FROMSETTING, FBYTE, offsetof (gamesettings, interleaved),
	"EnableSPC", FROMSETTING, FBYTE, offsetof (gamesettings, emulatespc),
	"SPCSkipM",  FROMSETTING, FBYTE, offsetof (gamesettings, spcskipmethod),
	"OpenWins",  FROMSETTING, FWORD, offsetof (gamesettings, openwindows),
	"NoFastROM", FROMSETTING, FBYTE, offsetof (gamesettings, ignorefastrom),
	"GameRes",   FGLOBAL, FBYTE, (dword) &gameres,        // 15
	"GUIRes",    FGLOBAL, FBYTE, (dword) &guires,
	"AddSubM",   FGLOBAL, FBYTE, (dword) &addsubmethod,
	"SoundKHz",  FGLOBAL, FBYTE, (dword) &soundkhz,
	"StereoSnd", FGLOBAL, FBYTE, (dword) &stereosound,
	"P1Control", FGLOBAL, FBYTE, (dword) &pcontrol[0],      // 20
	"P2Control", FGLOBAL, FBYTE, (dword) &pcontrol[1],
	"P3Control", FGLOBAL, FBYTE, (dword) &pcontrol[2],
	"P4Control", FGLOBAL, FBYTE, (dword) &pcontrol[3],
	"DisableIS", FGLOBAL, FBYTE, (dword) &disallowinst,
	"WaitTrace", FGLOBAL, FBYTE, (dword) &waitretrace,    // 25
	"LeadingEd", FGLOBAL, FBYTE, (dword) &leadingedge,
	"ROMDir",    FGLOBAL, FSTRING, (dword) romdir,
	"SRAMDir",   FGLOBAL, FSTRING, (dword) sramdir,
	"InstDir",   FGLOBAL, FSTRING, (dword) instdir,
	"SShotDir",  FGLOBAL, FSTRING, (dword) sshotdir,      // 30
	"BackGrnd",  FGLOBAL, FBYTE, (dword) &background,
	"ESCQuits",  FGLOBAL, FBYTE, (dword) &escquits,
	"WindowSet", FGLOBAL, FBYTE, (dword) &set.window,
	"TextSet",   FGLOBAL, FBYTE, (dword) &set.text,
	"CtrlSet",   FGLOBAL, FBYTE, (dword) &set.control,     // 35
	"ChoiceSet", FGLOBAL, FBYTE, (dword) &set.choice,
	"ButtonSet", FGLOBAL, FBYTE, (dword) &set.button,
	"BtTextSet", FGLOBAL, FBYTE, (dword) &set.buttontext,
	"TitleSet",  FGLOBAL, FBYTE, (dword) &set.title,
	"TtTextSet", FGLOBAL, FBYTE, (dword) &set.titletext,   // 40
	"FocusSet",  FGLOBAL, FBYTE, (dword) &set.focus,
	"FlashSet",  FGLOBAL, FBYTE, (dword) &set.flash,
	"JoyUp",     FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, up),
	"JoyDown",   FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, down),
	"JoyLeft",   FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, left),   // 45
	"JoyRight",  FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, right),
	"JoyX",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, x),
	"JoyY",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, y),
	"JoyA",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, a),
	"JoyB",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, b),      // 50
	"JoyL",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, l),
	"JoyR",      FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, r),
	"JoySelect", FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, select),
	"JoyStart",  FJOYPADSETTING, FBYTE, offsetof (struct snesjoypad, start),
	"WinPosX",   FWINDOWPOS, FWORD, offsetof (struct windowsettings, x),      // 55
	"WinPosY",   FWINDOWPOS, FWORD, offsetof (struct windowsettings, y),
	"WinZOrder", FWINDOWPOS, FBYTE, offsetof (struct windowsettings, zorder),
	"JoyMinX",   FGLOBAL, FWORD, (dword) &joyminx,
	"JoyMaxX",   FGLOBAL, FWORD, (dword) &joymaxx,
	"JoyMinY",   FGLOBAL, FWORD, (dword) &joyminy,         // 60
	"JoyMaxY",   FGLOBAL, FWORD, (dword) &joymaxy,
	"JoyMidX",   FGLOBAL, FWORD, (dword) &joymidx,
	"JoyMidY",   FGLOBAL, FWORD, (dword) &joymidy,
	"JoyThresh", FGLOBAL, FWORD, (dword) &joythresh,
	"BackNum",   FGLOBAL, FWORD, (dword) &backtracknum,    // 65
	"FPUCopy",   FGLOBAL, FBYTE, (dword) &fpucopy,        
	"Windowing", FROMSETTING, FBYTE, offsetof (gamesettings, windowing),
	"IndirHDMA", FROMSETTING, FBYTE, offsetof (gamesettings, indirecthdma),
	"AutoBackT", FGLOBAL, FBYTE, (dword) &autobacktrack,
	"BackTTime", FGLOBAL, FWORD, (dword) &backtracktime,
	"AskB4Exit", FGLOBAL, FBYTE, (dword) &confirmexit,
	"ShowFPS",   FGLOBAL, FBYTE, (dword) &showfps,
};

	// Commands:
	//
	// New ROM "filename.ext"
	// New Joypad n
	// New Window n
	// New Cheat bbaaaa=vv+...
	//
	// ; Statements starting with a semicolon are ignored.

struct gamesettings gsdefault = {
	"[Defaults]", // char filename [13];
	true,     // boolean autoreg;
	2, 100,   // byte frameskip, regpercent;
	false,    // boolean grspeedup;
	100, 100, // byte cpupercent, spcpercent;
	0xFF,     // word soundch;
	31,       // byte bgs;
	0, 0,     // byte forcerom, forcecountry;
	false,    // boolean interleaved;
	false,    // boolean emulatespc;
	0,        // byte spcskipmethod;
	1,        // word openwindows;
	true,     // boolean ignorefastrom
	true, true// boolean windowing, indirecthdma
};

struct gamesettings *gs [MAXGAMEDATABASE] = {
	&gsdefault // First entry (gs[0]) is the defaults.
};
struct gamesettings *curgs;
int curgsnum = 0;
int numgamesettings = 0;
int gsentries = 1;
boolean romloaded = false, romrunning = false;

void initfilemanager (char *argv0)
{
	char temp[80];
	
	curgs = gs[curgsnum];
	strcpy (temp, argv0);
	stripfilename (temp);
	_fullpath (exedir, temp, 80);
	debug0(exedir);
}

void uninitfilemanager (void)
{
	int x, y;

	for (x = 1; x < MAXGAMEDATABASE; x++) {
		if (gs[x] == NULL) continue;
		for (y = 0; y < gs[x]->patches; y++) {
			free (gs[x]->cheat[y]->desc);
			free (gs[x]->cheat[y]->patch);
			free (gs[x]->cheat[y]);
		}
		free (gs[x]);
	}
}

boolean exists (char *s)
{
	if (access (s, 0) == 0)
		return true;
	else
		return false;
}

boolean isadir (char *s)
{
	static struct _stat buf;

	// first checks whether the path is valid...
    if (_stat (s, &buf) == -1) {
		// no, so it might be an incomplete path.  Decide based on the existance of an extention.
		if (findlastch (s + findlastch(s, SLASH) + 1, '.') == -1) {
			return true;
		} else {
			return false;
		}
	} else if (S_ISDIR(buf.st_mode))
		return true;
	return false;
}

void delstr (char *s, int p, int n)
{
	for (s += p; *s != '\0'; s++) {
		*s = s[n];
		if (*s == '\0') break;
	}
}

int findlastch (char *s, char ch)
{
	int x;
	for (x = strlen(s)-1; x >= 0; x--) {
		if (s[x] == ch) {
			return x;
		}
	}
	return x;
}

int findfirstch (char *s, char ch)
{
	int x;
	for (x = 0; s[x] != '\0'; x++) {
		if (s[x] == ch) {
			return x;
		}
	}
	return -1;
}

int countchar (char *s, char ch)
{
	int n = 0;
	
	while (*s != '\0') {
		if (*s == ch) n++;
		s++;
	}
	return n;
}

void trimspace (char *s)
{
	int y, n;
	
	for (y = 0; s[y] == ' ' || s[y] == 9; y++)
		;
	delstr (s, 0, y);
	for (y = strlen(s)-1, n = 0; (s[y] == ' ' || s[y] == 9) && y >= 0; y--, n++)
		;
	delstr (s, y+1, n);
}

void trimfilespec (char *s)
{
	trimspace (s);
	if (countchar (s, SLASH) > 1 && s [strlen(s) - 1] == SLASH) {
		s [strlen(s) - 1] = '\0';
	}
}

void strippathname (char *name)
{
	int x, p;

	if (isadir (name)) {
		name[0] = '\0';
		return;
	}
	p = findlastch (name, SLASH);
	x = findlastch (name, ':');
	if (x > p) p = x;
	delstr (name, 0, p + 1);
}

void stripfilename (char *name)
{
	int x;
	if (!isadir (name)) {
		x = findlastch (name, SLASH);
		if (name [x - 1] == ':' || x == 0) {
			x++; // Don't delete backslash if file is in root.
		}
		delstr (name, x, strlen (name) - x);
	} else {
		x = strlen(name);
		if (name[x-1] == SLASH)
			name[x-1] = '\0';
	}
}

void getabspath (char *path)
{	// absolute path reletive to executable directory
	char tempcwd [80], temppath [80];
	unsigned dummy;
	
	getcwd (tempcwd, 80);
	_dos_setdrive (exedir [0]-'A'+1, &dummy);
	chdir (exedir);
	_fullpath (temppath, path, 80);
	strcpy (path, temppath);
	_dos_setdrive (tempcwd [0]-'A'+1, &dummy);
	chdir (tempcwd);
}

void combinepathfile (char *comb, char *path, char *fn)
{	// This function doesn't combine two paths... it just appends fn to path
	int x = strlen (path);
	
	strcpy (comb, path);
	if (comb [x-1] != SLASH) {
		comb [x] = SLASH;
		x++;
	}
	strcpy (comb+x, fn);
}

void combinepaths (char *comb, char *path, char *offs)
{
	char tempcwd [80], temppath [80];
	unsigned dummy, originaldrive;
	
	_dos_getdrive (&originaldrive); // Save current drive
	path[0] = toupper(path[0]);
	offs[0] = toupper(offs[0]);
	if (offs[1] == ':')
		_dos_setdrive (offs[0]-'A'+1, &dummy);
	else if (path [1] == ':')
		_dos_setdrive (path[0]-'A'+1, &dummy);
	getcwd (tempcwd, 80); // save current directory

	_fullpath (temppath, path, 80);
	_dos_getdrive (&dummy);
	if (dummy == temppath[0]-'A'+1)
		chdir (path);
	chdir (offs);
	getcwd (comb, 80);

	_dos_setdrive (tempcwd [0]-'A'+1, &dummy);
	chdir (tempcwd); // restore current directory
	_dos_setdrive (originaldrive, &dummy); // Restore current drive
}

#define ntohex(n) ((n) > 9 ? (n)+'A'-10 : (n)+'0')
#define ishexd(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'Z'))
#define hexton(c) ((c) >= 'A' ? (c)-'A'+10 : (c)-'0')
	// ONLY WORKS ON UPPERCASE HEX!

int verifyspecformat (char *patchspec)
{	// Removes spaces...btw...and converts to uppercase.
	// False=bad format, other=number of patches.
	char *o_patchspec = patchspec;
	int i, n;
	
	strupr (patchspec);
	debug0 ("Checking %s",patchspec);
	while (*patchspec)
		if (*patchspec == ' ')
			for (i = 0; patchspec[i]; i++)
				patchspec[i] = patchspec[i+1];
		else
			patchspec++;
	patchspec = o_patchspec;
	i = 0; n = 0;
	for (;;) {
		if (!((patchspec[i + 4] == '-')  ^ (patchspec[i + 6] == '='))) {
			debug0 ("Not game genie nor native format");
			return false;  // Must have a dash or equals, but not both
		}
		if (!ishexd(patchspec[i]) || !ishexd(patchspec[i+1]) || !ishexd(patchspec[i+2]) ||
			!ishexd(patchspec[i+3]) || (!ishexd(patchspec[i+4]) && patchspec[i+4] != '-') ||
			!ishexd(patchspec[i+5]) || (!ishexd(patchspec[i+6]) && patchspec[i+6] != '=') ||
			!ishexd(patchspec[i+7]) || !ishexd(patchspec[i+8])) {
			debug0 ("Digit problem in cheat");
			return false;  // Must all be hex digits
		}
		n++;
		if (patchspec[i + 6] == '=' && ishexd(patchspec[i+9]) && ishexd(patchspec[i+10])) {
			i += 2; // 2 More digits.
			debug0 ("Word-sized cheat");
		}
		if (strlen (patchspec) - i < 10)
			break;
		if (patchspec[i+9] != '+') {
			debug0 ("Multiple patches detected in cheat");

⌨️ 快捷键说明

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