📄 cpu.cpp
字号:
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 (®, 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 (®, 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 + -