Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 54 changed files
... ...
@@ -1,19 +1,14 @@
1 1
 set(HEADERS
2 2
 	snes9x/65c816.h
3 3
 	snes9x/apu/apu.h
4
-	snes9x/apu/blargg_common.h
5
-	snes9x/apu/blargg_config.h
6
-	snes9x/apu/blargg_endian.h
7
-	snes9x/apu/bspline_resampler.h
8
-	snes9x/apu/hermite_resampler.h
9
-	snes9x/apu/linear_resampler.h
10
-	snes9x/apu/osculating_resampler.h
4
+	snes9x/apu/bapu/dsp/blargg_common.h
5
+	snes9x/apu/bapu/dsp/blargg_config.h
6
+	snes9x/apu/bapu/dsp/blargg_endian.h
7
+	snes9x/apu/bapu/dsp/sdsp.hpp
8
+	snes9x/apu/bapu/dsp/SPC_DSP.h
9
+	snes9x/apu/bapu/smp/smp.hpp
10
+	snes9x/apu/bapu/snes/snes.hpp
11 11
 	snes9x/apu/resampler.h
12
-	snes9x/apu/ring_buffer.h
13
-	snes9x/apu/sinc_resampler.h
14
-	snes9x/apu/SNES_SPC.h
15
-	snes9x/apu/SPC_CPU.h
16
-	snes9x/apu/SPC_DSP.h
17 12
 	snes9x/cpuaddr.h
18 13
 	snes9x/cpuexec.h
19 14
 	snes9x/cpumacro.h
... ...
@@ -28,9 +23,14 @@ set(HEADERS
28 23
 	XSFConfigDialog_SNSF.h)
29 24
 set(SNES9X_SOURCES
30 25
 	snes9x/apu/apu.cpp
31
-	snes9x/apu/SNES_SPC.cpp
32
-	snes9x/apu/SNES_SPC_misc.cpp
33
-	snes9x/apu/SPC_DSP.cpp
26
+	snes9x/apu/bapu/dsp/sdsp.cpp
27
+	snes9x/apu/bapu/dsp/SPC_DSP.cpp
28
+	snes9x/apu/bapu/smp/algorithms.cpp
29
+	snes9x/apu/bapu/smp/core.cpp
30
+	snes9x/apu/bapu/smp/iplrom.cpp
31
+	snes9x/apu/bapu/smp/memory.cpp
32
+	snes9x/apu/bapu/smp/smp.cpp
33
+	snes9x/apu/bapu/smp/timing.cpp
34 34
 	snes9x/cpu.cpp
35 35
 	snes9x/cpuexec.cpp
36 36
 	snes9x/cpuops.cpp
... ...
@@ -56,6 +56,6 @@ set_target_properties(in_snsf PROPERTIES PREFIX "")
56 56
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Header Files" FILES ${HEADERS})
57 57
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCES})
58 58
 target_compile_options(in_snsf PUBLIC
59
-	$<$<CXX_COMPILER_ID:MSVC>:/wd4127 /wd4245 /wd6385 /wd6386 /wd26453 /wd26495 /wd26812 /wd26819>)
59
+	$<$<CXX_COMPILER_ID:MSVC>:/wd4127 /wd4245 /wd4389 /wd6385 /wd6386 /wd26439 /wd26453 /wd26495 /wd26812 /wd26819>)
60 60
 target_link_libraries(in_snsf
61 61
 	in_xsf_framework)
... ...
@@ -31,19 +31,19 @@
31 31
 
32 32
 XSFConfigDialog_SNSF::XSFConfigDialog_SNSF(XSFConfig &newConfig, wxWindow *parent, const wxString &title) : XSFConfigDialog(newConfig, parent, title)
33 33
 {
34
-	auto reverseStereoCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Reverse Stereo", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->reverseStereo });
35
-	this->outputSizer->Add(reverseStereoCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
34
+	auto separateEchoBufferCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Separate Echo Buffer", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->separateEchoBuffer });
35
+	this->outputSizer->Add(separateEchoBufferCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
36 36
 
37
-	auto resamplerLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Resampler");
38
-	this->outputSizer->Add(resamplerLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
39
-	wxArrayString resamplerChoices;
40
-	resamplerChoices.Add("Linear Resampler");
41
-	resamplerChoices.Add("Hermite Resampler");
42
-	resamplerChoices.Add("Bspline Resampler");
43
-	resamplerChoices.Add("Osculating Resampler");
44
-	resamplerChoices.Add("Sinc Resampler");
45
-	auto resamplerChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, resamplerChoices, 0, wxGenericValidator{ &this->resampler });
46
-	this->outputSizer->Add(resamplerChoice, { 5, 1 }, { 1, 1 }, wxALL, 5);
37
+	auto interpolationLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Interpolation");
38
+	this->outputSizer->Add(interpolationLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
39
+	wxArrayString interpolationChoices;
40
+	interpolationChoices.Add("None");
41
+	interpolationChoices.Add("Linear");
42
+	interpolationChoices.Add("Guassian");
43
+	interpolationChoices.Add("Cubic");
44
+	interpolationChoices.Add("Sinc");
45
+	auto interpolationChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, interpolationChoices, 0, wxGenericValidator{ &this->interpolation });
46
+	this->outputSizer->Add(interpolationChoice, { 5, 1 }, { 1, 1 }, wxALL, 5);
47 47
 
48 48
 	auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
49 49
 	this->outputSizer->Add(muteLabel, { 6, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
... ...
@@ -31,7 +31,7 @@ class XSFConfigDialog_SNSF : public XSFConfigDialog
31 31
 public:
32 32
 	XSFConfigDialog_SNSF(XSFConfig &newConfig, wxWindow *parent, const wxString &title);
33 33
 
34
-	bool reverseStereo;
35
-	int resampler;
34
+	bool separateEchoBuffer;
35
+	int interpolation;
36 36
 	wxArrayInt mute;
37 37
 };
... ...
@@ -3,10 +3,6 @@
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4 4
  *
5 5
  * Partially based on the vio*sf framework
6
- *
7
- * NOTE: 16-bit sound is always enabled, the player is currently limited to
8
- * creating a 16-bit PCM for Winamp and can not handle 8-bit sound from
9
- * snes9x.
10 6
  */
11 7
 
12 8
 #include <bitset>
... ...
@@ -40,7 +36,7 @@ XSFConfig *XSFConfig::Create()
40 36
 	return new XSFConfig_SNSF();
41 37
 }
42 38
 
43
-XSFConfig_SNSF::XSFConfig_SNSF() : XSFConfig(), /*sixteenBitSound(false), */reverseStereo(false), mutes(), resampler(0)
39
+XSFConfig_SNSF::XSFConfig_SNSF() : XSFConfig(), separateEchoBuffer(false), interpolation(0), mutes()
44 40
 {
45 41
 	this->supportedSampleRates.push_back(8000);
46 42
 	this->supportedSampleRates.push_back(11025);
... ...
@@ -57,26 +53,24 @@ XSFConfig_SNSF::XSFConfig_SNSF() : XSFConfig(), /*sixteenBitSound(false), */reve
57 53
 
58 54
 void XSFConfig_SNSF::LoadSpecificConfig()
59 55
 {
60
-	//this->sixteenBitSound = this->configIO->GetValue("SixteenBitSound", XSFConfig_SNSF::initSixteenBitSound);
61
-	this->reverseStereo = this->configIO->GetValue("ReverseStereo", XSFConfig_SNSF::initReverseStereo);
62
-	this->resampler = this->configIO->GetValue("Resampler", XSFConfig_SNSF::initResampler);
56
+	this->separateEchoBuffer = this->configIO->GetValue("SeparateEchoBuffer", XSFConfig_SNSF::initSeparateEchoBuffer);
57
+	this->interpolation = this->configIO->GetValue("Interpolation", XSFConfig_SNSF::initInterpolation);
63 58
 	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_SNSF::initMutes));
64 59
 	mutesSS >> this->mutes;
65 60
 }
66 61
 
67 62
 void XSFConfig_SNSF::SaveSpecificConfig()
68 63
 {
69
-	//this->configIO->SetValue("SixteenBitSound", this->sixteenBitSound);
70
-	this->configIO->SetValue("ReverseStereo", this->reverseStereo);
71
-	this->configIO->SetValue("Resampler", this->resampler);
64
+	this->configIO->SetValue("SeparateEchoBuffer", this->separateEchoBuffer);
65
+	this->configIO->SetValue("Interpolation", this->interpolation);
72 66
 	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
73 67
 }
74 68
 
75 69
 void XSFConfig_SNSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
76 70
 {
77 71
 	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
78
-	snsfDialog->reverseStereo = this->reverseStereo;
79
-	snsfDialog->resampler = static_cast<int>(this->resampler);
72
+	snsfDialog->separateEchoBuffer = this->separateEchoBuffer;
73
+	snsfDialog->interpolation = static_cast<int>(this->interpolation);
80 74
 	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
81 75
 		if (this->mutes[x])
82 76
 			snsfDialog->mute.Add(x);
... ...
@@ -85,8 +79,8 @@ void XSFConfig_SNSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
85 79
 void XSFConfig_SNSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
86 80
 {
87 81
 	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
88
-	snsfDialog->reverseStereo = XSFConfig_SNSF::initReverseStereo;
89
-	snsfDialog->resampler = XSFConfig_SNSF::initResampler;
82
+	snsfDialog->separateEchoBuffer = XSFConfig_SNSF::initSeparateEchoBuffer;
83
+	snsfDialog->interpolation = XSFConfig_SNSF::initInterpolation;
90 84
 	snsfDialog->mute.Clear();
91 85
 	auto tmpMutes = std::bitset<8>(XSFConfig_SNSF::initMutes);
92 86
 	for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
... ...
@@ -97,8 +91,8 @@ void XSFConfig_SNSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
97 91
 void XSFConfig_SNSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
98 92
 {
99 93
 	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
100
-	this->reverseStereo = snsfDialog->reverseStereo;
101
-	this->resampler = snsfDialog->resampler;
94
+	this->separateEchoBuffer = snsfDialog->separateEchoBuffer;
95
+	this->interpolation = snsfDialog->interpolation;
102 96
 	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
103 97
 		this->mutes[x] = snsfDialog->mute.Index(x) != wxNOT_FOUND;
104 98
 }
... ...
@@ -108,8 +102,8 @@ void XSFConfig_SNSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
108 102
 	if (preLoad)
109 103
 	{
110 104
 		memset(&Settings, 0, sizeof(Settings));
111
-		//Settings.SixteenBitSound = this->sixteenBitSound;
112
-		Settings.ReverseStereo = this->reverseStereo;
105
+		Settings.SeparateEchoBuffer = this->separateEchoBuffer;
106
+		Settings.InterpolationMethod = this->interpolation;
113 107
 	}
114 108
 	else
115 109
 		S9xSetSoundControl(static_cast<std::uint8_t>(this->mutes.to_ulong()) ^ 0xFF);
... ...
@@ -118,7 +112,7 @@ void XSFConfig_SNSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
118 112
 void XSFConfig_SNSF::About(HWND parent)
119 113
 {
120 114
 	MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
121
-		"Utilizes modified snes9x v1.53 for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
115
+		"Utilizes modified snes9x v" VERSION " for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
122 116
 }
123 117
 
124 118
 XSFConfigDialog *XSFConfig_SNSF::CreateDialogBox(wxWindow *window, const std::string &title)
... ...
@@ -3,10 +3,6 @@
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4 4
  *
5 5
  * Partially based on the vio*sf framework
6
- *
7
- * NOTE: 16-bit sound is always enabled, the player is currently limited to
8
- * creating a 16-bit PCM for Winamp and can not handle 8-bit sound from
9
- * snes9x.
10 6
  */
11 7
 
12 8
 #pragma once
... ...
@@ -23,12 +19,13 @@ class XSFPlayer;
23 19
 class XSFConfig_SNSF : public XSFConfig
24 20
 {
25 21
 protected:
26
-	static constexpr bool /*initSixteenBitSound = true, */initReverseStereo = false;
27
-	static constexpr unsigned initResampler = 1;
22
+	static constexpr bool initSeparateEchoBuffer = false;
23
+	static constexpr unsigned initInterpolation = 2;
28 24
 	inline static const std::string initMutes = "00000000";
29 25
 
30 26
 	friend class XSFConfig;
31
-	bool /*sixteenBitSound, */reverseStereo;
27
+	bool separateEchoBuffer;
28
+	unsigned interpolation;
32 29
 	std::bitset<8> mutes;
33 30
 
34 31
 	XSFConfig_SNSF();
... ...
@@ -39,8 +36,6 @@ protected:
39 36
 	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
40 37
 	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
41 38
 public:
42
-	unsigned resampler;
43
-
44 39
 	void About(HWND parent) override;
45 40
 	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
46 41
 };
... ...
@@ -20,18 +20,13 @@
20 20
 #include <cstdint>
21 21
 #include <zlib.h>
22 22
 #include "XSFCommon.h"
23
-#include "XSFConfig_SNSF.h"
23
+#include "XSFConfig.h"
24 24
 #include "XSFPlayer.h"
25 25
 
26 26
 #undef min
27 27
 #undef max
28 28
 
29 29
 #include "snes9x/apu/apu.h"
30
-#include "snes9x/apu/linear_resampler.h"
31
-#include "snes9x/apu/hermite_resampler.h"
32
-#include "snes9x/apu/bspline_resampler.h"
33
-#include "snes9x/apu/osculating_resampler.h"
34
-#include "snes9x/apu/sinc_resampler.h"
35 30
 #include "snes9x/memmap.h"
36 31
 
37 32
 class XSFPlayer_SNSF : public XSFPlayer
... ...
@@ -211,23 +206,12 @@ bool XSFPlayer_SNSF::Load()
211 206
 	Settings.SoundSync = true;
212 207
 	Settings.Mute = false;
213 208
 	Settings.SoundPlaybackRate = this->sampleRate;
214
-	Settings.SixteenBitSound = true;
215 209
 	Settings.Stereo = true;
216 210
 
217 211
 	Memory.Init();
218 212
 
219 213
 	S9xInitAPU();
220
-	XSFConfig_SNSF *xSFConfig_SNSF = dynamic_cast<XSFConfig_SNSF *>(xSFConfig.get());
221
-	if (xSFConfig_SNSF->resampler == 4)
222
-		S9xInitSound<SincResampler>(10, 0);
223
-	else if (xSFConfig_SNSF->resampler == 3)
224
-		S9xInitSound<OsculatingResampler>(10, 0);
225
-	else if (xSFConfig_SNSF->resampler == 2)
226
-		S9xInitSound<BsplineResampler>(10, 0);
227
-	else if (xSFConfig_SNSF->resampler == 1)
228
-		S9xInitSound<HermiteResampler>(10, 0);
229
-	else
230
-		S9xInitSound<LinearResampler>(10, 0);
214
+	S9xInitSound(10);
231 215
 
232 216
 	if (!buffer.Init())
233 217
 		return false;
... ...
@@ -1,191 +1,20 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
180
-const uint16_t Carry = 1;
181
-const uint16_t Zero = 2;
182
-const uint16_t IRQ = 4;
183
-const uint16_t Decimal = 8;
184
-const uint16_t IndexFlag = 16;
185
-const uint16_t MemoryFlag = 32;
186
-const uint16_t Overflow = 64;
187
-const uint16_t Negative = 128;
188
-const uint16_t Emulation = 256;
9
+inline constexpr uint16_t Carry = 1;
10
+inline constexpr uint16_t Zero = 2;
11
+inline constexpr uint16_t IRQ = 4;
12
+inline constexpr uint16_t Decimal = 8;
13
+inline constexpr uint16_t IndexFlag = 16;
14
+inline constexpr uint16_t MemoryFlag = 32;
15
+inline constexpr uint16_t Overflow = 64;
16
+inline constexpr uint16_t Negative = 128;
17
+inline constexpr uint16_t Emulation = 256;
189 18
 
190 19
 union pair
191 20
 {
192 21
similarity index 83%
193 22
rename from src/in_snsf/snes9x/docs/snes9x-license.txt
194 23
rename to src/in_snsf/snes9x/LICENSE
... ...
@@ -16,13 +16,20 @@
16 16
 
17 17
   (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
18 18
                              Nach (n-a-c-h@users.sourceforge.net),
19
-                             zones (kasumitokoduck@yahoo.com)
19
+
20
+  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
20 21
 
21 22
   (c) Copyright 2006 - 2007  nitsuja
22 23
 
23
-  (c) Copyright 2009 - 2010  BearOso,
24
+  (c) Copyright 2009 - 2019  BearOso,
24 25
                              OV2
25 26
 
27
+  (c) Copyright 2017         qwertymodo
28
+
29
+  (c) Copyright 2011 - 2017  Hans-Kristian Arntzen,
30
+                             Daniel De Matteis
31
+                             (Under no circumstances will commercial rights be given)
32
+
26 33
 
27 34
   BS-X C emulator code
28 35
   (c) Copyright 2005 - 2006  Dreamer Nom,
... ...
@@ -116,6 +123,9 @@
116 123
   Sound emulator code used in 1.52+
117 124
   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
118 125
 
126
+  S-SMP emulator code used in 1.54+
127
+  (c) Copyright 2016         byuu
128
+
119 129
   SH assembler code partly based on x86 assembler code
120 130
   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
121 131
 
... ...
@@ -129,7 +139,7 @@
129 139
   (c) Copyright 2006 - 2007  Shay Green
130 140
 
131 141
   GTK+ GUI code
132
-  (c) Copyright 2004 - 2010  BearOso
142
+  (c) Copyright 2004 - 2019  BearOso
133 143
 
134 144
   Win32 GUI code
135 145
   (c) Copyright 2003 - 2006  blip,
... ...
@@ -137,11 +147,16 @@
137 147
                              Matthew Kendora,
138 148
                              Nach,
139 149
                              nitsuja
140
-  (c) Copyright 2009 - 2010  OV2
150
+  (c) Copyright 2009 - 2019  OV2
141 151
 
142 152
   Mac OS GUI code
143 153
   (c) Copyright 1998 - 2001  John Stiles
144
-  (c) Copyright 2001 - 2010  zones
154
+  (c) Copyright 2001 - 2011  zones
155
+
156
+  Libretro port
157
+  (c) Copyright 2011 - 2017  Hans-Kristian Arntzen,
158
+                             Daniel De Matteis
159
+                             (Under no circumstances will commercial rights be given)
145 160
 
146 161
 
147 162
   Specific ports contains the works of other authors. See headers in
... ...
@@ -149,6 +164,7 @@
149 164
 
150 165
 
151 166
   Snes9x homepage: http://www.snes9x.com/
167
+  Snes9x source code: https://github.com/snes9xgit/snes9x/
152 168
 
153 169
   Permission to use, copy, modify and/or distribute Snes9x in both binary
154 170
   and source form, for non-commercial purposes, is hereby granted without
... ...
@@ -171,3 +187,12 @@
171 187
 
172 188
   Super NES and Super Nintendo Entertainment System are trademarks of
173 189
   Nintendo Co., Limited and its subsidiary companies.
190
+
191
+-------------------------------------------------------------------------------
192
+
193
+Some parts included in Snes9x are usually available under a different license,
194
+their authors have granted exception for their use in Snes9x (and/or they are
195
+licensed as LGPL):
196
+ - JMA: GPL/LGPL, see jma/license.txt
197
+ - snes_ntsc: LGPL, see filter/snes_ntsc-license.txt
198
+ - xBRZ: GPLv3, see filter/xbrz-license.txt
174 199
deleted file mode 100644
... ...
@@ -1,327 +0,0 @@
1
-// Core SPC emulation: CPU, timers, SMP registers, memory
2
-
3
-// snes_spc 0.9.0. http://www.slack.net/~ant/
4
-
5
-#include <algorithm>
6
-#include <cstring>
7
-#include "SNES_SPC.h"
8
-
9
-/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
10
-can redistribute it and/or modify it under the terms of the GNU Lesser
11
-General Public License as published by the Free Software Foundation; either
12
-version 2.1 of the License, or (at your option) any later version. This
13
-module is distributed in the hope that it will be useful, but WITHOUT ANY
14
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
-details. You should have received a copy of the GNU Lesser General Public
17
-License along with this module; if not, write to the Free Software Foundation,
18
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
-
20
-//// Timers
21
-
22
-#ifdef SPC_DISABLE_TEMPO
23
-template<typename T> static inline T TIMER_DIV(SNES_SPC::Timer *t, const T &n) { return n >> t->prescaler; }
24
-template<typename T> static inline T TIMER_MUL(SNES_SPC::Timer *t, const T &n) { return n << t->prescaler; }
25
-#else
26
-template<typename T> static inline T TIMER_DIV(SNES_SPC::Timer *t, const T &n) { return n / t->prescaler; }
27
-template<typename T> static inline T TIMER_MUL(SNES_SPC::Timer *t, const T &n) { return n * t->prescaler; }
28
-#endif
29
-
30
-auto SNES_SPC::run_timer_(Timer *t, rel_time_t time) -> Timer *
31
-{
32
-	int elapsed = TIMER_DIV(t, time - t->next_time) + 1;
33
-	t->next_time += TIMER_MUL(t, elapsed);
34
-
35
-	if (t->enabled)
36
-	{
37
-		int remain = IF_0_THEN_256(t->period - t->divider);
38
-		int divider = t->divider + elapsed;
39
-		int over = elapsed - remain;
40
-		if (over >= 0)
41
-		{
42
-			int n = over / t->period;
43
-			t->counter = (t->counter + 1 + n) & 0x0F;
44
-			divider = over - n * t->period;
45
-		}
46
-		t->divider = static_cast<uint8_t>(divider);
47
-	}
48
-	return t;
49
-}
50
-
51
-auto SNES_SPC::run_timer(Timer *t, rel_time_t time) -> Timer *
52
-{
53
-	if (time >= t->next_time)
54
-		t = this->run_timer_(t, time);
55
-	return t;
56
-}
57
-
58
-//// ROM
59
-
60
-void SNES_SPC::enable_rom(bool enable)
61
-{
62
-	if (this->m.rom_enabled != enable)
63
-	{
64
-		this->m.rom_enabled = this->dsp.rom_enabled = enable;
65
-		if (enable)
66
-			std::copy_n(&this->m.ram.ram[rom_addr], static_cast<int>(rom_size), &this->m.hi_ram[0]);
67
-		auto data = enable ? &this->m.rom[0] : &this->m.hi_ram[0];
68
-		std::copy_n(&data[0], static_cast<int>(rom_size), &this->m.ram.ram[rom_addr]);
69
-		// TODO: ROM can still get overwritten when DSP writes to echo buffer
70
-	}
71
-}
72
-
73
-//// DSP
74
-
75
-void SNES_SPC::RUN_DSP(rel_time_t time)
76
-{
77
-	int count = time - this->m.dsp_time;
78
-	if (count)
79
-	{
80
-		assert(count > 0);
81
-		this->m.dsp_time = time;
82
-		this->dsp.run(count);
83
-	}
84
-}
85
-
86
-int SNES_SPC::dsp_read(rel_time_t time)
87
-{
88
-	this->RUN_DSP(time);
89
-
90
-	int result = this->dsp.read(this->m.smp_regs[0][r_dspaddr] & 0x7F);
91
-
92
-#ifdef SPC_DSP_READ_HOOK
93
-	SPC_DSP_READ_HOOK(spc_time + time, this->m.smp_regs[0][r_dspaddr] & 0x7F, result);
94
-#endif
95
-
96
-	return result;
97
-}
98
-
99
-void SNES_SPC::dsp_write(int data, rel_time_t time)
100
-{
101
-	this->RUN_DSP(time);
102
-
103
-#ifdef SPC_DSP_WRITE_HOOK
104
-	SPC_DSP_WRITE_HOOK(this->m.spc_time + time, this->m.smp_regs[0][r_dspaddr], static_cast<uint8_t>(data));
105
-#endif
106
-
107
-	if (this->m.smp_regs[0][r_dspaddr] <= 0x7F)
108
-		this->dsp.write(this->m.smp_regs[0][r_dspaddr], data);
109
-}
110
-
111
-//// CPU write
112
-
113
-// divided into multiple functions to keep rarely-used functionality separate
114
-// so often-used functionality can be optimized better by compiler
115
-
116
-// If write isn't preceded by read, data has this added to it
117
-static const int no_read_before_write = 0x2000;
118
-
119
-void SNES_SPC::cpu_write_smp_reg_(int data, rel_time_t time, int addr)
120
-{
121
-	switch (addr)
122
-	{
123
-		case r_t0target:
124
-		case r_t1target:
125
-		case r_t2target:
126
-		{
127
-			auto t = &this->m.timers[addr - r_t0target];
128
-			int period = IF_0_THEN_256(data);
129
-			if (t->period != period)
130
-			{
131
-				t = this->run_timer(t, time);
132
-				t->period = period;
133
-			}
134
-			break;
135
-		}
136
-
137
-		case r_t0out:
138
-		case r_t1out:
139
-		case r_t2out:
140
-			if (data < no_read_before_write  / 2)
141
-				this->run_timer(&this->m.timers[addr - r_t0out], time - 1)->counter = 0;
142
-			break;
143
-
144
-		// Registers that act like RAM
145
-		case 0x8:
146
-		case 0x9:
147
-			this->m.smp_regs[1][addr] = static_cast<uint8_t>(data);
148
-			break;
149
-
150
-		case r_test:
151
-			break;
152
-
153
-		case r_control:
154
-			// port clears
155
-			if (data & 0x10)
156
-			{
157
-				this->m.smp_regs[1][r_cpuio0] = 0;
158
-				this->m.smp_regs[1][r_cpuio1] = 0;
159
-			}
160
-			if (data & 0x20)
161
-			{
162
-				this->m.smp_regs[1][r_cpuio2] = 0;
163
-				this->m.smp_regs[1][r_cpuio3] = 0;
164
-			}
165
-
166
-			// timers
167
-			for (int i = 0; i < timer_count; ++i)
168
-			{
169
-				auto t = &this->m.timers[i];
170
-				bool enabled = !!((data >> i) & 1);
171
-				if (t->enabled != enabled)
172
-				{
173
-					t = this->run_timer(t, time);
174
-					t->enabled = enabled;
175
-					if (enabled)
176
-						t->divider = t->counter = 0;
177
-				}
178
-			}
179
-			this->enable_rom(!!(data & 0x80));
180
-	}
181
-}
182
-
183
-void SNES_SPC::cpu_write_smp_reg(int data, rel_time_t time, int addr)
184
-{
185
-	if (addr == r_dspdata) // 99%
186
-		this->dsp_write(data, time);
187
-	else
188
-		this->cpu_write_smp_reg_(data, time, addr);
189
-}
190
-
191
-void SNES_SPC::cpu_write_high(int data, int i, rel_time_t time)
192
-{
193
-	if (i < rom_size)
194
-	{
195
-		this->m.hi_ram [i] = static_cast<uint8_t>(data);
196
-		if (this->m.rom_enabled)
197
-			this->m.ram.ram[i + rom_addr] = this->m.rom[i]; // restore overwritten ROM
198
-	}
199
-	else
200
-	{
201
-		assert(this->m.ram.ram[i + rom_addr] == static_cast<uint8_t>(data));
202
-		this->m.ram.ram[i + rom_addr] = cpu_pad_fill; // restore overwritten padding
203
-		this->cpu_write(data, i + rom_addr - 0x10000, time);
204
-	}
205
-}
206
-
207
-static const int bits_in_int = CHAR_BIT * sizeof(int);
208
-
209
-void SNES_SPC::cpu_write(int data, int addr, rel_time_t time)
210
-{
211
-	// RAM
212
-	this->m.ram.ram[addr] = static_cast<uint8_t>(data);
213
-	int reg = addr - 0xF0;
214
-	if (reg >= 0) // 64%
215
-	{
216
-		// $F0-$FF
217
-		if (reg < reg_count) // 87%
218
-		{
219
-			this->m.smp_regs[0][reg] = static_cast<uint8_t>(data);
220
-
221
-			// Ports
222
-#ifdef SPC_PORT_WRITE_HOOK
223
-			if (static_cast<unsigned>(reg - r_cpuio0) < port_count)
224
-				SPC_PORT_WRITE_HOOK(this->m.spc_time + time, (reg - r_cpuio0), static_cast<uint8_t>(data), &this->m.smp_regs[0][r_cpuio0]);
225
-#endif
226
-
227
-			// Registers other than $F2 and $F4-$F7
228
-			//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
229
-			// TODO: this is a bit on the fragile side
230
-			if (((~0x2F00 << (bits_in_int - 16)) << reg) < 0) // 36%
231
-				this->cpu_write_smp_reg(data, time, reg);
232
-		}
233
-		// High mem/address wrap-around
234
-		else
235
-		{
236
-			reg -= rom_addr - 0xF0;
237
-			if (reg >= 0) // 1% in IPL ROM area or address wrapped around
238
-				this->cpu_write_high(data, reg, time);
239
-		}
240
-	}
241
-}
242
-
243
-//// CPU read
244
-
245
-int SNES_SPC::cpu_read_smp_reg(int reg, rel_time_t time)
246
-{
247
-	int result = this->m.smp_regs[1][reg];
248
-	reg -= r_dspaddr;
249
-	// DSP addr and data
250
-	if (static_cast<unsigned>(reg) <= 1) // 4% 0xF2 and 0xF3
251
-	{
252
-		result = this->m.smp_regs[0][r_dspaddr];
253
-		if (static_cast<unsigned>(reg) == 1)
254
-			result = this->dsp_read(time); // 0xF3
255
-	}
256
-	return result;
257
-}
258
-
259
-int SNES_SPC::cpu_read(int addr, rel_time_t time)
260
-{
261
-	// RAM
262
-	int result = this->m.ram.ram[addr];
263
-	int reg = addr - 0xF0;
264
-	if (reg >= 0) // 40%
265
-	{
266
-		reg -= 0x10;
267
-		if (static_cast<unsigned>(reg) >= 0xFF00) // 21%
268
-		{
269
-			reg += 0x10 - r_t0out;
270
-
271
-			// Timers
272
-			if (static_cast<unsigned>(reg) < timer_count) // 90%
273
-			{
274
-				auto t = &this->m.timers[reg];
275
-				if (time >= t->next_time)
276
-					t = this->run_timer_(t, time);
277
-				result = t->counter;
278
-				t->counter = 0;
279
-			}
280
-			// Other registers
281
-			else if (reg < 0) // 10%
282
-				result = this->cpu_read_smp_reg(reg + r_t0out, time);
283
-			else // 1%
284
-			{
285
-				assert(reg + (r_t0out + 0xF0 - 0x10000) < 0x100);
286
-				result = this->cpu_read(reg + (r_t0out + 0xF0 - 0x10000), time);
287
-			}
288
-		}
289
-	}
290
-
291
-	return result;
292
-}
293
-
294
-//// Run
295
-
296
-static const int cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
297
-
298
-void SNES_SPC::end_frame(time_t end_time)
299
-{
300
-	// Catch CPU up to as close to end as possible. If final instruction
301
-	// would exceed end, does NOT execute it and leaves m.spc_time < end.
302
-	if (end_time > this->m.spc_time)
303
-		this->run_until_(end_time);
304
-
305
-	this->m.spc_time -= end_time;
306
-	this->m.extra_clocks += end_time;
307
-
308
-	// Greatest number of clocks early that emulation can stop early due to
309
-	// not being able to execute current instruction without going over
310
-	// allowed time.
311
-	assert(-cpu_lag_max <= this->m.spc_time && this->m.spc_time <= cpu_lag_max);
312
-
313
-	// Catch timers up to CPU
314
-	for (int i = 0; i < timer_count; ++i)
315
-		this->run_timer(&this->m.timers [i], 0);
316
-
317
-	// Catch DSP up to CPU
318
-	if (this->m.dsp_time < 0)
319
-		this->RUN_DSP(0);
320
-
321
-	// Save any extra samples beyond what should be generated
322
-	if (this->m.buf_begin)
323
-		this->save_extra();
324
-}
325
-
326
-// Inclusion here allows static memory access functions and better optimization
327
-#include "SPC_CPU.h"
328 0
deleted file mode 100644
... ...
@@ -1,236 +0,0 @@
1
-// SNES SPC-700 APU emulator
2
-
3
-// snes_spc 0.9.0
4
-#pragma once
5
-
6
-#include "SPC_DSP.h"
7
-#include "blargg_endian.h"
8
-
9
-// (n ? n : 256)
10
-template<typename T> inline T IF_0_THEN_256(const T &n) { return static_cast<uint8_t>(n - 1) + 1; }
11
-
12
-struct SNES_SPC
13
-{
14
-public:
15
-	// Must be called once before using
16
-	void init();
17
-
18
-	// Sample pairs generated per second
19
-	enum { sample_rate = 32000 };
20
-
21
-	// Emulator use
22
-
23
-	// Sets IPL ROM data. Library does not include ROM data. Most SPC music files
24
-	// don't need ROM, but a full emulator must provide this.
25
-	enum { rom_size = 0x40 };
26
-	void init_rom(const uint8_t rom[rom_size]);
27
-
28
-	// Sets destination for output samples
29
-	typedef short sample_t;
30
-	void set_output(sample_t *out, int out_size);
31
-
32
-	// Number of samples written to output since last set
33
-	int sample_count() const;
34
-
35
-	// Resets SPC to power-on state. This resets your output buffer, so you must
36
-	// call set_output() after this.
37
-	void reset();
38
-
39
-	// Emulates pressing reset switch on SNES. This resets your output buffer, so
40
-	// you must call set_output() after this.
41
-	void soft_reset();
42
-
43
-	// 1024000 SPC clocks per second, sample pair every 32 clocks
44
-	typedef int time_t;
45
-	enum { clock_rate = 1024000 };
46
-	enum { clocks_per_sample = 32 };
47
-
48
-	// Emulated port read/write at specified time
49
-	enum { port_count = 4 };
50
-	int read_port(time_t, int port);
51
-	void write_port(time_t, int port, int data);
52
-
53
-	// Runs SPC to end_time and starts a new time frame at 0
54
-	void end_frame(time_t end_time);
55
-
56
-	// Sound control
57
-
58
-	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
59
-	// Reduces emulation accuracy.
60
-	enum { voice_count = 8 };
61
-	void mute_voices(int mask);
62
-
63
-	// If true, prevents channels and global volumes from being phase-negated.
64
-	// Only supported by fast DSP.
65
-	void disable_surround(bool disable = true );
66
-
67
-	// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
68
-	enum { tempo_unit = 0x100 };
69
-	void set_tempo(int);
70
-
71
-	// SPC music files
72
-
73
-	// Clears echo region. Useful after loading an SPC as many have garbage in echo.
74
-	void clear_echo();
75
-
76
-	// Plays for count samples and write samples to out. Discards samples if out
77
-	// is NULL. Count must be a multiple of 2 since output is stereo.
78
-	void play(int count, sample_t *out);
79
-
80
-	// Skips count samples. Several times faster than play() when using fast DSP.
81
-	void skip(int count);
82
-
83
-	//// Snes9x Accessor
84
-
85
-	void spc_allow_time_overflow(bool);
86
-
87
-	void dsp_set_stereo_switch(int);
88
-	uint8_t dsp_reg_value(int, int);
89
-	int dsp_envx_value(int);
90
-
91
-public:
92
-	// Time relative to m_spc_time. Speeds up code a bit by eliminating need to
93
-	// constantly add m_spc_time to time from CPU. CPU uses time that ends at
94
-	// 0 to eliminate reloading end time every instruction. It pays off.
95
-	typedef int rel_time_t;
96
-
97
-	struct Timer
98
-	{
99
-		rel_time_t next_time; // time of next event
100
-		int prescaler;
101
-		int period;
102
-		int divider;
103
-		bool enabled;
104
-		int counter;
105
-	};
106
-	enum { reg_count = 0x10 };
107
-	enum { timer_count = 3 };
108
-	enum { extra_size = SPC_DSP::extra_size };
109
-
110
-private:
111
-	SPC_DSP dsp;
112
-
113
-	struct state_t
114
-	{
115
-		Timer timers[timer_count];
116
-
117
-		uint8_t smp_regs[2][reg_count];
118
-
119
-		struct
120
-		{
121
-			int pc;
122
-			int a;
123
-			int x;
124
-			int y;
125
-			int psw;
126
-			int sp;
127
-		} cpu_regs;
128
-
129
-		rel_time_t dsp_time;
130
-		time_t spc_time;
131
-
132
-		int tempo;
133
-
134
-		int extra_clocks;
135
-		sample_t *buf_begin;
136
-		const sample_t *buf_end;
137
-		sample_t *extra_pos;
138
-		sample_t extra_buf[extra_size];
139
-
140
-		bool rom_enabled;
141
-		uint8_t rom[rom_size];
142
-		uint8_t hi_ram[rom_size];
143
-
144
-		unsigned char cycle_table[256];
145
-
146
-		struct
147
-		{
148
-			// padding to neutralize address overflow
149
-			union
150
-			{
151
-				uint8_t padding1[0x100];
152
-				uint16_t align; // makes compiler align data for 16-bit access
153
-			} padding1[1];
154
-			uint8_t ram[0x10000];
155
-			uint8_t padding2[0x100];
156
-		} ram;
157
-	};
158
-	state_t m;
159
-
160
-	enum { rom_addr = 0xFFC0 };
161
-
162
-	enum { skipping_time = 127 };
163
-
164
-	// Value that padding should be filled with
165
-	enum { cpu_pad_fill = 0xFF };
166
-
167
-	enum
168
-	{
169
-		r_test = 0x0,
170
-		r_control = 0x1,
171
-		r_dspaddr = 0x2,
172
-		r_dspdata = 0x3,
173
-		r_cpuio0 = 0x4,
174
-		r_cpuio1 = 0x5,
175
-		r_cpuio2 = 0x6,
176
-		r_cpuio3 = 0x7,
177
-		r_f8 = 0x8,
178
-		r_f9 = 0x9,
179
-		r_t0target = 0xA,
180
-		r_t1target = 0xB,
181
-		r_t2target = 0xC,
182
-		r_t0out = 0xD,
183
-		r_t1out = 0xE,
184
-		r_t2out = 0xF
185
-	};
186
-
187
-	void timers_loaded();
188
-	void enable_rom(bool enable);
189
-	void reset_buf();
190
-	void save_extra();
191
-	void load_regs(const uint8_t in[reg_count]);
192
-	void ram_loaded();
193
-	void regs_loaded();
194
-	void reset_time_regs();
195
-	void reset_common(int timer_counter_init);
196
-
197
-	Timer *run_timer_(Timer *t, rel_time_t);
198
-	Timer *run_timer(Timer *t, rel_time_t);
199
-	void RUN_DSP(rel_time_t);
200
-	int dsp_read(rel_time_t);
201
-	void dsp_write(int data, rel_time_t);
202
-	void cpu_write_smp_reg_(int data, rel_time_t, int addr);
203
-	void cpu_write_smp_reg(int data, rel_time_t, int addr);
204
-	void cpu_write_high(int data, int i, rel_time_t);
205
-	void cpu_write(int data, int addr, rel_time_t);
206
-	int cpu_read_smp_reg(int i, rel_time_t);
207
-	int cpu_read(int addr, rel_time_t);
208
-	unsigned CPU_mem_bit(const uint8_t *pc, rel_time_t);
209
-
210
-	bool check_echo_access(int addr);
211
-	uint8_t *run_until_(time_t end_time);
212
-
213
-	// Snes9x timing hack
214
-	bool allow_time_overflow;
215
-};
216
-
217
-inline int SNES_SPC::sample_count() const { return (this->m.extra_clocks >> 5) * 2; }
218
-
219
-inline int SNES_SPC::read_port(time_t t, int port)
220
-{
221
-	assert(static_cast<unsigned>(port) < port_count);
222
-	return this->run_until_(t)[port];
223
-}
224
-
225
-inline void SNES_SPC::write_port(time_t t, int port, int data)
226
-{
227
-	assert(static_cast<unsigned>(port) < port_count);
228
-	this->run_until_(t)[0x10 + port] = data;
229
-	this->m.ram.ram[0xF4 + port] = data;
230
-}
231
-
232
-inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
233
-
234
-inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
235
-
236
-inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
237 0
deleted file mode 100644
... ...
@@ -1,307 +0,0 @@
1
-// SPC emulation support: init, sample buffering, reset, SPC loading
2
-
3
-// snes_spc 0.9.0. http://www.slack.net/~ant/
4
-
5
-#include <algorithm>
6
-#include <cstring>
7
-#include "SNES_SPC.h"
8
-
9
-/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
10
-can redistribute it and/or modify it under the terms of the GNU Lesser
11
-General Public License as published by the Free Software Foundation; either
12
-version 2.1 of the License, or (at your option) any later version. This
13
-module is distributed in the hope that it will be useful, but WITHOUT ANY
14
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
-details. You should have received a copy of the GNU Lesser General Public
17
-License along with this module; if not, write to the Free Software Foundation,
18
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
-
20
-//// Init
21
-
22
-void SNES_SPC::init()
23
-{
24
-	memset(&this->m, 0, sizeof(this->m));
25
-	this->dsp.init(this->m.ram.ram);
26
-
27
-	this->m.tempo = tempo_unit;
28
-
29
-	// Most SPC music doesn't need ROM, and almost all the rest only rely
30
-	// on these two bytes
31
-	this->m.rom[0x3E] = 0xFF;
32
-	this->m.rom[0x3F] = 0xC0;
33
-
34
-	static const unsigned char cycle_table[] =
35
-	{
36
-		//01    23    45    67    89    AB    CD    EF
37
-		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x54, 0x68, // 0
38
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x65, 0x22, 0x46, // 1
39
-		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x54, 0x74, // 2
40
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x65, 0x22, 0x38, // 3
41
-		0x28, 0x47, 0x34, 0x36, 0x26, 0x44, 0x54, 0x66, // 4
42
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x45, 0x22, 0x43, // 5
43
-		0x28, 0x47, 0x34, 0x36, 0x26, 0x44, 0x54, 0x75, // 6
44
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0x36, // 7
45
-		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x52, 0x45, // 8
46
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0xC5, // 9
47
-		0x38, 0x47, 0x34, 0x36, 0x26, 0x44, 0x52, 0x44, // A
48
-		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0x34, // B
49
-		0x38, 0x47, 0x45, 0x47, 0x25, 0x64, 0x52, 0x49, // C
50
-		0x48, 0x47, 0x56, 0x67, 0x45, 0x55, 0x22, 0x83, // D
51
-		0x28, 0x47, 0x34, 0x36, 0x24, 0x53, 0x43, 0x40, // E
52
-		0x48, 0x47, 0x45, 0x56, 0x34, 0x54, 0x22, 0x60  // F
53
-	};
54
-
55
-	// unpack cycle table
56
-	for (int i = 0; i < 128; ++i)
57
-	{
58
-		int n = cycle_table[i];
59
-		this->m.cycle_table[i * 2] = n >> 4;
60
-		this->m.cycle_table[i * 2 + 1] = n & 0x0F;
61
-	}
62
-
63
-	this->allow_time_overflow = false;
64
-
65
-	this->dsp.rom = this->m.rom;
66
-	this->dsp.hi_ram = this->m.hi_ram;
67
-
68
-	this->reset();
69
-}
70
-
71
-void SNES_SPC::init_rom(const uint8_t in[rom_size])
72
-{
73
-	std::copy_n(&in[0], static_cast<int>(rom_size), &this->m.rom[0]);
74
-}
75
-
76
-void SNES_SPC::set_tempo(int t)
77
-{
78
-	this->m.tempo = t;
79
-	static const int timer2_shift = 4; // 64 kHz
80
-	static const int other_shift = 3; //  8 kHz
81
-
82
-#ifdef SPC_DISABLE_TEMPO
83
-	this->m.timers[2].prescaler = timer2_shift;
84
-	this->m.timers[1].prescaler = timer2_shift + other_shift;
85
-	this->m.timers[0].prescaler = timer2_shift + other_shift;
86
-#else
87
-	if (!t)
88
-		t = 1;
89
-	static const int timer2_rate = 1 << timer2_shift;
90
-	int rate = (timer2_rate * tempo_unit + (t >> 1)) / t;
91
-	if (rate < timer2_rate / 4)
92
-		rate = timer2_rate / 4; // max 4x tempo
93
-	this->m.timers[2].prescaler = rate;
94
-	this->m.timers[1].prescaler = rate << other_shift;
95
-	this->m.timers[0].prescaler = rate << other_shift;
96
-#endif
97
-}
98
-
99
-// Timer registers have been loaded. Applies these to the timers. Does not
100
-// reset timer prescalers or dividers.
101
-void SNES_SPC::timers_loaded()
102
-{
103
-	for (int i = 0; i < timer_count; ++i)
104
-	{
105
-		auto &t = this->m.timers[i];
106
-		t.period = IF_0_THEN_256(this->m.smp_regs[0][r_t0target + i]);
107
-		t.enabled = !!((this->m.smp_regs[0][r_control] >> i) & 1);
108
-		t.counter = this->m.smp_regs[1][r_t0out + i] & 0x0F;
109
-	}
110
-
111
-	this->set_tempo(this->m.tempo);
112
-}
113
-
114
-// Loads registers from unified 16-byte format
115
-void SNES_SPC::load_regs(const uint8_t in[reg_count])
116
-{
117
-	std::copy_n(&in[0], static_cast<int>(reg_count), &this->m.smp_regs[0][0]);
118
-	std::copy_n(&this->m.smp_regs[0][0], static_cast<int>(reg_count), &this->m.smp_regs[1][0]);
119
-
120
-	// These always read back as 0
121
-	this->m.smp_regs[1][r_test] = this->m.smp_regs[1][r_control] = this->m.smp_regs[1][r_t0target] = this->m.smp_regs[1][r_t1target] = this->m.smp_regs[1][r_t2target] = 0;
122
-}
123
-
124
-// RAM was just loaded from SPC, with $F0-$FF containing SMP registers
125
-// and timer counts. Copies these to proper registers.
126
-void SNES_SPC::ram_loaded()
127
-{
128
-	this->m.rom_enabled = this->dsp.rom_enabled = false;
129
-	this->load_regs(&this->m.ram.ram[0xF0]);
130
-
131
-	// Put STOP instruction around memory to catch PC underflow/overflow
132
-	memset(this->m.ram.padding1, cpu_pad_fill, sizeof(this->m.ram.padding1));
133
-	memset(this->m.ram.padding2, cpu_pad_fill, sizeof(this->m.ram.padding2));
134
-}
135
-
136
-// Registers were just loaded. Applies these new values.
137
-void SNES_SPC::regs_loaded()
138
-{
139
-	this->enable_rom(!!(this->m.smp_regs[0][r_control] & 0x80));
140
-	this->timers_loaded();
141
-}
142
-
143
-void SNES_SPC::reset_time_regs()
144
-{
145
-	this->m.spc_time = 0;
146
-	this->m.dsp_time = 0;
147
-
148
-	std::for_each(&this->m.timers[0], &this->m.timers[timer_count], [](Timer &t)
149
-	{
150
-		t.next_time = 1;
151
-		t.divider = 0;
152
-	});
153
-
154
-	this->regs_loaded();
155
-
156
-	this->m.extra_clocks = 0;
157
-	this->reset_buf();
158
-}
159
-
160
-void SNES_SPC::reset_common(int timer_counter_init)
161
-{
162
-	std::fill_n(&this->m.smp_regs[1][r_t0out], static_cast<int>(timer_count), timer_counter_init);
163
-
164
-	// Run IPL ROM
165
-	memset(&this->m.cpu_regs, 0, sizeof(this->m.cpu_regs));
166
-	this->m.cpu_regs.pc = rom_addr;
167
-
168
-	this->m.smp_regs[0][r_test] = 0x0A;
169
-	this->m.smp_regs[0][r_control] = 0xB0; // ROM enabled, clear ports
170
-	std::fill_n(&this->m.smp_regs[1][r_cpuio0], static_cast<int>(port_count), 0);
171
-
172
-	this->reset_time_regs();
173
-}
174
-
175
-void SNES_SPC::soft_reset()
176
-{
177
-	this->reset_common(0);
178
-	this->dsp.soft_reset();
179
-}
180
-
181
-void SNES_SPC::reset()
182
-{
183
-	this->m.cpu_regs.pc = 0xFFC0;
184
-	this->m.cpu_regs.a = this->m.cpu_regs.x = this->m.cpu_regs.y = 0x00;
185
-	this->m.cpu_regs.psw = 0x02;
186
-	this->m.cpu_regs.sp = 0xEF;
187
-	std::fill_n(&this->m.ram.ram[0], 0x10000, 0);
188
-	this->ram_loaded();
189
-	this->reset_common(0x0F);
190
-	this->dsp.reset();
191
-}
192
-
193
-void SNES_SPC::clear_echo()
194
-{
195
-	if (!(this->dsp.read(SPC_DSP::r_flg) & 0x20))
196
-	{
197
-		int addr = 0x100 * this->dsp.read(SPC_DSP::r_esa);
198
-		int end  = addr + 0x800 * (this->dsp.read(SPC_DSP::r_edl) & 0x0F);
199
-		if (end > 0x10000)
200
-			end = 0x10000;
201
-		std::fill(&this->m.ram.ram[addr], &this->m.ram.ram[end], 0xFF);
202
-	}
203
-}
204
-
205
-//// Sample output
206
-
207
-void SNES_SPC::reset_buf()
208
-{
209
-	// Start with half extra buffer of silence
210
-	sample_t *out = this->m.extra_buf;
211
-	while (out < &this->m.extra_buf[extra_size / 2])
212
-		*out++ = 0;
213
-
214
-	this->m.extra_pos = out;
215
-	this->m.buf_begin = nullptr;
216
-
217
-	this->dsp.set_output(nullptr, 0);
218
-}
219
-
220
-void SNES_SPC::set_output(sample_t *out, int size)
221
-{
222
-	assert(!(size & 1)); // size must be even
223
-
224
-	this->m.extra_clocks &= clocks_per_sample - 1;
225
-	if (out)
226
-	{
227
-		auto out_end = out + size;
228
-		this->m.buf_begin = out;
229
-		this->m.buf_end = out_end;
230
-
231
-		// Copy extra to output
232
-		auto in = this->m.extra_buf;
233
-		while (in < this->m.extra_pos && out < out_end)
234
-			*out++ = *in++;
235
-
236
-		// Handle output being full already
237
-		if (out >= out_end)
238
-		{
239
-			// Have DSP write to remaining extra space
240
-			out = this->dsp.extra();
241
-			out_end = &this->dsp.extra()[extra_size];
242
-
243
-			// Copy any remaining extra samples as if DSP wrote them
244
-			while (in < m.extra_pos)
245
-				*out++ = *in++;
246
-			assert(out <= out_end);
247
-		}
248
-
249
-		this->dsp.set_output(out, out_end - out);
250
-	}
251
-	else
252
-		this->reset_buf();
253
-}
254
-
255
-void SNES_SPC::save_extra()
256
-{
257
-	// Get end pointers
258
-	auto main_end = this->m.buf_end; // end of data written to buf
259
-	auto dsp_end = this->dsp.out_pos(); // end of data written to dsp.extra()
260
-	if (this->m.buf_begin <= dsp_end && dsp_end <= main_end)
261
-	{
262
-		main_end = dsp_end;
263
-		dsp_end = this->dsp.extra(); // nothing in DSP's extra
264
-	}
265
-
266
-	// Copy any extra samples at these ends into extra_buf
267
-	auto out = this->m.extra_buf;
268
-	for (auto in = this->m.buf_begin + this->sample_count(); in < main_end; ++in)
269
-		*out++ = *in;
270
-	for (auto in = this->dsp.extra(); in < dsp_end; ++in)
271
-		*out++ = *in;
272
-
273
-	this->m.extra_pos = out;
274
-	assert(out <= &this->m.extra_buf[extra_size]);
275
-}
276
-
277
-void SNES_SPC::play(int count, sample_t *out)
278
-{
279
-	assert(!(count & 1)); // must be even
280
-	if (count)
281
-	{
282
-		this->set_output(out, count);
283
-		this->end_frame(count * (clocks_per_sample / 2));
284
-	}
285
-}
286
-
287
-void SNES_SPC::skip(int count)
288
-{
289
-	this->play(count, nullptr);
290
-}
291
-
292
-//// Snes9x Accessor
293
-
294
-void SNES_SPC::dsp_set_stereo_switch(int value)
295
-{
296
-	this->dsp.set_stereo_switch(value);
297
-}
298
-
299
-uint8_t SNES_SPC::dsp_reg_value(int ch, int addr)
300
-{
301
-	return this->dsp.reg_value(ch, addr);
302
-}
303
-
304
-int SNES_SPC::dsp_envx_value(int ch)
305
-{
306
-	return this->dsp.envx_value(ch);
307
-}
308 0
deleted file mode 100644
... ...
@@ -1,1173 +0,0 @@
1
-// snes_spc 0.9.0. http://www.slack.net/~ant/
2
-
3
-/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
4
-can redistribute it and/or modify it under the terms of the GNU Lesser
5
-General Public License as published by the Free Software Foundation; either
6
-version 2.1 of the License, or (at your option) any later version. This
7
-module is distributed in the hope that it will be useful, but WITHOUT ANY
8
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
-details. You should have received a copy of the GNU Lesser General Public
11
-License along with this module; if not, write to the Free Software Foundation,
12
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
13
-
14
-#pragma once
15
-
16
-//// Memory access
17
-
18
-// TODO: remove non-wrapping versions?
19
-#define SPC_NO_SP_WRAPAROUND 0
20
-
21
-unsigned SNES_SPC::CPU_mem_bit(const uint8_t *pc, rel_time_t rel_time)
22
-{
23
-	unsigned addr = get_le16(pc);
24
-	unsigned t = this->cpu_read(addr & 0x1FFF, rel_time) >> (addr >> 13);
25
-	return (t << 8) & 0x100;
26
-}
27
-
28
-//// Status flag handling
29
-
30
-// Hex value in name to clarify code and bit shifting.
31
-// Flag stored in indicated variable during emulation
32
-const int n80 = 0x80; // nz
33
-const int v40 = 0x40; // psw
34
-const int p20 = 0x20; // dp
35
-const int b10 = 0x10; // psw
36
-const int h08 = 0x08; // psw
37
-const int i04 = 0x04; // psw
38
-const int z02 = 0x02; // nz
39
-const int c01 = 0x01; // c
40
-
41
-const int nz_neg_mask = 0x880; // either bit set indicates N flag set
42
-
43
-uint8_t *SNES_SPC::run_until_(time_t end_time)
44
-{
45
-	rel_time_t rel_time = this->m.spc_time - end_time;
46
-	/*assert( rel_time <= 0 );*/
47
-	this->m.spc_time = end_time;
48
-	this->m.dsp_time += rel_time;
49
-	this->m.timers[0].next_time += rel_time;
50
-	this->m.timers[1].next_time += rel_time;
51
-	this->m.timers[2].next_time += rel_time;
52
-
53
-	auto ram = this->m.ram.ram;
54
-	int a = this->m.cpu_regs.a;
55
-	int x = this->m.cpu_regs.x;
56
-	int y = this->m.cpu_regs.y;
57
-	const uint8_t *pc;
58
-	uint8_t *sp;
59
-	int psw;
60
-	int c;
61
-	int nz;
62
-	int dp;
63
-
64
-	// timers are by far the most common thing read from dp
65
-	auto CPU_READ_TIMER = [&](rel_time_t offset, int addr_) -> int
66
-	{
67
-		int out;
68
-		rel_time_t adj_time = rel_time + offset;
69
-		int dp_addr = addr_;
70
-		int ti = dp_addr - (r_t0out + 0xF0);
71
-		if (static_cast<unsigned>(ti) < timer_count)
72
-		{
73
-			auto t = &this->m.timers[ti];
74
-			if (adj_time >= t->next_time)
75
-				t = this->run_timer_(t, adj_time);
76
-			out = t->counter;
77
-			t->counter = 0;
78
-		}
79
-		else
80
-		{
81
-			out = ram[dp_addr];
82
-			int i = dp_addr - 0xF0;
83
-			if (static_cast<unsigned>(i) < 0x10)
84
-				out = this->cpu_read_smp_reg(i, adj_time);
85
-		}
86
-		return out;
87
-	};
88
-
89
-	auto DP_ADDR = [&](int addr) { return dp + addr; };
90
-
91
-	auto READ_PROG16 = [&](int addr) { return get_le16(ram + addr); };
92
-
93
-	auto SET_PC = [&](int n) { pc = ram + n; };
94
-	auto GET_PC = [&]() { return pc - ram; };
95
-
96
-	auto SET_SP = [&](int v) { sp = ram + 0x101 + v; };
97
-	auto GET_SP = [&]() { return sp - 0x101 - ram; };
98
-
99
-	auto PUSH16 = [&](int data)
100
-	{
101
-		sp -= 2;
102
-#if !SPC_NO_SP_WRAPAROUND
103
-		int addr = sp - ram;
104
-		if (addr > 0x100)
105
-#endif
106
-			set_le16(sp, data);
107
-#if !SPC_NO_SP_WRAPAROUND
108
-		else
109
-		{
110
-			ram[static_cast<uint8_t>(addr) + 0x100] = static_cast<uint8_t>(data);
111
-			sp[1] = static_cast<uint8_t>(data >> 8);
112
-			sp += 0x100;
113
-		}
114
-#endif
115
-	};
116
-	auto PUSH = [&](int data)
117
-	{
118
-		*--sp = static_cast<uint8_t>(data);
119
-#if !SPC_NO_SP_WRAPAROUND
120
-		if (sp - ram == 0x100)
121
-			sp += 0x100;
122
-#endif
123
-	};
124
-	auto POP = [&](int &out)
125
-	{
126
-		out = *sp++;
127
-#if !SPC_NO_SP_WRAPAROUND
128
-		if (sp - ram == 0x201)
129
-		{
130
-			out = sp[-0x101];
131
-			sp -= 0x100;
132
-		}
133
-#endif
134
-	};
135
-
136
-	auto MEM_BIT = [&](rel_time_t rel) { return this->CPU_mem_bit(pc, rel_time + rel); };
137
-
138
-	auto GET_PSW = [&](int &out)
139
-	{
140
-		out = psw & ~(n80 | p20 | z02 | c01);
141
-		out |= (c >> 8) & c01;
142
-		out |= (dp >> 3) & p20;
143
-		out |= ((nz >> 4) | nz) & n80;
144
-		if (!static_cast<uint8_t>(nz))
145
-			out |= z02;
146
-	};
147
-	auto SET_PSW = [&](int in)
148
-	{
149
-		psw = in;
150
-		c = in << 8;
151
-		dp = (in << 3) & 0x100;
152
-		nz = ((in << 4) & 0x800) | (~in & z02);
153
-	};
154
-
155
-	SET_PC(this->m.cpu_regs.pc);
156
-	SET_SP(this->m.cpu_regs.sp);
157
-	SET_PSW(this->m.cpu_regs.psw);
158
-
159
-	goto loop;
160
-
161
-	// Main loop
162
-
163
-cbranch_taken_loop:
164
-	pc += *reinterpret_cast<const int8_t *>(pc);
165
-inc_pc_loop:
166
-	++pc;
167
-loop:
168
-	unsigned data;
169
-
170
-	unsigned opcode = *pc;
171
-	if (this->allow_time_overflow && rel_time >= 0)
172
-		goto stop;
173
-	if ((rel_time += this->m.cycle_table[opcode]) > 0 && !this->allow_time_overflow)
174
-		goto out_of_time;
175
-
176
-#ifdef SPC_CPU_OPCODE_HOOK
177
-	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
178
-#endif
179
-
180
-	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
181
-	data = *++pc;
182
-	switch (opcode)
183
-	{
184
-		// Common instructions
185
-
186
-#define BRANCH(cond) \
187
-{ \
188
-	++pc; \
189
-	pc += static_cast<int8_t>(data); \
190
-	if (cond) \
191
-		goto loop; \
192
-	pc -= static_cast<int8_t>(data); \
193
-	rel_time -= 2; \
194
-	goto loop; \
195
-}
196
-
197
-		case 0xF0: // BEQ
198
-			BRANCH(!static_cast<uint8_t>(nz)) // 89% taken
199
-
200
-		case 0xD0: // BNE
201
-			BRANCH(static_cast<uint8_t>(nz))
202
-
203
-		case 0x3F: // CALL
204
-		{
205
-			int old_addr = GET_PC() + 2;
206
-			SET_PC(get_le16(pc));
207
-			PUSH16(old_addr);
208
-			goto loop;
209
-		}
210
-
211
-		case 0x6F:// RET
212
-#if SPC_NO_SP_WRAPAROUND
213
-			SET_PC(get_le16(sp));
214
-			sp += 2;
215
-#else
216
-			{
217
-				int addr = sp - ram;
218
-				SET_PC(get_le16(sp));
219
-				sp += 2;
220
-				if (addr < 0x1FF)
221
-					goto loop;
222
-
223
-				SET_PC(sp[-0x101] * 0x100 + ram[static_cast<uint8_t>(addr) + 0x100]);
224
-				sp -= 0x100;
225
-			}
226
-#endif
227
-			goto loop;
228
-
229
-		case 0xE4: // MOV a,dp
230
-			++pc;
231
-			// 80% from timer
232
-			a = nz = CPU_READ_TIMER(0, DP_ADDR(data));
233
-			goto loop;
234
-
235
-		case 0xFA: // MOV dp,dp
236
-		{
237
-			int temp = CPU_READ_TIMER(-2, DP_ADDR(data));
238
-			data = temp + no_read_before_write;
239
-		}
240
-		// fall through
241
-		case 0x8F: // MOV dp,#imm
242
-		{
243
-			int temp = *(pc + 1);
244
-			pc += 2;
245
-			{
246
-				int i = dp + temp;
247
-				ram[i] = static_cast<uint8_t>(data);
248
-				i -= 0xF0;
249
-				if (static_cast<unsigned>(i) < 0x10) // 76%
250
-				{
251
-					this->m.smp_regs[0][i] = static_cast<uint8_t>(data);
252
-
253
-					// Registers other than $F2 and $F4-$F7
254
-					//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
255
-					if (((~0x2F00 << (bits_in_int - 16)) << i) < 0) // 12%
256
-						this->cpu_write_smp_reg(data, rel_time, i);
257
-				}
258
-			}
259
-			goto loop;
260
-		}
261
-
262
-		case 0xC4: // MOV dp,a
263
-			++pc;
264
-			{
265
-				int i = dp + data;
266
-				ram[i] = static_cast<uint8_t>(a);
267
-				i -= 0xF0;
268
-				if (static_cast<unsigned>(i) < 0x10) // 39%
269
-				{
270
-					unsigned sel = i - 2;
271
-					this->m.smp_regs[0][i] = static_cast<uint8_t>(a);
272
-
273
-					if (sel == 1) // 51% $F3
274
-						this->dsp_write(a, rel_time);
275
-					else if (sel > 1) // 1% not $F2 or $F3
276
-						this->cpu_write_smp_reg_(a, rel_time, i);
277
-				}
278
-			}
279
-			goto loop;
280
-
281
-#define CASE(n) case n:
282
-
283
-// Define common address modes based on opcode for immediate mode. Execution
284
-// ends with data set to the address of the operand.
285
-#define ADDR_MODES_(op) \
286
-	CASE(op - 0x02) /* (X) */ \
287
-		data = x + dp; \
288
-		--pc; \
289
-		goto end_##op; \
290
-	CASE(op + 0x0F) /* (dp)+Y */ \
291
-		data = READ_PROG16(data + dp) + y; \
292
-		goto end_##op; \
293
-	CASE(op - 0x01) /* (dp+X) */ \
294
-		data = READ_PROG16(static_cast<uint8_t>(data + x) + dp); \
295
-		goto end_##op; \
296
-	CASE(op + 0x0E) /* abs+Y */ \
297
-		data += y; \
298
-		goto abs_##op; \
299
-	CASE(op + 0x0D) /* abs+X */ \
300
-		data += x; \
301
-	CASE(op - 0x03) /* abs */ \
302
-	abs_##op: \
303
-		data += 0x100 * *(++pc); \
304
-		goto end_##op; \
305
-	CASE(op + 0x0C) /* dp+X */ \
306
-		data = static_cast<uint8_t>(data + x);
307
-
308
-#define ADDR_MODES_NO_DP(op) \
309
-	ADDR_MODES_(op) \
310
-		data += dp; \
311
-	end_##op:
312
-
313
-#define ADDR_MODES(op) \
314
-	ADDR_MODES_(op) \
315
-	CASE(op - 0x04) /* dp */ \
316
-		data += dp; \
317
-	end_##op:
318
-
319
-		// 1. 8-bit Data Transmission Commands. Group I
320
-
321
-		ADDR_MODES_NO_DP(0xE8) // MOV A,addr
322
-			a = nz = this->cpu_read(data, rel_time);
323
-			goto inc_pc_loop;
324
-
325
-		case 0xBF: // MOV A,(X)+
326
-		{
327
-			int temp = x + dp;
328
-			x = static_cast<uint8_t>(x + 1);
329
-			a = nz = this->cpu_read(temp, rel_time - 1);
330
-			goto loop;
331
-		}
332
-
333
-		case 0xE8: // MOV A,imm
334
-			a  = data;
335
-			nz = data;
336
-			goto inc_pc_loop;
337
-
338
-		case 0xF9: // MOV X,dp+Y
339
-			data = static_cast<uint8_t>(data + y);
340
-		case 0xF8: // MOV X,dp
341
-			x = nz = CPU_READ_TIMER(0, DP_ADDR(data));
342
-			goto inc_pc_loop;
343
-
344
-		case 0xE9: // MOV X,abs
345
-			data = get_le16(pc);
346
-			++pc;
347
-			data = this->cpu_read(data, rel_time);
348
-		case 0xCD: // MOV X,imm
349
-			x  = data;
350
-			nz = data;
351
-			goto inc_pc_loop;
352
-
353
-		case 0xFB: // MOV Y,dp+X
354
-			data = static_cast<uint8_t>(data + x);
355
-		case 0xEB: // MOV Y,dp
356
-			// 70% from timer
357
-			++pc;
358
-			y = nz = CPU_READ_TIMER(0, DP_ADDR(data));
359
-			goto loop;
360
-
361
-		case 0xEC: // MOV Y,abs
362
-		{
363
-			int temp = get_le16(pc);
364
-			pc += 2;
365
-			y = nz = CPU_READ_TIMER(0, temp);
366
-			//y = nz = this->cpu_read(temp, rel_time);
367
-			goto loop;
368
-		}
369
-
370
-		case 0x8D: // MOV Y,imm
371
-			y  = data;
372
-			nz = data;
373
-			goto inc_pc_loop;
374
-
375
-		// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
376
-
377
-		ADDR_MODES_NO_DP(0xC8) // MOV addr,A
378
-			this->cpu_write(a, data, rel_time);
379
-			goto inc_pc_loop;
380
-
381
-		{
382
-			int temp;
383
-			case 0xCC: // MOV abs,Y
384
-				temp = y;
385
-				goto mov_abs_temp;
386
-			case 0xC9: // MOV abs,X
387
-				temp = x;
388
-			mov_abs_temp:
389
-				this->cpu_write(temp, get_le16(pc), rel_time);
390
-				pc += 2;
391
-				goto loop;
392
-		}
393
-
394
-		case 0xD9: // MOV dp+Y,X
395
-			data = static_cast<uint8_t>(data + y);
396
-		case 0xD8: // MOV dp,X
397
-			this->cpu_write(x, data + dp, rel_time);
398
-			goto inc_pc_loop;
399
-
400
-		case 0xDB: // MOV dp+X,Y
401
-			data = static_cast<uint8_t>(data + x);
402
-		case 0xCB: // MOV dp,Y
403
-			this->cpu_write(y, data + dp, rel_time);
404
-			goto inc_pc_loop;
405
-
406
-		// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
407
-
408
-		case 0x7D: // MOV A,X
409
-			a = nz = x;
410
-			goto loop;
411
-
412
-		case 0xDD: // MOV A,Y
413
-			a = nz = y;
414
-			goto loop;
415
-
416
-		case 0x5D: // MOV X,A
417
-			x = nz = a;
418
-			goto loop;
419
-
420
-		case 0xFD: // MOV Y,A
421
-			y = nz = a;
422
-			goto loop;
423
-
424
-		case 0x9D: // MOV X,SP
425
-			x = nz = GET_SP();
426
-			goto loop;
427
-
428
-		case 0xBD: // MOV SP,X
429
-			SET_SP(x);
430
-			goto loop;
431
-
432
-		//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
433
-
434
-		case 0xAF: // MOV (X)+,A
435
-			this->cpu_write(a + no_read_before_write, DP_ADDR(x), rel_time);
436
-			++x;
437
-			goto loop;
438
-
439
-		// 5. 8-BIT LOGIC OPERATION COMMANDS
440
-
441
-#define LOGICAL_OP(op, func) \
442
-	ADDR_MODES(op) /* addr */ \
443
-		data = this->cpu_read(data, rel_time); \
444
-	case op: /* imm */ \
445
-		nz = a func##= data; \
446
-		goto inc_pc_loop; \
447
-		{ \
448
-			unsigned addr; \
449
-			case op + 0x11: /* X,Y */ \
450
-				data = this->cpu_read(DP_ADDR(y), rel_time - 2); \
451
-				addr = x + dp; \
452
-				goto addr_##op; \
453
-			case op + 0x01: /* dp,dp */ \
454
-				data = this->cpu_read(DP_ADDR(data), rel_time - 3); \
455
-			case op + 0x10: /*dp,imm*/ \
456
-			{ \
457
-				auto addr2 = pc + 1; \
458
-				pc += 2; \
459
-				addr = *addr2 + dp; \
460
-			} \
461
-			addr_##op: \
462
-				nz = data func this->cpu_read(addr, rel_time - 1); \
463
-				this->cpu_write(nz, addr, rel_time); \
464
-				goto loop; \
465
-		}
466
-
467
-		LOGICAL_OP(0x28, &); // AND
468
-
469
-		LOGICAL_OP(0x08, |); // OR
470
-
471
-		LOGICAL_OP(0x48, ^); // EOR
472
-
473
-		// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
474
-
475
-		ADDR_MODES(0x68) // CMP addr
476
-			data = this->cpu_read(data, rel_time);
477
-		case 0x68: // CMP imm
478
-			nz = a - data;
479
-			c = ~nz;
480
-			nz &= 0xFF;
481
-			goto inc_pc_loop;
482
-
483
-		case 0x79: // CMP (X),(Y)
484
-			data = this->cpu_read(DP_ADDR(y), rel_time - 2);
485
-			nz = this->cpu_read(DP_ADDR(x), rel_time - 1) - data;
486
-			c = ~nz;
487
-			nz &= 0xFF;
488
-			goto loop;
489
-
490
-		case 0x69: // CMP dp,dp
491
-			data = this->cpu_read(DP_ADDR(data), rel_time - 3);
492
-		case 0x78: // CMP dp,imm
493
-			nz = this->cpu_read(DP_ADDR(*(++pc)), rel_time - 1) - data;
494
-			c = ~nz;
495
-			nz &= 0xFF;
496
-			goto inc_pc_loop;
497
-
498
-		case 0x3E: // CMP X,dp
499
-			data += dp;
500
-			goto cmp_x_addr;
501
-		case 0x1E: // CMP X,abs
502
-			data = get_le16(pc);
503
-			++pc;
504
-		cmp_x_addr:
505
-			data = this->cpu_read(data, rel_time);
506
-		case 0xC8: // CMP X,imm
507
-			nz = x - data;
508
-			c = ~nz;
509
-			nz &= 0xFF;
510
-			goto inc_pc_loop;
511
-
512
-		case 0x7E: // CMP Y,dp
513
-			data += dp;
514
-			goto cmp_y_addr;
515
-		case 0x5E: // CMP Y,abs
516
-			data = get_le16(pc);
517
-			++pc;
518
-		cmp_y_addr:
519
-			data = this->cpu_read(data, rel_time);
520
-		case 0xAD: // CMP Y,imm
521
-			nz = y - data;
522
-			c = ~nz;
523
-			nz &= 0xFF;
524
-			goto inc_pc_loop;
525
-
526
-		{
527
-			int addr;
528
-			case 0xB9: // SBC (x),(y)
529
-			case 0x99: // ADC (x),(y)
530
-				--pc; // compensate for inc later
531
-				data = this->cpu_read(DP_ADDR(y), rel_time - 2);
532
-				addr = x + dp;
533
-				goto adc_addr;
534
-			case 0xA9: // SBC dp,dp
535
-			case 0x89: // ADC dp,dp
536
-				data = this->cpu_read(DP_ADDR(data), rel_time - 3);
537
-			case 0xB8: // SBC dp,imm
538
-			case 0x98: // ADC dp,imm
539
-				addr = *(++pc) + dp;
540
-			adc_addr:
541
-				nz = this->cpu_read(addr, rel_time - 1);
542
-				goto adc_data;
543
-
544
-			// catch ADC and SBC together, then decode later based on operand
545
-#undef CASE
546
-#define CASE(n) case n: case (n) + 0x20:
547
-				ADDR_MODES(0x88) // ADC/SBC addr
548
-				data = this->cpu_read(data, rel_time);
549
-			case 0xA8: // SBC imm
550
-			case 0x88: // ADC imm
551
-				addr = -1; // A
552
-				nz = a;
553
-			adc_data:
554
-			{
555
-				int flags;
556
-				if (opcode >= 0xA0) // SBC
557
-					data ^= 0xFF;
558
-
559
-				flags = data ^ nz;
560
-				nz += data + (c >> 8 & 1);
561
-				flags ^= nz;
562
-
563
-				psw = (psw & ~(v40 | h08)) | ((flags >> 1) & h08) | (((flags + 0x80) >> 2) & v40);
564
-				c = nz;
565
-				if (addr < 0)
566
-				{
567
-					a = static_cast<uint8_t>(nz);
568
-					goto inc_pc_loop;
569
-				}
570
-				this->cpu_write(/*(uint8_t)*/nz, addr, rel_time);
571
-				goto inc_pc_loop;
572
-			}
573
-		}
574
-
575
-		// 6. ADDITION & SUBTRACTION COMMANDS
576
-
577
-#define INC_DEC_REG(reg, op) \
578
-	nz = reg op; \
579
-	reg = static_cast<uint8_t>(nz); \
580
-	goto loop;
581
-
582
-		case 0xBC: INC_DEC_REG(a, + 1) // INC A
583
-		case 0x3D: INC_DEC_REG(x, + 1) // INC X
584
-		case 0xFC: INC_DEC_REG(y, + 1) // INC Y
585
-
586
-		case 0x9C: INC_DEC_REG(a, - 1) // DEC A
587
-		case 0x1D: INC_DEC_REG(x, - 1) // DEC X
588
-		case 0xDC: INC_DEC_REG(y, - 1) // DEC Y
589
-
590
-		case 0x9B: // DEC dp+X
591
-		case 0xBB: // INC dp+X
592
-			data = static_cast<uint8_t>(data + x);
593
-		case 0x8B: // DEC dp
594
-		case 0xAB: // INC dp
595
-			data += dp;
596
-			goto inc_abs;
597
-		case 0x8C: // DEC abs
598
-		case 0xAC: // INC abs
599
-			data = get_le16(pc);
600
-			++pc;
601
-		inc_abs:
602
-			nz = ((opcode >> 4) & 2) - 1;
603
-			nz += this->cpu_read(data, rel_time - 1);
604
-			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
605
-			goto inc_pc_loop;
606
-
607
-		// 7. SHIFT, ROTATION COMMANDS
608
-
609
-		case 0x5C: // LSR A
610
-			c = 0;
611
-		case 0x7C: // ROR A
612
-		{
613
-			nz = ((c >> 1) & 0x80) | (a >> 1);
614
-			c = a << 8;
615
-			a = nz;
616
-			goto loop;
617
-		}
618
-
619
-		case 0x1C: // ASL A
620
-			c = 0;
621
-		case 0x3C: // ROL A
622
-		{
623
-			int temp = c >> 8 & 1;
624
-			c = a << 1;
625
-			nz = c | temp;
626
-			a = static_cast<uint8_t>(nz);
627
-			goto loop;
628
-		}
629
-
630
-		case 0x0B: // ASL dp
631
-			c = 0;
632
-			data += dp;
633
-			goto rol_mem;
634
-		case 0x1B: // ASL dp+X
635
-			c = 0;
636
-		case 0x3B: // ROL dp+X
637
-			data = static_cast<uint8_t>(data + x);
638
-		case 0x2B: // ROL dp
639
-			data += dp;
640
-			goto rol_mem;
641
-		case 0x0C: // ASL abs
642
-			c = 0;
643
-		case 0x2C: // ROL abs
644
-			data = get_le16(pc);
645
-			++pc;
646
-		rol_mem:
647
-			nz = c >> 8 & 1;
648
-			nz |= (c = this->cpu_read(data, rel_time - 1) << 1);
649
-			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
650
-			goto inc_pc_loop;
651
-
652
-		case 0x4B: // LSR dp
653
-			c = 0;
654
-			data += dp;
655
-			goto ror_mem;
656
-		case 0x5B: // LSR dp+X
657
-			c = 0;
658
-		case 0x7B: // ROR dp+X
659
-			data = static_cast<uint8_t>(data + x);
660
-		case 0x6B: // ROR dp
661
-			data += dp;
662
-			goto ror_mem;
663
-		case 0x4C: // LSR abs
664
-			c = 0;
665
-		case 0x6C: // ROR abs
666
-			data = get_le16(pc);
667
-			++pc;
668
-		ror_mem:
669
-		{
670
-			int temp = this->cpu_read(data, rel_time - 1);
671
-			nz = (c >> 1 & 0x80) | (temp >> 1);
672
-			c = temp << 8;
673
-			this->cpu_write(nz, data, rel_time);
674
-			goto inc_pc_loop;
675
-		}
676
-
677
-		case 0x9F: // XCN
678
-			nz = a = (a >> 4) | static_cast<uint8_t>(a << 4);
679
-			goto loop;
680
-
681
-		// 8. 16-BIT TRANSMISION COMMANDS
682
-
683
-		case 0xBA: // MOVW YA,dp
684
-			a = this->cpu_read(DP_ADDR(data), rel_time - 2);
685
-			nz = (a & 0x7F) | (a >> 1);
686
-			y = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
687
-			nz |= y;
688
-			goto inc_pc_loop;
689
-
690
-		case 0xDA: // MOVW dp,YA
691
-			this->cpu_write(a, DP_ADDR(data), rel_time - 1);
692
-			this->cpu_write(y + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
693
-			goto inc_pc_loop;
694
-
695
-		// 9. 16-BIT OPERATION COMMANDS
696
-
697
-		case 0x3A: // INCW dp
698
-		case 0x1A: // DECW dp
699
-		{
700
-			int temp;
701
-			// low byte
702
-			data += dp;
703
-			temp = this->cpu_read(data, rel_time - 3);
704
-			temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
705
-			nz = ((temp >> 1) | temp) & 0x7F;
706
-			this->cpu_write(/*(uint8_t)*/ temp, data, rel_time - 2);
707
-
708
-			// high byte
709
-			data = static_cast<uint8_t>(data + 1) + dp;
710
-			temp = static_cast<uint8_t>((temp >> 8) + this->cpu_read(data, rel_time - 1));
711
-			nz |= temp;
712
-			this->cpu_write(temp, data, rel_time);
713
-
714
-			goto inc_pc_loop;
715
-		}
716
-
717
-		case 0x7A: // ADDW YA,dp
718
-		case 0x9A: // SUBW YA,dp
719
-		{
720
-			int lo = this->cpu_read(DP_ADDR(data), rel_time - 2);
721
-			int hi = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
722
-
723
-			if (opcode == 0x9A) // SUBW
724
-			{
725
-				lo = (lo ^ 0xFF) + 1;
726
-				hi ^= 0xFF;
727
-			}
728
-
729
-			lo += a;
730
-			int result = y + hi + (lo >> 8);
731
-			int flags = hi ^ y ^ result;
732
-
733
-			psw = (psw & ~(v40 | h08)) | (flags >> 1 & h08) | ((flags + 0x80) >> 2 & v40);
734
-			c = result;
735
-			a = static_cast<uint8_t>(lo);
736
-			result = static_cast<uint8_t>(result);
737
-			y = result;
738
-			nz = (((lo >> 1) | lo) & 0x7F) | result;
739
-
740
-			goto inc_pc_loop;
741
-		}
742
-
743
-		case 0x5A: // CMPW YA,dp
744
-		{
745
-			int temp = a - this->cpu_read(DP_ADDR(data), rel_time - 1);
746
-			nz = ((temp >> 1) | temp) & 0x7F;
747
-			temp = y + (temp >> 8);
748
-			temp -= this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
749
-			nz |= temp;
750
-			c  = ~temp;
751
-			nz &= 0xFF;
752
-			goto inc_pc_loop;
753
-		}
754
-
755
-		// 10. MULTIPLICATION & DIVISON COMMANDS
756
-
757
-		case 0xCF: // MUL YA
758
-		{
759
-			unsigned temp = y * a;
760
-			a = static_cast<uint8_t>(temp);
761
-			nz = ((temp >> 1) | temp) & 0x7F;
762
-			y = temp >> 8;
763
-			nz |= y;
764
-			goto loop;
765
-		}
766
-
767
-		case 0x9E: // DIV YA,X
768
-		{
769
-			unsigned ya = y * 0x100 + a;
770
-
771
-			psw &= ~(h08 | v40);
772
-
773
-			if (y >= x)
774
-				psw |= v40;
775
-
776
-			if ((y & 15) >= (x & 15))
777
-				psw |= h08;
778
-
779
-			if (y < x * 2)
780
-			{
781
-				a = ya / x;
782
-				y = ya - a * x;
783
-			}
784
-			else
785
-			{
786
-				a = 255 - (ya - x * 0x200) / (256 - x);
787
-				y = x + (ya - x * 0x200) % (256 - x);
788
-			}
789
-
790
-			nz = static_cast<uint8_t>(a);
791
-			a = static_cast<uint8_t>(a);
792
-
793
-			goto loop;
794
-		}
795
-
796
-		// 11. DECIMAL COMPENSATION COMMANDS
797
-
798
-		case 0xDF: // DAA
799
-			if (a > 0x99 || c & 0x100)
800
-			{
801
-				a += 0x60;
802
-				c = 0x100;
803
-			}
804
-
805
-			if ((a & 0x0F) > 9 || psw & h08)
806
-				a += 0x06;
807
-
808
-			nz = a;
809
-			a = static_cast<uint8_t>(a);
810
-			goto loop;
811
-
812
-		case 0xBE: // DAS
813
-			if (a > 0x99 || !(c & 0x100))
814
-			{
815
-				a -= 0x60;
816
-				c = 0;
817
-			}
818
-
819
-			if ((a & 0x0F) > 9 || !(psw & h08))
820
-				a -= 0x06;
821
-
822
-			nz = a;
823
-			a = static_cast<uint8_t>(a);
824
-			goto loop;
825
-
826
-		// 12. BRANCHING COMMANDS
827
-
828
-		case 0x2F: // BRA rel
829
-			pc += static_cast<int8_t>(data);
830
-			goto inc_pc_loop;
831
-
832
-		case 0x30: // BMI
833
-			BRANCH(nz & nz_neg_mask)
834
-
835
-		case 0x10: // BPL
836
-			BRANCH(!(nz & nz_neg_mask))
837
-
838
-		case 0xB0: // BCS
839
-			BRANCH(c & 0x100)
840
-
841
-		case 0x90: // BCC
842
-			BRANCH(!(c & 0x100))
843
-
844
-		case 0x70: // BVS
845
-			BRANCH(psw & v40)
846
-
847
-		case 0x50: // BVC
848
-			BRANCH(!(psw & v40))
849
-
850
-#define CBRANCH(cond) \
851
-{ \
852
-	++pc; \
853
-	if (cond) \
854
-		goto cbranch_taken_loop; \
855
-	rel_time -= 2; \
856
-	goto inc_pc_loop; \
857
-}
858
-
859
-		case 0x03: // BBS dp.bit,rel
860
-		case 0x23:
861
-		case 0x43:
862
-		case 0x63:
863
-		case 0x83:
864
-		case 0xA3:
865
-		case 0xC3:
866
-		case 0xE3:
867
-			CBRANCH((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1)
868
-
869
-		case 0x13: // BBC dp.bit,rel
870
-		case 0x33:
871
-		case 0x53:
872
-		case 0x73:
873
-		case 0x93:
874
-		case 0xB3:
875
-		case 0xD3:
876
-		case 0xF3:
877
-			CBRANCH(!((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1))
878
-
879
-		case 0xDE: // CBNE dp+X,rel
880
-			data = static_cast<uint8_t>(data + x);
881
-			// fall through
882
-		case 0x2E: // CBNE dp,rel
883
-		{
884
-			// 61% from timer
885
-			int temp = CPU_READ_TIMER(-4, DP_ADDR(data));
886
-			CBRANCH(temp != a)
887
-		}
888
-
889
-		case 0x6E: // DBNZ dp,rel
890
-		{
891
-			unsigned temp = this->cpu_read(DP_ADDR(data), rel_time - 4) - 1;
892
-			this->cpu_write(/*(uint8_t)*/ temp + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data)), rel_time - 3);
893
-			CBRANCH(temp)
894
-		}
895
-
896
-		case 0xFE: // DBNZ Y,rel
897
-			y = static_cast<uint8_t>(y - 1);
898
-			BRANCH(y)
899
-
900
-		case 0x1F: // JMP [abs+X]
901
-			SET_PC(get_le16(pc) + x);
902
-			// fall through
903
-		case 0x5F: // JMP abs
904
-			SET_PC(get_le16(pc));
905
-			goto loop;
906
-
907
-		// 13. SUB-ROUTINE CALL RETURN COMMANDS
908
-
909
-		case 0x0F: // BRK
910
-		{
911
-			int temp;
912
-			int ret_addr = GET_PC();
913
-			SET_PC(READ_PROG16(0xFFDE)); // vector address verified
914
-			PUSH16(ret_addr);
915
-			GET_PSW(temp);
916
-			psw = (psw | b10) & ~i04;
917
-			PUSH(temp);
918
-			goto loop;
919
-		}
920
-
921
-		case 0x4F: // PCALL offset
922
-		{
923
-			int ret_addr = GET_PC() + 1;
924
-			SET_PC(0xFF00 | data);
925
-			PUSH16(ret_addr);
926
-			goto loop;
927
-		}
928
-
929
-		case 0x01: // TCALL n
930
-		case 0x11:
931
-		case 0x21:
932
-		case 0x31:
933
-		case 0x41:
934
-		case 0x51:
935
-		case 0x61:
936
-		case 0x71:
937
-		case 0x81:
938
-		case 0x91:
939
-		case 0xA1:
940
-		case 0xB1:
941
-		case 0xC1:
942
-		case 0xD1:
943
-		case 0xE1:
944
-		case 0xF1:
945
-		{
946
-			int ret_addr = GET_PC();
947
-			SET_PC(READ_PROG16(0xFFDE - (opcode >> 3)));
948
-			PUSH16(ret_addr);
949
-			goto loop;
950
-		}
951
-
952
-		// 14. STACK OPERATION COMMANDS
953
-
954
-		{
955
-			int temp;
956
-		case 0x7F: // RET1
957
-			temp = *sp;
958
-			SET_PC(get_le16(sp + 1));
959
-			sp += 3;
960
-			goto set_psw;
961
-		case 0x8E: // POP PSW
962
-			POP(temp);
963
-		set_psw:
964
-			SET_PSW(temp);
965
-			goto loop;
966
-		}
967
-
968
-		case 0x0D: // PUSH PSW
969
-		{
970
-			int temp;
971
-			GET_PSW(temp);
972
-			PUSH(temp);
973
-			goto loop;
974
-		}
975
-
976
-		case 0x2D: // PUSH A
977
-			PUSH(a);
978
-			goto loop;
979
-
980
-		case 0x4D: // PUSH X
981
-			PUSH(x);
982
-			goto loop;
983
-
984
-		case 0x6D: // PUSH Y
985
-			PUSH(y);
986
-			goto loop;
987
-
988
-		case 0xAE: // POP A
989
-			POP(a);
990
-			goto loop;
991
-
992
-		case 0xCE: // POP X
993
-			POP(x);
994
-			goto loop;
995
-
996
-		case 0xEE: // POP Y
997
-			POP(y);
998
-			goto loop;
999
-
1000
-		// 15. BIT OPERATION COMMANDS
1001
-
1002
-		case 0x02: // SET1
1003
-		case 0x22:
1004
-		case 0x42:
1005
-		case 0x62:
1006
-		case 0x82:
1007
-		case 0xA2:
1008
-		case 0xC2:
1009
-		case 0xE2:
1010
-		case 0x12: // CLR1
1011
-		case 0x32:
1012
-		case 0x52:
1013
-		case 0x72:
1014
-		case 0x92:
1015
-		case 0xB2:
1016
-		case 0xD2:
1017
-		case 0xF2:
1018
-		{
1019
-			int bit = 1 << (opcode >> 5);
1020
-			int mask = ~bit;
1021
-			if (opcode & 0x10)
1022
-				bit = 0;
1023
-			data += dp;
1024
-			this->cpu_write((this->cpu_read(data, rel_time - 1) & mask) | bit, data, rel_time);
1025
-			goto inc_pc_loop;
1026
-		}
1027
-
1028
-		case 0x0E: // TSET1 abs
1029
-		case 0x4E: // TCLR1 abs
1030
-			data = get_le16(pc);
1031
-			pc += 2;
1032
-			{
1033
-				unsigned temp = this->cpu_read(data, rel_time - 2);
1034
-				nz = static_cast<uint8_t>(a - temp);
1035
-				temp &= ~a;
1036
-				if (opcode == 0x0E)
1037
-					temp |= a;
1038
-				this->cpu_write(temp, data, rel_time);
1039
-			}
1040
-			goto loop;
1041
-
1042
-		case 0x4A: // AND1 C,mem.bit
1043
-			c &= MEM_BIT(0);
1044
-			pc += 2;
1045
-			goto loop;
1046
-
1047
-		case 0x6A: // AND1 C,/mem.bit
1048
-			c &= ~MEM_BIT(0);
1049
-			pc += 2;
1050
-			goto loop;
1051
-
1052
-		case 0x0A: // OR1 C,mem.bit
1053
-			c |= MEM_BIT(-1);
1054
-			pc += 2;
1055
-			goto loop;
1056
-
1057
-		case 0x2A: // OR1 C,/mem.bit
1058
-			c |= ~MEM_BIT(-1);
1059
-			pc += 2;
1060
-			goto loop;
1061
-
1062
-		case 0x8A: // EOR1 C,mem.bit
1063
-			c ^= MEM_BIT(-1);
1064
-			pc += 2;
1065
-			goto loop;
1066
-
1067
-		case 0xEA: // NOT1 mem.bit
1068
-			data = get_le16(pc);
1069
-			pc += 2;
1070
-			{
1071
-				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 1);
1072
-				temp ^= 1 << (data >> 13);
1073
-				this->cpu_write(temp, data & 0x1FFF, rel_time);
1074
-			}
1075
-			goto loop;
1076
-
1077
-		case 0xCA: // MOV1 mem.bit,C
1078
-			data = get_le16(pc);
1079
-			pc += 2;
1080
-			{
1081
-				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 2);
1082
-				unsigned bit = data >> 13;
1083
-				temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
1084
-				this->cpu_write(temp + no_read_before_write, data & 0x1FFF, rel_time);
1085
-			}
1086
-			goto loop;
1087
-
1088
-		case 0xAA: // MOV1 C,mem.bit
1089
-			c = MEM_BIT(0);
1090
-			pc += 2;
1091
-			goto loop;
1092
-
1093
-		// 16. PROGRAM PSW FLAG OPERATION COMMANDS
1094
-
1095
-		case 0x60: // CLRC
1096
-			c = 0;
1097
-			goto loop;
1098
-
1099
-		case 0x80: // SETC
1100
-			c = ~0;
1101
-			goto loop;
1102
-
1103
-		case 0xED: // NOTC
1104
-			c ^= 0x100;
1105
-			goto loop;
1106
-
1107
-		case 0xE0: // CLRV
1108
-			psw &= ~(v40 | h08);
1109
-			goto loop;
1110
-
1111
-		case 0x20: // CLRP
1112
-			dp = 0;
1113
-			goto loop;
1114
-
1115
-		case 0x40: // SETP
1116
-			dp = 0x100;
1117
-			goto loop;
1118
-
1119
-		case 0xA0: // EI
1120
-			psw |= i04;
1121
-			goto loop;
1122
-
1123
-		case 0xC0: // DI
1124
-			psw &= ~i04;
1125
-			goto loop;
1126
-
1127
-		// 17. OTHER COMMANDS
1128
-
1129
-		case 0x00: // NOP
1130
-			goto loop;
1131
-
1132
-		case 0xFF: // STOP
1133
-		{
1134
-			// handle PC wrap-around
1135
-			unsigned addr = GET_PC() - 1;
1136
-			if (addr >= 0x10000)
1137
-			{
1138
-				addr &= 0xFFFF;
1139
-				SET_PC(addr);
1140
-				goto loop;
1141
-			}
1142
-		}
1143
-		// fall through
1144
-		case 0xEF: // SLEEP
1145
-			--pc;
1146
-			rel_time = 0;
1147
-			goto stop;
1148
-	} // switch
1149
-
1150
-	assert(0); // catch any unhandled instructions
1151
-
1152
-out_of_time:
1153
-	rel_time -= this->m.cycle_table[*pc]; // undo partial execution of opcode
1154
-stop:
1155
-
1156
-	// Uncache registers
1157
-	m.cpu_regs.pc = static_cast<uint16_t>(GET_PC());
1158
-	m.cpu_regs.sp = static_cast<uint8_t>(GET_SP());
1159
-	m.cpu_regs.a = static_cast<uint8_t>(a);
1160
-	m.cpu_regs.x = static_cast<uint8_t>(x);
1161
-	m.cpu_regs.y = static_cast<uint8_t>(y);
1162
-	int temp;
1163
-	GET_PSW(temp);
1164
-	m.cpu_regs.psw = static_cast<uint8_t>(temp);
1165
-
1166
-	this->m.spc_time += rel_time;
1167
-	this->m.dsp_time -= rel_time;
1168
-	this->m.timers[0].next_time -= rel_time;
1169
-	this->m.timers[1].next_time -= rel_time;
1170
-	this->m.timers[2].next_time -= rel_time;
1171
-	/*assert( m.spc_time >= end_time );*/
1172
-	return &this->m.smp_regs[0][r_cpuio0];
1173
-}
... ...
@@ -1,361 +1,90 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
3 6
 
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
7
+#include <memory>
8
+#include "apu.h"
9
+#include "resampler.h"
169 10
 
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
11
+#include "bapu/snes/snes.hpp"
12
+#include "bapu/dsp/sdsp.hpp"
13
+#include "bapu/smp/smp.hpp"
173 14
 
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
15
+static constexpr int APU_DEFAULT_INPUT_RATE = 31950; // ~59.94Hz
16
+static constexpr int APU_SAMPLE_BLOCK = 48;
17
+static constexpr int APU_NUMERATOR_NTSC = 15664;
18
+static constexpr int APU_DENOMINATOR_NTSC = 328125;
19
+static constexpr int APU_NUMERATOR_PAL = 34176;
20
+static constexpr int APU_DENOMINATOR_PAL = 709379;
21
+// Max number of samples we'll ever generate before call to port API and
22
+// moving the samples to the resampler.
23
+// This is 535 sample frames, which corresponds to 1 video frame + some leeway
24
+// for use with SoundSync, multiplied by 2, for left and right samples.
25
+static constexpr int MINIMUM_BUFFER_SIZE = 550 * 2;
177 26
 
178
-#include <memory>
179
-#include "apu.h"
180
-#include "linear_resampler.h"
181
-#include "hermite_resampler.h"
182
-#include "bspline_resampler.h"
183
-#include "osculating_resampler.h"
184
-#include "sinc_resampler.h"
185
-
186
-bool SincResampler::initializedLUTs = false;
187
-double SincResampler::sinc_lut[SincResampler::SINC_SAMPLES + 1];
188
-
189
-static const uint32_t APU_DEFAULT_INPUT_RATE = 32000;
190
-static const int APU_MINIMUM_SAMPLE_COUNT = 512;
191
-static const int APU_MINIMUM_SAMPLE_BLOCK = 128;
192
-static const uint32_t APU_NUMERATOR_NTSC = 15664;
193
-static const uint32_t APU_DENOMINATOR_NTSC = 328125;
194
-static const uint32_t APU_NUMERATOR_PAL = 34176;
195
-static const uint32_t APU_DENOMINATOR_PAL = 709379;
196
-
197
-static std::unique_ptr<SNES_SPC> spc_core;
198
-
199
-static const uint8_t APUROM[] =
27
+namespace SNES
200 28
 {
201
-	0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
202
-	0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
203
-	0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
204
-	0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
205
-	0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB,
206
-	0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
207
-	0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD,
208
-	0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
209
-};
29
+	CPU cpu;
30
+}
210 31
 
211 32
 namespace spc
212 33
 {
213 34
 	static bool sound_in_sync = true;
214 35
 	static bool sound_enabled = false;
215 36
 
216
-	static int buffer_size;
217
-	static int lag_master = 0;
218
-	static int lag = 0;
219
-
220
-	static std::unique_ptr<uint8_t[]> landing_buffer;
221
-	static std::unique_ptr<uint8_t[]> shrink_buffer;
222
-
223 37
 	static std::unique_ptr<Resampler> resampler;
224 38
 
225 39
 	static int32_t reference_time;
226 40
 	static uint32_t remainder;
227 41
 
228
-	static const int timing_hack_numerator = SNES_SPC::tempo_unit;
229
-	static int timing_hack_denominator = SNES_SPC::tempo_unit;
42
+	static constexpr int timing_hack_numerator = 256;
43
+	static int timing_hack_denominator = 256;
230 44
 	/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
231 45
 	   if necessary on game load. */
232 46
 	static uint32_t ratio_numerator = APU_NUMERATOR_NTSC;
233 47
 	static uint32_t ratio_denominator = APU_DENOMINATOR_NTSC;
234 48
 }
235 49
 
236
-static void EightBitize(uint8_t *buffer, int sample_count)
50
+void S9xClearSamples()
237 51
 {
238
-	int16_t *buf16 = reinterpret_cast<int16_t *>(buffer);
239
-
240
-	for (int i = 0; i < sample_count; ++i)
241
-		buffer[i] = static_cast<uint8_t>((buf16[i] / 256) + 128);
242
-}
243
-
244
-static void DeStereo(uint8_t *buffer, int sample_count)
245
-{
246
-	int16_t *buf = reinterpret_cast<int16_t *>(buffer);
247
-
248
-	for (int i = 0; i < sample_count >> 1; ++i)
249
-	{
250
-		int32_t s1 = static_cast<int32_t>(buf[2 * i]);
251
-		int32_t s2 = static_cast<int32_t>(buf[2 * i + 1]);
252
-		buf[i] = static_cast<int16_t>((s1 + s2) >> 1);
253
-	}
254
-}
255
-
256
-static void ReverseStereo(uint8_t *src_buffer, int sample_count)
257
-{
258
-	int16_t *buffer = reinterpret_cast<int16_t *>(src_buffer);
259
-
260
-	for (int i = 0; i < sample_count; i += 2)
261
-		std::swap(buffer[i], buffer[i + 1]);
52
+	spc::resampler->clear();
262 53
 }
263 54
 
264
-bool S9xMixSamples(uint8_t *buffer, int sample_count)
55
+bool S9xMixSamples(uint8_t *dest, int sample_count)
265 56
 {
266
-	static int shrink_buffer_size = -1;
267
-	uint8_t *dest;
268
-
269
-	if (!Settings.SixteenBitSound || !Settings.Stereo)
270
-	{
271
-		/* We still need both stereo samples for generating the mono sample */
272
-		if (!Settings.Stereo)
273
-			sample_count <<= 1;
274
-
275
-		/* We still have to generate 16-bit samples for bit-dropping, too */
276
-		if (shrink_buffer_size < (sample_count << 1))
277
-		{
278
-			spc::shrink_buffer.reset(new uint8_t[sample_count << 1]);
279
-			shrink_buffer_size = sample_count << 1;
280
-		}
281
-
282
-		dest = spc::shrink_buffer.get();
283
-	}
284
-	else
285
-		dest = buffer;
57
+	int16_t *out = reinterpret_cast<int16_t *>(dest);
286 58
 
287 59
 	if (Settings.Mute)
288 60
 	{
289
-		std::fill_n(&dest[0], sample_count << 1, 0);
290
-		spc::resampler->clear();
291
-
292
-		return false;
61
+		std::fill_n(&out[0], sample_count, 0);
62
+		S9xClearSamples();
293 63
 	}
294 64
 	else
295 65
 	{
296
-		if (spc::resampler->avail() >= sample_count + spc::lag)
297
-		{
298
-			spc::resampler->read(reinterpret_cast<short *>(dest), sample_count);
299
-			if (spc::lag == spc::lag_master)
300
-				spc::lag = 0;
301
-		}
66
+		if (spc::resampler->avail() >= sample_count)
67
+			spc::resampler->read(reinterpret_cast<short *>(out), sample_count);
302 68
 		else
303 69
 		{
304
-			std::fill_n(&buffer[0], (sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1), Settings.SixteenBitSound ? 0 : 128);
305
-			if (!spc::lag)
306
-				spc::lag = spc::lag_master;
307
-
70
+			std::fill_n(&out[0], sample_count, 0);
308 71
 			return false;
309 72
 		}
310 73
 	}
311 74
 
312
-	if (Settings.ReverseStereo && Settings.Stereo)
313
-		ReverseStereo(dest, sample_count);
314
-
315
-	if (!Settings.Stereo || !Settings.SixteenBitSound)
316
-	{
317
-		if (!Settings.Stereo)
318
-		{
319
-			DeStereo(dest, sample_count);
320
-			sample_count >>= 1;
321
-		}
322
-
323
-		if (!Settings.SixteenBitSound)
324
-			EightBitize(dest, sample_count);
325
-
326
-		std::copy_n(&dest[0], sample_count << (Settings.SixteenBitSound ? 1 : 0), &buffer[0]);
327
-	}
75
+	spc::sound_in_sync = spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync || Settings.TurboMode || Settings.Mute;
328 76
 
329 77
 	return true;
330 78
 }
331 79
 
332 80
 int S9xGetSampleCount()
333 81
 {
334
-	return spc::resampler->avail() >> (Settings.Stereo ? 0 : 1);
335
-}
336
-
337
-void S9xFinalizeSamples()
338
-{
339
-	if (!Settings.Mute)
340
-	{
341
-		if (!spc::resampler->push(reinterpret_cast<short *>(spc::landing_buffer.get()), spc_core->sample_count()))
342
-		{
343
-			/* We weren't able to process the entire buffer. Potential overrun. */
344
-			spc::sound_in_sync = false;
345
-
346
-			if (Settings.SoundSync && !Settings.TurboMode)
347
-				return;
348
-		}
349
-	}
350
-
351
-	spc::sound_in_sync = !Settings.SoundSync || Settings.TurboMode || Settings.Mute || spc::resampler->space_empty() >= spc::resampler->space_filled();
352
-
353
-	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
82
+	return spc::resampler->avail();
354 83
 }
355 84
 
356 85
 void S9xLandSamples()
357 86
 {
358
-	S9xFinalizeSamples();
87
+	spc::sound_in_sync = spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync || Settings.TurboMode || Settings.Mute;
359 88
 }
360 89
 
361 90
 bool S9xSyncSound()
... ...
@@ -377,42 +106,20 @@ static void UpdatePlaybackRate()
377 106
 	spc::resampler->time_ratio(time_ratio);
378 107
 }
379 108
 
380
-template<class ResamplerClass> bool S9xInitSound(int buffer_ms, int lag_ms)
109
+bool S9xInitSound(int buffer_ms)
381 110
 {
382
-	// buffer_ms : buffer size given in millisecond
383
-	// lag_ms    : allowable time-lag given in millisecond
384
-
385
-	int sample_count = buffer_ms * 32000 / 1000;
386
-	int lag_sample_count = lag_ms * 32000 / 1000;
387
-
388
-	spc::lag_master = lag_sample_count;
389
-	if (Settings.Stereo)
390
-		spc::lag_master <<= 1;
391
-	spc::lag = spc::lag_master;
111
+	// The resampler and spc unit use samples (16-bit short) as arguments.
112
+	int buffer_size_samples = MINIMUM_BUFFER_SIZE;
113
+	int requested_buffer_size_samples = Settings.SoundPlaybackRate * buffer_ms * 2 / 1000;
392 114
 
393
-	if (sample_count < APU_MINIMUM_SAMPLE_COUNT)
394
-		sample_count = APU_MINIMUM_SAMPLE_COUNT;
115
+	if (requested_buffer_size_samples > buffer_size_samples)
116
+		buffer_size_samples = requested_buffer_size_samples;
395 117
 
396
-	spc::buffer_size = sample_count;
397
-	if (Settings.Stereo)
398
-		spc::buffer_size <<= 1;
399
-	if (Settings.SixteenBitSound)
400
-		spc::buffer_size <<= 1;
401
-
402
-	spc::landing_buffer.reset(new uint8_t[spc::buffer_size * 2]);
403
-	if (!spc::landing_buffer)
404
-		return false;
405
-
406
-	/* The resampler and spc unit use samples (16-bit short) as
407
-	 *   arguments. Use 2x in the resampler for buffer leveling with SoundSync */
408
-	spc::resampler.reset(new ResamplerClass(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)));
118
+	spc::resampler.reset(new Resampler(buffer_size_samples));
409 119
 	if (!spc::resampler)
410
-	{
411
-		spc::landing_buffer.reset();
412 120
 		return false;
413
-	}
414 121
 
415
-	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
122
+	SNES::dsp.spc_dsp.set_output(spc::resampler.get());
416 123
 
417 124
 	UpdatePlaybackRate();
418 125
 
... ...
@@ -421,15 +128,9 @@ template<class ResamplerClass> bool S9xInitSound(int buffer_ms, int lag_ms)
421 128
 	return spc::sound_enabled;
422 129
 }
423 130
 
424
-template bool S9xInitSound<LinearResampler>(int, int);
425
-template bool S9xInitSound<HermiteResampler>(int, int);
426
-template bool S9xInitSound<BsplineResampler>(int, int);
427
-template bool S9xInitSound<OsculatingResampler>(int, int);
428
-template bool S9xInitSound<SincResampler>(int, int);
429
-
430 131
 void S9xSetSoundControl(uint8_t voice_switch)
431 132
 {
432
-	spc_core->dsp_set_stereo_switch((voice_switch << 8) | voice_switch);
133
+	SNES::dsp.spc_dsp.set_stereo_switch((voice_switch << 8) | voice_switch);
433 134
 }
434 135
 
435 136
 void S9xSetSoundMute(bool mute)
... ...
@@ -441,15 +142,6 @@ void S9xSetSoundMute(bool mute)
441 142
 
442 143
 bool S9xInitAPU()
443 144
 {
444
-	spc_core.reset(new SNES_SPC);
445
-	if (!spc_core)
446
-		return false;
447
-
448
-	spc_core->init();
449
-	spc_core->init_rom(APUROM);
450
-
451
-	spc::landing_buffer.reset();
452
-	spc::shrink_buffer.reset();
453 145
 	spc::resampler.reset();
454 146
 
455 147
 	return true;
... ...
@@ -457,10 +149,7 @@ bool S9xInitAPU()
457 149
 
458 150
 void S9xDeinitAPU()
459 151
 {
460
-	spc_core.reset();
461 152
 	spc::resampler.reset();
462
-	spc::landing_buffer.reset();
463
-	spc::shrink_buffer.reset();
464 153
 }
465 154
 
466 155
 static inline int S9xAPUGetClock(int32_t cpucycles)
... ...
@@ -473,14 +162,26 @@ static inline int S9xAPUGetClockRemainder(int32_t cpucycles)
473 162
 	return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) % spc::ratio_denominator;
474 163
 }
475 164
 
165
+void S9xAPUExecute()
166
+{
167
+	SNES::smp.clock -= S9xAPUGetClock(CPU.Cycles);
168
+	SNES::smp.enter();
169
+
170
+	spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
171
+
172
+	S9xAPUSetReferenceTime(CPU.Cycles);
173
+}
174
+
476 175
 uint8_t S9xAPUReadPort(int port)
477 176
 {
478
-	return static_cast<uint8_t>(spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port));
177
+	S9xAPUExecute();
178
+	return static_cast<uint8_t>(SNES::smp.port_read(port & 3));
479 179
 }
480 180
 
481 181
 void S9xAPUWritePort(int port, uint8_t byte)
482 182
 {
483
-	spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte);
183
+	S9xAPUExecute();
184
+	SNES::cpu.port_write(port & 3, byte);
484 185
 }
485 186
 
486 187
 void S9xAPUSetReferenceTime(int32_t cpucycles)
... ...
@@ -488,28 +189,18 @@ void S9xAPUSetReferenceTime(int32_t cpucycles)
488 189
 	spc::reference_time = cpucycles;
489 190
 }
490 191
 
491
-void S9xAPUExecute()
492
-{
493
-	/* Accumulate partial APU cycles */
494
-	spc_core->end_frame(S9xAPUGetClock(CPU.Cycles));
495
-
496
-	spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
497
-
498
-	S9xAPUSetReferenceTime(CPU.Cycles);
499
-}
500
-
501 192
 void S9xAPUEndScanline()
502 193
 {
503 194
 	S9xAPUExecute();
195
+	SNES::dsp.synchronize();
504 196
 
505
-	if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync)
197
+	if (spc::resampler->space_filled() >= APU_SAMPLE_BLOCK || !spc::sound_in_sync)
506 198
 		S9xLandSamples();
507 199
 }
508 200
 
509 201
 void S9xAPUTimingSetSpeedup(int ticks)
510 202
 {
511
-	spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks;
512
-	spc_core->set_tempo(spc::timing_hack_denominator);
203
+	spc::timing_hack_denominator = 256 - ticks;
513 204
 
514 205
 	spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC;
515 206
 	spc::ratio_denominator = (Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC) * spc::timing_hack_denominator / spc::timing_hack_numerator;
... ...
@@ -517,17 +208,14 @@ void S9xAPUTimingSetSpeedup(int ticks)
517 208
 	UpdatePlaybackRate();
518 209
 }
519 210
 
520
-void S9xAPUAllowTimeOverflow(bool allow)
521
-{
522
-	spc_core->spc_allow_time_overflow(allow);
523
-}
524
-
525 211
 void S9xResetAPU()
526 212
 {
527 213
 	spc::reference_time = 0;
528 214
 	spc::remainder = 0;
529
-	spc_core->reset();
530
-	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
531 215
 
532
-	spc::resampler->clear();
216
+	SNES::cpu.reset();
217
+	SNES::smp.power();
218
+	SNES::dsp.power();
219
+
220
+	S9xClearSamples();
533 221
 }
... ...
@@ -1,184 +1,12 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
180 9
 #include "../snes9x.h"
181
-#include "SNES_SPC.h"
182 10
 
183 11
 bool S9xInitAPU();
184 12
 void S9xDeinitAPU();
... ...
@@ -188,9 +16,8 @@ void S9xAPUWritePort(int, uint8_t);
188 16
 void S9xAPUEndScanline();
189 17
 void S9xAPUSetReferenceTime(int32_t);
190 18
 void S9xAPUTimingSetSpeedup(int);
191
-void S9xAPUAllowTimeOverflow(bool);
192 19
 
193
-template<class ResamplerClass> bool S9xInitSound(int, int);
20
+bool S9xInitSound(int);
194 21
 bool S9xOpenSoundDevice();
195 22
 
196 23
 bool S9xSyncSound();
197 24
similarity index 53%
198 25
rename from src/in_snsf/snes9x/apu/SPC_DSP.cpp
199 26
rename to src/in_snsf/snes9x/apu/bapu/dsp/SPC_DSP.cpp
... ...
@@ -3,6 +3,7 @@
3 3
 #include <algorithm>
4 4
 #include <cstring>
5 5
 #include "SPC_DSP.h"
6
+#include "../../../snes9x.h"
6 7
 
7 8
 #include "blargg_endian.h"
8 9
 
... ...
@@ -21,7 +22,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
21 22
 # error "Requires that int type have at least 32 bits"
22 23
 #endif
23 24
 
24
-static const uint8_t initial_regs[] =
25
+static constexpr uint8_t initial_regs[] =
25 26
 {
26 27
 	0x45, 0x8B, 0x5A, 0x9A, 0xE4, 0x82, 0x1B, 0x78, 0x00, 0x00, 0xAA, 0x96, 0x89, 0x0E, 0xE0, 0x80,
27 28
 	0x2A, 0x49, 0x3D, 0xBA, 0x14, 0xA0, 0xAC, 0xC5, 0x00, 0x00, 0x51, 0xBB, 0x9C, 0x4E, 0x7B, 0xFF,
... ...
@@ -41,14 +42,14 @@ template<typename T> static inline void CLAMP16(T &io)
41 42
 		io = (io >> 31) ^ 0x7FFF;
42 43
 }
43 44
 
45
+void SPC_DSP::set_output(Resampler *newResampler)
46
+{
47
+	this->resampler = newResampler;
48
+}
49
+
44 50
 void SPC_DSP::set_output(sample_t *out, int size)
45 51
 {
46 52
 	assert(!(size & 1)); // must be even
47
-	if (!out)
48
-	{
49
-		out = this->m.extra;
50
-		size = extra_size;
51
-	}
52 53
 	this->m.out_begin = this->m.out = out;
53 54
 	this->m.out_end = out + size;
54 55
 }
... ...
@@ -58,7 +59,7 @@ void SPC_DSP::set_output(sample_t *out, int size)
58 59
 
59 60
 // Gaussian interpolation
60 61
 
61
-static const short gauss[] =
62
+static constexpr short gauss[] =
62 63
 {
63 64
 	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
64 65
 	   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
... ...
@@ -91,33 +92,393 @@ static const short gauss[] =
91 92
 	1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
92 93
 	1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
93 94
 	1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
94
-	1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
95
+	1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305
95 96
 };
96 97
 
97
-int SPC_DSP::interpolate(const voice_t *v)
98
+// Interpolation by Mudlord
99
+static constexpr short cubic[] =
100
+{
101
+	   0,  -4,  -8, -12, -16, -20, -23, -27, -30, -34, -37, -41, -44, -47, -50, -53,
102
+	 -56, -59, -62, -65, -68, -71, -73, -76, -78, -81, -84, -87, -89, -91, -93, -95,
103
+	 -98,-100,-102,-104,-106,-109,-110,-112,-113,-116,-117,-119,-121,-122,-123,-125,
104
+	-126,-128,-129,-131,-132,-134,-134,-136,-136,-138,-138,-140,-141,-141,-142,-143,
105
+	-144,-144,-145,-146,-147,-148,-147,-148,-148,-149,-149,-150,-150,-150,-150,-151,
106
+	-151,-151,-151,-151,-152,-152,-151,-152,-151,-152,-151,-151,-151,-151,-150,-150,
107
+	-150,-149,-149,-149,-149,-148,-147,-147,-146,-146,-145,-145,-144,-144,-143,-142,
108
+	-141,-141,-140,-139,-139,-138,-137,-136,-135,-135,-133,-133,-132,-131,-130,-129,
109
+	-128,-127,-126,-125,-124,-123,-121,-121,-119,-118,-117,-116,-115,-114,-112,-111,
110
+	-110,-109,-107,-106,-105,-104,-102,-102,-100, -99, -97, -97, -95, -94, -92, -91,
111
+	 -90, -88, -87, -86, -85, -84, -82, -81, -79, -78, -76, -76, -74, -73, -71, -70,
112
+	 -68, -67, -66, -65, -63, -62, -60, -60, -58, -57, -55, -55, -53, -52, -50, -49,
113
+	 -48, -46, -45, -44, -43, -42, -40, -39, -38, -37, -36, -35, -34, -32, -31, -30,
114
+	 -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -19, -17, -16, -15, -14,
115
+	 -14, -13, -12, -11, -11, -10,  -9,  -9,  -8,  -8,  -7,  -7,  -6,  -5,  -4,  -4,
116
+	  -3,  -3,  -3,  -2,  -2,  -2,  -1,  -1,   0,  -1,   0,  -1,   0,   0,   0,   0,
117
+	   0,
118
+	2048,2048,2048,2048,2047,2047,2046,2045,2043,2042,2041,2039,2037,2035,2033,2031,
119
+	2028,2026,2024,2021,2018,2015,2012,2009,2005,2002,1999,1995,1991,1987,1982,1978,
120
+	1974,1969,1965,1960,1955,1951,1946,1940,1934,1929,1924,1918,1912,1906,1900,1895,
121
+	1888,1882,1875,1869,1862,1856,1849,1842,1835,1828,1821,1814,1806,1799,1791,1783,
122
+	1776,1768,1760,1753,1744,1737,1728,1720,1711,1703,1695,1686,1677,1668,1659,1651,
123
+	1641,1633,1623,1614,1605,1596,1587,1577,1567,1559,1549,1539,1529,1520,1510,1499,
124
+	1490,1480,1470,1460,1450,1440,1430,1420,1408,1398,1389,1378,1367,1357,1346,1336,
125
+	1325,1315,1304,1293,1282,1272,1261,1250,1239,1229,1218,1207,1196,1185,1174,1163,
126
+	1152,1141,1130,1119,1108,1097,1086,1075,1063,1052,1042,1030,1019,1008, 997, 986,
127
+	 974, 964, 952, 941, 930, 919, 908, 897, 886, 875, 864, 853, 842, 831, 820, 809,
128
+	 798, 787, 776, 765, 754, 744, 733, 722, 711, 700, 690, 679, 668, 658, 647, 637,
129
+	 626, 616, 605, 595, 584, 574, 564, 554, 543, 534, 524, 514, 503, 494, 483, 473,
130
+	 464, 454, 444, 435, 425, 416, 407, 397, 387, 378, 370, 360, 351, 342, 333, 325,
131
+	 315, 307, 298, 290, 281, 273, 265, 256, 248, 241, 233, 225, 216, 209, 201, 193,
132
+	 186, 178, 171, 164, 157, 150, 143, 137, 129, 123, 117, 110, 103,  97,  91,  85,
133
+	  79,  74,  68,  62,  56,  51,  46,  41,  35,  31,  27,  22,  17,  13,   8,   4,
134
+	   0
135
+};
136
+
137
+static constexpr short sinc[] =
98 138
 {
99
-	// Make pointers into gaussian based on fractional position between samples
100
-	int offset = (v->interp_pos >> 4) & 0xFF;
101
-	auto fwd = gauss + 255 - offset;
102
-	auto rev = gauss + offset; // mirror left half of gaussian
139
+	39,  -315,   666, 15642,   666,  -315,    39,   -38,
140
+	38,  -302,   613, 15642,   718,  -328,    41,   -38,
141
+	36,  -288,   561, 15641,   772,  -342,    42,   -38,
142
+	35,  -275,   510, 15639,   826,  -355,    44,   -38,
143
+	33,  -263,   459, 15636,   880,  -369,    46,   -38,
144
+	32,  -250,   408, 15632,   935,  -383,    47,   -38,
145
+	31,  -237,   358, 15628,   990,  -396,    49,   -38,
146
+	29,  -224,   309, 15622,  1046,  -410,    51,   -38,
147
+	28,  -212,   259, 15616,  1103,  -425,    53,   -38,
148
+	27,  -200,   211, 15609,  1159,  -439,    54,   -38,
149
+	25,  -188,   163, 15601,  1216,  -453,    56,   -38,
150
+	24,  -175,   115, 15593,  1274,  -467,    58,   -38,
151
+	23,  -164,    68, 15583,  1332,  -482,    60,   -38,
152
+	22,  -152,    22, 15573,  1391,  -496,    62,   -37,
153
+	21,  -140,   -24, 15562,  1450,  -511,    64,   -37,
154
+	19,  -128,   -70, 15550,  1509,  -526,    66,   -37,
155
+	18,  -117,  -115, 15538,  1569,  -540,    68,   -37,
156
+	17,  -106,  -159, 15524,  1629,  -555,    70,   -37,
157
+	16,   -94,  -203, 15510,  1690,  -570,    72,   -36,
158
+	15,   -83,  -247, 15495,  1751,  -585,    74,   -36,
159
+	14,   -72,  -289, 15479,  1813,  -600,    76,   -36,
160
+	13,   -62,  -332, 15462,  1875,  -616,    79,   -36,
161
+	12,   -51,  -374, 15445,  1937,  -631,    81,   -35,
162
+	11,   -40,  -415, 15426,  2000,  -646,    83,   -35,
163
+	11,   -30,  -456, 15407,  2063,  -662,    85,   -35,
164
+	10,   -20,  -496, 15387,  2127,  -677,    88,   -34,
165
+	 9,    -9,  -536, 15366,  2191,  -693,    90,   -34,
166
+	 8,     1,  -576, 15345,  2256,  -708,    92,   -34,
167
+	 7,    10,  -614, 15323,  2321,  -724,    95,   -33,
168
+	 7,    20,  -653, 15300,  2386,  -740,    97,   -33,
169
+	 6,    30,  -690, 15276,  2451,  -755,    99,   -33,
170
+	 5,    39,  -728, 15251,  2517,  -771,   102,   -32,
171
+	 5,    49,  -764, 15226,  2584,  -787,   104,   -32,
172
+	 4,    58,  -801, 15200,  2651,  -803,   107,   -32,
173
+	 3,    67,  -836, 15173,  2718,  -819,   109,   -31,
174
+	 3,    76,  -871, 15145,  2785,  -835,   112,   -31,
175
+	 2,    85,  -906, 15117,  2853,  -851,   115,   -30,
176
+	 2,    93,  -940, 15087,  2921,  -867,   117,   -30,
177
+	 1,   102,  -974, 15057,  2990,  -883,   120,   -29,
178
+	 1,   110, -1007, 15027,  3059,  -899,   122,   -29,
179
+	 0,   118, -1039, 14995,  3128,  -915,   125,   -29,
180
+	 0,   127, -1071, 14963,  3198,  -931,   128,   -28,
181
+	-1,   135, -1103, 14930,  3268,  -948,   131,   -28,
182
+	-1,   142, -1134, 14896,  3338,  -964,   133,   -27,
183
+	-1,   150, -1164, 14862,  3409,  -980,   136,   -27,
184
+	-2,   158, -1194, 14827,  3480,  -996,   139,   -26,
185
+	-2,   165, -1224, 14791,  3551, -1013,   142,   -26,
186
+	-3,   172, -1253, 14754,  3622, -1029,   144,   -25,
187
+	-3,   179, -1281, 14717,  3694, -1045,   147,   -25,
188
+	-3,   187, -1309, 14679,  3766, -1062,   150,   -24,
189
+	-3,   193, -1337, 14640,  3839, -1078,   153,   -24,
190
+	-4,   200, -1363, 14601,  3912, -1094,   156,   -23,
191
+	-4,   207, -1390, 14561,  3985, -1110,   159,   -23,
192
+	-4,   213, -1416, 14520,  4058, -1127,   162,   -22,
193
+	-4,   220, -1441, 14479,  4131, -1143,   165,   -22,
194
+	-4,   226, -1466, 14437,  4205, -1159,   168,   -22,
195
+	-5,   232, -1490, 14394,  4279, -1175,   171,   -21,
196
+	-5,   238, -1514, 14350,  4354, -1192,   174,   -21,
197
+	-5,   244, -1537, 14306,  4428, -1208,   177,   -20,
198
+	-5,   249, -1560, 14261,  4503, -1224,   180,   -20,
199
+	-5,   255, -1583, 14216,  4578, -1240,   183,   -19,
200
+	-5,   260, -1604, 14169,  4653, -1256,   186,   -19,
201
+	-5,   265, -1626, 14123,  4729, -1272,   189,   -18,
202
+	-5,   271, -1647, 14075,  4805, -1288,   192,   -18,
203
+	-5,   276, -1667, 14027,  4881, -1304,   195,   -17,
204
+	-6,   280, -1687, 13978,  4957, -1320,   198,   -17,
205
+	-6,   285, -1706, 13929,  5033, -1336,   201,   -16,
206
+	-6,   290, -1725, 13879,  5110, -1352,   204,   -16,
207
+	-6,   294, -1744, 13829,  5186, -1368,   207,   -15,
208
+	-6,   299, -1762, 13777,  5263, -1383,   210,   -15,
209
+	-6,   303, -1779, 13726,  5340, -1399,   213,   -14,
210
+	-6,   307, -1796, 13673,  5418, -1414,   216,   -14,
211
+	-6,   311, -1813, 13620,  5495, -1430,   219,   -13,
212
+	-5,   315, -1829, 13567,  5573, -1445,   222,   -13,
213
+	-5,   319, -1844, 13512,  5651, -1461,   225,   -13,
214
+	-5,   322, -1859, 13458,  5728, -1476,   229,   -12,
215
+	-5,   326, -1874, 13402,  5806, -1491,   232,   -12,
216
+	-5,   329, -1888, 13347,  5885, -1506,   235,   -11,
217
+	-5,   332, -1902, 13290,  5963, -1521,   238,   -11,
218
+	-5,   335, -1915, 13233,  6041, -1536,   241,   -10,
219
+	-5,   338, -1928, 13176,  6120, -1551,   244,   -10,
220
+	-5,   341, -1940, 13118,  6199, -1566,   247,   -10,
221
+	-5,   344, -1952, 13059,  6277, -1580,   250,    -9,
222
+	-5,   347, -1964, 13000,  6356, -1595,   253,    -9,
223
+	-5,   349, -1975, 12940,  6435, -1609,   256,    -8,
224
+	-4,   352, -1986, 12880,  6514, -1623,   259,    -8,
225
+	-4,   354, -1996, 12819,  6594, -1637,   262,    -8,
226
+	-4,   356, -2005, 12758,  6673, -1651,   265,    -7,
227
+	-4,   358, -2015, 12696,  6752, -1665,   268,    -7,
228
+	-4,   360, -2024, 12634,  6831, -1679,   271,    -7,
229
+	-4,   362, -2032, 12572,  6911, -1693,   274,    -6,
230
+	-4,   364, -2040, 12509,  6990, -1706,   277,    -6,
231
+	-4,   366, -2048, 12445,  7070, -1719,   280,    -6,
232
+	-3,   367, -2055, 12381,  7149, -1732,   283,    -5,
233
+	-3,   369, -2062, 12316,  7229, -1745,   286,    -5,
234
+	-3,   370, -2068, 12251,  7308, -1758,   289,    -5,
235
+	-3,   371, -2074, 12186,  7388, -1771,   291,    -4,
236
+	-3,   372, -2079, 12120,  7467, -1784,   294,    -4,
237
+	-3,   373, -2084, 12054,  7547, -1796,   297,    -4,
238
+	-3,   374, -2089, 11987,  7626, -1808,   300,    -4,
239
+	-2,   375, -2094, 11920,  7706, -1820,   303,    -3,
240
+	-2,   376, -2098, 11852,  7785, -1832,   305,    -3,
241
+	-2,   376, -2101, 11785,  7865, -1844,   308,    -3,
242
+	-2,   377, -2104, 11716,  7944, -1855,   311,    -3,
243
+	-2,   377, -2107, 11647,  8024, -1866,   313,    -2,
244
+	-2,   378, -2110, 11578,  8103, -1877,   316,    -2,
245
+	-2,   378, -2112, 11509,  8182, -1888,   318,    -2,
246
+	-1,   378, -2113, 11439,  8262, -1899,   321,    -2,
247
+	-1,   378, -2115, 11369,  8341, -1909,   323,    -2,
248
+	-1,   378, -2116, 11298,  8420, -1920,   326,    -2,
249
+	-1,   378, -2116, 11227,  8499, -1930,   328,    -1,
250
+	-1,   378, -2116, 11156,  8578, -1940,   331,    -1,
251
+	-1,   378, -2116, 11084,  8656, -1949,   333,    -1,
252
+	-1,   377, -2116, 11012,  8735, -1959,   335,    -1,
253
+	-1,   377, -2115, 10940,  8814, -1968,   337,    -1,
254
+	-1,   377, -2114, 10867,  8892, -1977,   340,    -1,
255
+	-1,   376, -2112, 10795,  8971, -1985,   342,    -1,
256
+	 0,   375, -2111, 10721,  9049, -1994,   344,    -1,
257
+	 0,   375, -2108, 10648,  9127, -2002,   346,     0,
258
+	 0,   374, -2106, 10574,  9205, -2010,   348,     0,
259
+	 0,   373, -2103, 10500,  9283, -2018,   350,     0,
260
+	 0,   372, -2100, 10426,  9360, -2025,   352,     0,
261
+	 0,   371, -2097, 10351,  9438, -2032,   354,     0,
262
+	 0,   370, -2093, 10276,  9515, -2039,   355,     0,
263
+	 0,   369, -2089, 10201,  9592, -2046,   357,     0,
264
+	 0,   367, -2084, 10126,  9669, -2052,   359,     0,
265
+	 0,   366, -2080, 10050,  9745, -2058,   360,     0,
266
+	 0,   365, -2075,  9974,  9822, -2064,   362,     0,
267
+	 0,   363, -2070,  9898,  9898, -2070,   363,     0,
268
+	 0,   362, -2064,  9822,  9974, -2075,   365,     0,
269
+	 0,   360, -2058,  9745, 10050, -2080,   366,     0,
270
+	 0,   359, -2052,  9669, 10126, -2084,   367,     0,
271
+	 0,   357, -2046,  9592, 10201, -2089,   369,     0,
272
+	 0,   355, -2039,  9515, 10276, -2093,   370,     0,
273
+	 0,   354, -2032,  9438, 10351, -2097,   371,     0,
274
+	 0,   352, -2025,  9360, 10426, -2100,   372,     0,
275
+	 0,   350, -2018,  9283, 10500, -2103,   373,     0,
276
+	 0,   348, -2010,  9205, 10574, -2106,   374,     0,
277
+	 0,   346, -2002,  9127, 10648, -2108,   375,     0,
278
+	-1,   344, -1994,  9049, 10721, -2111,   375,     0,
279
+	-1,   342, -1985,  8971, 10795, -2112,   376,    -1,
280
+	-1,   340, -1977,  8892, 10867, -2114,   377,    -1,
281
+	-1,   337, -1968,  8814, 10940, -2115,   377,    -1,
282
+	-1,   335, -1959,  8735, 11012, -2116,   377,    -1,
283
+	-1,   333, -1949,  8656, 11084, -2116,   378,    -1,
284
+	-1,   331, -1940,  8578, 11156, -2116,   378,    -1,
285
+	-1,   328, -1930,  8499, 11227, -2116,   378,    -1,
286
+	-2,   326, -1920,  8420, 11298, -2116,   378,    -1,
287
+	-2,   323, -1909,  8341, 11369, -2115,   378,    -1,
288
+	-2,   321, -1899,  8262, 11439, -2113,   378,    -1,
289
+	-2,   318, -1888,  8182, 11509, -2112,   378,    -2,
290
+	-2,   316, -1877,  8103, 11578, -2110,   378,    -2,
291
+	-2,   313, -1866,  8024, 11647, -2107,   377,    -2,
292
+	-3,   311, -1855,  7944, 11716, -2104,   377,    -2,
293
+	-3,   308, -1844,  7865, 11785, -2101,   376,    -2,
294
+	-3,   305, -1832,  7785, 11852, -2098,   376,    -2,
295
+	-3,   303, -1820,  7706, 11920, -2094,   375,    -2,
296
+	-4,   300, -1808,  7626, 11987, -2089,   374,    -3,
297
+	-4,   297, -1796,  7547, 12054, -2084,   373,    -3,
298
+	-4,   294, -1784,  7467, 12120, -2079,   372,    -3,
299
+	-4,   291, -1771,  7388, 12186, -2074,   371,    -3,
300
+	-5,   289, -1758,  7308, 12251, -2068,   370,    -3,
301
+	-5,   286, -1745,  7229, 12316, -2062,   369,    -3,
302
+	-5,   283, -1732,  7149, 12381, -2055,   367,    -3,
303
+	-6,   280, -1719,  7070, 12445, -2048,   366,    -4,
304
+	-6,   277, -1706,  6990, 12509, -2040,   364,    -4,
305
+	-6,   274, -1693,  6911, 12572, -2032,   362,    -4,
306
+	-7,   271, -1679,  6831, 12634, -2024,   360,    -4,
307
+	-7,   268, -1665,  6752, 12696, -2015,   358,    -4,
308
+	-7,   265, -1651,  6673, 12758, -2005,   356,    -4,
309
+	-8,   262, -1637,  6594, 12819, -1996,   354,    -4,
310
+	-8,   259, -1623,  6514, 12880, -1986,   352,    -4,
311
+	-8,   256, -1609,  6435, 12940, -1975,   349,    -5,
312
+	-9,   253, -1595,  6356, 13000, -1964,   347,    -5,
313
+	-9,   250, -1580,  6277, 13059, -1952,   344,    -5,
314
+   -10,   247, -1566,  6199, 13118, -1940,   341,    -5,
315
+   -10,   244, -1551,  6120, 13176, -1928,   338,    -5,
316
+   -10,   241, -1536,  6041, 13233, -1915,   335,    -5,
317
+   -11,   238, -1521,  5963, 13290, -1902,   332,    -5,
318
+   -11,   235, -1506,  5885, 13347, -1888,   329,    -5,
319
+   -12,   232, -1491,  5806, 13402, -1874,   326,    -5,
320
+   -12,   229, -1476,  5728, 13458, -1859,   322,    -5,
321
+   -13,   225, -1461,  5651, 13512, -1844,   319,    -5,
322
+   -13,   222, -1445,  5573, 13567, -1829,   315,    -5,
323
+   -13,   219, -1430,  5495, 13620, -1813,   311,    -6,
324
+   -14,   216, -1414,  5418, 13673, -1796,   307,    -6,
325
+   -14,   213, -1399,  5340, 13726, -1779,   303,    -6,
326
+   -15,   210, -1383,  5263, 13777, -1762,   299,    -6,
327
+   -15,   207, -1368,  5186, 13829, -1744,   294,    -6,
328
+   -16,   204, -1352,  5110, 13879, -1725,   290,    -6,
329
+   -16,   201, -1336,  5033, 13929, -1706,   285,    -6,
330
+   -17,   198, -1320,  4957, 13978, -1687,   280,    -6,
331
+   -17,   195, -1304,  4881, 14027, -1667,   276,    -5,
332
+   -18,   192, -1288,  4805, 14075, -1647,   271,    -5,
333
+   -18,   189, -1272,  4729, 14123, -1626,   265,    -5,
334
+   -19,   186, -1256,  4653, 14169, -1604,   260,    -5,
335
+   -19,   183, -1240,  4578, 14216, -1583,   255,    -5,
336
+   -20,   180, -1224,  4503, 14261, -1560,   249,    -5,
337
+   -20,   177, -1208,  4428, 14306, -1537,   244,    -5,
338
+   -21,   174, -1192,  4354, 14350, -1514,   238,    -5,
339
+   -21,   171, -1175,  4279, 14394, -1490,   232,    -5,
340
+   -22,   168, -1159,  4205, 14437, -1466,   226,    -4,
341
+   -22,   165, -1143,  4131, 14479, -1441,   220,    -4,
342
+   -22,   162, -1127,  4058, 14520, -1416,   213,    -4,
343
+   -23,   159, -1110,  3985, 14561, -1390,   207,    -4,
344
+   -23,   156, -1094,  3912, 14601, -1363,   200,    -4,
345
+   -24,   153, -1078,  3839, 14640, -1337,   193,    -3,
346
+   -24,   150, -1062,  3766, 14679, -1309,   187,    -3,
347
+   -25,   147, -1045,  3694, 14717, -1281,   179,    -3,
348
+   -25,   144, -1029,  3622, 14754, -1253,   172,    -3,
349
+   -26,   142, -1013,  3551, 14791, -1224,   165,    -2,
350
+   -26,   139,  -996,  3480, 14827, -1194,   158,    -2,
351
+   -27,   136,  -980,  3409, 14862, -1164,   150,    -1,
352
+   -27,   133,  -964,  3338, 14896, -1134,   142,    -1,
353
+   -28,   131,  -948,  3268, 14930, -1103,   135,    -1,
354
+   -28,   128,  -931,  3198, 14963, -1071,   127,     0,
355
+   -29,   125,  -915,  3128, 14995, -1039,   118,     0,
356
+   -29,   122,  -899,  3059, 15027, -1007,   110,     1,
357
+   -29,   120,  -883,  2990, 15057,  -974,   102,     1,
358
+   -30,   117,  -867,  2921, 15087,  -940,    93,     2,
359
+   -30,   115,  -851,  2853, 15117,  -906,    85,     2,
360
+   -31,   112,  -835,  2785, 15145,  -871,    76,     3,
361
+   -31,   109,  -819,  2718, 15173,  -836,    67,     3,
362
+   -32,   107,  -803,  2651, 15200,  -801,    58,     4,
363
+   -32,   104,  -787,  2584, 15226,  -764,    49,     5,
364
+   -32,   102,  -771,  2517, 15251,  -728,    39,     5,
365
+   -33,    99,  -755,  2451, 15276,  -690,    30,     6,
366
+   -33,    97,  -740,  2386, 15300,  -653,    20,     7,
367
+   -33,    95,  -724,  2321, 15323,  -614,    10,     7,
368
+   -34,    92,  -708,  2256, 15345,  -576,     1,     8,
369
+   -34,    90,  -693,  2191, 15366,  -536,    -9,     9,
370
+   -34,    88,  -677,  2127, 15387,  -496,   -20,    10,
371
+   -35,    85,  -662,  2063, 15407,  -456,   -30,    11,
372
+   -35,    83,  -646,  2000, 15426,  -415,   -40,    11,
373
+   -35,    81,  -631,  1937, 15445,  -374,   -51,    12,
374
+   -36,    79,  -616,  1875, 15462,  -332,   -62,    13,
375
+   -36,    76,  -600,  1813, 15479,  -289,   -72,    14,
376
+   -36,    74,  -585,  1751, 15495,  -247,   -83,    15,
377
+   -36,    72,  -570,  1690, 15510,  -203,   -94,    16,
378
+   -37,    70,  -555,  1629, 15524,  -159,  -106,    17,
379
+   -37,    68,  -540,  1569, 15538,  -115,  -117,    18,
380
+   -37,    66,  -526,  1509, 15550,   -70,  -128,    19,
381
+   -37,    64,  -511,  1450, 15562,   -24,  -140,    21,
382
+   -37,    62,  -496,  1391, 15573,    22,  -152,    22,
383
+   -38,    60,  -482,  1332, 15583,    68,  -164,    23,
384
+   -38,    58,  -467,  1274, 15593,   115,  -175,    24,
385
+   -38,    56,  -453,  1216, 15601,   163,  -188,    25,
386
+   -38,    54,  -439,  1159, 15609,   211,  -200,    27,
387
+   -38,    53,  -425,  1103, 15616,   259,  -212,    28,
388
+   -38,    51,  -410,  1046, 15622,   309,  -224,    29,
389
+   -38,    49,  -396,   990, 15628,   358,  -237,    31,
390
+   -38,    47,  -383,   935, 15632,   408,  -250,    32,
391
+   -38,    46,  -369,   880, 15636,   459,  -263,    33,
392
+   -38,    44,  -355,   826, 15639,   510,  -275,    35,
393
+   -38,    42,  -342,   772, 15641,   561,  -288,    36,
394
+   -38,    41,  -328,   718, 15642,   613,  -302,    38
395
+};
103 396
 
397
+int SPC_DSP::interpolate(const voice_t *v)
398
+{
399
+	int out;
104 400
 	auto in = &v->buf[(v->interp_pos >> 12) + v->buf_pos];
105
-	int out = (fwd[0] * in[0]) >> 11;
106
-	out += (fwd[256] * in[1]) >> 11;
107
-	out += (rev[256] * in[2]) >> 11;
108
-	out = static_cast<int16_t>(out);
109
-	out += (rev[0] * in[3]) >> 11;
110 401
 
111
-	CLAMP16(out);
112
-	out &= ~1;
402
+	switch (Settings.InterpolationMethod)
403
+	{
404
+		case 0: // raw
405
+			out = in[0] & ~1;
406
+			break;
407
+
408
+		case 1: // linear interpolation
409
+		{
410
+			int fract = v->interp_pos & 0xFFF;
411
+			out = (0x1000 - fract) * in[0];
412
+			out += fract * in[1];
413
+			out >>= 12;
414
+
415
+			CLAMP16(out);
416
+			break;
417
+		}
418
+
419
+		case 3: // cubic filter
420
+		{
421
+			// Make pointers into cubic based on fractional position between samples
422
+			int offset = (v->interp_pos >> 4) & 0xFF;
423
+			auto fwd = cubic + offset;
424
+			auto rev = cubic + 256 - offset; // mirror left half of cubic
425
+
426
+			out = fwd[0] * in[0];
427
+			out += fwd[257] * in[1];
428
+			out += rev[257] * in[2];
429
+			out += rev[0] * in[3];
430
+			out >>= 11;
431
+
432
+			CLAMP16(out);
433
+			break;
434
+		}
435
+
436
+		case 4: // sinc filter
437
+		{
438
+			int offset = (v->interp_pos & 0xFF0) >> 1;
439
+			auto filt = sinc + offset;
440
+
441
+			out = filt[0] * in[0];
442
+			out += filt[1] * in[1];
443
+			out += filt[2] * in[2];
444
+			out += filt[3] * in[3];
445
+			out += filt[4] * in[4];
446
+			out += filt[5] * in[5];
447
+			out += filt[6] * in[6];
448
+			out += filt[7] * in[7];
449
+			out >>= 14;
450
+
451
+			CLAMP16(out);
452
+			break;
453
+		}
454
+
455
+		default:
456
+		case 2: // Original gaussian filter
457
+		{
458
+			// Make pointers into gaussian based on fractional position between samples
459
+			int offset = (v->interp_pos >> 4) & 0xFF;
460
+			auto fwd = gauss + 255 - offset;
461
+			auto rev = gauss + offset; // mirror left half of gaussian
462
+
463
+			out = (fwd[0] * in[0]) >> 11;
464
+			out += (fwd[256] * in[1]) >> 11;
465
+			out += (rev[256] * in[2]) >> 11;
466
+			out = static_cast<int16_t>(out);
467
+			out += (rev[0] * in[3]) >> 11;
468
+
469
+			CLAMP16(out);
470
+			out &= ~1;
471
+		}
472
+	}
473
+
113 474
 	return out;
114 475
 }
115 476
 
116 477
 //// Counters
117 478
 
118
-static const int simple_counter_range = 2048 * 5 * 3; // 30720
479
+static constexpr int simple_counter_range = 2048 * 5 * 3; // 30720
119 480
 
120
-static const unsigned counter_rates[] =
481
+static constexpr unsigned counter_rates[] =
121 482
 {
122 483
 	simple_counter_range + 1, // never fires
123 484
 	2048, 1536,
... ...
@@ -134,7 +495,7 @@ static const unsigned counter_rates[] =
134 495
 	1
135 496
 };
136 497
 
137
-static const unsigned counter_offsets[] =
498
+static constexpr unsigned counter_offsets[] =
138 499
 {
139 500
 	1, 0, 1040,
140 501
 	536, 0, 1040,
... ...
@@ -630,20 +991,7 @@ void SPC_DSP::echo_27()
630 991
 		l = r = 0;
631 992
 
632 993
 	// Output sample to DAC
633
-#ifdef SPC_DSP_OUT_HOOK
634
-	SPC_DSP_OUT_HOOK(l, r);
635
-#else
636
-	sample_t *out = this->m.out;
637
-	out[0] = l;
638
-	out[1] = r;
639
-	out += 2;
640
-	if (out >= m.out_end)
641
-	{
642
-		out = this->m.extra;
643
-		this->m.out_end = &this->m.extra[extra_size];
644
-	}
645
-	this->m.out = out;
646
-#endif
994
+	this->resampler->push_sample(l, r);
647 995
 }
648 996
 void SPC_DSP::echo_28()
649 997
 {
... ...
@@ -652,12 +1000,7 @@ void SPC_DSP::echo_28()
652 1000
 void SPC_DSP::echo_write(int ch)
653 1001
 {
654 1002
 	if (!(this->m.t_echo_enabled & 0x20))
655
-	{
656
-		if (this->m.t_echo_ptr >= 0xffc0 && this->rom_enabled)
657
-			set_le16(&this->hi_ram[this->m.t_echo_ptr + ch * 2 - 0xffc0], this->m.t_echo_out [ch]);
658
-		else
659
-			set_le16(this->ECHO_PTR(ch), this->m.t_echo_out[ch]);
660
-	}
1003
+		set_le16(this->ECHO_PTR(ch), this->m.t_echo_out[ch]);
661 1004
 
662 1005
 	this->m.t_echo_out[ch] = 0;
663 1006
 }
... ...
@@ -741,7 +1084,7 @@ void SPC_DSP::run(int clocks_remain)
741 1084
 	switch (phase)
742 1085
 	{
743 1086
 		loop:
744
-#define PHASE(n) if (n && !--clocks_remain) break; case n:
1087
+#define PHASE(n) if (n && !--clocks_remain) break; /* Fall through */ case n:
745 1088
 		GEN_DSP_TIMING
746 1089
 #undef PHASE
747 1090
 
... ...
@@ -793,6 +1136,8 @@ void SPC_DSP::soft_reset_common()
793 1136
 	this->m.echo_offset = 0;
794 1137
 	this->m.phase = 0;
795 1138
 
1139
+	std::fill_n(&this->m.separate_echo_buffer[0], 0x10000, 0);
1140
+
796 1141
 	this->init_counter();
797 1142
 
798 1143
 	for (int i = 0; i < voice_count; ++i)
799 1144
similarity index 95%
800 1145
rename from src/in_snsf/snes9x/apu/SPC_DSP.h
801 1146
rename to src/in_snsf/snes9x/apu/bapu/dsp/SPC_DSP.h
... ...
@@ -4,6 +4,8 @@
4 4
 #pragma once
5 5
 
6 6
 #include "blargg_common.h"
7
+#include "../../resampler.h"
8
+#include "../../../snes9x.h"
7 9
 
8 10
 class SPC_DSP
9 11
 {
... ...
@@ -18,6 +20,8 @@ public:
18 20
 	typedef short sample_t;
19 21
 	void set_output(sample_t *out, int out_size);
20 22
 
23
+	void set_output(Resampler *resampler);
24
+
21 25
 	// Number of samples written to output since it was last set, always
22 26
 	// a multiple of 2. Undefined if more samples were generated than
23 27
 	// output buffer could hold.
... ...
@@ -56,8 +60,6 @@ public:
56 60
 	// Snes9x Accessor
57 61
 
58 62
 	int stereo_switch;
59
-	bool rom_enabled; // mirror
60
-	uint8_t *rom, *hi_ram; // mirror
61 63
 
62 64
 	void set_stereo_switch(int);
63 65
 	uint8_t reg_value(int, int);
... ...
@@ -130,6 +132,8 @@ public:
130 132
 private:
131 133
 	enum { brr_block_size = 9 };
132 134
 
135
+	Resampler *resampler;
136
+
133 137
 	struct state_t
134 138
 	{
135 139
 		uint8_t regs[register_count];
... ...
@@ -187,10 +191,13 @@ private:
187 191
 		// non-emulation state
188 192
 		uint8_t *ram; // 64K shared RAM between DSP and SMP
189 193
 		int mute_mask;
194
+
190 195
 		sample_t *out;
191 196
 		sample_t *out_end;
192 197
 		sample_t *out_begin;
193 198
 		sample_t extra[extra_size];
199
+
200
+		uint8_t separate_echo_buffer[0x10000];
194 201
 	};
195 202
 	state_t m;
196 203
 
... ...
@@ -225,7 +232,7 @@ private:
225 232
 	void voice_V9_V6_V3(voice_t *const);
226 233
 
227 234
 	// Current echo buffer pointer for left/right channel
228
-	uint8_t *ECHO_PTR(int ch) { return &this->m.ram[this->m.t_echo_ptr + ch * 2]; }
235
+	uint8_t *ECHO_PTR(int ch) { return Settings.SeparateEchoBuffer ? &this->m.separate_echo_buffer[this->m.t_echo_ptr + ch * 2] : &this->m.ram[this->m.t_echo_ptr + ch * 2]; }
229 236
 	// Sample in echo history buffer, where 0 is the oldest
230 237
 	int *ECHO_FIR(size_t i) { return this->m.echo_hist_pos[i]; }
231 238
 	// Calculate FIR point for left/right channel
232 239
similarity index 100%
233 240
rename from src/in_snsf/snes9x/apu/blargg_common.h
234 241
rename to src/in_snsf/snes9x/apu/bapu/dsp/blargg_common.h
235 242
similarity index 100%
236 243
rename from src/in_snsf/snes9x/apu/blargg_config.h
237 244
rename to src/in_snsf/snes9x/apu/bapu/dsp/blargg_config.h
238 245
similarity index 100%
239 246
rename from src/in_snsf/snes9x/apu/blargg_endian.h
240 247
rename to src/in_snsf/snes9x/apu/bapu/dsp/blargg_endian.h
241 248
new file mode 100644
... ...
@@ -0,0 +1,27 @@
1
+#include "../snes/snes.hpp"
2
+#include "sdsp.hpp"
3
+#include "SPC_DSP.h"
4
+#include "../smp/smp.hpp"
5
+
6
+namespace SNES
7
+{
8
+	DSP dsp;
9
+
10
+	void DSP::power()
11
+	{
12
+		this->spc_dsp.init(smp.apuram.get());
13
+		this->spc_dsp.reset();
14
+		this->clock = 0;
15
+	}
16
+
17
+	void DSP::reset()
18
+	{
19
+		this->spc_dsp.soft_reset();
20
+		this->clock = 0;
21
+	}
22
+
23
+	DSP::DSP()
24
+	{
25
+		this->clock = 0;
26
+	}
27
+}
0 28
new file mode 100644
... ...
@@ -0,0 +1,41 @@
1
+#pragma once
2
+
3
+#include "../snes/snes.hpp"
4
+#include "SPC_DSP.h"
5
+
6
+namespace SNES
7
+{
8
+	class DSP : public Processor
9
+	{
10
+	public:
11
+		uint8_t read(uint8_t addr)
12
+		{
13
+			this->synchronize();
14
+			return this->spc_dsp.read(addr);
15
+		}
16
+
17
+		void synchronize()
18
+		{
19
+			if (this->clock)
20
+			{
21
+				this->spc_dsp.run(this->clock);
22
+				this->clock = 0;
23
+			}
24
+		}
25
+
26
+		void write(uint8_t addr, uint8_t data)
27
+		{
28
+			this->synchronize();
29
+			this->spc_dsp.write(addr, data);
30
+		}
31
+
32
+		void power();
33
+		void reset();
34
+
35
+		DSP();
36
+
37
+		SPC_DSP spc_dsp;
38
+	};
39
+
40
+	extern DSP dsp;
41
+}
0 42
new file mode 100644
... ...
@@ -0,0 +1,140 @@
1
+#include "smp.hpp"
2
+
3
+namespace SNES
4
+{
5
+	uint8_t SMP::op_adc(uint8_t x, uint8_t y)
6
+	{
7
+		int r = x + y + this->regs.p.c;
8
+		this->regs.p.n = r & 0x80;
9
+		this->regs.p.v = ~(x ^ y) & (x ^ r) & 0x80;
10
+		this->regs.p.h = (x ^ y ^ r) & 0x10;
11
+		this->regs.p.z = static_cast<uint8_t>(r) == 0;
12
+		this->regs.p.c = r > 0xff;
13
+		return r;
14
+	}
15
+
16
+	uint16_t SMP::op_addw(uint16_t x, uint16_t y)
17
+	{
18
+		this->regs.p.c = 0;
19
+		uint16_t r = this->op_adc(x, y);
20
+		r |= this->op_adc(x >> 8, y >> 8) << 8;
21
+		regs.p.z = r == 0;
22
+		return r;
23
+	}
24
+
25
+	uint8_t SMP::op_and(uint8_t x, uint8_t y)
26
+	{
27
+		x &= y;
28
+		regs.p.n = x & 0x80;
29
+		regs.p.z = x == 0;
30
+		return x;
31
+	}
32
+
33
+	uint8_t SMP::op_cmp(uint8_t x, uint8_t y)
34
+	{
35
+		int r = x - y;
36
+		regs.p.n = r & 0x80;
37
+		regs.p.z = static_cast<uint8_t>(r) == 0;
38
+		regs.p.c = r >= 0;
39
+		return x;
40
+	}
41
+
42
+	uint16_t SMP::op_cmpw(uint16_t x, uint16_t y)
43
+	{
44
+		int r = x - y;
45
+		regs.p.n = r & 0x8000;
46
+		regs.p.z = static_cast<uint16_t>(r) == 0;
47
+		regs.p.c = r >= 0;
48
+		return x;
49
+	}
50
+
51
+	uint8_t SMP::op_eor(uint8_t x, uint8_t y)
52
+	{
53
+		x ^= y;
54
+		regs.p.n = x & 0x80;
55
+		regs.p.z = x == 0;
56
+		return x;
57
+	}
58
+
59
+	uint8_t SMP::op_or(uint8_t x, uint8_t y)
60
+	{
61
+		x |= y;
62
+		regs.p.n = x & 0x80;
63
+		regs.p.z = x == 0;
64
+		return x;
65
+	}
66
+
67
+	uint8_t SMP::op_sbc(uint8_t x, uint8_t y)
68
+	{
69
+		int r = x - y - !regs.p.c;
70
+		regs.p.n = r & 0x80;
71
+		regs.p.v = (x ^ y) & (x ^ r) & 0x80;
72
+		regs.p.h = !((x ^ y ^ r) & 0x10);
73
+		regs.p.z = static_cast<uint8_t>(r) == 0;
74
+		regs.p.c = r >= 0;
75
+		return r;
76
+	}
77
+
78
+	uint16_t SMP::op_subw(uint16_t x, uint16_t y)
79
+	{
80
+		regs.p.c = 1;
81
+		uint16_t r = this->op_sbc(x, y);
82
+		r |= this->op_sbc(x >> 8, y >> 8) << 8;
83
+		regs.p.z = r == 0;
84
+		return r;
85
+	}
86
+
87
+	uint8_t SMP::op_inc(uint8_t x)
88
+	{
89
+		++x;
90
+		regs.p.n = x & 0x80;
91
+		regs.p.z = x == 0;
92
+		return x;
93
+	}
94
+
95
+	uint8_t SMP::op_dec(uint8_t x)
96
+	{
97
+		--x;
98
+		regs.p.n = x & 0x80;
99
+		regs.p.z = x == 0;
100
+		return x;
101
+	}
102
+
103
+	uint8_t SMP::op_asl(uint8_t x)
104
+	{
105
+		regs.p.c = x & 0x80;
106
+		x <<= 1;
107
+		regs.p.n = x & 0x80;
108
+		regs.p.z = x == 0;
109
+		return x;
110
+	}
111
+
112
+	uint8_t SMP::op_lsr(uint8_t x)
113
+	{
114
+		regs.p.c = x & 0x01;
115
+		x >>= 1;
116
+		regs.p.n = x & 0x80;
117
+		regs.p.z = x == 0;
118
+		return x;
119
+	}
120
+
121
+	uint8_t SMP::op_rol(uint8_t x)
122
+	{
123
+		unsigned carry = static_cast<unsigned>(regs.p.c);
124
+		regs.p.c = x & 0x80;
125
+		x = (x << 1) | carry;
126
+		regs.p.n = x & 0x80;
127
+		regs.p.z = x == 0;
128
+		return x;
129
+	}
130
+
131
+	uint8_t SMP::op_ror(uint8_t x)
132
+	{
133
+		unsigned carry = static_cast<unsigned>(regs.p.c) << 7;
134
+		regs.p.c = x & 0x01;
135
+		x = carry | (x >> 1);
136
+		regs.p.n = x & 0x80;
137
+		regs.p.z = x == 0;
138
+		return x;
139
+	}
140
+}
0 141
new file mode 100644
... ...
@@ -0,0 +1,2110 @@
1
+#include "smp.hpp"
2
+#include "../dsp/sdsp.hpp"
3
+
4
+namespace SNES
5
+{
6
+	void SMP::tick()
7
+	{
8
+		this->timer0.tick();
9
+		this->timer1.tick();
10
+		this->timer2.tick();
11
+
12
+		++this->clock;
13
+		++dsp.clock;
14
+	}
15
+
16
+	void SMP::tick(unsigned clocks)
17
+	{
18
+		this->timer0.tick(clocks);
19
+		this->timer1.tick(clocks);
20
+		this->timer2.tick(clocks);
21
+
22
+		this->clock += clocks;
23
+		dsp.clock += clocks;
24
+	}
25
+
26
+	void SMP::op_io()
27
+	{
28
+		this->tick();
29
+	}
30
+
31
+	void SMP::op_io(unsigned clocks)
32
+	{
33
+		this->tick(clocks);
34
+	}
35
+
36
+	uint8_t SMP::op_read(uint16_t addr)
37
+	{
38
+		this->tick();
39
+		if ((addr & 0xfff0) == 0x00f0)
40
+			return this->mmio_read(addr);
41
+		if (addr >= 0xffc0 && this->status.iplrom_enable)
42
+			return SMP::iplrom[addr & 0x3f];
43
+		return this->apuram[addr];
44
+	}
45
+
46
+	void SMP::op_write(uint16_t addr, uint8_t data)
47
+	{
48
+		this->tick();
49
+		if ((addr & 0xfff0) == 0x00f0)
50
+			this->mmio_write(addr, data);
51
+		this->apuram[addr] = data; // all writes go to RAM, even MMIO writes
52
+	}
53
+
54
+	uint8_t SMP::op_readstack()
55
+	{
56
+		this->tick();
57
+		return this->apuram[0x0100 | ++this->regs.sp];
58
+	}
59
+
60
+	void SMP::op_writestack(uint8_t data)
61
+	{
62
+		this->tick();
63
+		this->apuram[0x0100 | this->regs.sp--] = data;
64
+	}
65
+
66
+	void SMP::op_step()
67
+	{
68
+		const auto op_readpc = [&]() { return this->op_read(this->regs.pc++); };
69
+		const auto op_readdp = [&](uint16_t addr) { return this->op_read((this->regs.p.p << 8) + (addr & 0xff)); };
70
+		const auto op_writedp = [&](uint16_t addr, uint8_t data) { this->op_write((this->regs.p.p << 8) + (addr & 0xff), data); };
71
+		const auto op_readaddr = [&](uint16_t addr) { return this->op_read(addr); };
72
+		const auto op_writeaddr = [&](uint16_t addr, uint8_t data) { this->op_write(addr, data); };
73
+
74
+		if (!this->opcode_cycle)
75
+			this->opcode_number = op_readpc();
76
+
77
+		switch (opcode_number)
78
+		{
79
+			// Start of core/oppseudo_misc.cpp
80
+
81
+			case 0x00:
82
+				this->op_io();
83
+				break;
84
+
85
+			case 0xef:
86
+			case 0xff:
87
+				this->op_io(2);
88
+				--this->regs.pc;
89
+				break;
90
+
91
+			case 0x9f:
92
+				this->op_io(4);
93
+				this->regs.B.a = (this->regs.B.a >> 4) | (this->regs.B.a << 4);
94
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
95
+				this->regs.p.z = !this->regs.B.a;
96
+				break;
97
+
98
+			case 0xdf:
99
+				this->op_io(2);
100
+				if (this->regs.p.c || this->regs.B.a > 0x99)
101
+				{
102
+					this->regs.B.a += 0x60;
103
+					this->regs.p.c = 1;
104
+				}
105
+				if (this->regs.p.h || (this->regs.B.a & 15) > 0x09)
106
+					this->regs.B.a += 0x06;
107
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
108
+				this->regs.p.z = !this->regs.B.a;
109
+				break;
110
+
111
+			case 0xbe:
112
+				this->op_io(2);
113
+				if (!this->regs.p.c || this->regs.B.a > 0x99)
114
+				{
115
+					this->regs.B.a -= 0x60;
116
+					this->regs.p.c = 0;
117
+				}
118
+				if (!this->regs.p.h || (this->regs.B.a & 15) > 0x09)
119
+					this->regs.B.a -= 0x06;
120
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
121
+				this->regs.p.z = !this->regs.B.a;
122
+				break;
123
+
124
+			case 0x60:
125
+			case 0x80:
126
+				this->op_io();
127
+				this->regs.p.c = opcode_number == 0x80;
128
+				break;
129
+
130
+			case 0x20:
131
+			case 0x40:
132
+				this->op_io();
133
+				this->regs.p.p = opcode_number == 0x40;
134
+				break;
135
+
136
+			case 0xe0:
137
+				this->op_io();
138
+				this->regs.p.v = 0;
139
+				this->regs.p.h = 0;
140
+				break;
141
+
142
+			case 0xed:
143
+				this->op_io(2);
144
+				this->regs.p.c = !this->regs.p.c;
145
+				break;
146
+
147
+			case 0xa0:
148
+			case 0xc0:
149
+				this->op_io(2);
150
+				this->regs.p.i = opcode_number == 0xa0;
151
+				break;
152
+
153
+			case 0x02:
154
+			case 0x22:
155
+			case 0x42:
156
+			case 0x62:
157
+			case 0x82:
158
+			case 0xa2:
159
+			case 0xc2:
160
+			case 0xe2:
161
+				this->dp = op_readpc();
162
+				this->rd = op_readdp(this->dp);
163
+				this->rd |= 0x01 << ((opcode_number & 0xE0) >> 5);
164
+				op_writedp(this->dp, this->rd);
165
+				break;
166
+
167
+			case 0x12:
168
+			case 0x32:
169
+			case 0x52:
170
+			case 0x72:
171
+			case 0x92:
172
+			case 0xb2:
173
+			case 0xd2:
174
+			case 0xf2:
175
+				this->dp = op_readpc();
176
+				this->rd = op_readdp(this->dp);
177
+				this->rd &= ~(0x01 << ((opcode_number & 0xE0) >> 5));
178
+				op_writedp(this->dp, this->rd);
179
+				break;
180
+
181
+			case 0x2d:
182
+				this->op_io(2);
183
+				this->op_writestack(this->regs.B.a);
184
+				break;
185
+
186
+			case 0x4d:
187
+				this->op_io(2);
188
+				this->op_writestack(this->regs.x);
189
+				break;
190
+
191
+			case 0x6d:
192
+				this->op_io(2);
193
+				this->op_writestack(this->regs.B.y);
194
+				break;
195
+
196
+			case 0x0d:
197
+				this->op_io(2);
198
+				this->op_writestack(this->regs.p);
199
+				break;
200
+
201
+			case 0xae:
202
+				this->op_io(2);
203
+				this->regs.B.a = this->op_readstack();
204
+				break;
205
+
206
+			case 0xce:
207
+				this->op_io(2);
208
+				this->regs.x = this->op_readstack();
209
+				break;
210
+
211
+			case 0xee:
212
+				this->op_io(2);
213
+				this->regs.B.y = this->op_readstack();
214
+				break;
215
+
216
+			case 0x8e:
217
+				this->op_io(2);
218
+				this->regs.p = this->op_readstack();
219
+				break;
220
+
221
+			case 0xcf:
222
+				this->op_io(8);
223
+				this->ya = this->regs.B.y * this->regs.B.a;
224
+				this->regs.B.a = this->ya;
225
+				this->regs.B.y = this->ya >> 8;
226
+				// result is set based on y (high-byte) only
227
+				this->regs.p.n = !!(this->regs.B.y & 0x80);
228
+				this->regs.p.z = !this->regs.B.y;
229
+				break;
230
+
231
+			case 0x9e:
232
+				this->op_io(11);
233
+				this->ya = this->regs.ya;
234
+				// overflow set if quotient >= 256
235
+				this->regs.p.v = !!(this->regs.B.y >= this->regs.x);
236
+				this->regs.p.h = !!((this->regs.B.y & 15) >= (this->regs.x & 15));
237
+				if (this->regs.B.y < (this->regs.x << 1))
238
+				{
239
+					// if quotient is <= 511 (will fit into 9-bit result)
240
+					this->regs.B.a = this->ya / this->regs.x;
241
+					this->regs.B.y = this->ya % this->regs.x;
242
+				}
243
+				else
244
+				{
245
+					// otherwise, the quotient won't fit into regs.p.v + regs.B.a
246
+					// this emulates the odd behavior of the S-SMP in this case
247
+					this->regs.B.a = 255 - (this->ya - (this->regs.x << 9)) / (256 - this->regs.x);
248
+					this->regs.B.y = this->regs.x + (this->ya - (this->regs.x << 9)) % (256 - this->regs.x);
249
+				}
250
+				// result is set based on a (quotient) only
251
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
252
+				this->regs.p.z = !this->regs.B.a;
253
+				break;
254
+
255
+			// End of core/oppseudo_misc.cpp
256
+
257
+			// Start of core/oppseudo_mov.cpp
258
+
259
+			case 0x7d:
260
+				this->op_io();
261
+				this->regs.B.a = this->regs.x;
262
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
263
+				this->regs.p.z = !this->regs.B.a;
264
+				break;
265
+
266
+			case 0xdd:
267
+				this->op_io();
268
+				this->regs.B.a = this->regs.B.y;
269
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
270
+				this->regs.p.z = !this->regs.B.a;
271
+				break;
272
+
273
+			case 0x5d:
274
+				this->op_io();
275
+				this->regs.x = this->regs.B.a;
276
+				this->regs.p.n = !!(this->regs.x & 0x80);
277
+				this->regs.p.z = !this->regs.x;
278
+				break;
279
+
280
+			case 0xfd:
281
+				this->op_io();
282
+				this->regs.B.y = this->regs.B.a;
283
+				this->regs.p.n = !!(this->regs.B.y & 0x80);
284
+				this->regs.p.z = !this->regs.B.y;
285
+				break;
286
+
287
+			case 0x9d:
288
+				this->op_io();
289
+				this->regs.x = this->regs.sp;
290
+				this->regs.p.n = !!(this->regs.x & 0x80);
291
+				this->regs.p.z = !this->regs.x;
292
+				break;
293
+
294
+			case 0xbd:
295
+				this->op_io();
296
+				this->regs.sp = this->regs.x;
297
+				break;
298
+
299
+			case 0xe8:
300
+				this->regs.B.a = op_readpc();
301
+				this->regs.p.n = !!(this->regs.B.a & 0x80);
302
+				this->regs.p.z = !this->regs.B.a;
303
+				break;
304
+
305
+			case 0xcd:
306
+				this->regs.x = op_readpc();
307
+				this->regs.p.n = !!(this->regs.x & 0x80);
308
+				this->regs.p.z = !this->regs.x;
309
+				break;
310
+
311
+			case 0x8d:
312
+				this->regs.B.y = op_readpc();
313
+				this->regs.p.n = !!(this->regs.B.y & 0x80);
314
+				this->regs.p.z = !this->regs.B.y;
315
+				break;
316
+
317
+			case 0xe6:
318
+				switch (++this->opcode_cycle)
319
+				{
320
+					case 1:
321
+						this->op_io();
322
+						break;
323
+					case 2:
324
+						this->regs.B.a = op_readdp(this->regs.x);
325
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
326
+						this->regs.p.z = !this->regs.B.a;
327
+						this->opcode_cycle = 0;
328
+						break;
329
+				}
330
+				break;
331
+
332
+			case 0xbf:
333
+				switch (++this->opcode_cycle)
334
+				{
335
+					case 1:
336
+						this->op_io();
337
+						break;
338
+					case 2:
339
+						this->regs.B.a = op_readdp(this->regs.x++);
340
+						this->op_io();
341
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
342
+						this->regs.p.z = !this->regs.B.a;
343
+						this->opcode_cycle = 0;
344
+						break;
345
+				}
346
+				break;
347
+
348
+			case 0xe4:
349
+				switch (++this->opcode_cycle)
350
+				{
351
+					case 1:
352
+						this->sp = op_readpc();
353
+						break;
354
+					case 2:
355
+						this->regs.B.a = op_readdp(this->sp);
356
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
357
+						this->regs.p.z = !this->regs.B.a;
358
+						this->opcode_cycle = 0;
359
+						break;
360
+				}
361
+				break;
362
+
363
+			case 0xf8:
364
+				switch (++this->opcode_cycle)
365
+				{
366
+					case 1:
367
+						this->sp = op_readpc();
368
+						break;
369
+					case 2:
370
+						this->regs.x = op_readdp(this->sp);
371
+						this->regs.p.n = !!(this->regs.x & 0x80);
372
+						this->regs.p.z = !this->regs.x;
373
+						this->opcode_cycle = 0;
374
+						break;
375
+				}
376
+				break;
377
+
378
+			case 0xeb:
379
+				switch (++this->opcode_cycle)
380
+				{
381
+					case 1:
382
+						this->sp = op_readpc();
383
+						break;
384
+					case 2:
385
+						this->regs.B.y = op_readdp(this->sp);
386
+						this->regs.p.n = !!(this->regs.B.y & 0x80);
387
+						this->regs.p.z = !this->regs.B.y;
388
+						this->opcode_cycle = 0;
389
+						break;
390
+				}
391
+				break;
392
+
393
+			case 0xf4:
394
+				switch (++this->opcode_cycle)
395
+				{
396
+					case 1:
397
+						this->sp = op_readpc();
398
+						this->op_io();
399
+						break;
400
+					case 2:
401
+						this->regs.B.a = op_readdp(this->sp + this->regs.x);
402
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
403
+						this->regs.p.z = !this->regs.B.a;
404
+						this->opcode_cycle = 0;
405
+						break;
406
+				}
407
+				break;
408
+
409
+			case 0xf9:
410
+				switch (++this->opcode_cycle)
411
+				{
412
+					case 1:
413
+						this->sp = op_readpc();
414
+						this->op_io();
415
+						break;
416
+					case 2:
417
+						this->regs.x = op_readdp(this->sp + this->regs.B.y);
418
+						this->regs.p.n = !!(this->regs.x & 0x80);
419
+						this->regs.p.z = !this->regs.x;
420
+						this->opcode_cycle = 0;
421
+						break;
422
+				}
423
+				break;
424
+
425
+			case 0xfb:
426
+				switch (++this->opcode_cycle)
427
+				{
428
+					case 1:
429
+						this->sp = op_readpc();
430
+						this->op_io();
431
+						break;
432
+					case 2:
433
+						this->regs.B.y = op_readdp(this->sp + this->regs.x);
434
+						this->regs.p.n = !!(this->regs.B.y & 0x80);
435
+						this->regs.p.z = !this->regs.B.y;
436
+						this->opcode_cycle = 0;
437
+						break;
438
+				}
439
+				break;
440
+
441
+			case 0xe5:
442
+				switch (++this->opcode_cycle)
443
+				{
444
+					case 1:
445
+						this->sp = op_readpc();
446
+						break;
447
+					case 2:
448
+						this->sp |= op_readpc() << 8;
449
+						break;
450
+					case 3:
451
+						this->regs.B.a = op_readaddr(this->sp);
452
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
453
+						this->regs.p.z = !this->regs.B.a;
454
+						this->opcode_cycle = 0;
455
+						break;
456
+				}
457
+				break;
458
+
459
+			case 0xe9:
460
+				switch (++this->opcode_cycle)
461
+				{
462
+					case 1:
463
+						this->sp = op_readpc();
464
+						this->sp |= op_readpc() << 8;
465
+						break;
466
+					case 2:
467
+						this->regs.x = op_readaddr(this->sp);
468
+						this->regs.p.n = !!(this->regs.x & 0x80);
469
+						this->regs.p.z = !this->regs.x;
470
+						this->opcode_cycle = 0;
471
+						break;
472
+				}
473
+				break;
474
+
475
+			case 0xec:
476
+				switch (++this->opcode_cycle)
477
+				{
478
+					case 1:
479
+						this->sp = op_readpc();
480
+						this->sp |= op_readpc() << 8;
481
+						break;
482
+					case 2:
483
+						this->regs.B.y = op_readaddr(this->sp);
484
+						this->regs.p.n = !!(this->regs.B.y & 0x80);
485
+						this->regs.p.z = !this->regs.B.y;
486
+						this->opcode_cycle = 0;
487
+						break;
488
+				}
489
+				break;
490
+
491
+			case 0xf5:
492
+				switch (++this->opcode_cycle)
493
+				{
494
+					case 1:
495
+						this->sp = op_readpc();
496
+						this->sp |= op_readpc() << 8;
497
+						this->op_io();
498
+						break;
499
+					case 2:
500
+						this->regs.B.a = op_readaddr(this->sp + this->regs.x);
501
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
502
+						this->regs.p.z = !this->regs.B.a;
503
+						this->opcode_cycle = 0;
504
+						break;
505
+				}
506
+				break;
507
+
508
+			case 0xf6:
509
+				switch (++this->opcode_cycle)
510
+				{
511
+					case 1:
512
+						this->sp = op_readpc();
513
+						this->sp |= op_readpc() << 8;
514
+						this->op_io();
515
+						break;
516
+					case 2:
517
+						this->regs.B.a = op_readaddr(this->sp + this->regs.B.y);
518
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
519
+						this->regs.p.z = !this->regs.B.a;
520
+						this->opcode_cycle = 0;
521
+						break;
522
+				}
523
+				break;
524
+
525
+			case 0xe7:
526
+				switch (++this->opcode_cycle)
527
+				{
528
+					case 1:
529
+						this->dp = op_readpc() + this->regs.x;
530
+						this->op_io();
531
+						break;
532
+					case 2:
533
+						this->sp = op_readdp(this->dp);
534
+						break;
535
+					case 3:
536
+						this->sp |= op_readdp(this->dp + 1) << 8;
537
+						break;
538
+					case 4:
539
+						this->regs.B.a = op_readaddr(this->sp);
540
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
541
+						this->regs.p.z = !this->regs.B.a;
542
+						this->opcode_cycle = 0;
543
+						break;
544
+				}
545
+				break;
546
+
547
+			case 0xf7:
548
+				switch (++this->opcode_cycle)
549
+				{
550
+					case 1:
551
+						this->dp = op_readpc();
552
+						this->op_io();
553
+						break;
554
+					case 2:
555
+						this->sp = op_readdp(this->dp);
556
+						break;
557
+					case 3:
558
+						this->sp |= op_readdp(this->dp + 1) << 8;
559
+						break;
560
+					case 4:
561
+						this->regs.B.a = op_readaddr(this->sp + this->regs.B.y);
562
+						this->regs.p.n = !!(this->regs.B.a & 0x80);
563
+						this->regs.p.z = !this->regs.B.a;
564
+						this->opcode_cycle = 0;
565
+						break;
566
+				}
567
+				break;
568
+
569
+			case 0xfa:
570
+				switch (++this->opcode_cycle)
571
+				{
572
+					case 1:
573
+						this->sp = op_readpc();
574
+						break;
575
+					case 2:
576
+						this->rd = op_readdp(this->sp);
577
+						break;
578
+					case 3:
579
+						this->dp = op_readpc();
580
+						break;
581
+					case 4:
582
+						op_writedp(this->dp, this->rd);
583
+						this->opcode_cycle = 0;
584
+						break;
585
+				}
586
+				break;
587
+
588
+			case 0x8f:
589
+				switch (++this->opcode_cycle)
590
+				{
591
+					case 1:
592
+						this->rd = op_readpc();
593
+						this->dp = op_readpc();
594
+						break;
595
+					case 2:
596
+						op_readdp(this->dp);
597
+						break;
598
+					case 3:
599
+						op_writedp(this->dp, this->rd);
600
+						this->opcode_cycle = 0;
601
+						break;
602
+				}
603
+				break;
604
+
605
+			case 0xc6:
606
+				switch (++this->opcode_cycle)
607
+				{
608
+					case 1:
609
+						this->op_io();
610
+						break;
611
+					case 2:
612
+						op_readdp(this->regs.x);
613
+						break;
614
+					case 3:
615
+						op_writedp(this->regs.x, this->regs.B.a);
616
+						this->opcode_cycle = 0;
617
+						break;
618
+				}
619
+				break;
620
+
621
+			case 0xaf:
622
+				switch (++this->opcode_cycle)
623
+				{
624
+					case 1:
625
+						this->op_io(2);
626
+						break;
627
+					case 2:
628
+						op_writedp(this->regs.x++, this->regs.B.a);
629
+						this->opcode_cycle = 0;
630
+						break;
631
+				}
632
+				break;
633
+
634
+			case 0xc4:
635
+				switch (++this->opcode_cycle)
636
+				{
637
+					case 1:
638
+						this->dp = op_readpc();
639
+						break;
640
+					case 2:
641
+						op_readdp(this->dp);
642
+						break;
643
+					case 3:
644
+						op_writedp(this->dp, this->regs.B.a);
645
+						this->opcode_cycle = 0;
646
+						break;
647
+				}
648
+				break;
649
+
650
+			case 0xd8:
651
+				switch (++this->opcode_cycle)
652
+				{
653
+					case 1:
654
+						this->dp = op_readpc();
655
+						break;
656
+					case 2:
657
+						op_readdp(this->dp);
658
+						break;
659
+					case 3:
660
+						op_writedp(this->dp, this->regs.x);
661
+						this->opcode_cycle = 0;
662
+						break;
663
+				}
664
+				break;
665
+
666
+			case 0xcb:
667
+				switch (++this->opcode_cycle)
668
+				{
669
+					case 1:
670
+						this->dp = op_readpc();
671
+						break;
672
+					case 2:
673
+						op_readdp(this->dp);
674
+						break;
675
+					case 3:
676
+						op_writedp(this->dp, this->regs.B.y);
677
+						this->opcode_cycle = 0;
678
+						break;
679
+				}
680
+				break;
681
+
682
+			case 0xd4:
683
+				switch (++this->opcode_cycle)
684
+				{
685
+					case 1:
686
+						this->dp = op_readpc();
687
+						this->op_io();
688
+						this->dp += this->regs.x;
689
+						break;
690
+					case 2:
691
+						op_readdp(this->dp);
692
+						break;
693
+					case 3:
694
+						op_writedp(this->dp, this->regs.B.a);
695
+						this->opcode_cycle = 0;
696
+						break;
697
+				}
698
+				break;
699
+
700
+			case 0xd9:
701
+				switch (++this->opcode_cycle)
702
+				{
703
+					case 1:
704
+						this->dp = op_readpc();
705
+						this->op_io();
706
+						this->dp += this->regs.B.y;
707
+						break;
708
+					case 2:
709
+						op_readdp(this->dp);
710
+						break;
711
+					case 3:
712
+						op_writedp(this->dp, this->regs.x);
713
+						this->opcode_cycle = 0;
714
+						break;
715
+				}
716
+				break;
717
+
718
+			case 0xdb:
719
+				switch (++this->opcode_cycle)
720
+				{
721
+					case 1:
722
+						this->dp = op_readpc();
723
+						this->op_io();
724
+						this->dp += this->regs.x;
725
+						break;
726
+					case 2:
727
+						op_readdp(this->dp);
728
+						break;
729
+					case 3:
730
+						op_writedp(this->dp, this->regs.B.y);
731
+						this->opcode_cycle = 0;
732
+						break;
733
+				}
734
+				break;
735
+
736
+			case 0xc5:
737
+				switch (++this->opcode_cycle)
738
+				{
739
+					case 1:
740
+						this->dp = op_readpc();
741
+						break;
742
+					case 2:
743
+						this->dp |= op_readpc() << 8;
744
+						break;
745
+					case 3:
746
+						op_readaddr(this->dp);
747
+						break;
748
+					case 4:
749
+						op_writeaddr(this->dp, this->regs.B.a);
750
+						this->opcode_cycle = 0;
751
+						break;
752
+				}
753
+				break;
754
+
755
+			case 0xc9:
756
+				switch (++this->opcode_cycle)
757
+				{
758
+					case 1:
759
+						this->dp = op_readpc();
760
+						break;
761
+					case 2:
762
+						this->dp |= op_readpc() << 8;
763
+						break;
764
+					case 3:
765
+						op_readaddr(this->dp);
766
+						break;
767
+					case 4:
768
+						op_writeaddr(this->dp, this->regs.x);
769
+						this->opcode_cycle = 0;
770
+						break;
771
+				}
772
+				break;
773
+
774
+			case 0xcc:
775
+				switch (++this->opcode_cycle)
776
+				{
777
+					case 1:
778
+						this->dp = op_readpc();
779
+						break;
780
+					case 2:
781
+						this->dp |= op_readpc() << 8;
782
+						break;
783
+					case 3:
784
+						op_readaddr(this->dp);
785
+						break;
786
+					case 4:
787
+						op_writeaddr(this->dp, this->regs.B.y);
788
+						this->opcode_cycle = 0;
789
+						break;
790
+				}
791
+				break;
792
+
793
+			case 0xd5:
794
+				switch (++this->opcode_cycle)
795
+				{
796
+					case 1:
797
+						this->dp = op_readpc();
798
+						this->dp |= op_readpc() << 8;
799
+						this->op_io();
800
+						this->dp += this->regs.x;
801
+						break;
802
+					case 2:
803
+						op_readaddr(this->dp);
804
+						break;
805
+					case 3:
806
+						op_writeaddr(this->dp, this->regs.B.a);
807
+						this->opcode_cycle = 0;
808
+						break;
809
+				}
810
+				break;
811
+
812
+			case 0xd6:
813
+				switch (++this->opcode_cycle)
814
+				{
815
+					case 1:
816
+						this->dp = op_readpc();
817
+						this->dp |= op_readpc() << 8;
818
+						this->op_io();
819
+						this->dp += this->regs.B.y;
820
+						break;
821
+					case 2:
822
+						op_readaddr(this->dp);
823
+						break;
824
+					case 3:
825
+						op_writeaddr(this->dp, this->regs.B.a);
826
+						this->opcode_cycle = 0;
827
+						break;
828
+				}
829
+				break;
830
+
831
+			case 0xc7:
832
+				switch (++this->opcode_cycle)
833
+				{
834
+					case 1:
835
+						this->sp = op_readpc();
836
+						this->op_io();
837
+						this->sp += this->regs.x;
838
+						break;
839
+					case 2:
840
+						this->dp = op_readdp(this->sp);
841
+						break;
842
+					case 3:
843
+						this->dp |= op_readdp(this->sp + 1) << 8;
844
+						break;
845
+					case 4:
846
+						op_readaddr(this->dp);
847
+						break;
848
+					case 5:
849
+						op_writeaddr(this->dp, this->regs.B.a);
850
+						this->opcode_cycle = 0;
851
+						break;
852
+				}
853
+				break;
854
+
855
+			case 0xd7:
856
+				switch (++this->opcode_cycle)
857
+				{
858
+					case 1:
859
+						this->sp = op_readpc();
860
+						break;
861
+					case 2:
862
+						this->dp = op_readdp(this->sp);
863
+						break;
864
+					case 3:
865
+						this->dp |= op_readdp(this->sp + 1) << 8;
866
+						this->op_io();
867
+						this->dp += this->regs.B.y;
868
+						break;
869
+					case 4:
870
+						op_readaddr(this->dp);
871
+						break;
872
+					case 5:
873
+						op_writeaddr(this->dp, this->regs.B.a);
874
+						this->opcode_cycle = 0;
875
+						break;
876
+				}
877
+				break;
878
+
879
+			case 0xba:
880
+				switch (++this->opcode_cycle)
881
+				{
882
+					case 1:
883
+						this->sp = op_readpc();
884
+						break;
885
+					case 2:
886
+						this->regs.B.a = op_readdp(this->sp);
887
+						this->op_io();
888
+						break;
889
+					case 3:
890
+						this->regs.B.y = op_readdp(this->sp + 1);
891
+						this->regs.p.n = !!(this->regs.ya & 0x8000);
892
+						this->regs.p.z = !this->regs.ya;
893
+						this->opcode_cycle = 0;
894
+						break;
895
+				}
896
+				break;
897
+
898
+			case 0xda:
899
+				switch (++this->opcode_cycle)
900
+				{
901
+					case 1:
902
+						this->dp = op_readpc();
903
+						break;
904
+					case 2:
905
+						op_readdp(this->dp);
906
+						break;
907
+					case 3:
908
+						op_writedp(this->dp, this->regs.B.a);
909
+						break;
910
+					case 4:
911
+						op_writedp(this->dp + 1, this->regs.B.y);
912
+						this->opcode_cycle = 0;
913
+						break;
914
+				}
915
+				break;
916
+
917
+			case 0xaa:
918
+				switch (++this->opcode_cycle)
919
+				{
920
+					case 1:
921
+						this->sp = op_readpc();
922
+						this->sp |= op_readpc() << 8;
923
+						break;
924
+					case 2:
925
+						this->bit = this->sp >> 13;
926
+						this->sp &= 0x1fff;
927
+						this->rd = op_readaddr(this->sp);
928
+						this->regs.p.c = !!(this->rd & (1 << this->bit));
929
+						this->opcode_cycle = 0;
930
+						break;
931
+				}
932
+				break;
933
+
934
+			case 0xca:
935
+				switch (++this->opcode_cycle)
936
+				{
937
+					case 1:
938
+						this->dp = op_readpc();
939
+						this->dp |= op_readpc() << 8;
940
+						break;
941
+					case 2:
942
+						this->bit = this->dp >> 13;
943
+						this->dp &= 0x1fff;
944
+						this->rd = op_readaddr(this->dp);
945
+						if (this->regs.p.c)
946
+							this->rd |= (1 << this->bit);
947
+						else
948
+							this->rd &= ~(1 << this->bit);
949
+						this->op_io();
950
+						break;
951
+					case 3:
952
+						op_writeaddr(this->dp, this->rd);
953
+						this->opcode_cycle = 0;
954
+						break;
955
+				}
956
+				break;
957
+
958
+			// End of core/oppseudo_mov.cpp
959
+
960
+			// Start of core/oppseudo_pc.cpp
961
+
962
+			case 0x2f:
963
+				this->rd = op_readpc();
964
+				this->op_io(2);
965
+				this->regs.pc += static_cast<int8_t>(this->rd);
966
+				break;
967
+
968
+			case 0xf0:
969
+				this->rd = op_readpc();
970
+				if (!this->regs.p.z)
971
+					break;
972
+				this->op_io(2);
973
+				this->regs.pc += static_cast<int8_t>(this->rd);
974
+				break;
975
+
976
+			case 0xd0:
977
+				this->rd = op_readpc();
978
+				if (this->regs.p.z)
979
+					break;
980
+				this->op_io(2);
981
+				this->regs.pc += static_cast<int8_t>(this->rd);
982
+				break;
983
+
984
+			case 0xb0:
985
+				this->rd = op_readpc();
986
+				if (!this->regs.p.c)
987
+					break;
988
+				this->op_io(2);
989
+				this->regs.pc += static_cast<int8_t>(this->rd);
990
+				break;
991
+
992
+			case 0x90:
993
+				this->rd = op_readpc();
994
+				if (this->regs.p.c)
995
+					break;
996
+				this->op_io(2);
997
+				this->regs.pc += static_cast<int8_t>(this->rd);
998
+				break;
999
+
1000
+			case 0x70:
1001
+				this->rd = op_readpc();
1002
+				if (!this->regs.p.v)
1003
+					break;
1004
+				this->op_io(2);
1005
+				this->regs.pc += static_cast<int8_t>(this->rd);
1006
+				break;
1007
+
1008
+			case 0x50:
1009
+				this->rd = op_readpc();
1010
+				if (this->regs.p.v)
1011
+					break;
1012
+				this->op_io(2);
1013
+				this->regs.pc += static_cast<int8_t>(this->rd);
1014
+				break;
1015
+
1016
+			case 0x30:
1017
+				this->rd = op_readpc();
1018
+				if (!this->regs.p.n)
1019
+					break;
1020
+				this->op_io(2);
1021
+				this->regs.pc += static_cast<int8_t>(this->rd);
1022
+				break;
1023
+
1024
+			case 0x10:
1025
+				this->rd = op_readpc();
1026
+				if (this->regs.p.n)
1027
+					break;
1028
+				this->op_io(2);
1029
+				this->regs.pc += static_cast<int8_t>(rd);
1030
+				break;
1031
+
1032
+			case 0x03:
1033
+			case 0x23:
1034
+			case 0x43:
1035
+			case 0x63:
1036
+			case 0x83:
1037
+			case 0xa3:
1038
+			case 0xc3:
1039
+			case 0xe3:
1040
+			{
1041
+				this->dp = op_readpc();
1042
+				this->sp = op_readdp(this->dp);
1043
+				this->rd = op_readpc();
1044
+				this->op_io();
1045
+				uint8_t mask = 1 << ((opcode_number & 0xE0) >> 5);
1046
+				if ((sp & mask) != mask)
1047
+					break;
1048
+				this->op_io(2);
1049
+				this->regs.pc += static_cast<int8_t>(this->rd);
1050
+				break;
1051
+			}
1052
+
1053
+			case 0x13:
1054
+			case 0x33:
1055
+			case 0x53:
1056
+			case 0x73:
1057
+			case 0x93:
1058
+			case 0xb3:
1059
+			case 0xd3:
1060
+			case 0xf3:
1061
+			{
1062
+				this->dp = op_readpc();
1063
+				this->sp = op_readdp(this->dp);
1064
+				this->rd = op_readpc();
1065
+				this->op_io();
1066
+				uint8_t mask = 1 << ((opcode_number & 0xE0) >> 5);
1067
+				if ((sp & mask) == mask)
1068
+					break;
1069
+				this->op_io(2);
1070
+				this->regs.pc += static_cast<int8_t>(this->rd);
1071
+				break;
1072
+			}
1073
+
1074
+			case 0x2e:
1075
+				this->dp = op_readpc();
1076
+				this->sp = op_readdp(this->dp);
1077
+				this->rd = op_readpc();
1078
+				this->op_io();
1079
+				if (this->regs.B.a == this->sp)
1080
+					break;
1081
+				this->op_io(2);
1082
+				this->regs.pc += static_cast<int8_t>(this->rd);
1083
+				break;
1084
+
1085
+			case 0xde:
1086
+				this->dp = op_readpc();
1087
+				this->op_io();
1088
+				this->sp = op_readdp(this->dp + this->regs.x);
1089
+				this->rd = op_readpc();
1090
+				this->op_io();
1091
+				if (this->regs.B.a == this->sp)
1092
+					break;
1093
+				this->op_io(2);
1094
+				this->regs.pc += static_cast<int8_t>(this->rd);
1095
+				break;
1096
+
1097
+			case 0x6e:
1098
+				this->dp = op_readpc();
1099
+				this->wr = op_readdp(this->dp);
1100
+				op_writedp(this->dp, --this->wr);
1101
+				this->rd = op_readpc();
1102
+				if (!this->wr)
1103
+					break;
1104
+				this->op_io(2);
1105
+				this->regs.pc += static_cast<int8_t>(this->rd);
1106
+				break;
1107
+
1108
+			case 0xfe:
1109
+				this->rd = op_readpc();
1110
+				this->op_io();
1111
+				--this->regs.B.y;
1112
+				this->op_io();
1113
+				if (!this->regs.B.y)
1114
+					break;
1115
+				this->op_io(2);
1116
+				this->regs.pc += static_cast<int8_t>(this->rd);
1117
+				break;
1118
+
1119
+			case 0x5f:
1120
+				this->rd = op_readpc();
1121
+				this->rd |= op_readpc() << 8;
1122
+				this->regs.pc = this->rd;
1123
+				break;
1124
+
1125
+			case 0x1f:
1126
+				this->dp = op_readpc();
1127
+				this->dp |= op_readpc() << 8;
1128
+				this->op_io();
1129
+				this->dp += this->regs.x;
1130
+				this->rd = op_readaddr(this->dp);
1131
+				this->rd |= op_readaddr(this->dp + 1) << 8;
1132
+				this->regs.pc = this->rd;
1133
+				break;
1134
+
1135
+			case 0x3f:
1136
+				this->rd = op_readpc();
1137
+				this->rd |= op_readpc() << 8;
1138
+				this->op_io(3);
1139
+				this->op_writestack(this->regs.pc >> 8);
1140
+				this->op_writestack(this->regs.pc);
1141
+				this->regs.pc = this->rd;
1142
+				break;
1143
+
1144
+			case 0x4f:
1145
+				this->rd = op_readpc();
1146
+				this->op_io(2);
1147
+				this->op_writestack(this->regs.pc >> 8);
1148
+				this->op_writestack(this->regs.pc);
1149
+				this->regs.pc = 0xff00 | this->rd;
1150
+				break;
1151
+
1152
+			case 0x01:
1153
+			case 0x11:
1154
+			case 0x21:
1155
+			case 0x31:
1156
+			case 0x41:
1157
+			case 0x51:
1158
+			case 0x61:
1159
+			case 0x71:
1160
+			case 0x81:
1161
+			case 0x91:
1162
+			case 0xa1:
1163
+			case 0xb1:
1164
+			case 0xc1:
1165
+			case 0xd1:
1166
+			case 0xe1:
1167
+			case 0xf1:
1168
+				this->dp = 0xffde - (((opcode_number & 0xF0) >> 4) << 1);
1169
+				this->rd = op_readaddr(this->dp);
1170
+				this->rd |= op_readaddr(this->dp + 1) << 8;
1171
+				this->op_io(3);
1172
+				this->op_writestack(this->regs.pc >> 8);
1173
+				this->op_writestack(this->regs.pc);
1174
+				this->regs.pc = this->rd;
1175
+				break;
1176
+
1177
+			case 0x0f:
1178
+				this->rd = op_readaddr(0xffde);
1179
+				this->rd |= op_readaddr(0xffdf) << 8;
1180
+				this->op_io(2);
1181
+				this->op_writestack(this->regs.pc >> 8);
1182
+				this->op_writestack(this->regs.pc);
1183
+				this->op_writestack(this->regs.p);
1184
+				this->regs.pc = this->rd;
1185
+				this->regs.p.b = 1;
1186
+				this->regs.p.i = 0;
1187
+				break;
1188
+
1189
+			case 0x6f:
1190
+				this->rd = this->op_readstack();
1191
+				this->rd |= this->op_readstack() << 8;
1192
+				this->op_io(2);
1193
+				this->regs.pc = this->rd;
1194
+				break;
1195
+
1196
+			case 0x7f:
1197
+				this->regs.p = this->op_readstack();
1198
+				this->rd = this->op_readstack();
1199
+				this->rd |= this->op_readstack() << 8;
1200
+				this->op_io(2);
1201
+				this->regs.pc = this->rd;
1202
+				break;
1203
+
1204
+			// End of core/oppseudo_pc.cpp
1205
+
1206
+			// Start of core/oppseudo_read.cpp
1207
+
1208
+			case 0x88:
1209
+				this->rd = op_readpc();
1210
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1211
+				break;
1212
+
1213
+			case 0x28:
1214
+				this->rd = op_readpc();
1215
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1216
+				break;
1217
+
1218
+			case 0x68:
1219
+				this->rd = op_readpc();
1220
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1221
+				break;
1222
+
1223
+			case 0xc8:
1224
+				this->rd = op_readpc();
1225
+				this->regs.x = this->op_cmp(this->regs.x, this->rd);
1226
+				break;
1227
+
1228
+			case 0xad:
1229
+				this->rd = op_readpc();
1230
+				this->regs.B.y = this->op_cmp(this->regs.B.y, this->rd);
1231
+				break;
1232
+
1233
+			case 0x48:
1234
+				this->rd = op_readpc();
1235
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1236
+				break;
1237
+
1238
+			case 0x08:
1239
+				this->rd = op_readpc();
1240
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1241
+				break;
1242
+
1243
+			case 0xa8:
1244
+				this->rd = op_readpc();
1245
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1246
+				break;
1247
+
1248
+			case 0x86:
1249
+				this->op_io();
1250
+				this->rd = op_readdp(this->regs.x);
1251
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1252
+				break;
1253
+
1254
+			case 0x26:
1255
+				this->op_io();
1256
+				this->rd = op_readdp(this->regs.x);
1257
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1258
+				break;
1259
+
1260
+			case 0x66:
1261
+				this->op_io();
1262
+				this->rd = op_readdp(this->regs.x);
1263
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1264
+				break;
1265
+
1266
+			case 0x46:
1267
+				this->op_io();
1268
+				this->rd = op_readdp(this->regs.x);
1269
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1270
+				break;
1271
+
1272
+			case 0x06:
1273
+				this->op_io();
1274
+				this->rd = op_readdp(this->regs.x);
1275
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1276
+				break;
1277
+
1278
+			case 0xa6:
1279
+				this->op_io();
1280
+				this->rd = op_readdp(this->regs.x);
1281
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1282
+				break;
1283
+
1284
+			case 0x84:
1285
+				this->dp = op_readpc();
1286
+				this->rd = op_readdp(this->dp);
1287
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1288
+				break;
1289
+
1290
+			case 0x24:
1291
+				this->dp = op_readpc();
1292
+				this->rd = op_readdp(this->dp);
1293
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1294
+				break;
1295
+
1296
+			case 0x64:
1297
+				this->dp = op_readpc();
1298
+				this->rd = op_readdp(this->dp);
1299
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1300
+				break;
1301
+
1302
+			case 0x3e:
1303
+				this->dp = op_readpc();
1304
+				this->rd = op_readdp(this->dp);
1305
+				this->regs.x = this->op_cmp(this->regs.x, this->rd);
1306
+				break;
1307
+
1308
+			case 0x7e:
1309
+				switch (++this->opcode_cycle)
1310
+				{
1311
+					case 1:
1312
+						this->dp = op_readpc();
1313
+						break;
1314
+					case 2:
1315
+						this->rd = op_readdp(this->dp);
1316
+						this->regs.B.y = this->op_cmp(this->regs.B.y, this->rd);
1317
+						this->opcode_cycle = 0;
1318
+						break;
1319
+				}
1320
+				break;
1321
+
1322
+			case 0x44:
1323
+				this->dp = op_readpc();
1324
+				this->rd = op_readdp(dp);
1325
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1326
+				break;
1327
+
1328
+			case 0x04:
1329
+				this->dp = op_readpc();
1330
+				this->rd = op_readdp(this->dp);
1331
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1332
+				break;
1333
+
1334
+			case 0xa4:
1335
+				this->dp = op_readpc();
1336
+				this->rd = op_readdp(this->dp);
1337
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1338
+				break;
1339
+
1340
+			case 0x94:
1341
+				this->dp = op_readpc();
1342
+				this->op_io();
1343
+				this->rd = op_readdp(this->dp + this->regs.x);
1344
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1345
+				break;
1346
+
1347
+			case 0x34:
1348
+				this->dp = op_readpc();
1349
+				this->op_io();
1350
+				this->rd = op_readdp(this->dp + this->regs.x);
1351
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1352
+				break;
1353
+
1354
+			case 0x74:
1355
+				this->dp = op_readpc();
1356
+				this->op_io();
1357
+				this->rd = op_readdp(this->dp + this->regs.x);
1358
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1359
+				break;
1360
+
1361
+			case 0x54:
1362
+				this->dp = op_readpc();
1363
+				this->op_io();
1364
+				this->rd = op_readdp(this->dp + this->regs.x);
1365
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1366
+				break;
1367
+
1368
+			case 0x14:
1369
+				this->dp = op_readpc();
1370
+				this->op_io();
1371
+				this->rd = op_readdp(this->dp + this->regs.x);
1372
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1373
+				break;
1374
+
1375
+			case 0xb4:
1376
+				this->dp = op_readpc();
1377
+				this->op_io();
1378
+				this->rd = op_readdp(this->dp + this->regs.x);
1379
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1380
+				break;
1381
+
1382
+			case 0x85:
1383
+				this->dp = op_readpc();
1384
+				this->dp |= op_readpc() << 8;
1385
+				this->rd = op_readaddr(this->dp);
1386
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1387
+				break;
1388
+
1389
+			case 0x25:
1390
+				this->dp = op_readpc();
1391
+				this->dp |= op_readpc() << 8;
1392
+				this->rd = op_readaddr(this->dp);
1393
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1394
+				break;
1395
+
1396
+			case 0x65:
1397
+				this->dp = op_readpc();
1398
+				this->dp |= op_readpc() << 8;
1399
+				this->rd = op_readaddr(this->dp);
1400
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1401
+				break;
1402
+
1403
+			case 0x1e:
1404
+				this->dp = op_readpc();
1405
+				this->dp |= op_readpc() << 8;
1406
+				this->rd = op_readaddr(this->dp);
1407
+				this->regs.x = this->op_cmp(this->regs.x, this->rd);
1408
+				break;
1409
+
1410
+			case 0x5e:
1411
+				this->dp = op_readpc();
1412
+				this->dp |= op_readpc() << 8;
1413
+				this->rd = op_readaddr(this->dp);
1414
+				this->regs.B.y = this->op_cmp(this->regs.B.y, this->rd);
1415
+				break;
1416
+
1417
+			case 0x45:
1418
+				this->dp = op_readpc();
1419
+				this->dp |= op_readpc() << 8;
1420
+				this->rd = op_readaddr(this->dp);
1421
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1422
+				break;
1423
+
1424
+			case 0x05:
1425
+				this->dp = op_readpc();
1426
+				this->dp |= op_readpc() << 8;
1427
+				this->rd = op_readaddr(this->dp);
1428
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1429
+				break;
1430
+
1431
+			case 0xa5:
1432
+				this->dp = op_readpc();
1433
+				this->dp |= op_readpc() << 8;
1434
+				this->rd = op_readaddr(this->dp);
1435
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1436
+				break;
1437
+
1438
+			case 0x95:
1439
+				this->dp = op_readpc();
1440
+				this->dp |= op_readpc() << 8;
1441
+				this->op_io();
1442
+				this->rd = op_readaddr(this->dp + this->regs.x);
1443
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1444
+				break;
1445
+
1446
+			case 0x96:
1447
+				this->dp = op_readpc();
1448
+				this->dp |= op_readpc() << 8;
1449
+				this->op_io();
1450
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1451
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1452
+				break;
1453
+
1454
+			case 0x35:
1455
+				this->dp = op_readpc();
1456
+				this->dp |= op_readpc() << 8;
1457
+				this->op_io();
1458
+				this->rd = op_readaddr(this->dp + this->regs.x);
1459
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1460
+				break;
1461
+
1462
+			case 0x36:
1463
+				this->dp = op_readpc();
1464
+				this->dp |= op_readpc() << 8;
1465
+				this->op_io();
1466
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1467
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1468
+				break;
1469
+
1470
+			case 0x75:
1471
+				this->dp = op_readpc();
1472
+				this->dp |= op_readpc() << 8;
1473
+				this->op_io();
1474
+				this->rd = op_readaddr(this->dp + this->regs.x);
1475
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1476
+				break;
1477
+
1478
+			case 0x76:
1479
+				this->dp = op_readpc();
1480
+				this->dp |= op_readpc() << 8;
1481
+				this->op_io();
1482
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1483
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1484
+				break;
1485
+
1486
+			case 0x55:
1487
+				this->dp = op_readpc();
1488
+				this->dp |= op_readpc() << 8;
1489
+				this->op_io();
1490
+				this->rd = op_readaddr(this->dp + this->regs.x);
1491
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1492
+				break;
1493
+
1494
+			case 0x56:
1495
+				this->dp = op_readpc();
1496
+				this->dp |= op_readpc() << 8;
1497
+				this->op_io();
1498
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1499
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1500
+				break;
1501
+
1502
+			case 0x15:
1503
+				this->dp = op_readpc();
1504
+				this->dp |= op_readpc() << 8;
1505
+				this->op_io();
1506
+				this->rd = op_readaddr(this->dp + this->regs.x);
1507
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1508
+				break;
1509
+
1510
+			case 0x16:
1511
+				this->dp = op_readpc();
1512
+				this->dp |= op_readpc() << 8;
1513
+				this->op_io();
1514
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1515
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1516
+				break;
1517
+
1518
+			case 0xb5:
1519
+				this->dp = op_readpc();
1520
+				this->dp |= op_readpc() << 8;
1521
+				this->op_io();
1522
+				this->rd = op_readaddr(this->dp + this->regs.x);
1523
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1524
+				break;
1525
+
1526
+			case 0xb6:
1527
+				this->dp = op_readpc();
1528
+				this->dp |= op_readpc() << 8;
1529
+				this->op_io();
1530
+				this->rd = op_readaddr(this->dp + this->regs.B.y);
1531
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1532
+				break;
1533
+
1534
+			case 0x87:
1535
+				this->dp = op_readpc() + this->regs.x;
1536
+				this->op_io();
1537
+				this->sp = op_readdp(this->dp);
1538
+				this->sp |= op_readdp(this->dp + 1) << 8;
1539
+				this->rd = op_readaddr(this->sp);
1540
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1541
+				break;
1542
+
1543
+			case 0x27:
1544
+				this->dp = op_readpc() + this->regs.x;
1545
+				this->op_io();
1546
+				this->sp = op_readdp(this->dp);
1547
+				this->sp |= op_readdp(this->dp + 1) << 8;
1548
+				this->rd = op_readaddr(this->sp);
1549
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1550
+				break;
1551
+
1552
+			case 0x67:
1553
+				this->dp = op_readpc() + this->regs.x;
1554
+				this->op_io();
1555
+				this->sp = op_readdp(this->dp);
1556
+				this->sp |= op_readdp(this->dp + 1) << 8;
1557
+				this->rd = op_readaddr(this->sp);
1558
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1559
+				break;
1560
+
1561
+			case 0x47:
1562
+				this->dp = op_readpc() + this->regs.x;
1563
+				this->op_io();
1564
+				this->sp = op_readdp(this->dp);
1565
+				this->sp |= op_readdp(this->dp + 1) << 8;
1566
+				this->rd = op_readaddr(this->sp);
1567
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1568
+				break;
1569
+
1570
+			case 0x07:
1571
+				this->dp = op_readpc() + this->regs.x;
1572
+				this->op_io();
1573
+				this->sp = op_readdp(this->dp);
1574
+				this->sp |= op_readdp(this->dp + 1) << 8;
1575
+				this->rd = op_readaddr(this->sp);
1576
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1577
+				break;
1578
+
1579
+			case 0xa7:
1580
+				this->dp = op_readpc() + this->regs.x;
1581
+				this->op_io();
1582
+				this->sp = op_readdp(this->dp);
1583
+				this->sp |= op_readdp(this->dp + 1) << 8;
1584
+				this->rd = op_readaddr(this->sp);
1585
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1586
+				break;
1587
+
1588
+			case 0x97:
1589
+				this->dp = op_readpc();
1590
+				this->op_io();
1591
+				this->sp = op_readdp(this->dp);
1592
+				this->sp |= op_readdp(this->dp + 1) << 8;
1593
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1594
+				this->regs.B.a = this->op_adc(this->regs.B.a, this->rd);
1595
+				break;
1596
+
1597
+			case 0x37:
1598
+				this->dp = op_readpc();
1599
+				this->op_io();
1600
+				this->sp = op_readdp(this->dp);
1601
+				this->sp |= op_readdp(this->dp + 1) << 8;
1602
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1603
+				this->regs.B.a = this->op_and(this->regs.B.a, this->rd);
1604
+				break;
1605
+
1606
+			case 0x77:
1607
+				this->dp = op_readpc();
1608
+				this->op_io();
1609
+				this->sp = op_readdp(this->dp);
1610
+				this->sp |= op_readdp(this->dp + 1) << 8;
1611
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1612
+				this->regs.B.a = this->op_cmp(this->regs.B.a, this->rd);
1613
+				break;
1614
+
1615
+			case 0x57:
1616
+				this->dp = op_readpc();
1617
+				this->op_io();
1618
+				this->sp = op_readdp(this->dp);
1619
+				this->sp |= op_readdp(this->dp + 1) << 8;
1620
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1621
+				this->regs.B.a = this->op_eor(this->regs.B.a, this->rd);
1622
+				break;
1623
+
1624
+			case 0x17:
1625
+				this->dp = op_readpc();
1626
+				this->op_io();
1627
+				this->sp = op_readdp(this->dp);
1628
+				this->sp |= op_readdp(this->dp + 1) << 8;
1629
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1630
+				this->regs.B.a = this->op_or(this->regs.B.a, this->rd);
1631
+				break;
1632
+
1633
+			case 0xb7:
1634
+				this->dp = op_readpc();
1635
+				this->op_io();
1636
+				this->sp = op_readdp(this->dp);
1637
+				this->sp |= op_readdp(this->dp + 1) << 8;
1638
+				this->rd = op_readaddr(this->sp + this->regs.B.y);
1639
+				this->regs.B.a = this->op_sbc(this->regs.B.a, this->rd);
1640
+				break;
1641
+
1642
+			case 0x99:
1643
+				this->op_io();
1644
+				this->rd = op_readdp(this->regs.B.y);
1645
+				this->wr = op_readdp(this->regs.x);
1646
+				this->wr = this->op_adc(this->wr, this->rd);
1647
+				op_writedp(this->regs.x, this->wr);
1648
+				break;
1649
+
1650
+			case 0x39:
1651
+				this->op_io();
1652
+				this->rd = op_readdp(this->regs.B.y);
1653
+				this->wr = op_readdp(this->regs.x);
1654
+				this->wr = this->op_and(this->wr, this->rd);
1655
+				op_writedp(this->regs.x, this->wr);
1656
+				break;
1657
+
1658
+			case 0x79:
1659
+				this->op_io();
1660
+				this->rd = op_readdp(this->regs.B.y);
1661
+				this->wr = op_readdp(this->regs.x);
1662
+				this->wr = this->op_cmp(wr, rd);
1663
+				this->op_io();
1664
+				break;
1665
+
1666
+			case 0x59:
1667
+				this->op_io();
1668
+				this->rd = op_readdp(this->regs.B.y);
1669
+				this->wr = op_readdp(this->regs.x);
1670
+				this->wr = this->op_eor(this->wr, this->rd);
1671
+				op_writedp(this->regs.x, this->wr);
1672
+				break;
1673
+
1674
+			case 0x19:
1675
+				this->op_io();
1676
+				this->rd = op_readdp(this->regs.B.y);
1677
+				this->wr = op_readdp(this->regs.x);
1678
+				this->wr = this->op_or(this->wr, this->rd);
1679
+				op_writedp(this->regs.x, this->wr);
1680
+				break;
1681
+
1682
+			case 0xb9:
1683
+				this->op_io();
1684
+				this->rd = op_readdp(this->regs.B.y);
1685
+				this->wr = op_readdp(this->regs.x);
1686
+				this->wr = this->op_sbc(this->wr, this->rd);
1687
+				op_writedp(this->regs.x, this->wr);
1688
+				break;
1689
+
1690
+			case 0x89:
1691
+				this->sp = op_readpc();
1692
+				this->rd = op_readdp(this->sp);
1693
+				this->dp = op_readpc();
1694
+				this->wr = op_readdp(this->dp);
1695
+				this->wr = this->op_adc(this->wr, this->rd);
1696
+				op_writedp(this->dp, this->wr);
1697
+				break;
1698
+
1699
+			case 0x29:
1700
+				this->sp = op_readpc();
1701
+				this->rd = op_readdp(this->sp);
1702
+				this->dp = op_readpc();
1703
+				this->wr = op_readdp(this->dp);
1704
+				this->wr = this->op_and(this->wr, this->rd);
1705
+				op_writedp(this->dp, this->wr);
1706
+				break;
1707
+
1708
+			case 0x69:
1709
+				this->sp = op_readpc();
1710
+				this->rd = op_readdp(this->sp);
1711
+				this->dp = op_readpc();
1712
+				this->wr = op_readdp(this->dp);
1713
+				this->wr = this->op_cmp(this->wr, this->rd);
1714
+				this->op_io();
1715
+				break;
1716
+
1717
+			case 0x49:
1718
+				this->sp = op_readpc();
1719
+				this->rd = op_readdp(this->sp);
1720
+				this->dp = op_readpc();
1721
+				this->wr = op_readdp(this->dp);
1722
+				this->wr = this->op_eor(this->wr, this->rd);
1723
+				op_writedp(this->dp, this->wr);
1724
+				break;
1725
+
1726
+			case 0x09:
1727
+				this->sp = op_readpc();
1728
+				this->rd = op_readdp(this->sp);
1729
+				this->dp = op_readpc();
1730
+				this->wr = op_readdp(this->dp);
1731
+				this->wr = this->op_or(this->wr, this->rd);
1732
+				op_writedp(this->dp, this->wr);
1733
+				break;
1734
+
1735
+			case 0xa9:
1736
+				this->sp = op_readpc();
1737
+				this->rd = op_readdp(this->sp);
1738
+				this->dp = op_readpc();
1739
+				this->wr = op_readdp(this->dp);
1740
+				this->wr = this->op_sbc(this->wr, this->rd);
1741
+				op_writedp(this->dp, this->wr);
1742
+				break;
1743
+
1744
+			case 0x98:
1745
+				this->rd = op_readpc();
1746
+				this->dp = op_readpc();
1747
+				this->wr = op_readdp(this->dp);
1748
+				this->wr = this->op_adc(this->wr, this->rd);
1749
+				op_writedp(this->dp, this->wr);
1750
+				break;
1751
+
1752
+			case 0x38:
1753
+				this->rd = op_readpc();
1754
+				this->dp = op_readpc();
1755
+				this->wr = op_readdp(this->dp);
1756
+				this->wr = this->op_and(this->wr, this->rd);
1757
+				op_writedp(this->dp, this->wr);
1758
+				break;
1759
+
1760
+			case 0x78:
1761
+				this->rd = op_readpc();
1762
+				this->dp = op_readpc();
1763
+				this->wr = op_readdp(this->dp);
1764
+				this->wr = this->op_cmp(this->wr, this->rd);
1765
+				this->op_io();
1766
+				break;
1767
+
1768
+			case 0x58:
1769
+				this->rd = op_readpc();
1770
+				this->dp = op_readpc();
1771
+				this->wr = op_readdp(this->dp);
1772
+				this->wr = this->op_eor(this->wr, this->rd);
1773
+				op_writedp(this->dp, this->wr);
1774
+				break;
1775
+
1776
+			case 0x18:
1777
+				this->rd = op_readpc();
1778
+				this->dp = op_readpc();
1779
+				this->wr = op_readdp(this->dp);
1780
+				this->wr = this->op_or(this->wr, this->rd);
1781
+				op_writedp(this->dp, this->wr);
1782
+				break;
1783
+
1784
+			case 0xb8:
1785
+				this->rd = op_readpc();
1786
+				this->dp = op_readpc();
1787
+				this->wr = op_readdp(this->dp);
1788
+				this->wr = this->op_sbc(this->wr, this->rd);
1789
+				op_writedp(this->dp, this->wr);
1790
+				break;
1791
+
1792
+			case 0x7a:
1793
+				this->dp = op_readpc();
1794
+				this->rd = op_readdp(this->dp);
1795
+				this->op_io();
1796
+				this->rd |= op_readdp(this->dp + 1) << 8;
1797
+				this->regs.ya = this->op_addw(this->regs.ya, this->rd);
1798
+				break;
1799
+
1800
+			case 0x9a:
1801
+				this->dp = op_readpc();
1802
+				this->rd = op_readdp(this->dp);
1803
+				this->op_io();
1804
+				this->rd |= op_readdp(this->dp + 1) << 8;
1805
+				this->regs.ya = this->op_subw(this->regs.ya, this->rd);
1806
+				break;
1807
+
1808
+			case 0x5a:
1809
+				this->dp = op_readpc();
1810
+				this->rd = op_readdp(this->dp);
1811
+				this->rd |= op_readdp(this->dp + 1) << 8;
1812
+				this->op_cmpw(this->regs.ya, this->rd);
1813
+				break;
1814
+
1815
+			case 0x4a:
1816
+				this->dp = op_readpc();
1817
+				this->dp |= op_readpc() << 8;
1818
+				this->bit = this->dp >> 13;
1819
+				this->dp &= 0x1fff;
1820
+				this->rd = op_readaddr(this->dp);
1821
+				this->regs.p.c = this->regs.p.c & !!(this->rd & (1 << this->bit));
1822
+				break;
1823
+
1824
+			case 0x6a:
1825
+				this->dp = op_readpc();
1826
+				this->dp |= op_readpc() << 8;
1827
+				this->bit = this->dp >> 13;
1828
+				this->dp &= 0x1fff;
1829
+				this->rd = op_readaddr(this->dp);
1830
+				this->regs.p.c = this->regs.p.c & !(this->rd & (1 << this->bit));
1831
+				break;
1832
+
1833
+			case 0x8a:
1834
+				this->dp = op_readpc();
1835
+				this->dp |= op_readpc() << 8;
1836
+				this->bit = this->dp >> 13;
1837
+				this->dp &= 0x1fff;
1838
+				this->rd = op_readaddr(this->dp);
1839
+				this->op_io();
1840
+				this->regs.p.c = this->regs.p.c ^ !!(this->rd & (1 << this->bit));
1841
+				break;
1842
+
1843
+			case 0xea:
1844
+				this->dp = op_readpc();
1845
+				this->dp |= op_readpc() << 8;
1846
+				this->bit = this->dp >> 13;
1847
+				this->dp &= 0x1fff;
1848
+				this->rd = op_readaddr(this->dp);
1849
+				this->rd ^= 1 << this->bit;
1850
+				op_writeaddr(this->dp, this->rd);
1851
+				break;
1852
+
1853
+			case 0x0a:
1854
+				this->dp = op_readpc();
1855
+				this->dp |= op_readpc() << 8;
1856
+				this->bit = this->dp >> 13;
1857
+				this->dp &= 0x1fff;
1858
+				this->rd = op_readaddr(this->dp);
1859
+				this->op_io();
1860
+				this->regs.p.c = this->regs.p.c | !!(this->rd & (1 << this->bit));
1861
+				break;
1862
+
1863
+			case 0x2a:
1864
+				this->dp = op_readpc();
1865
+				this->dp |= op_readpc() << 8;
1866
+				this->bit = this->dp >> 13;
1867
+				this->dp &= 0x1fff;
1868
+				this->rd = op_readaddr(this->dp);
1869
+				this->op_io();
1870
+				this->regs.p.c = this->regs.p.c | !(this->rd & (1 << this->bit));
1871
+				break;
1872
+
1873
+			// End of core/oppseudo_read.cpp
1874
+
1875
+			// Start of core/oppseudo_rmw.cpp
1876
+
1877
+			case 0xbc:
1878
+				this->op_io();
1879
+				this->regs.B.a = this->op_inc(this->regs.B.a);
1880
+				break;
1881
+
1882
+			case 0x3d:
1883
+				this->op_io();
1884
+				this->regs.x = this->op_inc(this->regs.x);
1885
+				break;
1886
+
1887
+			case 0xfc:
1888
+				this->op_io();
1889
+				this->regs.B.y = this->op_inc(this->regs.B.y);
1890
+				break;
1891
+
1892
+			case 0x9c:
1893
+				this->op_io();
1894
+				this->regs.B.a = this->op_dec(this->regs.B.a);
1895
+				break;
1896
+
1897
+			case 0x1d:
1898
+				this->op_io();
1899
+				this->regs.x = this->op_dec(this->regs.x);
1900
+				break;
1901
+
1902
+			case 0xdc:
1903
+				this->op_io();
1904
+				this->regs.B.y = this->op_dec(this->regs.B.y);
1905
+				break;
1906
+
1907
+			case 0x1c:
1908
+				this->op_io();
1909
+				this->regs.B.a = this->op_asl(this->regs.B.a);
1910
+				break;
1911
+
1912
+			case 0x5c:
1913
+				this->op_io();
1914
+				this->regs.B.a = this->op_lsr(this->regs.B.a);
1915
+				break;
1916
+
1917
+			case 0x3c:
1918
+				this->op_io();
1919
+				this->regs.B.a = this->op_rol(this->regs.B.a);
1920
+				break;
1921
+
1922
+			case 0x7c:
1923
+				this->op_io();
1924
+				this->regs.B.a = this->op_ror(this->regs.B.a);
1925
+				break;
1926
+
1927
+			case 0xab:
1928
+				this->dp = op_readpc();
1929
+				this->rd = op_readdp(this->dp);
1930
+				this->rd = this->op_inc(this->rd);
1931
+				op_writedp(this->dp, this->rd);
1932
+				break;
1933
+
1934
+			case 0x8b:
1935
+				this->dp = op_readpc();
1936
+				this->rd = op_readdp(this->dp);
1937
+				this->rd = this->op_dec(this->rd);
1938
+				op_writedp(this->dp, this->rd);
1939
+				break;
1940
+
1941
+			case 0x0b:
1942
+				this->dp = op_readpc();
1943
+				this->rd = op_readdp(this->dp);
1944
+				this->rd = this->op_asl(this->rd);
1945
+				op_writedp(this->dp, this->rd);
1946
+				break;
1947
+
1948
+			case 0x4b:
1949
+				this->dp = op_readpc();
1950
+				this->rd = op_readdp(this->dp);
1951
+				this->rd = this->op_lsr(this->rd);
1952
+				op_writedp(this->dp, this->rd);
1953
+				break;
1954
+
1955
+			case 0x2b:
1956
+				this->dp = op_readpc();
1957
+				this->rd = op_readdp(this->dp);
1958
+				this->rd = this->op_rol(this->rd);
1959
+				op_writedp(this->dp, this->rd);
1960
+				break;
1961
+
1962
+			case 0x6b:
1963
+				this->dp = op_readpc();
1964
+				this->rd = op_readdp(this->dp);
1965
+				this->rd = this->op_ror(this->rd);
1966
+				op_writedp(this->dp, this->rd);
1967
+				break;
1968
+
1969
+			case 0xbb:
1970
+				this->dp = op_readpc();
1971
+				this->op_io();
1972
+				this->rd = op_readdp(this->dp + this->regs.x);
1973
+				this->rd = this->op_inc(this->rd);
1974
+				op_writedp(this->dp + this->regs.x, this->rd);
1975
+				break;
1976
+
1977
+			case 0x9b:
1978
+				this->dp = op_readpc();
1979
+				this->op_io();
1980
+				this->rd = op_readdp(this->dp + this->regs.x);
1981
+				this->rd = this->op_dec(this->rd);
1982
+				op_writedp(this->dp + this->regs.x, this->rd);
1983
+				break;
1984
+
1985
+			case 0x1b:
1986
+				this->dp = op_readpc();
1987
+				this->op_io();
1988
+				this->rd = op_readdp(this->dp + this->regs.x);
1989
+				this->rd = this->op_asl(this->rd);
1990
+				op_writedp(this->dp + this->regs.x, this->rd);
1991
+				break;
1992
+
1993
+			case 0x5b:
1994
+				this->dp = op_readpc();
1995
+				this->op_io();
1996
+				this->rd = op_readdp(this->dp + this->regs.x);
1997
+				this->rd = this->op_lsr(this->rd);
1998
+				op_writedp(this->dp + this->regs.x, this->rd);
1999
+				break;
2000
+
2001
+			case 0x3b:
2002
+				this->dp = op_readpc();
2003
+				this->op_io();
2004
+				this->rd = op_readdp(this->dp + this->regs.x);
2005
+				this->rd = this->op_rol(this->rd);
2006
+				op_writedp(this->dp + this->regs.x, this->rd);
2007
+				break;
2008
+
2009
+			case 0x7b:
2010
+				this->dp = op_readpc();
2011
+				this->op_io();
2012
+				this->rd = op_readdp(this->dp + this->regs.x);
2013
+				this->rd = this->op_ror(this->rd);
2014
+				op_writedp(this->dp + this->regs.x, this->rd);
2015
+				break;
2016
+
2017
+			case 0xac:
2018
+				this->dp = op_readpc();
2019
+				this->dp |= op_readpc() << 8;
2020
+				this->rd = op_readaddr(this->dp);
2021
+				this->rd = this->op_inc(this->rd);
2022
+				op_writeaddr(this->dp, this->rd);
2023
+				break;
2024
+
2025
+			case 0x8c:
2026
+				this->dp = op_readpc();
2027
+				this->dp |= op_readpc() << 8;
2028
+				this->rd = op_readaddr(this->dp);
2029
+				this->rd = this->op_dec(this->rd);
2030
+				op_writeaddr(this->dp, this->rd);
2031
+				break;
2032
+
2033
+			case 0x0c:
2034
+				this->dp = op_readpc();
2035
+				this->dp |= op_readpc() << 8;
2036
+				this->rd = op_readaddr(this->dp);
2037
+				this->rd = this->op_asl(this->rd);
2038
+				op_writeaddr(this->dp, this->rd);
2039
+				break;
2040
+
2041
+			case 0x4c:
2042
+				this->dp = op_readpc();
2043
+				this->dp |= op_readpc() << 8;
2044
+				this->rd = op_readaddr(this->dp);
2045
+				this->rd = this->op_lsr(this->rd);
2046
+				op_writeaddr(this->dp, this->rd);
2047
+				break;
2048
+
2049
+			case 0x2c:
2050
+				this->dp = op_readpc();
2051
+				this->dp |= op_readpc() << 8;
2052
+				this->rd = op_readaddr(this->dp);
2053
+				this->rd = this->op_rol(this->rd);
2054
+				op_writeaddr(this->dp, this->rd);
2055
+				break;
2056
+
2057
+			case 0x6c:
2058
+				this->dp = op_readpc();
2059
+				this->dp |= op_readpc() << 8;
2060
+				this->rd = op_readaddr(this->dp);
2061
+				this->rd = this->op_ror(this->rd);
2062
+				op_writeaddr(this->dp, this->rd);
2063
+				break;
2064
+
2065
+			case 0x0e:
2066
+				this->dp = op_readpc();
2067
+				this->dp |= op_readpc() << 8;
2068
+				this->rd = op_readaddr(this->dp);
2069
+				this->regs.p.n = !!((this->regs.B.a - this->rd) & 0x80);
2070
+				this->regs.p.z = !(this->regs.B.a - this->rd);
2071
+				op_readaddr(this->dp);
2072
+				op_writeaddr(this->dp, this->rd | this->regs.B.a);
2073
+				break;
2074
+
2075
+			case 0x4e:
2076
+				this->dp = op_readpc();
2077
+				this->dp |= op_readpc() << 8;
2078
+				this->rd = op_readaddr(this->dp);
2079
+				this->regs.p.n = !!((this->regs.B.a - this->rd) & 0x80);
2080
+				this->regs.p.z = !(this->regs.B.a - this->rd);
2081
+				op_readaddr(this->dp);
2082
+				op_writeaddr(this->dp, this->rd & ~this->regs.B.a);
2083
+				break;
2084
+
2085
+			case 0x3a:
2086
+				this->dp = op_readpc();
2087
+				this->rd = op_readdp(this->dp);
2088
+				++this->rd;
2089
+				op_writedp(this->dp++, this->rd);
2090
+				this->rd += op_readdp(this->dp) << 8;
2091
+				op_writedp(this->dp, this->rd >> 8);
2092
+				this->regs.p.n = !!(this->rd & 0x8000);
2093
+				this->regs.p.z = !this->rd;
2094
+				break;
2095
+
2096
+			case 0x1a:
2097
+				this->dp = op_readpc();
2098
+				this->rd = op_readdp(this->dp);
2099
+				--this->rd;
2100
+				op_writedp(this->dp++, this->rd);
2101
+				this->rd += op_readdp(this->dp) << 8;
2102
+				op_writedp(this->dp, this->rd >> 8);
2103
+				this->regs.p.n = !!(this->rd & 0x8000);
2104
+				this->regs.p.z = !this->rd;
2105
+				break;
2106
+
2107
+			// End of core/oppseudo_rmw.cpp
2108
+		}
2109
+	}
2110
+}
0 2111
new file mode 100644
... ...
@@ -0,0 +1,46 @@
1
+#include "smp.hpp"
2
+
3
+namespace SNES
4
+{
5
+	// this is the IPLROM for the S-SMP coprocessor.
6
+	// the S-SMP does not allow writing to the IPLROM.
7
+	// all writes are instead mapped to the extended
8
+	// RAM region, accessible when $f1.d7 is clear.
9
+
10
+	const uint8_t SMP::iplrom[64] =
11
+	{
12
+		/*ffc0*/  0xcd, 0xef,        //mov   x,#$ef
13
+		/*ffc2*/  0xbd,              //mov   sp,x
14
+		/*ffc3*/  0xe8, 0x00,        //mov   a,#$00
15
+		/*ffc5*/  0xc6,              //mov   (x),a
16
+		/*ffc6*/  0x1d,              //dec   x
17
+		/*ffc7*/  0xd0, 0xfc,        //bne   $ffc5
18
+		/*ffc9*/  0x8f, 0xaa, 0xf4,  //mov   $f4,#$aa
19
+		/*ffcc*/  0x8f, 0xbb, 0xf5,  //mov   $f5,#$bb
20
+		/*ffcf*/  0x78, 0xcc, 0xf4,  //cmp   $f4,#$cc
21
+		/*ffd2*/  0xd0, 0xfb,        //bne   $ffcf
22
+		/*ffd4*/  0x2f, 0x19,        //bra   $ffef
23
+		/*ffd6*/  0xeb, 0xf4,        //mov   y,$f4
24
+		/*ffd8*/  0xd0, 0xfc,        //bne   $ffd6
25
+		/*ffda*/  0x7e, 0xf4,        //cmp   y,$f4
26
+		/*ffdc*/  0xd0, 0x0b,        //bne   $ffe9
27
+		/*ffde*/  0xe4, 0xf5,        //mov   a,$f5
28
+		/*ffe0*/  0xcb, 0xf4,        //mov   $f4,y
29
+		/*ffe2*/  0xd7, 0x00,        //mov   ($00)+y,a
30
+		/*ffe4*/  0xfc,              //inc   y
31
+		/*ffe5*/  0xd0, 0xf3,        //bne   $ffda
32
+		/*ffe7*/  0xab, 0x01,        //inc   $01
33
+		/*ffe9*/  0x10, 0xef,        //bpl   $ffda
34
+		/*ffeb*/  0x7e, 0xf4,        //cmp   y,$f4
35
+		/*ffed*/  0x10, 0xeb,        //bpl   $ffda
36
+		/*ffef*/  0xba, 0xf6,        //movw  ya,$f6
37
+		/*fff1*/  0xda, 0x00,        //movw  $00,ya
38
+		/*fff3*/  0xba, 0xf4,        //movw  ya,$f4
39
+		/*fff5*/  0xc4, 0xf4,        //mov   $f4,a
40
+		/*fff7*/  0xdd,              //mov   a,y
41
+		/*fff8*/  0x5d,              //mov   x,a
42
+		/*fff9*/  0xd0, 0xdb,        //bne   $ffd6
43
+		/*fffb*/  0x1f, 0x00, 0x00,  //jmp   ($0000+x)
44
+		/*fffe*/  0xc0, 0xff         //reset vector location ($ffc0)
45
+	};
46
+}
0 47
new file mode 100644
... ...
@@ -0,0 +1,145 @@
1
+#include "smp.hpp"
2
+#include "../dsp/sdsp.hpp"
3
+
4
+namespace SNES
5
+{
6
+	unsigned SMP::port_read(unsigned addr)
7
+	{
8
+		return this->apuram[0xf4 + (addr & 3)];
9
+	}
10
+
11
+	void SMP::port_write(unsigned addr, unsigned data)
12
+	{
13
+		this->apuram[0xf4 + (addr & 3)] = data;
14
+	}
15
+
16
+	unsigned SMP::mmio_read(unsigned addr)
17
+	{
18
+		switch (addr)
19
+		{
20
+			case 0xf2:
21
+				return this->status.dsp_addr;
22
+
23
+			case 0xf3:
24
+				return dsp.read(this->status.dsp_addr & 0x7f);
25
+
26
+			case 0xf4:
27
+			case 0xf5:
28
+			case 0xf6:
29
+			case 0xf7:
30
+				return cpu.port_read(addr);
31
+
32
+			case 0xf8:
33
+				return this->status.ram00f8;
34
+
35
+			case 0xf9:
36
+				return this->status.ram00f9;
37
+
38
+			case 0xfd:
39
+			{
40
+				unsigned result = this->timer0.stage3_ticks & 15;
41
+				this->timer0.stage3_ticks = 0;
42
+				return result;
43
+			}
44
+
45
+			case 0xfe:
46
+			{
47
+				unsigned result = this->timer1.stage3_ticks & 15;
48
+				this->timer1.stage3_ticks = 0;
49
+				return result;
50
+			}
51
+
52
+			case 0xff:
53
+			{
54
+				unsigned result = this->timer2.stage3_ticks & 15;
55
+				this->timer2.stage3_ticks = 0;
56
+				return result;
57
+			}
58
+		}
59
+
60
+		return 0x00;
61
+	}
62
+
63
+	void SMP::mmio_write(unsigned addr, unsigned data)
64
+	{
65
+		switch (addr)
66
+		{
67
+			case 0xf1:
68
+				status.iplrom_enable = !!(data & 0x80);
69
+
70
+				if (data & 0x30)
71
+				{
72
+					if (data & 0x20)
73
+					{
74
+						cpu.port_write(3, 0x00);
75
+						cpu.port_write(2, 0x00);
76
+					}
77
+					if (data & 0x10)
78
+					{
79
+						cpu.port_write(1, 0x00);
80
+						cpu.port_write(0, 0x00);
81
+					}
82
+				}
83
+
84
+				if (!this->timer2.enable && !!(data & 0x04))
85
+				{
86
+					this->timer2.stage2_ticks = 0;
87
+					this->timer2.stage3_ticks = 0;
88
+				}
89
+				this->timer2.enable = !!(data & 0x04);
90
+
91
+				if (!this->timer1.enable && !!(data & 0x02))
92
+				{
93
+					this->timer1.stage2_ticks = 0;
94
+					this->timer1.stage3_ticks = 0;
95
+				}
96
+				this->timer1.enable = !!(data & 0x02);
97
+
98
+				if (!this->timer0.enable && !!(data & 0x01))
99
+				{
100
+					this->timer0.stage2_ticks = 0;
101
+					this->timer0.stage3_ticks = 0;
102
+				}
103
+				this->timer0.enable = !!(data & 0x01);
104
+
105
+				break;
106
+
107
+			case 0xf2:
108
+				this->status.dsp_addr = data;
109
+				break;
110
+
111
+			case 0xf3:
112
+				if (this->status.dsp_addr & 0x80)
113
+					break;
114
+				dsp.write(this->status.dsp_addr, data);
115
+				break;
116
+
117
+			case 0xf4:
118
+			case 0xf5:
119
+			case 0xf6:
120
+			case 0xf7:
121
+				this->port_write(addr, data);
122
+				break;
123
+
124
+			case 0xf8:
125
+				this->status.ram00f8 = data;
126
+				break;
127
+
128
+			case 0xf9:
129
+				this->status.ram00f9 = data;
130
+				break;
131
+
132
+			case 0xfa:
133
+				this->timer0.target = data;
134
+				break;
135
+
136
+			case 0xfb:
137
+				this->timer1.target = data;
138
+				break;
139
+
140
+			case 0xfc:
141
+				this->timer2.target = data;
142
+				break;
143
+		}
144
+	}
145
+}
0 146
new file mode 100644
... ...
@@ -0,0 +1,64 @@
1
+#include "smp.hpp"
2
+
3
+namespace SNES
4
+{
5
+	SMP smp;
6
+
7
+	void SMP::enter()
8
+	{
9
+		while (this->clock < 0)
10
+			this->op_step();
11
+	}
12
+
13
+	void SMP::power()
14
+	{
15
+		Processor::clock = 0;
16
+
17
+		this->timer0.target = 0;
18
+		this->timer1.target = 0;
19
+		this->timer2.target = 0;
20
+
21
+		this->reset();
22
+	}
23
+
24
+	void SMP::reset()
25
+	{
26
+		for (unsigned n = 0x0000; n <= 0xffff; ++n)
27
+			this->apuram[n] = 0x00;
28
+
29
+		this->opcode_number = 0;
30
+		this->opcode_cycle = 0;
31
+
32
+		this->regs.pc = 0xffc0;
33
+		this->regs.sp = 0xef;
34
+		this->regs.B.a = 0x00;
35
+		this->regs.x = 0x00;
36
+		this->regs.B.y = 0x00;
37
+		this->regs.p = 0x02;
38
+
39
+		// $00f1
40
+		this->status.iplrom_enable = true;
41
+
42
+		// $00f2
43
+		this->status.dsp_addr = 0x00;
44
+
45
+		// $00f8,$00f9
46
+		this->status.ram00f8 = 0x00;
47
+		this->status.ram00f9 = 0x00;
48
+
49
+		// timers
50
+		this->timer0.enable = this->timer1.enable = this->timer2.enable = false;
51
+		this->timer0.stage1_ticks = this->timer1.stage1_ticks = this->timer2.stage1_ticks = 0;
52
+		this->timer0.stage2_ticks = this->timer1.stage2_ticks = this->timer2.stage2_ticks = 0;
53
+		this->timer0.stage3_ticks = this->timer1.stage3_ticks = this->timer2.stage3_ticks = 0;
54
+	}
55
+
56
+	SMP::SMP()
57
+	{
58
+		this->apuram.reset(new uint8_t[64 * 1024]);
59
+	}
60
+
61
+	SMP::~SMP()
62
+	{
63
+	}
64
+}
0 65
new file mode 100644
... ...
@@ -0,0 +1,148 @@
1
+#pragma once
2
+
3
+#include <memory>
4
+#include "../snes/snes.hpp"
5
+
6
+namespace SNES
7
+{
8
+	class SMP : public Processor
9
+	{
10
+	public:
11
+		static const uint8_t iplrom[64];
12
+		std::unique_ptr<uint8_t[]> apuram;
13
+
14
+		unsigned port_read(unsigned port);
15
+		void port_write(unsigned port, unsigned data);
16
+
17
+		unsigned mmio_read(unsigned addr);
18
+		void mmio_write(unsigned addr, unsigned data);
19
+
20
+		void enter();
21
+		void power();
22
+		void reset();
23
+
24
+		SMP();
25
+		~SMP();
26
+
27
+	//private:
28
+		struct Flags
29
+		{
30
+			bool n, v, p, b, h, i, z, c;
31
+
32
+			operator unsigned() const
33
+			{
34
+				return (this->n << 7) | (this->v << 6) | (this->p << 5) | (this->b << 4) | (this->h << 3) | (this->i << 2) | (this->z << 1) | (this->c << 0);
35
+			}
36
+
37
+			unsigned operator=(unsigned data)
38
+			{
39
+				this->n = !!(data & 0x80);
40
+				this->v = !!(data & 0x40);
41
+				this->p = !!(data & 0x20);
42
+				this->b = !!(data & 0x10);
43
+				this->h = !!(data & 0x08);
44
+				this->i = !!(data & 0x04);
45
+				this->z = !!(data & 0x02);
46
+				this->c = !!(data & 0x01);
47
+				return data;
48
+			}
49
+
50
+			unsigned operator|=(unsigned data)
51
+			{
52
+				return this->operator=(this->operator unsigned() | data);
53
+			}
54
+
55
+			unsigned operator^=(unsigned data)
56
+			{
57
+				return this->operator=(this->operator unsigned() ^ data);
58
+			}
59
+
60
+			unsigned operator&=(unsigned data)
61
+			{
62
+				return this->operator=(this->operator unsigned() & data);
63
+			}
64
+		};
65
+
66
+		unsigned opcode_number;
67
+		unsigned opcode_cycle;
68
+
69
+		uint16_t rd, wr, dp, sp, ya, bit;
70
+
71
+		struct Regs
72
+		{
73
+			uint16_t pc;
74
+			uint8_t sp;
75
+			union
76
+			{
77
+				uint16_t ya;
78
+#ifdef __BIG_ENDIAN__
79
+				struct { uint8_t y, a; } B;
80
+#else
81
+				struct { uint8_t a, y; } B;
82
+#endif
83
+			};
84
+			uint8_t x;
85
+			Flags p;
86
+		} regs;
87
+
88
+		struct Status
89
+		{
90
+			// $00f1
91
+			bool iplrom_enable;
92
+
93
+			// $00f2
94
+			unsigned dsp_addr;
95
+
96
+			// $00f8,$00f9
97
+			unsigned ram00f8;
98
+			unsigned ram00f9;
99
+		} status;
100
+
101
+		template<unsigned frequency> struct Timer
102
+		{
103
+			bool enable;
104
+			uint8_t target;
105
+			uint8_t stage1_ticks;
106
+			uint8_t stage2_ticks;
107
+			uint8_t stage3_ticks;
108
+
109
+			void tick();
110
+			void tick(unsigned clocks);
111
+		};
112
+
113
+		Timer<128> timer0;
114
+		Timer<128> timer1;
115
+		Timer<16> timer2;
116
+
117
+		inline void tick();
118
+		inline void tick(unsigned clocks);
119
+		inline void op_io();
120
+		inline void op_io(unsigned clocks);
121
+		inline uint8_t op_read(uint16_t addr);
122
+		inline void op_write(uint16_t addr, uint8_t data);
123
+		void op_step();
124
+		void op_writestack(uint8_t data);
125
+		uint8_t op_readstack();
126
+		uint64_t cycle_table_cpu[256];
127
+		unsigned cycle_table_dsp[256];
128
+		uint64_t cycle_step_cpu;
129
+
130
+		uint8_t op_adc(uint8_t x, uint8_t y);
131
+		uint16_t op_addw(uint16_t x, uint16_t y);
132
+		uint8_t op_and(uint8_t x, uint8_t y);
133
+		uint8_t op_cmp(uint8_t x, uint8_t y);
134
+		uint16_t op_cmpw(uint16_t x, uint16_t y);
135
+		uint8_t op_eor(uint8_t x, uint8_t y);
136
+		uint8_t op_inc(uint8_t x);
137
+		uint8_t op_dec(uint8_t x);
138
+		uint8_t op_or(uint8_t x, uint8_t y);
139
+		uint8_t op_sbc(uint8_t x, uint8_t y);
140
+		uint16_t op_subw(uint16_t x, uint16_t y);
141
+		uint8_t op_asl(uint8_t x);
142
+		uint8_t op_lsr(uint8_t x);
143
+		uint8_t op_rol(uint8_t x);
144
+		uint8_t op_ror(uint8_t x);
145
+	};
146
+
147
+	extern SMP smp;
148
+}
0 149
new file mode 100644
... ...
@@ -0,0 +1,42 @@
1
+#include "smp.hpp"
2
+
3
+namespace SNES
4
+{
5
+	template<unsigned cycle_frequency> void SMP::Timer<cycle_frequency>::tick()
6
+	{
7
+		if (++this->stage1_ticks < cycle_frequency)
8
+			return;
9
+
10
+		this->stage1_ticks = 0;
11
+		if (!this->enable)
12
+			return;
13
+
14
+		if (++this->stage2_ticks != this->target)
15
+			return;
16
+
17
+		this->stage2_ticks = 0;
18
+		this->stage3_ticks = (this->stage3_ticks + 1) & 15;
19
+	}
20
+
21
+	template<unsigned cycle_frequency> void SMP::Timer<cycle_frequency>::tick(unsigned clocks)
22
+	{
23
+		this->stage1_ticks += clocks;
24
+		if (this->stage1_ticks < cycle_frequency)
25
+			return;
26
+
27
+		this->stage1_ticks -= cycle_frequency;
28
+		if (!this->enable)
29
+			return;
30
+
31
+		if (++this->stage2_ticks != this->target)
32
+			return;
33
+
34
+		this->stage2_ticks = 0;
35
+		this->stage3_ticks = (this->stage3_ticks + 1) & 15;
36
+	}
37
+
38
+	template void SMP::Timer<128>::tick();
39
+	template void SMP::Timer<128>::tick(unsigned);
40
+	template void SMP::Timer<16>::tick();
41
+	template void SMP::Timer<16>::tick(unsigned);
42
+}
0 43
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+#pragma once
2
+
3
+#include "../../../snes9x.h"
4
+
5
+namespace SNES
6
+{
7
+	struct Processor
8
+	{
9
+		unsigned frequency;
10
+		int32_t clock;
11
+	};
12
+
13
+	class CPU
14
+	{
15
+	public:
16
+		enum { Threaded = false };
17
+		int frequency;
18
+		uint8_t registers[4];
19
+
20
+		void reset()
21
+		{
22
+			this->registers[0] = this->registers[1] = this->registers[2] = this->registers[3] = 0;
23
+		}
24
+
25
+		void port_write(uint8_t port, uint8_t data)
26
+		{
27
+			this->registers[port & 3] = data;
28
+		}
29
+
30
+		uint8_t port_read(uint8_t port)
31
+		{
32
+			return this->registers[port & 3];
33
+		}
34
+	};
35
+
36
+	extern CPU cpu;
37
+}
0 38
deleted file mode 100644
... ...
@@ -1,125 +0,0 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
2
-
3
-#pragma once
4
-
5
-#include <cmath>
6
-#include "resampler.h"
7
-
8
-class BsplineResampler : public Resampler
9
-{
10
-protected:
11
-	double r_step;
12
-	double r_frac;
13
-	int r_left[6], r_right[6];
14
-
15
-	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
16
-	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
17
-
18
-	double bspline(double x, double a, double b, double c, double d, double e, double f)
19
-	{
20
-		float ym2py2 = a + e, ym1py1 = b + d;
21
-		float y2mym2 = e - a, y1mym1 = d - b;
22
-		float sixthym1py1 = 1 / 6.0 * ym1py1;
23
-		float c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * c;
24
-		float c1 = 1 / 24.0 * y2mym2 + 5 / 12.0 * y1mym1;
25
-		float c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * c;
26
-		float c3 = 1 / 12.0 * y2mym2 - 1 / 6.0 * y1mym1;
27
-		float c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * c;
28
-		float c5 = 1 / 120.0 * (f - a) + 1 / 24.0 * (b - e) + 1 / 12.0 * (d - c);
29
-		return ((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0;
30
-	}
31
-
32
-public:
33
-	BsplineResampler(int num_samples) : Resampler(num_samples)
34
-	{
35
-		this->clear();
36
-	}
37
-
38
-	void time_ratio(double ratio)
39
-	{
40
-		this->r_step = ratio;
41
-		this->clear();
42
-	}
43
-
44
-	void clear()
45
-	{
46
-		ring_buffer::clear();
47
-		this->r_frac = 1.0;
48
-		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
49
-		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
50
-	}
51
-
52
-	void read(short *data, int num_samples)
53
-	{
54
-		int i_position = this->start >> 1;
55
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
56
-		int o_position = 0;
57
-		int consumed = 0;
58
-
59
-		while (o_position < num_samples && consumed < this->buffer_size)
60
-		{
61
-			int s_left = internal_buffer[i_position];
62
-			int s_right = internal_buffer[i_position + 1];
63
-			int max_samples = this->buffer_size >> 1;
64
-			static const double margin_of_error = 1.0e-10;
65
-
66
-			if (std::abs(this->r_step - 1.0) < margin_of_error)
67
-			{
68
-				data[o_position] = static_cast<short>(s_left);
69
-				data[o_position + 1] = static_cast<short>(s_right);
70
-
71
-				o_position += 2;
72
-				i_position += 2;
73
-				if (i_position >= max_samples)
74
-					i_position -= max_samples;
75
-				consumed += 2;
76
-
77
-				continue;
78
-			}
79
-
80
-			while (this->r_frac <= 1.0 && o_position < num_samples)
81
-			{
82
-				data[o_position] = SHORT_CLAMP(bspline(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3], this->r_left[4], this->r_left[5]));
83
-				data[o_position + 1] = SHORT_CLAMP(bspline(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3], this->r_right[4], this->r_right[5]));
84
-
85
-				o_position += 2;
86
-
87
-				this->r_frac += this->r_step;
88
-			}
89
-
90
-			if (this->r_frac > 1.0)
91
-			{
92
-				this->r_left[0] = this->r_left[1];
93
-				this->r_left[1] = this->r_left[2];
94
-				this->r_left[2] = this->r_left[3];
95
-				this->r_left[3] = this->r_left[4];
96
-				this->r_left[4] = this->r_left[5];
97
-				this->r_left[5] = s_left;
98
-
99
-				this->r_right[0] = this->r_right[1];
100
-				this->r_right[1] = this->r_right[2];
101
-				this->r_right[2] = this->r_right[3];
102
-				this->r_right[3] = this->r_right[4];
103
-				this->r_right[4] = this->r_right[5];
104
-				this->r_right[5] = s_right;
105
-
106
-				this->r_frac -= 1.0;
107
-
108
-				i_position += 2;
109
-				if (i_position >= max_samples)
110
-					i_position -= max_samples;
111
-				consumed += 2;
112
-			}
113
-		}
114
-
115
-		this->size -= consumed << 1;
116
-		this->start += consumed << 1;
117
-		if (this->start >= this->buffer_size)
118
-			this->start -= this->buffer_size;
119
-	}
120
-
121
-	int avail()
122
-	{
123
-		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
124
-	}
125
-};
126 0
deleted file mode 100644
... ...
@@ -1,130 +0,0 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
2
-
3
-#pragma once
4
-
5
-#include <cmath>
6
-#include "resampler.h"
7
-
8
-class HermiteResampler : public Resampler
9
-{
10
-protected:
11
-	double r_step;
12
-	double r_frac;
13
-	int r_left[4], r_right[4];
14
-
15
-	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
16
-	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
17
-
18
-	double hermite(double mu1, double a, double b, double c, double d)
19
-	{
20
-		static const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
21
-		static const double bias = 0.0; //-1 = left, 0 = even, 1 = right
22
-
23
-		double mu2, mu3, m0, m1, a0, a1, a2, a3;
24
-
25
-		mu2 = mu1 * mu1;
26
-		mu3 = mu2 * mu1;
27
-
28
-		m0  = (b - a) * (1 + bias) * (1 - tension) / 2;
29
-		m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
30
-		m1  = (c - b) * (1 + bias) * (1 - tension) / 2;
31
-		m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
32
-
33
-		a0 = 2 * mu3 - 3 * mu2 + 1;
34
-		a1 = mu3 - 2 * mu2 + mu1;
35
-		a2 = mu3 - mu2;
36
-		a3 = -2 * mu3 + 3 * mu2;
37
-
38
-		return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
39
-	}
40
-
41
-public:
42
-	HermiteResampler(int num_samples) : Resampler(num_samples)
43
-	{
44
-		this->clear();
45
-	}
46
-
47
-	void time_ratio(double ratio)
48
-	{
49
-		this->r_step = ratio;
50
-		this->clear();
51
-	}
52
-
53
-	void clear()
54
-	{
55
-		ring_buffer::clear();
56
-		this->r_frac = 1.0;
57
-		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
58
-		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
59
-	}
60
-
61
-	void read(short *data, int num_samples)
62
-	{
63
-		int i_position = this->start >> 1;
64
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
65
-		int o_position = 0;
66
-		int consumed = 0;
67
-
68
-		while (o_position < num_samples && consumed < this->buffer_size)
69
-		{
70
-			int s_left = internal_buffer[i_position];
71
-			int s_right = internal_buffer[i_position + 1];
72
-			int max_samples = this->buffer_size >> 1;
73
-			static const double margin_of_error = 1.0e-10;
74
-
75
-			if (std::abs(this->r_step - 1.0) < margin_of_error)
76
-			{
77
-				data[o_position] = static_cast<short>(s_left);
78
-				data[o_position + 1] = static_cast<short>(s_right);
79
-
80
-				o_position += 2;
81
-				i_position += 2;
82
-				if (i_position >= max_samples)
83
-					i_position -= max_samples;
84
-				consumed += 2;
85
-
86
-				continue;
87
-			}
88
-
89
-			while (this->r_frac <= 1.0 && o_position < num_samples)
90
-			{
91
-				data[o_position] = SHORT_CLAMP(hermite(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
92
-				data[o_position + 1] = SHORT_CLAMP(hermite(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
93
-
94
-				o_position += 2;
95
-
96
-				this->r_frac += this->r_step;
97
-			}
98
-
99
-			if (this->r_frac > 1.0)
100
-			{
101
-				this->r_left[0] = this->r_left[1];
102
-				this->r_left[1] = this->r_left[2];
103
-				this->r_left[2] = this->r_left[3];
104
-				this->r_left[3] = s_left;
105
-
106
-				this->r_right[0] = this->r_right[1];
107
-				this->r_right[1] = this->r_right[2];
108
-				this->r_right[2] = this->r_right[3];
109
-				this->r_right[3] = s_right;
110
-
111
-				this->r_frac -= 1.0;
112
-
113
-				i_position += 2;
114
-				if (i_position >= max_samples)
115
-					i_position -= max_samples;
116
-				consumed += 2;
117
-			}
118
-		}
119
-
120
-		this->size -= consumed << 1;
121
-		this->start += consumed << 1;
122
-		if (this->start >= this->buffer_size)
123
-			this->start -= this->buffer_size;
124
-	}
125
-
126
-	int avail()
127
-	{
128
-		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
129
-	}
130
-};
131 0
deleted file mode 100644
... ...
@@ -1,100 +0,0 @@
1
-/* Simple fixed-point linear resampler by BearOso*/
2
-
3
-#pragma once
4
-
5
-#include "resampler.h"
6
-#include "XSFCommon.h"
7
-
8
-class LinearResampler : public Resampler
9
-{
10
-	static const int f_prec = 15;
11
-	static const uint32_t f__one = 1 << f_prec;
12
-
13
-protected:
14
-	uint32_t f__r_step;
15
-	uint32_t f__inv_r_step;
16
-	uint32_t f__r_frac;
17
-	int r_left, r_right;
18
-
19
-	static short lerp(uint32_t t, int a, short b) { return (((b - a) * t) >> f_prec) + a; }
20
-
21
-public:
22
-	LinearResampler(int num_samples) : Resampler(num_samples)
23
-	{
24
-		this->f__r_frac = 0;
25
-	}
26
-
27
-	void time_ratio(double ratio)
28
-	{
29
-		if (fEqual(ratio, 0.0))
30
-			ratio = 1.0;
31
-		this->f__r_step = static_cast<uint32_t>(ratio * f__one);
32
-		this->f__inv_r_step = static_cast<uint32_t>(f__one / ratio);
33
-		this->clear();
34
-	}
35
-
36
-	void clear()
37
-	{
38
-		ring_buffer::clear();
39
-		this->f__r_frac = 0;
40
-		this->r_left = 0;
41
-		this->r_right = 0;
42
-	}
43
-
44
-	void read(short *data, int num_samples)
45
-	{
46
-		int i_position = this->start >> 1;
47
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
48
-		int o_position = 0;
49
-		int consumed = 0;
50
-		int max_samples = this->buffer_size >> 1;
51
-
52
-		while (o_position < num_samples && consumed < this->buffer_size)
53
-		{
54
-			if (this->f__r_step == f__one)
55
-			{
56
-				data[o_position] = internal_buffer[i_position];
57
-				data[o_position + 1] = internal_buffer[i_position + 1];
58
-
59
-				o_position += 2;
60
-				i_position += 2;
61
-				if (i_position >= max_samples)
62
-					i_position -= max_samples;
63
-				consumed += 2;
64
-
65
-				continue;
66
-			}
67
-
68
-			while (this->f__r_frac <= f__one && o_position < num_samples)
69
-			{
70
-				data[o_position] = lerp(this->f__r_frac, this->r_left, internal_buffer[i_position]);
71
-				data[o_position + 1] = lerp(this->f__r_frac, this->r_right, internal_buffer[i_position + 1]);
72
-
73
-				o_position += 2;
74
-
75
-				this->f__r_frac += this->f__r_step;
76
-			}
77
-
78
-			if (this->f__r_frac > f__one)
79
-			{
80
-				this->f__r_frac -= f__one;
81
-				this->r_left = internal_buffer[i_position];
82
-				this->r_right = internal_buffer[i_position + 1];
83
-				i_position += 2;
84
-				if (i_position >= max_samples)
85
-					i_position -= max_samples;
86
-				consumed += 2;
87
-			}
88
-		}
89
-
90
-		this->size -= consumed << 1;
91
-		this->start += consumed << 1;
92
-		if (this->start >= this->buffer_size)
93
-			this->start -= this->buffer_size;
94
-	}
95
-
96
-	int avail()
97
-	{
98
-		return (((this->size >> 2) * this->f__inv_r_step) - ((this->f__r_frac * this->f__inv_r_step) >> f_prec)) >> (f_prec - 1);
99
-	}
100
-};
101 0
deleted file mode 100644
... ...
@@ -1,126 +0,0 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
2
-
3
-#pragma once
4
-
5
-#include <cmath>
6
-#include "resampler.h"
7
-
8
-class OsculatingResampler : public Resampler
9
-{
10
-protected:
11
-	double r_step;
12
-	double r_frac;
13
-	int r_left[6], r_right[6];
14
-
15
-	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
16
-	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
17
-
18
-	double osculating(double x, double a, double b, double c, double d, double e, double f)
19
-	{
20
-		double z = x - 0.5;
21
-		double even1 = a + f, odd1 = a - f;
22
-		double even2 = b + e, odd2 = b - e;
23
-		double even3 = c + d, odd3 = c - d;
24
-		double c0 = 0.01171875 * even1 - 0.09765625 * even2 + 0.5859375 * even3;
25
-		double c1 = 0.2109375 * odd2 - 281 / 192.0 * odd3 - 13 / 384.0 * odd1;
26
-		double c2 = 0.40625 * even2 - 17 / 48.0 * even3 - 5 / 96.0 * even1;
27
-		double c3 = 0.1875 * odd1 - 53 / 48.0 * odd2 + 2.375 * odd3;
28
-		double c4 = 1 / 48.0*even1 - 0.0625 * even2 + 1 / 24.0 * even3;
29
-		double c5 = 25 / 24.0 * odd2 - 25 / 12.0 * odd3 - 5 / 24.0 * odd1;
30
-		return ((((c5 * z + c4) * z + c3) * z + c2) * z + c1) * z + c0;
31
-	}
32
-
33
-public:
34
-	OsculatingResampler(int num_samples) : Resampler(num_samples)
35
-	{
36
-		this->clear();
37
-	}
38
-
39
-	void time_ratio(double ratio)
40
-	{
41
-		this->r_step = ratio;
42
-		this->clear();
43
-	}
44
-
45
-	void clear()
46
-	{
47
-		ring_buffer::clear();
48
-		this->r_frac = 1.0;
49
-		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
50
-		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
51
-	}
52
-
53
-	void read(short *data, int num_samples)
54
-	{
55
-		int i_position = this->start >> 1;
56
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
57
-		int o_position = 0;
58
-		int consumed = 0;
59
-
60
-		while (o_position < num_samples && consumed < this->buffer_size)
61
-		{
62
-			int s_left = internal_buffer[i_position];
63
-			int s_right = internal_buffer[i_position + 1];
64
-			int max_samples = this->buffer_size >> 1;
65
-			static const double margin_of_error = 1.0e-10;
66
-
67
-			if (std::abs(this->r_step - 1.0) < margin_of_error)
68
-			{
69
-				data[o_position] = static_cast<short>(s_left);
70
-				data[o_position + 1] = static_cast<short>(s_right);
71
-
72
-				o_position += 2;
73
-				i_position += 2;
74
-				if (i_position >= max_samples)
75
-					i_position -= max_samples;
76
-				consumed += 2;
77
-
78
-				continue;
79
-			}
80
-
81
-			while (this->r_frac <= 1.0 && o_position < num_samples)
82
-			{
83
-				data[o_position] = SHORT_CLAMP(osculating(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3], this->r_left[4], this->r_left[5]));
84
-				data[o_position + 1] = SHORT_CLAMP(osculating(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3], this->r_right[4], this->r_right[5]));
85
-
86
-				o_position += 2;
87
-
88
-				this->r_frac += this->r_step;
89
-			}
90
-
91
-			if (this->r_frac > 1.0)
92
-			{
93
-				this->r_left[0] = this->r_left[1];
94
-				this->r_left[1] = this->r_left[2];
95
-				this->r_left[2] = this->r_left[3];
96
-				this->r_left[3] = this->r_left[4];
97
-				this->r_left[4] = this->r_left[5];
98
-				this->r_left[5] = s_left;
99
-
100
-				this->r_right[0] = this->r_right[1];
101
-				this->r_right[1] = this->r_right[2];
102
-				this->r_right[2] = this->r_right[3];
103
-				this->r_right[3] = this->r_right[4];
104
-				this->r_right[4] = this->r_right[5];
105
-				this->r_right[5] = s_right;
106
-
107
-				this->r_frac -= 1.0;
108
-
109
-				i_position += 2;
110
-				if (i_position >= max_samples)
111
-					i_position -= max_samples;
112
-				consumed += 2;
113
-			}
114
-		}
115
-
116
-		this->size -= consumed << 1;
117
-		this->start += consumed << 1;
118
-		if (this->start >= this->buffer_size)
119
-			this->start -= this->buffer_size;
120
-	}
121
-
122
-	int avail()
123
-	{
124
-		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
125
-	}
126
-};
... ...
@@ -1,42 +1,193 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
1
+/*****************************************************************************\
2
+  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
2 6
 
3 7
 #pragma once
4 8
 
5
-#include "ring_buffer.h"
9
+#include <algorithm>
10
+#include <limits>
11
+#include <memory>
12
+#include <cstdint>
13
+#include <cmath>
14
+#include "XSFCommon.h"
6 15
 
7
-class Resampler : public ring_buffer
16
+class Resampler
8 17
 {
9 18
 public:
10
-	virtual void clear() = 0;
11
-	virtual void time_ratio(double) = 0;
12
-	virtual void read(short *, int) = 0;
13
-	virtual int avail() = 0;
19
+	int size;
20
+	int buffer_size;
21
+	int start;
22
+	std::unique_ptr<int16_t[]> buffer;
14 23
 
15
-	Resampler(int num_samples) : ring_buffer(num_samples << 1)
24
+	float r_step;
25
+	float r_frac;
26
+	int   r_left[4], r_right[4];
27
+
28
+	static float hermite(float mu1, float a, float b, float c, float d)
29
+	{
30
+		float mu2 = mu1 * mu1;
31
+		float mu3 = mu2 * mu1;
32
+
33
+		float m0 = (c - a) * 0.5;
34
+		float m1 = (d - b) * 0.5;
35
+
36
+		float a0 = +2 * mu3 - 3 * mu2 + 1;
37
+		float a1 = mu3 - 2 * mu2 + mu1;
38
+		float a2 = mu3 - mu2;
39
+		float a3 = -2 * mu3 + 3 * mu2;
40
+
41
+		return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
42
+	}
43
+
44
+	Resampler(int num_samples)
45
+	{
46
+		this->buffer_size = num_samples;
47
+		this->buffer.reset(new int16_t[this->buffer_size]);
48
+		this->r_step = 1.0;
49
+		this->clear();
50
+	}
51
+
52
+	void time_ratio(double ratio)
16 53
 	{
54
+		this->r_step = ratio;
17 55
 	}
18 56
 
19
-	virtual ~Resampler()
57
+	void clear()
20 58
 	{
59
+		this->start = 0;
60
+		this->size = 0;
61
+		std::fill_n(&this->buffer[0], this->buffer_size, 0);
62
+
63
+		this->r_frac = 0.0;
64
+		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
65
+		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
21 66
 	}
22 67
 
23
-	bool push(short *src, int num_samples)
68
+	bool pull(int16_t *dst, int num_samples)
24 69
 	{
25
-		if (this->max_write() < num_samples)
70
+		if (this->space_filled() < num_samples)
26 71
 			return false;
27 72
 
28
-		!num_samples || ring_buffer::push(reinterpret_cast<unsigned char *>(src), num_samples << 1);
73
+		std::copy_n(&this->buffer[start], std::min(num_samples, this->buffer_size - this->start), &dst[0]);
74
+
75
+		if (num_samples > this->buffer_size - this->start)
76
+			std::copy_n(&this->buffer[0], num_samples - (this->buffer_size - this->start), &dst[this->buffer_size - this->start]);
77
+
78
+		this->start = (this->start + num_samples) % this->buffer_size;
79
+		this->size -= num_samples;
29 80
 
30 81
 		return true;
31 82
 	}
32 83
 
33
-	int max_write()
84
+	void push_sample(int16_t l, int16_t r)
85
+	{
86
+		if (this->space_empty() >= 2)
87
+		{
88
+			int end = this->start + this->size;
89
+			if (end >= this->buffer_size)
90
+				end -= this->buffer_size;
91
+			this->buffer[end] = l;
92
+			this->buffer[end + 1] = r;
93
+			this->size += 2;
94
+		}
95
+	}
96
+
97
+	bool push(int16_t *src, int num_samples)
34 98
 	{
35
-		return this->space_empty () >> 1;
99
+		if (this->space_empty() < num_samples)
100
+			return false;
101
+
102
+		int end = this->start + this->size;
103
+		if (end > this->buffer_size)
104
+			end -= this->buffer_size;
105
+		int first_write_size = std::min(num_samples, this->buffer_size - end);
106
+
107
+		std::copy_n(&src[0], first_write_size, &this->buffer[end]);
108
+
109
+		if (num_samples > first_write_size)
110
+			std::copy_n(&src[first_write_size], num_samples - first_write_size, &this->buffer[0]);
111
+
112
+		this->size += num_samples;
113
+
114
+		return true;
115
+	}
116
+
117
+	void read(int16_t *data, int num_samples)
118
+	{
119
+		// If we are outputting the exact same ratio as the input, pull directly from the input buffer
120
+		if (fEqual(this->r_step, 1.0f))
121
+		{
122
+			this->pull(data, num_samples);
123
+			return;
124
+		}
125
+
126
+		int o_position = 0;
127
+
128
+		while (o_position < num_samples && this->size > 0)
129
+		{
130
+			int s_left = this->buffer[start];
131
+			int s_right = this->buffer[start + 1];
132
+			int hermite_val[2];
133
+
134
+			while (this->r_frac <= 1.0 && o_position < num_samples)
135
+			{
136
+				hermite_val[0] = static_cast<int>(hermite(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
137
+				hermite_val[1] = static_cast<int>(hermite(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
138
+				data[o_position] = static_cast<int16_t>(std::clamp<int>(hermite_val[0], std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()));
139
+				data[o_position + 1] = static_cast<int16_t>(std::clamp<int>(hermite_val[1], std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()));
140
+
141
+				o_position += 2;
142
+
143
+				this->r_frac += this->r_step;
144
+			}
145
+
146
+			if (this->r_frac > 1.0)
147
+			{
148
+				this->r_left[0] = this->r_left[1];
149
+				this->r_left[1] = this->r_left[2];
150
+				this->r_left[2] = this->r_left[3];
151
+				this->r_left[3] = s_left;
152
+
153
+				this->r_right[0] = this->r_right[1];
154
+				this->r_right[1] = this->r_right[2];
155
+				this->r_right[2] = this->r_right[3];
156
+				this->r_right[3] = s_right;
157
+
158
+				--this->r_frac;
159
+
160
+				this->start += 2;
161
+				if (this->start >= this->buffer_size)
162
+					this->start -= this->buffer_size;
163
+				this->size -= 2;
164
+			}
165
+		}
166
+	}
167
+
168
+	int space_empty() const
169
+	{
170
+		return this->buffer_size - this->size;
171
+	}
172
+
173
+	int space_filled() const
174
+	{
175
+		return this->size;
176
+	}
177
+
178
+	int avail()
179
+	{
180
+		// If we are outputting the exact same ratio as the input, find out directly from the input buffer
181
+		if (fEqual(this->r_step, 1.0f))
182
+			return this->size;
183
+
184
+		return static_cast<int>(std::trunc(((this->size >> 1) - this->r_frac) / this->r_step)) * 2;
36 185
 	}
37 186
 
38 187
 	void resize(int num_samples)
39 188
 	{
40
-		ring_buffer::resize(num_samples << 1);
189
+		this->buffer_size = num_samples;
190
+		this->buffer.reset(new int16_t[this->buffer_size]);
191
+		this->clear();
41 192
 	}
42 193
 };
43 194
deleted file mode 100644
... ...
@@ -1,65 +0,0 @@
1
-/* Simple byte-based ring buffer. Licensed under public domain (C) BearOso. */
2
-
3
-#pragma once
4
-
5
-#include <memory>
6
-#include <algorithm>
7
-#include <cstring>
8
-
9
-class ring_buffer
10
-{
11
-protected:
12
-	int size;
13
-	int buffer_size;
14
-	int start;
15
-	std::unique_ptr<unsigned char[]> buffer;
16
-
17
-public:
18
-	ring_buffer(int buf_size)
19
-	{
20
-		this->buffer_size = buf_size;
21
-		this->buffer.reset(new unsigned char[this->buffer_size]);
22
-		this->clear();
23
-	}
24
-
25
-	bool push(unsigned char *src, int bytes)
26
-	{
27
-		if (this->space_empty() < bytes)
28
-			return false;
29
-
30
-		int end = (this->start + this->size) % this->buffer_size;
31
-		int first_write_size = std::min(bytes, this->buffer_size - end);
32
-
33
-		std::copy_n(&src[0], first_write_size, &this->buffer[end]);
34
-
35
-		if (bytes > first_write_size)
36
-			std::copy(&src[first_write_size], &src[bytes], &this->buffer[0]);
37
-
38
-		this->size += bytes;
39
-
40
-		return true;
41
-	}
42
-
43
-	int space_empty()
44
-	{
45
-		return this->buffer_size - this->size;
46
-	}
47
-
48
-	int space_filled()
49
-	{
50
-		return this->size;
51
-	}
52
-
53
-	void clear()
54
-	{
55
-		this->start = this->size = 0;
56
-		std::fill_n(&this->buffer[0], this->buffer_size, 0);
57
-	}
58
-
59
-	void resize(int new_size)
60
-	{
61
-		this->buffer_size = new_size;
62
-		this->buffer.reset(new unsigned char[this->buffer_size]);
63
-		this->clear();
64
-	}
65
-};
66 0
deleted file mode 100644
... ...
@@ -1,145 +0,0 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
2
-
3
-#pragma once
4
-
5
-#include <algorithm>
6
-#define _USE_MATH_DEFINES
7
-#include <cmath>
8
-#include "resampler.h"
9
-#include "XSFCommon.h"
10
-
11
-#ifndef M_PI
12
-const double M_PI = 3.14159265358979323846;
13
-#endif
14
-
15
-class SincResampler : public Resampler
16
-{
17
-protected:
18
-	static bool initializedLUTs;
19
-	static const unsigned SINC_RESOLUTION = 8192;
20
-	static const unsigned SINC_WIDTH = 8;
21
-	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
22
-	static double sinc_lut[SINC_SAMPLES + 1];
23
-
24
-	double r_step;
25
-	double r_frac;
26
-	int r_left[SINC_WIDTH * 2], r_right[SINC_WIDTH * 2];
27
-
28
-	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
29
-	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
30
-
31
-	static inline double sinc(double x)
32
-	{
33
-		return fEqual(x, 0.0) ? 1.0 : std::sin(x * M_PI) / (x * M_PI);
34
-	}
35
-
36
-	double sinc(const int *data)
37
-	{
38
-		double kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
39
-		int i = SINC_WIDTH, shift = static_cast<int>(std::floor(this->r_frac * SINC_RESOLUTION));
40
-		int step = this->r_step > 1.0 ? static_cast<int>(SINC_RESOLUTION / this->r_step) : SINC_RESOLUTION;
41
-		int shift_adj = shift * step / SINC_RESOLUTION;
42
-		for (; i >= -static_cast<int>(SINC_WIDTH - 1); --i)
43
-		{
44
-			int pos = i * step;
45
-			kernel_sum += kernel[i + SINC_WIDTH - 1] = this->sinc_lut[std::abs(shift_adj - pos)];
46
-		}
47
-		double sum = 0.0;
48
-		for (i = 0; i < static_cast<int>(SINC_WIDTH * 2); ++i)
49
-			sum += data[i] * kernel[i];
50
-		return sum / kernel_sum;
51
-	}
52
-
53
-public:
54
-	SincResampler(int num_samples) : Resampler(num_samples)
55
-	{
56
-		if (!this->initializedLUTs)
57
-		{
58
-			double dx = static_cast<double>(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
59
-			for (unsigned i = 0; i <= SINC_SAMPLES; ++i, x += dx)
60
-				this->sinc_lut[i] = std::abs(x) < SINC_WIDTH ? sinc(x) * sinc(x / SINC_WIDTH) : 0.0;
61
-			this->initializedLUTs = true;
62
-		}
63
-		this->clear();
64
-	}
65
-
66
-	void time_ratio(double ratio)
67
-	{
68
-		this->r_step = ratio;
69
-		this->clear();
70
-	}
71
-
72
-	void clear()
73
-	{
74
-		ring_buffer::clear();
75
-		this->r_frac = 1.0;
76
-		std::fill_n(&this->r_left[0], SINC_WIDTH * 2, 0);
77
-		std::fill_n(&this->r_right[0], SINC_WIDTH * 2, 0);
78
-	}
79
-
80
-	void read(short *data, int num_samples)
81
-	{
82
-		int i_position = this->start >> 1;
83
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
84
-		int o_position = 0;
85
-		int consumed = 0;
86
-
87
-		while (o_position < num_samples && consumed < this->buffer_size)
88
-		{
89
-			int s_left = internal_buffer[i_position];
90
-			int s_right = internal_buffer[i_position + 1];
91
-			int max_samples = this->buffer_size >> 1;
92
-			static const double margin_of_error = 1.0e-10;
93
-
94
-			if (std::abs(this->r_step - 1.0) < margin_of_error)
95
-			{
96
-				data[o_position] = static_cast<short>(s_left);
97
-				data[o_position + 1] = static_cast<short>(s_right);
98
-
99
-				o_position += 2;
100
-				i_position += 2;
101
-				if (i_position >= max_samples)
102
-					i_position -= max_samples;
103
-				consumed += 2;
104
-
105
-				continue;
106
-			}
107
-
108
-			while (this->r_frac <= 1.0 && o_position < num_samples)
109
-			{
110
-				data[o_position] = SHORT_CLAMP(sinc(this->r_left));
111
-				data[o_position + 1] = SHORT_CLAMP(sinc(this->r_right));
112
-
113
-				o_position += 2;
114
-
115
-				this->r_frac += this->r_step;
116
-			}
117
-
118
-			if (this->r_frac > 1.0)
119
-			{
120
-				std::copy_n(&this->r_left[1], SINC_WIDTH * 2 - 1, &this->r_left[0]);
121
-				this->r_left[SINC_WIDTH * 2 - 1] = s_left;
122
-
123
-				std::copy_n(&this->r_right[1], SINC_WIDTH * 2 - 1, &this->r_right[0]);
124
-				this->r_right[SINC_WIDTH * 2 - 1] = s_right;
125
-
126
-				this->r_frac -= 1.0;
127
-
128
-				i_position += 2;
129
-				if (i_position >= max_samples)
130
-					i_position -= max_samples;
131
-				consumed += 2;
132
-			}
133
-		}
134
-
135
-		this->size -= consumed << 1;
136
-		this->start += consumed << 1;
137
-		if (this->start >= this->buffer_size)
138
-			this->start -= this->buffer_size;
139
-	}
140
-
141
-	int avail()
142
-	{
143
-		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
144
-	}
145
-};
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <algorithm>
179 8
 #include "snes9x.h"
... ...
@@ -188,8 +17,7 @@ static void S9xSoftResetCPU()
188 17
 	CPU.V_Counter = 0;
189 18
 	CPU.Flags &= DEBUG_MODE_FLAG | TRACE_FLAG;
190 19
 	CPU.PCBase = nullptr;
191
-	CPU.NMILine = CPU.IRQLine = CPU.IRQTransition = CPU.IRQLastState = false;
192
-	CPU.IRQPending = Timings.IRQPendCount;
20
+	CPU.NMIPending = CPU.IRQLine = CPU.IRQTransition = false;
193 21
 	CPU.MemSpeed = SLOW_ONE_CYCLE;
194 22
 	CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
195 23
 	CPU.FastROMSpeed = SLOW_ONE_CYCLE;
... ...
@@ -218,6 +46,9 @@ static void S9xSoftResetCPU()
218 46
 	Timings.H_Max = Timings.H_Max_Master;
219 47
 	Timings.V_Max = Timings.V_Max_Master;
220 48
 	Timings.NMITriggerPos = 0xffff;
49
+	Timings.NextIRQTimer = 0x0fffffff;
50
+	Timings.IRQFlagChanging = IRQ_NONE;
51
+
221 52
 	Timings.WRAMRefreshPos = Model->_5A22 == 2 ? SNES_WRAM_REFRESH_HC_v2 : SNES_WRAM_REFRESH_HC_v1;
222 53
 
223 54
 	S9xSetPCBase(Registers.PC.xPBPC);
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -286,6 +115,8 @@ inline uint32_t AbsoluteIndexedIndirectSlow(AccessMode a) // (a,X)
286 115
 inline uint32_t AbsoluteIndexedIndirect(AccessMode) // (a,X)
287 116
 {
288 117
 	uint16_t addr = Immediate16Slow(READ);
118
+
119
+	AddCycles(ONE_CYCLE);
289 120
 	addr += Registers.X.W;
290 121
 
291 122
 	// Address load wraps within the bank
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include "snes9x.h"
179 8
 #include "memmap.h"
... ...
@@ -216,46 +45,77 @@ static inline void S9xReschedule()
216 45
 	}
217 46
 }
218 47
 
48
+static void CHECK_FOR_IRQ_CHANGE()
49
+{
50
+	if (Timings.IRQFlagChanging)
51
+	{
52
+		if (Timings.IRQFlagChanging & IRQ_TRIGGER_NMI)
53
+		{
54
+			CPU.NMIPending = true;
55
+			Timings.NMITriggerPos = CPU.Cycles + 6;
56
+		}
57
+		if (Timings.IRQFlagChanging & IRQ_CLEAR_FLAG)
58
+			ClearIRQ();
59
+		else if (Timings.IRQFlagChanging & IRQ_SET_FLAG)
60
+			SetIRQ();
61
+		Timings.IRQFlagChanging = IRQ_NONE;
62
+	}
63
+}
64
+
219 65
 void S9xMainLoop()
220 66
 {
67
+	if (CPU.Flags & SCAN_KEYS_FLAG)
68
+		CPU.Flags &= ~SCAN_KEYS_FLAG;
69
+
221 70
 	for (;;)
222 71
 	{
223
-		if (CPU.NMILine)
72
+		if (CPU.NMIPending)
224 73
 		{
225 74
 			if (Timings.NMITriggerPos <= CPU.Cycles)
226 75
 			{
227
-				CPU.NMILine = false;
76
+				CPU.NMIPending = false;
228 77
 				Timings.NMITriggerPos = 0xffff;
229 78
 				if (CPU.WaitingForInterrupt)
230 79
 				{
231 80
 					CPU.WaitingForInterrupt = false;
232 81
 					++Registers.PC.W.xPC;
82
+					CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
83
+					while (CPU.Cycles >= CPU.NextEvent)
84
+						S9xDoHEventProcessing();
233 85
 				}
234 86
 
87
+				CHECK_FOR_IRQ_CHANGE();
235 88
 				S9xOpcode_NMI();
236 89
 			}
237 90
 		}
238 91
 
239
-		if (CPU.IRQTransition)
92
+		if (CPU.Cycles >= Timings.NextIRQTimer)
240 93
 		{
241
-			if (CPU.IRQPending)
242
-				--CPU.IRQPending;
243
-			else
244
-			{
245
-				if (CPU.WaitingForInterrupt)
246
-				{
247
-					CPU.WaitingForInterrupt = false;
248
-					++Registers.PC.W.xPC;
249
-				}
94
+			S9xUpdateIRQPositions(false);
95
+			CPU.IRQLine = true;
96
+		}
250 97
 
251
-				CPU.IRQTransition = false;
252
-				CPU.IRQPending = Timings.IRQPendCount;
98
+		if (CPU.IRQLine)
99
+		{
100
+			if (CPU.WaitingForInterrupt)
101
+			{
102
+				CPU.WaitingForInterrupt = false;
103
+				++Registers.PC.W.xPC;
104
+				CPU.Cycles += TWO_CYCLES + ONE_DOT_CYCLE / 2;
105
+				while (CPU.Cycles >= CPU.NextEvent)
106
+					S9xDoHEventProcessing();
107
+			}
253 108
 
254
-				if (!CheckFlag(IRQ))
255
-					S9xOpcode_IRQ();
109
+			if (!CheckFlag(IRQ))
110
+			{
111
+				/* The flag pushed onto the stack is the new value */
112
+				CHECK_FOR_IRQ_CHANGE();
113
+				S9xOpcode_IRQ();
256 114
 			}
257 115
 		}
258 116
 
117
+		CHECK_FOR_IRQ_CHANGE();
118
+
259 119
 		if (CPU.Flags & SCAN_KEYS_FLAG)
260 120
 			break;
261 121
 
... ...
@@ -265,9 +125,7 @@ void S9xMainLoop()
265 125
 		if (CPU.PCBase)
266 126
 		{
267 127
 			Op = CPU.PCBase[Registers.PC.W.xPC];
268
-			CPU.PrevCycles = CPU.Cycles;
269 128
 			CPU.Cycles += CPU.MemSpeed;
270
-			S9xCheckInterrupts();
271 129
 			Opcodes = ICPU.S9xOpcodes;
272 130
 		}
273 131
 		else
... ...
@@ -281,7 +139,7 @@ void S9xMainLoop()
281 139
 		{
282 140
 			uint8_t *oldPCBase = CPU.PCBase;
283 141
 
284
-			CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + (static_cast<uint16_t>(Registers.PC.W.xPC + 4)));
142
+			CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + static_cast<uint16_t>(Registers.PC.W.xPC + 4));
285 143
 			if (oldPCBase != CPU.PCBase || (Registers.PC.W.xPC & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
286 144
 				Opcodes = S9xOpcodesSlow;
287 145
 		}
... ...
@@ -291,9 +149,6 @@ void S9xMainLoop()
291 149
 	}
292 150
 
293 151
 	S9xPackStatus();
294
-
295
-	if (CPU.Flags & SCAN_KEYS_FLAG)
296
-		CPU.Flags &= ~SCAN_KEYS_FLAG;
297 152
 }
298 153
 
299 154
 void S9xDoHEventProcessing()
... ...
@@ -315,11 +170,11 @@ void S9xDoHEventProcessing()
315 170
 		case HC_HCOUNTER_MAX_EVENT:
316 171
 			S9xAPUEndScanline();
317 172
 			CPU.Cycles -= Timings.H_Max;
318
-			CPU.PrevCycles -= Timings.H_Max;
319
-			S9xAPUSetReferenceTime(CPU.Cycles);
320
-
321
-			if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
173
+			if (Timings.NMITriggerPos != 0xffff)
322 174
 				Timings.NMITriggerPos -= Timings.H_Max;
175
+			if (Timings.NextIRQTimer != 0x0fffffff)
176
+				Timings.NextIRQTimer -= Timings.H_Max;
177
+			S9xAPUSetReferenceTime(CPU.Cycles);
323 178
 
324 179
 			++CPU.V_Counter;
325 180
 			if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
... ...
@@ -343,10 +198,6 @@ void S9xDoHEventProcessing()
343 198
 
344 199
 				// FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles.
345 200
 				Memory.FillRAM[0x4210] = Model->_5A22;
346
-				CPU.NMILine = false;
347
-				Timings.NMITriggerPos = 0xffff;
348
-
349
-				CPU.Flags |= SCAN_KEYS_FLAG;
350 201
 			}
351 202
 
352 203
 			// From byuu:
... ...
@@ -375,6 +226,8 @@ void S9xDoHEventProcessing()
375 226
 
376 227
 			if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
377 228
 			{
229
+				CPU.Flags |= SCAN_KEYS_FLAG;
230
+
378 231
 				PPU.HDMA = 0;
379 232
 				// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
380 233
 				PPU.ForcedBlanking = !!((Memory.FillRAM[0x2100] >> 7) & 1);
... ...
@@ -399,7 +252,7 @@ void S9xDoHEventProcessing()
399 252
 				{
400 253
 					// FIXME: triggered at HC=6, checked just before the final CPU cycle,
401 254
 					// then, when to call S9xOpcode_NMI()?
402
-					CPU.NMILine = true;
255
+					CPU.NMIPending = true;
403 256
 					Timings.NMITriggerPos = 6 + 6;
404 257
 				}
405 258
 			}
... ...
@@ -422,9 +275,7 @@ void S9xDoHEventProcessing()
422 275
 			break;
423 276
 
424 277
 		case HC_WRAM_REFRESH_EVENT:
425
-			CPU.PrevCycles = CPU.Cycles;
426 278
 			CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
427
-			S9xCheckInterrupts();
428 279
 
429 280
 			S9xReschedule();
430 281
 	}
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -263,36 +92,3 @@ inline void S9xFixCycles()
263 92
 		}
264 93
 	}
265 94
 }
266
-
267
-inline void S9xCheckInterrupts()
268
-{
269
-	bool thisIRQ = PPU.HTimerEnabled || PPU.VTimerEnabled;
270
-
271
-	if (CPU.IRQLine && thisIRQ)
272
-		CPU.IRQTransition = true;
273
-
274
-	if (PPU.HTimerEnabled)
275
-	{
276
-		int32_t htimepos = PPU.HTimerPosition;
277
-		if (CPU.Cycles >= Timings.H_Max)
278
-			htimepos += Timings.H_Max;
279
-
280
-		if (CPU.PrevCycles >= htimepos || CPU.Cycles < htimepos)
281
-			thisIRQ = false;
282
-	}
283
-
284
-	if (PPU.VTimerEnabled)
285
-	{
286
-		int32_t vcounter = CPU.V_Counter;
287
-		if (CPU.Cycles >= Timings.H_Max)
288
-			++vcounter;
289
-
290
-		if (vcounter != PPU.VTimerPosition)
291
-			thisIRQ = false;
292
-	}
293
-
294
-	if (!CPU.IRQLastState && thisIRQ)
295
-		CPU.IRQLine = true;
296
-
297
-	CPU.IRQLastState = thisIRQ;
298
-}
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -291,57 +120,39 @@ inline void ADC16(uint16_t Work16)
291 120
 {
292 121
 	if (CheckDecimal())
293 122
 	{
294
-		uint16_t A1 = Registers.A.W & 0x000F;
295
-		uint16_t A2 = Registers.A.W & 0x00F0;
296
-		uint16_t A3 = Registers.A.W & 0x0F00;
297
-		uint32_t A4 = Registers.A.W & 0xF000;
298
-		uint16_t W1 = Work16 & 0x000F;
299
-		uint16_t W2 = Work16 & 0x00F0;
300
-		uint16_t W3 = Work16 & 0x0F00;
301
-		uint16_t W4 = Work16 & 0xF000;
302
-
303
-		A1 += W1 + CheckCarry();
304
-		if (A1 > 0x0009)
305
-		{
306
-			A1 -= 0x000A;
307
-			A1 &= 0x000F;
308
-			A2 += 0x0010;
309
-		}
310
-
311
-		A2 += W2;
312
-		if (A2 > 0x0090)
313
-		{
314
-			A2 -= 0x00A0;
315
-			A2 &= 0x00F0;
316
-			A3 += 0x0100;
317
-		}
318
-
319
-		A3 += W3;
320
-		if (A3 > 0x0900)
321
-		{
322
-			A3 -= 0x0A00;
323
-			A3 &= 0x0F00;
324
-			A4 += 0x1000;
325
-		}
326
-
327
-		A4 += W4;
328
-		if (A4 > 0x9000)
329
-		{
330
-			A4 -= 0xA000;
331
-			A4 &= 0xF000;
332
-			SetCarry();
333
-		}
334
-		else
335
-			ClearCarry();
123
+		uint32_t carry = CheckCarry();
124
+
125
+		uint32_t result = (Registers.A.W & 0x000F) + (Work16 & 0x000F) + carry;
126
+		if (result > 0x0009)
127
+			result += 0x0006;
128
+		carry = result > 0x000F;
129
+
130
+		result = (Registers.A.W & 0x00F0) + (Work16 & 0x00F0) + (result & 0x000F) + carry * 0x10;
131
+		if (result > 0x009F)
132
+			result += 0x0060;
133
+		carry = result > 0x00FF;
336 134
 
337
-		uint16_t Ans16 = A4 | A3 | A2 | A1;
135
+		result = (Registers.A.W & 0x0F00) + (Work16 & 0x0F00) + (result & 0x00FF) + carry * 0x100;
136
+		if (result > 0x09FF)
137
+			result += 0x0600;
138
+		carry = result > 0x0FFF;
338 139
 
339
-		if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000)
140
+		result = (Registers.A.W & 0xF000) + (Work16 & 0xF000) + (result & 0x0FFF) + carry * 0x1000;
141
+
142
+		if ((Registers.A.W & 0x8000) == (Work16 & 0x8000) && (Registers.A.W & 0x8000) != (result & 0x8000))
340 143
 			SetOverflow();
341 144
 		else
342 145
 			ClearOverflow();
343 146
 
344
-		Registers.A.W = Ans16;
147
+		if (result > 0x9FFF)
148
+			result += 0x6000;
149
+
150
+		if (result > 0xFFFF)
151
+			SetCarry();
152
+		else
153
+			ClearCarry();
154
+
155
+		Registers.A.W = result & 0xFFFF;
345 156
 		SetZN(Registers.A.W);
346 157
 	}
347 158
 	else
... ...
@@ -364,37 +175,29 @@ inline void ADC8(uint8_t Work8)
364 175
 {
365 176
 	if (CheckDecimal())
366 177
 	{
367
-		uint8_t A1 = Registers.A.W & 0x0F;
368
-		uint16_t A2 = Registers.A.W & 0xF0;
369
-		uint8_t W1 = Work8 & 0x0F;
370
-		uint8_t W2 = Work8 & 0xF0;
371
-
372
-		A1 += W1 + CheckCarry();
373
-		if (A1 > 0x09)
374
-		{
375
-			A1 -= 0x0A;
376
-			A1 &= 0x0F;
377
-			A2 += 0x10;
378
-		}
379
-
380
-		A2 += W2;
381
-		if (A2 > 0x90)
382
-		{
383
-			A2 -= 0xA0;
384
-			A2 &= 0xF0;
385
-			SetCarry();
386
-		}
387
-		else
388
-			ClearCarry();
178
+		uint32_t carry = CheckCarry();
389 179
 
390
-		uint8_t Ans8 = A2 | A1;
180
+		uint32_t result = (Registers.A.B.l & 0x0F) + (Work8 & 0x0F) + carry;
181
+		if (result > 0x09)
182
+			result += 0x06;
183
+		carry = result > 0x0F;
391 184
 
392
-		if (~(Registers.A.B.l ^ Work8) & (Work8 ^ Ans8) & 0x80)
185
+		result = (Registers.A.B.l & 0xF0) + (Work8 & 0xF0) + (result & 0x0F) + (carry * 0x10);
186
+
187
+		if ((Registers.A.B.l & 0x80) == (Work8 & 0x80) && (Registers.A.B.l & 0x80) != (result & 0x80))
393 188
 			SetOverflow();
394 189
 		else
395 190
 			ClearOverflow();
396 191
 
397
-		Registers.A.B.l = Ans8;
192
+		if (result > 0x9F)
193
+			result += 0x60;
194
+
195
+		if (result > 0xFF)
196
+			SetCarry();
197
+		else
198
+			ClearCarry();
199
+
200
+		Registers.A.B.l = result & 0xFF;
398 201
 		SetZN(Registers.A.B.l);
399 202
 	}
400 203
 	else
... ...
@@ -667,58 +470,41 @@ inline void SBC16(uint16_t Work16)
667 470
 {
668 471
 	if (CheckDecimal())
669 472
 	{
670
-		uint16_t A1 = Registers.A.W & 0x000F;
671
-		uint16_t A2 = Registers.A.W & 0x00F0;
672
-		uint16_t A3 = Registers.A.W & 0x0F00;
673
-		uint32_t A4 = Registers.A.W & 0xF000;
674
-		uint16_t W1 = Work16 & 0x000F;
675
-		uint16_t W2 = Work16 & 0x00F0;
676
-		uint16_t W3 = Work16 & 0x0F00;
677
-		uint16_t W4 = Work16 & 0xF000;
678
-
679
-		A1 -= W1 + !CheckCarry();
680
-		A2 -= W2;
681
-		A3 -= W3;
682
-		A4 -= W4;
683
-
684
-		if (A1 > 0x000F)
685
-		{
686
-			A1 += 0x000A;
687
-			A1 &= 0x000F;
688
-			A2 -= 0x0010;
689
-		}
690
-
691
-		if (A2 > 0x00F0)
692
-		{
693
-			A2 += 0x00A0;
694
-			A2 &= 0x00F0;
695
-			A3 -= 0x0100;
696
-		}
697
-
698
-		if (A3 > 0x0F00)
699
-		{
700
-			A3 += 0x0A00;
701
-			A3 &= 0x0F00;
702
-			A4 -= 0x1000;
703
-		}
704
-
705
-		if (A4 > 0xF000)
706
-		{
707
-			A4 += 0xA000;
708
-			A4 &= 0xF000;
709
-			ClearCarry();
710
-		}
711
-		else
712
-			SetCarry();
473
+		int carry = CheckCarry();
474
+
475
+		Work16 ^= 0xFFFF;
476
+
477
+		int result = (Registers.A.W & 0x000F) + (Work16 & 0x000F) + carry;
478
+		if (result < 0x0010)
479
+			result -= 0x0006;
480
+		carry = result > 0x000F;
481
+
482
+		result = (Registers.A.W & 0x00F0) + (Work16 & 0x00F0) + (result & 0x000F) + carry * 0x10;
483
+		if (result < 0x0100)
484
+			result -= 0x0060;
485
+		carry = result > 0x00FF;
713 486
 
714
-		uint16_t Ans16 = A4 | A3 | A2 | A1;
487
+		result = (Registers.A.W & 0x0F00) + (Work16 & 0x0F00) + (result & 0x00FF) + carry * 0x100;
488
+		if (result < 0x1000)
489
+			result -= 0x0600;
490
+		carry = result > 0x0FFF;
715 491
 
716
-		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000)
492
+		result = (Registers.A.W & 0xF000) + (Work16 & 0xF000) + (result & 0x0FFF) + carry * 0x1000;
493
+
494
+		if (!((Registers.A.W ^ Work16) & 0x8000) && ((Registers.A.W ^ result) & 0x8000))
717 495
 			SetOverflow();
718 496
 		else
719 497
 			ClearOverflow();
720 498
 
721
-		Registers.A.W = Ans16;
499
+		if (result < 0x10000)
500
+			result -= 0x6000;
501
+
502
+		if (result > 0xFFFF)
503
+			SetCarry();
504
+		else
505
+			ClearCarry();
506
+
507
+		Registers.A.W = result & 0xFFFF;
722 508
 		SetZN(Registers.A.W);
723 509
 	}
724 510
 	else
... ...
@@ -741,38 +527,31 @@ inline void SBC8(uint8_t Work8)
741 527
 {
742 528
 	if (CheckDecimal())
743 529
 	{
744
-		uint8_t A1 = Registers.A.W & 0x0F;
745
-		uint16_t A2 = Registers.A.W & 0xF0;
746
-		uint8_t W1 = Work8 & 0x0F;
747
-		uint8_t W2 = Work8 & 0xF0;
748
-
749
-		A1 -= W1 + !CheckCarry();
750
-		A2 -= W2;
751
-
752
-		if (A1 > 0x0F)
753
-		{
754
-			A1 += 0x0A;
755
-			A1 &= 0x0F;
756
-			A2 -= 0x10;
757
-		}
758
-
759
-		if (A2 > 0xF0)
760
-		{
761
-			A2 += 0xA0;
762
-			A2 &= 0xF0;
763
-			ClearCarry();
764
-		}
765
-		else
766
-			SetCarry();
530
+		int carry = CheckCarry();
531
+
532
+		Work8 ^= 0xFF;
767 533
 
768
-		uint8_t Ans8 = A2 | A1;
534
+		int result = (Registers.A.B.l & 0x0F) + (Work8 & 0x0F) + carry;
535
+		if (result < 0x10)
536
+			result -= 0x06;
537
+		carry = (result > 0x0F);
769 538
 
770
-		if ((Registers.A.B.l ^ Work8) & (Registers.A.B.l ^ Ans8) & 0x80)
539
+		result = (Registers.A.B.l & 0xF0) + (Work8 & 0xF0) + (result & 0x0F) + carry * 0x10;
540
+
541
+		if ((Registers.A.B.l & 0x80) == (Work8 & 0x80) && (Registers.A.B.l & 0x80) != (result & 0x80))
771 542
 			SetOverflow();
772 543
 		else
773 544
 			ClearOverflow();
774 545
 
775
-		Registers.A.B.l = Ans8;
546
+		if (result < 0x100)
547
+			result -= 0x60;
548
+
549
+		if (result > 0xFF)
550
+			SetCarry();
551
+		else
552
+			ClearCarry();
553
+
554
+		Registers.A.B.l = result & 0xFF;
776 555
 		SetZN(Registers.A.B.l);
777 556
 	}
778 557
 	else
... ...
@@ -1,185 +1,14 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include "snes9x.h"
179 8
 #include "memmap.h"
180 9
 #include "apu/apu.h"
181 10
 
182
-static inline void AddCycles(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
11
+static inline void AddCycles(int32_t n) { CPU.Cycles += n; while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
183 12
 
184 13
 #include "cpuaddr.h"
185 14
 #include "cpuops.h"
... ...
@@ -1537,15 +1366,17 @@ static void OpF8()
1537 1366
 // CLI
1538 1367
 static void Op58()
1539 1368
 {
1540
-	ClearIRQ();
1541 1369
 	AddCycles(ONE_CYCLE);
1370
+
1371
+	Timings.IRQFlagChanging |= IRQ_CLEAR_FLAG;
1542 1372
 }
1543 1373
 
1544 1374
 // SEI
1545 1375
 static void Op78()
1546 1376
 {
1547
-	SetIRQ();
1548 1377
 	AddCycles(ONE_CYCLE);
1378
+
1379
+	Timings.IRQFlagChanging |= IRQ_SET_FLAG;
1549 1380
 }
1550 1381
 
1551 1382
 // CLV
... ...
@@ -2843,8 +2674,9 @@ static void Op40Slow()
2843 2674
 static void OpCB()
2844 2675
 {
2845 2676
 	CPU.WaitingForInterrupt = true;
2677
+
2846 2678
 	--Registers.PC.W.xPC;
2847
-	AddCycles(TWO_CYCLES);
2679
+	AddCycles(ONE_CYCLE);
2848 2680
 }
2849 2681
 
2850 2682
 // STP
... ...
@@ -1,186 +1,15 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include "snes9x.h"
179 8
 #include "memmap.h"
180 9
 #include "dma.h"
181 10
 #include "apu/apu.h"
182 11
 
183
-static inline void ADD_CYCLES(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); }
12
+static inline void ADD_CYCLES(int32_t n) { CPU.Cycles += n; }
184 13
 
185 14
 extern uint8_t *HDMAMemPointers[8];
186 15
 extern int HDMA_ModeByteCounts[8];
... ...
@@ -365,7 +194,7 @@ bool S9xDoDMA(uint8_t Channel)
365 194
 							if (!UPDATE_COUNTERS())
366 195
 								return false;
367 196
 							--count;
368
-
197
+						// Fall through
369 198
 						case 1:
370 199
 							Work = S9xGetByte((d->ABank << 16) + p);
371 200
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -402,7 +231,7 @@ bool S9xDoDMA(uint8_t Channel)
402 231
 								b = 1;
403 232
 								break;
404 233
 							}
405
-
234
+						// Fall through
406 235
 						case 1:
407 236
 							Work = S9xGetByte((d->ABank << 16) + p);
408 237
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
... ...
@@ -413,7 +242,7 @@ bool S9xDoDMA(uint8_t Channel)
413 242
 								b = 2;
414 243
 								break;
415 244
 							}
416
-
245
+						// Fall through
417 246
 						case 2:
418 247
 							Work = S9xGetByte((d->ABank << 16) + p);
419 248
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -424,7 +253,7 @@ bool S9xDoDMA(uint8_t Channel)
424 253
 								b = 3;
425 254
 								break;
426 255
 							}
427
-
256
+						// Fall through
428 257
 						case 3:
429 258
 							Work = S9xGetByte((d->ABank << 16) + p);
430 259
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -454,7 +283,7 @@ bool S9xDoDMA(uint8_t Channel)
454 283
 								b = 1;
455 284
 								break;
456 285
 							}
457
-
286
+						// Fall through
458 287
 						case 1:
459 288
 							Work = S9xGetByte((d->ABank << 16) + p);
460 289
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -465,7 +294,7 @@ bool S9xDoDMA(uint8_t Channel)
465 294
 								b = 2;
466 295
 								break;
467 296
 							}
468
-
297
+						// Fall through
469 298
 						case 2:
470 299
 							Work = S9xGetByte((d->ABank << 16) + p);
471 300
 							S9xSetPPU(Work, 0x2102 + d->BAddress);
... ...
@@ -476,7 +305,7 @@ bool S9xDoDMA(uint8_t Channel)
476 305
 								b = 3;
477 306
 								break;
478 307
 							}
479
-
308
+						// Fall through
480 309
 						case 3:
481 310
 							Work = S9xGetByte((d->ABank << 16) + p);
482 311
 							S9xSetPPU(Work, 0x2103 + d->BAddress);
... ...
@@ -618,10 +447,10 @@ bool S9xDoDMA(uint8_t Channel)
618 447
 									if (!UPDATE_COUNTERS())
619 448
 										return false;
620 449
 									--count;
621
-
450
+								// Fall through
622 451
 								case 1:
623
-									Work = *(base + p);
624
-									REGISTER_2119_linear(Work);
452
+									OpenBus = *(base + p);
453
+									REGISTER_2119_linear(OpenBus);
625 454
 									if (!UPDATE_COUNTERS())
626 455
 										return false;
627 456
 									--count;
... ...
@@ -651,7 +480,7 @@ bool S9xDoDMA(uint8_t Channel)
651 480
 									if (!UPDATE_COUNTERS())
652 481
 										return false;
653 482
 									--count;
654
-
483
+								// Fall through
655 484
 								case 1:
656 485
 									Work = *(base + p);
657 486
 									REGISTER_2119_tile(Work);
... ...
@@ -686,7 +515,7 @@ bool S9xDoDMA(uint8_t Channel)
686 515
 								if (!UPDATE_COUNTERS())
687 516
 									return false;
688 517
 								--count;
689
-
518
+							// Fall through
690 519
 							case 1:
691 520
 								Work = *(base + p);
692 521
 								S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -724,7 +553,7 @@ bool S9xDoDMA(uint8_t Channel)
724 553
 								b = 1;
725 554
 								break;
726 555
 							}
727
-
556
+						// Fall through
728 557
 						case 1:
729 558
 							Work = *(base + p);
730 559
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
... ...
@@ -735,7 +564,7 @@ bool S9xDoDMA(uint8_t Channel)
735 564
 								b = 2;
736 565
 								break;
737 566
 							}
738
-
567
+						// Fall through
739 568
 						case 2:
740 569
 							Work = *(base + p);
741 570
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -746,7 +575,7 @@ bool S9xDoDMA(uint8_t Channel)
746 575
 								b = 3;
747 576
 								break;
748 577
 							}
749
-
578
+						// Fall through
750 579
 						case 3:
751 580
 							Work = *(base + p);
752 581
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -776,7 +605,7 @@ bool S9xDoDMA(uint8_t Channel)
776 605
 								b = 1;
777 606
 								break;
778 607
 							}
779
-
608
+						// Fall through
780 609
 						case 1:
781 610
 							Work = *(base + p);
782 611
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
... ...
@@ -787,7 +616,7 @@ bool S9xDoDMA(uint8_t Channel)
787 616
 								b = 2;
788 617
 								break;
789 618
 							}
790
-
619
+						// Fall through
791 620
 						case 2:
792 621
 							Work = *(base + p);
793 622
 							S9xSetPPU(Work, 0x2102 + d->BAddress);
... ...
@@ -798,7 +627,7 @@ bool S9xDoDMA(uint8_t Channel)
798 627
 								b = 3;
799 628
 								break;
800 629
 							}
801
-
630
+						// Fall through
802 631
 						case 3:
803 632
 							Work = *(base + p);
804 633
 							S9xSetPPU(Work, 0x2103 + d->BAddress);
... ...
@@ -1066,12 +895,8 @@ bool S9xDoDMA(uint8_t Channel)
1066 895
 		}
1067 896
 	}
1068 897
 
1069
-	if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff))
1070
-	{
898
+	if (CPU.NMIPending && Timings.NMITriggerPos != 0xffff)
1071 899
 		Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay;
1072
-		if (Timings.NMITriggerPos >= Timings.H_Max)
1073
-			Timings.NMITriggerPos -= Timings.H_Max;
1074
-	}
1075 900
 
1076 901
 	CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false;
1077 902
 	CPU.CurrentDMAorHDMAChannel = -1;
... ...
@@ -1176,9 +1001,10 @@ void S9xStartHDMA()
1176 1001
 
1177 1002
 uint8_t S9xDoHDMA(uint8_t byte)
1178 1003
 {
1179
-	SDMA *p = &DMA[0];
1004
+	SDMA *p;
1180 1005
 
1181
-	int d = 0;
1006
+	int d;
1007
+	uint8_t mask;
1182 1008
 
1183 1009
 	CPU.InHDMA = CPU.InDMAorHDMA = true;
1184 1010
 	CPU.HDMARanInDMA = CPU.InDMA ? byte : 0;
... ...
@@ -1188,7 +1014,7 @@ uint8_t S9xDoHDMA(uint8_t byte)
1188 1014
 	// XXX: Not quite right...
1189 1015
 	ADD_CYCLES(Timings.DMACPUSync);
1190 1016
 
1191
-	for (uint8_t mask = 1; mask; mask <<= 1, ++p, ++d)
1017
+	for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, ++p, ++d)
1192 1018
 	{
1193 1019
 		if (byte & mask)
1194 1020
 		{
... ...
@@ -1374,7 +1200,10 @@ uint8_t S9xDoHDMA(uint8_t byte)
1374 1200
 								case 1:
1375 1201
 									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
1376 1202
 									ADD_CYCLES(SLOW_ONE_CYCLE);
1377
-									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
1203
+									// XXX: All HDMA should read to MDR first. This one just
1204
+									// happens to fix Speedy Gonzales.
1205
+									OpenBus = *(HDMAMemPointers[d] + 1);
1206
+									S9xSetPPU(OpenBus, 0x2101 + p->BAddress);
1378 1207
 									ADD_CYCLES(SLOW_ONE_CYCLE);
1379 1208
 									HDMAMemPointers[d] += 2;
1380 1209
 									break;
... ...
@@ -1484,7 +1313,16 @@ uint8_t S9xDoHDMA(uint8_t byte)
1484 1313
 							ADD_CYCLES(SLOW_ONE_CYCLE);
1485 1314
 					}
1486 1315
 				}
1316
+			}
1317
+		}
1318
+	}
1487 1319
 
1320
+	for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, ++p, ++d)
1321
+	{
1322
+		if (byte & mask)
1323
+		{
1324
+			if (p->DoTransfer)
1325
+			{
1488 1326
 				if (p->HDMAIndirectAddressing)
1489 1327
 					p->DMACount_Or_HDMAIndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
1490 1328
 				else
... ...
@@ -1500,7 +1338,6 @@ uint8_t S9xDoHDMA(uint8_t byte)
1500 1338
 					byte &= ~mask;
1501 1339
 					PPU.HDMAEnded |= mask;
1502 1340
 					p->DoTransfer = false;
1503
-					continue;
1504 1341
 				}
1505 1342
 			}
1506 1343
 			else
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -183,9 +12,7 @@ inline void addCyclesInMemoryAccess(int32_t speed)
183 12
 {
184 13
 	if (!CPU.InDMAorHDMA)
185 14
 	{
186
-		CPU.PrevCycles = CPU.Cycles;
187 15
 		CPU.Cycles += speed;
188
-		S9xCheckInterrupts();
189 16
 		while (CPU.Cycles >= CPU.NextEvent)
190 17
 			S9xDoHEventProcessing();
191 18
 	}
... ...
@@ -195,9 +22,7 @@ inline void addCyclesInMemoryAccess_x2(int32_t speed)
195 22
 {
196 23
 	if (!CPU.InDMAorHDMA)
197 24
 	{
198
-		CPU.PrevCycles = CPU.Cycles;
199 25
 		CPU.Cycles += speed << 1;
200
-		S9xCheckInterrupts();
201 26
 		while (CPU.Cycles >= CPU.NextEvent)
202 27
 			S9xDoHEventProcessing();
203 28
 	}
... ...
@@ -278,34 +103,35 @@ inline uint8_t S9xGetByte(uint32_t Address)
278 103
 
279 104
 inline uint16_t S9xGetWord(uint32_t Address, s9xwrap_t w = WRAP_NONE)
280 105
 {
106
+	uint16_t word;
107
+
281 108
 	uint32_t mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
282 109
 	if ((Address & mask) == mask)
283 110
 	{
284 111
 		PC_t a;
285 112
 
286
-		OpenBus = S9xGetByte(Address);
113
+		word = OpenBus = S9xGetByte(Address);
287 114
 
288 115
 		switch (w)
289 116
 		{
290 117
 			case WRAP_PAGE:
291 118
 				a.xPBPC = Address;
292 119
 				++a.B.xPCl;
293
-				return OpenBus | (S9xGetByte(a.xPBPC) << 8);
120
+				return word | (S9xGetByte(a.xPBPC) << 8);
294 121
 
295 122
 			case WRAP_BANK:
296 123
 				a.xPBPC = Address;
297 124
 				++a.W.xPC;
298
-				return OpenBus | (S9xGetByte(a.xPBPC) << 8);
125
+				return word | (S9xGetByte(a.xPBPC) << 8);
299 126
 
300 127
 			default:
301
-				return OpenBus | (S9xGetByte(Address + 1) << 8);
128
+				return word | (S9xGetByte(Address + 1) << 8);
302 129
 		}
303 130
 	}
304 131
 
305 132
 	int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
306 133
 	uint8_t *GetAddress = Memory.Map[block];
307 134
 	int32_t speed = memory_speed(Address);
308
-	uint16_t word;
309 135
 
310 136
 	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
311 137
 	{
... ...
@@ -326,8 +152,8 @@ inline uint16_t S9xGetWord(uint32_t Address, s9xwrap_t w = WRAP_NONE)
326 152
 		case CMemory::MAP_PPU:
327 153
 			if (CPU.InDMAorHDMA)
328 154
 			{
329
-				OpenBus = S9xGetByte(Address);
330
-				return OpenBus | (S9xGetByte(Address + 1) << 8);
155
+				word = OpenBus = S9xGetByte(Address);
156
+				return word | (S9xGetByte(Address + 1) << 8);
331 157
 			}
332 158
 
333 159
 			word  = S9xGetPPU(Address & 0xffff);
... ...
@@ -550,8 +376,7 @@ inline void S9xSetPCBase(uint32_t Address)
550 376
 	Registers.PC.xPBPC = Address & 0xffffff;
551 377
 	ICPU.ShiftedPB = Address & 0xff0000;
552 378
 
553
-	int block;
554
-	uint8_t *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)];
379
+	uint8_t *GetAddress = Memory.Map[static_cast<int>((Address & 0xffffff) >> MEMMAP_SHIFT)];
555 380
 
556 381
 	CPU.MemSpeed = memory_speed(Address);
557 382
 	CPU.MemSpeedx2 = CPU.MemSpeed << 1;
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include "snes9x.h"
179 8
 #include "memmap.h"
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <vector>
179 8
 #include <algorithm>
... ...
@@ -358,13 +187,20 @@ int CMemory::ScoreLoROM(bool skip_header, int32_t romoff)
358 187
 	return score;
359 188
 }
360 189
 
361
-bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
190
+int CMemory::First512BytesCountZeroes() const
362 191
 {
363
-	int retry_count = 0;
192
+	const uint8_t *buf = ROM;
193
+	int zeroCount = 0;
194
+	for (int i = 0; i < 512; ++i)
195
+		if (buf[i] == 0)
196
+			++zeroCount;
197
+	return zeroCount;
198
+}
364 199
 
200
+bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
201
+{
365 202
 	std::fill_n(&this->ROM[0], static_cast<int>(MAX_ROM_SIZE), 0);
366 203
 
367
-again:
368 204
 	this->CalculatedSize = 0;
369 205
 	this->ExtendedFormat = NOPE;
370 206
 
... ...
@@ -378,8 +214,22 @@ again:
378 214
 
379 215
 	int hi_score = this->ScoreHiROM(false);
380 216
 	int lo_score = this->ScoreLoROM(false);
217
+	int score_nonheadered = std::max(hi_score, lo_score);
218
+	int score_headered = std::max(this->ScoreHiROM(TRUE), this->ScoreLoROM(TRUE));
219
+
220
+	bool size_is_likely_headered = !((totalFileSize - 512) & 0xFFFF);
221
+	if (size_is_likely_headered)
222
+		score_headered += 2;
223
+	else
224
+		score_headered -= 2;
225
+	if (this->First512BytesCountZeroes() >= 0x1E0)
226
+		score_headered += 2;
227
+	else
228
+		score_headered -= 2;
229
+
230
+	bool headered_score_highest = score_headered > score_nonheadered;
381 231
 
382
-	if (((hi_score > lo_score && this->ScoreHiROM(true) > hi_score) || (hi_score <= lo_score && this->ScoreLoROM(true) > lo_score)))
232
+	if (headered_score_highest)
383 233
 	{
384 234
 		std::copy_n(&this->ROM[512], totalFileSize - 512, &this->ROM[0]);
385 235
 		totalFileSize -= 512;
... ...
@@ -388,9 +238,11 @@ again:
388 238
 		lo_score = this->ScoreLoROM(false);
389 239
 	}
390 240
 
391
-	this->CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
241
+	this->CalculatedSize = ((totalFileSize + 0x1fff) / 0x2000) * 0x2000;
392 242
 
393 243
 	if (this->CalculatedSize > 0x400000 &&
244
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x3423 && // exclude SA-1
245
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x3523 &&
394 246
 		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4332 && // exclude S-DD1
395 247
 		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4532 &&
396 248
 		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF93a && // exclude SPC7110
... ...
@@ -496,11 +348,10 @@ again:
496 348
 		hi_score = this->ScoreHiROM(false);
497 349
 		lo_score = this->ScoreLoROM(false);
498 350
 
499
-		if (((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0))) && !retry_count)
351
+		if ((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0)))
500 352
 		{
501 353
 			Settings.ForceNotInterleaved = true;
502
-			++retry_count;
503
-			goto again;
354
+			return false;
504 355
 		}
505 356
 	}
506 357
 
... ...
@@ -661,7 +512,6 @@ void CMemory::InitROM()
661 512
 	   and the NMI handler, time enough for an instruction or two. */
662 513
 	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
663 514
 	Timings.NMIDMADelay = 24;
664
-	Timings.IRQPendCount = 0;
665 515
 
666 516
 	//// Hack games
667 517
 
... ...
@@ -765,7 +615,7 @@ void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint3
765 615
 		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
766 616
 		{
767 617
 			uint32_t p = (c << 4) | (i >> 12);
768
-			this->Map[p] = reinterpret_cast<uint8_t *>(index);
618
+			this->Map[p] = reinterpret_cast<uint8_t *>(static_cast<intptr_t>(index));
769 619
 			this->BlockIsROM[p] = false;
770 620
 			this->BlockIsRAM[p] = isRAM;
771 621
 		}
... ...
@@ -791,8 +641,13 @@ void CMemory::map_WRAM()
791 641
 
792 642
 void CMemory::map_LoROMSRAM()
793 643
 {
794
-	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
795
-	this->map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
644
+	if (!this->SRAMSize)
645
+		return;
646
+
647
+	uint32_t hi = this->SRAMSize > 5 ? 0x7fff : 0xffff;
648
+
649
+	this->map_index(0x70, 0x7d, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
650
+	this->map_index(0xf0, 0xff, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
796 651
 }
797 652
 
798 653
 void CMemory::map_HiROMSRAM()
... ...
@@ -857,7 +712,7 @@ void CMemory::Map_JumboLoROMMap()
857 712
 	this->map_System();
858 713
 
859 714
 	this->map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
860
-	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
715
+	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x600000, 0x600000);
861 716
 	this->map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
862 717
 	this->map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
863 718
 
... ...
@@ -909,10 +764,11 @@ void CMemory::Map_SDD1LoROMMap()
909 764
 	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
910 765
 	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
911 766
 
912
-	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
767
+	this->map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
913 768
 	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize, 0); // will be overwritten dynamically
914 769
 
915 770
 	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
771
+	this->map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
916 772
 
917 773
 	this->map_WRAM();
918 774
 
... ...
@@ -973,66 +829,22 @@ void CMemory::ApplyROMFixes()
973 829
 	//// APU timing hacks :(
974 830
 
975 831
 	Timings.APUSpeedup = 0;
976
-	Timings.APUAllowTimeOverflow = false;
977 832
 
978 833
 	if (!Settings.DisableGameSpecificHacks)
979 834
 	{
980
-		if (this->match_id("AVCJ")) // Rendering Ranger R2
981
-			Timings.APUSpeedup = 4;
982
-
983
-		if (this->match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki
984
-			this->match_id("JG  ") || // Illusion of Gaia
985
-			this->match_id("CQ  ") || // Stunt Race FX
986
-			this->match_na("SOULBLADER - 1") || // Soul Blader
987
-			this->match_na("SOULBLAZER - 1 USA") || // Soul Blazer
988
-			this->match_na("SLAP STICK 1 JPN") || // Slap Stick
989
-			this->match_id("E9 ") || // Robotrek
990
-			this->match_nn("ACTRAISER") || // Actraiser
991
-			this->match_nn("ActRaiser-2") || // Actraiser 2
992
-			this->match_id("AQT") || // Tenchi Souzou, Terranigma
993
-			this->match_id("ATV") || // Tales of Phantasia
994
-			this->match_id("ARF") || // Star Ocean
995
-			this->match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
996
-			this->match_id("A4B") || // Super Bomberman 4
997
-			this->match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban
998
-			this->match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban
999
-			this->match_id("APB") || // Super Bomberman - Panic Bomber W
1000
-			this->match_na("DARK KINGDOM") || // Dark Kingdom
1001
-			this->match_na("ZAN3 SFC") || // Zan III Spirits
1002
-			this->match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai
1003
-			this->match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta
1004
-			this->match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase
1005
-			this->match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing
1006
-			this->match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen
1007
-			this->match_na("MASTERS") || // Harukanaru Augusta 2 - Masters
1008
-			this->match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider
1009
-			this->match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou
1010
-			this->match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
1011
-			this->match_nn("SWORD WORLD SFC") || // Sword World SFC/2
1012
-			this->match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4
1013
-			this->match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master
1014
-			this->match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
1015
-			this->match_na("HEIWA Parlor!Mini8") || // Parlor mini 8
1016
-			this->match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
1017
-			Timings.APUSpeedup = 1;
1018
-
1019
-		if (this->match_na("EARTHWORM JIM 2") || // Earthworm Jim 2
1020
-			this->match_na("NBA Hangtime") || // NBA Hang Time
1021
-			this->match_na("MSPACMAN") || // Ms Pacman
1022
-			this->match_na("THE MASK") || // The Mask
1023
-			this->match_na("PRIMAL RAGE") || // Primal Rage
1024
-			this->match_na("DOOM TROOPERS")) // Doom Troopers
1025
-			Timings.APUAllowTimeOverflow = true;
835
+		//if (this->match_id("AVCJ")) // Rendering Ranger R2
836
+		//	Timings.APUSpeedup = 2;
837
+		if (this->match_na("CIRCUIT USA"))
838
+			Timings.APUSpeedup = 3;
1026 839
 	}
1027 840
 
1028 841
 	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
1029
-	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
1030 842
 
1031 843
 	//// Other timing hacks :(
1032 844
 
1033 845
 	Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
1034 846
 	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
1035
-	Timings.IRQTriggerCycles = 10;
847
+	Timings.IRQTriggerCycles = 14;
1036 848
 
1037 849
 	if (!Settings.DisableGameSpecificHacks)
1038 850
 	{
... ...
@@ -1040,17 +852,10 @@ void CMemory::ApplyROMFixes()
1040 852
 		// Some games need really severe delay timing...
1041 853
 		if (this->match_na("BATTLE GRANDPRIX")) // Battle Grandprix
1042 854
 			Timings.DMACPUSync = 20;
1043
-
1044
-		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
1045
-		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
1046
-		// If Snes9x jumps into the IRQ handler before escaping from the loop,
1047
-		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
1048
-		if (this->match_na("Aero the AcroBat 2"))
1049
-			Timings.IRQPendCount = 2;
1050
-
1051
-		// XXX: What's happening?
1052
-		if (this->match_na("X-MEN")) // Spider-Man and the X-Men
1053
-			Settings.BlockInvalidVRAMAccess = false;
855
+		else if (match_na("KORYU NO MIMI ENG")) // Koryu no Mimi translation by rpgone)
856
+			// An infinite loop reads $4210 and checks NMI flag. This only works if LDA instruction executes before the NMI triggers,
857
+			// which doesn't work very well with s9x's default DMA timing.
858
+			Timings.DMACPUSync = 20;
1054 859
 
1055 860
 		//// SRAM initial value
1056 861
 
... ...
@@ -1,189 +1,18 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
180 9
 #include <memory>
181 10
 #include <cstdint>
182 11
 
183
-const int32_t MEMMAP_BLOCK_SIZE = 0x1000;
184
-const size_t MEMMAP_NUM_BLOCKS = 0x1000000 / MEMMAP_BLOCK_SIZE;
185
-const uint32_t MEMMAP_SHIFT = 12;
186
-const uint32_t MEMMAP_MASK = MEMMAP_BLOCK_SIZE - 1;
12
+inline constexpr int32_t MEMMAP_BLOCK_SIZE = 0x1000;
13
+inline constexpr size_t MEMMAP_NUM_BLOCKS = 0x1000000 / MEMMAP_BLOCK_SIZE;
14
+inline constexpr uint32_t MEMMAP_SHIFT = 12;
15
+inline constexpr uint32_t MEMMAP_MASK = MEMMAP_BLOCK_SIZE - 1;
187 16
 
188 17
 struct CMemory
189 18
 {
... ...
@@ -245,6 +74,7 @@ struct CMemory
245 74
 
246 75
 	int ScoreHiROM(bool, int32_t romoff = 0);
247 76
 	int ScoreLoROM(bool, int32_t romoff = 0);
77
+	int First512BytesCountZeroes() const;
248 78
 	bool LoadROMSNSF(const uint8_t *, int32_t, const uint8_t *, int32_t);
249 79
 
250 80
 	char *Safe(const char *);
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -208,7 +37,7 @@
208 37
 # define strcasecmp stricmp
209 38
 #endif
210 39
 
211
-#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64)
40
+#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || (defined(__BYTE_ORDER__) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN__)
212 41
 # define LSB_FIRST
213 42
 # define FAST_LSB_WORD_ACCESS
214 43
 #else
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <algorithm>
179 8
 #include "snes9x.h"
... ...
@@ -184,26 +13,92 @@
184 13
 
185 14
 extern uint8_t *HDMAMemPointers[8];
186 15
 
187
-void S9xUpdateHVTimerPosition()
16
+static int CyclesUntilNext(int hc, int vc)
188 17
 {
189
-	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
190
-	if (Timings.H_Max == Timings.H_Max_Master) // 1364
18
+	int32_t total = 0;
19
+	int vpos = CPU.V_Counter;
20
+
21
+	if (vc - vpos > 0)
191 22
 	{
192
-		if (PPU.IRQHBeamPos > 322)
193
-			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
194
-		if (PPU.IRQHBeamPos > 326)
195
-			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
23
+		// It's still in this frame */
24
+		// Add number of lines
25
+		total += (vc - vpos) * Timings.H_Max_Master;
26
+		// If line 240 is in there and we're odd, subtract a dot
27
+		if (vpos <= 240 && vc > 240 && Timings.InterlaceField && !IPPU.Interlace)
28
+			total -= ONE_DOT_CYCLE;
196 29
 	}
30
+	else
31
+	{
32
+		if (vc == vpos && hc > CPU.Cycles)
33
+			return hc;
34
+
35
+		total += (Timings.V_Max - vpos) * Timings.H_Max_Master;
36
+		if (vpos <= 240 && Timings.InterlaceField && !IPPU.Interlace)
37
+			total -= ONE_DOT_CYCLE;
38
+
39
+		total += vc * Timings.H_Max_Master;
40
+		if (vc > 240 && !Timings.InterlaceField && !IPPU.Interlace)
41
+			total -= ONE_DOT_CYCLE;
42
+	}
43
+
44
+	total += hc;
45
+
46
+	return total;
47
+}
48
+
49
+void S9xUpdateIRQPositions(bool initial)
50
+{
51
+	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
52
+	PPU.HTimerPosition -= PPU.IRQHBeamPos ? 0 : ONE_DOT_CYCLE;
53
+	PPU.HTimerPosition += PPU.IRQHBeamPos > 322 ? (ONE_DOT_CYCLE / 2) : 0;
54
+	PPU.HTimerPosition += PPU.IRQHBeamPos > 326 ? (ONE_DOT_CYCLE / 2) : 0;
197 55
 
198 56
 	PPU.VTimerPosition = PPU.IRQVBeamPos;
199 57
 
200
-	if (PPU.HTimerPosition >= Timings.H_Max && PPU.IRQHBeamPos < 340)
58
+	if (PPU.VTimerEnabled && PPU.VTimerPosition >= Timings.V_Max + (IPPU.Interlace ? 1 : 0))
59
+		Timings.NextIRQTimer = 0x0fffffff;
60
+	else if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
61
+		Timings.NextIRQTimer = 0x0fffffff;
62
+	else if (PPU.HTimerEnabled && !PPU.VTimerEnabled)
201 63
 	{
202
-		PPU.HTimerPosition -= Timings.H_Max;
203
-		++PPU.VTimerPosition;
204
-		// FIXME
205
-		if (PPU.VTimerPosition >= Timings.V_Max)
206
-			PPU.VTimerPosition = 0;
64
+		int v_pos = CPU.V_Counter;
65
+
66
+		Timings.NextIRQTimer = PPU.HTimerPosition;
67
+		if (CPU.Cycles > Timings.NextIRQTimer - Timings.IRQTriggerCycles)
68
+		{
69
+			Timings.NextIRQTimer += Timings.H_Max;
70
+			++v_pos;
71
+		}
72
+
73
+		// Check for short dot scanline
74
+		if (v_pos == 240 && Timings.InterlaceField && !IPPU.Interlace)
75
+		{
76
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
77
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
78
+		}
79
+	}
80
+	else if (!PPU.HTimerEnabled && PPU.VTimerEnabled)
81
+	{
82
+		if (CPU.V_Counter == PPU.VTimerPosition && initial)
83
+			Timings.NextIRQTimer = CPU.Cycles + Timings.IRQTriggerCycles - ONE_DOT_CYCLE;
84
+		else
85
+			Timings.NextIRQTimer = CyclesUntilNext(Timings.IRQTriggerCycles - ONE_DOT_CYCLE, PPU.VTimerPosition);
86
+	}
87
+	else
88
+	{
89
+		Timings.NextIRQTimer = CyclesUntilNext(PPU.HTimerPosition, PPU.VTimerPosition);
90
+
91
+		// Check for short dot scanline
92
+		int field = Timings.InterlaceField;
93
+
94
+		if (PPU.VTimerPosition < CPU.V_Counter || (PPU.VTimerPosition == CPU.V_Counter && Timings.NextIRQTimer > Timings.H_Max))
95
+			field = !field;
96
+
97
+		if (PPU.VTimerPosition == 240 && field && !IPPU.Interlace)
98
+		{
99
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
100
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
101
+		}
207 102
 	}
208 103
 }
209 104
 
... ...
@@ -252,7 +147,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
252 147
 
253 148
 			case 0x2102: // OAMADDL
254 149
 				PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
255
-				PPU.OAMFlip = 2;
150
+				PPU.OAMFlip = 0;
256 151
 				PPU.SavedOAMAddr = PPU.OAMAddr;
257 152
 				if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
258 153
 					PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
... ...
@@ -281,7 +176,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
281 176
 
282 177
 			case 0x2105: // BGMODE
283 178
 				if (Byte != Memory.FillRAM[0x2105])
284
-					IPPU.Interlace = !!(Memory.FillRAM[0x2133] & 1);
179
+					IPPU.Interlace = 0;
285 180
 
286 181
 				break;
287 182
 
... ...
@@ -326,15 +221,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
326 221
 				PPU.VMA.Address &= 0xff00;
327 222
 				PPU.VMA.Address |= Byte;
328 223
 
329
-				if (PPU.VMA.FullGraphicCount)
330
-				{
331
-					uint32_t addr = PPU.VMA.Address;
332
-					uint32_t rem = addr & PPU.VMA.Mask1;
333
-					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
334
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
335
-				}
336
-				else
337
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
224
+				S9xUpdateVRAMReadBuffer();
338 225
 
339 226
 				break;
340 227
 
... ...
@@ -342,15 +229,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
342 229
 				PPU.VMA.Address &= 0x00ff;
343 230
 				PPU.VMA.Address |= Byte << 8;
344 231
 
345
-				if (PPU.VMA.FullGraphicCount)
346
-				{
347
-					uint32_t addr = PPU.VMA.Address;
348
-					uint32_t rem = addr & PPU.VMA.Mask1;
349
-					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
350
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
351
-				}
352
-				else
353
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
232
+				S9xUpdateVRAMReadBuffer();
354 233
 
355 234
 				break;
356 235
 
... ...
@@ -499,7 +378,7 @@ uint8_t S9xGetPPU(uint16_t Address)
499 378
 				return (PPU.OpenBus1 = Memory.FillRAM[Address]);
500 379
 
501 380
 			case 0x2137: // SLHV
502
-				return OpenBus;
381
+				return PPU.OpenBus1;
503 382
 
504 383
 			case 0x2138: // OAMDATAREAD
505 384
 				if (PPU.OAMAddr & 0x100)
... ...
@@ -531,36 +410,20 @@ uint8_t S9xGetPPU(uint16_t Address)
531 410
 				return (PPU.OpenBus1 = byte);
532 411
 
533 412
 			case 0x2139: // VMDATALREAD
534
-				byte = IPPU.VRAMReadBuffer & 0xff;
413
+				byte = PPU.VRAMReadBuffer & 0xff;
535 414
 				if (!PPU.VMA.High)
536 415
 				{
537
-					if (PPU.VMA.FullGraphicCount)
538
-					{
539
-						uint32_t addr = PPU.VMA.Address;
540
-						uint32_t rem = addr & PPU.VMA.Mask1;
541
-						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
542
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
543
-					}
544
-					else
545
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
416
+					S9xUpdateVRAMReadBuffer();
546 417
 
547 418
 					PPU.VMA.Address += PPU.VMA.Increment;
548 419
 				}
549 420
 				return (PPU.OpenBus1 = byte);
550 421
 
551 422
 			case 0x213a: // VMDATAHREAD
552
-				byte = (IPPU.VRAMReadBuffer >> 8) & 0xff;
423
+				byte = (PPU.VRAMReadBuffer >> 8) & 0xff;
553 424
 				if (PPU.VMA.High)
554 425
 				{
555
-					if (PPU.VMA.FullGraphicCount)
556
-					{
557
-						uint32_t addr = PPU.VMA.Address;
558
-						uint32_t rem = addr & PPU.VMA.Mask1;
559
-						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
560
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
561
-					}
562
-					else
563
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
426
+					S9xUpdateVRAMReadBuffer();
564 427
 
565 428
 					PPU.VMA.Address += PPU.VMA.Increment;
566 429
 				}
... ...
@@ -729,23 +592,24 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
729 592
 		switch (Address)
730 593
 		{
731 594
 			case 0x4200: // NMITIMEN
595
+				if (Byte == Memory.FillRAM[0x4200])
596
+					break;
597
+
732 598
 				PPU.VTimerEnabled = !!(Byte & 0x20);
733 599
 				PPU.HTimerEnabled = !!(Byte & 0x10);
734 600
 
735
-				if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
736
-					CPU.IRQTransition = true;
737
-
738
-				if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
601
+				if (!(Byte & 0x10) && !(Byte & 0x20))
739 602
 					CPU.IRQLine = CPU.IRQTransition = false;
740 603
 
604
+				if ((Byte & 0x30) != (Memory.FillRAM[0x4200] & 0x30))
605
+					// Only allow instantaneous IRQ if turning it completely on or off
606
+					S9xUpdateIRQPositions(!(Byte & 0x30) || !(Memory.FillRAM[0x4200] & 0x30));
607
+
741 608
 				// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
742 609
 				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && (Memory.FillRAM[0x4210] & 0x80))
743
-				{
744 610
 					// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
745 611
 					// then, when to call S9xOpcode_NMI()?
746
-					CPU.NMILine = true;
747
-					Timings.NMITriggerPos = CPU.Cycles + 12;
748
-				}
612
+					Timings.IRQFlagChanging |= IRQ_TRIGGER_NMI;
749 613
 
750 614
 				break;
751 615
 
... ...
@@ -779,28 +643,28 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
779 643
 				pos = PPU.IRQHBeamPos;
780 644
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
781 645
 				if (PPU.IRQHBeamPos != pos)
782
-					S9xUpdateHVTimerPosition();
646
+					S9xUpdateIRQPositions(false);
783 647
 				break;
784 648
 
785 649
 			case 0x4208: // HTIMEH
786 650
 				pos = PPU.IRQHBeamPos;
787 651
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
788 652
 				if (PPU.IRQHBeamPos != pos)
789
-					S9xUpdateHVTimerPosition();
653
+					S9xUpdateIRQPositions(false);
790 654
 				break;
791 655
 
792 656
 			case 0x4209: // VTIMEL
793 657
 				pos = PPU.IRQVBeamPos;
794 658
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
795 659
 				if (PPU.IRQVBeamPos != pos)
796
-					S9xUpdateHVTimerPosition();
660
+					S9xUpdateIRQPositions(true);
797 661
 				break;
798 662
 
799 663
 			case 0x420a: // VTIMEH
800 664
 				pos = PPU.IRQVBeamPos;
801 665
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
802 666
 				if (PPU.IRQVBeamPos != pos)
803
-					S9xUpdateHVTimerPosition();
667
+					S9xUpdateIRQPositions(true);
804 668
 				break;
805 669
 
806 670
 			case 0x420b: // MDMAEN
... ...
@@ -837,7 +701,11 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
837 701
 
838 702
 			case 0x420d: // MEMSEL
839 703
 				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
704
+				{
840 705
 					CPU.FastROMSpeed = Byte & 1 ? ONE_CYCLE : SLOW_ONE_CYCLE;
706
+					// we might currently be in FastROMSpeed region, S9xSetPCBase will update CPU.MemSpeed
707
+					S9xSetPCBase(Registers.PC.xPBPC);
708
+				}
841 709
 
842 710
 				break;
843 711
 
... ...
@@ -1021,7 +889,7 @@ void S9xSoftResetPPU()
1021 889
 
1022 890
 	PPU.OpenBus1 = PPU.OpenBus2 = 0;
1023 891
 
1024
-	IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
892
+	PPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
1025 893
 	IPPU.Interlace = false;
1026 894
 
1027 895
 	for (int c = 0; c < 0x8000; c += 0x100)
... ...
@@ -1033,4 +901,5 @@ void S9xSoftResetPPU()
1033 901
 	std::fill_n(&Memory.FillRAM[0x1000], 0x1000, 0);
1034 902
 
1035 903
 	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
904
+	Memory.FillRAM[0x2126] = Memory.FillRAM[0x2128] = 1;
1036 905
 }
... ...
@@ -1,183 +1,12 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
180
-const int32_t FIRST_VISIBLE_LINE = 1;
9
+inline constexpr int32_t FIRST_VISIBLE_LINE = 1;
181 10
 
182 11
 enum
183 12
 {
... ...
@@ -190,13 +19,12 @@ enum
190 19
 	TILE_4BIT_ODD
191 20
 };
192 21
 
193
-const size_t MAX_2BIT_TILES = 4096;
194
-const size_t MAX_4BIT_TILES = 2048;
195
-const size_t MAX_8BIT_TILES = 1024;
22
+inline constexpr size_t MAX_2BIT_TILES = 4096;
23
+inline constexpr size_t MAX_4BIT_TILES = 2048;
24
+inline constexpr size_t MAX_8BIT_TILES = 1024;
196 25
 
197 26
 struct InternalPPU
198 27
 {
199
-	uint16_t VRAMReadBuffer;
200 28
 	bool Interlace;
201 29
 	uint32_t Red[256];
202 30
 	uint32_t Green[256];
... ...
@@ -255,6 +83,8 @@ struct SPPU
255 83
 
256 84
 	uint8_t OpenBus1;
257 85
 	uint8_t OpenBus2;
86
+
87
+	uint16_t VRAMReadBuffer;
258 88
 };
259 89
 
260 90
 extern uint16_t SignExtend[2];
... ...
@@ -267,7 +97,7 @@ void S9xSetPPU(uint8_t, uint16_t);
267 97
 uint8_t S9xGetPPU(uint16_t);
268 98
 void S9xSetCPU(uint8_t, uint16_t);
269 99
 uint8_t S9xGetCPU(uint16_t);
270
-void S9xUpdateHVTimerPosition();
100
+void S9xUpdateIRQPositions(bool);
271 101
 
272 102
 #include "memmap.h"
273 103
 
... ...
@@ -281,30 +111,34 @@ struct SnesModel
281 111
 extern SnesModel *Model;
282 112
 extern SnesModel M1SNES;
283 113
 
114
+inline void S9xUpdateVRAMReadBuffer()
115
+{
116
+	if (PPU.VMA.FullGraphicCount)
117
+	{
118
+		uint32_t addr = PPU.VMA.Address;
119
+		uint32_t rem = addr & PPU.VMA.Mask1;
120
+		uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
121
+		PPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
122
+	}
123
+	else
124
+		PPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
125
+}
126
+
284 127
 inline void REGISTER_2104(uint8_t Byt)
285 128
 {
129
+	if (!(PPU.OAMFlip & 1))
130
+	{
131
+		PPU.OAMWriteRegister &= 0xff00;
132
+		PPU.OAMWriteRegister |= Byt;
133
+	}
134
+
286 135
 	if (PPU.OAMAddr & 0x100)
287 136
 	{
288 137
 		int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1);
289 138
 		if (Byt != PPU.OAMData[addr])
290 139
 			PPU.OAMData[addr] = Byt;
291
-
292
-		PPU.OAMFlip ^= 1;
293
-		if (!(PPU.OAMFlip & 1))
294
-		{
295
-			++PPU.OAMAddr;
296
-			PPU.OAMAddr &= 0x1ff;
297
-			if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
298
-				PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
299
-		}
300
-	}
301
-	else if (!(PPU.OAMFlip & 1))
302
-	{
303
-		PPU.OAMWriteRegister &= 0xff00;
304
-		PPU.OAMWriteRegister |= Byt;
305
-		PPU.OAMFlip |= 1;
306 140
 	}
307
-	else
141
+	else if (PPU.OAMFlip & 1)
308 142
 	{
309 143
 		PPU.OAMWriteRegister &= 0x00ff;
310 144
 		uint8_t lowbyte = static_cast<uint8_t>(PPU.OAMWriteRegister);
... ...
@@ -317,16 +151,29 @@ inline void REGISTER_2104(uint8_t Byt)
317 151
 			PPU.OAMData[addr] = lowbyte;
318 152
 			PPU.OAMData[addr + 1] = highbyte;
319 153
 		}
154
+	}
320 155
 
321
-		PPU.OAMFlip &= ~1;
156
+	PPU.OAMFlip ^= 1;
157
+	if (!(PPU.OAMFlip & 1))
158
+	{
322 159
 		++PPU.OAMAddr;
160
+		PPU.OAMAddr &= 0x1ff;
323 161
 		if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
324 162
 			PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
325 163
 	}
326 164
 }
327 165
 
328 166
 // This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :(
329
-inline bool CHECK_INBLANK() { return Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE; }
167
+inline bool CHECK_INBLANK()
168
+{
169
+	if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)
170
+	{
171
+		PPU.VMA.Address += !PPU.VMA.High ? PPU.VMA.Increment : 0;
172
+		return true;
173
+	}
174
+	else
175
+		return false;
176
+}
330 177
 
331 178
 inline void REGISTER_2118(uint8_t Byt)
332 179
 {
... ...
@@ -348,64 +195,64 @@ inline void REGISTER_2118(uint8_t Byt)
348 195
 		PPU.VMA.Address += PPU.VMA.Increment;
349 196
 }
350 197
 
351
-inline void REGISTER_2119(uint8_t Byt)
198
+inline void REGISTER_2118_tile(uint8_t Byt)
352 199
 {
353 200
 	if (CHECK_INBLANK())
354 201
 		return;
355 202
 
356
-	uint32_t address;
203
+	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
204
+	uint32_t address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
357 205
 
358
-	if (PPU.VMA.FullGraphicCount)
359
-	{
360
-		uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
361
-		address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff;
362
-		Memory.VRAM[address] = Byt;
363
-	}
364
-	else
365
-		Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byt;
206
+	Memory.VRAM[address] = Byt;
366 207
 
367
-	if (PPU.VMA.High)
208
+	if (!PPU.VMA.High)
368 209
 		PPU.VMA.Address += PPU.VMA.Increment;
369 210
 }
370 211
 
371
-inline void REGISTER_2118_tile(uint8_t Byt)
212
+inline void REGISTER_2118_linear(uint8_t Byt)
372 213
 {
373 214
 	if (CHECK_INBLANK())
374 215
 		return;
375 216
 
376
-	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
377
-	uint32_t address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
217
+	uint32_t address;
378 218
 
379
-	Memory.VRAM[address] = Byt;
219
+	Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byt;
380 220
 
381 221
 	if (!PPU.VMA.High)
382 222
 		PPU.VMA.Address += PPU.VMA.Increment;
383 223
 }
384 224
 
385
-inline void REGISTER_2119_tile(uint8_t Byt)
225
+inline void REGISTER_2119(uint8_t Byt)
386 226
 {
387 227
 	if (CHECK_INBLANK())
388 228
 		return;
389 229
 
390
-	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
391
-	uint32_t address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff;
230
+	uint32_t address;
392 231
 
393
-	Memory.VRAM[address] = Byt;
232
+	if (PPU.VMA.FullGraphicCount)
233
+	{
234
+		uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
235
+		address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff;
236
+		Memory.VRAM[address] = Byt;
237
+	}
238
+	else
239
+		Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byt;
394 240
 
395 241
 	if (PPU.VMA.High)
396 242
 		PPU.VMA.Address += PPU.VMA.Increment;
397 243
 }
398 244
 
399
-inline void REGISTER_2118_linear(uint8_t Byt)
245
+inline void REGISTER_2119_tile(uint8_t Byt)
400 246
 {
401 247
 	if (CHECK_INBLANK())
402 248
 		return;
403 249
 
404
-	uint32_t address;
250
+	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
251
+	uint32_t address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff;
405 252
 
406
-	Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byt;
253
+	Memory.VRAM[address] = Byt;
407 254
 
408
-	if (!PPU.VMA.High)
255
+	if (PPU.VMA.High)
409 256
 		PPU.VMA.Address += PPU.VMA.Increment;
410 257
 }
411 258
 
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <algorithm>
179 8
 #include "snes9x.h"
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
... ...
@@ -1,219 +1,51 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #pragma once
179 8
 
180 9
 #ifndef VERSION
181
-#define VERSION "1.53"
10
+#define VERSION "1.60"
182 11
 #endif
183 12
 
184 13
 #include "port.h"
185 14
 
186
-const int SNES_WIDTH = 256;
187
-const int SNES_HEIGHT = 224;
188
-const uint16_t SNES_HEIGHT_EXTENDED = 239;
15
+inline constexpr int SNES_WIDTH = 256;
16
+inline constexpr int SNES_HEIGHT = 224;
17
+inline constexpr uint16_t SNES_HEIGHT_EXTENDED = 239;
189 18
 
190
-const int32_t SNES_MAX_NTSC_VCOUNTER = 262;
191
-const int32_t SNES_MAX_PAL_VCOUNTER = 312;
192
-const int32_t SNES_HCOUNTER_MAX = 341;
19
+inline constexpr double NTSC_MASTER_CLOCK = 21477272.727272; // 21477272 + 8/11 exact
20
+inline constexpr double PAL_MASTER_CLOCK = 21281370.0;
193 21
 
194
-const int32_t ONE_CYCLE = 6;
195
-const int32_t SLOW_ONE_CYCLE = 8;
196
-const int32_t TWO_CYCLES = 12;
197
-const int32_t ONE_DOT_CYCLE = 4;
22
+inline constexpr int32_t SNES_MAX_NTSC_VCOUNTER = 262;
23
+inline constexpr int32_t SNES_MAX_PAL_VCOUNTER = 312;
24
+inline constexpr int32_t SNES_HCOUNTER_MAX = 341;
198 25
 
199
-const int32_t SNES_CYCLES_PER_SCANLINE = SNES_HCOUNTER_MAX * ONE_DOT_CYCLE;
26
+inline constexpr int32_t ONE_CYCLE = 6;
27
+inline constexpr int32_t SLOW_ONE_CYCLE = 8;
28
+inline constexpr int32_t TWO_CYCLES = 12;
29
+inline constexpr int32_t ONE_DOT_CYCLE = 4;
200 30
 
201
-const int32_t SNES_WRAM_REFRESH_HC_v1 = 530;
202
-const int32_t SNES_WRAM_REFRESH_HC_v2 = 538;
203
-const int32_t SNES_WRAM_REFRESH_CYCLES = 40;
31
+inline constexpr int32_t SNES_CYCLES_PER_SCANLINE = SNES_HCOUNTER_MAX * ONE_DOT_CYCLE;
204 32
 
205
-const int32_t SNES_HBLANK_START_HC = 1096; // H=274
206
-const int32_t SNES_HDMA_START_HC = 1106; // FIXME: not true
207
-const int32_t SNES_HBLANK_END_HC = 4; // H=1
208
-const int32_t SNES_HDMA_INIT_HC = 20; // FIXME: not true
209
-const int32_t SNES_RENDER_START_HC = 48 * ONE_DOT_CYCLE; // FIXME: Snes9x renders a line at a time.
33
+inline constexpr int32_t SNES_WRAM_REFRESH_HC_v1 = 530;
34
+inline constexpr int32_t SNES_WRAM_REFRESH_HC_v2 = 538;
35
+inline constexpr int32_t SNES_WRAM_REFRESH_CYCLES = 40;
210 36
 
211
-const uint32_t DEBUG_MODE_FLAG = 1; // debugger
212
-const uint32_t TRACE_FLAG = 1 << 1; // debugger
213
-const uint32_t SCAN_KEYS_FLAG = 1 << 4; // CPU
214
-const uint32_t HALTED_FLAG = 1 << 12; // APU
37
+inline constexpr int32_t SNES_HBLANK_START_HC = 1096; // H=274
38
+inline constexpr int32_t SNES_HDMA_START_HC = 1106; // FIXME: not true
39
+inline constexpr int32_t SNES_HBLANK_END_HC = 4; // H=1
40
+inline constexpr int32_t SNES_HDMA_INIT_HC = 20; // FIXME: not true
41
+inline constexpr int32_t SNES_RENDER_START_HC = 128 * ONE_DOT_CYCLE; // FIXME: Snes9x renders a line at a time.
215 42
 
216
-const size_t ROM_NAME_LEN = 23;
43
+inline constexpr uint32_t DEBUG_MODE_FLAG = 1; // debugger
44
+inline constexpr uint32_t TRACE_FLAG = 1 << 1; // debugger
45
+inline constexpr uint32_t SCAN_KEYS_FLAG = 1 << 4; // CPU
46
+inline constexpr uint32_t HALTED_FLAG = 1 << 12; // APU
47
+
48
+inline constexpr size_t ROM_NAME_LEN = 23;
217 49
 
218 50
 struct SCPUState
219 51
 {
... ...
@@ -222,7 +54,7 @@ struct SCPUState
222 54
 	int32_t PrevCycles;
223 55
 	int32_t V_Counter;
224 56
 	uint8_t *PCBase;
225
-	bool NMILine;
57
+	bool NMIPending;
226 58
 	bool IRQLine;
227 59
 	bool IRQTransition;
228 60
 	bool IRQLastState;
... ...
@@ -251,6 +83,14 @@ enum
251 83
 	HC_WRAM_REFRESH_EVENT = 6
252 84
 };
253 85
 
86
+enum
87
+{
88
+	IRQ_NONE = 0x0,
89
+	IRQ_SET_FLAG = 0x1,
90
+	IRQ_CLEAR_FLAG = 0x2,
91
+	IRQ_TRIGGER_NMI = 0x4
92
+};
93
+
254 94
 struct STimings
255 95
 {
256 96
 	int32_t H_Max_Master;
... ...
@@ -262,13 +102,14 @@ struct STimings
262 102
 	int32_t HDMAInit;
263 103
 	int32_t HDMAStart;
264 104
 	int32_t NMITriggerPos;
105
+	int32_t NextIRQTimer;
265 106
 	int32_t IRQTriggerCycles;
266 107
 	int32_t WRAMRefreshPos;
267 108
 	int32_t RenderPos;
268 109
 	bool InterlaceField;
269 110
 	int32_t DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly.
270 111
 	int32_t NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly.
271
-	int32_t IRQPendCount; // This value is just a hack.
112
+	int32_t IRQFlagChanging; // This value is just a hack.
272 113
 	int32_t APUSpeedup;
273 114
 	bool APUAllowTimeOverflow;
274 115
 };
... ...
@@ -281,12 +122,11 @@ struct SSettings
281 122
 	bool PAL;
282 123
 
283 124
 	bool SoundSync;
284
-	bool SixteenBitSound;
285 125
 	uint32_t SoundPlaybackRate;
286 126
 	uint32_t SoundInputRate;
287 127
 	bool Stereo;
288
-	bool ReverseStereo;
289 128
 	bool Mute;
129
+	int32_t InterpolationMethod;
290 130
 
291 131
 	bool DisableGameSpecificHacks;
292 132
 	bool BlockInvalidVRAMAccessMaster;
... ...
@@ -294,6 +134,8 @@ struct SSettings
294 134
 	int32_t HDMATimingHack;
295 135
 
296 136
 	bool TurboMode;
137
+
138
+	bool SeparateEchoBuffer;
297 139
 };
298 140
 
299 141
 struct SSNESGameFixes