partially revert snes9x core. fixes performance issues.

This commit is contained in:
Daryl Borth 2018-08-16 08:41:30 -06:00
parent 4f2234cbc2
commit 5ea5f217b5
43 changed files with 2721 additions and 5783 deletions

View File

@ -15,11 +15,11 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
| FEATURES |
•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————•
* Based on Snes9x 1.56 (with faster Blargg S-SMP module)
* Based on hybrid Snes9x 1.51 and 1.56 (with faster Blargg S-SMP module)
* Wiimote, Nunchuk, Classic, and Gamecube controller support
* SNES Superscope, Mouse, Justifier support
* Cheat support
* BS-X support
* Satellaview (BS-X) support
* Auto Load/Save Game Snapshots and SRAM
* Custom controller configurations
* SD, USB, DVD, SMB, Zip, and 7z support
@ -35,9 +35,8 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
[4.3.8]
* Updated core to 1.56 (with less accurate but faster Blargg audio core)
* Partially update core to 1.56 (with less accurate but faster Blargg audio core)
* Improved audio synchronization with dynamic rate control - fixes audio crackles
* Added BS-X BIOS loading
* Memory optimizations to free up more MEM1 for Snes9x
* Disable multi pixel format support for a speed boost
* Add MSU1 support (thanks qwertymodo!)
@ -516,14 +515,6 @@ need to place your ROM image(s) into "\snes9xgx\roms" directory and place any
cheat code files (optional) in the "\snes9xgx\cheats" directory. Once this is
done you can proceed to run the emulator via the Homebrew Channel.
-=[ Satellaview (BS-X) ]=-
Snes9x GX supports loading BS games. The BSX BIOS is required.
Download the English + No DRM BS-X ROM here:
https://project.satellaview.org/downloads.htm
Put it in your snes9xgx folder, renamed to BS-X.bin.
•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————•
| INITIAL SETUP |
•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————•

View File

@ -16,8 +16,6 @@
#include "fileop.h"
#include "filebrowser.h"
#define MAX_CHEATS 100
extern SCheatData Cheat;
/****************************************************************************
@ -32,44 +30,26 @@ static bool LoadCheatFile (int length)
uint8 data [28];
int offset = 0;
while (offset < length) {
if(Cheat.g.size() >= MAX_CHEATS || (length - offset) < 28)
while (offset < length)
{
if(Cheat.num_cheats >= MAX_CHEATS || (length - offset) < 28)
break;
memcpy (data, savebuffer+offset, 28);
offset += 28;
SCheat c;
char name[21];
char cheat[10];
c.byte = data[1];
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
memcpy (name, &data[8], 20);
name[20] = 0;
snprintf (cheat, 10, "%x=%x", c.address, c.byte);
S9xAddCheatGroup (name, cheat);
Cheat.c [Cheat.num_cheats].enabled = 0; // cheats always off
Cheat.c [Cheat.num_cheats].byte = data [1];
Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16);
Cheat.c [Cheat.num_cheats].saved_byte = data [5];
Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0;
memcpy (Cheat.c [Cheat.num_cheats].name, &data[8], 20);
Cheat.c [Cheat.num_cheats].name[20] = 0;
Cheat.num_cheats++;
}
return true;
}
void ToggleCheat(uint32 num) {
if(Cheat.g[num].enabled) {
S9xDisableCheatGroup(num);
}
else {
S9xEnableCheatGroup(num);
}
for(int i=0; i < Cheat.g.size(); i++) {
if(Cheat.g[i].enabled) {
Cheat.enabled = TRUE;
return;
}
}
Cheat.enabled = FALSE;
}
/****************************************************************************
* SetupCheats
*
@ -79,6 +59,9 @@ void ToggleCheat(uint32 num) {
void
WiiSetupCheats()
{
memset(Cheat.c, 0, sizeof(Cheat.c));
Cheat.num_cheats = 0;
char filepath[1024];
int offset = 0;

View File

@ -50,8 +50,6 @@ bool inSz = false;
unsigned long SNESROMSize = 0;
bool loadingFile = false;
extern bool isBSX();
/****************************************************************************
* autoLoadMethod()
* Auto-determines and sets the load device
@ -455,8 +453,6 @@ int BrowserLoadSz()
return szfiles;
}
static bool bsxBiosLoadFailed;
int WiiFileLoader()
{
size_t size;
@ -488,16 +484,7 @@ int WiiFileLoader()
if(size <= 0)
return 0;
SNESROMSize = Memory.HeaderRemove(size, Memory.ROM);
bsxBiosLoadFailed = false;
if(isBSX()) {
sprintf (filepath, "%s%s/BS-X.bin", pathPrefix[GCSettings.LoadMethod], APPFOLDER);
if(LoadFile ((char *)Memory.BIOSROM, filepath, 0, SILENT) == 0) {
bsxBiosLoadFailed = true;
}
}
SNESROMSize = Memory.HeaderRemove(size, Memory.HeaderCount, Memory.ROM);
return SNESROMSize;
}
@ -529,13 +516,10 @@ int BrowserLoadFile()
S9xDeleteCheats();
Memory.LoadROM("ROM");
if (SNESROMSize == 0)
if (SNESROMSize <= 0)
{
ErrorPrompt("Error loading game!");
}
else if(bsxBiosLoadFailed) {
ErrorPrompt("BS-X BIOS file not found!");
}
else
{
// load SRAM or snapshot

View File

@ -44,7 +44,6 @@
#include "snes9x/cheats.h"
extern SCheatData Cheat;
extern void ToggleCheat(uint32);
#define THREAD_SLEEP 100
@ -2041,13 +2040,10 @@ static int MenuGameSettings()
else if(cheatsBtn.GetState() == STATE_CLICKED)
{
cheatsBtn.ResetState();
if(Cheat.g.size() > 0) {
if(Cheat.num_cheats > 0)
menu = MENU_GAMESETTINGS_CHEATS;
}
else {
else
InfoPrompt("Cheats file not found!");
}
}
else if(screenshotBtn.GetState() == STATE_CLICKED)
{
@ -2097,10 +2093,10 @@ static int MenuGameCheats()
u16 i = 0;
OptionList options;
for(i=0; i < Cheat.g.size(); i++)
for(i=0; i < Cheat.num_cheats; i++)
{
sprintf (options.name[i], "%s", Cheat.g[i].name);
sprintf (options.value[i], "%s", Cheat.g[i].enabled == true ? "On" : "Off");
sprintf (options.name[i], "%s", Cheat.c[i].name);
sprintf (options.value[i], "%s", Cheat.c[i].enabled == true ? "On" : "Off");
}
options.length = i;
@ -2149,8 +2145,11 @@ static int MenuGameCheats()
if(ret >= 0)
{
ToggleCheat(ret);
sprintf (options.value[ret], "%s", Cheat.g[ret].enabled == true ? "On" : "Off");
if(Cheat.c[ret].enabled)
S9xDisableCheat(ret);
else
S9xEnableCheat(ret);
sprintf (options.value[ret], "%s", Cheat.c[ret].enabled == true ? "On" : "Off");
optionBrowser.TriggerUpdate();
}
@ -3171,11 +3170,17 @@ static int MenuSettingsVideo()
Settings.DisplayFrameRate ^= 1;
break;
case 8:
GCSettings.superFxSpeed += 10;
if(GCSettings.superFxSpeed > 200) {
GCSettings.superFxSpeed = 100;
GCSettings.sfxOverclock++;
if (GCSettings.sfxOverclock > 2)
GCSettings.sfxOverclock = 0;
switch(GCSettings.sfxOverclock)
{
case 0: Settings.SuperFXSpeedPerLine = 0.417 * 10.5e6; reset_sfx = true; break;
case 1: Settings.SuperFXSpeedPerLine = 0.417 * 40.5e6; reset_sfx = true; break;
case 2: Settings.SuperFXSpeedPerLine = 0.417 * 60.5e6; reset_sfx = true; break;
}
if (reset_sfx) S9xResetSuperFX();
S9xReset();
break;
}
@ -3219,7 +3224,15 @@ static int MenuSettingsVideo()
sprintf (options.value[6], "PAL (60Hz)"); break;
}
sprintf (options.value[7], "%s", Settings.DisplayFrameRate ? "On" : "Off");
sprintf (options.value[8], "%d%", GCSettings.superFxSpeed);
switch(GCSettings.sfxOverclock)
{
case 0:
sprintf (options.value[8], "Default"); break;
case 1:
sprintf (options.value[8], "40 Mhz"); break;
case 2:
sprintf (options.value[8], "60 Mhz"); break;
}
optionBrowser.TriggerUpdate();
}

View File

@ -150,7 +150,7 @@ preparePrefsData ()
createXMLSetting("FilterMethod", "Filter Method", toStr(GCSettings.FilterMethod));
createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift));
createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift));
createXMLSetting("superFxSpeed", "SuperFX Speed", toStr(GCSettings.superFxSpeed));
createXMLSetting("sfxOverclock", "SuperFX Overclock", toStr(GCSettings.sfxOverclock));
createXMLSection("Menu", "Menu Settings");
@ -335,7 +335,7 @@ decodePrefsData ()
//Emulation Settings
loadXMLSetting(&GCSettings.superFxSpeed, "superFxSpeed");
loadXMLSetting(&GCSettings.sfxOverclock, "sfxOverclock");
// Menu Settings
@ -458,8 +458,6 @@ DefaultSettings ()
GCSettings.language = LANG_ENGLISH;
#endif
GCSettings.superFxSpeed = 100;
/****************** SNES9x Settings ***********************/
// Default ALL to false
@ -500,7 +498,10 @@ DefaultSettings ()
Settings.FrameTimePAL = 20000;
Settings.FrameTimeNTSC = 16667;
Settings.SuperFXClockMultiplier = 100;
GCSettings.sfxOverclock = 0;
/* Initialize SuperFX CPU to normal speed by default */
Settings.SuperFXSpeedPerLine = 0.417 * 10.5e6;
}
/****************************************************************************

View File

@ -1,388 +0,0 @@
#include <vector>
#include <string.h>
#include <stdio.h>
#include "port.h"
#include "bml.h"
static char *strndup_p(char *str, int len)
{
char *buffer;
int n;
buffer = (char *) malloc (len + 1);
if (buffer)
{
for (n = 0; ((n < len) && (str[n] != 0)); n++) buffer[n] = str[n];
buffer[n] = '\0';
}
return buffer;
}
static inline bml_node *bml_node_new (void)
{
bml_node *node = new bml_node;
node->data = NULL;
node->name = NULL;
node->depth = -1;
return node;
}
static inline int islf(char c)
{
return (c == '\r' || c == '\n');
}
static inline int isblank(char c)
{
return (c == ' ' || c == '\t');
}
static inline int isalnum(char c)
{
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9'));
}
static inline int bml_valid (char c)
{
return (isalnum (c) || c == '-');
}
static char *strndup_trim (char *str, int len)
{
int start;
int end;
for (start = 0; str[start] && start != len && isblank (str[start]); start++) {}
if (!str[start] || start >= len)
return strdup ("");
for (end = len - 1; isblank (str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}
return strndup_p (str + start, end - start + 1);
}
static inline unsigned int bml_read_depth (char *data)
{
unsigned int depth;
for (depth = 0; isblank (data[depth]); depth++) {}
return depth;
}
static void bml_parse_depth (bml_node *node, char **data)
{
unsigned int depth = bml_read_depth (*data);
*data += depth;
node->depth = depth;
}
static void bml_parse_name (bml_node *node, char **data)
{
int len;
for (len = 0; bml_valid(*(*data + len)); len++) {};
node->name = strndup_trim (*data, len);
*data += len;
}
static void bml_parse_data (bml_node *node, char **data)
{
char *p = *data;
int len;
if (p[0] == '=' && p[1] == '\"')
{
len = 2;
while (p[len] && p[len] != '\"' && !islf (p[len]))
len++;
if (p[len] != '\"')
return;
node->data = strndup_p (p + 2, len - 2);
*data += len + 1;
}
else if (*p == '=')
{
len = 1;
while (p[len] && !islf (p[len]) && p[len] != '"' && p[len] != ' ')
len++;
if (p[len] == '\"')
return;
node->data = strndup_trim (p + 1, len - 1);
*data += len;
}
else if (*p == ':')
{
len = 1;
while (p[len] && !islf (p[len]))
len++;
node->data = strndup_trim (p + 1, len - 1);
*data += len;
}
return;
}
static void bml_skip_empty (char **data)
{
char *p = *data;
while (*p)
{
for (; *p && isblank (*p) ; p++) {}
if (!islf(p[0]) && (p[0] != '/' && p[1] != '/'))
return;
/* Skip comment data */
while (*p && *p != '\r' && *p != '\n')
p++;
/* If we found new-line, try to skip more */
if (*p)
{
p++;
*data = p;
}
}
}
static char *bml_read_line (char **data)
{
char *line;
char *p;
bml_skip_empty (data);
line = *data;
if (line == NULL || *line == '\0')
return NULL;
p = strpbrk (line, "\r\n\0");
if (p == NULL)
return NULL;
if (islf (*p))
{
*p = '\0';
p++;
}
*data = p;
return line;
}
static void bml_parse_attr (bml_node *node, char **data)
{
char *p = *data;
bml_node *n;
int len;
while (*p && !islf (*p))
{
if (*p != ' ')
return;
while (isblank (*p))
p++;
if (p[0] == '/' && p[1] == '/')
break;
n = bml_node_new ();
len = 0;
while (bml_valid (p[len]))
len++;
if (len == 0)
return;
n->name = strndup_trim (p, len);
p += len;
bml_parse_data (n, &p);
n->depth = bml_attr_type;
node->child.push_back (n);
}
*data = p;
}
static int contains_space (char *str)
{
for (int i = 0; str[i]; i++)
{
if (isblank (str[i]))
return 1;
}
return 0;
}
static void bml_print_node (bml_node *node, int depth)
{
int i;
if (!node)
return;
for (i = 0; i < depth * 2; i++)
{
printf (" ");
}
if (node->name)
printf ("%s", node->name);
if (node->data)
{
if (contains_space (node->data))
printf ("=\"%s\"", node->data);
else
printf (": %s", node->data);
}
for (i = 0; i < (int) node->child.size () && node->child[i]->depth == bml_attr_type; i++)
{
if (node->child[i]->name)
{
printf (" %s", node->child[i]->name);
if (node->child[i]->data)
{
if (contains_space (node->child[i]->data))
printf ("=\"%s\"", node->child[i]->data);
else
printf ("=%s", node->child[i]->data);
}
}
}
if (depth >= 0)
printf ("\n");
for (; i < (int) node->child.size(); i++)
{
bml_print_node (node->child[i], depth + 1);
}
if (depth == 0)
printf ("\n");
}
void bml_print_node (bml_node *node)
{
bml_print_node (node, -1);
}
static bml_node *bml_parse_node (char **doc)
{
char *line;
bml_node *node = NULL;
if ((line = bml_read_line (doc)))
{
node = bml_node_new ();
bml_parse_depth (node, &line);
bml_parse_name (node, &line);
bml_parse_data (node, &line);
bml_parse_attr (node, &line);
}
else
return NULL;
bml_skip_empty (doc);
while (*doc && (int) bml_read_depth (*doc) > node->depth)
{
bml_node *child = bml_parse_node (doc);
if (child)
node->child.push_back (child);
bml_skip_empty (doc);
}
return node;
}
void bml_free_node (bml_node *node)
{
delete[] (node->name);
delete[] (node->data);
for (unsigned int i = 0; i < node->child.size(); i++)
{
bml_free_node (node->child[i]);
delete node->child[i];
}
return;
}
bml_node *bml_parse (char **doc)
{
bml_node *root = NULL;
bml_node *node = NULL;
char *ptr = *doc;
root = bml_node_new ();
while ((node = bml_parse_node (&ptr)))
{
root->child.push_back (node);
}
if (!root->child.size())
{
delete root;
root = NULL;
}
return root;
}
bml_node *bml_find_sub (bml_node *n, const char *name)
{
unsigned int i;
for (i = 0; i < n->child.size (); i++)
{
if (!strcasecmp (n->child[i]->name, name))
return n->child[i];
}
return NULL;
}
bml_node *bml_parse_file (const char *filename)
{
FILE *file = NULL;
char *buffer = NULL;
int file_size = 0;
bml_node *node = NULL;
file = fopen (filename, "rb");
if (!file)
return NULL;
fseek (file, 0, SEEK_END);
file_size = ftell (file);
fseek (file, 0, SEEK_SET);
buffer = new char[file_size + 1];
fread (buffer, file_size, 1, file);
buffer[file_size] = '\0';
fclose (file);
node = bml_parse (&buffer);
delete[] buffer;
return node;
}

View File

@ -1,31 +0,0 @@
#ifndef __BML_H
#define __BML_H
#include <vector>
const int bml_attr_type = -2;
typedef struct bml_node
{
char *name;
char *data;
int depth;
std::vector<bml_node *> child;
} bml_node;
bml_node *bml_find_sub (bml_node *node, const char *name);
bml_node *bml_parse_file (const char *filename);
/* Parse character array into BML tree. Destructive to input. */
bml_node *bml_parse (char **buffer);
/* Recursively free bml_node and substructures */
void bml_free_node (bml_node *);
/* Print node structure to stdout */
void bml_print_node (bml_node *);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -193,8 +178,6 @@
#ifndef _BSX_H_
#define _BSX_H_
#include <fstream>
struct SBSX
{
bool8 dirty; // Changed register values
@ -212,22 +195,6 @@ struct SBSX
uint8 MMC[16];
uint8 prevMMC[16];
uint8 test2192[32];
bool flash_csr;
bool flash_gsr;
bool flash_bsr;
bool flash_cmd_done;
std::ifstream sat_stream1;
std::ifstream sat_stream2;
bool sat_pf_latch1_enable, sat_dt_latch1_enable;
bool sat_pf_latch2_enable, sat_dt_latch2_enable;
bool sat_stream1_loaded, sat_stream2_loaded;
bool sat_stream1_first, sat_stream2_first;
uint8 sat_stream1_count, sat_stream2_count;
uint16 sat_stream1_queue, sat_stream2_queue;
};
extern struct SBSX BSX;

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -261,9 +246,6 @@ const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram,
if (sscanf(tmp, "%x", &address) != 1)
return ("Invalid Gold Finger code.");
// Correct GoldFinger Address
address = (address & 0x7FFF) | ((address & 0x7F8000) << 1) | 0x8000;
for (i = 0; i < 3; i++)
{
unsigned int byte;

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -193,31 +178,22 @@
#ifndef _CHEATS_H_
#define _CHEATS_H_
#include "port.h"
#include <vector>
#define MAX_CHEATS 150
struct SCheat
{
uint32 address;
uint8 byte;
uint8 saved_byte;
bool8 conditional;
bool8 cond_true;
uint8 cond_byte;
bool8 enabled;
};
struct SCheatGroup
{
char *name;
bool8 enabled;
std::vector<struct SCheat> c;
bool8 saved;
char name[22];
};
struct SCheatData
{
std::vector<struct SCheatGroup> g;
bool8 enabled;
struct SCheat c[MAX_CHEATS];
uint32 num_cheats;
uint8 CWRAM[0x20000];
uint8 CSRAM[0x10000];
uint8 CIRAM[0x2000];
@ -259,23 +235,20 @@ typedef enum
extern SCheatData Cheat;
extern Watch watches[16];
int S9xAddCheatGroup (const char *name, const char *cheat);
int S9xModifyCheatGroup (uint32 index, const char *name, const char *cheat);
void S9xEnableCheatGroup (uint32 index);
void S9xDisableCheatGroup (uint32 index);
void S9xApplyCheat (uint32);
void S9xApplyCheats (void);
void S9xRemoveCheat (uint32);
void S9xRemoveCheats (void);
void S9xDeleteCheat (uint32);
void S9xDeleteCheats (void);
char *S9xCheatGroupToText (uint32 index);
void S9xDeleteCheatGroup (uint32 index);
bool8 S9xLoadCheatFile (const char *filename);
bool8 S9xSaveCheatFile (const char *filename);
void S9xUpdateCheatsInMemory (void);
int S9xImportCheatsFromDatabase(const char *filename);
void S9xCheatsDisable (void);
void S9xCheatsEnable (void);
char *S9xCheatValidate (char *cheat);
void S9xEnableCheat (uint32);
void S9xDisableCheat (uint32);
void S9xAddCheat (bool8, bool8, uint32, uint8);
void S9xInitCheatData (void);
void S9xInitWatchedAddress (void);
bool8 S9xLoadCheatFile (const char *);
bool8 S9xSaveCheatFile (const char *);
void S9xStartCheatSearch (SCheatData *);
void S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8);
void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -189,757 +174,233 @@
Nintendo Co., Limited and its subsidiary companies.
***********************************************************************************/
#include "snes9x.h"
#include "memmap.h"
#include "cheats.h"
#include "bml.h"
static inline uint8 S9xGetByteFree (uint32 Address)
static uint8 S9xGetByteFree (uint32);
static void S9xSetByteFree (uint8, uint32);
static uint8 S9xGetByteFree (uint32 address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
uint8 byte;
uint32 Cycles = CPU.Cycles;
uint32 WaitAddress = CPU.WaitAddress;
uint8 byte;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
byte = *(GetAddress + (Address & 0xffff));
return (byte);
}
byte = S9xGetByte(address);
switch ((pint) GetAddress)
{
case CMemory::MAP_CPU:
byte = S9xGetCPU(Address & 0xffff);
return (byte);
CPU.WaitAddress = WaitAddress;
CPU.Cycles = Cycles;
case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100)
return (OpenBus);
byte = S9xGetPPU(Address & 0xffff);
return (byte);
case CMemory::MAP_LOROM_SRAM:
case CMemory::MAP_SA1RAM:
// Address & 0x7fff : offset into bank
// Address & 0xff0000 : bank
// bank >> 1 | offset : SRAM address, unbound
// unbound & SRAMMask : SRAM offset
byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));
return (byte);
case CMemory::MAP_LOROM_SRAM_B:
byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));
return (byte);
case CMemory::MAP_HIROM_SRAM:
case CMemory::MAP_RONLY_SRAM:
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
return (byte);
case CMemory::MAP_BWRAM:
byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
return (byte);
case CMemory::MAP_DSP:
byte = S9xGetDSP(Address & 0xffff);
return (byte);
case CMemory::MAP_SPC7110_ROM:
byte = S9xGetSPC7110Byte(Address);
return (byte);
case CMemory::MAP_SPC7110_DRAM:
byte = S9xGetSPC7110(0x4800);
return (byte);
case CMemory::MAP_C4:
byte = S9xGetC4(Address & 0xffff);
return (byte);
case CMemory::MAP_OBC_RAM:
byte = S9xGetOBC1(Address & 0xffff);
return (byte);
case CMemory::MAP_SETA_DSP:
byte = S9xGetSetaDSP(Address);
return (byte);
case CMemory::MAP_SETA_RISC:
byte = S9xGetST018(Address);
return (byte);
case CMemory::MAP_BSX:
byte = S9xGetBSX(Address);
return (byte);
case CMemory::MAP_NONE:
default:
byte = OpenBus;
return (byte);
}
return (byte);
}
static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
static void S9xSetByteFree (uint8 byte, uint32 address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.Map[block];
uint32 Cycles = CPU.Cycles;
uint32 WaitAddress = CPU.WaitAddress;
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{
*(SetAddress + (Address & 0xffff)) = Byte;
return;
}
S9xSetByte(byte, address);
switch ((pint) SetAddress)
{
case CMemory::MAP_CPU:
S9xSetCPU(Byte, Address & 0xffff);
return;
case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100)
return;
S9xSetPPU(Byte, Address & 0xffff);
return;
case CMemory::MAP_LOROM_SRAM:
if (Memory.SRAMMask)
{
*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte;
CPU.SRAMModified = TRUE;
}
return;
case CMemory::MAP_LOROM_SRAM_B:
if (Multi.sramMaskB)
{
*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = Byte;
CPU.SRAMModified = TRUE;
}
return;
case CMemory::MAP_HIROM_SRAM:
if (Memory.SRAMMask)
{
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte;
CPU.SRAMModified = TRUE;
}
return;
case CMemory::MAP_BWRAM:
*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte;
CPU.SRAMModified = TRUE;
return;
case CMemory::MAP_SA1RAM:
*(Memory.SRAM + (Address & 0xffff)) = Byte;
return;
case CMemory::MAP_DSP:
S9xSetDSP(Byte, Address & 0xffff);
return;
case CMemory::MAP_C4:
S9xSetC4(Byte, Address & 0xffff);
return;
case CMemory::MAP_OBC_RAM:
S9xSetOBC1(Byte, Address & 0xffff);
return;
case CMemory::MAP_SETA_DSP:
S9xSetSetaDSP(Byte, Address);
return;
case CMemory::MAP_SETA_RISC:
S9xSetST018(Byte, Address);
return;
case CMemory::MAP_BSX:
S9xSetBSX(Byte, Address);
return;
case CMemory::MAP_NONE:
default:
return;
}
CPU.WaitAddress = WaitAddress;
CPU.Cycles = Cycles;
}
void S9xInitWatchedAddress (void)
{
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
}
void S9xInitCheatData (void)
{
Cheat.RAM = Memory.RAM;
Cheat.SRAM = Memory.SRAM;
Cheat.FillRAM = Memory.FillRAM;
Cheat.RAM = Memory.RAM;
Cheat.SRAM = Memory.SRAM;
Cheat.FillRAM = Memory.FillRAM;
}
void S9xUpdateCheatInMemory (SCheat *c)
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte)
{
uint8 byte;
if (Cheat.num_cheats < sizeof(Cheat.c) / sizeof(Cheat.c[0]))
{
Cheat.c[Cheat.num_cheats].address = address;
Cheat.c[Cheat.num_cheats].byte = byte;
Cheat.c[Cheat.num_cheats].enabled = enable;
if (!c->enabled)
return;
if (save_current_value)
{
Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address);
Cheat.c[Cheat.num_cheats].saved = TRUE;
}
byte = S9xGetByteFree (c->address);
if (byte != c->byte)
{
/* The game wrote a different byte to the address, update saved_byte */
c->saved_byte = byte;
if (c->conditional)
{
if (c->saved_byte != c->cond_byte && c->cond_true)
{
/* Condition is now false, let the byte stand */
c->cond_true = false;
}
else if (c->saved_byte == c->cond_byte && !c->cond_true)
{
c->cond_true = true;
S9xSetByteFree (c->byte, c->address);
}
}
else
S9xSetByteFree (c->byte, c->address);
}
else if (c->conditional)
{
if (byte == c->cond_byte)
{
c->cond_true = true;
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
}
}
Cheat.num_cheats++;
}
}
void S9xDisableCheat (SCheat *c)
void S9xDeleteCheat (uint32 which1)
{
if (!c->enabled)
return;
if (which1 < Cheat.num_cheats)
{
if (Cheat.c[which1].enabled)
S9xRemoveCheat(which1);
if (!Cheat.enabled)
{
c->enabled = false;
return;
}
memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1));
/* Make sure we restore the up-to-date written byte */
S9xUpdateCheatInMemory (c);
c->enabled = false;
if (c->conditional && !c->cond_true)
return;
S9xSetByteFree (c->saved_byte, c->address);
c->cond_true = false;
}
void S9xDeleteCheatGroup (uint32 g)
{
unsigned int i;
if (g >= Cheat.g.size ())
return;
for (i = 0; i < Cheat.g[g].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[g].c[i]);
}
delete[] Cheat.g[g].name;
Cheat.g.erase (Cheat.g.begin () + g);
Cheat.num_cheats--;
}
}
void S9xDeleteCheats (void)
{
unsigned int i;
for (i = 0; i < Cheat.g.size (); i++)
{
S9xDisableCheatGroup (i);
delete[] Cheat.g[i].name;
}
Cheat.g.clear ();
S9xRemoveCheats();
Cheat.num_cheats = 0;
}
void S9xEnableCheat (SCheat *c)
void S9xRemoveCheat (uint32 which1)
{
uint8 byte;
if (Cheat.c[which1].saved)
{
uint32 address = Cheat.c[which1].address;
if (c->enabled)
return;
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
c->enabled = true;
if (!Cheat.enabled)
return;
byte = S9xGetByteFree(c->address);
if (c->conditional)
{
if (byte != c->cond_byte)
return;
c->cond_true = true;
}
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte;
else
S9xSetByteFree(Cheat.c[which1].saved_byte, address);
}
}
void S9xEnableCheatGroup (uint32 num)
void S9xRemoveCheats (void)
{
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xEnableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = true;
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xRemoveCheat(i);
}
void S9xDisableCheatGroup (uint32 num)
void S9xEnableCheat (uint32 which1)
{
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = false;
if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled)
{
Cheat.c[which1].enabled = TRUE;
S9xApplyCheat(which1);
}
}
SCheat S9xTextToCheat (char *text)
void S9xDisableCheat (uint32 which1)
{
SCheat c;
unsigned int byte = 0;
unsigned int cond_byte = 0;
c.enabled = false;
c.conditional = false;
if (!S9xGameGenieToRaw (text, c.address, c.byte))
{
byte = c.byte;
}
else if (!S9xProActionReplayToRaw (text, c.address, c.byte))
{
byte = c.byte;
}
else if (sscanf (text, "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x = %x", &c.address, &byte) == 2)
{
}
else if (sscanf (text, "%x / %x / %x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x / %x", &c.address, &byte) == 2)
{
}
else
{
c.address = 0;
byte = 0;
}
c.byte = byte;
c.cond_byte = cond_byte;
return c;
if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled)
{
S9xRemoveCheat(which1);
Cheat.c[which1].enabled = FALSE;
}
}
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
void S9xApplyCheat (uint32 which1)
{
SCheatGroup g;
char *code;
char *code_string = strdup (cheat);
uint32 address = Cheat.c[which1].address;
g.name = strdup (name);
g.enabled = false;
if (!Cheat.c[which1].saved)
{
Cheat.c[which1].saved_byte = S9xGetByteFree(address);
Cheat.c[which1].saved = TRUE;
}
for (code = strtok (code_string, "+"); code; code = strtok (NULL, "+"))
{
if (code)
{
SCheat c = S9xTextToCheat (code);
if (c.address)
g.c.push_back (c);
}
}
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
delete[] code_string;
return g;
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].byte;
else
S9xSetByteFree(Cheat.c[which1].byte, address);
}
int S9xAddCheatGroup (const char *name, const char *cheat)
void S9xApplyCheats (void)
{
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
if (g.c.size () == 0)
return -1;
Cheat.g.push_back (g);
return Cheat.g.size () - 1;
}
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
{
if (num >= Cheat.g.size())
return -1;
S9xDisableCheatGroup (num);
delete[] Cheat.g[num].name;
Cheat.g[num] = S9xCreateCheatGroup (name, cheat);
return num;
}
char *S9xCheatToText (SCheat *c)
{
int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */
char *text;
if (c->conditional)
size += 3; /* additional 2 byte, 1 ? */
text = new char[size];
if (c->conditional)
snprintf (text, size, "%06x=%02x?%02x", c->address, c->cond_byte, c->byte);
else
snprintf (text, size, "%06x=%02x", c->address, c->byte);
return text;
}
char *S9xCheatGroupToText (SCheatGroup *g)
{
std::string text = "";
unsigned int i;
if (g->c.size () == 0)
return NULL;
for (i = 0; i < g->c.size (); i++)
{
char *tmp = S9xCheatToText (&g->c[i]);
if (i != 0)
text += " + ";
text += tmp;
delete[] tmp;
}
return strdup (text.c_str ());
}
char *S9xCheatValidate (char *code_string)
{
SCheatGroup g = S9xCreateCheatGroup ("temp", code_string);
delete[] g.name;
if (g.c.size() > 0)
{
return S9xCheatGroupToText (&g);
}
return NULL;
}
char *S9xCheatGroupToText (uint32 num)
{
if (num >= Cheat.g.size ())
return NULL;
return S9xCheatGroupToText (&Cheat.g[num]);
}
void S9xUpdateCheatsInMemory (void)
{
unsigned int i;
unsigned int j;
if (!Cheat.enabled)
return;
for (i = 0; i < Cheat.g.size (); i++)
{
for (j = 0; j < Cheat.g[i].c.size (); j++)
{
S9xUpdateCheatInMemory (&Cheat.g[i].c[j]);
}
}
}
static int S9xCheatIsDuplicate (char *name, char *code)
{
unsigned int i;
for (i = 0; i < Cheat.g.size(); i++)
{
if (!strcmp (name, Cheat.g[i].name))
{
char *code_string = S9xCheatGroupToText (i);
char *validated = S9xCheatValidate (code);
if (validated && !strcmp (code_string, validated))
{
free (code_string);
free (validated);
return TRUE;
}
free (code_string);
free (validated);
}
}
return FALSE;
}
static void S9xLoadCheatsFromBMLNode (bml_node *n)
{
unsigned int i;
for (i = 0; i < n->child.size (); i++)
{
if (!strcasecmp (n->child[i]->name, "cheat"))
{
char *desc = NULL;
char *code = NULL;
bool8 enabled = false;
bml_node *c = n->child[i];
bml_node *tmp = NULL;
tmp = bml_find_sub(c, "name");
if (!tmp)
desc = (char *) "";
else
desc = tmp->data;
tmp = bml_find_sub(c, "code");
if (tmp)
code = tmp->data;
if (bml_find_sub(c, "enable"))
enabled = true;
if (code && !S9xCheatIsDuplicate (desc, code))
{
int index = S9xAddCheatGroup (desc, code);
if (enabled)
S9xEnableCheatGroup (index);
}
}
}
return;
}
static bool8 S9xLoadCheatFileClassic (const char *filename)
{
FILE *fs;
uint8 data[28];
fs = fopen(filename, "rb");
if (!fs)
return (FALSE);
while (fread ((void *) data, 1, 28, fs) == 28)
{
SCheat c;
char name[21];
char cheat[10];
c.enabled = (data[0] & 4) == 0;
c.byte = data[1];
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
memcpy (name, &data[8], 20);
name[20] = 0;
snprintf (cheat, 10, "%x=%x", c.address, c.byte);
S9xAddCheatGroup (name, cheat);
if (c.enabled)
S9xEnableCheatGroup (Cheat.g.size () - 1);
}
fclose(fs);
return (TRUE);
if (Settings.ApplyCheats)
{
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xApplyCheat(i);
}
}
bool8 S9xLoadCheatFile (const char *filename)
{
bml_node *bml = NULL;
bml_node *n = NULL;
FILE *fs;
uint8 data[28];
bml = bml_parse_file (filename);
if (!bml)
{
return S9xLoadCheatFileClassic (filename);
}
Cheat.num_cheats = 0;
n = bml_find_sub (bml, "cheat");
if (n)
{
S9xLoadCheatsFromBMLNode (bml);
}
fs = fopen(filename, "rb");
if (!fs)
return (FALSE);
bml_free_node (bml);
while (fread((void *) data, 1, 28, fs) == 28)
{
Cheat.c[Cheat.num_cheats].enabled = (data[0] & 4) == 0;
Cheat.c[Cheat.num_cheats].byte = data[1];
Cheat.c[Cheat.num_cheats].address = data[2] | (data[3] << 8) | (data[4] << 16);
Cheat.c[Cheat.num_cheats].saved_byte = data[5];
Cheat.c[Cheat.num_cheats].saved = (data[0] & 8) != 0;
memmove(Cheat.c[Cheat.num_cheats].name, &data[8], 20);
Cheat.c[Cheat.num_cheats++].name[20] = 0;
}
if (!n)
{
return S9xLoadCheatFileClassic (filename);
}
fclose(fs);
return (TRUE);
return (TRUE);
}
bool8 S9xSaveCheatFile (const char *filename)
{
unsigned int i;
FILE *file = NULL;
if (Cheat.num_cheats == 0)
{
remove(filename);
return (TRUE);
}
if (Cheat.g.size () == 0)
{
remove (filename);
return TRUE;
}
FILE *fs;
uint8 data[28];
file = fopen (filename, "w");
fs = fopen(filename, "wb");
if (!fs)
return (FALSE);
if (!file)
return FALSE;
for (uint32 i = 0; i < Cheat.num_cheats; i++)
{
memset(data, 0, 28);
for (i = 0; i < Cheat.g.size (); i++)
{
char *txt = S9xCheatGroupToText (i);
if (i == 0)
{
data[6] = 254;
data[7] = 252;
}
fprintf (file,
"cheat\n"
" name: %s\n"
" code: %s\n"
"%s\n",
Cheat.g[i].name ? Cheat.g[i].name : "",
txt,
Cheat.g[i].enabled ? " enable\n" : ""
);
if (!Cheat.c[i].enabled)
data[0] |= 4;
delete[] txt;
}
if (Cheat.c[i].saved)
data[0] |= 8;
fclose (file);
data[1] = Cheat.c[i].byte;
data[2] = (uint8) (Cheat.c[i].address >> 0);
data[3] = (uint8) (Cheat.c[i].address >> 8);
data[4] = (uint8) (Cheat.c[i].address >> 16);
data[5] = Cheat.c[i].saved_byte;
return TRUE;
}
void S9xCheatsDisable (void)
{
unsigned int i;
if (!Cheat.enabled)
return;
for (i = 0; i < Cheat.g.size (); i++)
{
if (Cheat.g[i].enabled)
{
S9xDisableCheatGroup (i);
Cheat.g[i].enabled = TRUE;
}
}
Cheat.enabled = FALSE;
}
void S9xCheatsEnable (void)
{
unsigned int i;
if (Cheat.enabled)
return;
Cheat.enabled = TRUE;
for (i = 0; i < Cheat.g.size (); i++)
{
if (Cheat.g[i].enabled)
{
Cheat.g[i].enabled = FALSE;
S9xEnableCheatGroup (i);
}
}
}
int S9xImportCheatsFromDatabase (const char *filename)
{
bml_node *bml;
char sha256_txt[65];
char hextable[] = "0123456789abcdef";
unsigned int i;
bml = bml_parse_file (filename);
if (!bml)
return -1; /* No file */
for (i = 0; i < 32; i++)
{
sha256_txt[i * 2] = hextable[Memory.ROMSHA256[i] >> 4];
sha256_txt[i * 2 + 1] = hextable[Memory.ROMSHA256[i] & 0xf];
}
sha256_txt[64] = '\0';
for (i = 0; i < bml->child.size (); i++)
{
if (!strcasecmp (bml->child[i]->name, "cartridge"))
{
bml_node *n;
if ((n = bml_find_sub (bml->child[i], "sha256")))
{
if (!strcasecmp (n->data, sha256_txt))
{
S9xLoadCheatsFromBMLNode (bml->child[i]);
bml_free_node (bml);
return 0;
}
}
}
}
bml_free_node (bml);
return -2; /* No codes */
memmove(&data[8], Cheat.c[i].name, 19);
if (fwrite(data, 28, 1, fs) != 1)
{
fclose(fs);
return (FALSE);
}
}
return (fclose(fs) == 0);
}

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -196,7 +181,6 @@
#include <string>
#include <algorithm>
#include <assert.h>
#include <ctype.h>
#include "snes9x.h"
#include "memmap.h"
@ -210,6 +194,10 @@
#include "netplay.h"
#endif
#ifdef GEKKO
#include "../snes9xgx.h"
#endif
using namespace std;
#define NONE (-2)
@ -227,8 +215,7 @@ using namespace std;
#define SUPERSCOPE 10
#define ONE_JUSTIFIER 11
#define TWO_JUSTIFIERS 12
#define MACSRIFLE 13
#define NUMCTLS 14 // This must be LAST
#define NUMCTLS 13 // This must be LAST
#define POLL_ALL NUMCTLS
@ -242,8 +229,6 @@ using namespace std;
#define JUSTIFIER_START 0x20
#define JUSTIFIER_SELECT 0x08
#define MACSRIFLE_TRIGGER 0x01
#define MAP_UNKNOWN (-1)
#define MAP_NONE 0
#define MAP_BUTTON 1
@ -324,14 +309,6 @@ static struct
int8 pads[4];
} mp5[2];
static struct
{
int16 x, y;
uint8 buttons;
uint32 ID;
struct crosshair crosshair;
} macsrifle;
static set<struct exemulti *> exemultis;
static set<uint32> pollmap[NUMCTLS + 1];
static map<uint32, s9xcommand_t> keymap;
@ -452,6 +429,7 @@ static const int ptrspeeds[4] = { 1, 1, 4, 8 };
S(ToggleBG2), \
S(ToggleBG3), \
S(ToggleEmuTurbo), \
S(ToggleHDMA), \
S(ToggleSprites), \
S(ToggleTransparency) \
@ -477,7 +455,6 @@ static const char *command_names[LAST_COMMAND + 1] =
static void DisplayStateChange (const char *, bool8);
static void DoGunLatch (int, int);
static void DoMacsRifleLatch (int, int);
static int maptype (int);
static bool strless (const char *, const char *);
static int findstr (const char *, const char **, int);
@ -528,12 +505,6 @@ static void DoGunLatch (int x, int y)
PPU.GunHLatch = (uint16) x;
}
static void DoMacsRifleLatch (int x, int y)
{
PPU.GunVLatch = (uint16) (y + 42);// + (int16) macsrifle.adjust_y;
PPU.GunHLatch = (uint16) (x + 76);// + (int16) macsrifle.adjust_x;
}
static int maptype (int t)
{
switch (t)
@ -545,7 +516,6 @@ static int maptype (int t)
case S9xButtonMouse:
case S9xButtonSuperscope:
case S9xButtonJustifier:
case S9xButtonMacsRifle:
case S9xButtonCommand:
case S9xButtonPseudopointer:
case S9xButtonPort:
@ -573,7 +543,6 @@ void S9xControlsReset (void)
mouse[0].buttons &= ~0x30;
mouse[1].buttons &= ~0x30;
justifier.buttons &= ~JUSTIFIER_SELECT;
macsrifle.buttons = 0;
}
void S9xControlsSoftReset (void)
@ -587,9 +556,6 @@ void S9xControlsSoftReset (void)
read_idx[i][j]=0;
FLAG_LATCH = FALSE;
curcontrollers[0] = newcontrollers[0];
curcontrollers[1] = newcontrollers[1];
}
void S9xUnmapAllControls (void)
@ -661,17 +627,6 @@ void S9xUnmapAllControls (void)
if (!(superscope.crosshair.set & 4))
superscope.crosshair.bg = 1;
macsrifle.x = macsrifle.y = 0;
macsrifle.buttons = 0;
macsrifle.ID = InvalidControlID;
if (!(macsrifle.crosshair.set & 1))
macsrifle.crosshair.img = 2;
if (!(macsrifle.crosshair.set & 2))
macsrifle.crosshair.fg = 5;
if (!(macsrifle.crosshair.set & 4))
macsrifle.crosshair.bg = 1;
memset(pseudobuttons, 0, sizeof(pseudobuttons));
turbo_time = 1;
@ -728,16 +683,6 @@ void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2
newcontrollers[port] = ONE_JUSTIFIER + id1;
return;
case CTL_MACSRIFLE:
if (!Settings.MacsRifleMaster)
{
S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES M.A.C.S. Rifle: MacsRifleMaster disabled");
break;
}
newcontrollers[port] = MACSRIFLE;
return;
case CTL_MP5:
if (id1 < -1 || id1 > 7)
break;
@ -841,26 +786,6 @@ bool S9xVerifyControllers (void)
break;
case MACSRIFLE:
if (!Settings.MacsRifleMaster)
{
S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES M.A.C.S. Rifle: MacsRifleMaster disabled");
newcontrollers[port] = NONE;
ret = true;
break;
}
if (used[i]++ > 0)
{
snprintf(buf, sizeof(buf), "M.A.C.S. Rifle used more than once! Disabling extra instances");
S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf);
newcontrollers[port] = NONE;
ret = true;
break;
}
break;
case MP5:
if (!Settings.MultiPlayer5Master)
{
@ -962,11 +887,6 @@ void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *
*controller = CTL_JUSTIFIER;
*id1 = i - ONE_JUSTIFIER;
return;
case MACSRIFLE:
*controller = CTL_MACSRIFLE;
*id1 = 1;
return;
}
}
@ -1035,13 +955,6 @@ void S9xReportControllers (void)
else
c += sprintf(c, "Blue and Pink Justifiers. ");
break;
case MACSRIFLE:
if (port == 0)
c += sprintf(c, "M.A.C.S. Rifle (cannot fire). ");
else
c += sprintf(c, "M.A.C.S. Rifle. ");
break;
}
}
@ -1129,17 +1042,6 @@ char * S9xGetCommandName (s9xcommand_t command)
break;
case S9xButtonMacsRifle:
if (!command.button.macsrifle.trigger)
return (strdup("None"));
s = "MacsRifle";
c = ' ';
if (command.button.macsrifle.trigger) { s += c; s += "Trigger"; c = '+'; }
break;
case S9xButtonCommand:
if (command.button.command >= LAST_COMMAND)
return (strdup("None"));
@ -1147,7 +1049,7 @@ char * S9xGetCommandName (s9xcommand_t command)
return (strdup(command_names[command.button.command]));
case S9xPointer:
if (!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1 && !command.pointer.aim_macsrifle)
if (!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1)
return (strdup("None"));
s = "Pointer";
@ -1158,7 +1060,6 @@ char * S9xGetCommandName (s9xcommand_t command)
if (command.pointer.aim_scope ) { s += c; s += "Superscope"; c = '+'; }
if (command.pointer.aim_justifier0) { s += c; s += "Justifier1"; c = '+'; }
if (command.pointer.aim_justifier1) { s += c; s += "Justifier2"; c = '+'; }
if (command.pointer.aim_macsrifle) { s += c; s += "MacsRifle"; c = '+'; }
break;
@ -1492,19 +1393,6 @@ s9xcommand_t S9xGetCommandT (const char *name)
cmd.type = S9xButtonJustifier;
}
else
if (!strncmp(name, "MacsRifle ", 10))
{
s = name + 10;
i = 0;
if ((cmd.button.macsrifle.trigger = strncmp(s, "Trigger", 7) ? 0 : 1)) { s += i = 7; }
if (i == 0 || *s != 0 || *(s - 1) == '+')
return (cmd);
cmd.type = S9xButtonMacsRifle;
}
else
if (!strncmp(name, "Pointer ", 8))
{
s = name + 8;
@ -1514,8 +1402,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
if ((cmd.pointer.aim_mouse1 = strncmp(s, "Mouse2", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; }
if ((cmd.pointer.aim_scope = strncmp(s, "Superscope", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; }
if ((cmd.pointer.aim_justifier0 = strncmp(s, "Justifier1", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; }
if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; }
if ((cmd.pointer.aim_macsrifle = strncmp(s, "MacsRifle", 9) ? 0 : 1)) { s += i = 9; }
if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1)) { s += i = 10; }
if (i == 0 || *s != 0 || *(s - 1) == '+')
return (cmd);
@ -1816,7 +1703,6 @@ void S9xUnmapID (uint32 id)
if (superscope.ID == id) superscope.ID = InvalidControlID;
if (justifier.ID[0] == id) justifier.ID[0] = InvalidControlID;
if (justifier.ID[1] == id) justifier.ID[1] = InvalidControlID;
if (macsrifle.ID == id) macsrifle.ID = InvalidControlID;
if (id >= PseudoPointerBase)
pseudopointer[id - PseudoPointerBase].mapped = false;
@ -1882,10 +1768,6 @@ bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll)
t = ONE_JUSTIFIER + mapping.button.justifier.idx;
break;
case S9xButtonMacsRifle:
t = MACSRIFLE;
break;
case S9xButtonCommand:
case S9xButtonPseudopointer:
case S9xButtonPort:
@ -1992,12 +1874,6 @@ bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll)
fprintf(stderr, "ERROR: Rejecting attempt to control Justifier2 with two pointers\n");
return (false);
}
if (mapping.pointer.aim_macsrifle && macsrifle.ID != InvalidControlID && macsrifle.ID != id)
{
fprintf(stderr, "ERROR: Rejecting attempt to control M.A.C.S. Rifle with two pointers\n");
return (false);
}
}
S9xUnmapID(id);
@ -2016,7 +1892,6 @@ bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll)
if (mapping.pointer.aim_scope ) pollmap[SUPERSCOPE ].insert(id);
if (mapping.pointer.aim_justifier0) pollmap[ONE_JUSTIFIER ].insert(id);
if (mapping.pointer.aim_justifier1) pollmap[TWO_JUSTIFIERS].insert(id);
if (mapping.pointer.aim_macsrifle ) pollmap[MACSRIFLE ].insert(id);
break;
case S9xPointerPort:
@ -2036,7 +1911,6 @@ bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll)
if (mapping.pointer.aim_scope ) superscope.ID = id;
if (mapping.pointer.aim_justifier0) justifier.ID[0] = id;
if (mapping.pointer.aim_justifier1) justifier.ID[1] = id;
if (mapping.pointer.aim_macsrifle ) macsrifle.ID = id;
return (true);
}
@ -2180,6 +2054,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
{
uint16 r, s, t, st;
s = t = st = 0;
r = cmd.button.joypad.buttons;
st = r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo;
r ^= st;
@ -2305,17 +2180,6 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
return;
case S9xButtonMacsRifle:
i = 0;
if (cmd.button.macsrifle.trigger) i |= MACSRIFLE_TRIGGER;
if(data1)
macsrifle.buttons |= i;
else
macsrifle.buttons &= ~i;
return;
case S9xButtonCommand:
if (((enum command_numbers) cmd.button.command) >= LAST_COMMAND)
{
@ -2472,7 +2336,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
if (S9xUnfreezeGame(filename))
{
snprintf(buf, 256, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
S9xSetInfoString (buf);
}
else
@ -2509,7 +2373,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
if (S9xUnfreezeGame(filename))
{
snprintf(buf, 256, "%s.%03d loaded", def, i - QuickLoad000);
sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000);
S9xSetInfoString(buf);
}
else
@ -2536,7 +2400,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000);
snprintf(buf, 256, "%s.%03d saved", def, i - QuickSave000);
sprintf(buf, "%s.%03d saved", def, i - QuickSave000);
S9xSetInfoString(buf);
S9xFreezeGame(filename);
@ -2594,6 +2458,11 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
DisplayStateChange("Sprites", !(Settings.BG_Forced & 16));
break;
case ToggleHDMA:
Settings.DisableHDMA = !Settings.DisableHDMA;
DisplayStateChange("HDMA emulation", !Settings.DisableHDMA);
break;
case ToggleTransparency:
Settings.Transparency = !Settings.Transparency;
DisplayStateChange("Transparency effects", Settings.Transparency);
@ -2711,12 +2580,6 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
justifier.y[1] = data2;
}
if (cmd.pointer.aim_macsrifle)
{
macsrifle.x = data1;
macsrifle.y = data2;
}
return;
case S9xButtonPseudopointer:
@ -3013,9 +2876,8 @@ void S9xSetJoypadLatch (bool latch)
switch (i = curcontrollers[n])
{
case MP5:
for (int j = 0, k; j < 4; ++j)
for (int j = 0, k = mp5[n].pads[j]; j < 4; k = mp5[n].pads[++j])
{
k = mp5[n].pads[j];
if (k == NONE)
continue;
do_polling(k);
@ -3072,10 +2934,6 @@ void S9xSetJoypadLatch (bool latch)
do_polling(ONE_JUSTIFIER);
break;
case MACSRIFLE:
do_polling(i);
break;
default:
break;
}
@ -3126,10 +2984,6 @@ uint8 S9xReadJOYSERn (int n)
case TWO_JUSTIFIERS:
return (bits);
case MACSRIFLE:
do_polling(i);
return (bits | ((macsrifle.buttons & 0x01) ? 1 : 0));
default:
return (bits);
}
@ -3225,10 +3079,6 @@ uint8 S9xReadJOYSERn (int n)
return (bits | 1);
}
case MACSRIFLE:
do_polling(i);
return (bits | ((macsrifle.buttons & 0x01) ? 1 : 0));
default:
read_idx[n][0]++;
return (bits);
@ -3296,13 +3146,6 @@ void S9xDoAutoJoypad (void)
WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0);
break;
case MACSRIFLE:
read_idx[n][0] = 16;
Memory.FillRAM[0x4218 + n * 2] = 0xff;
Memory.FillRAM[0x4219 + n * 2] = macsrifle.buttons;
WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0);
break;
default:
WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0);
WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0);
@ -3324,9 +3167,8 @@ void S9xControlEOF (void)
switch (i = curcontrollers[n])
{
case MP5:
for (j = 0; j < 4; ++j)
for (j = 0, i = mp5[n].pads[j]; j < 4; i = mp5[n].pads[++j])
{
i = mp5[n].pads[j];
if (i == NONE)
continue;
@ -3369,6 +3211,9 @@ void S9xControlEOF (void)
DoGunLatch(superscope.x, superscope.y);
c = &superscope.crosshair;
#ifdef GEKKO
if(GCSettings.crosshair)
#endif
if (IPPU.RenderThisFrame)
S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, superscope.x, superscope.y);
}
@ -3379,6 +3224,9 @@ void S9xControlEOF (void)
if (n == 1 && !justifier.offscreen[1])
{
c = &justifier.crosshair[1];
#ifdef GEKKO
if(GCSettings.crosshair)
#endif
if (IPPU.RenderThisFrame)
S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[1], justifier.y[1]);
}
@ -3398,6 +3246,9 @@ void S9xControlEOF (void)
if (!justifier.offscreen[0])
{
c = &justifier.crosshair[0];
#ifdef GEKKO
if(GCSettings.crosshair)
#endif
if (IPPU.RenderThisFrame)
S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[0], justifier.y[0]);
}
@ -3405,18 +3256,6 @@ void S9xControlEOF (void)
break;
case MACSRIFLE:
if (n == 1)
{
DoMacsRifleLatch(macsrifle.x, macsrifle.y);
c = &macsrifle.crosshair;
if (IPPU.RenderThisFrame)
S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, macsrifle.x, macsrifle.y);
}
break;
default:
break;
}
@ -3522,7 +3361,6 @@ void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg
case X_SUPERSCOPE: c = &superscope.crosshair; break;
case X_JUSTIFIER1: c = &justifier.crosshair[0]; break;
case X_JUSTIFIER2: c = &justifier.crosshair[1]; break;
case X_MACSRIFLE: c = &macsrifle.crosshair; break;
default:
fprintf(stderr, "S9xSetControllerCrosshair() called with an invalid controller ID %d\n", ctl);
return;
@ -3540,9 +3378,8 @@ void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg
for (i = 0; i < 16; i++)
{
for (j = 0; color_names[i][j] && fg[j] == color_names[i][j]; j++) ;
if (isalnum(fg[j]))
continue;
if (isalnum(fg[j]))
continue;
if (!color_names[i][j])
break;
@ -3568,9 +3405,8 @@ void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg
for (i = 0; i < 16; i++)
{
for (j = 0; color_names[i][j] && bg[j] == color_names[i][j]; j++) ;
if (isalnum(bg[j]))
continue;
if (isalnum(bg[j]))
continue;
if (!color_names[i][j])
break;
@ -3614,7 +3450,6 @@ void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **
case X_SUPERSCOPE: c = &superscope.crosshair; break;
case X_JUSTIFIER1: c = &justifier.crosshair[0]; break;
case X_JUSTIFIER2: c = &justifier.crosshair[1]; break;
case X_MACSRIFLE: c = &macsrifle.crosshair; break;
default:
fprintf(stderr, "S9xGetControllerCrosshair() called with an invalid controller ID %d\n", ctl);
return;
@ -3633,7 +3468,7 @@ void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **
void S9xControlPreSaveState (struct SControlSnapshot *s)
{
memset(s, 0, sizeof(*s));
s->ver = 4;
s->ver = 3;
for (int j = 0; j < 2; j++)
{
@ -3682,11 +3517,7 @@ void S9xControlPreSaveState (struct SControlSnapshot *s)
for (int k = 0; k < 2; k++)
COPY(mp5[j].pads[k]);
COPY(macsrifle.x);
COPY(macsrifle.y);
COPY(macsrifle.buttons);
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
assert(i == sizeof(s->internal));
#undef COPY
@ -3759,15 +3590,6 @@ void S9xControlPostLoadState (struct SControlSnapshot *s)
assert(i == sizeof(s->internal));
if (s->ver > 3)
{
COPY(macsrifle.x);
COPY(macsrifle.y);
COPY(macsrifle.buttons);
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
}
#undef COPY
}
@ -3886,30 +3708,3 @@ void MovieSetJustifier (int i, uint8 in[11])
justifier.offscreen[0] = *ptr++;
justifier.offscreen[1] = *ptr;
}
bool MovieGetMacsRifle (int i, uint8 out[5])
{
if (i < 0 || i > 1 || curcontrollers[i] != MACSRIFLE)
return (false);
uint8 *ptr = out;
WRITE_WORD(ptr, macsrifle.x); ptr += 2;
WRITE_WORD(ptr, macsrifle.y); ptr += 2;
*ptr = macsrifle.buttons;
return (true);
}
void MovieSetMacsRifle (int i, uint8 in[5])
{
if (i < 0 || i > 1 || curcontrollers[i] != MACSRIFLE)
return;
uint8 *ptr = in;
macsrifle.x = READ_WORD(ptr); ptr += 2;
macsrifle.y = READ_WORD(ptr); ptr += 2;
macsrifle.buttons = *ptr;
}

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -188,7 +173,7 @@
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co., Limited and its subsidiary companies.
***********************************************************************************/
#include "port.h"
#ifndef _CONTROLS_H_
#define _CONTROLS_H_
@ -200,9 +185,8 @@
#define S9xButtonJustifier 4
#define S9xButtonCommand 5
#define S9xButtonMulti 6
#define S9xButtonMacsRifle 7
#define S9xAxisJoypad 8
#define S9xPointer 9
#define S9xAxisJoypad 7
#define S9xPointer 8
#define S9xButtonPseudopointer 254
#define S9xAxisPseudopointer 253
@ -275,11 +259,6 @@ typedef struct
uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer)
} justifier;
struct
{
uint8 trigger:1;
} macsrifle;
int32 multi_idx;
uint16 command;
} button;
@ -317,7 +296,6 @@ typedef struct
uint16 aim_scope:1;
uint16 aim_justifier0:1;
uint16 aim_justifier1:1;
uint16 aim_macsrifle:1;
} pointer;
uint8 port[4];
@ -337,8 +315,7 @@ enum controllers
CTL_MOUSE, // use id1 to specify 0-1
CTL_SUPERSCOPE,
CTL_JUSTIFIER, // use id1: 0=one justifier, 1=two justifiers
CTL_MP5, // use id1-id4 to specify pad 0-7 (or -1)
CTL_MACSRIFLE
CTL_MP5 // use id1-id4 to specify pad 0-7 (or -1)
};
void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); // port=0-1
@ -468,7 +445,6 @@ struct SControlSnapshot
uint8 dummy3[8];
bool8 pad_read, pad_read_last;
uint8 internal[60]; // yes, we need to save this!
uint8 internal_macs[5];
};
void S9xControlPreSaveState (struct SControlSnapshot *s);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -223,14 +208,12 @@ static void S9xResetCPU (void)
static void S9xSoftResetCPU (void)
{
CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector.
CPU.PrevCycles = CPU.Cycles;
CPU.PrevCycles = -1;
CPU.V_Counter = 0;
CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG);
CPU.PCBase = NULL;
CPU.NMIPending = FALSE;
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQExternal = FALSE;
CPU.IRQActive = FALSE;
CPU.IRQPending = 0;
CPU.MemSpeed = SLOW_ONE_CYCLE;
CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
CPU.FastROMSpeed = SLOW_ONE_CYCLE;
@ -243,6 +226,9 @@ static void S9xSoftResetCPU (void)
CPU.WhichEvent = HC_RENDER_EVENT;
CPU.NextEvent = Timings.RenderPos;
CPU.WaitingForInterrupt = FALSE;
CPU.WaitAddress = 0xffffffff;
CPU.WaitCounter = 0;
CPU.PBPCAtOpcodeStart = 0xffffffff;
CPU.AutoSaveTimer = 0;
CPU.SRAMModified = FALSE;
@ -266,9 +252,6 @@ static void S9xSoftResetCPU (void)
Timings.H_Max = Timings.H_Max_Master;
Timings.V_Max = Timings.V_Max_Master;
Timings.NMITriggerPos = 0xffff;
Timings.NextIRQTimer = 0x0fffffff;
Timings.IRQFlagChanging = IRQ_NONE;
if (Model->_5A22 == 2)
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2;
else
@ -278,6 +261,7 @@ static void S9xSoftResetCPU (void)
ICPU.S9xOpcodes = S9xOpcodesE1;
ICPU.S9xOpLengths = S9xOpLengthsM1X1;
ICPU.CPUExecuting = TRUE;
S9xUnpackStatus();
}
@ -291,12 +275,14 @@ void S9xReset (void)
memset(Memory.VRAM, 0x00, 0x10000);
memset(Memory.FillRAM, 0, 0x8000);
S9xResetBSX();
if (Settings.BS)
S9xResetBSX();
S9xResetCPU();
S9xResetPPU();
S9xResetDMA();
S9xResetAPU();
S9xResetMSU();
S9xResetMSU();
if (Settings.DSP)
S9xResetDSP();
@ -333,7 +319,7 @@ void S9xSoftReset (void)
S9xSoftResetPPU();
S9xResetDMA();
S9xSoftResetAPU();
S9xResetMSU();
S9xResetMSU();
if (Settings.DSP)
S9xResetDSP();

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -202,115 +187,98 @@
#include "missing.h"
#endif
static inline void S9xReschedule (void);
void S9xMainLoop (void)
{
#define CHECK_FOR_IRQ_CHANGE() \
if (Timings.IRQFlagChanging) \
{ \
if (Timings.IRQFlagChanging == IRQ_CLEAR_FLAG) \
ClearIRQ(); \
else if (Timings.IRQFlagChanging == IRQ_SET_FLAG) \
SetIRQ(); \
Timings.IRQFlagChanging = IRQ_NONE; \
}
for (;;)
{
if (CPU.NMIPending)
if (CPU.Flags)
{
#ifdef DEBUGGER
if (Settings.TraceHCEvent)
S9xTraceFormattedMessage ("Comparing %d to %d\n", Timings.NMITriggerPos, CPU.Cycles);
#endif
if (Timings.NMITriggerPos <= CPU.Cycles)
if (CPU.Flags & NMI_FLAG)
{
CPU.NMIPending = FALSE;
Timings.NMITriggerPos = 0xffff;
if (CPU.WaitingForInterrupt)
if (Timings.NMITriggerPos <= CPU.Cycles)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing();
CPU.Flags &= ~NMI_FLAG;
Timings.NMITriggerPos = 0xffff;
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
S9xOpcode_NMI();
}
CHECK_FOR_IRQ_CHANGE();
S9xOpcode_NMI();
}
}
if (CPU.Cycles >= Timings.NextIRQTimer)
{
#ifdef DEBUGGER
S9xTraceMessage ("Timer triggered\n");
#endif
S9xUpdateIRQPositions(false);
CPU.IRQLine = TRUE;
}
if (CPU.IRQLine || CPU.IRQExternal)
{
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing();
}
if (!CheckFlag(IRQ))
#ifdef DEBUGGER
if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
{
/* The flag pushed onto the stack is the new value */
CHECK_FOR_IRQ_CHANGE();
S9xOpcode_IRQ();
}
}
/* Change IRQ flag for instructions that set it only on last cycle */
CHECK_FOR_IRQ_CHANGE();
#ifdef DEBUGGER
if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
{
for (int Break = 0; Break != 6; Break++)
{
if (S9xBreakpoint[Break].Enabled &&
S9xBreakpoint[Break].Bank == Registers.PB &&
S9xBreakpoint[Break].Address == Registers.PCw)
for (int Break = 0; Break != 6; Break++)
{
if (S9xBreakpoint[Break].Enabled == 2)
S9xBreakpoint[Break].Enabled = TRUE;
if (S9xBreakpoint[Break].Enabled &&
S9xBreakpoint[Break].Bank == Registers.PB &&
S9xBreakpoint[Break].Address == Registers.PCw)
{
if (S9xBreakpoint[Break].Enabled == 2)
S9xBreakpoint[Break].Enabled = TRUE;
else
CPU.Flags |= DEBUG_MODE_FLAG;
}
}
}
#endif
if (CPU.Flags & IRQ_FLAG)
{
if (CPU.IRQPending)
// FIXME: In case of IRQ during WRAM refresh
CPU.IRQPending--;
else
{
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
if (CPU.IRQActive && !Settings.DisableIRQ)
{
if (!CheckFlag(IRQ))
// in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared.
S9xOpcode_IRQ();
}
else
CPU.Flags |= DEBUG_MODE_FLAG;
CPU.Flags &= ~IRQ_FLAG;
}
}
if (CPU.Flags & SCAN_KEYS_FLAG)
break;
#ifdef DEBUGGER
if (CPU.Flags & DEBUG_MODE_FLAG)
break;
if (CPU.Flags & TRACE_FLAG)
S9xTrace();
if (CPU.Flags & SINGLE_STEP_FLAG)
{
CPU.Flags &= ~SINGLE_STEP_FLAG;
CPU.Flags |= DEBUG_MODE_FLAG;
}
#endif
}
if (CPU.Flags & DEBUG_MODE_FLAG)
break;
if (CPU.Flags & TRACE_FLAG)
S9xTrace();
if (CPU.Flags & SINGLE_STEP_FLAG)
{
CPU.Flags &= ~SINGLE_STEP_FLAG;
CPU.Flags |= DEBUG_MODE_FLAG;
}
#ifdef CPU_SHUTDOWN
CPU.PBPCAtOpcodeStart = Registers.PBPC;
#endif
if (CPU.Flags & SCAN_KEYS_FLAG)
break;
register uint8 Op;
register struct SOpcodes *Opcodes;
CPU.PrevCycles = CPU.Cycles;
if (CPU.PCBase)
{
Op = CPU.PCBase[Registers.PCw];
@ -336,8 +304,13 @@ void S9xMainLoop (void)
Registers.PCw++;
(*Opcodes[Op].S9xOpcode)();
if (Settings.SA1)
if (SA1.Executing)
S9xSA1MainLoop();
#if (S9X_ACCURACY_LEVEL <= 2)
while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing();
#endif
}
S9xPackStatus();
@ -352,70 +325,76 @@ void S9xMainLoop (void)
}
}
static inline void S9xReschedule (void)
void S9xSetIRQ (uint32 source)
{
switch (CPU.WhichEvent)
CPU.IRQActive |= source;
CPU.IRQPending = Timings.IRQPendCount;
CPU.Flags |= IRQ_FLAG;
if (CPU.WaitingForInterrupt)
{
case HC_HBLANK_START_EVENT:
CPU.WhichEvent = HC_HDMA_START_EVENT;
CPU.NextEvent = Timings.HDMAStart;
break;
case HC_HDMA_START_EVENT:
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
CPU.NextEvent = Timings.H_Max;
break;
case HC_HCOUNTER_MAX_EVENT:
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
CPU.NextEvent = Timings.HDMAInit;
break;
case HC_HDMA_INIT_EVENT:
CPU.WhichEvent = HC_RENDER_EVENT;
CPU.NextEvent = Timings.RenderPos;
break;
case HC_RENDER_EVENT:
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
CPU.NextEvent = Timings.WRAMRefreshPos;
break;
case HC_WRAM_REFRESH_EVENT:
CPU.WhichEvent = HC_HBLANK_START_EVENT;
CPU.NextEvent = Timings.HBlankStart;
break;
// Force IRQ to trigger immediately after WAI -
// Final Fantasy Mystic Quest crashes without this.
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
#ifdef DEBUGGER
S9xTraceMessage("--- /IRQ low");
#endif
}
void S9xClearIRQ (uint32 source)
{
CPU.IRQActive &= ~source;
if (!CPU.IRQActive)
CPU.Flags &= ~IRQ_FLAG;
#ifdef DEBUGGER
S9xTraceMessage("--- /IRQ high");
#endif
}
void S9xDoHEventProcessing (void)
{
#ifdef DEBUGGER
static char eventname[7][32] =
static char eventname[13][32] =
{
"",
"HC_HBLANK_START_EVENT",
"HC_IRQ_1_3_EVENT ",
"HC_HDMA_START_EVENT ",
"HC_IRQ_3_5_EVENT ",
"HC_HCOUNTER_MAX_EVENT",
"HC_IRQ_5_7_EVENT ",
"HC_HDMA_INIT_EVENT ",
"HC_IRQ_7_9_EVENT ",
"HC_RENDER_EVENT ",
"HC_WRAM_REFRESH_EVENT"
"HC_IRQ_9_A_EVENT ",
"HC_WRAM_REFRESH_EVENT",
"HC_IRQ_A_1_EVENT "
};
#endif
#ifdef DEBUGGER
if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d VC:%04d",
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles, CPU.V_Counter);
S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d",
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
#endif
#ifdef CPU_SHUTDOWN
CPU.WaitCounter++;
#endif
switch (CPU.WhichEvent)
{
case HC_HBLANK_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HBlankStart);
S9xReschedule();
break;
case HC_HDMA_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
S9xReschedule();
if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
@ -438,12 +417,11 @@ void S9xDoHEventProcessing (void)
S9xAPUEndScanline();
CPU.Cycles -= Timings.H_Max;
if (Timings.NMITriggerPos != 0xffff)
Timings.NMITriggerPos -= Timings.H_Max;
if (Timings.NextIRQTimer != 0x0fffffff)
Timings.NextIRQTimer -= Timings.H_Max;
S9xAPUSetReferenceTime(CPU.Cycles);
if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
Timings.NMITriggerPos -= Timings.H_Max;
CPU.V_Counter++;
if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
{
@ -467,9 +445,12 @@ void S9xDoHEventProcessing (void)
// FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles.
Memory.FillRAM[0x4210] = Model->_5A22;
CPU.Flags &= ~NMI_FLAG;
Timings.NMITriggerPos = 0xffff;
ICPU.Frame++;
PPU.HVBeamCounterLatched = 0;
CPU.Flags |= SCAN_KEYS_FLAG;
}
// From byuu:
@ -496,12 +477,11 @@ void S9xDoHEventProcessing (void)
else
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1;
S9xCheckMissingHTimerPosition(0);
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
{
S9xEndScreenRefresh();
CPU.Flags |= SCAN_KEYS_FLAG;
PPU.HDMA = 0;
// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
#ifdef DEBUGGER
@ -531,13 +511,9 @@ void S9xDoHEventProcessing (void)
Memory.FillRAM[0x4210] = 0x80 | Model->_5A22;
if (Memory.FillRAM[0x4200] & 0x80)
{
#ifdef DEBUGGER
if (Settings.TraceHCEvent)
S9xTraceFormattedMessage ("NMI Scheduled for next scanline.");
#endif
// FIXME: triggered at HC=6, checked just before the final CPU cycle,
// then, when to call S9xOpcode_NMI()?
CPU.NMIPending = TRUE;
CPU.Flags |= NMI_FLAG;
Timings.NMITriggerPos = 6 + 6;
}
@ -552,11 +528,13 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1
S9xStartScreenRefresh();
CPU.NextEvent = -1;
S9xReschedule();
break;
case HC_HDMA_INIT_EVENT:
S9xCheckMissingHTimerPosition(Timings.HDMAInit);
S9xReschedule();
if (CPU.V_Counter == 0)
@ -573,6 +551,7 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight)
RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE));
S9xCheckMissingHTimerPosition(Timings.RenderPos);
S9xReschedule();
break;
@ -582,11 +561,28 @@ void S9xDoHEventProcessing (void)
S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles);
#endif
S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES);
CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos);
S9xReschedule();
break;
case HC_IRQ_1_3_EVENT:
case HC_IRQ_3_5_EVENT:
case HC_IRQ_5_7_EVENT:
case HC_IRQ_7_9_EVENT:
case HC_IRQ_9_A_EVENT:
case HC_IRQ_A_1_EVENT:
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
S9xSetIRQ(PPU_IRQ_SOURCE);
else
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
S9xSetIRQ(PPU_IRQ_SOURCE);
S9xReschedule();
break;
}
#ifdef DEBUGGER
@ -595,3 +591,4 @@ void S9xDoHEventProcessing (void)
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
#endif
}

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -194,9 +179,6 @@
#define _CPUEXEC_H_
#include "ppu.h"
#ifdef DEBUGGER
#include "debug.h"
#endif
struct SOpcodes
{
@ -211,6 +193,7 @@ struct SICPU
uint8 _Zero;
uint8 _Negative;
uint8 _Overflow;
bool8 CPUExecuting;
uint32 ShiftedPB;
uint32 ShiftedDB;
uint32 Frame;
@ -234,6 +217,8 @@ void S9xMainLoop (void);
void S9xReset (void);
void S9xSoftReset (void);
void S9xDoHEventProcessing (void);
void S9xClearIRQ (uint32);
void S9xSetIRQ (uint32);
static inline void S9xUnpackStatus (void)
{
@ -285,4 +270,84 @@ static inline void S9xFixCycles (void)
}
}
static inline void S9xReschedule (void)
{
uint8 next = 0;
int32 hpos = 0;
switch (CPU.WhichEvent)
{
case HC_HBLANK_START_EVENT:
case HC_IRQ_1_3_EVENT:
next = HC_HDMA_START_EVENT;
hpos = Timings.HDMAStart;
break;
case HC_HDMA_START_EVENT:
case HC_IRQ_3_5_EVENT:
next = HC_HCOUNTER_MAX_EVENT;
hpos = Timings.H_Max;
break;
case HC_HCOUNTER_MAX_EVENT:
case HC_IRQ_5_7_EVENT:
next = HC_HDMA_INIT_EVENT;
hpos = Timings.HDMAInit;
break;
case HC_HDMA_INIT_EVENT:
case HC_IRQ_7_9_EVENT:
next = HC_RENDER_EVENT;
hpos = Timings.RenderPos;
break;
case HC_RENDER_EVENT:
case HC_IRQ_9_A_EVENT:
next = HC_WRAM_REFRESH_EVENT;
hpos = Timings.WRAMRefreshPos;
break;
case HC_WRAM_REFRESH_EVENT:
case HC_IRQ_A_1_EVENT:
next = HC_HBLANK_START_EVENT;
hpos = Timings.HBlankStart;
break;
}
if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos))
{
hpos = (int32) PPU.HTimerPosition;
switch (next)
{
case HC_HDMA_START_EVENT:
next = HC_IRQ_1_3_EVENT;
break;
case HC_HCOUNTER_MAX_EVENT:
next = HC_IRQ_3_5_EVENT;
break;
case HC_HDMA_INIT_EVENT:
next = HC_IRQ_5_7_EVENT;
break;
case HC_RENDER_EVENT:
next = HC_IRQ_7_9_EVENT;
break;
case HC_WRAM_REFRESH_EVENT:
next = HC_IRQ_9_A_EVENT;
break;
case HC_HBLANK_START_EVENT:
next = HC_IRQ_A_1_EVENT;
break;
}
}
CPU.NextEvent = hpos;
CPU.WhichEvent = next;
}
#endif

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -295,6 +280,7 @@ static void Op##OP (void) \
S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \
else \
Registers.PCw = newPC.W; \
CPUShutdown(); \
} \
}
@ -529,6 +515,9 @@ static inline void CPY (uint8 val)
static inline void DEC16 (uint32 OpAddress, s9xwrap_t w)
{
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
uint16 Work16 = S9xGetWord(OpAddress, w) - 1;
AddCycles(ONE_CYCLE);
S9xSetWord(Work16, OpAddress, w, WRITE_10);
@ -538,6 +527,9 @@ static inline void DEC16 (uint32 OpAddress, s9xwrap_t w)
static inline void DEC8 (uint32 OpAddress)
{
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
uint8 Work8 = S9xGetByte(OpAddress) - 1;
AddCycles(ONE_CYCLE);
S9xSetByte(Work8, OpAddress);
@ -559,6 +551,9 @@ static inline void EOR (uint8 val)
static inline void INC16 (uint32 OpAddress, s9xwrap_t w)
{
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
uint16 Work16 = S9xGetWord(OpAddress, w) + 1;
AddCycles(ONE_CYCLE);
S9xSetWord(Work16, OpAddress, w, WRITE_10);
@ -568,6 +563,9 @@ static inline void INC16 (uint32 OpAddress, s9xwrap_t w)
static inline void INC8 (uint32 OpAddress)
{
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
uint8 Work8 = S9xGetByte(OpAddress) + 1;
AddCycles(ONE_CYCLE);
S9xSetByte(Work8, OpAddress);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -203,9 +188,13 @@
#endif
#ifdef SA1_OPCODES
#define AddCycles(n) { SA1.Cycles += (n); }
#define AddCycles(n) { }
#else
#if (S9X_ACCURACY_LEVEL >= 3)
#define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
#else
#define AddCycles(n) { CPU.Cycles += (n); }
#endif
#endif
#include "cpuaddr.h"
@ -670,6 +659,9 @@ rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY)
static void Op3AM1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.AL--;
SetZN(Registers.AL);
}
@ -677,6 +669,9 @@ static void Op3AM1 (void)
static void Op3AM0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.A.W--;
SetZN(Registers.A.W);
}
@ -684,6 +679,9 @@ static void Op3AM0 (void)
static void Op3ASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckMemory())
{
@ -815,6 +813,9 @@ rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR)
static void Op1AM1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.AL++;
SetZN(Registers.AL);
}
@ -822,6 +823,9 @@ static void Op1AM1 (void)
static void Op1AM0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.A.W++;
SetZN(Registers.A.W);
}
@ -829,6 +833,9 @@ static void Op1AM0 (void)
static void Op1ASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckMemory())
{
@ -1543,6 +1550,54 @@ mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB)
/* Branch Instructions ***************************************************** */
#ifdef CPU_SHUTDOWN
#ifndef SA1_OPCODES
inline void CPUShutdown (void)
{
if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress)
{
// Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt.
if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG)))
{
CPU.WaitAddress = 0xffffffff;
if (Settings.SA1)
S9xSA1ExecuteDuringSleep();
CPU.Cycles = CPU.NextEvent;
ICPU.CPUExecuting = FALSE;
S9xAPUExecute();
ICPU.CPUExecuting = TRUE;
}
else
if (CPU.WaitCounter >= 2)
CPU.WaitCounter = 1;
else
CPU.WaitCounter--;
}
}
#else
inline void CPUShutdown (void)
{
if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress)
{
if (CPU.WaitCounter >= 1)
SA1.Executing = FALSE;
else
CPU.WaitCounter++;
}
}
#endif
#else
#define CPUShutdown()
#endif
// BCC
bOP(90E0, Relative, !CheckCarry(), 0, 0)
bOP(90E1, Relative, !CheckCarry(), 0, 1)
@ -1635,25 +1690,16 @@ static void OpF8 (void)
// CLI
static void Op58 (void)
{
AddCycles(ONE_CYCLE);
#ifndef SA1_OPCODES
Timings.IRQFlagChanging = IRQ_CLEAR_FLAG;
#else
ClearIRQ();
#endif
AddCycles(ONE_CYCLE);
//CHECK_FOR_IRQ();
}
// SEI
static void Op78 (void)
{
AddCycles(ONE_CYCLE);
#ifndef SA1_OPCODES
Timings.IRQFlagChanging = IRQ_SET_FLAG;
#else
SetIRQ();
#endif
AddCycles(ONE_CYCLE);
}
// CLV
@ -1668,6 +1714,9 @@ static void OpB8 (void)
static void OpCAX1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.XL--;
SetZN(Registers.XL);
}
@ -1675,6 +1724,9 @@ static void OpCAX1 (void)
static void OpCAX0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.X.W--;
SetZN(Registers.X.W);
}
@ -1682,6 +1734,9 @@ static void OpCAX0 (void)
static void OpCASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1698,6 +1753,9 @@ static void OpCASlow (void)
static void Op88X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.YL--;
SetZN(Registers.YL);
}
@ -1705,6 +1763,9 @@ static void Op88X1 (void)
static void Op88X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.Y.W--;
SetZN(Registers.Y.W);
}
@ -1712,6 +1773,9 @@ static void Op88X0 (void)
static void Op88Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1730,6 +1794,9 @@ static void Op88Slow (void)
static void OpE8X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.XL++;
SetZN(Registers.XL);
}
@ -1737,6 +1804,9 @@ static void OpE8X1 (void)
static void OpE8X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.X.W++;
SetZN(Registers.X.W);
}
@ -1744,6 +1814,9 @@ static void OpE8X0 (void)
static void OpE8Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1760,6 +1833,9 @@ static void OpE8Slow (void)
static void OpC8X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.YL++;
SetZN(Registers.YL);
}
@ -1767,6 +1843,9 @@ static void OpC8X1 (void)
static void OpC8X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.Y.W++;
SetZN(Registers.Y.W);
}
@ -1774,15 +1853,18 @@ static void OpC8X0 (void)
static void OpC8Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
Registers.YL++;
Registers.YL--;
SetZN(Registers.YL);
}
else
{
Registers.Y.W++;
Registers.Y.W--;
SetZN(Registers.Y.W);
}
}
@ -2289,7 +2371,7 @@ static void Op28E1 (void)
SetFlags(MemoryFlag | IndexFlag);
S9xUnpackStatus();
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
static void Op28E0 (void)
@ -2306,7 +2388,7 @@ static void Op28E0 (void)
}
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
static void Op28Slow (void)
@ -2334,7 +2416,7 @@ static void Op28Slow (void)
}
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
// PLX
@ -2903,7 +2985,7 @@ void S9xOpcode_NMI (void)
AddCycles(2 * SLOW_ONE_CYCLE);
S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8));
#else
if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10))
if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20))
{
OpenBus = Memory.FillRAM[0x220d];
AddCycles(2 * SLOW_ONE_CYCLE);
@ -2987,11 +3069,17 @@ static void Op5CSlow (void)
static void Op4C (void)
{
S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP)));
#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES)
CPUShutdown();
#endif
}
static void Op4CSlow (void)
{
S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP)));
#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES)
CPUShutdown();
#endif
}
static void Op6C (void)
@ -3337,7 +3425,7 @@ static void OpC2 (void)
}
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
static void OpC2Slow (void)
@ -3366,7 +3454,7 @@ static void OpC2Slow (void)
}
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
static void OpE2 (void)
@ -3474,7 +3562,7 @@ static void Op40Slow (void)
}
S9xFixCycles();
CHECK_FOR_IRQ();
//CHECK_FOR_IRQ();
}
/* STP/WAI ***************************************************************** */
@ -3482,16 +3570,44 @@ static void Op40Slow (void)
// WAI
static void OpCB (void)
{
// Ok, let's just C-ify the ASM versions separately.
#ifdef SA1_OPCODES
SA1.WaitingForInterrupt = TRUE;
Registers.PCw--;
AddCycles(TWO_CYCLES);
#else
CPU.WaitingForInterrupt = TRUE;
Registers.PCw--;
AddCycles(ONE_CYCLE);
#if 0
// XXX: FIXME
if (Settings.Shutdown)
{
SA1.Cycles = SA1.NextEvent;
SA1.Executing = FALSE;
//S9xAPUExecute(); // FIXME
SA1.Executing = TRUE;
}
#endif
#else // SA1_OPCODES
#if 0
if (CPU.IRQActive)
AddCycles(TWO_CYCLES);
else
#endif
{
CPU.WaitingForInterrupt = TRUE;
Registers.PCw--;
#ifdef CPU_SHUTDOWN
if (Settings.Shutdown)
{
CPU.Cycles = CPU.NextEvent;
ICPU.CPUExecuting = FALSE;
S9xAPUExecute();
ICPU.CPUExecuting = TRUE;
}
else
AddCycles(TWO_CYCLES);
#else
AddCycles(TWO_CYCLES);
#endif
}
#endif // SA1_OPCODES
}
// STP
@ -3534,7 +3650,7 @@ static void Op42 (void)
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf);
if (trace != NULL)
fclose(trace);
ENSURE_TRACE_OPEN(trace, "WDMtrace.log", "ab")
trace = fopen("WDMtrace.log", "ab");
}
break;
@ -3908,3 +4024,4 @@ struct SOpcodes S9xOpcodesSlow[256] =
{ OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow },
{ OpFFSlow }
};

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -196,9 +181,8 @@
void S9xOpcode_NMI (void);
void S9xOpcode_IRQ (void);
#ifndef SA1_OPCODES
#define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); }
#else
#define CHECK_FOR_IRQ() {}
#endif
#define CHECK_FOR_IRQ() \
if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \
S9xOpcode_IRQ()
#endif

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -214,7 +199,6 @@ const char * S9xGetCrosshair (int idx);
// Superscope: 2 White Black
// Justifier 1: 4 Blue Black
// Justifier 2: 4 MagicPink Black
// Macs Rifle: 2 White Black
//
// Available colors are: Trans, Black, 25Grey, 50Grey, 75Grey, White, Red, Orange,
// Yellow, Green, Cyan, Sky, Blue, Violet, MagicPink, and Purple.
@ -227,8 +211,7 @@ enum crosscontrols
X_MOUSE2,
X_SUPERSCOPE,
X_JUSTIFIER1,
X_JUSTIFIER2,
X_MACSRIFLE
X_JUSTIFIER2
};
void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -193,8 +178,6 @@
#ifndef _DISPLAY_H_
#define _DISPLAY_H_
#include "snes9x.h"
enum s9x_getdirtype
{
DEFAULT_DIR = 0,
@ -206,16 +189,14 @@ enum s9x_getdirtype
SCREENSHOT_DIR,
SPC_DIR,
CHEAT_DIR,
PATCH_DIR,
IPS_DIR,
BIOS_DIR,
LOG_DIR,
SAT_DIR,
LAST_DIR
};
void S9xUsage (void);
char * S9xParseArgs (char **, int);
void S9xParseArgsForCheats (char **, int);
void S9xLoadConfigFiles (char **, int);
void S9xSetInfoString (const char *);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -200,7 +185,7 @@
#include "missing.h"
#endif
#define ADD_CYCLES(n) { CPU.Cycles += (n); }
#define ADD_CYCLES(n) CPU.Cycles += (n)
extern uint8 *HDMAMemPointers[8];
extern int HDMA_ModeByteCounts[8];
@ -613,7 +598,7 @@ bool8 S9xDoDMA (uint8 Channel)
S9xSetPPU(Work, 0x2100 + d->BAddress);
UPDATE_COUNTERS;
count--;
// Fall through
case 1:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -648,7 +633,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 1;
break;
}
// Fall through
case 1:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2100 + d->BAddress);
@ -658,7 +643,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 2;
break;
}
// Fall through
case 2:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -668,7 +653,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 3;
break;
}
// Fall through
case 3:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -697,7 +682,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 1;
break;
}
// Fall through
case 1:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -707,7 +692,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 2;
break;
}
// Fall through
case 2:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2102 + d->BAddress);
@ -717,7 +702,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 3;
break;
}
// Fall through
case 3:
Work = S9xGetByte((d->ABank << 16) + p);
S9xSetPPU(Work, 0x2103 + d->BAddress);
@ -756,6 +741,9 @@ bool8 S9xDoDMA (uint8 Channel)
break;
case 0x18: // VMDATAL
#ifndef CORRECT_VRAM_READS
IPPU.FirstVRAMRead = TRUE;
#endif
if (!PPU.VMA.FullGraphicCount)
{
do
@ -778,6 +766,9 @@ bool8 S9xDoDMA (uint8 Channel)
break;
case 0x19: // VMDATAH
#ifndef CORRECT_VRAM_READS
IPPU.FirstVRAMRead = TRUE;
#endif
if (!PPU.VMA.FullGraphicCount)
{
do
@ -846,6 +837,9 @@ bool8 S9xDoDMA (uint8 Channel)
if (d->BAddress == 0x18)
{
// VMDATAL
#ifndef CORRECT_VRAM_READS
IPPU.FirstVRAMRead = TRUE;
#endif
if (!PPU.VMA.FullGraphicCount)
{
switch (b)
@ -857,10 +851,10 @@ bool8 S9xDoDMA (uint8 Channel)
REGISTER_2118_linear(Work);
UPDATE_COUNTERS;
count--;
// Fall through
case 1:
OpenBus = *(base + p);
REGISTER_2119_linear(OpenBus);
Work = *(base + p);
REGISTER_2119_linear(Work);
UPDATE_COUNTERS;
count--;
}
@ -887,7 +881,7 @@ bool8 S9xDoDMA (uint8 Channel)
REGISTER_2118_tile(Work);
UPDATE_COUNTERS;
count--;
// Fall through
case 1:
Work = *(base + p);
REGISTER_2119_tile(Work);
@ -919,7 +913,7 @@ bool8 S9xDoDMA (uint8 Channel)
S9xSetPPU(Work, 0x2100 + d->BAddress);
UPDATE_COUNTERS;
count--;
// Fall through
case 1:
Work = *(base + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -955,7 +949,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 1;
break;
}
// Fall through
case 1:
Work = *(base + p);
S9xSetPPU(Work, 0x2100 + d->BAddress);
@ -965,7 +959,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 2;
break;
}
// Fall through
case 2:
Work = *(base + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -975,7 +969,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 3;
break;
}
// Fall through
case 3:
Work = *(base + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -1004,7 +998,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 1;
break;
}
// Fall through
case 1:
Work = *(base + p);
S9xSetPPU(Work, 0x2101 + d->BAddress);
@ -1014,7 +1008,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 2;
break;
}
// Fall through
case 2:
Work = *(base + p);
S9xSetPPU(Work, 0x2102 + d->BAddress);
@ -1024,7 +1018,7 @@ bool8 S9xDoDMA (uint8 Channel)
b = 3;
break;
}
// Fall through
case 3:
Work = *(base + p);
S9xSetPPU(Work, 0x2103 + d->BAddress);
@ -1288,9 +1282,11 @@ bool8 S9xDoDMA (uint8 Channel)
}
}
if (CPU.NMIPending && (Timings.NMITriggerPos != 0xffff))
if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff))
{
Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay;
if (Timings.NMITriggerPos >= Timings.H_Max)
Timings.NMITriggerPos -= Timings.H_Max;
}
// Release the memory used in SPC7110 DMA
@ -1377,7 +1373,10 @@ static inline bool8 HDMAReadLineCount (int d)
void S9xStartHDMA (void)
{
PPU.HDMA = Memory.FillRAM[0x420c];
if (Settings.DisableHDMA)
PPU.HDMA = 0;
else
PPU.HDMA = Memory.FillRAM[0x420c];
#ifdef DEBUGGER
missing.hdma_this_frame = PPU.HDMA;
@ -1421,14 +1420,13 @@ void S9xStartHDMA (void)
uint8 S9xDoHDMA (uint8 byte)
{
struct SDMA *p;
struct SDMA *p = &DMA[0];
uint32 ShiftedIBank;
uint16 IAddr;
bool8 temp;
int32 tmpch;
int d;
uint8 mask;
int d = 0;
CPU.InHDMA = TRUE;
CPU.InDMAorHDMA = TRUE;
@ -1439,7 +1437,7 @@ uint8 S9xDoHDMA (uint8 byte)
// XXX: Not quite right...
ADD_CYCLES(Timings.DMACPUSync);
for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, p++, d++)
for (uint8 mask = 1; mask; mask <<= 1, p++, d++)
{
if (byte & mask)
{
@ -1641,10 +1639,7 @@ uint8 S9xDoHDMA (uint8 byte)
case 1:
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
// XXX: All HDMA should read to MDR first. This one just
// happens to fix Speedy Gonzales.
OpenBus = *(HDMAMemPointers[d] + 1);
S9xSetPPU(OpenBus, 0x2101 + p->BAddress);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 2;
break;
@ -1757,16 +1752,7 @@ uint8 S9xDoHDMA (uint8 byte)
#undef DOBYTE
}
}
}
}
for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, p++, d++)
{
if (byte & mask)
{
if (p->DoTransfer)
{
if (p->HDMAIndirectAddressing)
p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
else
@ -1782,6 +1768,7 @@ uint8 S9xDoHDMA (uint8 byte)
byte &= ~mask;
PPU.HDMAEnded |= mask;
p->DoTransfer = FALSE;
continue;
}
}
else

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -214,10 +199,10 @@ void S9xInitSuperFX (void)
void S9xResetSuperFX (void)
{
// FIXME: Snes9x can't execute CPU and SuperFX at a time. Don't ask me what is 0.417 :P
SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
//SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
SuperFX.speedPerLine = (uint32) (Settings.SuperFXSpeedPerLine * ((1.0f / Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
SuperFX.oneLineDone = FALSE;
SuperFX.vFlags = 0;
CPU.IRQExternal = FALSE;
FxReset(&SuperFX);
}
@ -315,10 +300,13 @@ uint8 S9xGetSuperFX (uint16 address)
uint8 byte;
byte = Memory.FillRAM[address];
#ifdef CPU_SHUTDOWN
if (address == 0x3030)
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif
if (address == 0x3031)
{
CPU.IRQExternal = FALSE;
S9xClearIRQ(GSU_IRQ_SOURCE);
Memory.FillRAM[0x3031] = byte & 0x7f;
}
@ -329,11 +317,11 @@ void S9xSuperFXExec (void)
{
if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18)
{
FxEmulate(((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine) * Settings.SuperFXClockMultiplier / 100);
FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine);
uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8);
if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ)
CPU.IRQExternal = TRUE;
S9xSetIRQ(GSU_IRQ_SOURCE);
}
}

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -203,6 +188,8 @@
#include "bsx.h"
#include "msu1.h"
#if (S9X_ACCURACY_LEVEL >= 2)
#define addCyclesInMemoryAccess \
if (!CPU.InDMAorHDMA) \
{ \
@ -219,6 +206,18 @@
S9xDoHEventProcessing(); \
}
#else
#define addCyclesInMemoryAccess \
if (!CPU.InDMAorHDMA) \
CPU.Cycles += speed;
#define addCyclesInMemoryAccess_x2 \
if (!CPU.InDMAorHDMA) \
CPU.Cycles += speed << 1;
#endif
extern uint8 OpenBus;
static inline int32 memory_speed (uint32 address)
@ -249,6 +248,10 @@ inline uint8 S9xGetByte (uint32 Address)
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
#ifdef CPU_SHUTDOWN
if (Memory.BlockIsRAM[block])
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif
byte = *(GetAddress + (Address & 0xffff));
addCyclesInMemoryAccess;
return (byte);
@ -345,39 +348,42 @@ inline uint8 S9xGetByte (uint32 Address)
inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
{
uint16 word;
uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
if ((Address & mask) == mask)
{
PC_t a;
word = OpenBus = S9xGetByte(Address);
OpenBus = S9xGetByte(Address);
switch (w)
{
case WRAP_PAGE:
a.xPBPC = Address;
a.B.xPCl++;
return (word | (S9xGetByte(a.xPBPC) << 8));
return (OpenBus | (S9xGetByte(a.xPBPC) << 8));
case WRAP_BANK:
a.xPBPC = Address;
a.W.xPC++;
return (word | (S9xGetByte(a.xPBPC) << 8));
return (OpenBus | (S9xGetByte(a.xPBPC) << 8));
case WRAP_NONE:
default:
return (word | (S9xGetByte(Address + 1) << 8));
return (OpenBus | (S9xGetByte(Address + 1) << 8));
}
}
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
int32 speed = memory_speed(Address);
uint16 word;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
#ifdef CPU_SHUTDOWN
if (Memory.BlockIsRAM[block])
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif
word = READ_WORD(GetAddress + (Address & 0xffff));
addCyclesInMemoryAccess_x2;
return (word);
@ -395,8 +401,8 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA)
{
word = OpenBus = S9xGetByte(Address);
return (word | (S9xGetByte(Address + 1) << 8));
OpenBus = S9xGetByte(Address);
return (OpenBus | (S9xGetByte(Address + 1) << 8));
}
word = S9xGetPPU(Address & 0xffff);
@ -505,14 +511,33 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
inline void S9xSetByte (uint8 Byte, uint32 Address)
{
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.WriteMap[block];
int32 speed = memory_speed(Address);
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{
#ifdef CPU_SHUTDOWN
SetAddress += (Address & 0xffff);
*SetAddress = Byte;
addCyclesInMemoryAccess;
if (Settings.SA1)
{
if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2)
{
SA1.Executing = SA1.S9xOpcodes != NULL;
SA1.WaitCounter = 0;
}
}
#else
*(SetAddress + (Address & 0xffff)) = Byte;
addCyclesInMemoryAccess;
#endif
return;
}
@ -569,6 +594,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
case CMemory::MAP_SA1RAM:
*(Memory.SRAM + (Address & 0xffff)) = Byte;
SA1.Executing = !SA1.Waiting;
addCyclesInMemoryAccess;
return;
@ -645,14 +671,33 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
return;
}
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.WriteMap[block];
int32 speed = memory_speed(Address);
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{
#ifdef CPU_SHUTDOWN
SetAddress += (Address & 0xffff);
WRITE_WORD(SetAddress, Word);
addCyclesInMemoryAccess_x2;
if (Settings.SA1)
{
if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2)
{
SA1.Executing = SA1.S9xOpcodes != NULL;
SA1.WaitCounter = 0;
}
}
#else
WRITE_WORD(SetAddress + (Address & 0xffff), Word);
addCyclesInMemoryAccess_x2;
#endif
return;
}
@ -762,6 +807,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
case CMemory::MAP_SA1RAM:
WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word);
SA1.Executing = !SA1.Waiting;
addCyclesInMemoryAccess_x2;
return;

View File

@ -453,7 +453,7 @@ void S9xEndScreenRefresh (void)
else
S9xControlEOF();
S9xUpdateCheatsInMemory ();
S9xApplyCheats();
#ifdef DEBUGGER
if (CPU.Flags & FRAME_ADVANCE_FLAG)
@ -2159,22 +2159,6 @@ static void DisplayPressedKeys (void)
break;
}
case CTL_MACSRIFLE:
{
/*
uint8 buf[6], *p = buf;
MovieGetScope(port, buf);
int16 x = READ_WORD(p);
int16 y = READ_WORD(p + 2);
uint8 buttons = buf[4];
sprintf(string, "#%d %d: (%03d,%03d) %c%c%c%c", port, ids[0], x, y,
(buttons & 0x80) ? 'F' : ' ', (buttons & 0x40) ? 'C' : ' ',
(buttons & 0x20) ? 'T' : ' ', (buttons & 0x10) ? 'P' : ' ');
S9xDisplayString(string, line++, 1, false);
*/
break;
}
case CTL_NONE:
{
sprintf(string, "#%d -", port);

File diff suppressed because it is too large Load Diff

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -276,7 +261,6 @@ struct CMemory
uint32 ROMChecksum;
uint32 ROMComplementChecksum;
uint32 ROMCRC32;
unsigned char ROMSHA256[32];
int32 ROMFramesPerSecond;
bool8 HiROM;
@ -294,24 +278,17 @@ struct CMemory
int ScoreHiROM (bool8, int32 romoff = 0);
int ScoreLoROM (bool8, int32 romoff = 0);
uint32 HeaderRemove (uint32, uint8 *);
uint32 FileLoader (uint8 *, const char *, uint32);
uint32 MemLoader (uint8 *, const char*, uint32);
bool8 LoadROMMem (const uint8 *, uint32);
uint32 HeaderRemove (uint32, int32 &, uint8 *);
uint32 FileLoader (uint8 *, const char *, int32);
bool8 LoadROM (const char *);
bool8 LoadROMInt (int32);
bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32);
bool8 LoadMultiCart (const char *, const char *);
bool8 LoadMultiCartInt ();
bool8 LoadSufamiTurbo ();
bool8 LoadBSCart ();
bool8 LoadGNEXT ();
bool8 LoadSufamiTurbo (const char *, const char *);
bool8 LoadSameGame (const char *, const char *);
bool8 LoadSRAM (const char *);
bool8 SaveSRAM (const char *);
void ClearSRAM (bool8 onlyNonSavedSRAM = 0);
bool8 LoadSRTC (void);
bool8 SaveSRTC (void);
bool8 SaveMPAK (const char *);
char * Safe (const char *);
char * SafeANK (const char *);
@ -347,12 +324,10 @@ struct CMemory
void Map_SetaDSPLoROMMap (void);
void Map_SDD1LoROMMap (void);
void Map_SA1LoROMMap (void);
void Map_BSSA1LoROMMap (void);
void Map_HiROMMap (void);
void Map_ExtendedHiROMMap (void);
void Map_SameGameHiROMMap (void);
void Map_SPC7110HiROMMap (void);
void Map_BSCartLoROMMap(uint8);
void Map_BSCartHiROMMap(void);
uint16 checksum_calc_sum (uint8 *, uint32);
uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000);
@ -391,7 +366,7 @@ extern CMemory Memory;
extern SMulti Multi;
void S9xAutoSaveSRAM (void);
bool8 LoadZip(const char *, uint32 *, uint8 *);
bool8 LoadZip(const char *, int32 *, int32 *, uint8 *);
enum s9xwrap_t
{

View File

@ -269,105 +269,189 @@ static inline void S9xTryGunLatch (bool force)
}
}
static int CyclesUntilNext (int hc, int vc)
void S9xCheckMissingHTimerPosition (int32 hc)
{
int32 total = 0;
int vpos = CPU.V_Counter;
if (vc - vpos > 0)
if (PPU.HTimerPosition == hc)
{
// It's still in this frame */
// Add number of lines
total += (vc - vpos) * Timings.H_Max_Master;
// If line 240 is in there and we're odd, subtract a dot
if (vpos <= 240 && vc > 240 && Timings.InterlaceField & !IPPU.Interlace)
total -= ONE_DOT_CYCLE;
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
S9xSetIRQ(PPU_IRQ_SOURCE);
else
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
S9xSetIRQ(PPU_IRQ_SOURCE);
}
else
{
if (vc == vpos && (hc > CPU.Cycles))
{
return hc;
}
total += (Timings.V_Max - vpos) * Timings.H_Max_Master;
if (vpos <= 240 && Timings.InterlaceField && !IPPU.Interlace)
total -= ONE_DOT_CYCLE;
total += (vc) * Timings.H_Max_Master;
if (vc > 240 && !Timings.InterlaceField && !IPPU.Interlace)
total -= ONE_DOT_CYCLE;
}
total += hc;
return total;
}
void S9xUpdateIRQPositions (bool initial)
void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range)
{
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
PPU.HTimerPosition -= PPU.IRQHBeamPos ? 0 : ONE_DOT_CYCLE;
PPU.HTimerPosition += PPU.IRQHBeamPos > 322 ? (ONE_DOT_CYCLE / 2) : 0;
PPU.HTimerPosition += PPU.IRQHBeamPos > 326 ? (ONE_DOT_CYCLE / 2) : 0;
if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range)))
{
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
CPU.IRQPending = 1;
else
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
CPU.IRQPending = 1;
}
}
void S9xCheckMissingHTimerRange (int32 hc_from, int32 range)
{
if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range)))
{
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
S9xSetIRQ(PPU_IRQ_SOURCE);
else
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
S9xSetIRQ(PPU_IRQ_SOURCE);
}
}
void S9xUpdateHVTimerPosition (void)
{
if (PPU.HTimerEnabled)
{
#ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
if (PPU.IRQHBeamPos != 0)
{
// IRQ_read
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE;
if (Timings.H_Max == Timings.H_Max_Master) // 1364
{
if (PPU.IRQHBeamPos > 322)
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
if (PPU.IRQHBeamPos > 326)
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
}
PPU.HTimerPosition += 14;
// /IRQ
PPU.HTimerPosition += 4;
// after CPU executing
PPU.HTimerPosition += 6;
}
else
PPU.HTimerPosition = 10 + 4 + 6;
}
else
PPU.HTimerPosition = 10 + 4 + 6;
PPU.VTimerPosition = PPU.IRQVBeamPos;
if (PPU.VTimerEnabled && (PPU.VTimerPosition >= (Timings.V_Max + (IPPU.Interlace ? 1 : 0))))
if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340))
{
Timings.NextIRQTimer = 0x0fffffff;
PPU.HTimerPosition -= Timings.H_Max;
PPU.VTimerPosition++;
// FIXME
if (PPU.VTimerPosition >= Timings.V_Max)
PPU.VTimerPosition = 0;
}
else if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
{
Timings.NextIRQTimer = 0x0fffffff;
}
else if (PPU.HTimerEnabled && !PPU.VTimerEnabled)
{
int v_pos = CPU.V_Counter;
Timings.NextIRQTimer = PPU.HTimerPosition;
if (CPU.Cycles > Timings.NextIRQTimer - Timings.IRQTriggerCycles)
if (PPU.HTimerPosition < CPU.Cycles)
{
switch (CPU.WhichEvent)
{
Timings.NextIRQTimer += Timings.H_Max;
v_pos++;
}
case HC_IRQ_1_3_EVENT:
CPU.WhichEvent = HC_HDMA_START_EVENT;
CPU.NextEvent = Timings.HDMAStart;
break;
// Check for short dot scanline
if (v_pos == 240 && Timings.InterlaceField && !IPPU.Interlace)
{
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
case HC_IRQ_3_5_EVENT:
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
CPU.NextEvent = Timings.H_Max;
break;
case HC_IRQ_5_7_EVENT:
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
CPU.NextEvent = Timings.HDMAInit;
break;
case HC_IRQ_7_9_EVENT:
CPU.WhichEvent = HC_RENDER_EVENT;
CPU.NextEvent = Timings.RenderPos;
break;
case HC_IRQ_9_A_EVENT:
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
CPU.NextEvent = Timings.WRAMRefreshPos;
break;
case HC_IRQ_A_1_EVENT:
CPU.WhichEvent = HC_HBLANK_START_EVENT;
CPU.NextEvent = Timings.HBlankStart;
break;
}
}
else if (!PPU.HTimerEnabled && PPU.VTimerEnabled)
else
if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent)))
{
if (CPU.V_Counter == PPU.VTimerPosition && initial)
Timings.NextIRQTimer = CPU.Cycles + Timings.IRQTriggerCycles;
else
Timings.NextIRQTimer = CyclesUntilNext (Timings.IRQTriggerCycles, PPU.VTimerPosition);
CPU.NextEvent = PPU.HTimerPosition;
switch (CPU.WhichEvent)
{
case HC_HDMA_START_EVENT:
CPU.WhichEvent = HC_IRQ_1_3_EVENT;
break;
case HC_HCOUNTER_MAX_EVENT:
CPU.WhichEvent = HC_IRQ_3_5_EVENT;
break;
case HC_HDMA_INIT_EVENT:
CPU.WhichEvent = HC_IRQ_5_7_EVENT;
break;
case HC_RENDER_EVENT:
CPU.WhichEvent = HC_IRQ_7_9_EVENT;
break;
case HC_WRAM_REFRESH_EVENT:
CPU.WhichEvent = HC_IRQ_9_A_EVENT;
break;
case HC_HBLANK_START_EVENT:
CPU.WhichEvent = HC_IRQ_A_1_EVENT;
break;
}
}
else
{
Timings.NextIRQTimer = CyclesUntilNext (PPU.HTimerPosition, PPU.VTimerPosition);
// Check for short dot scanline
int field = Timings.InterlaceField;
if (PPU.VTimerPosition < CPU.V_Counter ||
(PPU.VTimerPosition == CPU.V_Counter && Timings.NextIRQTimer > Timings.H_Max))
switch (CPU.WhichEvent)
{
field = !field;
}
case HC_IRQ_1_3_EVENT:
CPU.WhichEvent = HC_HDMA_START_EVENT;
CPU.NextEvent = Timings.HDMAStart;
break;
if (PPU.VTimerPosition == 240 && field && !IPPU.Interlace)
{
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
case HC_IRQ_3_5_EVENT:
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
CPU.NextEvent = Timings.H_Max;
break;
case HC_IRQ_5_7_EVENT:
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
CPU.NextEvent = Timings.HDMAInit;
break;
case HC_IRQ_7_9_EVENT:
CPU.WhichEvent = HC_RENDER_EVENT;
CPU.NextEvent = Timings.RenderPos;
break;
case HC_IRQ_9_A_EVENT:
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
CPU.NextEvent = Timings.WRAMRefreshPos;
break;
case HC_IRQ_A_1_EVENT:
CPU.WhichEvent = HC_HBLANK_START_EVENT;
CPU.NextEvent = Timings.HBlankStart;
break;
}
}
#ifdef DEBUGGER
S9xTraceFormattedMessage("--- IRQ Timer HC:%d VC:%d set %d cycles HTimer:%d Pos:%04d->%04d VTimer:%d Pos:%03d->%03d", CPU.Cycles, CPU.V_Counter,
Timings.NextIRQTimer, PPU.HTimerEnabled, PPU.IRQHBeamPos, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.IRQVBeamPos, PPU.VTimerPosition);
S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition);
#endif
}
@ -485,7 +569,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
case 0x2102: // OAMADDL
PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
PPU.OAMFlip = 0;
PPU.OAMFlip = 2;
PPU.OAMReadFlip = 0;
PPU.SavedOAMAddr = PPU.OAMAddr;
if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
@ -715,7 +799,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
case 0x2116: // VMADDL
PPU.VMA.Address &= 0xff00;
PPU.VMA.Address |= Byte;
#ifdef CORRECT_VRAM_READS
if (PPU.VMA.FullGraphicCount)
{
uint32 addr = PPU.VMA.Address;
@ -725,13 +809,15 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
}
else
IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
#else
IPPU.FirstVRAMRead = TRUE;
#endif
break;
case 0x2117: // VMADDH
PPU.VMA.Address &= 0x00ff;
PPU.VMA.Address |= Byte << 8;
#ifdef CORRECT_VRAM_READS
if (PPU.VMA.FullGraphicCount)
{
uint32 addr = PPU.VMA.Address;
@ -741,14 +827,22 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
}
else
IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
#else
IPPU.FirstVRAMRead = TRUE;
#endif
break;
case 0x2118: // VMDATAL
#ifndef CORRECT_VRAM_READS
IPPU.FirstVRAMRead = TRUE;
#endif
REGISTER_2118(Byte);
break;
case 0x2119: // VMDATAH
#ifndef CORRECT_VRAM_READS
IPPU.FirstVRAMRead = TRUE;
#endif
REGISTER_2119(Byte);
break;
@ -1184,6 +1278,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
uint8 S9xGetPPU (uint16 Address)
{
// MAP_PPU: $2000-$3FFF
if (Settings.MSU1 && (Address & 0xfff8) == 0x2000)
return (S9xMSU1ReadPort(Address & 7));
else
@ -1261,7 +1356,7 @@ uint8 S9xGetPPU (uint16 Address)
case 0x2137: // SLHV
S9xLatchCounters(0);
return (PPU.OpenBus1);
return (OpenBus);
case 0x2138: // OAMDATAREAD
if (PPU.OAMAddr & 0x100)
@ -1308,6 +1403,7 @@ uint8 S9xGetPPU (uint16 Address)
return (PPU.OpenBus1 = byte);
case 0x2139: // VMDATALREAD
#ifdef CORRECT_VRAM_READS
byte = IPPU.VRAMReadBuffer & 0xff;
if (!PPU.VMA.High)
{
@ -1323,13 +1419,33 @@ uint8 S9xGetPPU (uint16 Address)
PPU.VMA.Address += PPU.VMA.Increment;
}
#else
if (IPPU.FirstVRAMRead)
byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff];
else
if (PPU.VMA.FullGraphicCount)
{
uint32 addr = PPU.VMA.Address - 1;
uint32 rem = addr & PPU.VMA.Mask1;
uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
byte = Memory.VRAM[((address << 1) - 2) & 0xffff];
}
else
byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff];
if (!PPU.VMA.High)
{
PPU.VMA.Address += PPU.VMA.Increment;
IPPU.FirstVRAMRead = FALSE;
}
#endif
#ifdef DEBUGGER
missing.vram_read = 1;
#endif
return (PPU.OpenBus1 = byte);
case 0x213a: // VMDATAHREAD
#ifdef CORRECT_VRAM_READS
byte = (IPPU.VRAMReadBuffer >> 8) & 0xff;
if (PPU.VMA.High)
{
@ -1345,6 +1461,26 @@ uint8 S9xGetPPU (uint16 Address)
PPU.VMA.Address += PPU.VMA.Increment;
}
#else
if (IPPU.FirstVRAMRead)
byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff];
else
if (PPU.VMA.FullGraphicCount)
{
uint32 addr = PPU.VMA.Address - 1;
uint32 rem = addr & PPU.VMA.Mask1;
uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
byte = Memory.VRAM[((address << 1) - 1) & 0xffff];
}
else
byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xffff];
if (PPU.VMA.High)
{
PPU.VMA.Address += PPU.VMA.Increment;
IPPU.FirstVRAMRead = FALSE;
}
#endif
#ifdef DEBUGGER
missing.vram_read = 1;
#endif
@ -1560,22 +1696,13 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
switch (Address)
{
case 0x4200: // NMITIMEN
#ifdef DEBUGGER
if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("Write to 0x4200. Byte is %2x was %2x\n", Byte, Memory.FillRAM[Address]);
#endif
if (Byte == Memory.FillRAM[0x4200])
break;
if (Byte & 0x20)
{
PPU.VTimerEnabled = TRUE;
#ifdef DEBUGGER
#ifdef DEBUGGER
missing.virq = 1;
missing.virq_pos = PPU.IRQVBeamPos;
#endif
#endif
}
else
PPU.VTimerEnabled = FALSE;
@ -1583,22 +1710,22 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
if (Byte & 0x10)
{
PPU.HTimerEnabled = TRUE;
#ifdef DEBUGGER
#ifdef DEBUGGER
missing.hirq = 1;
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
#endif
}
else
PPU.HTimerEnabled = FALSE;
if (!(Byte & 0x10) && !(Byte & 0x20))
{
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
}
S9xUpdateHVTimerPosition();
S9xUpdateIRQPositions(true);
// The case that IRQ will trigger in an instruction such as STA $4200.
// FIXME: not true but good enough for Snes9x, I think.
S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles);
if (!(Byte & 0x30))
S9xClearIRQ(PPU_IRQ_SOURCE);
// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
@ -1606,20 +1733,10 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
{
// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
// then, when to call S9xOpcode_NMI()?
CPU.NMIPending = TRUE;
CPU.Flags |= NMI_FLAG;
Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
#ifdef DEBUGGER
if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("NMI Triggered on low-to-high occurring at next HC=%d\n", Timings.NMITriggerPos);
#endif
}
#ifdef DEBUGGER
S9xTraceFormattedMessage("--- IRQ Timer Enable HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
#endif
break;
case 0x4201: // WRIO
@ -1663,7 +1780,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
if (PPU.IRQHBeamPos != pos)
S9xUpdateIRQPositions(false);
S9xUpdateHVTimerPosition();
#ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
@ -1673,7 +1790,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
pos = PPU.IRQHBeamPos;
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQHBeamPos != pos)
S9xUpdateIRQPositions(false);
S9xUpdateHVTimerPosition();
#ifdef DEBUGGER
missing.hirq_pos = PPU.IRQHBeamPos;
#endif
@ -1683,7 +1800,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
if (PPU.IRQVBeamPos != pos)
S9xUpdateIRQPositions(true);
S9xUpdateHVTimerPosition();
#ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos;
#endif
@ -1693,7 +1810,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
pos = PPU.IRQVBeamPos;
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
if (PPU.IRQVBeamPos != pos)
S9xUpdateIRQPositions(true);
S9xUpdateHVTimerPosition();
#ifdef DEBUGGER
missing.virq_pos = PPU.IRQVBeamPos;
#endif
@ -1703,9 +1820,8 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
if (CPU.InDMAorHDMA)
return;
// XXX: Not quite right...
if (Byte) {
CPU.Cycles += Timings.DMACPUSync;
}
if (Byte)
CPU.Cycles += Timings.DMACPUSync;
if (Byte & 0x01)
S9xDoDMA(0);
if (Byte & 0x02)
@ -1731,6 +1847,8 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
case 0x420c: // HDMAEN
if (CPU.InDMAorHDMA)
return;
if (Settings.DisableHDMA)
Byte = 0;
Memory.FillRAM[0x420c] = Byte;
// Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
PPU.HDMA = Byte & ~PPU.HDMAEnded;
@ -1757,7 +1875,17 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
break;
case 0x4210: // RDNMI
#if 0
Memory.FillRAM[0x4210] = Model->_5A22;
#endif
return;
case 0x4211: // TIMEUP
#if 0
S9xClearIRQ(PPU_IRQ_SOURCE);
#endif
return;
case 0x4212: // HVBJOY
case 0x4213: // RDIO
case 0x4214: // RDDIVL
@ -1873,22 +2001,22 @@ uint8 S9xGetCPU (uint16 Address)
switch (Address)
{
case 0x4210: // RDNMI
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif
byte = Memory.FillRAM[0x4210];
Memory.FillRAM[0x4210] = Model->_5A22;
return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22);
case 0x4211: // TIMEUP
byte = 0;
if (CPU.IRQLine)
{
byte = 0x80;
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
}
byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0;
S9xClearIRQ(PPU_IRQ_SOURCE);
return (byte | (OpenBus & 0x7f));
case 0x4212: // HVBJOY
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif
return (REGISTER_4212() | (OpenBus & 0x3e));
case 0x4213: // RDIO
@ -1937,20 +2065,6 @@ void S9xResetPPU (void)
PPU.M7byte = 0;
}
void S9xResetPPUFast (void)
{
PPU.RecomputeClipWindows = TRUE;
IPPU.ColorsChanged = TRUE;
IPPU.OBJChanged = TRUE;
memset(IPPU.TileCached[TILE_2BIT], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT], 0, MAX_4BIT_TILES);
memset(IPPU.TileCached[TILE_8BIT], 0, MAX_8BIT_TILES);
memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_2BIT_ODD], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES);
}
void S9xSoftResetPPU (void)
{
S9xControlsSoftReset();
@ -2092,10 +2206,14 @@ void S9xSoftResetPPU (void)
memset(IPPU.TileCached[TILE_4BIT], 0, MAX_4BIT_TILES);
memset(IPPU.TileCached[TILE_8BIT], 0, MAX_8BIT_TILES);
memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_2BIT_ODD], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_2BIT_ODD], 0, MAX_2BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES);
memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES);
#ifdef CORRECT_VRAM_READS
IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
#else
IPPU.FirstVRAMRead = FALSE;
#endif
GFX.InterlaceFrame = 0;
IPPU.Interlace = FALSE;
IPPU.InterlaceOBJ = FALSE;

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -212,6 +197,11 @@
#define CLIP_XOR 2
#define CLIP_XNOR 3
#define PPU_IRQ_SOURCE (1 << 1)
#define GSU_IRQ_SOURCE (1 << 2)
#define SA1_IRQ_SOURCE (1 << 7)
#define SA1_DMA_IRQ_SOURCE (1 << 5)
struct ClipData
{
uint8 Count;
@ -227,7 +217,11 @@ struct InternalPPU
bool8 OBJChanged;
uint8 *TileCache[7];
uint8 *TileCached[7];
#ifdef CORRECT_VRAM_READS
uint16 VRAMReadBuffer;
#else
bool8 FirstVRAMRead;
#endif
bool8 Interlace;
bool8 InterlaceOBJ;
bool8 PseudoHires;
@ -384,13 +378,15 @@ extern struct SPPU PPU;
extern struct InternalPPU IPPU;
void S9xResetPPU (void);
void S9xResetPPUFast (void);
void S9xSoftResetPPU (void);
void S9xSetPPU (uint8, uint16);
uint8 S9xGetPPU (uint16);
void S9xSetCPU (uint8, uint16);
uint8 S9xGetCPU (uint16);
void S9xUpdateIRQPositions (bool initial);
void S9xUpdateHVTimerPosition (void);
void S9xCheckMissingHTimerPosition (int32);
void S9xCheckMissingHTimerRange (int32, int32);
void S9xCheckMissingHTimerHalt (int32, int32);
void S9xFixColourBrightness (void);
void S9xDoAutoJoypad (void);
@ -420,12 +416,6 @@ static inline void FLUSH_REDRAW (void)
static inline void REGISTER_2104 (uint8 Byte)
{
if (!(PPU.OAMFlip & 1))
{
PPU.OAMWriteRegister &= 0xff00;
PPU.OAMWriteRegister |= Byte;
}
if (PPU.OAMAddr & 0x100)
{
int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1);
@ -447,8 +437,33 @@ static inline void REGISTER_2104 (uint8 Byte)
pObj->Size = Byte & 128;
}
PPU.OAMFlip ^= 1;
if (!(PPU.OAMFlip & 1))
{
++PPU.OAMAddr;
PPU.OAMAddr &= 0x1ff;
if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
{
PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
IPPU.OBJChanged = TRUE;
}
}
else
{
if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
IPPU.OBJChanged = TRUE;
}
}
else if (PPU.OAMFlip & 1)
else
if (!(PPU.OAMFlip & 1))
{
PPU.OAMWriteRegister &= 0xff00;
PPU.OAMWriteRegister |= Byte;
PPU.OAMFlip |= 1;
if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
IPPU.OBJChanged = TRUE;
}
else
{
PPU.OAMWriteRegister &= 0x00ff;
uint8 lowbyte = (uint8) (PPU.OAMWriteRegister);
@ -481,24 +496,15 @@ static inline void REGISTER_2104 (uint8 Byte)
PPU.OBJ[addr].VPos = highbyte;
}
}
}
PPU.OAMFlip ^= 1;
if (!(PPU.OAMFlip & 1))
{
PPU.OAMFlip &= ~1;
++PPU.OAMAddr;
PPU.OAMAddr &= 0x1ff;
if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
{
PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
IPPU.OBJChanged = TRUE;
}
}
else
{
if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
IPPU.OBJChanged = TRUE;
}
}
// This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :(
@ -508,18 +514,12 @@ static inline void REGISTER_2104 (uint8 Byte)
{ \
printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \
if (Settings.BlockInvalidVRAMAccess) \
{ \
PPU.VMA.Address += !PPU.VMA.High ? PPU.VMA.Increment : 0; \
return; \
} \
}
#else
#define CHECK_INBLANK() \
if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \
{ \
PPU.VMA.Address += !PPU.VMA.High ? PPU.VMA.Increment : 0; \
return; \
}
return;
#endif
static inline void REGISTER_2118 (uint8 Byte)
@ -559,80 +559,10 @@ static inline void REGISTER_2118 (uint8 Byte)
}
}
static inline void REGISTER_2118_tile (uint8 Byte)
{
CHECK_INBLANK();
uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
uint32 address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
Memory.VRAM[address] = Byte;
IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE;
IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE;
IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
if (!PPU.VMA.High)
PPU.VMA.Address += PPU.VMA.Increment;
}
static inline void REGISTER_2118_linear (uint8 Byte)
{
CHECK_INBLANK();
uint32 address;
Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte;
IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE;
IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE;
IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
if (!PPU.VMA.High)
PPU.VMA.Address += PPU.VMA.Increment;
}
#undef CHECK_INBLANK
#ifdef DEBUGGER
#define CHECK_INBLANK() \
if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \
{ \
printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \
if (Settings.BlockInvalidVRAMAccess) \
{ \
PPU.VMA.Address += PPU.VMA.High ? PPU.VMA.Increment : 0; \
return; \
} \
}
#else
#define CHECK_INBLANK() \
if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \
{ \
PPU.VMA.Address += PPU.VMA.High ? PPU.VMA.Increment : 0; \
return; \
}
#endif
static inline void REGISTER_2119 (uint8 Byte)
{
CHECK_INBLANK();
uint32 address;
if (PPU.VMA.FullGraphicCount)
@ -666,6 +596,31 @@ static inline void REGISTER_2119 (uint8 Byte)
}
}
static inline void REGISTER_2118_tile (uint8 Byte)
{
CHECK_INBLANK();
uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
uint32 address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
Memory.VRAM[address] = Byte;
IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE;
IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE;
IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
if (!PPU.VMA.High)
PPU.VMA.Address += PPU.VMA.Increment;
}
static inline void REGISTER_2119_tile (uint8 Byte)
{
CHECK_INBLANK();
@ -691,6 +646,30 @@ static inline void REGISTER_2119_tile (uint8 Byte)
PPU.VMA.Address += PPU.VMA.Increment;
}
static inline void REGISTER_2118_linear (uint8 Byte)
{
CHECK_INBLANK();
uint32 address;
Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte;
IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE;
IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE;
IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE;
IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE;
IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE;
if (!PPU.VMA.High)
PPU.VMA.Address += PPU.VMA.Increment;
}
static inline void REGISTER_2119_linear (uint8 Byte)
{
CHECK_INBLANK();

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -195,6 +180,7 @@
uint8 SA1OpenBus;
static void S9xSA1Reset (void);
static void S9xSA1SetBWRAMMemMap (uint8);
static void S9xSetSA1MemMap (uint32, uint8);
static void S9xSA1CharConv2 (void);
@ -204,37 +190,31 @@ static void S9xSA1ReadVariableLengthData (bool8, bool8);
void S9xSA1Init (void)
{
SA1.Cycles = 0;
SA1.PrevCycles = 0;
SA1.Flags = 0;
SA1.IRQActive = FALSE;
SA1.WaitingForInterrupt = FALSE;
SA1.Waiting = FALSE;
SA1.Flags = 0;
SA1.Executing = FALSE;
memset(&Memory.FillRAM[0x2200], 0, 0x200);
Memory.FillRAM[0x2200] = 0x20;
Memory.FillRAM[0x2220] = 0x00;
Memory.FillRAM[0x2221] = 0x01;
Memory.FillRAM[0x2222] = 0x02;
Memory.FillRAM[0x2223] = 0x03;
Memory.FillRAM[0x2228] = 0x0f;
SA1.in_char_dma = FALSE;
SA1.TimerIRQLastState = FALSE;
SA1.HTimerIRQPos = 0;
SA1.VTimerIRQPos = 0;
SA1.HCounter = 0;
SA1.VCounter = 0;
SA1.PrevHCounter = 0;
SA1.arithmetic_op = 0;
Memory.FillRAM[0x2228] = 0xff;
SA1.op1 = 0;
SA1.op2 = 0;
SA1.arithmetic_op = 0;
SA1.sum = 0;
SA1.overflow = FALSE;
SA1.VirtualBitmapFormat = 0;
SA1.variable_bit_pos = 0;
SA1.S9xOpcodes = NULL;
}
static void S9xSA1Reset (void)
{
SA1Registers.PBPC = 0;
SA1Registers.PB = 0;
SA1Registers.PCw = 0;
SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
SA1Registers.D.W = 0;
SA1Registers.DB = 0;
SA1Registers.SH = 1;
@ -248,20 +228,17 @@ void S9xSA1Init (void)
SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
SA1ClearFlags(Decimal);
SA1.MemSpeed = SLOW_ONE_CYCLE;
SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
SA1.WaitingForInterrupt = FALSE;
SA1.PCBase = NULL;
S9xSA1SetPCBase(SA1Registers.PBPC);
SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
SA1.S9xOpLengths = S9xOpLengthsM1X1;
S9xSA1SetPCBase(SA1Registers.PBPC);
S9xSA1UnpackStatus();
S9xSA1FixCycles();
SA1.Executing = TRUE;
SA1.BWRAM = Memory.SRAM;
CPU.IRQExternal = FALSE;
Memory.FillRAM[0x2225] = 0;
}
static void S9xSA1SetBWRAMMemMap (uint8 val)
@ -303,6 +280,23 @@ void S9xSA1PostLoadState (void)
SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4;
Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000;
S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]);
SA1.Waiting = (Memory.FillRAM[0x2200] & 0x60) != 0;
SA1.Executing = !SA1.Waiting;
}
void S9xSA1ExecuteDuringSleep (void)
{
#if 0
if (SA1.Executing)
{
while (CPU.Cycles < CPU.NextEvent)
{
S9xSA1MainLoop();
CPU.Cycles += TWO_CYCLES * 2;
}
}
#endif
}
static void S9xSetSA1MemMap (uint32 which1, uint8 map)
@ -315,43 +309,14 @@ static void S9xSetSA1MemMap (uint32 which1, uint8 map)
for (int c = 0; c < 0x100; c += 16)
{
uint8 *block;
if (Multi.cartType != 5)
block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)];
else
{
if ((map & 7) < 4)
block = Memory.ROM + Multi.cartOffsetA + ((map & 7) * 0x100000 + (c << 12));
else
block = Memory.ROM + Multi.cartOffsetB + (((map & 7) - 4) * 0x100000 + (c << 12));
}
uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)];
for (int i = c; i < c + 16; i++)
Memory.Map[start + i] = SA1.Map[start + i] = block;
}
for (int c = 0; c < 0x200; c += 16)
{
// conversion to int is needed here - map is promoted but which1 is not
int32 offset;
uint8 *block;
if (Multi.cartType != 5)
{
offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000;
block = &Memory.ROM[offset];
}
else
{
if ((map & 7) < 4)
{
offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000;
block = Memory.ROM + Multi.cartOffsetA + offset;
}
else
{
offset = (((map & 0x80) ? (map - 4) : which1) & 7) * 0x100000 + (c << 11) - 0x8000;
block = Memory.ROM + Multi.cartOffsetB + offset;
}
}
uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000];
for (int i = c + 8; i < c + 16; i++)
Memory.Map[start2 + i] = SA1.Map[start2 + i] = block;
}
@ -361,48 +326,31 @@ uint8 S9xGetSA1 (uint32 address)
{
switch (address)
{
case 0x2300: // S-CPU flag
return ((Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0));
case 0x2300:
return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE))));
case 0x2301: // SA-1 flag
return ((Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0));
case 0x2301:
return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0));
case 0x2302: // H counter (L)
SA1.HTimerIRQPos = SA1.HCounter / ONE_DOT_CYCLE;
SA1.VTimerIRQPos = SA1.VCounter;
return ((uint8) SA1.HTimerIRQPos);
case 0x2303: // H counter (H)
return ((uint8) (SA1.HTimerIRQPos >> 8));
case 0x2304: // V counter (L)
return ((uint8) SA1.VTimerIRQPos);
case 0x2305: // V counter (H)
return ((uint8) (SA1.VTimerIRQPos >> 8));
case 0x2306: // arithmetic result (LLL)
case 0x2306:
return ((uint8) SA1.sum);
case 0x2307: // arithmetic result (LLH)
case 0x2307:
return ((uint8) (SA1.sum >> 8));
case 0x2308: // arithmetic result (LHL)
case 0x2308:
return ((uint8) (SA1.sum >> 16));
case 0x2309: // arithmetic result (LLH)
case 0x2309:
return ((uint8) (SA1.sum >> 24));
case 0x230a: // arithmetic result (HLL)
case 0x230a:
return ((uint8) (SA1.sum >> 32));
case 0x230b: // arithmetic overflow
return (SA1.overflow ? 0x80 : 0);
case 0x230c: // variable-length data read port (L)
case 0x230c:
return (Memory.FillRAM[0x230c]);
case 0x230d: // variable-length data read port (H)
case 0x230d:
{
uint8 byte = Memory.FillRAM[0x230d];
@ -412,10 +360,8 @@ uint8 S9xGetSA1 (uint32 address)
return (byte);
}
case 0x230e: // version code register
return (0x01);
default:
//printf("R: %04x\n", address);
break;
}
@ -426,279 +372,337 @@ void S9xSetSA1 (uint8 byte, uint32 address)
{
switch (address)
{
case 0x2200: // SA-1 control
#ifdef DEBUGGER
if (byte & 0x60)
printf("SA-1 sleep\n");
#endif
case 0x2200:
SA1.Waiting = (byte & 0x60) != 0;
//SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
// SA-1 reset
if (!(byte & 0x80) && (Memory.FillRAM[0x2200] & 0x20))
{
#ifdef DEBUGGER
printf("SA-1 reset\n");
#endif
SA1Registers.PBPC = 0;
SA1Registers.PB = 0;
SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
S9xSA1SetPCBase(SA1Registers.PBPC);
}
if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20))
S9xSA1Reset();
// SA-1 IRQ control
if (byte & 0x80)
{
Memory.FillRAM[0x2301] |= 0x80;
if (Memory.FillRAM[0x220a] & 0x80)
Memory.FillRAM[0x220b] &= ~0x80;
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= SNES_IRQ_SOURCE;
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
}
}
// SA-1 NMI control
if (byte & 0x10)
{
Memory.FillRAM[0x2301] |= 0x10;
if (Memory.FillRAM[0x220a] & 0x10)
Memory.FillRAM[0x220b] &= ~0x10;
}
break;
case 0x2201: // S-CPU interrupt enable
// S-CPU IRQ enable
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
{
Memory.FillRAM[0x2202] &= ~0x80;
CPU.IRQExternal = TRUE;
}
// S-CPU CHDMA IRQ enable
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
{
Memory.FillRAM[0x2202] &= ~0x20;
CPU.IRQExternal = TRUE;
}
break;
case 0x2202: // S-CPU interrupt clear
// S-CPU IRQ clear
if (byte & 0x80)
Memory.FillRAM[0x2300] &= ~0x80;
// S-CPU CHDMA IRQ clear
if (byte & 0x20)
Memory.FillRAM[0x2300] &= ~0x20;
if (!(Memory.FillRAM[0x2300] & 0xa0))
CPU.IRQExternal = FALSE;
break;
case 0x2203: // SA-1 reset vector (L)
case 0x2204: // SA-1 reset vector (H)
case 0x2205: // SA-1 NMI vector (L)
case 0x2206: // SA-1 NMI vector (H)
case 0x2207: // SA-1 IRQ vector (L)
case 0x2208: // SA-1 IRQ vector (H)
break;
case 0x2209: // S-CPU control
// 0x40: S-CPU IRQ overwrite
// 0x20: S-CPU NMI overwrite
// S-CPU IRQ control
if (byte & 0x80)
{
Memory.FillRAM[0x2300] |= 0x80;
if (Memory.FillRAM[0x2201] & 0x80)
{
Memory.FillRAM[0x2202] &= ~0x80;
CPU.IRQExternal = TRUE;
SA1.Flags |= NMI_FLAG;
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
}
}
break;
case 0x220a: // SA-1 interrupt enable
// SA-1 IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
Memory.FillRAM[0x220b] &= ~0x80;
case 0x2201:
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
S9xSetIRQ(SA1_IRQ_SOURCE);
// SA-1 timer IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
Memory.FillRAM[0x220b] &= ~0x40;
// SA-1 DMA IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
Memory.FillRAM[0x220b] &= ~0x20;
// SA-1 NMI enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
Memory.FillRAM[0x220b] &= ~0x10;
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
break;
case 0x220b: // SA-1 interrupt clear
// SA-1 IRQ clear
case 0x2202:
if (byte & 0x80)
Memory.FillRAM[0x2301] &= ~0x80;
{
Memory.FillRAM[0x2300] &= ~0x80;
S9xClearIRQ(SA1_IRQ_SOURCE);
}
// SA-1 timer IRQ clear
if (byte & 0x40)
Memory.FillRAM[0x2301] &= ~0x40;
// SA-1 DMA IRQ clear
if (byte & 0x20)
Memory.FillRAM[0x2301] &= ~0x20;
{
Memory.FillRAM[0x2300] &= ~0x20;
S9xClearIRQ(SA1_DMA_IRQ_SOURCE);
}
break;
case 0x2203:
//printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8));
break;
case 0x2204:
//printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]);
break;
case 0x2205:
//printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8));
break;
case 0x2206:
//printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]);
break;
case 0x2207:
//printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8));
break;
case 0x2208:
//printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]);
break;
case 0x2209:
Memory.FillRAM[0x2209] = byte;
if (byte & 0x80)
Memory.FillRAM[0x2300] |= 0x80;
if (byte & Memory.FillRAM[0x2201] & 0x80)
S9xSetIRQ(SA1_IRQ_SOURCE);
break;
case 0x220a:
if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= SNES_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= TIMER_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= DMA_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
{
SA1.Flags |= NMI_FLAG;
//SA1.Executing = !SA1.Waiting;
}
break;
case 0x220b:
if (byte & 0x80)
{
SA1.IRQActive &= ~SNES_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x80;
}
if (byte & 0x40)
{
SA1.IRQActive &= ~TIMER_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x40;
}
if (byte & 0x20)
{
SA1.IRQActive &= ~DMA_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x20;
}
// SA-1 NMI clear
if (byte & 0x10)
Memory.FillRAM[0x2301] &= ~0x10;
if (!SA1.IRQActive)
SA1.Flags &= ~IRQ_FLAG;
break;
case 0x220c: // S-CPU NMI vector (L)
case 0x220d: // S-CPU NMI vector (H)
case 0x220e: // S-CPU IRQ vector (L)
case 0x220f: // S-CPU IRQ vector (H)
case 0x220c:
//printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8));
break;
case 0x2210: // SA-1 timer control
// 0x80: mode (linear / HV)
// 0x02: V timer enable
// 0x01: H timer enable
#ifdef DEBUGGER
printf("SA-1 timer control write:%02x\n", byte);
case 0x220d:
//printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]);
break;
case 0x220e:
//printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8));
break;
case 0x220f:
//printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]);
break;
case 0x2210:
#if 0
printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV");
printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled");
printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled");
#endif
break;
case 0x2211: // SA-1 timer reset
SA1.HCounter = 0;
SA1.VCounter = 0;
case 0x2211:
//printf("Timer reset\n");
break;
case 0x2212: // SA-1 H-timer (L)
SA1.HTimerIRQPos = byte | (Memory.FillRAM[0x2213] << 8);
case 0x2212:
//printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8));
break;
case 0x2213: // SA-1 H-timer (H)
SA1.HTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2212];
case 0x2213:
//printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]);
break;
case 0x2214: // SA-1 V-timer (L)
SA1.VTimerIRQPos = byte | (Memory.FillRAM[0x2215] << 8);
case 0x2214:
//printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8));
break;
case 0x2215: // SA-1 V-timer (H)
SA1.VTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2214];
case 0x2215:
//printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]);
break;
case 0x2220: // MMC bank C
case 0x2221: // MMC bank D
case 0x2222: // MMC bank E
case 0x2223: // MMC bank F
case 0x2220:
case 0x2221:
case 0x2222:
case 0x2223:
//printf("MMC: %02x\n", byte);
S9xSetSA1MemMap(address - 0x2220, byte);
break;
case 0x2224: // S-CPU BW-RAM mapping
case 0x2224:
//printf("BWRAM image SNES %02x -> 0x6000\n", byte);
Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000;
break;
case 0x2225: // SA-1 BW-RAM mapping
case 0x2225:
//printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]);
if (byte != Memory.FillRAM[0x2225])
S9xSA1SetBWRAMMemMap(byte);
break;
case 0x2226: // S-CPU BW-RAM write enable
case 0x2227: // SA-1 BW-RAM write enable
case 0x2228: // BW-RAM write-protected area
case 0x2229: // S-CPU I-RAM write protection
case 0x222a: // SA-1 I-RAM write protection
case 0x2226:
//printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled");
break;
case 0x2230: // DMA control
// 0x80: enable
// 0x40: priority (DMA / SA-1)
// 0x20: character conversion / normal
// 0x10: BW-RAM -> I-RAM / SA-1 -> I-RAM
// 0x04: destinatin (BW-RAM / I-RAM)
// 0x03: source
case 0x2227:
//printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled");
break;
case 0x2231: // character conversion DMA parameters
// 0x80: CHDEND (complete / incomplete)
// 0x03: color mode
// (byte >> 2) & 7: virtual VRAM width
case 0x2228:
//printf("BW-RAM write protect area %02x\n", byte);
break;
case 0x2229:
//printf("I-RAM SNES write protect area %02x\n", byte);
break;
case 0x222a:
//printf("I-RAM SA1 write protect area %02x\n", byte);
break;
case 0x2230:
#if 0
printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled");
printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1");
printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal");
printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM");
printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM");
printf("DMA source %s\n", DMAsource[byte & 3]);
#endif
break;
case 0x2231:
if (byte & 0x80)
SA1.in_char_dma = FALSE;
#if 0
printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete");
printf("DMA colour mode %d\n", byte & 3);
printf("virtual VRAM width %d\n", (byte >> 2) & 7);
#endif
break;
case 0x2232: // DMA source start address (LL)
case 0x2233: // DMA source start address (LH)
case 0x2234: // DMA source start address (HL)
case 0x2232:
case 0x2233:
case 0x2234:
Memory.FillRAM[address] = byte;
#if 0
printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16));
#endif
break;
case 0x2235: // DMA destination start address (LL)
case 0x2235:
Memory.FillRAM[0x2235] = byte;
break;
case 0x2236: // DMA destination start address (LH)
case 0x2236:
Memory.FillRAM[0x2236] = byte;
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM
S9xSA1DMA();
else
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) // CC1
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0)
{
SA1.in_char_dma = TRUE;
Memory.FillRAM[0x2300] |= 0x20;
if (Memory.FillRAM[0x2201] & 0x20)
{
Memory.FillRAM[0x2202] &= ~0x20;
CPU.IRQExternal = TRUE;
}
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
SA1.in_char_dma = TRUE;
}
break;
case 0x2237: // DMA destination start address (HL)
case 0x2237:
Memory.FillRAM[0x2237] = byte;
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM
S9xSA1DMA();
#if 0
printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16));
#endif
break;
case 0x2238: // DMA terminal counter (L)
case 0x2239: // DMA terminal counter (H)
case 0x2238:
case 0x2239:
Memory.FillRAM[address] = byte;
#if 0
printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8));
#endif
break;
case 0x223f: // BW-RAM bitmap format
case 0x223f:
//printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4);
SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
break;
case 0x2240: // bitmap register 0
case 0x2241: // bitmap register 1
case 0x2242: // bitmap register 2
case 0x2243: // bitmap register 3
case 0x2244: // bitmap register 4
case 0x2245: // bitmap register 5
case 0x2246: // bitmap register 6
case 0x2247: // bitmap register 7
case 0x2248: // bitmap register 8
case 0x2249: // bitmap register 9
case 0x224a: // bitmap register A
case 0x224b: // bitmap register B
case 0x224c: // bitmap register C
case 0x224d: // bitmap register D
case 0x224e: // bitmap register E
case 0x2240:
case 0x2241:
case 0x2242:
case 0x2243:
case 0x2244:
case 0x2245:
case 0x2246:
case 0x2247:
case 0x2248:
case 0x2249:
case 0x224a:
case 0x224b:
case 0x224c:
case 0x224d:
case 0x224e:
#if 0
if (!(SA1.Flags & TRACE_FLAG))
{
TraceSA1();
Trace();
}
#endif
Memory.FillRAM[address] = byte;
break;
case 0x224f: // bitmap register F
case 0x224f:
Memory.FillRAM[0x224f] = byte;
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // CC2
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled
{
memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16);
SA1.in_char_dma = (SA1.in_char_dma + 1) & 7;
@ -708,69 +712,58 @@ void S9xSetSA1 (uint8 byte, uint32 address)
break;
case 0x2250: // arithmetic control
case 0x2250:
if (byte & 2)
SA1.sum = 0;
SA1.arithmetic_op = byte & 3;
break;
case 0x2251: // multiplicand / dividend (L)
SA1.op1 = (SA1.op1 & 0xff00) | byte;
case 0x2251:
SA1.op1 = (SA1.op1 & 0xff00) | byte;
break;
case 0x2252: // multiplicand / dividend (H)
SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8);
case 0x2252:
SA1.op1 = (SA1.op1 & 0xff) | (byte << 8);
break;
case 0x2253: // multiplier / divisor (L)
SA1.op2 = (SA1.op2 & 0xff00) | byte;
case 0x2253:
SA1.op2 = (SA1.op2 & 0xff00) | byte;
break;
case 0x2254: // multiplier / divisor (H)
SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8);
case 0x2254:
SA1.op2 = (SA1.op2 & 0xff) | (byte << 8);
switch (SA1.arithmetic_op)
{
case 0: // signed multiplication
SA1.sum = (int16) SA1.op1 * (int16) SA1.op2;
SA1.op2 = 0;
case 0: // multiply
SA1.sum = SA1.op1 * SA1.op2;
break;
case 1: // unsigned division
case 1: // divide
if (SA1.op2 == 0)
SA1.sum = 0;
SA1.sum = SA1.op1 << 16;
else
{
int16 dividend = (int16) SA1.op1;
uint16 divisor = (uint16) SA1.op2;
uint16 remainder = (dividend >= 0) ? dividend % divisor : (dividend % divisor) + divisor;
uint16 quotient = (dividend - remainder) / divisor;
SA1.sum = (remainder << 16) | quotient;
}
SA1.op1 = 0;
SA1.op2 = 0;
SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16);
break;
case 2: // cumulative sum
default:
SA1.sum += (int16) SA1.op1 * (int16) SA1.op2;
SA1.overflow = (SA1.sum >= (1ULL << 40));
SA1.sum &= (1ULL << 40) - 1;
SA1.op2 = 0;
SA1.sum += SA1.op1 * SA1.op2;
if (SA1.sum & ((int64) 0xffffff << 32))
SA1.overflow = TRUE;
break;
}
break;
case 0x2258: // variable bit-field length / auto inc / start
case 0x2258: // Variable bit-field length/auto inc/start.
Memory.FillRAM[0x2258] = byte;
S9xSA1ReadVariableLengthData(TRUE, FALSE);
return;
case 0x2259: // variable bit-field start address (LL)
case 0x225a: // variable bit-field start address (LH)
case 0x225b: // variable bit-field start address (HL)
case 0x2259: // Variable bit-field start address
case 0x225a:
case 0x225b:
Memory.FillRAM[address] = byte;
// XXX: ???
SA1.variable_bit_pos = 0;
@ -778,6 +771,7 @@ void S9xSetSA1 (uint8 byte, uint32 address)
return;
default:
//printf("W: %02x->%04x\n", byte, address);
break;
}
@ -896,11 +890,14 @@ static void S9xSA1DMA (void)
}
memmove(d, s, len);
// SA-1 DMA IRQ control
Memory.FillRAM[0x2301] |= 0x20;
if (Memory.FillRAM[0x220a] & 0x20)
Memory.FillRAM[0x220b] &= ~0x20;
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= DMA_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
}
static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift)
@ -1099,10 +1096,6 @@ void S9xSA1SetPCBase (uint32 address)
SA1Registers.PBPC = address & 0xffffff;
SA1.ShiftedPB = address & 0xff0000;
// FIXME
SA1.MemSpeed = memory_speed(address);
SA1.MemSpeedx2 = SA1.MemSpeed << 1;
uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
@ -1140,3 +1133,4 @@ void S9xSA1SetPCBase (uint32 address)
return;
}
}

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -213,33 +198,32 @@ struct SSA1
uint8 _Zero;
uint8 _Negative;
uint8 _Overflow;
bool8 CPUExecuting;
uint32 ShiftedPB;
uint32 ShiftedDB;
uint32 Flags;
int32 Cycles;
int32 PrevCycles;
uint8 *PCBase;
bool8 IRQActive;
bool8 Waiting;
bool8 WaitingForInterrupt;
uint32 WaitAddress;
uint32 WaitCounter;
uint32 PBPCAtOpcodeStart;
uint8 *WaitByteAddress1;
uint8 *WaitByteAddress2;
uint8 *Map[MEMMAP_NUM_BLOCKS];
uint8 *WriteMap[MEMMAP_NUM_BLOCKS];
uint8 *BWRAM;
bool8 in_char_dma;
bool8 TimerIRQLastState;
uint16 HTimerIRQPos;
uint16 VTimerIRQPos;
int16 HCounter;
int16 VCounter;
int16 PrevHCounter;
int32 MemSpeed;
int32 MemSpeedx2;
int32 arithmetic_op;
uint16 op1;
uint16 op2;
uint64 sum;
bool8 Executing;
bool8 overflow;
bool8 in_char_dma;
int16 op1;
int16 op2;
int32 arithmetic_op;
int64 sum;
uint8 VirtualBitmapFormat;
uint8 variable_bit_pos;
};
@ -279,8 +263,13 @@ uint8 S9xGetSA1 (uint32);
void S9xSetSA1 (uint8, uint32);
void S9xSA1Init (void);
void S9xSA1MainLoop (void);
void S9xSA1ExecuteDuringSleep (void);
void S9xSA1PostLoadState (void);
#define SNES_IRQ_SOURCE (1 << 7)
#define TIMER_IRQ_SOURCE (1 << 6)
#define DMA_IRQ_SOURCE (1 << 5)
static inline void S9xSA1UnpackStatus (void)
{
SA1._Zero = (SA1Registers.PL & Zero) == 0;

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -236,43 +221,20 @@
#define StackRelative SA1StackRelative
#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed
//#undef CPU_SHUTDOWN
#define SA1_OPCODES
#include "cpuops.cpp"
static void S9xSA1UpdateTimer (void);
void S9xSA1MainLoop (void)
{
if (Memory.FillRAM[0x2200] & 0x60)
if (SA1.Flags & NMI_FLAG)
{
SA1.Cycles += 6; // FIXME
S9xSA1UpdateTimer();
return;
}
// SA-1 NMI
if ((Memory.FillRAM[0x2200] & 0x10) && !(Memory.FillRAM[0x220b] & 0x10))
{
Memory.FillRAM[0x2301] |= 0x10;
Memory.FillRAM[0x220b] |= 0x10;
if (SA1.WaitingForInterrupt)
if (Memory.FillRAM[0x2200] & 0x10)
{
SA1.WaitingForInterrupt = FALSE;
SA1Registers.PCw++;
}
S9xSA1Opcode_NMI();
}
else
if (!SA1CheckFlag(IRQ))
{
// SA-1 Timer IRQ
if ((Memory.FillRAM[0x220a] & 0x40) && !(Memory.FillRAM[0x220b] & 0x40))
{
Memory.FillRAM[0x2301] |= 0x40;
SA1.Flags &= ~NMI_FLAG;
Memory.FillRAM[0x2301] |= 0x10;
if (SA1.WaitingForInterrupt)
{
@ -280,45 +242,38 @@ void S9xSA1MainLoop (void)
SA1Registers.PCw++;
}
S9xSA1Opcode_IRQ();
S9xSA1Opcode_NMI();
}
}
if (SA1.Flags & IRQ_FLAG)
{
if (SA1.IRQActive)
{
if (SA1.WaitingForInterrupt)
{
SA1.WaitingForInterrupt = FALSE;
SA1Registers.PCw++;
}
if (!SA1CheckFlag(IRQ))
S9xSA1Opcode_IRQ();
}
else
// SA-1 DMA IRQ
if ((Memory.FillRAM[0x220a] & 0x20) && !(Memory.FillRAM[0x220b] & 0x20))
{
Memory.FillRAM[0x2301] |= 0x20;
if (SA1.WaitingForInterrupt)
{
SA1.WaitingForInterrupt = FALSE;
SA1Registers.PCw++;
}
S9xSA1Opcode_IRQ();
}
else
// SA-1 IRQ
if ((Memory.FillRAM[0x2200] & 0x80) && !(Memory.FillRAM[0x220b] & 0x80))
{
Memory.FillRAM[0x2301] |= 0x80;
if (SA1.WaitingForInterrupt)
{
SA1.WaitingForInterrupt = FALSE;
SA1Registers.PCw++;
}
S9xSA1Opcode_IRQ();
}
SA1.Flags &= ~IRQ_FLAG;
}
for (int i = 0; i < 5 && !(Memory.FillRAM[0x2200] & 0x60); i++)
for (int i = 0; i < 3 && SA1.Executing; i++)
{
#ifdef DEBUGGER
if (SA1.Flags & TRACE_FLAG)
S9xSA1Trace();
#endif
#ifdef CPU_SHUTDOWN
SA1.PBPCAtOpcodeStart = SA1Registers.PBPC;
#endif
register uint8 Op;
register struct SOpcodes *Opcodes;
@ -344,71 +299,5 @@ void S9xSA1MainLoop (void)
Registers.PCw++;
(*Opcodes[Op].S9xOpcode)();
}
S9xSA1UpdateTimer();
}
static void S9xSA1UpdateTimer (void) // FIXME
{
SA1.PrevHCounter = SA1.HCounter;
if (Memory.FillRAM[0x2210] & 0x80)
{
SA1.HCounter += (SA1.Cycles - SA1.PrevCycles);
if (SA1.HCounter >= 0x800)
{
SA1.HCounter -= 0x800;
SA1.PrevHCounter -= 0x800;
if (++SA1.VCounter >= 0x200)
SA1.VCounter = 0;
}
}
else
{
SA1.HCounter += (SA1.Cycles - SA1.PrevCycles);
if (SA1.HCounter >= Timings.H_Max_Master)
{
SA1.HCounter -= Timings.H_Max_Master;
SA1.PrevHCounter -= Timings.H_Max_Master;
if (++SA1.VCounter >= Timings.V_Max_Master)
SA1.VCounter = 0;
}
}
if (SA1.Cycles >= Timings.H_Max_Master)
SA1.Cycles -= Timings.H_Max_Master;
SA1.PrevCycles = SA1.Cycles;
bool8 thisIRQ = Memory.FillRAM[0x2210] & 0x03;
if (Memory.FillRAM[0x2210] & 0x01)
{
if (SA1.PrevHCounter >= SA1.HTimerIRQPos * ONE_DOT_CYCLE || SA1.HCounter < SA1.HTimerIRQPos * ONE_DOT_CYCLE)
thisIRQ = FALSE;
}
if (Memory.FillRAM[0x2210] & 0x02)
{
if (SA1.VCounter != SA1.VTimerIRQPos * ONE_DOT_CYCLE)
thisIRQ = FALSE;
}
// SA-1 Timer IRQ control
if (!SA1.TimerIRQLastState && thisIRQ)
{
Memory.FillRAM[0x2301] |= 0x40;
if (Memory.FillRAM[0x220a] & 0x40)
{
Memory.FillRAM[0x220b] &= ~0x40;
#ifdef DEBUGGER
S9xTraceFormattedMessage("--- SA-1 Timer IRQ triggered prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
SA1.PrevHCounter, SA1.HCounter,
(Memory.FillRAM[0x2210] & 0x01) ? 1 : 0, SA1.HTimerIRQPos * ONE_DOT_CYCLE,
(Memory.FillRAM[0x2210] & 0x02) ? 1 : 0, SA1.VTimerIRQPos);
#endif
}
}
SA1.TimerIRQLastState = thisIRQ;
}

View File

@ -1,178 +0,0 @@
/*********************************************************************
* Filename: sha256.c
* Author: Brad Conte (brad AT bradconte.com)
* Copyright:
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Implementation of the SHA-256 hashing algorithm.
SHA-256 is one of the three algorithms in the SHA2
specification. The others, SHA-384 and SHA-512, are not
offered in this implementation.
Algorithm specification can be found here:
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
This implementation uses little endian byte order.
*********************************************************************/
/*************************** HEADER FILES ***************************/
#include <stdlib.h>
#include <memory.h>
/****************************** MACROS ******************************/
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
#define SHA256_BLOCK_SIZE 32 /* SHA256 outputs a 32 byte digest */
/**************************** DATA TYPES ****************************/
typedef unsigned char BYTE; /* 8-bit byte */
typedef unsigned int WORD; /* 32-bit word, change to "long" for 16-bit machines */
typedef struct {
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
/**************************** VARIABLES *****************************/
static const WORD k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
/* Append to the padding the total message's length in bits and transform. */
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
/* Since this implementation uses little endian byte ordering and SHA uses big endian,
reverse all the bytes when copying the final state to the output hash. */
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
void sha256sum(unsigned char *data, unsigned int length, unsigned char *hash)
{
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx, data, length);
sha256_final(&ctx, hash);
}

View File

@ -1,6 +0,0 @@
#ifndef __SHA256_H
#define __SHA256_H
void sha256sum (unsigned char *data, unsigned int length, unsigned char *hash);
#endif

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,14 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
(c) Copyright 2001 - 2010 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
MSU-1 code
(c) Copyright 2016 qwertymodo
Specific ports contains the works of other authors. See headers in
@ -357,7 +345,7 @@ struct SnapshotScreenshotInfo
static struct Obsolete
{
uint8 CPU_IRQActive;
uint8 reserved;
} Obsolete;
#define STRUCT struct SCPUState
@ -368,7 +356,7 @@ static FreezeData SnapCPU[] =
INT_ENTRY(6, PrevCycles),
INT_ENTRY(6, V_Counter),
INT_ENTRY(6, Flags),
OBSOLETE_INT_ENTRY(6, 7, CPU_IRQActive),
INT_ENTRY(6, IRQActive),
INT_ENTRY(6, IRQPending),
INT_ENTRY(6, MemSpeed),
INT_ENTRY(6, MemSpeedx2),
@ -381,14 +369,9 @@ static FreezeData SnapCPU[] =
INT_ENTRY(6, WhichEvent),
INT_ENTRY(6, NextEvent),
INT_ENTRY(6, WaitingForInterrupt),
DELETED_INT_ENTRY(6, 7, WaitAddress, 4),
DELETED_INT_ENTRY(6, 7, WaitCounter, 4),
DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4),
INT_ENTRY(7, NMIPending),
INT_ENTRY(7, IRQLine),
INT_ENTRY(7, IRQTransition),
INT_ENTRY(7, IRQLastState),
INT_ENTRY(7, IRQExternal)
INT_ENTRY(6, WaitAddress),
INT_ENTRY(6, WaitCounter),
INT_ENTRY(6, PBPCAtOpcodeStart)
};
#undef STRUCT
@ -573,8 +556,7 @@ static FreezeData SnapControls[] =
ARRAY_ENTRY(6, dummy3, 8, uint8_ARRAY_V),
INT_ENTRY(6, pad_read),
INT_ENTRY(6, pad_read_last),
ARRAY_ENTRY(6, internal, 60, uint8_ARRAY_V),
ARRAY_ENTRY(10, internal_macs, 5, uint8_ARRAY_V)
ARRAY_ENTRY(6, internal, 60, uint8_ARRAY_V)
};
#undef STRUCT
@ -596,10 +578,8 @@ static FreezeData SnapTimings[] =
INT_ENTRY(6, InterlaceField),
INT_ENTRY(6, DMACPUSync),
INT_ENTRY(6, NMIDMADelay),
INT_ENTRY(6, IRQFlagChanging),
INT_ENTRY(6, APUSpeedup),
INT_ENTRY(7, IRQTriggerCycles),
INT_ENTRY(7, APUAllowTimeOverflow)
INT_ENTRY(6, IRQPendCount),
INT_ENTRY(6, APUSpeedup)
};
#undef STRUCT
@ -668,17 +648,17 @@ static FreezeData SnapFX[] =
static FreezeData SnapSA1[] =
{
DELETED_INT_ENTRY(6, 7, CPUExecuting, 1),
INT_ENTRY(6, CPUExecuting),
INT_ENTRY(6, ShiftedPB),
INT_ENTRY(6, ShiftedDB),
INT_ENTRY(6, Flags),
DELETED_INT_ENTRY(6, 7, IRQActive, 1),
DELETED_INT_ENTRY(6, 7, Waiting, 1),
INT_ENTRY(6, IRQActive),
INT_ENTRY(6, Waiting),
INT_ENTRY(6, WaitingForInterrupt),
DELETED_INT_ENTRY(6, 7, WaitAddress, 4),
DELETED_INT_ENTRY(6, 7, WaitCounter, 4),
DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4),
DELETED_INT_ENTRY(6, 7, Executing, 1),
INT_ENTRY(6, WaitAddress),
INT_ENTRY(6, WaitCounter),
INT_ENTRY(6, PBPCAtOpcodeStart),
INT_ENTRY(6, Executing),
INT_ENTRY(6, overflow),
INT_ENTRY(6, in_char_dma),
INT_ENTRY(6, op1),
@ -686,17 +666,7 @@ static FreezeData SnapSA1[] =
INT_ENTRY(6, arithmetic_op),
INT_ENTRY(6, sum),
INT_ENTRY(6, VirtualBitmapFormat),
INT_ENTRY(6, variable_bit_pos),
INT_ENTRY(7, Cycles),
INT_ENTRY(7, PrevCycles),
INT_ENTRY(7, TimerIRQLastState),
INT_ENTRY(7, HTimerIRQPos),
INT_ENTRY(7, VTimerIRQPos),
INT_ENTRY(7, HCounter),
INT_ENTRY(7, VCounter),
INT_ENTRY(7, PrevHCounter),
INT_ENTRY(7, MemSpeed),
INT_ENTRY(7, MemSpeedx2)
INT_ENTRY(6, variable_bit_pos)
};
#undef STRUCT
@ -1143,16 +1113,16 @@ static FreezeData SnapBSX[] =
static FreezeData SnapMSU1[] =
{
INT_ENTRY(9, MSU1_STATUS),
INT_ENTRY(9, MSU1_DATA_SEEK),
INT_ENTRY(9, MSU1_DATA_POS),
INT_ENTRY(9, MSU1_TRACK_SEEK),
INT_ENTRY(9, MSU1_CURRENT_TRACK),
INT_ENTRY(9, MSU1_RESUME_TRACK),
INT_ENTRY(9, MSU1_VOLUME),
INT_ENTRY(9, MSU1_CONTROL),
INT_ENTRY(9, MSU1_AUDIO_POS),
INT_ENTRY(9, MSU1_RESUME_POS)
INT_ENTRY(7, MSU1_STATUS),
INT_ENTRY(7, MSU1_DATA_SEEK),
INT_ENTRY(7, MSU1_DATA_POS),
INT_ENTRY(7, MSU1_TRACK_SEEK),
INT_ENTRY(7, MSU1_CURRENT_TRACK),
INT_ENTRY(7, MSU1_RESUME_TRACK),
INT_ENTRY(7, MSU1_VOLUME),
INT_ENTRY(7, MSU1_CONTROL),
INT_ENTRY(7, MSU1_AUDIO_POS),
INT_ENTRY(7, MSU1_RESUME_POS)
};
#undef STRUCT
@ -1181,8 +1151,6 @@ static int UnfreezeStructCopy (STREAM, const char *, uint8 **, FreezeData *, int
static void UnfreezeStructFromCopy (void *, FreezeData *, int, uint8 *, int);
static void FreezeBlock (STREAM, const char *, uint8 *, int);
static void FreezeStruct (STREAM, const char *, void *, FreezeData *, int);
static bool CheckBlockName(STREAM stream, const char *name, int &len);
static void SkipBlockWithName(STREAM stream, const char *name);
void S9xResetSaveTimer (bool8 dontsave)
@ -1195,7 +1163,7 @@ void S9xResetSaveTimer (bool8 dontsave)
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, SAVE_INFO_OOPS);
S9xFreezeGame(filename);
}
@ -1203,21 +1171,6 @@ void S9xResetSaveTimer (bool8 dontsave)
t = time(NULL);
}
uint32 S9xFreezeSize()
{
nulStream stream;
S9xFreezeToStream(&stream);
return stream.size();
}
bool8 S9xFreezeGameMem (uint8 *buf, uint32 bufSize)
{
memStream mStream(buf, bufSize);
S9xFreezeToStream(&mStream);
return (TRUE);
}
bool8 S9xFreezeGame (const char *filename)
{
STREAM stream = NULL;
@ -1243,14 +1196,6 @@ bool8 S9xFreezeGame (const char *filename)
return (FALSE);
}
int S9xUnfreezeGameMem (const uint8 *buf, uint32 bufSize)
{
memStream stream(buf, bufSize);
int result = S9xUnfreezeFromStream(&stream);
return result;
}
bool8 S9xUnfreezeGame (const char *filename)
{
STREAM stream = NULL;
@ -1325,8 +1270,10 @@ bool8 S9xUnfreezeGame (const char *filename)
void S9xFreezeToStream (STREAM stream)
{
char buffer[8192];
uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE];
char buffer[1024];
uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE];
S9xSetSoundMute(TRUE);
sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION);
WRITE_STREAM(buffer, strlen(buffer), stream);
@ -1466,19 +1413,19 @@ void S9xFreezeToStream (STREAM stream)
}
}
S9xSetSoundMute(FALSE);
delete [] soundsnapshot;
}
int S9xUnfreezeFromStream (STREAM stream)
{
const bool8 fast = Settings.FastSavestates;
int result = SUCCESS;
int version, len;
char buffer[PATH_MAX + 1];
len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1;
if (READ_STREAM(buffer, len, stream) != (unsigned int ) len)
if (READ_STREAM(buffer, len, stream) != len)
return (WRONG_FORMAT);
if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0)
@ -1539,31 +1486,19 @@ int S9xUnfreezeFromStream (STREAM stream)
if (result != SUCCESS)
break;
if (fast)
result = UnfreezeBlock(stream, "VRA", Memory.VRAM, 0x10000);
else
result = UnfreezeBlockCopy(stream, "VRA", &local_vram, 0x10000);
result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000);
if (result != SUCCESS)
break;
if (fast)
result = UnfreezeBlock(stream, "RAM", Memory.RAM, 0x20000);
else
result = UnfreezeBlockCopy(stream, "RAM", &local_ram, 0x20000);
result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000);
if (result != SUCCESS)
break;
if (fast)
result = UnfreezeBlock(stream, "SRA", Memory.SRAM, 0x20000);
else
result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000);
result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000);
if (result != SUCCESS)
break;
if (fast)
result = UnfreezeBlock(stream, "FIL", Memory.FillRAM, 0x8000);
else
result = UnfreezeBlockCopy(stream, "FIL", &local_fillram, 0x8000);
result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000);
if (result != SUCCESS)
break;
@ -1603,19 +1538,9 @@ int S9xUnfreezeFromStream (STREAM stream)
if (result != SUCCESS && Settings.DSP == 4)
break;
if (Settings.C4)
{
if (fast)
result = UnfreezeBlock(stream, "CX4", Memory.C4RAM, 8192);
else
result = UnfreezeBlockCopy(stream, "CX4", &local_cx4_data, 8192);
if (result != SUCCESS)
break;
}
else
{
SkipBlockWithName(stream, "CX4");
}
result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192);
if (result != SUCCESS && Settings.C4)
break;
result = UnfreezeStructCopy(stream, "ST0", &local_st010, SnapST010, COUNT(SnapST010), version);
if (result != SUCCESS && Settings.SETA == ST_010)
@ -1625,19 +1550,9 @@ int S9xUnfreezeFromStream (STREAM stream)
if (result != SUCCESS && Settings.OBC1)
break;
if (Settings.OBC1)
{
if (fast)
result = UnfreezeBlock(stream, "OBM", Memory.OBC1RAM, 8192);
else
result = UnfreezeBlockCopy(stream, "OBM", &local_obc1_data, 8192);
if (result != SUCCESS)
break;
}
else
{
SkipBlockWithName(stream, "OBM");
}
result = UnfreezeBlockCopy (stream, "OBM", &local_obc1_data, 8192);
if (result != SUCCESS && Settings.OBC1)
break;
result = UnfreezeStructCopy(stream, "S71", &local_spc7110, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), version);
if (result != SUCCESS && Settings.SPC7110)
@ -1700,15 +1615,9 @@ int S9xUnfreezeFromStream (STREAM stream)
uint32 old_flags = CPU.Flags;
uint32 sa1_old_flags = SA1.Flags;
if (fast)
{
S9xResetPPUFast();
}
else
{
//Do not call this if you have written directly to "Memory." arrays
S9xReset();
}
S9xSetSoundMute(TRUE);
S9xReset();
UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version);
@ -1719,19 +1628,15 @@ int S9xUnfreezeFromStream (STREAM stream)
struct SDMASnapshot dma_snap;
UnfreezeStructFromCopy(&dma_snap, SnapDMA, COUNT(SnapDMA), local_dma, version);
if (local_vram)
memcpy(Memory.VRAM, local_vram, 0x10000);
memcpy(Memory.VRAM, local_vram, 0x10000);
if (local_ram)
memcpy(Memory.RAM, local_ram, 0x20000);
memcpy(Memory.RAM, local_ram, 0x20000);
if (local_sram)
memcpy(Memory.SRAM, local_sram, 0x20000);
memcpy(Memory.SRAM, local_sram, 0x20000);
if (local_fillram)
memcpy(Memory.FillRAM, local_fillram, 0x8000);
memcpy(Memory.FillRAM, local_fillram, 0x8000);
S9xAPULoadState(local_apu_sound);
S9xAPULoadState(local_apu_sound);
struct SControlSnapshot ctl_snap;
UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version);
@ -1786,46 +1691,11 @@ int S9xUnfreezeFromStream (STREAM stream)
if (local_msu1_data)
UnfreezeStructFromCopy(&MSU1, SnapMSU1, COUNT(SnapMSU1), local_msu1_data, version);
if (version < SNAPSHOT_VERSION_IRQ)
{
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
CPU.NMIPending = (CPU.Flags & (1 << 7)) ? TRUE : FALSE;
CPU.IRQLine = (CPU.Flags & (1 << 11)) ? TRUE : FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQLastState = FALSE;
CPU.IRQExternal = (Obsolete.CPU_IRQActive & ~(1 << 1)) ? TRUE : FALSE;
switch (CPU.WhichEvent)
{
case 12: case 1: CPU.WhichEvent = 1; break;
case 2: case 3: CPU.WhichEvent = 2; break;
case 4: case 5: CPU.WhichEvent = 3; break;
case 6: case 7: CPU.WhichEvent = 4; break;
case 8: case 9: CPU.WhichEvent = 5; break;
case 10: case 11: CPU.WhichEvent = 6; break;
}
if (local_sa1) // FIXME
{
SA1.Cycles = SA1.PrevCycles = 0;
SA1.TimerIRQLastState = FALSE;
SA1.HTimerIRQPos = Memory.FillRAM[0x2212] | (Memory.FillRAM[0x2213] << 8);
SA1.VTimerIRQPos = Memory.FillRAM[0x2214] | (Memory.FillRAM[0x2215] << 8);
SA1.HCounter = 0;
SA1.VCounter = 0;
SA1.PrevHCounter = 0;
SA1.MemSpeed = SLOW_ONE_CYCLE;
SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
}
}
CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG);
ICPU.ShiftedPB = Registers.PB << 16;
ICPU.ShiftedDB = Registers.DB << 16;
S9xSetPCBase(Registers.PBPC);
S9xUnpackStatus();
S9xUpdateIRQPositions(false);
S9xFixCycles();
for (int d = 0; d < 8; d++)
@ -1938,9 +1808,11 @@ int S9xUnfreezeFromStream (STREAM stream)
else
{
// couldn't load graphics, so black out the screen instead
for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++)
memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2);
//for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++)
// memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2);
}
S9xSetSoundMute(FALSE);
}
if (local_cpu) delete [] local_cpu;
@ -2136,51 +2008,6 @@ static void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size
WRITE_STREAM(block, size, stream);
}
static bool CheckBlockName(STREAM stream, const char *name, int &len)
{
char buffer[16];
len = 0;
long rewind = FIND_STREAM(stream);
size_t l = READ_STREAM(buffer, 11, stream);
buffer[l] = 0;
REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0);
if (buffer[4] == '-')
{
len = (((unsigned char)buffer[6]) << 24)
| (((unsigned char)buffer[7]) << 16)
| (((unsigned char)buffer[8]) << 8)
| (((unsigned char)buffer[9]) << 0);
}
else
len = atoi(buffer + 4);
if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':')
{
return false;
}
if (len <= 0)
{
return false;
}
return true;
}
static void SkipBlockWithName(STREAM stream, const char *name)
{
int len;
bool matchesName = CheckBlockName(stream, name, len);
if (matchesName)
{
long rewind = FIND_STREAM(stream);
rewind += len + 11;
REVERT_STREAM(stream, rewind, 0);
}
}
static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size)
{
char buffer[20];
@ -2193,9 +2020,7 @@ static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int siz
if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':')
{
err:
#ifdef DEBUGGER
fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer);
#endif
REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0);
return (WRONG_FORMAT);
}
@ -2219,12 +2044,9 @@ static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int siz
len = size;
}
if (!Settings.FastSavestates)
{
memset(block, 0, size);
}
memset(block, 0, size);
if (READ_STREAM(block, len, stream) != (unsigned int) len)
if (READ_STREAM(block, len, stream) != len)
{
REVERT_STREAM(stream, rewind, 0);
return (WRONG_FORMAT);
@ -2249,13 +2071,6 @@ static int UnfreezeBlockCopy (STREAM stream, const char *name, uint8 **block, in
{
int result;
//check name first to avoid memory allocation
int blockLength;
if (!CheckBlockName(stream, name, blockLength))
{
return 0;
}
*block = new uint8[size];
result = UnfreezeBlock(stream, name, *block, size);

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,14 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
(c) Copyright 2001 - 2010 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
MSU-1 code
(c) Copyright 2016 qwertymodo
Specific ports contains the works of other authors. See headers in
@ -193,12 +181,8 @@
#ifndef _SNAPSHOT_H_
#define _SNAPSHOT_H_
#include "snes9x.h"
#define SNAPSHOT_MAGIC "#!s9xsnp"
#define SNAPSHOT_VERSION_IRQ 7
#define SNAPSHOT_VERSION_BAPU 8
#define SNAPSHOT_VERSION 10
#define SNAPSHOT_VERSION 7
#define SUCCESS 1
#define WRONG_FORMAT (-1)
@ -210,11 +194,9 @@
void S9xResetSaveTimer (bool8);
bool8 S9xFreezeGame (const char *);
uint32 S9xFreezeSize (void);
bool8 S9xFreezeGameMem (uint8 *,uint32);
bool8 S9xUnfreezeGame (const char *);
int S9xUnfreezeGameMem (const uint8 *,uint32);
void S9xFreezeToStream (STREAM);
int S9xUnfreezeFromStream (STREAM);
bool8 S9xSPCDump (const char *);
#endif

View File

@ -17,20 +17,13 @@
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
(c) Copyright 2009 - 2010 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
@ -124,9 +117,6 @@
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
@ -140,7 +130,7 @@
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
(c) Copyright 2004 - 2010 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
@ -148,16 +138,11 @@
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
(c) Copyright 2009 - 2010 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
(c) Copyright 2001 - 2010 zones
Specific ports contains the works of other authors. See headers in
@ -194,51 +179,40 @@
#define _SNES9X_H_
#ifndef VERSION
#define VERSION "1.56.2"
#define VERSION "1.53"
#endif
#include "port.h"
#include "65c816.h"
#include "messages.h"
#define S9X_ACCURACY_LEVEL 3
#ifdef ZLIB
#include <zlib.h>
#define FSTREAM gzFile
#define READ_FSTREAM(p, l, s) gzread(s, p, l)
#define WRITE_FSTREAM(p, l, s) gzwrite(s, p, l)
#define GETS_FSTREAM(p, l, s) gzgets(s, p, l)
#define GETC_FSTREAM(s) gzgetc(s)
#define OPEN_FSTREAM(f, m) gzopen(f, m)
#define REOPEN_FSTREAM(f, m) gzdopen(f, m)
#define FIND_FSTREAM(f) gztell(f)
#define REVERT_FSTREAM(s, o, p) gzseek(s, o, p)
#define CLOSE_FSTREAM(s) gzclose(s)
#define STREAM gzFile
#define READ_STREAM(p, l, s) gzread(s, p, l)
#define WRITE_STREAM(p, l, s) gzwrite(s, p, l)
#define GETS_STREAM(p, l, s) gzgets(s, p, l)
#define GETC_STREAM(s) gzgetc(s)
#define OPEN_STREAM(f, m) gzopen(f, m)
#define REOPEN_STREAM(f, m) gzdopen(f, m)
#define FIND_STREAM(f) gztell(f)
#define REVERT_STREAM(f, o, s) gzseek(f, o, s)
#define CLOSE_STREAM(s) gzclose(s)
#else
#define FSTREAM FILE *
#define READ_FSTREAM(p, l, s) fread(p, 1, l, s)
#define WRITE_FSTREAM(p, l, s) fwrite(p, 1, l, s)
#define GETS_FSTREAM(p, l, s) fgets(p, l, s)
#define GETC_FSTREAM(s) fgetc(s)
#define OPEN_FSTREAM(f, m) fopen(f, m)
#define REOPEN_FSTREAM(f, m) fdopen(f, m)
#define FIND_FSTREAM(s) ftell(s)
#define REVERT_FSTREAM(s, o, p) fseek(s, o, p)
#define CLOSE_FSTREAM(s) fclose(s)
#define STREAM FILE *
#define READ_STREAM(p, l, s) fread(p, 1, l, s)
#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s)
#define GETS_STREAM(p, l, s) fgets(p, l, s)
#define GETC_STREAM(s) fgetc(s)
#define OPEN_STREAM(f, m) fopen(f, m)
#define REOPEN_STREAM(f, m) fdopen(f, m)
#define FIND_STREAM(f) ftell(f)
#define REVERT_STREAM(f, o, s) fseek(f, o, s)
#define CLOSE_STREAM(s) fclose(s)
#endif
#include "stream.h"
#define STREAM Stream *
#define READ_STREAM(p, l, s) s->read(p,l)
#define WRITE_STREAM(p, l, s) s->write(p,l)
#define GETS_STREAM(p, l, s) s->gets(p,l)
#define GETC_STREAM(s) s->get_char()
#define OPEN_STREAM(f, m) openStreamFromFSTREAM(f, m)
#define REOPEN_STREAM(f, m) reopenStreamFromFd(f, m)
#define FIND_STREAM(s) s->pos()
#define REVERT_STREAM(s, o, p) s->revert(p, o)
#define CLOSE_STREAM(s) s->closeStream()
#define SNES_WIDTH 256
#define SNES_HEIGHT 224
#define SNES_HEIGHT_EXTENDED 239
@ -254,15 +228,9 @@
#define SNES_MAX_PAL_VCOUNTER 312
#define SNES_HCOUNTER_MAX 341
#ifndef ALLOW_CPU_OVERCLOCK
#define ONE_CYCLE 6
#define SLOW_ONE_CYCLE 8
#define TWO_CYCLES 12
#else
#define ONE_CYCLE (Settings.OneClockCycle)
#define SLOW_ONE_CYCLE (Settings.OneSlowClockCycle)
#define TWO_CYCLES (Settings.TwoClockCycles)
#endif
#define ONE_DOT_CYCLE 4
#define SNES_CYCLES_PER_SCANLINE (SNES_HCOUNTER_MAX * ONE_DOT_CYCLE)
@ -295,6 +263,8 @@
#define TRACE_FLAG (1 << 1) // debugger
#define SINGLE_STEP_FLAG (1 << 2) // debugger
#define BREAK_FLAG (1 << 3) // debugger
#define NMI_FLAG (1 << 7) // CPU
#define IRQ_FLAG (1 << 11) // CPU
#define SCAN_KEYS_FLAG (1 << 4) // CPU
#define HALTED_FLAG (1 << 12) // APU
#define FRAME_ADVANCE_FLAG (1 << 9)
@ -304,16 +274,12 @@
struct SCPUState
{
uint32 Flags;
int32 Cycles;
int32 PrevCycles;
int32 V_Counter;
uint32 Flags;
uint8 *PCBase;
bool8 NMIPending;
bool8 IRQLine;
bool8 IRQTransition;
bool8 IRQLastState;
bool8 IRQExternal;
bool8 IRQActive;
int32 IRQPending;
int32 MemSpeed;
int32 MemSpeedx2;
@ -327,6 +293,9 @@ struct SCPUState
uint8 WhichEvent;
int32 NextEvent;
bool8 WaitingForInterrupt;
uint32 WaitAddress;
uint32 WaitCounter;
uint32 PBPCAtOpcodeStart;
uint32 AutoSaveTimer;
bool8 SRAMModified;
};
@ -334,18 +303,17 @@ struct SCPUState
enum
{
HC_HBLANK_START_EVENT = 1,
HC_HDMA_START_EVENT = 2,
HC_HCOUNTER_MAX_EVENT = 3,
HC_HDMA_INIT_EVENT = 4,
HC_RENDER_EVENT = 5,
HC_WRAM_REFRESH_EVENT = 6
};
enum
{
IRQ_NONE = 0,
IRQ_SET_FLAG = 1,
IRQ_CLEAR_FLAG = 2
HC_IRQ_1_3_EVENT = 2,
HC_HDMA_START_EVENT = 3,
HC_IRQ_3_5_EVENT = 4,
HC_HCOUNTER_MAX_EVENT = 5,
HC_IRQ_5_7_EVENT = 6,
HC_HDMA_INIT_EVENT = 7,
HC_IRQ_7_9_EVENT = 8,
HC_RENDER_EVENT = 9,
HC_IRQ_9_A_EVENT = 10,
HC_WRAM_REFRESH_EVENT = 11,
HC_IRQ_A_1_EVENT = 12
};
struct STimings
@ -359,14 +327,12 @@ struct STimings
int32 HDMAInit;
int32 HDMAStart;
int32 NMITriggerPos;
int32 NextIRQTimer;
int32 IRQTriggerCycles;
int32 WRAMRefreshPos;
int32 RenderPos;
bool8 InterlaceField;
int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly.
int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly.
int32 IRQFlagChanging; // This value is just a hack.
int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode.
int32 APUSpeedup;
bool8 APUAllowTimeOverflow;
};
@ -379,7 +345,6 @@ struct SSettings
bool8 TraceUnknownRegisters;
bool8 TraceDSP;
bool8 TraceHCEvent;
bool8 TraceSMP;
bool8 SuperFX;
uint8 DSP;
@ -394,12 +359,11 @@ struct SSettings
bool8 BS;
bool8 BSXItself;
bool8 BSXBootup;
bool8 MSU1;
bool8 MSU1;
bool8 MouseMaster;
bool8 SuperScopeMaster;
bool8 JustifierMaster;
bool8 MultiPlayer5Master;
bool8 MacsRifleMaster;
bool8 ForceLoROM;
bool8 ForceHiROM;
@ -437,15 +401,18 @@ struct SSettings
bool8 AutoDisplayMessages;
uint32 InitialInfoStringTimeout;
uint16 DisplayColor;
bool8 BilinearFilter;
bool8 Multi;
char CartAName[PATH_MAX + 1];
char CartBName[PATH_MAX + 1];
bool8 DisableGameSpecificHacks;
bool8 ShutdownMaster;
bool8 Shutdown;
bool8 BlockInvalidVRAMAccessMaster;
bool8 BlockInvalidVRAMAccess;
bool8 DisableIRQ;
bool8 DisableHDMA;
int32 HDMATimingHack;
bool8 ForcedPause;
@ -458,7 +425,6 @@ struct SSettings
bool8 TurboMode;
uint32 HighSpeedSeek;
bool8 FrameAdvance;
bool8 Rewinding;
bool8 NetPlay;
bool8 NetPlayServer;
@ -474,22 +440,15 @@ struct SSettings
bool8 TakeScreenshot;
int8 StretchScreenshots;
bool8 SnapshotScreenshots;
char InitialSnapshotFilename[PATH_MAX + 1];
bool8 FastSavestates;
bool8 ApplyCheats;
bool8 NoPatch;
bool8 IgnorePatchChecksum;
int32 AutoSaveDelay;
bool8 DontSaveOopsSnapshot;
bool8 UpAndDown;
bool8 OpenGLEnable;
uint32 SuperFXClockMultiplier;
int OneClockCycle;
int OneSlowClockCycle;
int TwoClockCycles;
float SuperFXSpeedPerLine;
int MaxSpriteTilesPerLine;
};

View File

@ -1,638 +0,0 @@
/***********************************************************************************
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
Jerremy Koot (jkoot@snes9x.com)
(c) Copyright 2002 - 2004 Matthew Kendora
(c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
(c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
(c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
Kris Bleakley (codeviolation@hotmail.com)
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
zones
C4 x86 assembler and some C emulation code
(c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
Nach,
zsKnight (zsknight@zsnes.com)
C4 C++ code
(c) Copyright 2003 - 2006 Brad Jorsch,
Nach
DSP-1 emulator code
(c) Copyright 1998 - 2006 _Demo_,
Andreas Naive (andreasnaive@gmail.com),
Gary Henderson,
Ivar (ivar@snes9x.com),
John Weidman,
Kris Bleakley,
Matthew Kendora,
Nach,
neviksti (neviksti@hotmail.com)
DSP-2 emulator code
(c) Copyright 2003 John Weidman,
Kris Bleakley,
Lord Nightmare (lord_nightmare@users.sourceforge.net),
Matthew Kendora,
neviksti
DSP-3 emulator code
(c) Copyright 2003 - 2006 John Weidman,
Kris Bleakley,
Lancer,
z80 gaiden
DSP-4 emulator code
(c) Copyright 2004 - 2006 Dreamer Nom,
John Weidman,
Kris Bleakley,
Nach,
z80 gaiden
OBC1 emulator code
(c) Copyright 2001 - 2004 zsKnight,
pagefault (pagefault@zsnes.com),
Kris Bleakley
Ported from x86 assembler to C by sanmaiwashi
SPC7110 and RTC C++ emulator code used in 1.39-1.51
(c) Copyright 2002 Matthew Kendora with research by
zsKnight,
John Weidman,
Dark Force
SPC7110 and RTC C++ emulator code used in 1.52+
(c) Copyright 2009 byuu,
neviksti
S-DD1 C emulator code
(c) Copyright 2003 Brad Jorsch with research by
Andreas Naive,
John Weidman
S-RTC C emulator code
(c) Copyright 2001 - 2006 byuu,
John Weidman
ST010 C++ emulator code
(c) Copyright 2003 Feather,
John Weidman,
Kris Bleakley,
Matthew Kendora
Super FX x86 assembler emulator code
(c) Copyright 1998 - 2003 _Demo_,
pagefault,
zsKnight
Super FX C emulator code
(c) Copyright 1997 - 1999 Ivar,
Gary Henderson,
John Weidman
Sound emulator code used in 1.5-1.51
(c) Copyright 1998 - 2003 Brad Martin
(c) Copyright 1998 - 2006 Charles Bilyue'
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
2xSaI filter
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
HQ2x, HQ3x, HQ4x filters
(c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
NTSC filter
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
funkyass,
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
Specific ports contains the works of other authors. See headers in
individual files.
Snes9x homepage: http://www.snes9x.com/
Permission to use, copy, modify and/or 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 or it's derivatives.
Snes9x is freeware for PERSONAL USE only. Commercial users should
seek permission of the copyright holders first. Commercial use includes,
but is not limited to, charging money for Snes9x or software derived from
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
using Snes9x as a promotion for your commercial product.
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.
***********************************************************************************/
// Abstract the details of reading from zip files versus FILE *'s.
#include <string>
#ifdef UNZIP_SUPPORT
# ifdef SYSTEM_ZIP
# include <minizip/unzip.h>
# else
# include "unzip.h"
# endif
#endif
#include "snes9x.h"
#include "stream.h"
// Generic constructor/destructor
Stream::Stream (void)
{
return;
}
Stream::~Stream (void)
{
return;
}
// Generic getline function, based on gets. Reimlpement if you can do better.
char * Stream::getline (void)
{
bool eof;
std::string ret;
ret = getline(eof);
if (ret.size() == 0 && eof)
return (NULL);
return (strdup(ret.c_str()));
}
std::string Stream::getline (bool &eof)
{
char buf[1024];
std::string ret;
eof = false;
ret.clear();
do
{
if (gets(buf, sizeof(buf)) == NULL)
{
eof = true;
break;
}
ret.append(buf);
}
while (*ret.rbegin() != '\n');
return (ret);
}
// snes9x.h FSTREAM Stream
fStream::fStream (FSTREAM f)
{
fp = f;
}
fStream::~fStream (void)
{
return;
}
int fStream::get_char (void)
{
return (GETC_FSTREAM(fp));
}
char * fStream::gets (char *buf, size_t len)
{
return (GETS_FSTREAM(buf, len, fp));
}
size_t fStream::read (void *buf, size_t len)
{
return (READ_FSTREAM(buf, len, fp));
}
size_t fStream::write (void *buf, size_t len)
{
return (WRITE_FSTREAM(buf, len, fp));
}
size_t fStream::pos (void)
{
return (FIND_FSTREAM(fp));
}
size_t fStream::size (void)
{
size_t sz;
REVERT_FSTREAM(fp,0L,SEEK_END);
sz = FIND_FSTREAM(fp);
REVERT_FSTREAM(fp,0L,SEEK_SET);
return sz;
}
int fStream::revert (size_t from, size_t offset)
{
return (REVERT_FSTREAM(fp, offset, from));
}
void fStream::closeStream()
{
CLOSE_FSTREAM(fp);
delete this;
}
// unzip Stream
#ifdef UNZIP_SUPPORT
unzStream::unzStream (unzFile &v)
{
file = v;
pos_in_buf = 0;
buf_pos_in_unzipped = unztell(file);
bytes_in_buf = 0;
// remember start pos for seeks
unzGetFilePos(file, &unz_file_start_pos);
}
unzStream::~unzStream (void)
{
return;
}
size_t unzStream::buffer_remaining()
{
return bytes_in_buf - pos_in_buf;
}
void unzStream::fill_buffer()
{
buf_pos_in_unzipped = unztell(file);
bytes_in_buf = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
pos_in_buf = 0;
}
int unzStream::get_char (void)
{
unsigned char c;
if (buffer_remaining() <= 0)
{
fill_buffer();
if (bytes_in_buf <= 0)
return (EOF);
}
c = *(buffer + pos_in_buf);
pos_in_buf++;
return ((int) c);
}
char * unzStream::gets (char *buf, size_t len)
{
size_t i;
int c;
for (i = 0; i < len - 1; i++)
{
c = get_char();
if (c == EOF)
{
if (i == 0)
return (NULL);
break;
}
buf[i] = (char) c;
if (buf[i] == '\n')
break;
}
buf[i] = '\0';
return (buf);
}
size_t unzStream::read (void *buf, size_t len)
{
if (len == 0)
return (len);
size_t to_read = len;
uint8 *read_to = (uint8 * )buf;
do
{
size_t in_buffer = buffer_remaining();
if (to_read <= in_buffer)
{
memcpy(read_to, buffer + pos_in_buf, to_read);
pos_in_buf += to_read;
to_read = 0;
break;
}
memcpy(read_to, buffer + pos_in_buf, in_buffer);
to_read -= in_buffer;
fill_buffer();
} while (bytes_in_buf);
return (len - to_read);
}
// not supported
size_t unzStream::write (void *buf, size_t len)
{
return (0);
}
size_t unzStream::pos (void)
{
return buf_pos_in_unzipped + pos_in_buf;
}
size_t unzStream::size (void)
{
unz_file_info info;
unzGetCurrentFileInfo(file,&info,NULL,0,NULL,0,NULL,0);
return info.uncompressed_size;
}
int unzStream::revert (size_t from, size_t offset)
{
size_t target_pos = from + offset;
// new pos inside buffered data
if (target_pos >= buf_pos_in_unzipped && target_pos < buf_pos_in_unzipped + bytes_in_buf)
{
pos_in_buf = target_pos - buf_pos_in_unzipped;
}
else // outside of buffer, reset file and read until pos
{
unzGoToFilePos(file, &unz_file_start_pos);
unzOpenCurrentFile(file); // necessary to reopen after seek
int times_to_read = target_pos / unz_BUFFSIZ + 1;
for( int i = 0; i < times_to_read; i++)
{
fill_buffer();
}
pos_in_buf = target_pos % unz_BUFFSIZ;
}
return 0;
}
void unzStream::closeStream()
{
unzClose(file);
delete this;
}
#endif
// memory Stream
memStream::memStream (uint8 *source, size_t sourceSize)
{
mem = head = source;
msize = remaining = sourceSize;
readonly = false;
}
memStream::memStream (const uint8 *source, size_t sourceSize)
{
mem = head = const_cast<uint8 *>(source);
msize = remaining = sourceSize;
readonly = true;
}
memStream::~memStream (void)
{
return;
}
int memStream::get_char (void)
{
if(!remaining)
return EOF;
remaining--;
return *head++;
}
char * memStream::gets (char *buf, size_t len)
{
size_t i;
int c;
for (i = 0; i < len - 1; i++)
{
c = get_char();
if (c == EOF)
{
if (i == 0)
return (NULL);
break;
}
buf[i] = (char) c;
if (buf[i] == '\n')
break;
}
buf[i] = '\0';
return (buf);
}
size_t memStream::read (void *buf, size_t len)
{
size_t bytes = len < remaining ? len : remaining;
memcpy(buf,head,bytes);
head += bytes;
remaining -= bytes;
return bytes;
}
size_t memStream::write (void *buf, size_t len)
{
if(readonly)
return 0;
size_t bytes = len < remaining ? len : remaining;
memcpy(head,buf,bytes);
head += bytes;
remaining -= bytes;
return bytes;
}
size_t memStream::pos (void)
{
return msize - remaining;
}
size_t memStream::size (void)
{
return msize;
}
int memStream::revert (size_t from, size_t offset)
{
size_t pos = from + offset;
if(pos > msize)
return -1;
head = mem + pos;
remaining = msize - pos;
return 0;
}
void memStream::closeStream()
{
delete [] mem;
delete this;
}
// dummy Stream
nulStream::nulStream (void)
{
bytes_written = 0;
}
nulStream::~nulStream (void)
{
return;
}
int nulStream::get_char (void)
{
return 0;
}
char * nulStream::gets (char *buf, size_t len)
{
*buf = '\0';
return NULL;
}
size_t nulStream::read (void *buf, size_t len)
{
return 0;
}
size_t nulStream::write (void *buf, size_t len)
{
bytes_written += len;
return len;
}
size_t nulStream::pos (void)
{
return 0;
}
size_t nulStream::size (void)
{
return bytes_written;
}
int nulStream::revert (size_t from, size_t offset)
{
bytes_written = from + offset;
return 0;
}
void nulStream::closeStream()
{
delete this;
}
Stream *openStreamFromFSTREAM(const char* filename, const char* mode)
{
FSTREAM f = OPEN_FSTREAM(filename,mode);
if(!f)
return NULL;
return new fStream(f);
}
Stream *reopenStreamFromFd(int fd, const char* mode)
{
FSTREAM f = REOPEN_FSTREAM(fd,mode);
if(!f)
return NULL;
return new fStream(f);
}

View File

@ -1,318 +0,0 @@
/***********************************************************************************
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
Jerremy Koot (jkoot@snes9x.com)
(c) Copyright 2002 - 2004 Matthew Kendora
(c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
(c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
(c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
Kris Bleakley (codeviolation@hotmail.com)
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
Nach (n-a-c-h@users.sourceforge.net),
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
(c) Copyright 2006 - 2007 nitsuja
(c) Copyright 2009 - 2018 BearOso,
OV2
(c) Copyright 2017 qwertymodo
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
BS-X C emulator code
(c) Copyright 2005 - 2006 Dreamer Nom,
zones
C4 x86 assembler and some C emulation code
(c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
Nach,
zsKnight (zsknight@zsnes.com)
C4 C++ code
(c) Copyright 2003 - 2006 Brad Jorsch,
Nach
DSP-1 emulator code
(c) Copyright 1998 - 2006 _Demo_,
Andreas Naive (andreasnaive@gmail.com),
Gary Henderson,
Ivar (ivar@snes9x.com),
John Weidman,
Kris Bleakley,
Matthew Kendora,
Nach,
neviksti (neviksti@hotmail.com)
DSP-2 emulator code
(c) Copyright 2003 John Weidman,
Kris Bleakley,
Lord Nightmare (lord_nightmare@users.sourceforge.net),
Matthew Kendora,
neviksti
DSP-3 emulator code
(c) Copyright 2003 - 2006 John Weidman,
Kris Bleakley,
Lancer,
z80 gaiden
DSP-4 emulator code
(c) Copyright 2004 - 2006 Dreamer Nom,
John Weidman,
Kris Bleakley,
Nach,
z80 gaiden
OBC1 emulator code
(c) Copyright 2001 - 2004 zsKnight,
pagefault (pagefault@zsnes.com),
Kris Bleakley
Ported from x86 assembler to C by sanmaiwashi
SPC7110 and RTC C++ emulator code used in 1.39-1.51
(c) Copyright 2002 Matthew Kendora with research by
zsKnight,
John Weidman,
Dark Force
SPC7110 and RTC C++ emulator code used in 1.52+
(c) Copyright 2009 byuu,
neviksti
S-DD1 C emulator code
(c) Copyright 2003 Brad Jorsch with research by
Andreas Naive,
John Weidman
S-RTC C emulator code
(c) Copyright 2001 - 2006 byuu,
John Weidman
ST010 C++ emulator code
(c) Copyright 2003 Feather,
John Weidman,
Kris Bleakley,
Matthew Kendora
Super FX x86 assembler emulator code
(c) Copyright 1998 - 2003 _Demo_,
pagefault,
zsKnight
Super FX C emulator code
(c) Copyright 1997 - 1999 Ivar,
Gary Henderson,
John Weidman
Sound emulator code used in 1.5-1.51
(c) Copyright 1998 - 2003 Brad Martin
(c) Copyright 1998 - 2006 Charles Bilyue'
Sound emulator code used in 1.52+
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
S-SMP emulator code used in 1.54+
(c) Copyright 2016 byuu
SH assembler code partly based on x86 assembler code
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
2xSaI filter
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
HQ2x, HQ3x, HQ4x filters
(c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
NTSC filter
(c) Copyright 2006 - 2007 Shay Green
GTK+ GUI code
(c) Copyright 2004 - 2018 BearOso
Win32 GUI code
(c) Copyright 2003 - 2006 blip,
funkyass,
Matthew Kendora,
Nach,
nitsuja
(c) Copyright 2009 - 2018 OV2
Mac OS GUI code
(c) Copyright 1998 - 2001 John Stiles
(c) Copyright 2001 - 2011 zones
Libretro port
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
Daniel De Matteis
(Under no circumstances will commercial rights be given)
Specific ports contains the works of other authors. See headers in
individual files.
Snes9x homepage: http://www.snes9x.com/
Permission to use, copy, modify and/or 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 or it's derivatives.
Snes9x is freeware for PERSONAL USE only. Commercial users should
seek permission of the copyright holders first. Commercial use includes,
but is not limited to, charging money for Snes9x or software derived from
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
using Snes9x as a promotion for your commercial product.
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.
***********************************************************************************/
#ifndef _STREAM_H_
#define _STREAM_H_
#include <string>
class Stream
{
public:
Stream (void);
virtual ~Stream (void);
virtual int get_char (void) = 0;
virtual char * gets (char *, size_t) = 0;
virtual char * getline (void); // free() when done
virtual std::string getline (bool &);
virtual size_t read (void *, size_t) = 0;
virtual size_t write (void *, size_t) = 0;
virtual size_t pos (void) = 0;
virtual size_t size (void) = 0;
virtual int revert (size_t from, size_t offset) = 0;
virtual void closeStream() = 0;
};
class fStream : public Stream
{
public:
fStream (FSTREAM);
virtual ~fStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
FSTREAM fp;
};
#ifdef UNZIP_SUPPORT
# ifdef SYSTEM_ZIP
# include <minizip/unzip.h>
# else
# include "unzip.h"
# endif
#define unz_BUFFSIZ 1024
class unzStream : public Stream
{
public:
unzStream (unzFile &);
virtual ~unzStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
void fill_buffer();
size_t buffer_remaining();
unzFile file;
char buffer[unz_BUFFSIZ];
size_t pos_in_buf;
size_t buf_pos_in_unzipped;
size_t bytes_in_buf;
unz_file_pos unz_file_start_pos;
};
#endif
class memStream : public Stream
{
public:
memStream (uint8 *,size_t);
memStream (const uint8 *,size_t);
virtual ~memStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
uint8 *mem;
size_t msize;
size_t remaining;
uint8 *head;
bool readonly;
};
/* dummy stream that always reads 0 and writes nowhere
but counts bytes written
*/
class nulStream : public Stream
{
public:
nulStream (void);
virtual ~nulStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
size_t bytes_written;
};
Stream *openStreamFromFSTREAM(const char* filename, const char* mode);
Stream *reopenStreamFromFd(int fd, const char* mode);
#endif

View File

@ -521,7 +521,13 @@ int main(int argc, char *argv[])
BrowserLoadFile();
}
Settings.SuperFXClockMultiplier = GCSettings.superFxSpeed;
switch (GCSettings.sfxOverclock)
{
case 0: Settings.SuperFXSpeedPerLine = 0.417 * 10.5e6; break;
case 1: Settings.SuperFXSpeedPerLine = 0.417 * 40.5e6; break;
case 2: Settings.SuperFXSpeedPerLine = 0.417 * 60.5e6; break;
S9xResetSuperFX();
}
while (1) // main loop
{

View File

@ -121,7 +121,7 @@ struct SGCSettings{
int language;
int PreviewImage;
int superFxSpeed;
int sfxOverclock;
};
void ExitApp();