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

📄 cpu.cpp

📁 SNES game emulator. C and asm files.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	for (x = 0; x < 256; x++) {
		((word*)cgram)[x] = ((custompalette[x] >> 19) & 31) + (((custompalette[x] >> 11) & 31) << 5)\
		 + (((custompalette[x] >> 3) & 31) << 10);  // Initialize to custom palette
	}
	memset (&state, 0, sizeof (ppuinternalregisters));
	state.hcounter = state.vcounter = 0;
	state.reg4210 = state.reg4211 = 1;
	state.vramincrate = 2;
	memset (instr_tally, 0, sizeof (instr_tally));
	memset (mmio_rtally, 0, sizeof (mmio_rtally));
	memset (mmio_wtally, 0, sizeof (mmio_wtally));
    memset (cstatus, 0, sizeof (cstatus));  // Recaching required
	memset (spr8x8size, 0, sizeof (spr8x8size));
	frame_cycles = total_frames = -1; // Force start of new frame
}

char *getaccessoryname (char *fn, char *dir, char *ext)
{
	static char full [100], full2 [100];
	int p;

	debug0 ("Get accessory name: fn %s dir %s ext %s", fn, dir, ext);
	full [0] = '\0';
	getabspath (full);
	combinepaths (full2, full, dir);
	combinepathfile (full, full2, fn);
	p = findlastch (full, '.') + 1;
	if (p == 0) {
		p = strlen (full) + 1;
		full [p - 1] = '.';
	}
	strcpy (full + p, ext);
	debug0 ("  Got path: %s", full);
	return full;
}

void savesram ()
{
	char *fn = getaccessoryname (curgs->filename, sramdir, "SRM");
	int size;
	FILE *fp;

	for (size = 0xFFFF; size > 0; size--)
		if (sram[size] != 255)
			break;
	if (size == 0) {
		debug0 ("Not saving SRAM %s because size is zero.", fn);
		return;
	}
	if (vidmode == 0) printf ("Saving SRAM... (%s)", fn);
	else              addmessage ("Saving SRAM... (%s)", fn);
		// now round up
	if (size > 32768) size = 65536;
	else if (size > 16384) size = 32768;
	else if (size > 8192) size = 16384;
	else if (size > 4096) size = 8192;
	else if (size > 2048) size = 4096;
	else if (size > 1024) size = 2048;
	else size = 1024;
	if ((fp = fopen (fn, "wb")) == NULL) {
		if (vidmode == 0) printf ("Error opening SRAM file to save!");
		else              addmessage ("Error opening SRAM file to save!");
		return;
	}
	fwrite (sram, size, 1, fp);
	fclose (fp);
}

void loadsram ()
{
	char *fn = getaccessoryname (curgs->filename, sramdir, "SRM");
	FILE *fp;

	memset (sram, 255, 0x10000);
	if (vidmode == 0) printf ("Loading SRAM (%s)...", fn);
	else              addmessage ("Loading SRAM (%s)...", fn);
	if ((fp = fopen (fn, "rb")) == NULL) {
		if (vidmode == 0) printf ("Error opening SRAM file to load!");
		else              addmessage ("Error opening SRAM file to load!");
		return;
	}
	fread (sram, 1, 0x10000, fp);
	fclose (fp);
}

int cursaveslot = 0;
	// supports 10 save slots (0-9)

// quick save ID's
#define QSRAM 1
#define QSREGISTERS 2
#define QSSRAM 3
#define QSEXPRAM 4
#define QSCGRAM 5
#define QSOAM 6
#define QSSIXVARS 7 /* frame_cycles, screen_scanline */
#define QSSTATE 8
#define QSVRAM 9
#define QSMMIO2100 10 /* $2100 to $21FF */
#define QSMMIO4200 11 /* $4200 to $43FF */

boolean instantsave (int slot, boolean autobacktrack)
{   // Returns OKAY if save worked
	char *fn, ext[4] = "QSx"; // "Quick Save X"
	FILE *fp;
	char fileid[4] = "QS\x1A";
	int id, size;
	char s[80];

	ext [2] = slot + '0';
	if (autobacktrack) {
		s[0] = slot + '0';
		s[1] = '\0'; fn = s;
		addmessage ("[Checkpoint]");
	} else {
		fn = getaccessoryname (curgs->filename, instdir, ext);
	}
	if ((fp = vfopen (fn, "wb")) == NULL) {
		addmessage ("Couldn't save state %s...", fn);
		return -1;
	}
	vfwrite (fileid, 1, 4, fp);
	id = QSREGISTERS; size = sizeof (regpack);
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (&reg, size, 1, fp);
	id = QSSTATE; size = sizeof (ppuinternalregisters);
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (&state, size, 1, fp);
	id = QSCGRAM; size = 256*2;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (cgram, size, 1, fp);
	id = QSOAM; size = 544;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (oam, size, 1, fp);
	id = QSSIXVARS; size = sizeof(int) * 6;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (&frame_cycles,    sizeof(int), 1, fp);
	vfwrite (&scan_cycles,     sizeof(int), 1, fp);
	vfwrite (&screen_scanline, sizeof(int), 1, fp);
	vfwrite (&cycles_per_scan, sizeof(int), 1, fp);
	vfwrite (&total_frames,    sizeof(int), 1, fp); // Optional
	vfwrite (&debug_instr,     sizeof(int), 1, fp); // Optional
	id = QSMMIO2100; size = 0xFF;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (registers + 0x0100, size, 1, fp);
	id = QSMMIO4200; size = 0x1FF;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (registers + 0x2200, size, 1, fp);
	id = QSRAM; size = 128*1024;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (ram, size, 1, fp);
	id = QSVRAM; size = 0x10000;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (vram, size, 1, fp);
	id = QSEXPRAM; size = 0x2000;
	vfwrite (&id, sizeof(int), 1, fp);
	vfwrite (&size, sizeof(int), 1, fp);
	vfwrite (expram, size, 1, fp);
	vfclose (fp);
	if (fn[1] != '\0') {
		sprintf (s, "State saved to %s.", fn);
		if (debugmode)
			adddebugline (s, false, '!');
		else
			addmessage ("%s", s);
	}
	return OKAY;
}

boolean instantload (int slot, boolean autobacktrack)
	// Returns OKAY if load worked
{
	char *fn, ext[4] = "QSx"; // ".Quick Save X"
	FILE *fp;
	char fileid[4];
	dword id, size;
	int x;
	char s[80];

	ext [2] = slot + '0';
	if (autobacktrack) {
		s[0] = slot + '0';
		s[1] = '\0'; fn = s;
	} else {
		fn = getaccessoryname (curgs->filename, instdir, ext);
	}
	if ((fp = vfopen (fn, "rb")) == NULL) {
		addmessage ("Couldn't open state %s", fn);
		return -1;
	}
	debug0 ("got here");
	vfread (fileid, 1, 4, fp);
	if (fileid[0]!='Q' || fileid[1]!='S' || fileid[2]!=26 || fileid[3]!=0) {
		addmessage ("%s: unrecognised file format!", fn);
		fclose (fp);
		return -1;
	}
	resetsystem (true);
	resetscreenframe ();
	applycustompalette();
	while (!vfeof(fp)) {
		vfread (&id, 1, 4, fp);
		vfread (&size, 1, 4, fp);
		switch (id) {
		case QSRAM:
			vfread (ram, size, 1, fp);
			break;
		case QSREGISTERS:
			vfread (&reg, size, 1, fp);
			break;
		case QSSRAM:
			memset (sram, 0xFF, 0x10000); // Clear SRAM
			vfread (sram, size, 1, fp);
			break;
		case QSEXPRAM:
			vfread (expram, size, 1, fp);
			break;
		case QSCGRAM:
			vfread (cgram, size, 1, fp);
			break;
		case QSOAM:
			vfread (oam, size, 1, fp);
			break;
		case QSSIXVARS:
			vfread (&frame_cycles, sizeof(int), 1, fp);
			vfread (&scan_cycles, sizeof(int), 1, fp);
			vfread (&screen_scanline, sizeof(int), 1, fp);
			vfread (&cycles_per_scan, sizeof(int), 1, fp);
			if (size > 16) vfread (&total_frames, sizeof(int), 1, fp);
			if (size > 20) vfread (&debug_instr, sizeof(int), 1, fp);
			for (x = 24; x < size; x++) // ignore any extra data
				fgetc (fp);
			break;
		case QSSTATE:
			if (size > sizeof (ppuinternalregisters)) {
				vfread (&state, sizeof (ppuinternalregisters), 1, fp);
				for (x = sizeof (ppuinternalregisters); x < size; x++)
					fgetc (fp); // ignore any extra data
			} else {
				vfread (&state, size, 1, fp);
			}
			break;
		case QSVRAM:
			vfread (vram, size, 1, fp);
			break;
		case QSMMIO2100:
			vfread (registers + 0x0100, size, 1, fp);
			break;
		case QSMMIO4200:
			vfread (registers + 0x2200, size, 1, fp);
			break;
		default:
			for (x = 0; x < size; x++)
				fgetc (fp); // ignore the data
			break;
		}
	}
	vfclose (fp);
	if (autobacktrack)
		sprintf (s, "[Backtracked to last checkpoint.]");
	else
		sprintf (s, "%s Loaded.", fn);
	if (debugmode)
		adddebugline (s, false, '!');
	else
		addmessage ("%s", s);
	romrunning = true;
	return OKAY;
}

void unassemble (dword opdata, char *s, byte P)
{
	byte opcode = (byte) opdata;
	char *format = opcodelist[opcode].format;
	boolean isword = false, islong = false, issigned = false, isnumber = false;
	int n, x;

	opdata >>= 8;
	for (;;) {
		if (*format == '%') {
			format++;
			switch (*format) {
			case '#':
				format++;
				isnumber = true;
				switch (*format) {
				case 'i':
					if (!(P & INDEX)) isword = true;
					break;
				case 'b':
					break;
				case 'w':
					isword = true;
					break;
				default:
					format--; // literal--to be printed
					if (!(P & MEMORY)) isword = true; break;
				}
				break;
			case 'b':
				break;
			case 'w':
				isword = true;
				break;
			case 'L':
				islong = true;
				break;
			}
			if (isnumber)
				*s++ = '#';
			if (issigned) {
				if (isword) n = (signed short) opdata;
				if (islong) n = opdata;
				else n = (signed char) opdata;
				x = sprintf (s, "%d", n);
			} else {
				if (isword) {
					n = (unsigned short) opdata;
					x = sprintf (s, "$%0.4X", n);
				} else  if (islong) {
					n = opdata;
					x = sprintf (s, "$%0.6X", n);
				} else {
					n = (unsigned char) opdata;
					x = sprintf (s, "$%0.2X", n);
				}
			}
			s += x;
			format++;
		} else {
			*s = *format;
			if (*s == '@') issigned = true;
			if (*s == '\0') break;
			s++;
			format++;
		}
	}
}

char *getdescr (byte opcode)
{
	char *opc = opcodelist[opcode].format;
	int x;

	for (x = 0; instrlist[x].mnemonic[0] != '\0'; x++) {
		if (instrlist[x].mnemonic[0] == opc[0] &&
			instrlist[x].mnemonic[1] == opc[1] &&
			instrlist[x].mnemonic[2] == opc[2]) {
			return instrlist[x].descr;
		}
	}
	return "[Search error: couldn't find opcode decription]";
}

boolean ispal ()
{
	if (curgs->forcecountry == FORCEPAL) return true;
	else if (curgs->forcecountry == FORCENTSC || curheader.country < 2) return false;
	else return true;
}

boolean ishirom ()
{
	if (curgs->forcerom == FORCEHIROM) return true;
	else if (curgs->forcerom == FORCELOROM || curheader.hirom == false) return false;
	else return true;
}

int curfastrom;
long framestarttime;
#define FTHISTORY 30
byte frametime [FTHISTORY];
boolean framewasrendered [FTHISTORY];

void getfps (int &vfps, int &rfps)
{   // returns the fps * 10. (One decimal place included..)
	int x, rf, t;

	x = 0, rf=0, t=0;
	do {
		t += frametime [x];
		if (framewasrendered[x]) rf++;
		x++;
	} while (x < FTHISTORY);
	if (t != 0) {
		vfps = FTHISTORY * 10000 / t;
		rfps = rf * 10000 / t;
	} else {
		vfps = rfps = 0;
	}
	setcolor (0);
}

#define HBCOMBINE(a) ((*REG4302(x) & 0xFF0000) | (a))
// Combine offset with HDMA Bank

inline int getcount (int x)
{
	int temp;

	temp = HBCOMBINE(*(word*)REG4308(x));
	temp = *SNESMEM(temp) & 0x7F;
	//if (temp > 0x80) temp &= 0x7F;
	if (temp == 0) state.hdma_inprogress &= ~(1 << x);
	return temp;
}

void resethdma ()
{
	int x;

	state.hdma_inprogress = *REG420C;
	for (x = 0; x < 8; x++) {
		if (!(*REG420C & (1 << x)))
			continue;
		if (!curgs->indirecthdma && (*REG4300(x) & 0x40)) { // Indirect
			debug0 ("Ignoring HDMA Indirect channel %d", x);
			state.hdma_inprogress &= ~(1 << x);
		}

		if (*REG4300(x) & 0x40) { // Indirect
			*REG4308(x) = *(word*)REG4302(x);

⌨️ 快捷键说明

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