mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-01 08:25:18 +01:00
backport more changes from snes9x master
This commit is contained in:
parent
e8f2613841
commit
856a1ac127
@ -32,7 +32,7 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
|
||||
| UPDATE HISTORY |
|
||||
•˜———–—––-- - —————————––––– ———–—––-- - —————————––––– ———–—––-- - ————————•
|
||||
|
||||
[4.3.8 - August 5, 2018]
|
||||
[4.3.8]
|
||||
|
||||
* Add MSU1 support (thanks qwertymodo!)
|
||||
* Add BPS soft-patching support (thanks qwertymodo!)
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "fileop.h"
|
||||
#include "filebrowser.h"
|
||||
|
||||
#define MAX_CHEATS 100
|
||||
|
||||
extern SCheatData Cheat;
|
||||
|
||||
/****************************************************************************
|
||||
@ -32,20 +34,23 @@ static bool LoadCheatFile (int length)
|
||||
|
||||
while (offset < length)
|
||||
{
|
||||
if(Cheat.num_cheats >= MAX_CHEATS || (length - offset) < 28)
|
||||
if(Cheat.g.size() >= MAX_CHEATS || (length - offset) < 28)
|
||||
break;
|
||||
|
||||
memcpy (data, savebuffer+offset, 28);
|
||||
offset += 28;
|
||||
|
||||
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++;
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -59,8 +64,7 @@ static bool LoadCheatFile (int length)
|
||||
void
|
||||
WiiSetupCheats()
|
||||
{
|
||||
memset(Cheat.c, 0, sizeof(Cheat.c));
|
||||
Cheat.num_cheats = 0;
|
||||
S9xDeleteCheats();
|
||||
|
||||
char filepath[1024];
|
||||
int offset = 0;
|
||||
|
@ -484,7 +484,7 @@ int WiiFileLoader()
|
||||
if(size <= 0)
|
||||
return 0;
|
||||
|
||||
SNESROMSize = Memory.HeaderRemove(size, Memory.HeaderCount, Memory.ROM);
|
||||
SNESROMSize = Memory.HeaderRemove(size, Memory.ROM);
|
||||
return SNESROMSize;
|
||||
}
|
||||
|
||||
|
@ -2063,11 +2063,14 @@ static int MenuGameSettings()
|
||||
else if(cheatsBtn.GetState() == STATE_CLICKED)
|
||||
{
|
||||
cheatsBtn.ResetState();
|
||||
if(Cheat.num_cheats > 0)
|
||||
|
||||
if(Cheat.g.size() > 0) {
|
||||
menu = MENU_GAMESETTINGS_CHEATS;
|
||||
else
|
||||
}
|
||||
else {
|
||||
InfoPrompt("Cheats file not found!");
|
||||
}
|
||||
}
|
||||
else if(screenshotBtn.GetState() == STATE_CLICKED)
|
||||
{
|
||||
if (WindowPrompt("Preview Screenshot", "Save a new Preview Screenshot? Current Screenshot image will be overwritten.", "OK", "Cancel"))
|
||||
@ -2116,10 +2119,10 @@ static int MenuGameCheats()
|
||||
u16 i = 0;
|
||||
OptionList options;
|
||||
|
||||
for(i=0; i < Cheat.num_cheats; i++)
|
||||
for(i=0; i < Cheat.g.size(); i++)
|
||||
{
|
||||
sprintf (options.name[i], "%s", Cheat.c[i].name);
|
||||
sprintf (options.value[i], "%s", Cheat.c[i].enabled == true ? "On" : "Off");
|
||||
sprintf (options.name[i], "%s", Cheat.g[i].name);
|
||||
sprintf (options.value[i], "%s", Cheat.g[i].enabled == true ? "On" : "Off");
|
||||
}
|
||||
|
||||
options.length = i;
|
||||
@ -2168,11 +2171,11 @@ static int MenuGameCheats()
|
||||
|
||||
if(ret >= 0)
|
||||
{
|
||||
if(Cheat.c[ret].enabled)
|
||||
S9xDisableCheat(ret);
|
||||
if(Cheat.g[ret].enabled)
|
||||
S9xDisableCheatGroup(ret);
|
||||
else
|
||||
S9xEnableCheat(ret);
|
||||
sprintf (options.value[ret], "%s", Cheat.c[ret].enabled == true ? "On" : "Off");
|
||||
S9xEnableCheatGroup(ret);
|
||||
sprintf (options.value[ret], "%s", Cheat.g[ret].enabled == true ? "On" : "Off");
|
||||
optionBrowser.TriggerUpdate();
|
||||
}
|
||||
|
||||
@ -3193,17 +3196,11 @@ static int MenuSettingsVideo()
|
||||
Settings.DisplayFrameRate ^= 1;
|
||||
break;
|
||||
case 8:
|
||||
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;
|
||||
GCSettings.superFxSpeed += 10;
|
||||
|
||||
if(GCSettings.superFxSpeed > 200) {
|
||||
GCSettings.superFxSpeed = 100;
|
||||
}
|
||||
if (reset_sfx) S9xResetSuperFX();
|
||||
S9xReset();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3247,15 +3244,7 @@ static int MenuSettingsVideo()
|
||||
sprintf (options.value[6], "PAL (60Hz)"); break;
|
||||
}
|
||||
sprintf (options.value[7], "%s", Settings.DisplayFrameRate ? "On" : "Off");
|
||||
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;
|
||||
}
|
||||
sprintf (options.value[8], "%d%", GCSettings.superFxSpeed);
|
||||
optionBrowser.TriggerUpdate();
|
||||
}
|
||||
|
||||
|
@ -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("sfxOverclock", "SuperFX Overclock", toStr(GCSettings.sfxOverclock));
|
||||
createXMLSetting("superFxSpeed", "SuperFX Speed", toStr(GCSettings.superFxSpeed));
|
||||
|
||||
createXMLSection("Menu", "Menu Settings");
|
||||
|
||||
@ -285,19 +285,17 @@ decodePrefsData ()
|
||||
int verMinor = version[2] - '0';
|
||||
int verPoint = version[4] - '0';
|
||||
|
||||
// first we'll check that the versioning is valid
|
||||
if(!(verMajor >= 0 && verMajor <= 9 &&
|
||||
// check that the versioning is valid
|
||||
if(!(verMajor >= 4 && verMajor <= 9 &&
|
||||
verMinor >= 0 && verMinor <= 9 &&
|
||||
verPoint >= 0 && verPoint <= 9))
|
||||
verPoint >= 0 && verPoint <= 9)) {
|
||||
result = false;
|
||||
else if(verMajor < 4) // less than version 4.0.0
|
||||
result = false; // reset settings
|
||||
else if(verMajor == 4 && verMinor == 0 && verPoint < 2) // anything less than 4.0.2
|
||||
result = false; // reset settings
|
||||
else
|
||||
}
|
||||
else {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result)
|
||||
{
|
||||
@ -337,7 +335,7 @@ decodePrefsData ()
|
||||
|
||||
//Emulation Settings
|
||||
|
||||
loadXMLSetting(&GCSettings.sfxOverclock, "sfxOverclock");
|
||||
loadXMLSetting(&GCSettings.superFxSpeed, "superFxSpeed");
|
||||
|
||||
// Menu Settings
|
||||
|
||||
@ -391,7 +389,7 @@ void FixInvalidSettings()
|
||||
if(!(GCSettings.yshift > -50 && GCSettings.yshift < 50))
|
||||
GCSettings.yshift = 0;
|
||||
if(!(GCSettings.MusicVolume >= 0 && GCSettings.MusicVolume <= 100))
|
||||
GCSettings.MusicVolume = 40;
|
||||
GCSettings.MusicVolume = 20;
|
||||
if(!(GCSettings.SFXVolume >= 0 && GCSettings.SFXVolume <= 100))
|
||||
GCSettings.SFXVolume = 40;
|
||||
if(GCSettings.language < 0 || GCSettings.language >= LANG_LENGTH)
|
||||
@ -443,7 +441,7 @@ DefaultSettings ()
|
||||
|
||||
GCSettings.WiimoteOrientation = 0;
|
||||
GCSettings.ExitAction = 0;
|
||||
GCSettings.MusicVolume = 40;
|
||||
GCSettings.MusicVolume = 20;
|
||||
GCSettings.SFXVolume = 40;
|
||||
GCSettings.Rumble = 1;
|
||||
GCSettings.PreviewImage = 0;
|
||||
@ -460,6 +458,8 @@ DefaultSettings ()
|
||||
GCSettings.language = LANG_ENGLISH;
|
||||
#endif
|
||||
|
||||
GCSettings.superFxSpeed = 100;
|
||||
|
||||
/****************** SNES9x Settings ***********************/
|
||||
|
||||
// Default ALL to false
|
||||
@ -488,6 +488,7 @@ DefaultSettings ()
|
||||
// Graphics
|
||||
Settings.Transparency = true;
|
||||
Settings.SupportHiRes = true;
|
||||
Settings.MaxSpriteTilesPerLine = 34;
|
||||
Settings.SkipFrames = AUTO_FRAMERATE;
|
||||
Settings.TurboSkipFrames = 19;
|
||||
Settings.DisplayFrameRate = false;
|
||||
@ -498,10 +499,7 @@ DefaultSettings ()
|
||||
Settings.FrameTimePAL = 20000;
|
||||
Settings.FrameTimeNTSC = 16667;
|
||||
|
||||
GCSettings.sfxOverclock = 0;
|
||||
/* Initialize SuperFX CPU to normal speed by default */
|
||||
Settings.SuperFXSpeedPerLine = 0.417 * 10.5e6;
|
||||
|
||||
Settings.SuperFXClockMultiplier = 100;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -700,6 +698,8 @@ bool LoadPrefs()
|
||||
CreateDirectory(dirPath);
|
||||
sprintf(dirPath, "%s%s", pathPrefix[GCSettings.LoadMethod], GCSettings.ArtworkFolder);
|
||||
CreateDirectory(dirPath);
|
||||
sprintf(dirPath, "%s%s", pathPrefix[GCSettings.LoadMethod], GCSettings.CheatFolder);
|
||||
CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
ResetText();
|
||||
|
@ -761,3 +761,27 @@ void S9xAPULoadState (uint8 *block)
|
||||
ptr += sizeof(int32);
|
||||
spc::remainder = GET_LE32(ptr);
|
||||
}
|
||||
|
||||
bool8 S9xSPCDump (const char *filename)
|
||||
{
|
||||
FILE *fs;
|
||||
uint8 buf[SNES_SPC::spc_file_size];
|
||||
size_t ignore;
|
||||
|
||||
fs = fopen(filename, "wb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
|
||||
spc_core->init_header(buf);
|
||||
spc_core->save_spc(buf);
|
||||
|
||||
ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs);
|
||||
|
||||
fclose(fs);
|
||||
|
||||
S9xSetSoundMute(FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
@ -200,6 +200,7 @@ void S9xAPUAllowTimeOverflow (bool);
|
||||
void S9xAPULoadState (uint8 *);
|
||||
void S9xAPUSaveState (uint8 *);
|
||||
void S9xDumpSPCSnapshot (void);
|
||||
bool8 S9xSPCDump (const char *);
|
||||
|
||||
bool8 S9xInitSound (int, int);
|
||||
bool8 S9xOpenSoundDevice (void);
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -246,6 +261,9 @@ 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;
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -178,22 +193,31 @@
|
||||
#ifndef _CHEATS_H_
|
||||
#define _CHEATS_H_
|
||||
|
||||
#define MAX_CHEATS 150
|
||||
#include "port.h"
|
||||
#include <vector>
|
||||
|
||||
struct SCheat
|
||||
{
|
||||
uint32 address;
|
||||
uint8 byte;
|
||||
uint8 saved_byte;
|
||||
bool8 conditional;
|
||||
bool8 cond_true;
|
||||
uint8 cond_byte;
|
||||
bool8 enabled;
|
||||
bool8 saved;
|
||||
char name[22];
|
||||
};
|
||||
|
||||
struct SCheatGroup
|
||||
{
|
||||
char *name;
|
||||
bool8 enabled;
|
||||
std::vector<struct SCheat> c;
|
||||
};
|
||||
|
||||
struct SCheatData
|
||||
{
|
||||
struct SCheat c[MAX_CHEATS];
|
||||
uint32 num_cheats;
|
||||
std::vector<struct SCheatGroup> g;
|
||||
bool8 enabled;
|
||||
uint8 CWRAM[0x20000];
|
||||
uint8 CSRAM[0x10000];
|
||||
uint8 CIRAM[0x2000];
|
||||
@ -235,20 +259,23 @@ typedef enum
|
||||
extern SCheatData Cheat;
|
||||
extern Watch watches[16];
|
||||
|
||||
void S9xApplyCheat (uint32);
|
||||
void S9xApplyCheats (void);
|
||||
void S9xRemoveCheat (uint32);
|
||||
void S9xRemoveCheats (void);
|
||||
void S9xDeleteCheat (uint32);
|
||||
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 S9xDeleteCheats (void);
|
||||
void S9xEnableCheat (uint32);
|
||||
void S9xDisableCheat (uint32);
|
||||
void S9xAddCheat (bool8, bool8, uint32, uint8);
|
||||
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 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);
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -174,45 +189,190 @@
|
||||
Nintendo Co., Limited and its subsidiary companies.
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
#include "snes9x.h"
|
||||
#include "memmap.h"
|
||||
#include "cheats.h"
|
||||
#include "bml.h"
|
||||
|
||||
static uint8 S9xGetByteFree (uint32);
|
||||
static void S9xSetByteFree (uint8, uint32);
|
||||
|
||||
|
||||
static uint8 S9xGetByteFree (uint32 address)
|
||||
static inline uint8 S9xGetByteFree (uint32 Address)
|
||||
{
|
||||
uint32 Cycles = CPU.Cycles;
|
||||
uint32 WaitAddress = CPU.WaitAddress;
|
||||
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *GetAddress = Memory.Map[block];
|
||||
uint8 byte;
|
||||
|
||||
byte = S9xGetByte(address);
|
||||
|
||||
CPU.WaitAddress = WaitAddress;
|
||||
CPU.Cycles = Cycles;
|
||||
|
||||
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
{
|
||||
byte = *(GetAddress + (Address & 0xffff));
|
||||
return (byte);
|
||||
}
|
||||
|
||||
switch ((pint) GetAddress)
|
||||
{
|
||||
case CMemory::MAP_CPU:
|
||||
byte = S9xGetCPU(Address & 0xffff);
|
||||
return (byte);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void S9xSetByteFree (uint8 byte, uint32 address)
|
||||
static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
|
||||
{
|
||||
uint32 Cycles = CPU.Cycles;
|
||||
uint32 WaitAddress = CPU.WaitAddress;
|
||||
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *SetAddress = Memory.Map[block];
|
||||
|
||||
S9xSetByte(byte, address);
|
||||
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
{
|
||||
*(SetAddress + (Address & 0xffff)) = Byte;
|
||||
return;
|
||||
}
|
||||
|
||||
CPU.WaitAddress = WaitAddress;
|
||||
CPU.Cycles = Cycles;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void S9xInitWatchedAddress (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
|
||||
watches[i].on = false;
|
||||
|
||||
}
|
||||
|
||||
void S9xInitCheatData (void)
|
||||
@ -222,133 +382,416 @@ void S9xInitCheatData (void)
|
||||
Cheat.FillRAM = Memory.FillRAM;
|
||||
}
|
||||
|
||||
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte)
|
||||
|
||||
void S9xUpdateCheatInMemory (SCheat *c)
|
||||
{
|
||||
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;
|
||||
uint8 byte;
|
||||
|
||||
if (save_current_value)
|
||||
if (!c->enabled)
|
||||
return;
|
||||
|
||||
byte = S9xGetByteFree (c->address);
|
||||
|
||||
if (byte != c->byte)
|
||||
{
|
||||
Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address);
|
||||
Cheat.c[Cheat.num_cheats].saved = TRUE;
|
||||
/* 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 S9xDeleteCheat (uint32 which1)
|
||||
void S9xDisableCheat (SCheat *c)
|
||||
{
|
||||
if (which1 < Cheat.num_cheats)
|
||||
if (!c->enabled)
|
||||
return;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
{
|
||||
if (Cheat.c[which1].enabled)
|
||||
S9xRemoveCheat(which1);
|
||||
|
||||
memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1));
|
||||
|
||||
Cheat.num_cheats--;
|
||||
c->enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void S9xDeleteCheats (void)
|
||||
{
|
||||
S9xRemoveCheats();
|
||||
Cheat.num_cheats = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
{
|
||||
S9xDisableCheatGroup (i);
|
||||
|
||||
delete[] Cheat.g[i].name;
|
||||
}
|
||||
|
||||
Cheat.g.clear ();
|
||||
}
|
||||
|
||||
void S9xRemoveCheat (uint32 which1)
|
||||
void S9xEnableCheat (SCheat *c)
|
||||
{
|
||||
if (Cheat.c[which1].saved)
|
||||
uint8 byte;
|
||||
|
||||
if (c->enabled)
|
||||
return;
|
||||
|
||||
c->enabled = true;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
return;
|
||||
|
||||
byte = S9xGetByteFree(c->address);
|
||||
|
||||
if (c->conditional)
|
||||
{
|
||||
uint32 address = Cheat.c[which1].address;
|
||||
if (byte != c->cond_byte)
|
||||
return;
|
||||
|
||||
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *ptr = Memory.Map[block];
|
||||
c->cond_true = true;
|
||||
}
|
||||
|
||||
c->saved_byte = byte;
|
||||
S9xSetByteFree (c->byte, c->address);
|
||||
}
|
||||
|
||||
void S9xEnableCheatGroup (uint32 num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < Cheat.g[num].c.size (); i++)
|
||||
{
|
||||
S9xEnableCheat (&Cheat.g[num].c[i]);
|
||||
}
|
||||
|
||||
Cheat.g[num].enabled = true;
|
||||
}
|
||||
|
||||
void S9xDisableCheatGroup (uint32 num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < Cheat.g[num].c.size (); i++)
|
||||
{
|
||||
S9xDisableCheat (&Cheat.g[num].c[i]);
|
||||
}
|
||||
|
||||
Cheat.g[num].enabled = false;
|
||||
}
|
||||
|
||||
SCheat S9xTextToCheat (char *text)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
if (ptr >= (uint8 *) CMemory::MAP_LAST)
|
||||
*(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte;
|
||||
else
|
||||
S9xSetByteFree(Cheat.c[which1].saved_byte, address);
|
||||
}
|
||||
}
|
||||
|
||||
void S9xRemoveCheats (void)
|
||||
{
|
||||
for (uint32 i = 0; i < Cheat.num_cheats; i++)
|
||||
if (Cheat.c[i].enabled)
|
||||
S9xRemoveCheat(i);
|
||||
}
|
||||
|
||||
void S9xEnableCheat (uint32 which1)
|
||||
{
|
||||
if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled)
|
||||
{
|
||||
Cheat.c[which1].enabled = TRUE;
|
||||
S9xApplyCheat(which1);
|
||||
c.address = 0;
|
||||
byte = 0;
|
||||
}
|
||||
|
||||
c.byte = byte;
|
||||
c.cond_byte = cond_byte;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void S9xDisableCheat (uint32 which1)
|
||||
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
|
||||
{
|
||||
if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled)
|
||||
SCheatGroup g;
|
||||
char *code;
|
||||
char *code_string = strdup (cheat);
|
||||
|
||||
g.name = strdup (name);
|
||||
g.enabled = false;
|
||||
|
||||
for (code = strtok (code_string, "+"); code; code = strtok (NULL, "+"))
|
||||
{
|
||||
S9xRemoveCheat(which1);
|
||||
Cheat.c[which1].enabled = FALSE;
|
||||
if (code)
|
||||
{
|
||||
SCheat c = S9xTextToCheat (code);
|
||||
if (c.address)
|
||||
g.c.push_back (c);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] code_string;
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
void S9xApplyCheat (uint32 which1)
|
||||
int S9xAddCheatGroup (const char *name, const char *cheat)
|
||||
{
|
||||
uint32 address = Cheat.c[which1].address;
|
||||
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
|
||||
if (g.c.size () == 0)
|
||||
return -1;
|
||||
|
||||
if (!Cheat.c[which1].saved)
|
||||
{
|
||||
Cheat.c[which1].saved_byte = S9xGetByteFree(address);
|
||||
Cheat.c[which1].saved = TRUE;
|
||||
}
|
||||
Cheat.g.push_back (g);
|
||||
return Cheat.g.size () - 1;
|
||||
}
|
||||
|
||||
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *ptr = Memory.Map[block];
|
||||
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
|
||||
{
|
||||
if (num >= Cheat.g.size())
|
||||
return -1;
|
||||
|
||||
if (ptr >= (uint8 *) CMemory::MAP_LAST)
|
||||
*(ptr + (address & 0xffff)) = Cheat.c[which1].byte;
|
||||
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
|
||||
S9xSetByteFree(Cheat.c[which1].byte, address);
|
||||
snprintf (text, size, "%06x=%02x", c->address, c->byte);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
void S9xApplyCheats (void)
|
||||
char *S9xCheatGroupToText (SCheatGroup *g)
|
||||
{
|
||||
if (Settings.ApplyCheats)
|
||||
std::string text = "";
|
||||
unsigned int i;
|
||||
|
||||
if (g->c.size () == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < g->c.size (); i++)
|
||||
{
|
||||
for (uint32 i = 0; i < Cheat.num_cheats; i++)
|
||||
if (Cheat.c[i].enabled)
|
||||
S9xApplyCheat(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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool8 S9xLoadCheatFile (const char *filename)
|
||||
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];
|
||||
|
||||
Cheat.num_cheats = 0;
|
||||
|
||||
fs = fopen(filename, "rb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
|
||||
while (fread((void *) data, 1, 28, fs) == 28)
|
||||
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;
|
||||
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);
|
||||
@ -356,51 +799,147 @@ bool8 S9xLoadCheatFile (const char *filename)
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool8 S9xLoadCheatFile (const char *filename)
|
||||
{
|
||||
bml_node *bml = NULL;
|
||||
bml_node *n = NULL;
|
||||
|
||||
bml = bml_parse_file (filename);
|
||||
if (!bml)
|
||||
{
|
||||
return S9xLoadCheatFileClassic (filename);
|
||||
}
|
||||
|
||||
n = bml_find_sub (bml, "cheat");
|
||||
if (n)
|
||||
{
|
||||
S9xLoadCheatsFromBMLNode (bml);
|
||||
}
|
||||
|
||||
bml_free_node (bml);
|
||||
|
||||
if (!n)
|
||||
{
|
||||
return S9xLoadCheatFileClassic (filename);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool8 S9xSaveCheatFile (const char *filename)
|
||||
{
|
||||
if (Cheat.num_cheats == 0)
|
||||
unsigned int i;
|
||||
FILE *file = NULL;
|
||||
|
||||
if (Cheat.g.size () == 0)
|
||||
{
|
||||
remove(filename);
|
||||
return (TRUE);
|
||||
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++)
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
{
|
||||
ZeroMemory(data, 28);
|
||||
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" : ""
|
||||
);
|
||||
|
||||
delete[] txt;
|
||||
}
|
||||
|
||||
if (!Cheat.c[i].enabled)
|
||||
data[0] |= 4;
|
||||
fclose (file);
|
||||
|
||||
if (Cheat.c[i].saved)
|
||||
data[0] |= 8;
|
||||
|
||||
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;
|
||||
|
||||
memmove(&data[8], Cheat.c[i].name, 19);
|
||||
|
||||
if (fwrite(data, 28, 1, fs) != 1)
|
||||
{
|
||||
fclose(fs);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (fclose(fs) == 0);
|
||||
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 */
|
||||
}
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -181,6 +196,7 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "snes9x.h"
|
||||
#include "memmap.h"
|
||||
@ -194,10 +210,6 @@
|
||||
#include "netplay.h"
|
||||
#endif
|
||||
|
||||
#ifdef GEKKO
|
||||
#include "../snes9xgx.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define NONE (-2)
|
||||
@ -215,7 +227,8 @@ using namespace std;
|
||||
#define SUPERSCOPE 10
|
||||
#define ONE_JUSTIFIER 11
|
||||
#define TWO_JUSTIFIERS 12
|
||||
#define NUMCTLS 13 // This must be LAST
|
||||
#define MACSRIFLE 13
|
||||
#define NUMCTLS 14 // This must be LAST
|
||||
|
||||
#define POLL_ALL NUMCTLS
|
||||
|
||||
@ -229,6 +242,8 @@ 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
|
||||
@ -309,6 +324,14 @@ 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;
|
||||
@ -429,7 +452,6 @@ static const int ptrspeeds[4] = { 1, 1, 4, 8 };
|
||||
S(ToggleBG2), \
|
||||
S(ToggleBG3), \
|
||||
S(ToggleEmuTurbo), \
|
||||
S(ToggleHDMA), \
|
||||
S(ToggleSprites), \
|
||||
S(ToggleTransparency) \
|
||||
|
||||
@ -455,6 +477,7 @@ 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);
|
||||
@ -505,6 +528,12 @@ 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)
|
||||
@ -516,6 +545,7 @@ static int maptype (int t)
|
||||
case S9xButtonMouse:
|
||||
case S9xButtonSuperscope:
|
||||
case S9xButtonJustifier:
|
||||
case S9xButtonMacsRifle:
|
||||
case S9xButtonCommand:
|
||||
case S9xButtonPseudopointer:
|
||||
case S9xButtonPort:
|
||||
@ -543,6 +573,7 @@ void S9xControlsReset (void)
|
||||
mouse[0].buttons &= ~0x30;
|
||||
mouse[1].buttons &= ~0x30;
|
||||
justifier.buttons &= ~JUSTIFIER_SELECT;
|
||||
macsrifle.buttons = 0;
|
||||
}
|
||||
|
||||
void S9xControlsSoftReset (void)
|
||||
@ -556,6 +587,9 @@ void S9xControlsSoftReset (void)
|
||||
read_idx[i][j]=0;
|
||||
|
||||
FLAG_LATCH = FALSE;
|
||||
|
||||
curcontrollers[0] = newcontrollers[0];
|
||||
curcontrollers[1] = newcontrollers[1];
|
||||
}
|
||||
|
||||
void S9xUnmapAllControls (void)
|
||||
@ -627,7 +661,18 @@ void S9xUnmapAllControls (void)
|
||||
if (!(superscope.crosshair.set & 4))
|
||||
superscope.crosshair.bg = 1;
|
||||
|
||||
ZeroMemory(pseudobuttons, sizeof(pseudobuttons));
|
||||
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;
|
||||
}
|
||||
@ -683,6 +728,16 @@ 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;
|
||||
@ -786,6 +841,26 @@ 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)
|
||||
{
|
||||
@ -887,6 +962,11 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -955,6 +1035,13 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,6 +1129,17 @@ 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"));
|
||||
@ -1049,7 +1147,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)
|
||||
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)
|
||||
return (strdup("None"));
|
||||
|
||||
s = "Pointer";
|
||||
@ -1060,6 +1158,7 @@ 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;
|
||||
|
||||
@ -1244,7 +1343,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
int i, j;
|
||||
const char *s;
|
||||
|
||||
ZeroMemory(&cmd, sizeof(cmd));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.type = S9xBadMapping;
|
||||
cmd.multi_press = 0;
|
||||
cmd.button_norpt = 0;
|
||||
@ -1393,6 +1492,19 @@ 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;
|
||||
@ -1402,7 +1514,8 @@ 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 ((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 (i == 0 || *s != 0 || *(s - 1) == '+')
|
||||
return (cmd);
|
||||
@ -1703,6 +1816,7 @@ 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;
|
||||
@ -1768,6 +1882,10 @@ 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:
|
||||
@ -1874,6 +1992,12 @@ 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);
|
||||
@ -1892,6 +2016,7 @@ 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:
|
||||
@ -1911,6 +2036,7 @@ 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);
|
||||
}
|
||||
@ -2054,7 +2180,6 @@ 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;
|
||||
@ -2180,6 +2305,17 @@ 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)
|
||||
{
|
||||
@ -2336,7 +2472,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
|
||||
if (S9xUnfreezeGame(filename))
|
||||
{
|
||||
sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
|
||||
snprintf(buf, 256, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
|
||||
S9xSetInfoString (buf);
|
||||
}
|
||||
else
|
||||
@ -2373,7 +2509,7 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
|
||||
if (S9xUnfreezeGame(filename))
|
||||
{
|
||||
sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000);
|
||||
snprintf(buf, 256, "%s.%03d loaded", def, i - QuickLoad000);
|
||||
S9xSetInfoString(buf);
|
||||
}
|
||||
else
|
||||
@ -2400,7 +2536,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);
|
||||
|
||||
sprintf(buf, "%s.%03d saved", def, i - QuickSave000);
|
||||
snprintf(buf, 256, "%s.%03d saved", def, i - QuickSave000);
|
||||
S9xSetInfoString(buf);
|
||||
|
||||
S9xFreezeGame(filename);
|
||||
@ -2458,11 +2594,6 @@ 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);
|
||||
@ -2580,6 +2711,12 @@ 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:
|
||||
@ -2876,8 +3013,9 @@ void S9xSetJoypadLatch (bool latch)
|
||||
switch (i = curcontrollers[n])
|
||||
{
|
||||
case MP5:
|
||||
for (int j = 0, k = mp5[n].pads[j]; j < 4; k = mp5[n].pads[++j])
|
||||
for (int j = 0, k; j < 4; ++j)
|
||||
{
|
||||
k = mp5[n].pads[j];
|
||||
if (k == NONE)
|
||||
continue;
|
||||
do_polling(k);
|
||||
@ -2934,6 +3072,10 @@ void S9xSetJoypadLatch (bool latch)
|
||||
do_polling(ONE_JUSTIFIER);
|
||||
break;
|
||||
|
||||
case MACSRIFLE:
|
||||
do_polling(i);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2984,6 +3126,10 @@ uint8 S9xReadJOYSERn (int n)
|
||||
case TWO_JUSTIFIERS:
|
||||
return (bits);
|
||||
|
||||
case MACSRIFLE:
|
||||
do_polling(i);
|
||||
return (bits | ((macsrifle.buttons & 0x01) ? 1 : 0));
|
||||
|
||||
default:
|
||||
return (bits);
|
||||
}
|
||||
@ -3079,6 +3225,10 @@ 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);
|
||||
@ -3146,6 +3296,13 @@ 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);
|
||||
@ -3167,8 +3324,9 @@ void S9xControlEOF (void)
|
||||
switch (i = curcontrollers[n])
|
||||
{
|
||||
case MP5:
|
||||
for (j = 0, i = mp5[n].pads[j]; j < 4; i = mp5[n].pads[++j])
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
i = mp5[n].pads[j];
|
||||
if (i == NONE)
|
||||
continue;
|
||||
|
||||
@ -3211,9 +3369,6 @@ 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);
|
||||
}
|
||||
@ -3224,9 +3379,6 @@ 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]);
|
||||
}
|
||||
@ -3246,9 +3398,6 @@ 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]);
|
||||
}
|
||||
@ -3256,6 +3405,18 @@ 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;
|
||||
}
|
||||
@ -3361,6 +3522,7 @@ 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;
|
||||
@ -3378,6 +3540,7 @@ 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;
|
||||
|
||||
@ -3405,6 +3568,7 @@ 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;
|
||||
|
||||
@ -3450,6 +3614,7 @@ 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;
|
||||
@ -3467,8 +3632,8 @@ void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **
|
||||
|
||||
void S9xControlPreSaveState (struct SControlSnapshot *s)
|
||||
{
|
||||
ZeroMemory(s, sizeof(*s));
|
||||
s->ver = 3;
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->ver = 4;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
@ -3517,7 +3682,11 @@ void S9xControlPreSaveState (struct SControlSnapshot *s)
|
||||
for (int k = 0; k < 2; k++)
|
||||
COPY(mp5[j].pads[k]);
|
||||
|
||||
assert(i == sizeof(s->internal));
|
||||
COPY(macsrifle.x);
|
||||
COPY(macsrifle.y);
|
||||
COPY(macsrifle.buttons);
|
||||
|
||||
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
|
||||
|
||||
#undef COPY
|
||||
|
||||
@ -3590,6 +3759,15 @@ 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
|
||||
}
|
||||
|
||||
@ -3708,3 +3886,30 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -173,7 +188,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_
|
||||
@ -185,8 +200,9 @@
|
||||
#define S9xButtonJustifier 4
|
||||
#define S9xButtonCommand 5
|
||||
#define S9xButtonMulti 6
|
||||
#define S9xAxisJoypad 7
|
||||
#define S9xPointer 8
|
||||
#define S9xButtonMacsRifle 7
|
||||
#define S9xAxisJoypad 8
|
||||
#define S9xPointer 9
|
||||
|
||||
#define S9xButtonPseudopointer 254
|
||||
#define S9xAxisPseudopointer 253
|
||||
@ -259,6 +275,11 @@ 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;
|
||||
@ -296,6 +317,7 @@ typedef struct
|
||||
uint16 aim_scope:1;
|
||||
uint16 aim_justifier0:1;
|
||||
uint16 aim_justifier1:1;
|
||||
uint16 aim_macsrifle:1;
|
||||
} pointer;
|
||||
|
||||
uint8 port[4];
|
||||
@ -315,7 +337,8 @@ 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_MP5, // use id1-id4 to specify pad 0-7 (or -1)
|
||||
CTL_MACSRIFLE
|
||||
};
|
||||
|
||||
void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); // port=0-1
|
||||
@ -445,6 +468,7 @@ 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);
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -208,12 +223,14 @@ 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 = -1;
|
||||
CPU.PrevCycles = CPU.Cycles;
|
||||
CPU.V_Counter = 0;
|
||||
CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG);
|
||||
CPU.PCBase = NULL;
|
||||
CPU.IRQActive = FALSE;
|
||||
CPU.IRQPending = 0;
|
||||
CPU.NMIPending = FALSE;
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
CPU.IRQExternal = FALSE;
|
||||
CPU.MemSpeed = SLOW_ONE_CYCLE;
|
||||
CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
|
||||
CPU.FastROMSpeed = SLOW_ONE_CYCLE;
|
||||
@ -226,9 +243,6 @@ 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;
|
||||
|
||||
@ -252,6 +266,9 @@ 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
|
||||
@ -261,7 +278,6 @@ static void S9xSoftResetCPU (void)
|
||||
|
||||
ICPU.S9xOpcodes = S9xOpcodesE1;
|
||||
ICPU.S9xOpLengths = S9xOpLengthsM1X1;
|
||||
ICPU.CPUExecuting = TRUE;
|
||||
|
||||
S9xUnpackStatus();
|
||||
}
|
||||
@ -273,11 +289,9 @@ void S9xReset (void)
|
||||
|
||||
memset(Memory.RAM, 0x55, 0x20000);
|
||||
memset(Memory.VRAM, 0x00, 0x10000);
|
||||
ZeroMemory(Memory.FillRAM, 0x8000);
|
||||
memset(Memory.FillRAM, 0, 0x8000);
|
||||
|
||||
if (Settings.BS)
|
||||
S9xResetBSX();
|
||||
|
||||
S9xResetCPU();
|
||||
S9xResetPPU();
|
||||
S9xResetDMA();
|
||||
@ -310,7 +324,7 @@ void S9xSoftReset (void)
|
||||
{
|
||||
S9xResetSaveTimer(FALSE);
|
||||
|
||||
ZeroMemory(Memory.FillRAM, 0x8000);
|
||||
memset(Memory.FillRAM, 0, 0x8000);
|
||||
|
||||
if (Settings.BS)
|
||||
S9xResetBSX();
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -287,6 +302,8 @@ static inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) // (a,X)
|
||||
static inline uint32 AbsoluteIndexedIndirect (AccessMode a) // (a,X)
|
||||
{
|
||||
uint16 addr = Immediate16Slow(READ);
|
||||
|
||||
AddCycles(ONE_CYCLE);
|
||||
addr += Registers.X.W;
|
||||
|
||||
// Address load wraps within the bank
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -187,29 +202,79 @@
|
||||
#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.Flags)
|
||||
{
|
||||
if (CPU.Flags & NMI_FLAG)
|
||||
if (CPU.NMIPending)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
if (Settings.TraceHCEvent)
|
||||
S9xTraceFormattedMessage ("Comparing %d to %d\n", Timings.NMITriggerPos, CPU.Cycles);
|
||||
#endif
|
||||
if (Timings.NMITriggerPos <= CPU.Cycles)
|
||||
{
|
||||
CPU.Flags &= ~NMI_FLAG;
|
||||
CPU.NMIPending = FALSE;
|
||||
Timings.NMITriggerPos = 0xffff;
|
||||
if (CPU.WaitingForInterrupt)
|
||||
{
|
||||
CPU.WaitingForInterrupt = FALSE;
|
||||
Registers.PCw++;
|
||||
CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
|
||||
while (CPU.Cycles >= CPU.NextEvent)
|
||||
S9xDoHEventProcessing();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
/* 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))
|
||||
{
|
||||
@ -226,36 +291,7 @@ void S9xMainLoop (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
#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 &= ~IRQ_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
if (CPU.Flags & SCAN_KEYS_FLAG)
|
||||
break;
|
||||
|
||||
#ifdef DEBUGGER
|
||||
if (CPU.Flags & DEBUG_MODE_FLAG)
|
||||
break;
|
||||
|
||||
@ -268,17 +304,13 @@ void S9xMainLoop (void)
|
||||
CPU.Flags |= DEBUG_MODE_FLAG;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#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];
|
||||
@ -304,13 +336,8 @@ void S9xMainLoop (void)
|
||||
Registers.PCw++;
|
||||
(*Opcodes[Op].S9xOpcode)();
|
||||
|
||||
if (SA1.Executing)
|
||||
if (Settings.SA1)
|
||||
S9xSA1MainLoop();
|
||||
|
||||
#if (S9X_ACCURACY_LEVEL <= 2)
|
||||
while (CPU.Cycles >= CPU.NextEvent)
|
||||
S9xDoHEventProcessing();
|
||||
#endif
|
||||
}
|
||||
|
||||
S9xPackStatus();
|
||||
@ -325,76 +352,70 @@ void S9xMainLoop (void)
|
||||
}
|
||||
}
|
||||
|
||||
void S9xSetIRQ (uint32 source)
|
||||
static inline void S9xReschedule (void)
|
||||
{
|
||||
CPU.IRQActive |= source;
|
||||
CPU.IRQPending = Timings.IRQPendCount;
|
||||
CPU.Flags |= IRQ_FLAG;
|
||||
|
||||
if (CPU.WaitingForInterrupt)
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
// Force IRQ to trigger immediately after WAI -
|
||||
// Final Fantasy Mystic Quest crashes without this.
|
||||
CPU.WaitingForInterrupt = FALSE;
|
||||
Registers.PCw++;
|
||||
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;
|
||||
}
|
||||
|
||||
#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[13][32] =
|
||||
static char eventname[7][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_IRQ_9_A_EVENT ",
|
||||
"HC_WRAM_REFRESH_EVENT",
|
||||
"HC_IRQ_A_1_EVENT "
|
||||
"HC_WRAM_REFRESH_EVENT"
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGGER
|
||||
if (Settings.TraceHCEvent)
|
||||
S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d",
|
||||
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
|
||||
#endif
|
||||
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitCounter++;
|
||||
S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d VC:%04d",
|
||||
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles, CPU.V_Counter);
|
||||
#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)
|
||||
@ -417,10 +438,11 @@ void S9xDoHEventProcessing (void)
|
||||
|
||||
S9xAPUEndScanline();
|
||||
CPU.Cycles -= Timings.H_Max;
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
|
||||
if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
|
||||
if (Timings.NMITriggerPos != 0xffff)
|
||||
Timings.NMITriggerPos -= Timings.H_Max;
|
||||
if (Timings.NextIRQTimer != 0x0fffffff)
|
||||
Timings.NextIRQTimer -= Timings.H_Max;
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
|
||||
CPU.V_Counter++;
|
||||
if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
|
||||
@ -445,12 +467,9 @@ 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:
|
||||
@ -477,11 +496,12 @@ 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
|
||||
@ -511,9 +531,13 @@ 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.Flags |= NMI_FLAG;
|
||||
CPU.NMIPending = TRUE;
|
||||
Timings.NMITriggerPos = 6 + 6;
|
||||
}
|
||||
|
||||
@ -528,13 +552,11 @@ 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)
|
||||
@ -551,7 +573,6 @@ 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;
|
||||
@ -561,28 +582,11 @@ 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
|
||||
@ -591,4 +595,3 @@ void S9xDoHEventProcessing (void)
|
||||
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -179,6 +194,9 @@
|
||||
#define _CPUEXEC_H_
|
||||
|
||||
#include "ppu.h"
|
||||
#ifdef DEBUGGER
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
struct SOpcodes
|
||||
{
|
||||
@ -193,7 +211,6 @@ struct SICPU
|
||||
uint8 _Zero;
|
||||
uint8 _Negative;
|
||||
uint8 _Overflow;
|
||||
bool8 CPUExecuting;
|
||||
uint32 ShiftedPB;
|
||||
uint32 ShiftedDB;
|
||||
uint32 Frame;
|
||||
@ -217,8 +234,6 @@ void S9xMainLoop (void);
|
||||
void S9xReset (void);
|
||||
void S9xSoftReset (void);
|
||||
void S9xDoHEventProcessing (void);
|
||||
void S9xClearIRQ (uint32);
|
||||
void S9xSetIRQ (uint32);
|
||||
|
||||
static inline void S9xUnpackStatus (void)
|
||||
{
|
||||
@ -270,84 +285,4 @@ 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
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -280,7 +295,6 @@ static void Op##OP (void) \
|
||||
S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \
|
||||
else \
|
||||
Registers.PCw = newPC.W; \
|
||||
CPUShutdown(); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -515,9 +529,6 @@ 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);
|
||||
@ -527,9 +538,6 @@ 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);
|
||||
@ -551,9 +559,6 @@ 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);
|
||||
@ -563,9 +568,6 @@ 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);
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -188,13 +203,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef SA1_OPCODES
|
||||
#define AddCycles(n) { }
|
||||
#define AddCycles(n) { SA1.Cycles += (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"
|
||||
@ -659,9 +670,6 @@ 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);
|
||||
}
|
||||
@ -669,9 +677,6 @@ 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);
|
||||
}
|
||||
@ -679,9 +684,6 @@ static void Op3AM0 (void)
|
||||
static void Op3ASlow (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
if (CheckMemory())
|
||||
{
|
||||
@ -813,9 +815,6 @@ 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);
|
||||
}
|
||||
@ -823,9 +822,6 @@ 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);
|
||||
}
|
||||
@ -833,9 +829,6 @@ static void Op1AM0 (void)
|
||||
static void Op1ASlow (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
if (CheckMemory())
|
||||
{
|
||||
@ -1550,54 +1543,6 @@ 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)
|
||||
@ -1690,16 +1635,25 @@ static void OpF8 (void)
|
||||
// CLI
|
||||
static void Op58 (void)
|
||||
{
|
||||
ClearIRQ();
|
||||
AddCycles(ONE_CYCLE);
|
||||
//CHECK_FOR_IRQ();
|
||||
|
||||
#ifndef SA1_OPCODES
|
||||
Timings.IRQFlagChanging = IRQ_CLEAR_FLAG;
|
||||
#else
|
||||
ClearIRQ();
|
||||
#endif
|
||||
}
|
||||
|
||||
// SEI
|
||||
static void Op78 (void)
|
||||
{
|
||||
SetIRQ();
|
||||
AddCycles(ONE_CYCLE);
|
||||
|
||||
#ifndef SA1_OPCODES
|
||||
Timings.IRQFlagChanging = IRQ_SET_FLAG;
|
||||
#else
|
||||
SetIRQ();
|
||||
#endif
|
||||
}
|
||||
|
||||
// CLV
|
||||
@ -1714,9 +1668,6 @@ static void OpB8 (void)
|
||||
static void OpCAX1 (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
Registers.XL--;
|
||||
SetZN(Registers.XL);
|
||||
}
|
||||
@ -1724,9 +1675,6 @@ 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);
|
||||
}
|
||||
@ -1734,9 +1682,6 @@ static void OpCAX0 (void)
|
||||
static void OpCASlow (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
if (CheckIndex())
|
||||
{
|
||||
@ -1753,9 +1698,6 @@ static void OpCASlow (void)
|
||||
static void Op88X1 (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
Registers.YL--;
|
||||
SetZN(Registers.YL);
|
||||
}
|
||||
@ -1763,9 +1705,6 @@ 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);
|
||||
}
|
||||
@ -1773,9 +1712,6 @@ static void Op88X0 (void)
|
||||
static void Op88Slow (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
if (CheckIndex())
|
||||
{
|
||||
@ -1794,9 +1730,6 @@ static void Op88Slow (void)
|
||||
static void OpE8X1 (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
Registers.XL++;
|
||||
SetZN(Registers.XL);
|
||||
}
|
||||
@ -1804,9 +1737,6 @@ 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);
|
||||
}
|
||||
@ -1814,9 +1744,6 @@ static void OpE8X0 (void)
|
||||
static void OpE8Slow (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
if (CheckIndex())
|
||||
{
|
||||
@ -1833,9 +1760,6 @@ static void OpE8Slow (void)
|
||||
static void OpC8X1 (void)
|
||||
{
|
||||
AddCycles(ONE_CYCLE);
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
Registers.YL++;
|
||||
SetZN(Registers.YL);
|
||||
}
|
||||
@ -1843,9 +1767,6 @@ 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);
|
||||
}
|
||||
@ -1853,18 +1774,15 @@ 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);
|
||||
}
|
||||
}
|
||||
@ -2371,7 +2289,7 @@ static void Op28E1 (void)
|
||||
SetFlags(MemoryFlag | IndexFlag);
|
||||
S9xUnpackStatus();
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
static void Op28E0 (void)
|
||||
@ -2388,7 +2306,7 @@ static void Op28E0 (void)
|
||||
}
|
||||
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
static void Op28Slow (void)
|
||||
@ -2416,7 +2334,7 @@ static void Op28Slow (void)
|
||||
}
|
||||
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
// PLX
|
||||
@ -2985,7 +2903,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] & 0x20))
|
||||
if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10))
|
||||
{
|
||||
OpenBus = Memory.FillRAM[0x220d];
|
||||
AddCycles(2 * SLOW_ONE_CYCLE);
|
||||
@ -3069,17 +2987,11 @@ 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)
|
||||
@ -3425,7 +3337,7 @@ static void OpC2 (void)
|
||||
}
|
||||
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
static void OpC2Slow (void)
|
||||
@ -3454,7 +3366,7 @@ static void OpC2Slow (void)
|
||||
}
|
||||
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
static void OpE2 (void)
|
||||
@ -3562,7 +3474,7 @@ static void Op40Slow (void)
|
||||
}
|
||||
|
||||
S9xFixCycles();
|
||||
//CHECK_FOR_IRQ();
|
||||
CHECK_FOR_IRQ();
|
||||
}
|
||||
|
||||
/* STP/WAI ***************************************************************** */
|
||||
@ -3570,44 +3482,16 @@ 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--;
|
||||
#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
|
||||
{
|
||||
#else
|
||||
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);
|
||||
AddCycles(ONE_CYCLE);
|
||||
#endif
|
||||
}
|
||||
#endif // SA1_OPCODES
|
||||
}
|
||||
|
||||
// STP
|
||||
@ -3650,7 +3534,7 @@ static void Op42 (void)
|
||||
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf);
|
||||
if (trace != NULL)
|
||||
fclose(trace);
|
||||
trace = fopen("WDMtrace.log", "ab");
|
||||
ENSURE_TRACE_OPEN(trace, "WDMtrace.log", "ab")
|
||||
}
|
||||
|
||||
break;
|
||||
@ -4024,4 +3908,3 @@ struct SOpcodes S9xOpcodesSlow[256] =
|
||||
{ OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow },
|
||||
{ OpFFSlow }
|
||||
};
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -181,8 +196,9 @@
|
||||
void S9xOpcode_NMI (void);
|
||||
void S9xOpcode_IRQ (void);
|
||||
|
||||
#define CHECK_FOR_IRQ() \
|
||||
if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \
|
||||
S9xOpcode_IRQ()
|
||||
|
||||
#ifndef SA1_OPCODES
|
||||
#define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); }
|
||||
#else
|
||||
#define CHECK_FOR_IRQ() {}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -185,7 +200,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];
|
||||
@ -598,7 +613,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);
|
||||
@ -633,7 +648,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2100 + d->BAddress);
|
||||
@ -643,7 +658,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 2:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -653,7 +668,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 3:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -682,7 +697,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -692,7 +707,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 2:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2102 + d->BAddress);
|
||||
@ -702,7 +717,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 3:
|
||||
Work = S9xGetByte((d->ABank << 16) + p);
|
||||
S9xSetPPU(Work, 0x2103 + d->BAddress);
|
||||
@ -741,9 +756,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
break;
|
||||
|
||||
case 0x18: // VMDATAL
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
do
|
||||
@ -766,9 +778,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
break;
|
||||
|
||||
case 0x19: // VMDATAH
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
do
|
||||
@ -837,9 +846,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
if (d->BAddress == 0x18)
|
||||
{
|
||||
// VMDATAL
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
switch (b)
|
||||
@ -851,10 +857,10 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
REGISTER_2118_linear(Work);
|
||||
UPDATE_COUNTERS;
|
||||
count--;
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = *(base + p);
|
||||
REGISTER_2119_linear(Work);
|
||||
OpenBus = *(base + p);
|
||||
REGISTER_2119_linear(OpenBus);
|
||||
UPDATE_COUNTERS;
|
||||
count--;
|
||||
}
|
||||
@ -881,7 +887,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
REGISTER_2118_tile(Work);
|
||||
UPDATE_COUNTERS;
|
||||
count--;
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = *(base + p);
|
||||
REGISTER_2119_tile(Work);
|
||||
@ -913,7 +919,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);
|
||||
@ -949,7 +955,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2100 + d->BAddress);
|
||||
@ -959,7 +965,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 2:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -969,7 +975,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 3:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -998,7 +1004,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 1:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
@ -1008,7 +1014,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 2:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2102 + d->BAddress);
|
||||
@ -1018,7 +1024,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
b = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case 3:
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2103 + d->BAddress);
|
||||
@ -1282,11 +1288,9 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
}
|
||||
}
|
||||
|
||||
if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff))
|
||||
if (CPU.NMIPending && (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
|
||||
@ -1373,9 +1377,6 @@ static inline bool8 HDMAReadLineCount (int d)
|
||||
|
||||
void S9xStartHDMA (void)
|
||||
{
|
||||
if (Settings.DisableHDMA)
|
||||
PPU.HDMA = 0;
|
||||
else
|
||||
PPU.HDMA = Memory.FillRAM[0x420c];
|
||||
|
||||
#ifdef DEBUGGER
|
||||
@ -1420,13 +1421,14 @@ void S9xStartHDMA (void)
|
||||
|
||||
uint8 S9xDoHDMA (uint8 byte)
|
||||
{
|
||||
struct SDMA *p = &DMA[0];
|
||||
struct SDMA *p;
|
||||
|
||||
uint32 ShiftedIBank;
|
||||
uint16 IAddr;
|
||||
bool8 temp;
|
||||
int32 tmpch;
|
||||
int d = 0;
|
||||
int d;
|
||||
uint8 mask;
|
||||
|
||||
CPU.InHDMA = TRUE;
|
||||
CPU.InDMAorHDMA = TRUE;
|
||||
@ -1437,7 +1439,7 @@ uint8 S9xDoHDMA (uint8 byte)
|
||||
// XXX: Not quite right...
|
||||
ADD_CYCLES(Timings.DMACPUSync);
|
||||
|
||||
for (uint8 mask = 1; mask; mask <<= 1, p++, d++)
|
||||
for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, p++, d++)
|
||||
{
|
||||
if (byte & mask)
|
||||
{
|
||||
@ -1639,7 +1641,10 @@ uint8 S9xDoHDMA (uint8 byte)
|
||||
case 1:
|
||||
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
|
||||
ADD_CYCLES(SLOW_ONE_CYCLE);
|
||||
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
|
||||
// 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);
|
||||
ADD_CYCLES(SLOW_ONE_CYCLE);
|
||||
HDMAMemPointers[d] += 2;
|
||||
break;
|
||||
@ -1752,7 +1757,16 @@ 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
|
||||
@ -1768,7 +1782,6 @@ uint8 S9xDoHDMA (uint8 byte)
|
||||
byte &= ~mask;
|
||||
PPU.HDMAEnded |= mask;
|
||||
p->DoTransfer = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -199,10 +214,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) (Settings.SuperFXSpeedPerLine * ((1.0f / Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
|
||||
SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
|
||||
SuperFX.oneLineDone = FALSE;
|
||||
SuperFX.vFlags = 0;
|
||||
CPU.IRQExternal = FALSE;
|
||||
FxReset(&SuperFX);
|
||||
}
|
||||
|
||||
@ -300,13 +315,10 @@ uint8 S9xGetSuperFX (uint16 address)
|
||||
uint8 byte;
|
||||
|
||||
byte = Memory.FillRAM[address];
|
||||
#ifdef CPU_SHUTDOWN
|
||||
if (address == 0x3030)
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
if (address == 0x3031)
|
||||
{
|
||||
S9xClearIRQ(GSU_IRQ_SOURCE);
|
||||
CPU.IRQExternal = FALSE;
|
||||
Memory.FillRAM[0x3031] = byte & 0x7f;
|
||||
}
|
||||
|
||||
@ -317,11 +329,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);
|
||||
FxEmulate(((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine) * Settings.SuperFXClockMultiplier / 100);
|
||||
|
||||
uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8);
|
||||
if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ)
|
||||
S9xSetIRQ(GSU_IRQ_SOURCE);
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -188,8 +203,6 @@
|
||||
#include "bsx.h"
|
||||
#include "msu1.h"
|
||||
|
||||
#if (S9X_ACCURACY_LEVEL >= 2)
|
||||
|
||||
#define addCyclesInMemoryAccess \
|
||||
if (!CPU.InDMAorHDMA) \
|
||||
{ \
|
||||
@ -206,18 +219,6 @@
|
||||
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)
|
||||
@ -248,10 +249,6 @@ 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);
|
||||
@ -348,42 +345,39 @@ 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;
|
||||
|
||||
OpenBus = S9xGetByte(Address);
|
||||
word = OpenBus = S9xGetByte(Address);
|
||||
|
||||
switch (w)
|
||||
{
|
||||
case WRAP_PAGE:
|
||||
a.xPBPC = Address;
|
||||
a.B.xPCl++;
|
||||
return (OpenBus | (S9xGetByte(a.xPBPC) << 8));
|
||||
return (word | (S9xGetByte(a.xPBPC) << 8));
|
||||
|
||||
case WRAP_BANK:
|
||||
a.xPBPC = Address;
|
||||
a.W.xPC++;
|
||||
return (OpenBus | (S9xGetByte(a.xPBPC) << 8));
|
||||
return (word | (S9xGetByte(a.xPBPC) << 8));
|
||||
|
||||
case WRAP_NONE:
|
||||
default:
|
||||
return (OpenBus | (S9xGetByte(Address + 1) << 8));
|
||||
return (word | (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);
|
||||
@ -401,8 +395,8 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
|
||||
case CMemory::MAP_PPU:
|
||||
if (CPU.InDMAorHDMA)
|
||||
{
|
||||
OpenBus = S9xGetByte(Address);
|
||||
return (OpenBus | (S9xGetByte(Address + 1) << 8));
|
||||
word = OpenBus = S9xGetByte(Address);
|
||||
return (word | (S9xGetByte(Address + 1) << 8));
|
||||
}
|
||||
|
||||
word = S9xGetPPU(Address & 0xffff);
|
||||
@ -511,33 +505,14 @@ 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;
|
||||
}
|
||||
|
||||
@ -594,7 +569,6 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
|
||||
|
||||
case CMemory::MAP_SA1RAM:
|
||||
*(Memory.SRAM + (Address & 0xffff)) = Byte;
|
||||
SA1.Executing = !SA1.Waiting;
|
||||
addCyclesInMemoryAccess;
|
||||
return;
|
||||
|
||||
@ -671,33 +645,14 @@ 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;
|
||||
}
|
||||
|
||||
@ -807,7 +762,6 @@ 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;
|
||||
|
||||
@ -931,8 +885,7 @@ inline void S9xSetPCBase (uint32 Address)
|
||||
Registers.PBPC = Address & 0xffffff;
|
||||
ICPU.ShiftedPB = Address & 0xff0000;
|
||||
|
||||
int block;
|
||||
uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)];
|
||||
uint8 *GetAddress = Memory.Map[(int)((Address & 0xffffff) >> MEMMAP_SHIFT)];
|
||||
|
||||
CPU.MemSpeed = memory_speed(Address);
|
||||
CPU.MemSpeedx2 = CPU.MemSpeed << 1;
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -215,7 +230,7 @@ static uint16 get_crosshair_color (uint8);
|
||||
bool8 S9xGraphicsInit (void)
|
||||
{
|
||||
S9xInitTileRenderer();
|
||||
ZeroMemory(BlackColourMap, 256 * sizeof(uint16));
|
||||
memset(BlackColourMap, 0, 256 * sizeof(uint16));
|
||||
|
||||
#ifdef GFX_MULTI_FORMAT
|
||||
if (GFX.BuildPixel == NULL)
|
||||
@ -226,9 +241,9 @@ bool8 S9xGraphicsInit (void)
|
||||
GFX.InterlaceFrame = 0;
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
IPPU.DirectColourMapsNeedRebuild = TRUE;
|
||||
Settings.BG_Forced = 0;
|
||||
S9xFixColourBrightness();
|
||||
S9xBuildDirectColourMaps();
|
||||
|
||||
GFX.X2 = (uint16 *) malloc(sizeof(uint16) * 0x10000);
|
||||
GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000);
|
||||
@ -245,7 +260,7 @@ bool8 S9xGraphicsInit (void)
|
||||
}
|
||||
|
||||
// Lookup table for color addition
|
||||
ZeroMemory(GFX.X2, 0x10000 * sizeof(uint16));
|
||||
memset(GFX.X2, 0, 0x10000 * sizeof(uint16));
|
||||
for (uint32 r = 0; r <= MAX_RED; r++)
|
||||
{
|
||||
uint32 r2 = r << 1;
|
||||
@ -271,7 +286,7 @@ bool8 S9xGraphicsInit (void)
|
||||
}
|
||||
|
||||
// Lookup table for 1/2 color subtraction
|
||||
ZeroMemory(GFX.ZERO, 0x10000 * sizeof(uint16));
|
||||
memset(GFX.ZERO, 0, 0x10000 * sizeof(uint16));
|
||||
for (uint32 r = 0; r <= MAX_RED; r++)
|
||||
{
|
||||
uint32 r2 = r;
|
||||
@ -321,15 +336,14 @@ void S9xBuildDirectColourMaps (void)
|
||||
for (uint32 p = 0; p < 8; p++)
|
||||
for (uint32 c = 0; c < 256; c++)
|
||||
DirectColourMaps[p][c] = BUILD_PIXEL(IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)], IPPU.XB[((c & 0x38) >> 1) | (p & 2)], IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]);
|
||||
|
||||
IPPU.DirectColourMapsNeedRebuild = FALSE;
|
||||
}
|
||||
|
||||
void S9xStartScreenRefresh (void)
|
||||
{
|
||||
GFX.InterlaceFrame = !GFX.InterlaceFrame;
|
||||
|
||||
if (IPPU.RenderThisFrame)
|
||||
{
|
||||
GFX.InterlaceFrame = !GFX.InterlaceFrame;
|
||||
if (!GFX.DoInterlace || !GFX.InterlaceFrame)
|
||||
{
|
||||
if (!S9xInitUpdate())
|
||||
@ -361,6 +375,7 @@ void S9xStartScreenRefresh (void)
|
||||
else
|
||||
#endif
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH;
|
||||
}
|
||||
@ -386,8 +401,8 @@ void S9xStartScreenRefresh (void)
|
||||
PPU.RecomputeClipWindows = TRUE;
|
||||
IPPU.PreviousLine = IPPU.CurrentLine = 0;
|
||||
|
||||
ZeroMemory(GFX.ZBuffer, GFX.ScreenSize);
|
||||
ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize);
|
||||
memset(GFX.ZBuffer, 0, GFX.ScreenSize);
|
||||
memset(GFX.SubZBuffer, 0, GFX.ScreenSize);
|
||||
}
|
||||
|
||||
if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
|
||||
@ -438,7 +453,7 @@ void S9xEndScreenRefresh (void)
|
||||
else
|
||||
S9xControlEOF();
|
||||
|
||||
S9xApplyCheats();
|
||||
S9xUpdateCheatsInMemory ();
|
||||
|
||||
#ifdef DEBUGGER
|
||||
if (CPU.Flags & FRAME_ADVANCE_FLAG)
|
||||
@ -692,7 +707,6 @@ void S9xUpdateScreen (void)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Have to back out of the regular speed hack
|
||||
for (register uint32 y = 0; y < GFX.StartY; y++)
|
||||
{
|
||||
@ -702,31 +716,20 @@ void S9xUpdateScreen (void)
|
||||
for (register int x = 255; x >= 0; x--, p--, q -= 2)
|
||||
*q = *(q + 1) = *p;
|
||||
}
|
||||
}
|
||||
|
||||
IPPU.DoubleWidthPixels = TRUE;
|
||||
IPPU.RenderedScreenWidth = 512;
|
||||
}
|
||||
|
||||
if (!IPPU.DoubleHeightPixels && IPPU.Interlace)
|
||||
if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6))
|
||||
{
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
GFX.DoInterlace = 2;
|
||||
|
||||
for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
|
||||
memmove(GFX.Screen + y * GFX.PPL, GFX.Screen + y * GFX.RealPPL, IPPU.RenderedScreenWidth * sizeof(uint16));
|
||||
}
|
||||
else if (IPPU.DoubleHeightPixels && !IPPU.Interlace)
|
||||
{
|
||||
for (register int32 y = 0; y < (int32) GFX.StartY; y++)
|
||||
memmove(GFX.Screen + y * GFX.RealPPL, GFX.Screen + y * GFX.PPL, IPPU.RenderedScreenWidth * sizeof(uint16));
|
||||
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
GFX.PPL = GFX.RealPPL;
|
||||
GFX.DoInterlace = 0;
|
||||
for (register int32 y = (int32) GFX.StartY - 2; y >= 0; y--)
|
||||
memmove(GFX.Screen + (y + 1) * GFX.PPL, GFX.Screen + y * GFX.RealPPL, GFX.PPL * sizeof(uint16));
|
||||
}
|
||||
}
|
||||
|
||||
@ -819,12 +822,12 @@ static void SetupOBJ (void)
|
||||
if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case
|
||||
{
|
||||
uint8 LineOBJ[SNES_HEIGHT_EXTENDED];
|
||||
ZeroMemory(LineOBJ, sizeof(LineOBJ));
|
||||
memset(LineOBJ, 0, sizeof(LineOBJ));
|
||||
|
||||
for (int i = 0; i < SNES_HEIGHT_EXTENDED; i++)
|
||||
{
|
||||
GFX.OBJLines[i].RTOFlags = 0;
|
||||
GFX.OBJLines[i].Tiles = 34;
|
||||
GFX.OBJLines[i].Tiles = Settings.MaxSpriteTilesPerLine;
|
||||
for (int j = 0; j < 32; j++)
|
||||
GFX.OBJLines[i].OBJ[j].Sprite = -1;
|
||||
}
|
||||
@ -896,7 +899,13 @@ static void SetupOBJ (void)
|
||||
{
|
||||
// First, find out which sprites are on which lines
|
||||
uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128];
|
||||
ZeroMemory(OBJOnLine, sizeof(OBJOnLine));
|
||||
// memset(OBJOnLine, 0, sizeof(OBJOnLine));
|
||||
/* Hold on here, that's a lot of bytes to initialise at once!
|
||||
* So we only initialise them per line, as needed. [Neb]
|
||||
* Bonus: We can quickly avoid looping if a line has no OBJs.
|
||||
*/
|
||||
bool8 AnyOBJOnLine[SNES_HEIGHT_EXTENDED];
|
||||
memset(AnyOBJOnLine, FALSE, sizeof(AnyOBJOnLine)); // better
|
||||
|
||||
for (S = 0; S < 128; S++)
|
||||
{
|
||||
@ -930,6 +939,11 @@ static void SetupOBJ (void)
|
||||
if (Y >= SNES_HEIGHT_EXTENDED)
|
||||
continue;
|
||||
|
||||
if (!AnyOBJOnLine[Y]) {
|
||||
memset(OBJOnLine[Y], 0, sizeof(OBJOnLine[Y]));
|
||||
AnyOBJOnLine[Y] = TRUE;
|
||||
}
|
||||
|
||||
if (PPU.OBJ[S].VFlip)
|
||||
// Yes, Width not Height. It so happens that the
|
||||
// sprites with H=2*W flip as two WxW sprites.
|
||||
@ -945,12 +959,14 @@ static void SetupOBJ (void)
|
||||
for (int Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++)
|
||||
{
|
||||
GFX.OBJLines[Y].RTOFlags = Y ? GFX.OBJLines[Y - 1].RTOFlags : 0;
|
||||
GFX.OBJLines[Y].Tiles = 34;
|
||||
GFX.OBJLines[Y].Tiles = Settings.MaxSpriteTilesPerLine;
|
||||
|
||||
uint8 FirstSprite = (PPU.FirstSprite + Y) & 0x7f;
|
||||
S = FirstSprite;
|
||||
j = 0;
|
||||
|
||||
if (AnyOBJOnLine[Y])
|
||||
{
|
||||
do
|
||||
{
|
||||
if (OBJOnLine[Y][S])
|
||||
@ -970,6 +986,7 @@ static void SetupOBJ (void)
|
||||
|
||||
S = (S + 1) & 0x7f;
|
||||
} while (S != FirstSprite);
|
||||
}
|
||||
|
||||
if (j < 32)
|
||||
GFX.OBJLines[Y].OBJ[j].Sprite = -1;
|
||||
@ -979,6 +996,8 @@ static void SetupOBJ (void)
|
||||
IPPU.OBJChanged = FALSE;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("no-tree-vrp")
|
||||
static void DrawOBJS (int D)
|
||||
{
|
||||
void (*DrawTile) (uint32, uint32, uint32, uint32) = NULL;
|
||||
@ -1071,6 +1090,8 @@ static void DrawOBJS (int D)
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
|
||||
static void DrawBackground (int bg, uint8 Zh, uint8 Zl)
|
||||
{
|
||||
@ -1329,8 +1350,8 @@ static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl)
|
||||
for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic)
|
||||
{
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
|
||||
uint32 HOffset = LineData[Y].BG[bg].HOffset;
|
||||
uint32 VOffset = LineData[Y + MosaicStart].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
|
||||
uint32 HOffset = LineData[Y + MosaicStart].BG[bg].HOffset;
|
||||
|
||||
Lines = PPU.Mosaic - MosaicStart;
|
||||
if (Y + MosaicStart + Lines > GFX.EndY)
|
||||
@ -1493,7 +1514,6 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
bool8 HiresInterlace = IPPU.Interlace && IPPU.DoubleWidthPixels;
|
||||
|
||||
void (*DrawTile) (uint32, uint32, uint32, uint32);
|
||||
void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32);
|
||||
|
||||
for (int clip = 0; clip < GFX.Clip[bg].Count; clip++)
|
||||
@ -1502,12 +1522,10 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
|
||||
if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2))
|
||||
{
|
||||
DrawTile = GFX.DrawTileMath;
|
||||
DrawClippedTile = GFX.DrawClippedTileMath;
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTile = GFX.DrawTileNomath;
|
||||
DrawClippedTile = GFX.DrawClippedTileNomath;
|
||||
}
|
||||
|
||||
@ -1539,8 +1557,8 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
uint32 Left = GFX.Clip[bg].Left[clip];
|
||||
uint32 Right = GFX.Clip[bg].Right[clip];
|
||||
uint32 Offset = Left * PixWidth + Y * GFX.PPL;
|
||||
uint32 LineHOffset = LineData[Y].BG[bg].HOffset;
|
||||
bool8 left_edge = (Left < (8 - (LineHOffset & 7)));
|
||||
uint32 HScroll = LineData[Y].BG[bg].HOffset;
|
||||
bool8 left_edge = (Left < (8 - (HScroll & 7)));
|
||||
uint32 Width = Right - Left;
|
||||
|
||||
while (Left < Right)
|
||||
@ -1551,7 +1569,7 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
{
|
||||
// SNES cannot do OPT for leftmost tile column
|
||||
VOffset = LineData[Y].BG[bg].VOffset;
|
||||
HOffset = LineHOffset;
|
||||
HOffset = HScroll;
|
||||
left_edge = FALSE;
|
||||
}
|
||||
else
|
||||
@ -1595,9 +1613,9 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
VOffset = LineData[Y].BG[bg].VOffset;
|
||||
|
||||
if (HCellOffset & OffsetEnableMask)
|
||||
HOffset = (HCellOffset & ~7) | (LineHOffset & 7);
|
||||
HOffset = (HCellOffset & ~7) | (HScroll & 7);
|
||||
else
|
||||
HOffset = LineHOffset;
|
||||
HOffset = HScroll;
|
||||
}
|
||||
|
||||
if (HiresInterlace)
|
||||
@ -1719,7 +1737,6 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
int Lines;
|
||||
int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff;
|
||||
int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3;
|
||||
int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff;
|
||||
int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3;
|
||||
int OffsetEnableMask = 0x2000 << bg;
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
@ -1741,8 +1758,8 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic)
|
||||
{
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 : Y;
|
||||
uint32 VOff = LineData[Y].BG[2].VOffset - 1;
|
||||
uint32 HOff = LineData[Y].BG[2].HOffset;
|
||||
uint32 VOff = LineData[Y + MosaicStart].BG[2].VOffset - 1;
|
||||
uint32 HOff = LineData[Y + MosaicStart].BG[2].HOffset;
|
||||
|
||||
Lines = PPU.Mosaic - MosaicStart;
|
||||
if (Y + MosaicStart + Lines > GFX.EndY)
|
||||
@ -1771,24 +1788,22 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
uint32 Left = GFX.Clip[bg].Left[clip];
|
||||
uint32 Right = GFX.Clip[bg].Right[clip];
|
||||
uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL;
|
||||
uint32 LineHOffset = LineData[Y].BG[bg].HOffset;
|
||||
bool8 left_edge = (Left < (8 - (LineHOffset & 7)));
|
||||
uint32 HScroll = LineData[Y + MosaicStart].BG[bg].HOffset;
|
||||
uint32 Width = Right - Left;
|
||||
|
||||
while (Left < Right)
|
||||
{
|
||||
uint32 VOffset, HOffset;
|
||||
|
||||
if (left_edge)
|
||||
if (Left < (8 - (HScroll & 7)))
|
||||
{
|
||||
// SNES cannot do OPT for leftmost tile column
|
||||
VOffset = LineData[Y].BG[bg].VOffset;
|
||||
HOffset = LineHOffset;
|
||||
left_edge = FALSE;
|
||||
VOffset = LineData[Y + MosaicStart].BG[bg].VOffset;
|
||||
HOffset = HScroll;
|
||||
}
|
||||
else
|
||||
{
|
||||
int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3;
|
||||
int HOffTile = (((Left + (HScroll & 7)) - 8) + (HOff & ~7)) >> 3;
|
||||
|
||||
if (BG.OffsetSizeH == 8)
|
||||
{
|
||||
@ -1824,12 +1839,12 @@ static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
if (VCellOffset & OffsetEnableMask)
|
||||
VOffset = VCellOffset + 1;
|
||||
else
|
||||
VOffset = LineData[Y].BG[bg].VOffset;
|
||||
VOffset = LineData[Y + MosaicStart].BG[bg].VOffset;
|
||||
|
||||
if (HCellOffset & OffsetEnableMask)
|
||||
HOffset = (HCellOffset & ~7) | (LineHOffset & 7);
|
||||
HOffset = (HCellOffset & ~7) | (HScroll & 7);
|
||||
else
|
||||
HOffset = LineHOffset;
|
||||
HOffset = HScroll;
|
||||
}
|
||||
|
||||
if (HiresInterlace)
|
||||
@ -2052,7 +2067,7 @@ static void DisplayPressedKeys (void)
|
||||
static int KeyOrder[] = { 8, 10, 7, 9, 0, 6, 14, 13, 5, 1, 4, 3, 2, 11, 12 }; // < ^ > v A B Y X L R S s
|
||||
|
||||
enum controllers controller;
|
||||
int line = 1;
|
||||
int line = Settings.DisplayMovieFrame && S9xMovieActive() ? 2 : 1;
|
||||
int8 ids[4];
|
||||
char string[255];
|
||||
|
||||
@ -2144,6 +2159,22 @@ 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);
|
||||
@ -2251,12 +2282,7 @@ void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int1
|
||||
fg = get_crosshair_color(fgcolor);
|
||||
bg = get_crosshair_color(bgcolor);
|
||||
|
||||
// XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it...
|
||||
#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP))
|
||||
if (x >= 0 && y >= 0)
|
||||
#endif
|
||||
{
|
||||
uint16 *s = GFX.Screen + y * GFX.RealPPL + x;
|
||||
uint16 *s = GFX.Screen + y * (int32)GFX.RealPPL + x;
|
||||
|
||||
for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx)
|
||||
{
|
||||
@ -2289,7 +2315,6 @@ void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int1
|
||||
*s = (bgcolor & 0x10) ? COLOR_ADD1_2(*s, bg) : bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GFX_MULTI_FORMAT
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -261,6 +276,7 @@ struct CMemory
|
||||
uint32 ROMChecksum;
|
||||
uint32 ROMComplementChecksum;
|
||||
uint32 ROMCRC32;
|
||||
unsigned char ROMSHA256[32];
|
||||
int32 ROMFramesPerSecond;
|
||||
|
||||
bool8 HiROM;
|
||||
@ -278,17 +294,24 @@ struct CMemory
|
||||
|
||||
int ScoreHiROM (bool8, int32 romoff = 0);
|
||||
int ScoreLoROM (bool8, int32 romoff = 0);
|
||||
uint32 HeaderRemove (uint32, int32 &, uint8 *);
|
||||
uint32 FileLoader (uint8 *, const char *, int32);
|
||||
uint32 HeaderRemove (uint32, uint8 *);
|
||||
uint32 FileLoader (uint8 *, const char *, uint32);
|
||||
uint32 MemLoader (uint8 *, const char*, uint32);
|
||||
bool8 LoadROMMem (const uint8 *, uint32);
|
||||
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 LoadSufamiTurbo (const char *, const char *);
|
||||
bool8 LoadSameGame (const char *, const char *);
|
||||
bool8 LoadMultiCartInt ();
|
||||
bool8 LoadSufamiTurbo ();
|
||||
bool8 LoadBSCart ();
|
||||
bool8 LoadGNEXT ();
|
||||
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 *);
|
||||
@ -324,10 +347,12 @@ 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);
|
||||
@ -366,7 +391,7 @@ extern CMemory Memory;
|
||||
extern SMulti Multi;
|
||||
|
||||
void S9xAutoSaveSRAM (void);
|
||||
bool8 LoadZip(const char *, int32 *, int32 *, uint8 *);
|
||||
bool8 LoadZip(const char *, uint32 *, uint8 *);
|
||||
|
||||
enum s9xwrap_t
|
||||
{
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -204,9 +219,6 @@ static inline void S9xLatchCounters (bool force)
|
||||
#ifdef DEBUGGER
|
||||
missing.h_v_latch = 1;
|
||||
#endif
|
||||
#if 0 // #ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
PPU.HVBeamCounterLatched = 1;
|
||||
PPU.VBeamPosLatched = (uint16) CPU.V_Counter;
|
||||
@ -245,9 +257,6 @@ static inline void S9xTryGunLatch (bool force)
|
||||
#ifdef DEBUGGER
|
||||
missing.h_v_latch = 1;
|
||||
#endif
|
||||
#if 0 // #ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
PPU.HVBeamCounterLatched = 1;
|
||||
PPU.VBeamPosLatched = (uint16) PPU.GunVLatch;
|
||||
@ -260,189 +269,105 @@ static inline void S9xTryGunLatch (bool force)
|
||||
}
|
||||
}
|
||||
|
||||
void S9xCheckMissingHTimerPosition (int32 hc)
|
||||
static int CyclesUntilNext (int hc, int vc)
|
||||
{
|
||||
if (PPU.HTimerPosition == hc)
|
||||
int32 total = 0;
|
||||
int vpos = CPU.V_Counter;
|
||||
|
||||
if (vc - vpos > 0)
|
||||
{
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
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 S9xCheckMissingHTimerHalt (int32 hc_from, int32 range)
|
||||
void S9xUpdateIRQPositions (bool initial)
|
||||
{
|
||||
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.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;
|
||||
PPU.VTimerPosition = PPU.IRQVBeamPos;
|
||||
|
||||
if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340))
|
||||
if (PPU.VTimerEnabled && (PPU.VTimerPosition >= (Timings.V_Max + (IPPU.Interlace ? 1 : 0))))
|
||||
{
|
||||
PPU.HTimerPosition -= Timings.H_Max;
|
||||
PPU.VTimerPosition++;
|
||||
// FIXME
|
||||
if (PPU.VTimerPosition >= Timings.V_Max)
|
||||
PPU.VTimerPosition = 0;
|
||||
Timings.NextIRQTimer = 0x0fffffff;
|
||||
}
|
||||
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)
|
||||
{
|
||||
Timings.NextIRQTimer += Timings.H_Max;
|
||||
v_pos++;
|
||||
}
|
||||
|
||||
if (PPU.HTimerPosition < CPU.Cycles)
|
||||
// Check for short dot scanline
|
||||
if (v_pos == 240 && Timings.InterlaceField && !IPPU.Interlace)
|
||||
{
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
case HC_IRQ_1_3_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_START_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAStart;
|
||||
break;
|
||||
|
||||
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;
|
||||
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
|
||||
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
|
||||
}
|
||||
}
|
||||
else if (!PPU.HTimerEnabled && PPU.VTimerEnabled)
|
||||
{
|
||||
if (CPU.V_Counter == PPU.VTimerPosition && initial)
|
||||
Timings.NextIRQTimer = CPU.Cycles + Timings.IRQTriggerCycles;
|
||||
else
|
||||
if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
Timings.NextIRQTimer = CyclesUntilNext (Timings.IRQTriggerCycles, PPU.VTimerPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CPU.WhichEvent)
|
||||
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))
|
||||
{
|
||||
case HC_IRQ_1_3_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_START_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAStart;
|
||||
break;
|
||||
field = !field;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition);
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -514,9 +439,9 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
if (PPU.Brightness != (Byte & 0xf))
|
||||
{
|
||||
IPPU.ColorsChanged = TRUE;
|
||||
IPPU.DirectColourMapsNeedRebuild = TRUE;
|
||||
PPU.Brightness = Byte & 0xf;
|
||||
S9xFixColourBrightness();
|
||||
S9xBuildDirectColourMaps();
|
||||
if (PPU.Brightness > IPPU.MaxBrightness)
|
||||
IPPU.MaxBrightness = PPU.Brightness;
|
||||
}
|
||||
@ -560,7 +485,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
|
||||
case 0x2102: // OAMADDL
|
||||
PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
|
||||
PPU.OAMFlip = 2;
|
||||
PPU.OAMFlip = 0;
|
||||
PPU.OAMReadFlip = 0;
|
||||
PPU.SavedOAMAddr = PPU.OAMAddr;
|
||||
if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
|
||||
@ -621,7 +546,10 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
PPU.BGMode = Byte & 7;
|
||||
// BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set
|
||||
PPU.BG3Priority = ((Byte & 0x0f) == 0x09);
|
||||
if (PPU.BGMode == 6 || PPU.BGMode == 5 || PPU.BGMode == 7)
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
else
|
||||
IPPU.Interlace = 0;
|
||||
#ifdef DEBUGGER
|
||||
missing.modes[PPU.BGMode] = 1;
|
||||
#endif
|
||||
@ -787,7 +715,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;
|
||||
@ -797,15 +725,13 @@ 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;
|
||||
@ -815,22 +741,14 @@ 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;
|
||||
|
||||
@ -1146,13 +1064,20 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
PPU.ScreenHeight = SNES_HEIGHT;
|
||||
if (IPPU.DoubleHeightPixels)
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
else
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
}
|
||||
|
||||
if ((Memory.FillRAM[0x2133] ^ Byte) & 3)
|
||||
{
|
||||
FLUSH_REDRAW();
|
||||
if ((Memory.FillRAM[0x2133] ^ Byte) & 2)
|
||||
IPPU.OBJChanged = TRUE;
|
||||
|
||||
IPPU.Interlace = Byte & 1;
|
||||
IPPU.InterlaceOBJ = Byte & 2;
|
||||
}
|
||||
@ -1259,10 +1184,9 @@ 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
|
||||
if (Address < 0x2100)
|
||||
return (OpenBus);
|
||||
|
||||
@ -1337,7 +1261,7 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
|
||||
case 0x2137: // SLHV
|
||||
S9xLatchCounters(0);
|
||||
return (OpenBus);
|
||||
return (PPU.OpenBus1);
|
||||
|
||||
case 0x2138: // OAMDATAREAD
|
||||
if (PPU.OAMAddr & 0x100)
|
||||
@ -1384,7 +1308,6 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
return (PPU.OpenBus1 = byte);
|
||||
|
||||
case 0x2139: // VMDATALREAD
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
byte = IPPU.VRAMReadBuffer & 0xff;
|
||||
if (!PPU.VMA.High)
|
||||
{
|
||||
@ -1400,33 +1323,13 @@ 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)
|
||||
{
|
||||
@ -1442,26 +1345,6 @@ 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
|
||||
@ -1677,9 +1560,18 @@ 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
|
||||
missing.virq = 1;
|
||||
missing.virq_pos = PPU.IRQVBeamPos;
|
||||
@ -1691,6 +1583,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
if (Byte & 0x10)
|
||||
{
|
||||
PPU.HTimerEnabled = TRUE;
|
||||
|
||||
#ifdef DEBUGGER
|
||||
missing.hirq = 1;
|
||||
missing.hirq_pos = PPU.IRQHBeamPos;
|
||||
@ -1699,14 +1592,13 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
else
|
||||
PPU.HTimerEnabled = FALSE;
|
||||
|
||||
S9xUpdateHVTimerPosition();
|
||||
if (!(Byte & 0x10) && !(Byte & 0x20))
|
||||
{
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
}
|
||||
|
||||
// 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);
|
||||
S9xUpdateIRQPositions(true);
|
||||
|
||||
// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
|
||||
if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
|
||||
@ -1714,10 +1606,20 @@ 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.Flags |= NMI_FLAG;
|
||||
CPU.NMIPending = TRUE;
|
||||
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
|
||||
@ -1761,7 +1663,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
pos = PPU.IRQHBeamPos;
|
||||
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
|
||||
if (PPU.IRQHBeamPos != pos)
|
||||
S9xUpdateHVTimerPosition();
|
||||
S9xUpdateIRQPositions(false);
|
||||
#ifdef DEBUGGER
|
||||
missing.hirq_pos = PPU.IRQHBeamPos;
|
||||
#endif
|
||||
@ -1771,7 +1673,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
pos = PPU.IRQHBeamPos;
|
||||
PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
|
||||
if (PPU.IRQHBeamPos != pos)
|
||||
S9xUpdateHVTimerPosition();
|
||||
S9xUpdateIRQPositions(false);
|
||||
#ifdef DEBUGGER
|
||||
missing.hirq_pos = PPU.IRQHBeamPos;
|
||||
#endif
|
||||
@ -1781,7 +1683,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
pos = PPU.IRQVBeamPos;
|
||||
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
|
||||
if (PPU.IRQVBeamPos != pos)
|
||||
S9xUpdateHVTimerPosition();
|
||||
S9xUpdateIRQPositions(true);
|
||||
#ifdef DEBUGGER
|
||||
missing.virq_pos = PPU.IRQVBeamPos;
|
||||
#endif
|
||||
@ -1791,7 +1693,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
pos = PPU.IRQVBeamPos;
|
||||
PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
|
||||
if (PPU.IRQVBeamPos != pos)
|
||||
S9xUpdateHVTimerPosition();
|
||||
S9xUpdateIRQPositions(true);
|
||||
#ifdef DEBUGGER
|
||||
missing.virq_pos = PPU.IRQVBeamPos;
|
||||
#endif
|
||||
@ -1801,8 +1703,9 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
if (CPU.InDMAorHDMA)
|
||||
return;
|
||||
// XXX: Not quite right...
|
||||
if (Byte)
|
||||
if (Byte) {
|
||||
CPU.Cycles += Timings.DMACPUSync;
|
||||
}
|
||||
if (Byte & 0x01)
|
||||
S9xDoDMA(0);
|
||||
if (Byte & 0x02)
|
||||
@ -1828,8 +1731,6 @@ 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;
|
||||
@ -1856,17 +1757,7 @@ 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
|
||||
@ -1982,22 +1873,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 = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0;
|
||||
S9xClearIRQ(PPU_IRQ_SOURCE);
|
||||
byte = 0;
|
||||
if (CPU.IRQLine)
|
||||
{
|
||||
byte = 0x80;
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
}
|
||||
|
||||
return (byte | (OpenBus & 0x7f));
|
||||
|
||||
case 0x4212: // HVBJOY
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
return (REGISTER_4212() | (OpenBus & 0x3e));
|
||||
|
||||
case 0x4213: // RDIO
|
||||
@ -2046,6 +1937,20 @@ 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();
|
||||
@ -2109,7 +2014,7 @@ void S9xSoftResetPPU (void)
|
||||
PPU.OAMReadFlip = 0;
|
||||
PPU.OAMTileAddress = 0;
|
||||
PPU.OAMWriteRegister = 0;
|
||||
ZeroMemory(PPU.OAMData, 512 + 32);
|
||||
memset(PPU.OAMData, 0, 512 + 32);
|
||||
|
||||
PPU.FirstSprite = 0;
|
||||
PPU.LastSprite = 127;
|
||||
@ -2183,19 +2088,15 @@ void S9xSoftResetPPU (void)
|
||||
memset(&IPPU.Clip[c], 0, sizeof(struct ClipData));
|
||||
IPPU.ColorsChanged = TRUE;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
IPPU.DirectColourMapsNeedRebuild = TRUE;
|
||||
ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES);
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
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);
|
||||
IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
|
||||
#else
|
||||
IPPU.FirstVRAMRead = FALSE;
|
||||
#endif
|
||||
GFX.InterlaceFrame = 0;
|
||||
IPPU.Interlace = FALSE;
|
||||
IPPU.InterlaceOBJ = FALSE;
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
@ -2216,14 +2117,16 @@ void S9xSoftResetPPU (void)
|
||||
IPPU.FrameSkip = 0;
|
||||
|
||||
S9xFixColourBrightness();
|
||||
S9xBuildDirectColourMaps();
|
||||
|
||||
for (int c = 0; c < 0x8000; c += 0x100)
|
||||
memset(&Memory.FillRAM[c], c >> 8, 0x100);
|
||||
ZeroMemory(&Memory.FillRAM[0x2100], 0x100);
|
||||
ZeroMemory(&Memory.FillRAM[0x4200], 0x100);
|
||||
ZeroMemory(&Memory.FillRAM[0x4000], 0x100);
|
||||
memset(&Memory.FillRAM[0x2100], 0, 0x100);
|
||||
memset(&Memory.FillRAM[0x4200], 0, 0x100);
|
||||
memset(&Memory.FillRAM[0x4000], 0, 0x100);
|
||||
// For BS Suttehakkun 2...
|
||||
ZeroMemory(&Memory.FillRAM[0x1000], 0x1000);
|
||||
memset(&Memory.FillRAM[0x1000], 0, 0x1000);
|
||||
|
||||
Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
|
||||
Memory.FillRAM[0x2126] = Memory.FillRAM[0x2128] = 1;
|
||||
}
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -197,11 +212,6 @@
|
||||
#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;
|
||||
@ -215,14 +225,9 @@ struct InternalPPU
|
||||
struct ClipData Clip[2][6];
|
||||
bool8 ColorsChanged;
|
||||
bool8 OBJChanged;
|
||||
bool8 DirectColourMapsNeedRebuild;
|
||||
uint8 *TileCache[7];
|
||||
uint8 *TileCached[7];
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
uint16 VRAMReadBuffer;
|
||||
#else
|
||||
bool8 FirstVRAMRead;
|
||||
#endif
|
||||
bool8 Interlace;
|
||||
bool8 InterlaceOBJ;
|
||||
bool8 PseudoHires;
|
||||
@ -379,15 +384,13 @@ 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 S9xUpdateHVTimerPosition (void);
|
||||
void S9xCheckMissingHTimerPosition (int32);
|
||||
void S9xCheckMissingHTimerRange (int32, int32);
|
||||
void S9xCheckMissingHTimerHalt (int32, int32);
|
||||
void S9xUpdateIRQPositions (bool initial);
|
||||
void S9xFixColourBrightness (void);
|
||||
void S9xDoAutoJoypad (void);
|
||||
|
||||
@ -417,6 +420,12 @@ 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);
|
||||
@ -438,33 +447,8 @@ 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))
|
||||
{
|
||||
PPU.OAMWriteRegister &= 0xff00;
|
||||
PPU.OAMWriteRegister |= Byte;
|
||||
PPU.OAMFlip |= 1;
|
||||
if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
|
||||
IPPU.OBJChanged = TRUE;
|
||||
}
|
||||
else
|
||||
else if (PPU.OAMFlip & 1)
|
||||
{
|
||||
PPU.OAMWriteRegister &= 0x00ff;
|
||||
uint8 lowbyte = (uint8) (PPU.OAMWriteRegister);
|
||||
@ -497,15 +481,24 @@ static inline void REGISTER_2104 (uint8 Byte)
|
||||
PPU.OBJ[addr].VPos = highbyte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PPU.OAMFlip &= ~1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :(
|
||||
@ -515,12 +508,18 @@ 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) \
|
||||
return;
|
||||
{ \
|
||||
PPU.VMA.Address += !PPU.VMA.High ? PPU.VMA.Increment : 0; \
|
||||
return; \
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void REGISTER_2118 (uint8 Byte)
|
||||
@ -560,10 +559,80 @@ static inline void REGISTER_2118 (uint8 Byte)
|
||||
}
|
||||
}
|
||||
|
||||
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_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)
|
||||
@ -597,31 +666,6 @@ 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();
|
||||
@ -647,30 +691,6 @@ 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();
|
||||
|
@ -1,353 +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),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
OV2
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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 - 2010 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
funkyass,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
|
||||
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
|
||||
#include "unzip.h"
|
||||
#endif
|
||||
#include "snes9x.h"
|
||||
#include "reader.h"
|
||||
|
||||
|
||||
// Generic constructor/destructor
|
||||
|
||||
Reader::Reader (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reader::~Reader (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Generic getline function, based on gets. Reimlpement if you can do better.
|
||||
|
||||
char * Reader::getline (void)
|
||||
{
|
||||
bool eof;
|
||||
std::string ret;
|
||||
|
||||
ret = getline(eof);
|
||||
if (ret.size() == 0 && eof)
|
||||
return (NULL);
|
||||
|
||||
return (strdup(ret.c_str()));
|
||||
}
|
||||
|
||||
std::string Reader::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 STREAM reader
|
||||
|
||||
fReader::fReader (STREAM f)
|
||||
{
|
||||
fp = f;
|
||||
}
|
||||
|
||||
fReader::~fReader (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int fReader::get_char (void)
|
||||
{
|
||||
return (GETC_STREAM(fp));
|
||||
}
|
||||
|
||||
char * fReader::gets (char *buf, size_t len)
|
||||
{
|
||||
return (GETS_STREAM(buf, len, fp));
|
||||
}
|
||||
|
||||
size_t fReader::read (char *buf, size_t len)
|
||||
{
|
||||
return (READ_STREAM(buf, len, fp));
|
||||
}
|
||||
|
||||
// unzip reader
|
||||
|
||||
#ifdef UNZIP_SUPPORT
|
||||
|
||||
unzReader::unzReader (unzFile &v)
|
||||
{
|
||||
file = v;
|
||||
head = NULL;
|
||||
numbytes = 0;
|
||||
}
|
||||
|
||||
unzReader::~unzReader (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int unzReader::get_char (void)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
if (numbytes <= 0)
|
||||
{
|
||||
numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
|
||||
if (numbytes <= 0)
|
||||
return (EOF);
|
||||
head = buffer;
|
||||
}
|
||||
|
||||
c = *head;
|
||||
head++;
|
||||
numbytes--;
|
||||
|
||||
return ((int) c);
|
||||
}
|
||||
|
||||
char * unzReader::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 unzReader::read (char *buf, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return (len);
|
||||
|
||||
if (len <= numbytes)
|
||||
{
|
||||
memcpy(buf, head, len);
|
||||
numbytes -= len;
|
||||
head += len;
|
||||
return (len);
|
||||
}
|
||||
|
||||
size_t numread = 0;
|
||||
if (numbytes > 0)
|
||||
{
|
||||
memcpy(buf, head, numbytes);
|
||||
numread += numbytes;
|
||||
head = NULL;
|
||||
numbytes = 0;
|
||||
}
|
||||
|
||||
int l = unzReadCurrentFile(file, buf + numread, len - numread);
|
||||
if (l > 0)
|
||||
numread += l;
|
||||
|
||||
return (numread);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,228 +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),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
OV2
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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 - 2010 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
funkyass,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
|
||||
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 _READER_H_
|
||||
#define _READER_H_
|
||||
|
||||
class Reader
|
||||
{
|
||||
public:
|
||||
Reader (void);
|
||||
virtual ~Reader (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 (char *, size_t) = 0;
|
||||
};
|
||||
|
||||
class fReader : public Reader
|
||||
{
|
||||
public:
|
||||
fReader (STREAM);
|
||||
virtual ~fReader (void);
|
||||
virtual int get_char (void);
|
||||
virtual char * gets (char *, size_t);
|
||||
virtual size_t read (char *, size_t);
|
||||
|
||||
private:
|
||||
STREAM fp;
|
||||
};
|
||||
|
||||
#ifdef UNZIP_SUPPORT
|
||||
|
||||
#define unz_BUFFSIZ 1024
|
||||
|
||||
class unzReader : public Reader
|
||||
{
|
||||
public:
|
||||
unzReader (unzFile &);
|
||||
virtual ~unzReader (void);
|
||||
virtual int get_char (void);
|
||||
virtual char * gets (char *, size_t);
|
||||
virtual size_t read (char *, size_t);
|
||||
|
||||
private:
|
||||
unzFile file;
|
||||
char buffer[unz_BUFFSIZ];
|
||||
char *head;
|
||||
size_t numbytes;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -180,7 +195,6 @@
|
||||
|
||||
uint8 SA1OpenBus;
|
||||
|
||||
static void S9xSA1Reset (void);
|
||||
static void S9xSA1SetBWRAMMemMap (uint8);
|
||||
static void S9xSetSA1MemMap (uint32, uint8);
|
||||
static void S9xSA1CharConv2 (void);
|
||||
@ -190,31 +204,37 @@ static void S9xSA1ReadVariableLengthData (bool8, bool8);
|
||||
|
||||
void S9xSA1Init (void)
|
||||
{
|
||||
SA1.IRQActive = FALSE;
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1.Waiting = FALSE;
|
||||
SA1.Cycles = 0;
|
||||
SA1.PrevCycles = 0;
|
||||
SA1.Flags = 0;
|
||||
SA1.Executing = FALSE;
|
||||
SA1.WaitingForInterrupt = 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] = 0xff;
|
||||
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;
|
||||
SA1.op1 = 0;
|
||||
SA1.op2 = 0;
|
||||
SA1.arithmetic_op = 0;
|
||||
SA1.sum = 0;
|
||||
SA1.overflow = FALSE;
|
||||
SA1.S9xOpcodes = NULL;
|
||||
}
|
||||
SA1.VirtualBitmapFormat = 0;
|
||||
SA1.variable_bit_pos = 0;
|
||||
|
||||
static void S9xSA1Reset (void)
|
||||
{
|
||||
SA1Registers.PBPC = 0;
|
||||
SA1Registers.PB = 0;
|
||||
SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
|
||||
SA1Registers.PCw = 0;
|
||||
SA1Registers.D.W = 0;
|
||||
SA1Registers.DB = 0;
|
||||
SA1Registers.SH = 1;
|
||||
@ -228,17 +248,20 @@ static void S9xSA1Reset (void)
|
||||
SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
|
||||
SA1ClearFlags(Decimal);
|
||||
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1.PCBase = NULL;
|
||||
S9xSA1SetPCBase(SA1Registers.PBPC);
|
||||
SA1.MemSpeed = SLOW_ONE_CYCLE;
|
||||
SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
|
||||
|
||||
SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
|
||||
SA1.S9xOpLengths = S9xOpLengthsM1X1;
|
||||
|
||||
S9xSA1SetPCBase(SA1Registers.PBPC);
|
||||
|
||||
S9xSA1UnpackStatus();
|
||||
S9xSA1FixCycles();
|
||||
SA1.Executing = TRUE;
|
||||
|
||||
SA1.BWRAM = Memory.SRAM;
|
||||
Memory.FillRAM[0x2225] = 0;
|
||||
|
||||
CPU.IRQExternal = FALSE;
|
||||
}
|
||||
|
||||
static void S9xSA1SetBWRAMMemMap (uint8 val)
|
||||
@ -280,23 +303,6 @@ 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)
|
||||
@ -309,14 +315,43 @@ static void S9xSetSA1MemMap (uint32 which1, uint8 map)
|
||||
|
||||
for (int c = 0; c < 0x100; c += 16)
|
||||
{
|
||||
uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)];
|
||||
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));
|
||||
}
|
||||
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)
|
||||
{
|
||||
uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000];
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
for (int i = c + 8; i < c + 16; i++)
|
||||
Memory.Map[start2 + i] = SA1.Map[start2 + i] = block;
|
||||
}
|
||||
@ -326,31 +361,48 @@ uint8 S9xGetSA1 (uint32 address)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x2300:
|
||||
return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE))));
|
||||
case 0x2300: // S-CPU flag
|
||||
return ((Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0));
|
||||
|
||||
case 0x2301:
|
||||
return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0));
|
||||
case 0x2301: // SA-1 flag
|
||||
return ((Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0));
|
||||
|
||||
case 0x2306:
|
||||
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)
|
||||
return ((uint8) SA1.sum);
|
||||
|
||||
case 0x2307:
|
||||
case 0x2307: // arithmetic result (LLH)
|
||||
return ((uint8) (SA1.sum >> 8));
|
||||
|
||||
case 0x2308:
|
||||
case 0x2308: // arithmetic result (LHL)
|
||||
return ((uint8) (SA1.sum >> 16));
|
||||
|
||||
case 0x2309:
|
||||
case 0x2309: // arithmetic result (LLH)
|
||||
return ((uint8) (SA1.sum >> 24));
|
||||
|
||||
case 0x230a:
|
||||
case 0x230a: // arithmetic result (HLL)
|
||||
return ((uint8) (SA1.sum >> 32));
|
||||
|
||||
case 0x230c:
|
||||
case 0x230b: // arithmetic overflow
|
||||
return (SA1.overflow ? 0x80 : 0);
|
||||
|
||||
case 0x230c: // variable-length data read port (L)
|
||||
return (Memory.FillRAM[0x230c]);
|
||||
|
||||
case 0x230d:
|
||||
case 0x230d: // variable-length data read port (H)
|
||||
{
|
||||
uint8 byte = Memory.FillRAM[0x230d];
|
||||
|
||||
@ -360,8 +412,10 @@ uint8 S9xGetSA1 (uint32 address)
|
||||
return (byte);
|
||||
}
|
||||
|
||||
case 0x230e: // version code register
|
||||
return (0x01);
|
||||
|
||||
default:
|
||||
//printf("R: %04x\n", address);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -372,337 +426,279 @@ void S9xSetSA1 (uint8 byte, uint32 address)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x2200:
|
||||
SA1.Waiting = (byte & 0x60) != 0;
|
||||
//SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
|
||||
case 0x2200: // SA-1 control
|
||||
#ifdef DEBUGGER
|
||||
if (byte & 0x60)
|
||||
printf("SA-1 sleep\n");
|
||||
#endif
|
||||
|
||||
if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20))
|
||||
S9xSA1Reset();
|
||||
// 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);
|
||||
}
|
||||
|
||||
// SA-1 IRQ control
|
||||
if (byte & 0x80)
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x80;
|
||||
if (Memory.FillRAM[0x220a] & 0x80)
|
||||
{
|
||||
SA1.Flags |= IRQ_FLAG;
|
||||
SA1.IRQActive |= SNES_IRQ_SOURCE;
|
||||
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x80;
|
||||
}
|
||||
|
||||
// SA-1 NMI control
|
||||
if (byte & 0x10)
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x10;
|
||||
if (Memory.FillRAM[0x220a] & 0x10)
|
||||
{
|
||||
SA1.Flags |= NMI_FLAG;
|
||||
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x10;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x2201:
|
||||
case 0x2201: // S-CPU interrupt enable
|
||||
// S-CPU IRQ enable
|
||||
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
|
||||
S9xSetIRQ(SA1_IRQ_SOURCE);
|
||||
{
|
||||
Memory.FillRAM[0x2202] &= ~0x80;
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
|
||||
// S-CPU CHDMA IRQ enable
|
||||
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
|
||||
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
|
||||
{
|
||||
Memory.FillRAM[0x2202] &= ~0x20;
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x2202:
|
||||
case 0x2202: // S-CPU interrupt clear
|
||||
// S-CPU IRQ clear
|
||||
if (byte & 0x80)
|
||||
{
|
||||
Memory.FillRAM[0x2300] &= ~0x80;
|
||||
S9xClearIRQ(SA1_IRQ_SOURCE);
|
||||
}
|
||||
|
||||
// S-CPU CHDMA IRQ clear
|
||||
if (byte & 0x20)
|
||||
{
|
||||
Memory.FillRAM[0x2300] &= ~0x20;
|
||||
S9xClearIRQ(SA1_DMA_IRQ_SOURCE);
|
||||
}
|
||||
|
||||
if (!(Memory.FillRAM[0x2300] & 0xa0))
|
||||
CPU.IRQExternal = FALSE;
|
||||
|
||||
break;
|
||||
|
||||
case 0x2203:
|
||||
//printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8));
|
||||
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 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;
|
||||
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 (byte & Memory.FillRAM[0x2201] & 0x80)
|
||||
S9xSetIRQ(SA1_IRQ_SOURCE);
|
||||
if (Memory.FillRAM[0x2201] & 0x80)
|
||||
{
|
||||
Memory.FillRAM[0x2202] &= ~0x80;
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x220a:
|
||||
case 0x220a: // SA-1 interrupt enable
|
||||
// SA-1 IRQ enable
|
||||
if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
|
||||
{
|
||||
SA1.Flags |= IRQ_FLAG;
|
||||
SA1.IRQActive |= SNES_IRQ_SOURCE;
|
||||
//SA1.Executing = !SA1.Waiting;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x80;
|
||||
|
||||
// SA-1 timer IRQ enable
|
||||
if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
|
||||
{
|
||||
SA1.Flags |= IRQ_FLAG;
|
||||
SA1.IRQActive |= TIMER_IRQ_SOURCE;
|
||||
//SA1.Executing = !SA1.Waiting;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x40;
|
||||
|
||||
// SA-1 DMA IRQ enable
|
||||
if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
|
||||
{
|
||||
SA1.Flags |= IRQ_FLAG;
|
||||
SA1.IRQActive |= DMA_IRQ_SOURCE;
|
||||
//SA1.Executing = !SA1.Waiting;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x20;
|
||||
|
||||
// SA-1 NMI enable
|
||||
if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
|
||||
{
|
||||
SA1.Flags |= NMI_FLAG;
|
||||
//SA1.Executing = !SA1.Waiting;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x10;
|
||||
|
||||
break;
|
||||
|
||||
case 0x220b:
|
||||
case 0x220b: // SA-1 interrupt clear
|
||||
// SA-1 IRQ clear
|
||||
if (byte & 0x80)
|
||||
{
|
||||
SA1.IRQActive &= ~SNES_IRQ_SOURCE;
|
||||
Memory.FillRAM[0x2301] &= ~0x80;
|
||||
}
|
||||
|
||||
// SA-1 timer IRQ clear
|
||||
if (byte & 0x40)
|
||||
{
|
||||
SA1.IRQActive &= ~TIMER_IRQ_SOURCE;
|
||||
Memory.FillRAM[0x2301] &= ~0x40;
|
||||
}
|
||||
|
||||
// SA-1 DMA IRQ clear
|
||||
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:
|
||||
//printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8));
|
||||
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)
|
||||
break;
|
||||
|
||||
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");
|
||||
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);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x2211:
|
||||
//printf("Timer reset\n");
|
||||
case 0x2211: // SA-1 timer reset
|
||||
SA1.HCounter = 0;
|
||||
SA1.VCounter = 0;
|
||||
break;
|
||||
|
||||
case 0x2212:
|
||||
//printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8));
|
||||
case 0x2212: // SA-1 H-timer (L)
|
||||
SA1.HTimerIRQPos = byte | (Memory.FillRAM[0x2213] << 8);
|
||||
break;
|
||||
|
||||
case 0x2213:
|
||||
//printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]);
|
||||
case 0x2213: // SA-1 H-timer (H)
|
||||
SA1.HTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2212];
|
||||
break;
|
||||
|
||||
case 0x2214:
|
||||
//printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8));
|
||||
case 0x2214: // SA-1 V-timer (L)
|
||||
SA1.VTimerIRQPos = byte | (Memory.FillRAM[0x2215] << 8);
|
||||
break;
|
||||
|
||||
case 0x2215:
|
||||
//printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]);
|
||||
case 0x2215: // SA-1 V-timer (H)
|
||||
SA1.VTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2214];
|
||||
break;
|
||||
|
||||
case 0x2220:
|
||||
case 0x2221:
|
||||
case 0x2222:
|
||||
case 0x2223:
|
||||
//printf("MMC: %02x\n", byte);
|
||||
case 0x2220: // MMC bank C
|
||||
case 0x2221: // MMC bank D
|
||||
case 0x2222: // MMC bank E
|
||||
case 0x2223: // MMC bank F
|
||||
S9xSetSA1MemMap(address - 0x2220, byte);
|
||||
break;
|
||||
|
||||
case 0x2224:
|
||||
//printf("BWRAM image SNES %02x -> 0x6000\n", byte);
|
||||
case 0x2224: // S-CPU BW-RAM mapping
|
||||
Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000;
|
||||
break;
|
||||
|
||||
case 0x2225:
|
||||
//printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]);
|
||||
case 0x2225: // SA-1 BW-RAM mapping
|
||||
if (byte != Memory.FillRAM[0x2225])
|
||||
S9xSA1SetBWRAMMemMap(byte);
|
||||
|
||||
break;
|
||||
|
||||
case 0x2226:
|
||||
//printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled");
|
||||
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
|
||||
break;
|
||||
|
||||
case 0x2227:
|
||||
//printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled");
|
||||
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
|
||||
break;
|
||||
|
||||
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:
|
||||
case 0x2231: // character conversion DMA parameters
|
||||
// 0x80: CHDEND (complete / incomplete)
|
||||
// 0x03: color mode
|
||||
// (byte >> 2) & 7: virtual VRAM width
|
||||
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:
|
||||
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
|
||||
case 0x2232: // DMA source start address (LL)
|
||||
case 0x2233: // DMA source start address (LH)
|
||||
case 0x2234: // DMA source start address (HL)
|
||||
break;
|
||||
|
||||
case 0x2235:
|
||||
Memory.FillRAM[0x2235] = byte;
|
||||
case 0x2235: // DMA destination start address (LL)
|
||||
break;
|
||||
|
||||
case 0x2236:
|
||||
case 0x2236: // DMA destination start address (LH)
|
||||
Memory.FillRAM[0x2236] = byte;
|
||||
|
||||
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM
|
||||
S9xSA1DMA();
|
||||
else
|
||||
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0)
|
||||
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) // CC1
|
||||
{
|
||||
SA1.in_char_dma = TRUE;
|
||||
|
||||
Memory.FillRAM[0x2300] |= 0x20;
|
||||
if (Memory.FillRAM[0x2201] & 0x20)
|
||||
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
|
||||
SA1.in_char_dma = TRUE;
|
||||
{
|
||||
Memory.FillRAM[0x2202] &= ~0x20;
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x2237:
|
||||
case 0x2237: // DMA destination start address (HL)
|
||||
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:
|
||||
case 0x2239:
|
||||
Memory.FillRAM[address] = byte;
|
||||
#if 0
|
||||
printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8));
|
||||
#endif
|
||||
case 0x2238: // DMA terminal counter (L)
|
||||
case 0x2239: // DMA terminal counter (H)
|
||||
break;
|
||||
|
||||
case 0x223f:
|
||||
//printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4);
|
||||
case 0x223f: // BW-RAM bitmap format
|
||||
SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
|
||||
break;
|
||||
|
||||
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;
|
||||
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
|
||||
break;
|
||||
|
||||
case 0x224f:
|
||||
case 0x224f: // bitmap register F
|
||||
Memory.FillRAM[0x224f] = byte;
|
||||
|
||||
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled
|
||||
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // CC2
|
||||
{
|
||||
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;
|
||||
@ -712,58 +708,69 @@ void S9xSetSA1 (uint8 byte, uint32 address)
|
||||
|
||||
break;
|
||||
|
||||
case 0x2250:
|
||||
case 0x2250: // arithmetic control
|
||||
if (byte & 2)
|
||||
SA1.sum = 0;
|
||||
SA1.arithmetic_op = byte & 3;
|
||||
break;
|
||||
|
||||
case 0x2251:
|
||||
case 0x2251: // multiplicand / dividend (L)
|
||||
SA1.op1 = (SA1.op1 & 0xff00) | byte;
|
||||
break;
|
||||
|
||||
case 0x2252:
|
||||
SA1.op1 = (SA1.op1 & 0xff) | (byte << 8);
|
||||
case 0x2252: // multiplicand / dividend (H)
|
||||
SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8);
|
||||
break;
|
||||
|
||||
case 0x2253:
|
||||
case 0x2253: // multiplier / divisor (L)
|
||||
SA1.op2 = (SA1.op2 & 0xff00) | byte;
|
||||
break;
|
||||
|
||||
case 0x2254:
|
||||
SA1.op2 = (SA1.op2 & 0xff) | (byte << 8);
|
||||
case 0x2254: // multiplier / divisor (H)
|
||||
SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8);
|
||||
|
||||
switch (SA1.arithmetic_op)
|
||||
{
|
||||
case 0: // multiply
|
||||
SA1.sum = SA1.op1 * SA1.op2;
|
||||
case 0: // signed multiplication
|
||||
SA1.sum = (int16) SA1.op1 * (int16) SA1.op2;
|
||||
SA1.op2 = 0;
|
||||
break;
|
||||
|
||||
case 1: // divide
|
||||
case 1: // unsigned division
|
||||
if (SA1.op2 == 0)
|
||||
SA1.sum = SA1.op1 << 16;
|
||||
SA1.sum = 0;
|
||||
else
|
||||
SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16);
|
||||
{
|
||||
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;
|
||||
break;
|
||||
|
||||
case 2: // cumulative sum
|
||||
default:
|
||||
SA1.sum += SA1.op1 * SA1.op2;
|
||||
if (SA1.sum & ((int64) 0xffffff << 32))
|
||||
SA1.overflow = TRUE;
|
||||
SA1.sum += (int16) SA1.op1 * (int16) SA1.op2;
|
||||
SA1.overflow = (SA1.sum >= (1ULL << 40));
|
||||
SA1.sum &= (1ULL << 40) - 1;
|
||||
SA1.op2 = 0;
|
||||
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
|
||||
case 0x225a:
|
||||
case 0x225b:
|
||||
case 0x2259: // variable bit-field start address (LL)
|
||||
case 0x225a: // variable bit-field start address (LH)
|
||||
case 0x225b: // variable bit-field start address (HL)
|
||||
Memory.FillRAM[address] = byte;
|
||||
// XXX: ???
|
||||
SA1.variable_bit_pos = 0;
|
||||
@ -771,7 +778,6 @@ void S9xSetSA1 (uint8 byte, uint32 address)
|
||||
return;
|
||||
|
||||
default:
|
||||
//printf("W: %02x->%04x\n", byte, address);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -890,14 +896,11 @@ static void S9xSA1DMA (void)
|
||||
}
|
||||
|
||||
memmove(d, s, len);
|
||||
Memory.FillRAM[0x2301] |= 0x20;
|
||||
|
||||
// SA-1 DMA IRQ control
|
||||
Memory.FillRAM[0x2301] |= 0x20;
|
||||
if (Memory.FillRAM[0x220a] & 0x20)
|
||||
{
|
||||
SA1.Flags |= IRQ_FLAG;
|
||||
SA1.IRQActive |= DMA_IRQ_SOURCE;
|
||||
//SA1.Executing = !SA1.Waiting;
|
||||
}
|
||||
Memory.FillRAM[0x220b] &= ~0x20;
|
||||
}
|
||||
|
||||
static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift)
|
||||
@ -1096,6 +1099,10 @@ 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)
|
||||
@ -1133,4 +1140,3 @@ void S9xSA1SetPCBase (uint32 address)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -198,32 +213,33 @@ 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 Executing;
|
||||
bool8 overflow;
|
||||
bool8 in_char_dma;
|
||||
int16 op1;
|
||||
int16 op2;
|
||||
bool8 TimerIRQLastState;
|
||||
uint16 HTimerIRQPos;
|
||||
uint16 VTimerIRQPos;
|
||||
int16 HCounter;
|
||||
int16 VCounter;
|
||||
int16 PrevHCounter;
|
||||
int32 MemSpeed;
|
||||
int32 MemSpeedx2;
|
||||
int32 arithmetic_op;
|
||||
int64 sum;
|
||||
uint16 op1;
|
||||
uint16 op2;
|
||||
uint64 sum;
|
||||
bool8 overflow;
|
||||
uint8 VirtualBitmapFormat;
|
||||
uint8 variable_bit_pos;
|
||||
};
|
||||
@ -263,13 +279,8 @@ 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;
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -221,20 +236,27 @@
|
||||
#define StackRelative SA1StackRelative
|
||||
#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed
|
||||
|
||||
//#undef CPU_SHUTDOWN
|
||||
#define SA1_OPCODES
|
||||
|
||||
#include "cpuops.cpp"
|
||||
|
||||
static void S9xSA1UpdateTimer (void);
|
||||
|
||||
|
||||
void S9xSA1MainLoop (void)
|
||||
{
|
||||
if (SA1.Flags & NMI_FLAG)
|
||||
if (Memory.FillRAM[0x2200] & 0x60)
|
||||
{
|
||||
if (Memory.FillRAM[0x2200] & 0x10)
|
||||
SA1.Cycles += 6; // FIXME
|
||||
S9xSA1UpdateTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// SA-1 NMI
|
||||
if ((Memory.FillRAM[0x2200] & 0x10) && !(Memory.FillRAM[0x220b] & 0x10))
|
||||
{
|
||||
SA1.Flags &= ~NMI_FLAG;
|
||||
Memory.FillRAM[0x2301] |= 0x10;
|
||||
Memory.FillRAM[0x220b] |= 0x10;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
@ -244,36 +266,59 @@ void S9xSA1MainLoop (void)
|
||||
|
||||
S9xSA1Opcode_NMI();
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!SA1CheckFlag(IRQ))
|
||||
{
|
||||
// SA-1 Timer IRQ
|
||||
if ((Memory.FillRAM[0x220a] & 0x40) && !(Memory.FillRAM[0x220b] & 0x40))
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x40;
|
||||
|
||||
if (SA1.Flags & IRQ_FLAG)
|
||||
{
|
||||
if (SA1.IRQActive)
|
||||
{
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
if (!SA1CheckFlag(IRQ))
|
||||
S9xSA1Opcode_IRQ();
|
||||
}
|
||||
else
|
||||
SA1.Flags &= ~IRQ_FLAG;
|
||||
// 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++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3 && SA1.Executing; i++)
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5 && !(Memory.FillRAM[0x2200] & 0x60); 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;
|
||||
|
||||
@ -299,5 +344,71 @@ 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;
|
||||
}
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,14 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
|
||||
MSU-1 code
|
||||
(c) Copyright 2016 qwertymodo
|
||||
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
|
||||
@ -345,7 +357,7 @@ struct SnapshotScreenshotInfo
|
||||
|
||||
static struct Obsolete
|
||||
{
|
||||
uint8 reserved;
|
||||
uint8 CPU_IRQActive;
|
||||
} Obsolete;
|
||||
|
||||
#define STRUCT struct SCPUState
|
||||
@ -356,7 +368,7 @@ static FreezeData SnapCPU[] =
|
||||
INT_ENTRY(6, PrevCycles),
|
||||
INT_ENTRY(6, V_Counter),
|
||||
INT_ENTRY(6, Flags),
|
||||
INT_ENTRY(6, IRQActive),
|
||||
OBSOLETE_INT_ENTRY(6, 7, CPU_IRQActive),
|
||||
INT_ENTRY(6, IRQPending),
|
||||
INT_ENTRY(6, MemSpeed),
|
||||
INT_ENTRY(6, MemSpeedx2),
|
||||
@ -369,9 +381,14 @@ static FreezeData SnapCPU[] =
|
||||
INT_ENTRY(6, WhichEvent),
|
||||
INT_ENTRY(6, NextEvent),
|
||||
INT_ENTRY(6, WaitingForInterrupt),
|
||||
INT_ENTRY(6, WaitAddress),
|
||||
INT_ENTRY(6, WaitCounter),
|
||||
INT_ENTRY(6, PBPCAtOpcodeStart)
|
||||
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)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -578,8 +595,10 @@ static FreezeData SnapTimings[] =
|
||||
INT_ENTRY(6, InterlaceField),
|
||||
INT_ENTRY(6, DMACPUSync),
|
||||
INT_ENTRY(6, NMIDMADelay),
|
||||
INT_ENTRY(6, IRQPendCount),
|
||||
INT_ENTRY(6, APUSpeedup)
|
||||
INT_ENTRY(6, IRQFlagChanging),
|
||||
INT_ENTRY(6, APUSpeedup),
|
||||
INT_ENTRY(7, IRQTriggerCycles),
|
||||
INT_ENTRY(7, APUAllowTimeOverflow)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -648,17 +667,17 @@ static FreezeData SnapFX[] =
|
||||
|
||||
static FreezeData SnapSA1[] =
|
||||
{
|
||||
INT_ENTRY(6, CPUExecuting),
|
||||
DELETED_INT_ENTRY(6, 7, CPUExecuting, 1),
|
||||
INT_ENTRY(6, ShiftedPB),
|
||||
INT_ENTRY(6, ShiftedDB),
|
||||
INT_ENTRY(6, Flags),
|
||||
INT_ENTRY(6, IRQActive),
|
||||
INT_ENTRY(6, Waiting),
|
||||
DELETED_INT_ENTRY(6, 7, IRQActive, 1),
|
||||
DELETED_INT_ENTRY(6, 7, Waiting, 1),
|
||||
INT_ENTRY(6, WaitingForInterrupt),
|
||||
INT_ENTRY(6, WaitAddress),
|
||||
INT_ENTRY(6, WaitCounter),
|
||||
INT_ENTRY(6, PBPCAtOpcodeStart),
|
||||
INT_ENTRY(6, Executing),
|
||||
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, overflow),
|
||||
INT_ENTRY(6, in_char_dma),
|
||||
INT_ENTRY(6, op1),
|
||||
@ -666,7 +685,17 @@ static FreezeData SnapSA1[] =
|
||||
INT_ENTRY(6, arithmetic_op),
|
||||
INT_ENTRY(6, sum),
|
||||
INT_ENTRY(6, VirtualBitmapFormat),
|
||||
INT_ENTRY(6, variable_bit_pos)
|
||||
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)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -1113,16 +1142,16 @@ static FreezeData SnapBSX[] =
|
||||
|
||||
static FreezeData SnapMSU1[] =
|
||||
{
|
||||
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)
|
||||
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)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -1151,6 +1180,8 @@ 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)
|
||||
@ -1163,7 +1194,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);
|
||||
sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
|
||||
snprintf(filename, PATH_MAX + 1, "%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);
|
||||
}
|
||||
@ -1171,6 +1202,21 @@ 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;
|
||||
@ -1196,6 +1242,14 @@ 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;
|
||||
@ -1270,11 +1324,9 @@ bool8 S9xUnfreezeGame (const char *filename)
|
||||
|
||||
void S9xFreezeToStream (STREAM stream)
|
||||
{
|
||||
char buffer[1024];
|
||||
char buffer[8192];
|
||||
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);
|
||||
|
||||
@ -1413,19 +1465,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) != len)
|
||||
if (READ_STREAM(buffer, len, stream) != (unsigned int ) len)
|
||||
return (WRONG_FORMAT);
|
||||
|
||||
if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0)
|
||||
@ -1486,19 +1538,31 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000);
|
||||
if (fast)
|
||||
result = UnfreezeBlock(stream, "VRA", Memory.VRAM, 0x10000);
|
||||
else
|
||||
result = UnfreezeBlockCopy(stream, "VRA", &local_vram, 0x10000);
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000);
|
||||
if (fast)
|
||||
result = UnfreezeBlock(stream, "RAM", Memory.RAM, 0x20000);
|
||||
else
|
||||
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);
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000);
|
||||
if (fast)
|
||||
result = UnfreezeBlock(stream, "FIL", Memory.FillRAM, 0x8000);
|
||||
else
|
||||
result = UnfreezeBlockCopy(stream, "FIL", &local_fillram, 0x8000);
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
@ -1538,9 +1602,19 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (result != SUCCESS && Settings.DSP == 4)
|
||||
break;
|
||||
|
||||
result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192);
|
||||
if (result != SUCCESS && Settings.C4)
|
||||
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 = UnfreezeStructCopy(stream, "ST0", &local_st010, SnapST010, COUNT(SnapST010), version);
|
||||
if (result != SUCCESS && Settings.SETA == ST_010)
|
||||
@ -1550,9 +1624,19 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (result != SUCCESS && Settings.OBC1)
|
||||
break;
|
||||
|
||||
result = UnfreezeBlockCopy (stream, "OBM", &local_obc1_data, 8192);
|
||||
if (result != SUCCESS && Settings.OBC1)
|
||||
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 = UnfreezeStructCopy(stream, "S71", &local_spc7110, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), version);
|
||||
if (result != SUCCESS && Settings.SPC7110)
|
||||
@ -1615,9 +1699,15 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
uint32 old_flags = CPU.Flags;
|
||||
uint32 sa1_old_flags = SA1.Flags;
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
|
||||
if (fast)
|
||||
{
|
||||
S9xResetPPUFast();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do not call this if you have written directly to "Memory." arrays
|
||||
S9xReset();
|
||||
}
|
||||
|
||||
UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version);
|
||||
|
||||
@ -1628,12 +1718,16 @@ 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);
|
||||
|
||||
if (local_ram)
|
||||
memcpy(Memory.RAM, local_ram, 0x20000);
|
||||
|
||||
if (local_sram)
|
||||
memcpy(Memory.SRAM, local_sram, 0x20000);
|
||||
|
||||
if (local_fillram)
|
||||
memcpy(Memory.FillRAM, local_fillram, 0x8000);
|
||||
|
||||
S9xAPULoadState(local_apu_sound);
|
||||
@ -1691,11 +1785,46 @@ 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++)
|
||||
@ -1705,6 +1834,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
CPU.HDMARanInDMA = 0;
|
||||
|
||||
S9xFixColourBrightness();
|
||||
S9xBuildDirectColourMaps();
|
||||
IPPU.ColorsChanged = TRUE;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
IPPU.RenderThisFrame = TRUE;
|
||||
@ -1807,11 +1937,9 @@ 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;
|
||||
@ -2007,6 +2135,51 @@ 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];
|
||||
@ -2019,7 +2192,9 @@ 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);
|
||||
}
|
||||
@ -2043,9 +2218,12 @@ static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int siz
|
||||
len = size;
|
||||
}
|
||||
|
||||
ZeroMemory(block, size);
|
||||
if (!Settings.FastSavestates)
|
||||
{
|
||||
memset(block, 0, size);
|
||||
}
|
||||
|
||||
if (READ_STREAM(block, len, stream) != len)
|
||||
if (READ_STREAM(block, len, stream) != (unsigned int) len)
|
||||
{
|
||||
REVERT_STREAM(stream, rewind, 0);
|
||||
return (WRONG_FORMAT);
|
||||
@ -2070,6 +2248,13 @@ 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);
|
||||
@ -2257,28 +2442,3 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool8 S9xSPCDump (const char *filename)
|
||||
{
|
||||
FILE *fs;
|
||||
uint8 buf[SNES_SPC::spc_file_size];
|
||||
size_t ignore;
|
||||
|
||||
fs = fopen(filename, "wb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
|
||||
spc_core->init_header(buf);
|
||||
spc_core->save_spc(buf);
|
||||
|
||||
ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs);
|
||||
|
||||
fclose(fs);
|
||||
|
||||
S9xSetSoundMute(FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,14 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
|
||||
MSU-1 code
|
||||
(c) Copyright 2016 qwertymodo
|
||||
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
|
||||
@ -181,8 +193,12 @@
|
||||
#ifndef _SNAPSHOT_H_
|
||||
#define _SNAPSHOT_H_
|
||||
|
||||
#include "snes9x.h"
|
||||
|
||||
#define SNAPSHOT_MAGIC "#!s9xsnp"
|
||||
#define SNAPSHOT_VERSION 7
|
||||
#define SNAPSHOT_VERSION_IRQ 7
|
||||
#define SNAPSHOT_VERSION_BAPU 8
|
||||
#define SNAPSHOT_VERSION 10
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
@ -194,9 +210,11 @@
|
||||
|
||||
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
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -190,29 +205,42 @@
|
||||
|
||||
#ifdef ZLIB
|
||||
#include <zlib.h>
|
||||
#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)
|
||||
#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)
|
||||
#else
|
||||
#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)
|
||||
#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)
|
||||
#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
|
||||
@ -228,9 +256,15 @@
|
||||
#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)
|
||||
@ -263,8 +297,6 @@
|
||||
#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)
|
||||
@ -274,12 +306,16 @@
|
||||
|
||||
struct SCPUState
|
||||
{
|
||||
uint32 Flags;
|
||||
int32 Cycles;
|
||||
int32 PrevCycles;
|
||||
int32 V_Counter;
|
||||
uint32 Flags;
|
||||
uint8 *PCBase;
|
||||
bool8 IRQActive;
|
||||
bool8 NMIPending;
|
||||
bool8 IRQLine;
|
||||
bool8 IRQTransition;
|
||||
bool8 IRQLastState;
|
||||
bool8 IRQExternal;
|
||||
int32 IRQPending;
|
||||
int32 MemSpeed;
|
||||
int32 MemSpeedx2;
|
||||
@ -293,9 +329,6 @@ struct SCPUState
|
||||
uint8 WhichEvent;
|
||||
int32 NextEvent;
|
||||
bool8 WaitingForInterrupt;
|
||||
uint32 WaitAddress;
|
||||
uint32 WaitCounter;
|
||||
uint32 PBPCAtOpcodeStart;
|
||||
uint32 AutoSaveTimer;
|
||||
bool8 SRAMModified;
|
||||
};
|
||||
@ -303,17 +336,18 @@ struct SCPUState
|
||||
enum
|
||||
{
|
||||
HC_HBLANK_START_EVENT = 1,
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
struct STimings
|
||||
@ -327,12 +361,14 @@ 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 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode.
|
||||
int32 IRQFlagChanging; // This value is just a hack.
|
||||
int32 APUSpeedup;
|
||||
bool8 APUAllowTimeOverflow;
|
||||
};
|
||||
@ -345,6 +381,7 @@ struct SSettings
|
||||
bool8 TraceUnknownRegisters;
|
||||
bool8 TraceDSP;
|
||||
bool8 TraceHCEvent;
|
||||
bool8 TraceSMP;
|
||||
|
||||
bool8 SuperFX;
|
||||
uint8 DSP;
|
||||
@ -364,6 +401,7 @@ struct SSettings
|
||||
bool8 SuperScopeMaster;
|
||||
bool8 JustifierMaster;
|
||||
bool8 MultiPlayer5Master;
|
||||
bool8 MacsRifleMaster;
|
||||
|
||||
bool8 ForceLoROM;
|
||||
bool8 ForceHiROM;
|
||||
@ -400,18 +438,15 @@ 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;
|
||||
@ -424,6 +459,7 @@ struct SSettings
|
||||
bool8 TurboMode;
|
||||
uint32 HighSpeedSeek;
|
||||
bool8 FrameAdvance;
|
||||
bool8 Rewinding;
|
||||
|
||||
bool8 NetPlay;
|
||||
bool8 NetPlayServer;
|
||||
@ -439,15 +475,23 @@ 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;
|
||||
float SuperFXSpeedPerLine;
|
||||
|
||||
uint32 SuperFXClockMultiplier;
|
||||
int OneClockCycle;
|
||||
int OneSlowClockCycle;
|
||||
int TwoClockCycles;
|
||||
int MaxSpriteTilesPerLine;
|
||||
};
|
||||
|
||||
struct SSNESGameFixes
|
||||
|
@ -17,13 +17,20 @@
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
(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,
|
||||
@ -117,6 +124,9 @@
|
||||
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)
|
||||
|
||||
@ -130,7 +140,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
(c) Copyright 2004 - 2018 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@ -138,11 +148,16 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
(c) Copyright 2009 - 2018 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
(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
|
||||
@ -474,7 +489,6 @@ static uint8 ConvertTile4h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile)
|
||||
#undef DOBIT
|
||||
|
||||
// First-level include: Get all the renderers.
|
||||
|
||||
#include "tile.cpp"
|
||||
|
||||
// Functions to select which converter and renderer to use.
|
||||
@ -697,13 +711,11 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
}
|
||||
|
||||
#define IS_BLANK_TILE() \
|
||||
(BG.Buffered[TileNumber] == BLANK_TILE)
|
||||
( ( (Tile & H_FLIP) ? BG.BufferedFlip[TileNumber] : BG.Buffered[TileNumber]) == BLANK_TILE)
|
||||
|
||||
#define SELECT_PALETTE() \
|
||||
if (BG.DirectColourMode) \
|
||||
{ \
|
||||
if (IPPU.DirectColourMapsNeedRebuild) \
|
||||
S9xBuildDirectColourMaps(); \
|
||||
GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; \
|
||||
} \
|
||||
else \
|
||||
@ -749,6 +761,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & (V_FLIP | H_FLIP))) \
|
||||
{ \
|
||||
bp = pCache + BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
DRAW_PIXEL(0, Pix = bp[0]); \
|
||||
@ -765,6 +778,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & V_FLIP)) \
|
||||
{ \
|
||||
bp = pCache + BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
DRAW_PIXEL(0, Pix = bp[7]); \
|
||||
@ -781,6 +795,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & H_FLIP)) \
|
||||
{ \
|
||||
bp = pCache + 56 - BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
DRAW_PIXEL(0, Pix = bp[0]); \
|
||||
@ -796,6 +811,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
else \
|
||||
{ \
|
||||
bp = pCache + 56 - BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
DRAW_PIXEL(0, Pix = bp[7]); \
|
||||
@ -840,18 +856,19 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & (V_FLIP | H_FLIP))) \
|
||||
{ \
|
||||
bp = pCache + BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
w = Width; \
|
||||
switch (StartPixel) \
|
||||
{ \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; /* Fall through */ \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; /* Fall through */ \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; /* Fall through */ \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; /* Fall through */ \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; /* Fall through */ \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; /* Fall through */ \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; /* Fall through */ \
|
||||
case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \
|
||||
} \
|
||||
} \
|
||||
@ -860,18 +877,19 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & V_FLIP)) \
|
||||
{ \
|
||||
bp = pCache + BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
w = Width; \
|
||||
switch (StartPixel) \
|
||||
{ \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; /* Fall through */ \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; /* Fall through */ \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; /* Fall through */ \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; /* Fall through */ \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; /* Fall through */ \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; /* Fall through */ \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; /* Fall through */ \
|
||||
case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \
|
||||
} \
|
||||
} \
|
||||
@ -880,18 +898,19 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
if (!(Tile & H_FLIP)) \
|
||||
{ \
|
||||
bp = pCache + 56 - BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
w = Width; \
|
||||
switch (StartPixel) \
|
||||
{ \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; /* Fall through */ \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; /* Fall through */ \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; /* Fall through */ \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; /* Fall through */ \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; /* Fall through */ \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; /* Fall through */ \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; /* Fall through */ \
|
||||
case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \
|
||||
} \
|
||||
} \
|
||||
@ -899,18 +918,19 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
else \
|
||||
{ \
|
||||
bp = pCache + 56 - BPSTART; \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \
|
||||
{ \
|
||||
w = Width; \
|
||||
switch (StartPixel) \
|
||||
{ \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \
|
||||
case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; /* Fall through */ \
|
||||
case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; /* Fall through */ \
|
||||
case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; /* Fall through */ \
|
||||
case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; /* Fall through */ \
|
||||
case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; /* Fall through */ \
|
||||
case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; /* Fall through */ \
|
||||
case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; /* Fall through */ \
|
||||
case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \
|
||||
} \
|
||||
} \
|
||||
@ -955,6 +975,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
\
|
||||
if (Pix) \
|
||||
{ \
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = LineCount; l > 0; l--, Offset += GFX.PPL) \
|
||||
{ \
|
||||
for (w = Width - 1; w >= 0; w--) \
|
||||
@ -991,6 +1012,7 @@ void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic)
|
||||
GFX.RealScreenColors = IPPU.ScreenColors; \
|
||||
GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \
|
||||
\
|
||||
OFFSET_IN_LINE; \
|
||||
for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) \
|
||||
{ \
|
||||
for (x = Left; x < Right; x++) \
|
||||
@ -1036,8 +1058,6 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
\
|
||||
if (DCMODE) \
|
||||
{ \
|
||||
if (IPPU.DirectColourMapsNeedRebuild) \
|
||||
S9xBuildDirectColourMaps(); \
|
||||
GFX.RealScreenColors = DirectColourMaps[0]; \
|
||||
} \
|
||||
else \
|
||||
@ -1051,6 +1071,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
uint32 Offset = GFX.StartY * GFX.PPL; \
|
||||
struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; \
|
||||
\
|
||||
OFFSET_IN_LINE; \
|
||||
for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) \
|
||||
{ \
|
||||
int yy, starty; \
|
||||
@ -1133,8 +1154,6 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
\
|
||||
if (DCMODE) \
|
||||
{ \
|
||||
if (IPPU.DirectColourMapsNeedRebuild) \
|
||||
S9xBuildDirectColourMaps(); \
|
||||
GFX.RealScreenColors = DirectColourMaps[0]; \
|
||||
} \
|
||||
else \
|
||||
@ -1166,6 +1185,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
uint32 Offset = StartY * GFX.PPL; \
|
||||
struct SLineMatrixData *l = &LineMatrixData[StartY]; \
|
||||
\
|
||||
OFFSET_IN_LINE; \
|
||||
for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) \
|
||||
{ \
|
||||
if (Line + VMosaic > GFX.EndY) \
|
||||
@ -1341,6 +1361,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
// The 1x1 pixel plotter, for speedhacking modes.
|
||||
|
||||
#define OFFSET_IN_LINE
|
||||
#define DRAW_PIXEL(N, M) \
|
||||
if (Z1 > GFX.DB[Offset + N] && (M)) \
|
||||
{ \
|
||||
@ -1375,6 +1396,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
#undef NAME2
|
||||
#undef DRAW_PIXEL
|
||||
#undef OFFSET_IN_LINE
|
||||
|
||||
// Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images.
|
||||
// Use it only on the main screen, subscreen should use Normal2x1 instead.
|
||||
@ -1388,11 +1410,16 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
#define DRAW_PIXEL_H2x1(N, M) \
|
||||
if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \
|
||||
{ \
|
||||
GFX.S[Offset + 2 * N] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \
|
||||
GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \
|
||||
if ((OffsetInLine + 2 * N ) != (SNES_WIDTH - 1) << 1) \
|
||||
GFX.S[Offset + 2 * N + 2] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \
|
||||
if ((OffsetInLine + 2 * N) == 0) \
|
||||
GFX.S[Offset + 2 * N] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \
|
||||
GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \
|
||||
}
|
||||
|
||||
#define OFFSET_IN_LINE \
|
||||
uint32 OffsetInLine = Offset % GFX.RealPPL;
|
||||
#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M)
|
||||
#define NAME2 Hires
|
||||
|
||||
@ -1402,6 +1429,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
#undef NAME2
|
||||
#undef DRAW_PIXEL
|
||||
#undef OFFSET_IN_LINE
|
||||
|
||||
// Interlace: Only draw every other line, so we'll redefine BPSTART and PITCH to do so.
|
||||
// Otherwise, it's the same as Normal2x1/Hires2x1.
|
||||
@ -1414,6 +1442,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
#ifndef NO_INTERLACE
|
||||
|
||||
#define OFFSET_IN_LINE
|
||||
#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M)
|
||||
#define NAME2 Interlace
|
||||
|
||||
@ -1423,7 +1452,10 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
#undef NAME2
|
||||
#undef DRAW_PIXEL
|
||||
#undef OFFSET_IN_LINE
|
||||
|
||||
#define OFFSET_IN_LINE \
|
||||
uint32 OffsetInLine = Offset % GFX.RealPPL;
|
||||
#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M)
|
||||
#define NAME2 HiresInterlace
|
||||
|
||||
@ -1433,6 +1465,7 @@ extern struct SLineMatrixData LineMatrixData[240];
|
||||
|
||||
#undef NAME2
|
||||
#undef DRAW_PIXEL
|
||||
#undef OFFSET_IN_LINE
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -518,13 +518,7 @@ int main(int argc, char *argv[])
|
||||
BrowserLoadFile();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
Settings.SuperFXClockMultiplier = GCSettings.superFxSpeed;
|
||||
|
||||
while (1) // main loop
|
||||
{
|
||||
|
@ -121,7 +121,7 @@ struct SGCSettings{
|
||||
int language;
|
||||
int PreviewImage;
|
||||
|
||||
int sfxOverclock;
|
||||
int superFxSpeed;
|
||||
};
|
||||
|
||||
void ExitApp();
|
||||
|
Loading…
Reference in New Issue
Block a user