Merge branch 'main' into mergeTASEmulators
This commit is contained in:
commit
e8ab40c227
|
@ -22,7 +22,7 @@ jobs:
|
||||||
- name: Installing apt packages
|
- name: Installing apt packages
|
||||||
run: sudo apt install libgtest-dev gcovr libtbb-dev libsdl2-dev libsdl2-image-dev
|
run: sudo apt install libgtest-dev gcovr libtbb-dev libsdl2-dev libsdl2-image-dev
|
||||||
- name: Run meson configuration
|
- name: Run meson configuration
|
||||||
run: meson setup build -DonlyOpenSource=true
|
run: meson setup build -DonlyOpenSource=true -DenableArkanoidInputs=true
|
||||||
- name: Building project
|
- name: Building project
|
||||||
run: ninja -C build
|
run: ninja -C build
|
||||||
- name: Running tests
|
- name: Running tests
|
||||||
|
|
|
@ -79,13 +79,13 @@ error_t HQNState::advanceFrame(bool sleep)
|
||||||
SDL_Delay(wantTicks - ticks);
|
SDL_Delay(wantTicks - ticks);
|
||||||
}
|
}
|
||||||
// m_frameTime = wantTicks - m_prevFrame;
|
// m_frameTime = wantTicks - m_prevFrame;
|
||||||
error_t result = m_emu->emulate_frame(joypad[0], joypad[1]);
|
// error_t result = m_emu->emulate_frame(joypad[0], joypad[1]);
|
||||||
if (m_listener)
|
if (m_listener)
|
||||||
m_listener->onAdvanceFrame(this);
|
m_listener->onAdvanceFrame(this);
|
||||||
ticks = SDL_GetTicks();
|
ticks = SDL_GetTicks();
|
||||||
m_frameTime = ticks - m_prevFrame;
|
m_frameTime = ticks - m_prevFrame;
|
||||||
m_prevFrame = ticks;
|
m_prevFrame = ticks;
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HQNState::setFramerate(int fps)
|
void HQNState::setFramerate(int fps)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b7c82dffab2329b332a4d21e37c5b25a2088d29c
|
Subproject commit e7fd15b6e3ffed9bd718c0bfc0b0a6247e5dfe76
|
10
meson.build
10
meson.build
|
@ -8,6 +8,11 @@ project('quickerNES','c','cpp',
|
||||||
# Loading dependencies
|
# Loading dependencies
|
||||||
subdir('source')
|
subdir('source')
|
||||||
|
|
||||||
|
# Grabbing hqn dependency
|
||||||
|
|
||||||
|
hqnSubproject = subproject('hqn')
|
||||||
|
hqnDependency = hqnSubproject.get_variable('hqnDependency')
|
||||||
|
|
||||||
# Do not build any targets if this is a subproject
|
# Do not build any targets if this is a subproject
|
||||||
if meson.is_subproject() == false
|
if meson.is_subproject() == false
|
||||||
|
|
||||||
|
@ -19,11 +24,6 @@ commonCompileArgs = [ '-Wfatal-errors', '-Wall']
|
||||||
jaffarCommonSubproject = subproject('jaffarCommon')
|
jaffarCommonSubproject = subproject('jaffarCommon')
|
||||||
jaffarCommonDependency = jaffarCommonSubproject.get_variable('jaffarCommonDependency')
|
jaffarCommonDependency = jaffarCommonSubproject.get_variable('jaffarCommonDependency')
|
||||||
|
|
||||||
# Grabbing hqn dependency
|
|
||||||
|
|
||||||
hqnSubproject = subproject('hqn')
|
|
||||||
hqnDependency = hqnSubproject.get_variable('hqnDependency')
|
|
||||||
|
|
||||||
# Building playback tool
|
# Building playback tool
|
||||||
if get_option('buildPlayer') == true
|
if get_option('buildPlayer') == true
|
||||||
executable('player',
|
executable('player',
|
||||||
|
|
|
@ -26,3 +26,9 @@ option('onlyOpenSource',
|
||||||
yield: true
|
yield: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
option('enableArkanoidInputs',
|
||||||
|
type : 'boolean',
|
||||||
|
value : false,
|
||||||
|
description : 'Build tests',
|
||||||
|
yield: true
|
||||||
|
)
|
|
@ -1,213 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Base controller class
|
|
||||||
// by eien86
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace quickNES
|
|
||||||
{
|
|
||||||
|
|
||||||
class Controller
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum controller_t { none, joypad, fourscore1, fourscore2 };
|
|
||||||
|
|
||||||
typedef uint32_t port_t;
|
|
||||||
|
|
||||||
struct input_t
|
|
||||||
{
|
|
||||||
bool power = false;
|
|
||||||
bool reset = false;
|
|
||||||
port_t port1 = 0;
|
|
||||||
port_t port2 = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool parseInputString(const std::string& input)
|
|
||||||
{
|
|
||||||
// Parse valid flag
|
|
||||||
bool isValid = true;
|
|
||||||
|
|
||||||
// Converting input into a stream for parsing
|
|
||||||
std::istringstream ss(input);
|
|
||||||
|
|
||||||
// Start separator
|
|
||||||
if (ss.get() != '|') isValid = false;
|
|
||||||
|
|
||||||
// Parsing console inputs
|
|
||||||
isValid &= parseConsoleInputs(_input.reset, _input.power, ss);
|
|
||||||
|
|
||||||
// Parsing controller 1 inputs
|
|
||||||
isValid &= parseControllerInputs(_controller1Type, _input.port1, ss);
|
|
||||||
|
|
||||||
// Parsing controller 1 inputs
|
|
||||||
isValid &= parseControllerInputs(_controller2Type, _input.port2, ss);
|
|
||||||
|
|
||||||
// End separator
|
|
||||||
if (ss.get() != '|') isValid = false;
|
|
||||||
|
|
||||||
// If its not the end of the stream, then extra values remain and its invalid
|
|
||||||
ss.get();
|
|
||||||
if (ss.eof() == false) isValid = false;
|
|
||||||
|
|
||||||
// Returning valid flag
|
|
||||||
return isValid;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void setController1Type(const controller_t type) { _controller1Type = type; }
|
|
||||||
inline void setController2Type(const controller_t type) { _controller2Type = type; }
|
|
||||||
|
|
||||||
inline bool getPowerButtonState() { return _input.power; }
|
|
||||||
inline bool getResetButtonState() { return _input.reset; }
|
|
||||||
inline port_t getController1Code() { return _input.port1; }
|
|
||||||
inline port_t getController2Code() { return _input.port2; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static bool parseJoyPadInput(uint8_t& code, std::istringstream& ss)
|
|
||||||
{
|
|
||||||
// Currently read character
|
|
||||||
char c;
|
|
||||||
|
|
||||||
// Cleaning code
|
|
||||||
code = 0;
|
|
||||||
|
|
||||||
// Up
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'U') return false;
|
|
||||||
if (c == 'U') code |= 0b00010000;
|
|
||||||
|
|
||||||
// Down
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'D') return false;
|
|
||||||
if (c == 'D') code |= 0b00100000;
|
|
||||||
|
|
||||||
// Left
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'L') return false;
|
|
||||||
if (c == 'L') code |= 0b01000000;
|
|
||||||
|
|
||||||
// Right
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'R') return false;
|
|
||||||
if (c == 'R') code |= 0b10000000;
|
|
||||||
|
|
||||||
// Start
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'S') return false;
|
|
||||||
if (c == 'S') code |= 0b00001000;
|
|
||||||
|
|
||||||
// Select
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 's') return false;
|
|
||||||
if (c == 's') code |= 0b00000100;
|
|
||||||
|
|
||||||
// B
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'B') return false;
|
|
||||||
if (c == 'B') code |= 0b00000010;
|
|
||||||
|
|
||||||
// A
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'A') return false;
|
|
||||||
if (c == 'A') code |= 0b00000001;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parseControllerInputs(const controller_t type, port_t& port, std::istringstream& ss)
|
|
||||||
{
|
|
||||||
// Parse valid flag
|
|
||||||
bool isValid = true;
|
|
||||||
|
|
||||||
// If no controller assigned then, its port is all zeroes.
|
|
||||||
if (type == controller_t::none) { port = 0; return true; }
|
|
||||||
|
|
||||||
// Controller separator
|
|
||||||
if (ss.get() != '|') isValid = false;
|
|
||||||
|
|
||||||
// If normal joypad, parse its code now
|
|
||||||
if (type == controller_t::joypad)
|
|
||||||
{
|
|
||||||
// Storage for joypad's code
|
|
||||||
uint8_t code = 0;
|
|
||||||
|
|
||||||
// Parsing joypad code
|
|
||||||
isValid &= parseJoyPadInput(code, ss);
|
|
||||||
|
|
||||||
// Pushing input code into the port
|
|
||||||
port = code;
|
|
||||||
|
|
||||||
// Adding joypad signature
|
|
||||||
// Per https://www.nesdev.org/wiki/Standard_controller, the joypad reports 1s after the first 8 bits
|
|
||||||
port |= ~0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If its fourscore, its like two joypads separated by a |
|
|
||||||
if (type == controller_t::fourscore1 || type == controller_t::fourscore2)
|
|
||||||
{
|
|
||||||
// Storage for joypad's code
|
|
||||||
uint8_t code1 = 0;
|
|
||||||
uint8_t code2 = 0;
|
|
||||||
|
|
||||||
// Parsing joypad code1
|
|
||||||
isValid &= parseJoyPadInput(code1, ss);
|
|
||||||
|
|
||||||
// Separator
|
|
||||||
if (ss.get() != '|') return false;
|
|
||||||
|
|
||||||
// Parsing joypad code1
|
|
||||||
isValid &= parseJoyPadInput(code2, ss);
|
|
||||||
|
|
||||||
// Creating code
|
|
||||||
port = code1;
|
|
||||||
port |= (uint32_t)0 | code2 << 8;
|
|
||||||
if (type == controller_t::fourscore1) port |= (uint32_t)0 | 1 << 19;
|
|
||||||
if (type == controller_t::fourscore2) port |= (uint32_t)0 | 1 << 18;
|
|
||||||
port |= (uint32_t)0 | 1 << 24;
|
|
||||||
port |= (uint32_t)0 | 1 << 25;
|
|
||||||
port |= (uint32_t)0 | 1 << 26;
|
|
||||||
port |= (uint32_t)0 | 1 << 27;
|
|
||||||
port |= (uint32_t)0 | 1 << 28;
|
|
||||||
port |= (uint32_t)0 | 1 << 29;
|
|
||||||
port |= (uint32_t)0 | 1 << 30;
|
|
||||||
port |= (uint32_t)0 | 1 << 31;
|
|
||||||
}
|
|
||||||
// Return valid flag
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parseConsoleInputs(bool& reset, bool& power, std::istringstream& ss)
|
|
||||||
{
|
|
||||||
// Parse valid flag
|
|
||||||
bool isValid = true;
|
|
||||||
|
|
||||||
// Currently read character
|
|
||||||
char c;
|
|
||||||
|
|
||||||
// Power trigger
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'P') isValid = false;
|
|
||||||
if (c == 'P') power = true;
|
|
||||||
if (c == '.') power = false;
|
|
||||||
|
|
||||||
// Reset trigger
|
|
||||||
c = ss.get();
|
|
||||||
if (c != '.' && c != 'r') isValid = false;
|
|
||||||
if (c == 'r') reset = true;
|
|
||||||
if (c == '.') reset = false;
|
|
||||||
|
|
||||||
// Return valid flag
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
input_t _input;
|
|
||||||
controller_t _controller1Type;
|
|
||||||
controller_t _controller2Type;
|
|
||||||
|
|
||||||
}; // class Controller
|
|
||||||
|
|
||||||
} // namespace quickNES
|
|
|
@ -0,0 +1,353 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Base controller class
|
||||||
|
// by eien86
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <jaffarCommon/exceptions.hpp>
|
||||||
|
#include <jaffarCommon/json.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace jaffar
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef uint32_t port_t;
|
||||||
|
|
||||||
|
struct input_t
|
||||||
|
{
|
||||||
|
bool power = false;
|
||||||
|
bool reset = false;
|
||||||
|
port_t port1 = 0;
|
||||||
|
port_t port2 = 0;
|
||||||
|
port_t arkanoidLatch = 0;
|
||||||
|
uint8_t arkanoidFire = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InputParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum controller_t
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
joypad,
|
||||||
|
fourscore1,
|
||||||
|
fourscore2,
|
||||||
|
arkanoidNES,
|
||||||
|
arkanoidFamicom
|
||||||
|
};
|
||||||
|
|
||||||
|
controller_t _controller1Type;
|
||||||
|
controller_t _controller2Type;
|
||||||
|
|
||||||
|
InputParser(const nlohmann::json &config)
|
||||||
|
{
|
||||||
|
// Parsing controller 1 type
|
||||||
|
{
|
||||||
|
bool isTypeRecognized = false;
|
||||||
|
const auto controller1Type = jaffarCommon::json::getString(config, "Controller 1 Type");
|
||||||
|
if (controller1Type == "None")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::none;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller1Type == "Joypad")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::joypad;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller1Type == "FourScore1")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::fourscore1;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller1Type == "FourScore2")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::fourscore2;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _QUICKERNES_SUPPORT_ARKANOID_INPUTS
|
||||||
|
if (controller1Type == "ArkanoidNES")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::arkanoidNES;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller1Type == "ArkanoidFamicom")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::arkanoidFamicom;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Controller 1 type not recognized: '%s'\n", controller1Type.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsing controller 2 type
|
||||||
|
{
|
||||||
|
bool isTypeRecognized = false;
|
||||||
|
const auto controller2Type = jaffarCommon::json::getString(config, "Controller 2 Type");
|
||||||
|
if (controller2Type == "None")
|
||||||
|
{
|
||||||
|
_controller2Type = controller_t::none;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller2Type == "Joypad")
|
||||||
|
{
|
||||||
|
_controller2Type = controller_t::joypad;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller2Type == "FourScore1")
|
||||||
|
{
|
||||||
|
_controller2Type = controller_t::fourscore1;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller2Type == "FourScore2")
|
||||||
|
{
|
||||||
|
_controller2Type = controller_t::fourscore2;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Controller 2 type not recognized: '%s'\n", controller2Type.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline input_t parseInputString(const std::string &inputString) const
|
||||||
|
{
|
||||||
|
// Storage for the input
|
||||||
|
input_t input;
|
||||||
|
|
||||||
|
// Converting input into a stream for parsing
|
||||||
|
std::istringstream ss(inputString);
|
||||||
|
|
||||||
|
// Start separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Parsing console inputs
|
||||||
|
parseConsoleInputs(input.reset, input.power, ss, inputString);
|
||||||
|
|
||||||
|
// Parsing controller 1 inputs
|
||||||
|
if (_controller1Type == arkanoidNES) parseArkanoidNESInput(input, ss, inputString);
|
||||||
|
if (_controller1Type == arkanoidFamicom) parseArkanoidFamicomInput(input, ss, inputString);
|
||||||
|
if (_controller1Type == joypad || _controller1Type == fourscore1) parseControllerInputs(_controller1Type, input.port1, ss, inputString);
|
||||||
|
|
||||||
|
// Parsing controller 2 inputs
|
||||||
|
if (_controller2Type == joypad || _controller2Type == fourscore2) parseControllerInputs(_controller2Type, input.port2, ss, inputString);
|
||||||
|
|
||||||
|
// End separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// If its not the end of the stream, then extra values remain and its invalid
|
||||||
|
ss.get();
|
||||||
|
if (ss.eof() == false) reportBadInputString(inputString);
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static inline void reportBadInputString(const std::string &inputString)
|
||||||
|
{
|
||||||
|
JAFFAR_THROW_LOGIC("Could not decode input string: '%s'\n", inputString.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parseJoyPadInput(uint8_t &code, std::istringstream &ss, const std::string &inputString)
|
||||||
|
{
|
||||||
|
// Currently read character
|
||||||
|
char c;
|
||||||
|
|
||||||
|
// Cleaning code
|
||||||
|
code = 0;
|
||||||
|
|
||||||
|
// Up
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'U') reportBadInputString(inputString);
|
||||||
|
if (c == 'U') code |= 0b00010000;
|
||||||
|
|
||||||
|
// Down
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'D') reportBadInputString(inputString);
|
||||||
|
if (c == 'D') code |= 0b00100000;
|
||||||
|
|
||||||
|
// Left
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'L') reportBadInputString(inputString);
|
||||||
|
if (c == 'L') code |= 0b01000000;
|
||||||
|
|
||||||
|
// Right
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'R') reportBadInputString(inputString);
|
||||||
|
if (c == 'R') code |= 0b10000000;
|
||||||
|
|
||||||
|
// Start
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'S') reportBadInputString(inputString);
|
||||||
|
if (c == 'S') code |= 0b00001000;
|
||||||
|
|
||||||
|
// Select
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 's') reportBadInputString(inputString);
|
||||||
|
if (c == 's') code |= 0b00000100;
|
||||||
|
|
||||||
|
// B
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'B') reportBadInputString(inputString);
|
||||||
|
if (c == 'B') code |= 0b00000010;
|
||||||
|
|
||||||
|
// A
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'A') reportBadInputString(inputString);
|
||||||
|
if (c == 'A') code |= 0b00000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void parseArkanoidInput(input_t& input, std::istringstream& ss, const std::string& inputString)
|
||||||
|
{
|
||||||
|
uint8_t potentiometer = 0;
|
||||||
|
uint8_t fire = 0;
|
||||||
|
|
||||||
|
// Controller separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
if (ss.get() != ' ') reportBadInputString(inputString);
|
||||||
|
if (ss.get() != ' ') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
char c = ss.get(); // Hundreds
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += 100 * ( (uint8_t)c - 48 );
|
||||||
|
|
||||||
|
c = ss.get(); // Tenths
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += 10 * ( (uint8_t)c - 48 );
|
||||||
|
|
||||||
|
c = ss.get(); // Units
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += (uint8_t)c - 48;
|
||||||
|
|
||||||
|
// Comma
|
||||||
|
if (ss.get() != ',') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Fire
|
||||||
|
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'F') reportBadInputString(inputString);
|
||||||
|
if (c == 'F') fire = 1;
|
||||||
|
|
||||||
|
// Fire is encoded in port 1
|
||||||
|
input.arkanoidFire = fire;
|
||||||
|
|
||||||
|
// Potentiometer is encoded in port 2 - MSB and adding one bit for signalling the presence of the potentiometer, subtracted from 173
|
||||||
|
uint8_t subtracter = 171 - potentiometer;
|
||||||
|
|
||||||
|
input.arkanoidLatch = 0;
|
||||||
|
if ((subtracter & 128) > 0) input.arkanoidLatch += 1;
|
||||||
|
if ((subtracter & 64) > 0) input.arkanoidLatch += 2;
|
||||||
|
if ((subtracter & 32) > 0) input.arkanoidLatch += 4;
|
||||||
|
if ((subtracter & 16) > 0) input.arkanoidLatch += 8;
|
||||||
|
if ((subtracter & 8) > 0) input.arkanoidLatch += 16;
|
||||||
|
if ((subtracter & 4) > 0) input.arkanoidLatch += 32;
|
||||||
|
if ((subtracter & 2) > 0) input.arkanoidLatch += 64;
|
||||||
|
if ((subtracter & 1) > 0) input.arkanoidLatch += 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parseControllerInputs(const controller_t type, port_t &port, std::istringstream &ss, const std::string &inputString)
|
||||||
|
{
|
||||||
|
// If no controller assigned then, its port is all zeroes.
|
||||||
|
if (type == controller_t::none)
|
||||||
|
{
|
||||||
|
port = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// If normal joypad, parse its code now
|
||||||
|
if (type == controller_t::joypad)
|
||||||
|
{
|
||||||
|
// Storage for joypad's code
|
||||||
|
uint8_t code = 0;
|
||||||
|
|
||||||
|
// Parsing joypad code
|
||||||
|
parseJoyPadInput(code, ss, inputString);
|
||||||
|
|
||||||
|
// Pushing input code into the port
|
||||||
|
port = code;
|
||||||
|
|
||||||
|
// Adding joypad signature
|
||||||
|
// Per https://www.nesdev.org/wiki/Standard_controller, the joypad reports 1s after the first 8 bits
|
||||||
|
port |= ~0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If its fourscore, its like two joypads separated by a |
|
||||||
|
if (type == controller_t::fourscore1 || type == controller_t::fourscore2)
|
||||||
|
{
|
||||||
|
// Storage for joypad's code
|
||||||
|
uint8_t code1 = 0;
|
||||||
|
uint8_t code2 = 0;
|
||||||
|
|
||||||
|
// Parsing joypad code1
|
||||||
|
parseJoyPadInput(code1, ss, inputString);
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Parsing joypad code1
|
||||||
|
parseJoyPadInput(code2, ss, inputString);
|
||||||
|
|
||||||
|
// Creating code
|
||||||
|
port = code1;
|
||||||
|
port |= (uint32_t)0 | code2 << 8;
|
||||||
|
if (type == controller_t::fourscore1) port |= (uint32_t)0 | 1 << 19;
|
||||||
|
if (type == controller_t::fourscore2) port |= (uint32_t)0 | 1 << 18;
|
||||||
|
port |= (uint32_t)0 | 1 << 24;
|
||||||
|
port |= (uint32_t)0 | 1 << 25;
|
||||||
|
port |= (uint32_t)0 | 1 << 26;
|
||||||
|
port |= (uint32_t)0 | 1 << 27;
|
||||||
|
port |= (uint32_t)0 | 1 << 28;
|
||||||
|
port |= (uint32_t)0 | 1 << 29;
|
||||||
|
port |= (uint32_t)0 | 1 << 30;
|
||||||
|
port |= (uint32_t)0 | 1 << 31;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void parseArkanoidNESInput(input_t& input, std::istringstream& ss, const std::string& inputString)
|
||||||
|
{
|
||||||
|
// Simply parse the arkanoid controller input
|
||||||
|
parseArkanoidInput(input, ss, inputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void parseArkanoidFamicomInput(input_t& input, std::istringstream& ss, const std::string& inputString)
|
||||||
|
{
|
||||||
|
// Parsing joypad controller
|
||||||
|
parseControllerInputs(controller_t::joypad, input.port1, ss, inputString);
|
||||||
|
|
||||||
|
// Controller separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Advancing 7 positions (this input is not supported)
|
||||||
|
for (size_t i = 0; i < 7; i++) if (ss.get() != '.') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Then, parse the arkanoid controller input
|
||||||
|
parseArkanoidInput(input, ss, inputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void parseConsoleInputs(bool &reset, bool &power, std::istringstream &ss, const std::string &inputString)
|
||||||
|
{
|
||||||
|
// Currently read character
|
||||||
|
char c;
|
||||||
|
|
||||||
|
// Power trigger
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'P') reportBadInputString(inputString);
|
||||||
|
if (c == 'P') power = true;
|
||||||
|
if (c == '.') power = false;
|
||||||
|
|
||||||
|
// Reset trigger
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'r') reportBadInputString(inputString);
|
||||||
|
if (c == 'r') reset = true;
|
||||||
|
if (c == '.') reset = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class InputParser
|
||||||
|
|
||||||
|
} // namespace jaffar
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "inputParser.hpp"
|
||||||
|
#include "jaffarCommon/logger.hpp"
|
||||||
#include "jaffarCommon/serializers/contiguous.hpp"
|
#include "jaffarCommon/serializers/contiguous.hpp"
|
||||||
#include "jaffarCommon/serializers/differential.hpp"
|
#include "jaffarCommon/serializers/differential.hpp"
|
||||||
#include "jaffarCommon/logger.hpp"
|
#include "jaffarCommon/deserializers/base.hpp"
|
||||||
#include "controller.hpp"
|
|
||||||
|
|
||||||
// Size of image generated in graphics buffer
|
// Size of image generated in graphics buffer
|
||||||
static const uint16_t image_width = 256;
|
static const uint16_t image_width = 256;
|
||||||
|
@ -12,56 +13,19 @@ static const uint16_t image_height = 240;
|
||||||
class NESInstanceBase
|
class NESInstanceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NESInstanceBase(const nlohmann::json &config)
|
||||||
|
{
|
||||||
|
_inputParser = std::make_unique<jaffar::InputParser>(config);
|
||||||
|
}
|
||||||
|
|
||||||
NESInstanceBase() = default;
|
|
||||||
virtual ~NESInstanceBase() = default;
|
virtual ~NESInstanceBase() = default;
|
||||||
|
|
||||||
inline void advanceState(const std::string &move)
|
virtual void advanceState(const jaffar::input_t &input) = 0;
|
||||||
{
|
|
||||||
bool isInputValid = _controller.parseInputString(move);
|
|
||||||
if (isInputValid == false) JAFFAR_THROW_LOGIC("Move provided cannot be parsed: '%s'\n", move.c_str());
|
|
||||||
|
|
||||||
// Parsing power
|
|
||||||
if (_controller.getPowerButtonState() == true) JAFFAR_THROW_LOGIC("Power button pressed, but not supported: '%s'\n", move.c_str());
|
|
||||||
|
|
||||||
// Parsing reset
|
|
||||||
if (_controller.getResetButtonState() == true) doSoftReset();
|
|
||||||
|
|
||||||
// Parsing Controllers
|
|
||||||
const auto controller1 = _controller.getController1Code();
|
|
||||||
const auto controller2 = _controller.getController2Code();
|
|
||||||
|
|
||||||
advanceStateImpl(controller1, controller2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setController1Type(const std::string& type)
|
|
||||||
{
|
|
||||||
bool isTypeRecognized = false;
|
|
||||||
|
|
||||||
if (type == "None") { _controller.setController1Type(quickNES::Controller::controller_t::none); isTypeRecognized = true; }
|
|
||||||
if (type == "Joypad") { _controller.setController1Type(quickNES::Controller::controller_t::joypad); isTypeRecognized = true; }
|
|
||||||
if (type == "FourScore1") { _controller.setController1Type(quickNES::Controller::controller_t::fourscore1); isTypeRecognized = true; }
|
|
||||||
if (type == "FourScore2") { _controller.setController1Type(quickNES::Controller::controller_t::fourscore2); isTypeRecognized = true; }
|
|
||||||
|
|
||||||
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Input type not recognized: '%s'\n", type.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setController2Type(const std::string& type)
|
|
||||||
{
|
|
||||||
bool isTypeRecognized = false;
|
|
||||||
|
|
||||||
if (type == "None") { _controller.setController2Type(quickNES::Controller::controller_t::none); isTypeRecognized = true; }
|
|
||||||
if (type == "Joypad") { _controller.setController2Type(quickNES::Controller::controller_t::joypad); isTypeRecognized = true; }
|
|
||||||
if (type == "FourScore1") { _controller.setController2Type(quickNES::Controller::controller_t::fourscore1); isTypeRecognized = true; }
|
|
||||||
if (type == "FourScore2") { _controller.setController2Type(quickNES::Controller::controller_t::fourscore2); isTypeRecognized = true; }
|
|
||||||
|
|
||||||
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Input type not recognized: '%s'\n", type.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void enableRendering() { _doRendering = true; };
|
inline void enableRendering() { _doRendering = true; };
|
||||||
inline void disableRendering() { _doRendering = false; };
|
inline void disableRendering() { _doRendering = false; };
|
||||||
|
|
||||||
inline bool loadROM(const uint8_t* romData, const size_t romSize)
|
inline bool loadROM(const uint8_t *romData, const size_t romSize)
|
||||||
{
|
{
|
||||||
// Actually loading rom file
|
// Actually loading rom file
|
||||||
auto status = loadROMImpl(romData, romSize);
|
auto status = loadROMImpl(romData, romSize);
|
||||||
|
@ -73,7 +37,7 @@ class NESInstanceBase
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableStateBlock(const std::string& block)
|
void enableStateBlock(const std::string &block)
|
||||||
{
|
{
|
||||||
// Calling implementation
|
// Calling implementation
|
||||||
enableStateBlockImpl(block);
|
enableStateBlockImpl(block);
|
||||||
|
@ -82,7 +46,7 @@ class NESInstanceBase
|
||||||
_stateSize = getFullStateSize();
|
_stateSize = getFullStateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void disableStateBlock(const std::string& block)
|
void disableStateBlock(const std::string &block)
|
||||||
{
|
{
|
||||||
// Calling implementation
|
// Calling implementation
|
||||||
disableStateBlockImpl(block);
|
disableStateBlockImpl(block);
|
||||||
|
@ -93,26 +57,26 @@ class NESInstanceBase
|
||||||
|
|
||||||
virtual size_t getFullStateSize() const = 0;
|
virtual size_t getFullStateSize() const = 0;
|
||||||
virtual size_t getDifferentialStateSize() const = 0;
|
virtual size_t getDifferentialStateSize() const = 0;
|
||||||
|
inline jaffar::InputParser *getInputParser() const { return _inputParser.get(); }
|
||||||
|
|
||||||
// Virtual functions
|
// Virtual functions
|
||||||
|
|
||||||
virtual uint8_t *getLowMem() const = 0;
|
virtual uint8_t *getLowMem() const = 0;
|
||||||
virtual size_t getLowMemSize() const = 0;
|
virtual size_t getLowMemSize() const = 0;
|
||||||
|
|
||||||
virtual void serializeState(jaffarCommon::serializer::Base& serializer) const = 0;
|
virtual void serializeState(jaffarCommon::serializer::Base &serializer) const = 0;
|
||||||
virtual void deserializeState(jaffarCommon::deserializer::Base& deserializer) = 0;
|
virtual void deserializeState(jaffarCommon::deserializer::Base &deserializer) = 0;
|
||||||
|
|
||||||
virtual void doSoftReset() = 0;
|
virtual void doSoftReset() = 0;
|
||||||
virtual void doHardReset() = 0;
|
virtual void doHardReset() = 0;
|
||||||
virtual std::string getCoreName() const = 0;
|
virtual std::string getCoreName() const = 0;
|
||||||
virtual void *getInternalEmulatorPointer() = 0;
|
virtual void *getInternalEmulatorPointer() = 0;
|
||||||
|
virtual void setNTABBlockSize(const size_t size) {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void enableStateBlockImpl(const std::string &block) = 0;
|
||||||
virtual void enableStateBlockImpl(const std::string& block) = 0;
|
virtual void disableStateBlockImpl(const std::string &block) = 0;
|
||||||
virtual void disableStateBlockImpl(const std::string& block) = 0;
|
virtual bool loadROMImpl(const uint8_t *romData, const size_t romSize) = 0;
|
||||||
virtual bool loadROMImpl(const uint8_t* romData, const size_t romSize) = 0;
|
|
||||||
virtual void advanceStateImpl(const quickNES::Controller::port_t controller1, const quickNES::Controller::port_t controller2) = 0;
|
|
||||||
|
|
||||||
// Storage for the light state size
|
// Storage for the light state size
|
||||||
size_t _stateSize;
|
size_t _stateSize;
|
||||||
|
@ -120,8 +84,6 @@ class NESInstanceBase
|
||||||
// Flag to determine whether to enable/disable rendering
|
// Flag to determine whether to enable/disable rendering
|
||||||
bool _doRendering = true;
|
bool _doRendering = true;
|
||||||
|
|
||||||
private:
|
// Input parser instance
|
||||||
|
std::unique_ptr<jaffar::InputParser> _inputParser;
|
||||||
// Controller class for input parsing
|
|
||||||
quickNES::Controller _controller;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include "nesInstance.hpp"
|
||||||
#include <unistd.h>
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
#include <extern/hqn/hqn.h>
|
#include <extern/hqn/hqn.h>
|
||||||
#include <extern/hqn/hqn_gui_controller.h>
|
#include <extern/hqn/hqn_gui_controller.h>
|
||||||
#include <jaffarCommon/serializers/contiguous.hpp>
|
|
||||||
#include <jaffarCommon/deserializers/contiguous.hpp>
|
#include <jaffarCommon/deserializers/contiguous.hpp>
|
||||||
#include <jaffarCommon/hash.hpp>
|
#include <jaffarCommon/hash.hpp>
|
||||||
#include "nesInstance.hpp"
|
#include <jaffarCommon/serializers/contiguous.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define _INVERSE_FRAME_RATE 16667
|
#define _INVERSE_FRAME_RATE 16667
|
||||||
|
|
||||||
struct stepData_t
|
struct stepData_t
|
||||||
{
|
{
|
||||||
std::string input;
|
std::string inputString;
|
||||||
|
jaffar::input_t decodedInput;
|
||||||
uint8_t *stateData;
|
uint8_t *stateData;
|
||||||
jaffarCommon::hash::hash_t hash;
|
jaffarCommon::hash::hash_t hash;
|
||||||
};
|
};
|
||||||
|
@ -26,10 +27,11 @@ class PlaybackInstance
|
||||||
static const uint16_t image_height = 240;
|
static const uint16_t image_height = 240;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void addStep(const std::string &input)
|
void addStep(const std::string &inputString, const jaffar::input_t decodedInput)
|
||||||
{
|
{
|
||||||
stepData_t step;
|
stepData_t step;
|
||||||
step.input = input;
|
step.inputString = inputString;
|
||||||
|
step.decodedInput = decodedInput;
|
||||||
step.stateData = (uint8_t *)malloc(_emu->getFullStateSize());
|
step.stateData = (uint8_t *)malloc(_emu->getFullStateSize());
|
||||||
|
|
||||||
jaffarCommon::serializer::Contiguous serializer(step.stateData);
|
jaffarCommon::serializer::Contiguous serializer(step.stateData);
|
||||||
|
@ -92,27 +94,33 @@ class PlaybackInstance
|
||||||
|
|
||||||
void initialize(const std::vector<std::string> &sequence)
|
void initialize(const std::vector<std::string> &sequence)
|
||||||
{
|
{
|
||||||
|
// Getting input decoder
|
||||||
|
auto inputParser = _emu->getInputParser();
|
||||||
|
|
||||||
// Building sequence information
|
// Building sequence information
|
||||||
for (const auto &input : sequence)
|
for (const auto &input : sequence)
|
||||||
{
|
{
|
||||||
|
// Getting decoded input
|
||||||
|
const auto decodedInput = inputParser->parseInputString(input);
|
||||||
|
|
||||||
// Adding new step
|
// Adding new step
|
||||||
addStep(input);
|
addStep(input, decodedInput);
|
||||||
|
|
||||||
// Advance state based on the input received
|
// Advance state based on the input received
|
||||||
_emu->advanceState(input);
|
_emu->advanceState(decodedInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding last step with no input
|
// Adding last step with no input
|
||||||
addStep("<End Of Sequence>");
|
addStep("<End Of Sequence>", jaffar::input_t());
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableRendering(SDL_Window* window)
|
void enableRendering(SDL_Window *window)
|
||||||
{
|
{
|
||||||
// Allocating video buffer
|
// Allocating video buffer
|
||||||
_video_buffer = (uint8_t *)malloc(image_width * image_height);
|
_video_buffer = (uint8_t *)malloc(image_width * image_height);
|
||||||
|
|
||||||
// Setting video buffer
|
// Setting video buffer
|
||||||
((emulator_t*)_emu->getInternalEmulatorPointer())->set_pixels(_video_buffer, image_width + 8);
|
((emulator_t *)_emu->getInternalEmulatorPointer())->set_pixels(_video_buffer, image_width + 8);
|
||||||
|
|
||||||
// Loading Emulator instance HQN
|
// Loading Emulator instance HQN
|
||||||
_hqnState.setEmulatorPointer(_emu->getInternalEmulatorPointer());
|
_hqnState.setEmulatorPointer(_emu->getInternalEmulatorPointer());
|
||||||
|
@ -149,14 +157,14 @@ class PlaybackInstance
|
||||||
// Load correct overlay images, if using overlay
|
// Load correct overlay images, if using overlay
|
||||||
if (_useOverlay == true)
|
if (_useOverlay == true)
|
||||||
{
|
{
|
||||||
if (step.input.find("A") != std::string::npos) overlayButtonASurface = _overlayButtonASurface;
|
if (step.inputString.find("A") != std::string::npos) overlayButtonASurface = _overlayButtonASurface;
|
||||||
if (step.input.find("B") != std::string::npos) overlayButtonBSurface = _overlayButtonBSurface;
|
if (step.inputString.find("B") != std::string::npos) overlayButtonBSurface = _overlayButtonBSurface;
|
||||||
if (step.input.find("S") != std::string::npos) overlayButtonSelectSurface = _overlayButtonSelectSurface;
|
if (step.inputString.find("S") != std::string::npos) overlayButtonSelectSurface = _overlayButtonSelectSurface;
|
||||||
if (step.input.find("T") != std::string::npos) overlayButtonStartSurface = _overlayButtonStartSurface;
|
if (step.inputString.find("T") != std::string::npos) overlayButtonStartSurface = _overlayButtonStartSurface;
|
||||||
if (step.input.find("L") != std::string::npos) overlayButtonLeftSurface = _overlayButtonLeftSurface;
|
if (step.inputString.find("L") != std::string::npos) overlayButtonLeftSurface = _overlayButtonLeftSurface;
|
||||||
if (step.input.find("R") != std::string::npos) overlayButtonRightSurface = _overlayButtonRightSurface;
|
if (step.inputString.find("R") != std::string::npos) overlayButtonRightSurface = _overlayButtonRightSurface;
|
||||||
if (step.input.find("U") != std::string::npos) overlayButtonUpSurface = _overlayButtonUpSurface;
|
if (step.inputString.find("U") != std::string::npos) overlayButtonUpSurface = _overlayButtonUpSurface;
|
||||||
if (step.input.find("D") != std::string::npos) overlayButtonDownSurface = _overlayButtonDownSurface;
|
if (step.inputString.find("D") != std::string::npos) overlayButtonDownSurface = _overlayButtonDownSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we do not store the blit information (too much memory), we need to load the previous frame and re-run the input
|
// Since we do not store the blit information (too much memory), we need to load the previous frame and re-run the input
|
||||||
|
@ -170,7 +178,7 @@ class PlaybackInstance
|
||||||
const auto stateData = getStateData(stepId - 1);
|
const auto stateData = getStateData(stepId - 1);
|
||||||
jaffarCommon::deserializer::Contiguous deserializer(stateData);
|
jaffarCommon::deserializer::Contiguous deserializer(stateData);
|
||||||
_emu->deserializeState(deserializer);
|
_emu->deserializeState(deserializer);
|
||||||
_emu->advanceState(getStateInput(stepId - 1));
|
_emu->advanceState(getDecodedInput(stepId - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updating image
|
// Updating image
|
||||||
|
@ -184,7 +192,7 @@ class PlaybackInstance
|
||||||
return _stepSequence.size();
|
return _stepSequence.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string getInput(const size_t stepId) const
|
const std::string getInputString(const size_t stepId) const
|
||||||
{
|
{
|
||||||
// Checking the required step id does not exceed contents of the sequence
|
// Checking the required step id does not exceed contents of the sequence
|
||||||
if (stepId > _stepSequence.size()) JAFFAR_THROW_LOGIC("[Error] Attempting to render a step larger than the step sequence");
|
if (stepId > _stepSequence.size()) JAFFAR_THROW_LOGIC("[Error] Attempting to render a step larger than the step sequence");
|
||||||
|
@ -193,7 +201,19 @@ class PlaybackInstance
|
||||||
const auto &step = _stepSequence[stepId];
|
const auto &step = _stepSequence[stepId];
|
||||||
|
|
||||||
// Returning step input
|
// Returning step input
|
||||||
return step.input;
|
return step.inputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jaffar::input_t getDecodedInput(const size_t stepId) const
|
||||||
|
{
|
||||||
|
// Checking the required step id does not exceed contents of the sequence
|
||||||
|
if (stepId > _stepSequence.size()) JAFFAR_THROW_LOGIC("[Error] Attempting to render a step larger than the step sequence");
|
||||||
|
|
||||||
|
// Getting step information
|
||||||
|
const auto &step = _stepSequence[stepId];
|
||||||
|
|
||||||
|
// Returning step input
|
||||||
|
return step.decodedInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *getStateData(const size_t stepId) const
|
const uint8_t *getStateData(const size_t stepId) const
|
||||||
|
@ -220,20 +240,8 @@ class PlaybackInstance
|
||||||
return step.hash;
|
return step.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string getStateInput(const size_t stepId) const
|
|
||||||
{
|
|
||||||
// Checking the required step id does not exceed contents of the sequence
|
|
||||||
if (stepId > _stepSequence.size()) JAFFAR_THROW_LOGIC("[Error] Attempting to render a step larger than the step sequence");
|
|
||||||
|
|
||||||
// Getting step information
|
|
||||||
const auto &step = _stepSequence[stepId];
|
|
||||||
|
|
||||||
// Returning step input
|
|
||||||
return step.input;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Internal sequence information
|
// Internal sequence information
|
||||||
std::vector<stepData_t> _stepSequence;
|
std::vector<stepData_t> _stepSequence;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include <cstdlib>
|
|
||||||
#include "argparse/argparse.hpp"
|
#include "argparse/argparse.hpp"
|
||||||
#include "jaffarCommon/serializers/contiguous.hpp"
|
|
||||||
#include "jaffarCommon/deserializers/contiguous.hpp"
|
#include "jaffarCommon/deserializers/contiguous.hpp"
|
||||||
#include "jaffarCommon/file.hpp"
|
#include "jaffarCommon/file.hpp"
|
||||||
#include "jaffarCommon/logger.hpp"
|
#include "jaffarCommon/logger.hpp"
|
||||||
|
#include "jaffarCommon/serializers/contiguous.hpp"
|
||||||
#include "jaffarCommon/string.hpp"
|
#include "jaffarCommon/string.hpp"
|
||||||
#include "nesInstance.hpp"
|
#include "nesInstance.hpp"
|
||||||
#include "playbackInstance.hpp"
|
#include "playbackInstance.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
SDL_Window *launchOutputWindow()
|
SDL_Window *launchOutputWindow()
|
||||||
{
|
{
|
||||||
|
@ -97,7 +97,7 @@ int main(int argc, char *argv[])
|
||||||
if (status == false) JAFFAR_THROW_LOGIC("[ERROR] Could not find or read from sequence file: %s\n", sequenceFilePath.c_str());
|
if (status == false) JAFFAR_THROW_LOGIC("[ERROR] Could not find or read from sequence file: %s\n", sequenceFilePath.c_str());
|
||||||
|
|
||||||
// Building sequence information
|
// Building sequence information
|
||||||
const auto sequence = jaffarCommon::string::split(inputSequence, ' ');
|
const auto sequence = jaffarCommon::string::split(inputSequence, '\n');
|
||||||
|
|
||||||
// Initializing terminal
|
// Initializing terminal
|
||||||
jaffarCommon::logger::initializeTerminal();
|
jaffarCommon::logger::initializeTerminal();
|
||||||
|
@ -112,16 +112,15 @@ int main(int argc, char *argv[])
|
||||||
jaffarCommon::logger::refreshTerminal();
|
jaffarCommon::logger::refreshTerminal();
|
||||||
|
|
||||||
// Creating emulator instance
|
// Creating emulator instance
|
||||||
NESInstance e;
|
nlohmann::json emulatorConfig;
|
||||||
|
emulatorConfig["Controller 1 Type"] = controller1Type;
|
||||||
|
emulatorConfig["Controller 2 Type"] = controller2Type;
|
||||||
|
NESInstance e(emulatorConfig);
|
||||||
|
|
||||||
// Setting controller types
|
|
||||||
e.setController1Type(controller1Type);
|
|
||||||
e.setController2Type(controller2Type);
|
|
||||||
|
|
||||||
// Loading ROM File
|
// Loading ROM File
|
||||||
std::string romFileData;
|
std::string romFileData;
|
||||||
if (jaffarCommon::file::loadStringFromFile(romFileData, romFilePath) == false) JAFFAR_THROW_LOGIC("Could not rom file: %s\n", romFilePath.c_str());
|
if (jaffarCommon::file::loadStringFromFile(romFileData, romFilePath) == false) JAFFAR_THROW_LOGIC("Could not rom file: %s\n", romFilePath.c_str());
|
||||||
e.loadROM((uint8_t*)romFileData.data(), romFileData.size());
|
e.loadROM((uint8_t *)romFileData.data(), romFileData.size());
|
||||||
|
|
||||||
// If an initial state is provided, load it now
|
// If an initial state is provided, load it now
|
||||||
if (stateFilePath != "")
|
if (stateFilePath != "")
|
||||||
|
@ -136,7 +135,7 @@ int main(int argc, char *argv[])
|
||||||
auto p = PlaybackInstance(&e);
|
auto p = PlaybackInstance(&e);
|
||||||
|
|
||||||
// If render is enabled then, create window now
|
// If render is enabled then, create window now
|
||||||
SDL_Window* window = nullptr;
|
SDL_Window *window = nullptr;
|
||||||
if (disableRender == false)
|
if (disableRender == false)
|
||||||
{
|
{
|
||||||
window = launchOutputWindow();
|
window = launchOutputWindow();
|
||||||
|
@ -166,7 +165,7 @@ int main(int argc, char *argv[])
|
||||||
if (disableRender == false) p.renderFrame(currentStep);
|
if (disableRender == false) p.renderFrame(currentStep);
|
||||||
|
|
||||||
// Getting input
|
// Getting input
|
||||||
const auto &input = p.getStateInput(currentStep);
|
const auto &inputString = p.getInputString(currentStep);
|
||||||
|
|
||||||
// Getting state hash
|
// Getting state hash
|
||||||
const auto hash = p.getStateHash(currentStep);
|
const auto hash = p.getStateHash(currentStep);
|
||||||
|
@ -181,8 +180,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
jaffarCommon::logger::log("[] ----------------------------------------------------------------\n");
|
jaffarCommon::logger::log("[] ----------------------------------------------------------------\n");
|
||||||
jaffarCommon::logger::log("[] Current Step #: %lu / %lu\n", currentStep + 1, sequenceLength);
|
jaffarCommon::logger::log("[] Current Step #: %lu / %lu\n", currentStep + 1, sequenceLength);
|
||||||
jaffarCommon::logger::log("[] Input: %s\n", input.c_str());
|
jaffarCommon::logger::log("[] Input: %s\n", inputString.c_str());
|
||||||
jaffarCommon::logger::log("[] State Hash: 0x%lX%lX\n", hash.first, hash.second);
|
jaffarCommon::logger::log("[] State Hash: 0x%lX%lX\n", hash.first, hash.second);
|
||||||
|
jaffarCommon::logger::log("[] Paddle X: %u\n", e.getLowMem()[0x11A]);
|
||||||
|
|
||||||
// Only print commands if not in reproduce mode
|
// Only print commands if not in reproduce mode
|
||||||
if (isReproduce == false) jaffarCommon::logger::log("[] Commands: n: -1 m: +1 | h: -10 | j: +10 | y: -100 | u: +100 | k: -1000 | i: +1000 | s: quicksave | p: play | q: quit\n");
|
if (isReproduce == false) jaffarCommon::logger::log("[] Commands: n: -1 m: +1 | h: -10 | j: +10 | y: -100 | u: +100 | k: -1000 | i: +1000 | s: quicksave | p: play | q: quit\n");
|
||||||
|
|
|
@ -73,5 +73,8 @@ quickNESSrc = [
|
||||||
quickNESDependency = declare_dependency(
|
quickNESDependency = declare_dependency(
|
||||||
compile_args : [ ],
|
compile_args : [ ],
|
||||||
include_directories : include_directories(['.', 'core/nes_emu']),
|
include_directories : include_directories(['.', 'core/nes_emu']),
|
||||||
sources : [ quickNESSrc ]
|
sources : [ quickNESSrc ],
|
||||||
|
dependencies : [
|
||||||
|
dependency('sdl2'),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "jaffarCommon/serializers/base.hpp"
|
#include "../nesInstanceBase.hpp"
|
||||||
#include "jaffarCommon/deserializers/base.hpp"
|
|
||||||
#include "core/nes_emu/Nes_Emu.h"
|
#include "core/nes_emu/Nes_Emu.h"
|
||||||
#include "core/nes_emu/Nes_State.h"
|
#include "core/nes_emu/Nes_State.h"
|
||||||
#include "../nesInstanceBase.hpp"
|
#include "jaffarCommon/deserializers/base.hpp"
|
||||||
|
#include "jaffarCommon/serializers/base.hpp"
|
||||||
|
|
||||||
#define _DUMMY_SIZE 65536
|
#define _DUMMY_SIZE 65536
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ extern void register_mapper_70();
|
||||||
class NESInstance final : public NESInstanceBase
|
class NESInstance final : public NESInstanceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NESInstance() : NESInstanceBase()
|
NESInstance(const nlohmann::json &config) : NESInstanceBase(config)
|
||||||
{
|
{
|
||||||
// If running the original QuickNES, register extra mappers now
|
// If running the original QuickNES, register extra mappers now
|
||||||
register_misc_mappers();
|
register_misc_mappers();
|
||||||
|
@ -28,14 +28,14 @@ class NESInstance final : public NESInstanceBase
|
||||||
uint8_t *getLowMem() const override { return _nes.low_mem(); };
|
uint8_t *getLowMem() const override { return _nes.low_mem(); };
|
||||||
size_t getLowMemSize() const override { return 0x800; };
|
size_t getLowMemSize() const override { return 0x800; };
|
||||||
|
|
||||||
void serializeState(jaffarCommon::serializer::Base& serializer) const override
|
void serializeState(jaffarCommon::serializer::Base &serializer) const override
|
||||||
{
|
{
|
||||||
Mem_Writer w(serializer.getOutputDataBuffer(), _stateSize, 0);
|
Mem_Writer w(serializer.getOutputDataBuffer(), _stateSize, 0);
|
||||||
Auto_File_Writer a(w);
|
Auto_File_Writer a(w);
|
||||||
_nes.save_state(a);
|
_nes.save_state(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserializeState(jaffarCommon::deserializer::Base& deserializer) override
|
void deserializeState(jaffarCommon::deserializer::Base &deserializer) override
|
||||||
{
|
{
|
||||||
Mem_File_Reader r(deserializer.getInputDataBuffer(), _stateSize);
|
Mem_File_Reader r(deserializer.getInputDataBuffer(), _stateSize);
|
||||||
Auto_File_Reader a(r);
|
Auto_File_Reader a(r);
|
||||||
|
@ -60,9 +60,14 @@ class NESInstance final : public NESInstanceBase
|
||||||
|
|
||||||
void *getInternalEmulatorPointer() override { return &_nes; }
|
void *getInternalEmulatorPointer() override { return &_nes; }
|
||||||
|
|
||||||
protected:
|
void advanceState(const jaffar::input_t &input) override
|
||||||
|
{
|
||||||
|
if (_doRendering == true) _nes.emulate_frame(input.port1, input.port2);
|
||||||
|
if (_doRendering == false) _nes.emulate_skip_frame(input.port1, input.port2);
|
||||||
|
}
|
||||||
|
|
||||||
bool loadROMImpl(const uint8_t* romData, const size_t romSize) override
|
protected:
|
||||||
|
bool loadROMImpl(const uint8_t *romData, const size_t romSize) override
|
||||||
{
|
{
|
||||||
// Loading rom data
|
// Loading rom data
|
||||||
Mem_File_Reader romReader(romData, (int)romSize);
|
Mem_File_Reader romReader(romData, (int)romSize);
|
||||||
|
@ -71,17 +76,10 @@ class NESInstance final : public NESInstanceBase
|
||||||
return result == 0;
|
return result == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableStateBlockImpl(const std::string& block) override {};
|
void enableStateBlockImpl(const std::string &block) override {};
|
||||||
void disableStateBlockImpl(const std::string& block) override {};
|
void disableStateBlockImpl(const std::string &block) override {};
|
||||||
|
|
||||||
void advanceStateImpl(const quickNES::Controller::port_t controller1, const quickNES::Controller::port_t controller2) override
|
|
||||||
{
|
|
||||||
if (_doRendering == true) _nes.emulate_frame(controller1, controller2);
|
|
||||||
if (_doRendering == false) _nes.emulate_skip_frame(controller1, controller2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Emulator instance
|
// Emulator instance
|
||||||
emulator_t _nes;
|
emulator_t _nes;
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,4 +82,4 @@ void Nes_Effects_Buffer::RestoreAudioBufferState()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,8 +3,8 @@
|
||||||
// Effects_Buffer with non-linear sound
|
// Effects_Buffer with non-linear sound
|
||||||
// Nes_Emu 0.7.0
|
// Nes_Emu 0.7.0
|
||||||
|
|
||||||
#include "effectsBuffer.hpp"
|
|
||||||
#include "buffer.hpp"
|
#include "buffer.hpp"
|
||||||
|
#include "effectsBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -38,4 +38,4 @@ class Nes_Effects_Buffer : public Effects_Buffer
|
||||||
friend Multi_Buffer *set_apu(Nes_Effects_Buffer *, Apu *);
|
friend Multi_Buffer *set_apu(Nes_Effects_Buffer *, Apu *);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -19,7 +19,7 @@ namespace quickerNES
|
||||||
int const amp_range = 15;
|
int const amp_range = 15;
|
||||||
|
|
||||||
Apu::Apu() : square1(&square_synth),
|
Apu::Apu() : square1(&square_synth),
|
||||||
square2(&square_synth)
|
square2(&square_synth)
|
||||||
{
|
{
|
||||||
dmc.apu = this;
|
dmc.apu = this;
|
||||||
dmc.prg_reader = 0;
|
dmc.prg_reader = 0;
|
||||||
|
@ -372,4 +372,4 @@ int Apu::read_status(nes_time_t time)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,9 +3,9 @@
|
||||||
// NES 2A03 APU sound chip emulator
|
// NES 2A03 APU sound chip emulator
|
||||||
// Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
|
#include "oscs.hpp"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "oscs.hpp"
|
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -360,4 +360,4 @@ inline void Apu::load_state(apu_state_t const &state)
|
||||||
dmc.run(last_time, last_time);
|
dmc.run(last_time, last_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
|
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
|
#include "blipBuffer.hpp"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "blipBuffer.hpp"
|
|
||||||
|
|
||||||
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
||||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
@ -419,4 +419,4 @@ void Blip_Buffer::RestoreAudioBufferState()
|
||||||
memcpy(buffer_, extra_buffer, sizeof(extra_buffer));
|
memcpy(buffer_, extra_buffer, sizeof(extra_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -377,4 +377,4 @@ inline int Blip_Reader::begin(Blip_Buffer &blip_buf)
|
||||||
int const blip_max_length = 0;
|
int const blip_max_length = 0;
|
||||||
int const blip_default_length = 250;
|
int const blip_default_length = 250;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -227,4 +227,4 @@ void Nonlinearizer::RestoreAudioBufferState()
|
||||||
prev = extra_prev;
|
prev = extra_prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,8 +3,8 @@
|
||||||
// NES non-linear audio buffer
|
// NES non-linear audio buffer
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "multiBuffer.hpp"
|
#include "multiBuffer.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -79,4 +79,4 @@ class Buffer : public Multi_Buffer
|
||||||
virtual void RestoreAudioBufferState();
|
virtual void RestoreAudioBufferState();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -1,7 +1,7 @@
|
||||||
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
|
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include "effectsBuffer.hpp"
|
#include "effectsBuffer.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
||||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
@ -515,4 +515,4 @@ void Effects_Buffer::mix_enhanced(blip_sample_t *out, long count)
|
||||||
r2.end(bufs[6]);
|
r2.end(bufs[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,11 +3,11 @@
|
||||||
// Multi-channel effects buffer with panning, echo and reverb
|
// Multi-channel effects buffer with panning, echo and reverb
|
||||||
// Game_Music_Emu 0.3.0
|
// Game_Music_Emu 0.3.0
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "multiBuffer.hpp"
|
#include "multiBuffer.hpp"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
||||||
class Effects_Buffer : public Multi_Buffer
|
class Effects_Buffer : public Multi_Buffer
|
||||||
|
@ -101,4 +101,4 @@ inline Effects_Buffer::channel_t Effects_Buffer::channel(int i)
|
||||||
return channels[i % chan_count];
|
return channels[i % chan_count];
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -105,4 +105,4 @@ void Fme7_Apu::run_until(blip_time_t end_time)
|
||||||
last_time = end_time;
|
last_time = end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,8 +3,8 @@
|
||||||
// Sunsoft FME-7 sound emulator
|
// Sunsoft FME-7 sound emulator
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../blipBuffer.hpp"
|
#include "../blipBuffer.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -152,4 +152,4 @@ inline void Fme7_Apu::load_state(fme7_apu_state_t const &in)
|
||||||
run_until(last_time);
|
run_until(last_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
|
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "multiBuffer.hpp"
|
#include "multiBuffer.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
||||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
@ -284,4 +284,4 @@ void Stereo_Buffer::RestoreAudioBufferState()
|
||||||
right()->RestoreAudioBufferState();
|
right()->RestoreAudioBufferState();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -199,4 +199,4 @@ inline long Mono_Buffer::read_samples(blip_sample_t *p, long s) { return buf.rea
|
||||||
|
|
||||||
inline long Mono_Buffer::samples_avail() const { return buf.samples_avail(); }
|
inline long Mono_Buffer::samples_avail() const { return buf.samples_avail(); }
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -180,4 +180,4 @@ void Namco_Apu::load_state(namco_state_t const &in)
|
||||||
run_until(last_time);
|
run_until(last_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,8 +3,8 @@
|
||||||
// Namco 106 sound chip emulator
|
// Namco 106 sound chip emulator
|
||||||
// Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../apu.hpp"
|
#include "../apu.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -112,4 +112,4 @@ inline void Namco_Apu::write_data(nes_time_t time, int data)
|
||||||
access() = data;
|
access() = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -679,4 +679,4 @@ void Noise::run(nes_time_t time, nes_time_t end_time)
|
||||||
delay = time - end_time;
|
delay = time - end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -169,4 +169,4 @@ struct Dmc : Osc
|
||||||
nes_time_t next_read_time() const;
|
nes_time_t next_read_time() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -212,4 +212,4 @@ void Vrc6_Apu::run_saw(nes_time_t end_time)
|
||||||
osc.last_amp = last_amp;
|
osc.last_amp = last_amp;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -4,9 +4,9 @@
|
||||||
// Konami VRC6 sound chip emulator
|
// Konami VRC6 sound chip emulator
|
||||||
// Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../blipBuffer.hpp"
|
|
||||||
#include "../apu.hpp"
|
#include "../apu.hpp"
|
||||||
|
#include "../blipBuffer.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -109,4 +109,4 @@ inline void Vrc6_Apu::treble_eq(blip_eq_t const &eq)
|
||||||
square_synth.treble_eq(eq);
|
square_synth.treble_eq(eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -1,6 +1,6 @@
|
||||||
#include <cstring>
|
|
||||||
#include "apu_vrc7.hpp"
|
#include "apu_vrc7.hpp"
|
||||||
#include "emu2413.hpp"
|
#include "emu2413.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -208,4 +208,4 @@ void Vrc7::update_last_amp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -4,9 +4,9 @@
|
||||||
// Konami VRC7 sound chip emulator
|
// Konami VRC7 sound chip emulator
|
||||||
// Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
|
// Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../blipBuffer.hpp"
|
#include "../blipBuffer.hpp"
|
||||||
#include "emu2413_state.hpp"
|
#include "emu2413_state.hpp"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -76,4 +76,4 @@ inline void Vrc7::osc_output(int i, Blip_Buffer *buf)
|
||||||
oscs[i].output = buf;
|
oscs[i].output = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -108,7 +108,7 @@ static const unsigned char default_inst[15][8] = {
|
||||||
|
|
||||||
/* AM speed(Hz) and depth(dB) */
|
/* AM speed(Hz) and depth(dB) */
|
||||||
#define AM_SPEED 3.7
|
#define AM_SPEED 3.7
|
||||||
//#define AM_DEPTH 4.8
|
// #define AM_DEPTH 4.8
|
||||||
#define AM_DEPTH 2.4
|
#define AM_DEPTH 2.4
|
||||||
|
|
||||||
/* Cut the lower b bit(s) off. */
|
/* Cut the lower b bit(s) off. */
|
||||||
|
@ -243,7 +243,7 @@ static void makeDphaseTable(OPLL *opll)
|
||||||
|
|
||||||
static void makeTllTable(OPLL *opll)
|
static void makeTllTable(OPLL *opll)
|
||||||
{
|
{
|
||||||
#define dB2(x) ((x)*2)
|
#define dB2(x) ((x) * 2)
|
||||||
|
|
||||||
static const double kltable[16] = {
|
static const double kltable[16] = {
|
||||||
dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)};
|
dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)};
|
||||||
|
@ -1152,4 +1152,4 @@ void OPLL_writeIO(OPLL *opll, e_uint32 adr, e_uint32 val)
|
||||||
opll->adr = val;
|
opll->adr = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -220,4 +220,4 @@ extern "C"
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
e_int32 feedback;
|
e_int32 feedback;
|
||||||
|
@ -38,4 +38,4 @@ extern "C"
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -114,4 +114,4 @@ class Cart
|
||||||
unsigned mapper;
|
unsigned mapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -15,15 +15,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include "cpu.hpp"
|
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
|
#include "cpu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include "ppu/ppu.hpp"
|
#include "ppu/ppu.hpp"
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
|
||||||
#include <jaffarCommon/serializers/base.hpp>
|
|
||||||
#include <jaffarCommon/deserializers/base.hpp>
|
#include <jaffarCommon/deserializers/base.hpp>
|
||||||
|
#include <jaffarCommon/serializers/base.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -53,18 +54,21 @@ struct nes_state_t
|
||||||
|
|
||||||
struct nes_state_lite_t
|
struct nes_state_lite_t
|
||||||
{
|
{
|
||||||
uint16_t timestamp; // CPU clocks * 15 (for NTSC)
|
uint16_t timestamp; // CPU clocks * 15 (for NTSC)
|
||||||
uint8_t frame_count; // number of frames emulated since power-up
|
uint8_t frame_count; // number of frames emulated since power-up
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct input_state_t
|
||||||
struct joypad_state_t
|
|
||||||
{
|
{
|
||||||
uint32_t joypad_latches[2]; // joypad 1 & 2 shift registers
|
uint32_t joypad_latches[2]; // input_state 1 & 2 shift registers
|
||||||
|
|
||||||
|
#ifdef _QUICKERNES_SUPPORT_ARKANOID_INPUTS
|
||||||
|
uint32_t arkanoid_latch; // arkanoid latch
|
||||||
|
uint8_t arkanoid_fire; // arkanoid latch
|
||||||
|
#endif
|
||||||
|
|
||||||
uint8_t w4016; // strobe
|
uint8_t w4016; // strobe
|
||||||
uint8_t unused[3];
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(joypad_state_t) == 12);
|
|
||||||
|
|
||||||
struct cpu_state_t
|
struct cpu_state_t
|
||||||
{
|
{
|
||||||
|
@ -83,6 +87,7 @@ class Core : private Cpu
|
||||||
typedef Cpu cpu;
|
typedef Cpu cpu;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
size_t _NTABBlockSize = 0x1000;
|
||||||
|
|
||||||
// Flags for lite state storage
|
// Flags for lite state storage
|
||||||
bool TIMEBlockEnabled = true;
|
bool TIMEBlockEnabled = true;
|
||||||
|
@ -97,13 +102,22 @@ class Core : private Cpu
|
||||||
bool CHRRBlockEnabled = true;
|
bool CHRRBlockEnabled = true;
|
||||||
bool SRAMBlockEnabled = true;
|
bool SRAMBlockEnabled = true;
|
||||||
|
|
||||||
|
// APU and Joypad
|
||||||
|
enum controllerType_t
|
||||||
|
{
|
||||||
|
none_t,
|
||||||
|
joypad_t,
|
||||||
|
arkanoidNES_t,
|
||||||
|
arkanoidFamicom_t,
|
||||||
|
};
|
||||||
|
|
||||||
Core() : ppu(this)
|
Core() : ppu(this)
|
||||||
{
|
{
|
||||||
cart = NULL;
|
cart = NULL;
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
mapper = NULL;
|
mapper = NULL;
|
||||||
memset(&nes, 0, sizeof nes);
|
memset(&nes, 0, sizeof nes);
|
||||||
memset(&joypad, 0, sizeof joypad);
|
memset(&input_state, 0, sizeof input_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Core()
|
~Core()
|
||||||
|
@ -153,7 +167,7 @@ class Core : private Cpu
|
||||||
reset(true, true);
|
reset(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void serializeState(jaffarCommon::serializer::Base& serializer) const
|
inline void serializeState(jaffarCommon::serializer::Base &serializer) const
|
||||||
{
|
{
|
||||||
// TIME Block
|
// TIME Block
|
||||||
if (TIMEBlockEnabled == true)
|
if (TIMEBlockEnabled == true)
|
||||||
|
@ -205,8 +219,8 @@ class Core : private Cpu
|
||||||
// CTRL Block
|
// CTRL Block
|
||||||
if (CTRLBlockEnabled == true)
|
if (CTRLBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto inputDataSize = sizeof(joypad_state_t);
|
const auto inputDataSize = sizeof(input_state_t);
|
||||||
const auto inputData = (uint8_t *)&joypad;
|
const auto inputData = (uint8_t *)&input_state;
|
||||||
serializer.pushContiguous(inputData, inputDataSize);
|
serializer.pushContiguous(inputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,9 +251,7 @@ class Core : private Cpu
|
||||||
// NTAB Block
|
// NTAB Block
|
||||||
if (NTABBlockEnabled == true)
|
if (NTABBlockEnabled == true)
|
||||||
{
|
{
|
||||||
size_t nametable_size = 0x1000;
|
const auto inputDataSize = _NTABBlockSize;
|
||||||
|
|
||||||
const auto inputDataSize = nametable_size;
|
|
||||||
const auto inputData = (uint8_t *)ppu.impl->nt_ram;
|
const auto inputData = (uint8_t *)ppu.impl->nt_ram;
|
||||||
serializer.push(inputData, inputDataSize);
|
serializer.push(inputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +279,7 @@ class Core : private Cpu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void deserializeState(jaffarCommon::deserializer::Base& deserializer)
|
inline void deserializeState(jaffarCommon::deserializer::Base &deserializer)
|
||||||
{
|
{
|
||||||
disable_rendering();
|
disable_rendering();
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
|
@ -276,10 +288,10 @@ class Core : private Cpu
|
||||||
// TIME Block
|
// TIME Block
|
||||||
if (TIMEBlockEnabled == true)
|
if (TIMEBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) &nes;
|
const auto outputData = (uint8_t *)&nes;
|
||||||
const auto inputDataSize = sizeof(nes_state_t);
|
const auto inputDataSize = sizeof(nes_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
|
|
||||||
nes.timestamp /= 5;
|
nes.timestamp /= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +299,8 @@ class Core : private Cpu
|
||||||
if (CPURBlockEnabled == true)
|
if (CPURBlockEnabled == true)
|
||||||
{
|
{
|
||||||
cpu_state_t s;
|
cpu_state_t s;
|
||||||
|
|
||||||
const auto outputData = (uint8_t*) &s;
|
const auto outputData = (uint8_t *)&s;
|
||||||
const auto inputDataSize = sizeof(cpu_state_t);
|
const auto inputDataSize = sizeof(cpu_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
|
|
||||||
|
@ -303,7 +315,7 @@ class Core : private Cpu
|
||||||
// PPUR Block
|
// PPUR Block
|
||||||
if (PPURBlockEnabled == true)
|
if (PPURBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) &ppu;
|
const auto outputData = (uint8_t *)&ppu;
|
||||||
const auto inputDataSize = sizeof(ppu_state_t);
|
const auto inputDataSize = sizeof(ppu_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +325,7 @@ class Core : private Cpu
|
||||||
{
|
{
|
||||||
Apu::apu_state_t apuState;
|
Apu::apu_state_t apuState;
|
||||||
|
|
||||||
const auto outputData = (uint8_t*) &apuState;
|
const auto outputData = (uint8_t *)&apuState;
|
||||||
const auto inputDataSize = sizeof(Apu::apu_state_t);
|
const auto inputDataSize = sizeof(Apu::apu_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
|
|
||||||
|
@ -324,8 +336,8 @@ class Core : private Cpu
|
||||||
// CTRL Block
|
// CTRL Block
|
||||||
if (CTRLBlockEnabled == true)
|
if (CTRLBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) &joypad;
|
const auto outputData = (uint8_t *)&input_state;
|
||||||
const auto inputDataSize = sizeof(joypad_state_t);
|
const auto inputDataSize = sizeof(input_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +346,7 @@ class Core : private Cpu
|
||||||
{
|
{
|
||||||
mapper->default_reset_state();
|
mapper->default_reset_state();
|
||||||
|
|
||||||
const auto outputData = (uint8_t*) mapper->state;
|
const auto outputData = (uint8_t *)mapper->state;
|
||||||
const auto inputDataSize = mapper->state_size;
|
const auto inputDataSize = mapper->state_size;
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
|
|
||||||
|
@ -344,7 +356,7 @@ class Core : private Cpu
|
||||||
// LRAM Block
|
// LRAM Block
|
||||||
if (LRAMBlockEnabled == true)
|
if (LRAMBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) low_mem;
|
const auto outputData = (uint8_t *)low_mem;
|
||||||
const auto inputDataSize = low_ram_size;
|
const auto inputDataSize = low_ram_size;
|
||||||
deserializer.pop(outputData, inputDataSize);
|
deserializer.pop(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
@ -352,7 +364,7 @@ class Core : private Cpu
|
||||||
// SPRT Block
|
// SPRT Block
|
||||||
if (SPRTBlockEnabled == true)
|
if (SPRTBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) ppu.spr_ram;
|
const auto outputData = (uint8_t *)ppu.spr_ram;
|
||||||
const auto inputDataSize = Ppu::spr_ram_size;
|
const auto inputDataSize = Ppu::spr_ram_size;
|
||||||
deserializer.pop(outputData, inputDataSize);
|
deserializer.pop(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
@ -360,10 +372,8 @@ class Core : private Cpu
|
||||||
// NTAB Block
|
// NTAB Block
|
||||||
if (NTABBlockEnabled == true)
|
if (NTABBlockEnabled == true)
|
||||||
{
|
{
|
||||||
size_t nametable_size = 0x1000;
|
const auto outputData = (uint8_t *)ppu.impl->nt_ram;
|
||||||
|
const auto inputDataSize = _NTABBlockSize;
|
||||||
const auto outputData = (uint8_t*) ppu.impl->nt_ram;
|
|
||||||
const auto inputDataSize = nametable_size;
|
|
||||||
deserializer.pop(outputData, inputDataSize);
|
deserializer.pop(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +382,7 @@ class Core : private Cpu
|
||||||
{
|
{
|
||||||
if (ppu.chr_is_writable)
|
if (ppu.chr_is_writable)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) ppu.impl->chr_ram;
|
const auto outputData = (uint8_t *)ppu.impl->chr_ram;
|
||||||
const auto inputDataSize = ppu.chr_size;
|
const auto inputDataSize = ppu.chr_size;
|
||||||
deserializer.pop(outputData, inputDataSize);
|
deserializer.pop(outputData, inputDataSize);
|
||||||
|
|
||||||
|
@ -385,7 +395,7 @@ class Core : private Cpu
|
||||||
{
|
{
|
||||||
if (sram_present)
|
if (sram_present)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t*) impl->sram;
|
const auto outputData = (uint8_t *)impl->sram;
|
||||||
const auto inputDataSize = impl->sram_size;
|
const auto inputDataSize = impl->sram_size;
|
||||||
deserializer.pop(outputData, inputDataSize);
|
deserializer.pop(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
@ -394,45 +404,141 @@ class Core : private Cpu
|
||||||
if (sram_present) enable_sram(true);
|
if (sram_present) enable_sram(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableStateBlock(const std::string& block)
|
void setNTABBlockSize(const size_t size) { _NTABBlockSize = size; }
|
||||||
{
|
|
||||||
bool recognizedBlock = false;
|
|
||||||
|
|
||||||
if (block == "TIME") { TIMEBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "CPUR") { CPURBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "PPUR") { PPURBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "APUR") { APURBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "CTRL") { CTRLBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "MAPR") { MAPRBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "LRAM") { LRAMBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "SPRT") { SPRTBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "NTAB") { NTABBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "CHRR") { CHRRBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
if (block == "SRAM") { SRAMBlockEnabled = true; recognizedBlock = true; }
|
|
||||||
|
|
||||||
if (recognizedBlock == false) { fprintf(stderr, "Unrecognized block type: %s\n", block.c_str()); exit(-1);}
|
void enableStateBlock(const std::string &block)
|
||||||
};
|
{
|
||||||
|
bool recognizedBlock = false;
|
||||||
|
|
||||||
|
if (block == "TIME")
|
||||||
|
{
|
||||||
|
TIMEBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CPUR")
|
||||||
|
{
|
||||||
|
CPURBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "PPUR")
|
||||||
|
{
|
||||||
|
PPURBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "APUR")
|
||||||
|
{
|
||||||
|
APURBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CTRL")
|
||||||
|
{
|
||||||
|
CTRLBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "MAPR")
|
||||||
|
{
|
||||||
|
MAPRBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "LRAM")
|
||||||
|
{
|
||||||
|
LRAMBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "SPRT")
|
||||||
|
{
|
||||||
|
SPRTBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "NTAB")
|
||||||
|
{
|
||||||
|
NTABBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CHRR")
|
||||||
|
{
|
||||||
|
CHRRBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "SRAM")
|
||||||
|
{
|
||||||
|
SRAMBlockEnabled = true;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
void disableStateBlock(const std::string& block)
|
if (recognizedBlock == false)
|
||||||
{
|
{
|
||||||
bool recognizedBlock = false;
|
fprintf(stderr, "Unrecognized block type: %s\n", block.c_str());
|
||||||
|
exit(-1);
|
||||||
if (block == "TIME") { TIMEBlockEnabled = false; recognizedBlock = true; }
|
}
|
||||||
if (block == "CPUR") { CPURBlockEnabled = false; recognizedBlock = true; }
|
};
|
||||||
if (block == "PPUR") { PPURBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "APUR") { APURBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "CTRL") { CTRLBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "MAPR") { MAPRBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "LRAM") { LRAMBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "SPRT") { SPRTBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "NTAB") { NTABBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "CHRR") { CHRRBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
if (block == "SRAM") { SRAMBlockEnabled = false; recognizedBlock = true; }
|
|
||||||
|
|
||||||
if (recognizedBlock == false) { fprintf(stderr, "Unrecognized block type: %s\n", block.c_str()); exit(-1);}
|
void disableStateBlock(const std::string &block)
|
||||||
};
|
{
|
||||||
|
bool recognizedBlock = false;
|
||||||
|
|
||||||
|
if (block == "TIME")
|
||||||
|
{
|
||||||
|
TIMEBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CPUR")
|
||||||
|
{
|
||||||
|
CPURBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "PPUR")
|
||||||
|
{
|
||||||
|
PPURBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "APUR")
|
||||||
|
{
|
||||||
|
APURBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CTRL")
|
||||||
|
{
|
||||||
|
CTRLBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "MAPR")
|
||||||
|
{
|
||||||
|
MAPRBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "LRAM")
|
||||||
|
{
|
||||||
|
LRAMBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "SPRT")
|
||||||
|
{
|
||||||
|
SPRTBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "NTAB")
|
||||||
|
{
|
||||||
|
NTABBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "CHRR")
|
||||||
|
{
|
||||||
|
CHRRBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
if (block == "SRAM")
|
||||||
|
{
|
||||||
|
SRAMBlockEnabled = false;
|
||||||
|
recognizedBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recognizedBlock == false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unrecognized block type: %s\n", block.c_str());
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void reset(bool full_reset, bool erase_battery_ram)
|
void reset(bool full_reset, bool erase_battery_ram)
|
||||||
{
|
{
|
||||||
|
@ -456,8 +562,13 @@ void disableStateBlock(const std::string& block)
|
||||||
if (!cart->has_battery_ram() || erase_battery_ram)
|
if (!cart->has_battery_ram() || erase_battery_ram)
|
||||||
memset(impl->sram, 0xFF, impl->sram_size);
|
memset(impl->sram, 0xFF, impl->sram_size);
|
||||||
|
|
||||||
joypad.joypad_latches[0] = 0;
|
input_state.joypad_latches[0] = 0;
|
||||||
joypad.joypad_latches[1] = 0;
|
input_state.joypad_latches[1] = 0;
|
||||||
|
|
||||||
|
#ifdef _QUICKERNES_SUPPORT_ARKANOID_INPUTS
|
||||||
|
input_state.arkanoid_latch = 0;
|
||||||
|
input_state.arkanoid_fire = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
nes.frame_count = 0;
|
nes.frame_count = 0;
|
||||||
}
|
}
|
||||||
|
@ -479,14 +590,16 @@ void disableStateBlock(const std::string& block)
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nes_time_t emulate_frame(uint32_t joypad1, uint32_t joypad2)
|
nes_time_t emulate_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire)
|
||||||
{
|
{
|
||||||
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
||||||
joypad_read_count = 0;
|
joypad_read_count = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
current_joypad[0] = joypad1;
|
current_joypad[0] = joypad1;
|
||||||
current_joypad[1] = joypad2;
|
current_joypad[1] = joypad2;
|
||||||
|
current_arkanoid_latch = arkanoid_latch;
|
||||||
|
current_arkanoid_fire = arkanoid_fire;
|
||||||
|
|
||||||
cpu_time_offset = ppu.begin_frame(nes.timestamp) - 1;
|
cpu_time_offset = ppu.begin_frame(nes.timestamp) - 1;
|
||||||
ppu_2002_time = 0;
|
ppu_2002_time = 0;
|
||||||
|
@ -556,6 +669,8 @@ void disableStateBlock(const std::string& block)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t current_joypad[2];
|
uint32_t current_joypad[2];
|
||||||
|
uint32_t current_arkanoid_latch;
|
||||||
|
uint8_t current_arkanoid_fire;
|
||||||
Cart const *cart;
|
Cart const *cart;
|
||||||
Mapper *mapper;
|
Mapper *mapper;
|
||||||
nes_state_t nes;
|
nes_state_t nes;
|
||||||
|
@ -604,24 +719,98 @@ void disableStateBlock(const std::string& block)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// APU and Joypad
|
|
||||||
joypad_state_t joypad;
|
|
||||||
|
|
||||||
|
controllerType_t _controllerType = controllerType_t::none_t;
|
||||||
|
|
||||||
|
input_state_t input_state;
|
||||||
|
|
||||||
|
void setControllerType(controllerType_t type) { _controllerType = type; }
|
||||||
|
|
||||||
|
#ifdef _QUICKERNES_SUPPORT_ARKANOID_INPUTS
|
||||||
int read_io(nes_addr_t addr)
|
int read_io(nes_addr_t addr)
|
||||||
{
|
{
|
||||||
if ((addr & 0xFFFE) == 0x4016)
|
if ((addr & 0xFFFE) == 0x4016)
|
||||||
{
|
{
|
||||||
// For performance's sake, this counter is only kept on demand
|
// For performance's sake, this counter is only kept on demand
|
||||||
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
||||||
joypad_read_count++;
|
joypad_read_count++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// If write flag is put into w4016, reading from it returns nothing
|
||||||
|
if (input_state.w4016 & 1) return 0;
|
||||||
|
|
||||||
|
// Proceed depending on input type
|
||||||
|
switch(_controllerType)
|
||||||
|
{
|
||||||
|
case controllerType_t::joypad_t:
|
||||||
|
{
|
||||||
|
const uint8_t result = input_state.joypad_latches[addr & 1] & 1;
|
||||||
|
input_state.joypad_latches[addr & 1] >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
case controllerType_t::arkanoidNES_t:
|
||||||
|
{
|
||||||
|
if (addr == 0x4017)
|
||||||
|
{
|
||||||
|
// latch 0 encodes fire, latch 1 encodes potentiometer
|
||||||
|
const uint8_t result = (input_state.arkanoid_latch & 1) * 16 + input_state.arkanoid_fire * 8;
|
||||||
|
|
||||||
|
// Advancing latch 1
|
||||||
|
input_state.arkanoid_latch >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case controllerType_t::arkanoidFamicom_t:
|
||||||
|
{
|
||||||
|
if (addr == 0x4016)
|
||||||
|
{
|
||||||
|
// latch 0 encodes fire
|
||||||
|
uint8_t result = (input_state.arkanoid_fire & 1) * 2;
|
||||||
|
|
||||||
|
// latch 0 also encodes input_state 1
|
||||||
|
result += (input_state.joypad_latches[0] & 1) & 1;
|
||||||
|
|
||||||
|
// Advancing input_state latch
|
||||||
|
input_state.joypad_latches[0] >>= 1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == 0x4017)
|
||||||
|
{
|
||||||
|
// latch 1 encodes potentiometer
|
||||||
|
const uint8_t result = (input_state.arkanoid_latch & 1) * 2;
|
||||||
|
|
||||||
|
// Advancing latch 1
|
||||||
|
input_state.arkanoid_latch >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (addr == Apu::status_addr)
|
||||||
|
return impl->apu.read_status(clock());
|
||||||
|
|
||||||
|
return addr >> 8; // simulate open bus
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int read_io(nes_addr_t addr)
|
||||||
|
{
|
||||||
|
if ((addr & 0xFFFE) == 0x4016)
|
||||||
|
{
|
||||||
// to do: to aid with recording, doesn't emulate transparent latch,
|
// to do: to aid with recording, doesn't emulate transparent latch,
|
||||||
// so a game that held strobe at 1 and read $4016 or $4017 would not get
|
// so a game that held strobe at 1 and read $4016 or $4017 would not get
|
||||||
// the current A status as occurs on a NES
|
// the current A status as occurs on a NES
|
||||||
if (joypad.w4016 & 1) return 0;
|
if (input_state.w4016 & 1) return 0;
|
||||||
const uint8_t result = joypad.joypad_latches[addr & 1] & 1;
|
const uint8_t result = input_state.joypad_latches[addr & 1] & 1;
|
||||||
joypad.joypad_latches[addr & 1] >>= 1;
|
input_state.joypad_latches[addr & 1] >>= 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,6 +819,7 @@ void disableStateBlock(const std::string& block)
|
||||||
|
|
||||||
return addr >> 8; // simulate open bus
|
return addr >> 8; // simulate open bus
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void write_io(nes_addr_t addr, int data)
|
void write_io(nes_addr_t addr, int data)
|
||||||
{
|
{
|
||||||
|
@ -641,16 +831,21 @@ void disableStateBlock(const std::string& block)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// joypad strobe
|
// input_state strobe
|
||||||
if (addr == 0x4016)
|
if (addr == 0x4016)
|
||||||
{
|
{
|
||||||
// if strobe goes low, latch data
|
// if strobe goes low, latch data
|
||||||
if (joypad.w4016 & 1 & ~data)
|
if (input_state.w4016 & 1 & ~data)
|
||||||
{
|
{
|
||||||
joypad.joypad_latches[0] = current_joypad[0];
|
input_state.joypad_latches[0] = current_joypad[0];
|
||||||
joypad.joypad_latches[1] = current_joypad[1];
|
input_state.joypad_latches[1] = current_joypad[1];
|
||||||
|
|
||||||
|
#ifdef _QUICKERNES_SUPPORT_ARKANOID_INPUTS
|
||||||
|
input_state.arkanoid_latch = current_arkanoid_latch;
|
||||||
|
input_state.arkanoid_fire = current_arkanoid_fire;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
joypad.w4016 = data;
|
input_state.w4016 = data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,19 +1180,19 @@ inline void Core::cpu_write(nes_addr_t addr, int data, nes_time_t time)
|
||||||
#define NES_CPU_READ(cpu, addr, time) \
|
#define NES_CPU_READ(cpu, addr, time) \
|
||||||
static_cast<Core &>(*cpu).cpu_read(addr, time)
|
static_cast<Core &>(*cpu).cpu_read(addr, time)
|
||||||
|
|
||||||
#define NES_CPU_WRITEX(cpu, addr, data, time) \
|
#define NES_CPU_WRITEX(cpu, addr, data, time) \
|
||||||
{ \
|
{ \
|
||||||
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NES_CPU_WRITE(cpu, addr, data, time) \
|
#define NES_CPU_WRITE(cpu, addr, data, time) \
|
||||||
{ \
|
{ \
|
||||||
if (addr < 0x800) \
|
if (addr < 0x800) \
|
||||||
cpu->low_mem[addr] = data; \
|
cpu->low_mem[addr] = data; \
|
||||||
else if (addr == 0x2007) \
|
else if (addr == 0x2007) \
|
||||||
static_cast<Core &>(*cpu).cpu_write_2007(data); \
|
static_cast<Core &>(*cpu).cpu_write_2007(data); \
|
||||||
else \
|
else \
|
||||||
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,6 @@ typedef unsigned nes_addr_t; // 16-bit address
|
||||||
class Cpu
|
class Cpu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void set_tracecb(void (*cb)(unsigned int *data))
|
void set_tracecb(void (*cb)(unsigned int *data))
|
||||||
{
|
{
|
||||||
tracecb = cb;
|
tracecb = cb;
|
||||||
|
@ -157,10 +156,10 @@ class Cpu
|
||||||
return (uint8_t *)code_map[addr >> page_bits] + addr;
|
return (uint8_t *)code_map[addr >> page_bits] + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const uint8_t *get_code(nes_addr_t addr) const
|
inline const uint8_t *get_code(nes_addr_t addr) const
|
||||||
{
|
{
|
||||||
return (const uint8_t *)code_map[addr >> page_bits] + addr;
|
return (const uint8_t *)code_map[addr >> page_bits] + addr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
File diff suppressed because it is too large
Load Diff
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
|
#include "apu/multiBuffer.hpp"
|
||||||
#include "cart.hpp"
|
#include "cart.hpp"
|
||||||
#include "core.hpp"
|
#include "core.hpp"
|
||||||
#include "apu/multiBuffer.hpp"
|
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -46,22 +46,25 @@ class Emu
|
||||||
|
|
||||||
int get_joypad_read_count() const { return emu.joypad_read_count; }
|
int get_joypad_read_count() const { return emu.joypad_read_count; }
|
||||||
void set_tracecb(void (*cb)(unsigned int *dest)) { emu.set_tracecb(cb); }
|
void set_tracecb(void (*cb)(unsigned int *dest)) { emu.set_tracecb(cb); }
|
||||||
|
|
||||||
// Save emulator state variants
|
// Save emulator state variants
|
||||||
void serializeState(jaffarCommon::serializer::Base& serializer) const { emu.serializeState(serializer); }
|
void serializeState(jaffarCommon::serializer::Base &serializer) const { emu.serializeState(serializer); }
|
||||||
void deserializeState(jaffarCommon::deserializer::Base& deserializer) { emu.deserializeState(deserializer); }
|
void deserializeState(jaffarCommon::deserializer::Base &deserializer) { emu.deserializeState(deserializer); }
|
||||||
void enableStateBlock(const std::string& block) { emu.enableStateBlock(block); };
|
void setNTABBlockSize(const size_t size) { emu.setNTABBlockSize(size); }
|
||||||
void disableStateBlock(const std::string& block) { emu.disableStateBlock(block); };
|
void enableStateBlock(const std::string &block) { emu.enableStateBlock(block); };
|
||||||
|
void disableStateBlock(const std::string &block) { emu.disableStateBlock(block); };
|
||||||
|
|
||||||
|
void setControllerType(Core::controllerType_t type) { emu.setControllerType(type); }
|
||||||
|
|
||||||
// Basic emulation
|
// Basic emulation
|
||||||
|
|
||||||
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
|
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
|
||||||
// and sound are available for output using the accessors below.
|
// and sound are available for output using the accessors below.
|
||||||
virtual const char *emulate_frame(uint32_t joypad1, uint32_t joypad2 = 0);
|
virtual const char *emulate_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire);
|
||||||
|
|
||||||
// Emulate one video frame using joypad1 and joypad2 as input, but skips drawing.
|
// Emulate one video frame using joypad1 and joypad2 as input, but skips drawing.
|
||||||
// Afterwards, audio is available for output using the accessors below.
|
// Afterwards, audio is available for output using the accessors below.
|
||||||
virtual const char *emulate_skip_frame(uint32_t joypad1, uint32_t joypad2 = 0);
|
virtual const char *emulate_skip_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire);
|
||||||
|
|
||||||
// Maximum size of palette that can be generated
|
// Maximum size of palette that can be generated
|
||||||
static const uint16_t max_palette_size = 256;
|
static const uint16_t max_palette_size = 256;
|
||||||
|
@ -71,7 +74,7 @@ class Emu
|
||||||
{
|
{
|
||||||
static const uint8_t left = 8;
|
static const uint8_t left = 8;
|
||||||
|
|
||||||
int burst_phase; // NTSC burst phase for frame (0, 1, or 2)
|
int burst_phase; // NTSC burst phase for frame (0, 1, or 2)
|
||||||
|
|
||||||
int sample_count; // number of samples (always a multiple of chan_count)
|
int sample_count; // number of samples (always a multiple of chan_count)
|
||||||
int chan_count; // 1: mono, 2: stereo
|
int chan_count; // 1: mono, 2: stereo
|
||||||
|
@ -205,8 +208,8 @@ class Emu
|
||||||
{
|
{
|
||||||
low_mem_size = 0x800
|
low_mem_size = 0x800
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t *get_low_mem() const { return (uint8_t*)emu.low_mem; }
|
uint8_t *get_low_mem() const { return (uint8_t *)emu.low_mem; }
|
||||||
size_t get_low_mem_size() const { return low_mem_size; }
|
size_t get_low_mem_size() const { return low_mem_size; }
|
||||||
|
|
||||||
// Optional 8K memory
|
// Optional 8K memory
|
||||||
|
@ -231,11 +234,11 @@ class Emu
|
||||||
uint8_t *pal_mem() const { return emu.ppu.getPaletteRAM(); }
|
uint8_t *pal_mem() const { return emu.ppu.getPaletteRAM(); }
|
||||||
uint16_t pal_mem_size() const { return emu.ppu.getPaletteRAMSize(); }
|
uint16_t pal_mem_size() const { return emu.ppu.getPaletteRAMSize(); }
|
||||||
|
|
||||||
uint8_t peek_prg(nes_addr_t addr) const { return *emu.get_code(addr); }
|
uint8_t peek_prg(nes_addr_t addr) const { return *emu.get_code(addr); }
|
||||||
void poke_prg(nes_addr_t addr, uint8_t value) { *emu.get_code(addr) = value; }
|
void poke_prg(nes_addr_t addr, uint8_t value) { *emu.get_code(addr) = value; }
|
||||||
uint8_t peek_ppu(int addr) { return emu.ppu.peekaddr(addr); }
|
uint8_t peek_ppu(int addr) { return emu.ppu.peekaddr(addr); }
|
||||||
|
|
||||||
uint8_t get_ppu2000() const { return emu.ppu.w2000; }
|
uint8_t get_ppu2000() const { return emu.ppu.w2000; }
|
||||||
|
|
||||||
void get_regs(unsigned int *dest) const
|
void get_regs(unsigned int *dest) const
|
||||||
{
|
{
|
||||||
|
@ -256,7 +259,7 @@ class Emu
|
||||||
|
|
||||||
virtual void loading_state(State const &) {}
|
virtual void loading_state(State const &) {}
|
||||||
long timestamp() const { return 0; }
|
long timestamp() const { return 0; }
|
||||||
void set_timestamp(long t) { }
|
void set_timestamp(long t) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
|
@ -275,7 +278,7 @@ class Emu
|
||||||
void clear_sound_buf();
|
void clear_sound_buf();
|
||||||
void fade_samples(blip_sample_t *, int size, int step);
|
void fade_samples(blip_sample_t *, int size, int step);
|
||||||
|
|
||||||
void* pixels_base_ptr;
|
void *pixels_base_ptr;
|
||||||
char *host_pixels;
|
char *host_pixels;
|
||||||
int host_palette_size;
|
int host_palette_size;
|
||||||
frame_t single_frame;
|
frame_t single_frame;
|
||||||
|
@ -293,17 +296,15 @@ class Emu
|
||||||
void SaveAudioBufferState();
|
void SaveAudioBufferState();
|
||||||
void RestoreAudioBufferState();
|
void RestoreAudioBufferState();
|
||||||
|
|
||||||
|
inline void *get_pixels_base_ptr()
|
||||||
inline void* get_pixels_base_ptr()
|
|
||||||
{
|
{
|
||||||
return pixels_base_ptr;
|
return pixels_base_ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline void Emu::set_pixels(void *p, long n)
|
inline void Emu::set_pixels(void *p, long n)
|
||||||
{
|
{
|
||||||
pixels_base_ptr = p;
|
pixels_base_ptr = p;
|
||||||
host_pixels = (char *)p + n;
|
host_pixels = (char *)p + n;
|
||||||
emu.ppu.host_row_bytes = n;
|
emu.ppu.host_row_bytes = n;
|
||||||
}
|
}
|
||||||
|
@ -318,4 +319,4 @@ inline long Emu::chr_size() const
|
||||||
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
|
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -291,4 +291,4 @@ Mapper *Mapper::getMapperFromCode(const int mapperCode)
|
||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -3,9 +3,9 @@
|
||||||
// NES mapper interface
|
// NES mapper interface
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include "../cart.hpp"
|
#include "../cart.hpp"
|
||||||
#include "../cpu.hpp"
|
#include "../cpu.hpp"
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -209,4 +209,4 @@ inline bool Mapper::write_intercepted(nes_time_t, nes_addr_t, int) { return fals
|
||||||
|
|
||||||
inline int Mapper::read(nes_time_t, nes_addr_t) { return -1; } // signal to caller
|
inline int Mapper::read(nes_time_t, nes_addr_t) { return -1; } // signal to caller
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -35,4 +35,4 @@ class Mapper000 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -126,4 +126,4 @@ class Mapper001 : public Mapper, mmc1_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -45,4 +45,4 @@ class Mapper002 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -44,4 +44,4 @@ class Mapper003 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -255,4 +255,4 @@ class Mapper004 : public Mapper, mmc3_state_t
|
||||||
int counter_just_clocked; // used only for debugging
|
int counter_just_clocked; // used only for debugging
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -149,4 +149,4 @@ class Mapper005 : public Mapper, mmc5_state_t
|
||||||
nes_time_t irq_time;
|
nes_time_t irq_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -52,4 +52,4 @@ class Mapper007 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -78,4 +78,4 @@ class Mapper009 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -76,4 +76,4 @@ class Mapper010 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -52,4 +52,4 @@ class Mapper011 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -94,4 +94,4 @@ class Mapper015 : public Mapper, Mapper015_state_t
|
||||||
unsigned long int i;
|
unsigned long int i;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -199,4 +199,4 @@ class Mapper019 : public Mapper, namco106_state_t
|
||||||
nes_time_t last_time;
|
nes_time_t last_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -256,4 +256,4 @@ void Mapper_VRC2_4<type_a, type_b>::write_irq(nes_time_t time,
|
||||||
|
|
||||||
typedef Mapper_VRC2_4<true, true> Mapper021;
|
typedef Mapper_VRC2_4<true, true> Mapper021;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -34,4 +34,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_VRC2_4<false, true> Mapper022;
|
typedef Mapper_VRC2_4<false, true> Mapper022;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -33,4 +33,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_VRC2_4<false, false> Mapper023;
|
typedef Mapper_VRC2_4<false, false> Mapper023;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -233,4 +233,4 @@ class Mapper_Vrc6 : public Mapper, vrc6_state_t
|
||||||
|
|
||||||
typedef Mapper_Vrc6<0> Mapper024;
|
typedef Mapper_Vrc6<0> Mapper024;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -33,4 +33,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_VRC2_4<true, false> Mapper025;
|
typedef Mapper_VRC2_4<true, false> Mapper025;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -11,4 +11,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_Vrc6<3> Mapper026;
|
typedef Mapper_Vrc6<3> Mapper026;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -53,4 +53,4 @@ class Mapper030 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -126,4 +126,4 @@ class Mapper032 : public Mapper, mapper32_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -103,4 +103,4 @@ class Mapper033 : public Mapper, tc0190_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -44,4 +44,4 @@ class Mapper034 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -53,4 +53,4 @@ class Mapper060 : public Mapper
|
||||||
uint8_t game_sel, last_game;
|
uint8_t game_sel, last_game;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -52,4 +52,4 @@ class Mapper066 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -190,4 +190,4 @@ class Mapper069 : public Mapper, fme7_state_t
|
||||||
Fme7_Apu sound;
|
Fme7_Apu sound;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -84,4 +84,4 @@ class Mapper_74x161x162x32 : public Mapper
|
||||||
|
|
||||||
typedef Mapper_74x161x162x32<70> Mapper070;
|
typedef Mapper_74x161x162x32<70> Mapper070;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -54,4 +54,4 @@ class Mapper071 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -134,4 +134,4 @@ class Mapper073 : public Mapper, vrc3_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -110,4 +110,4 @@ class Mapper075 : public Mapper, vrc1_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -77,4 +77,4 @@ class Mapper078 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
||||||
|
|
|
@ -95,4 +95,4 @@ void Mapper_AveNina<multicart>::write_regs()
|
||||||
|
|
||||||
typedef Mapper_AveNina<false> Mapper079;
|
typedef Mapper_AveNina<false> Mapper079;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -225,4 +225,4 @@ class Mapper085 : public Mapper, vrc7_state_t
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -26,4 +26,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_74x161x162x32<86> Mapper086;
|
typedef Mapper_74x161x162x32<86> Mapper086;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -50,4 +50,4 @@ class Mapper087 : public Mapper
|
||||||
void write(nes_time_t, nes_addr_t, int) {}
|
void write(nes_time_t, nes_addr_t, int) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -111,5 +111,4 @@ class Mapper_Namco_34x3 : public Mapper, namco_34x3_state_t
|
||||||
|
|
||||||
typedef Mapper_Namco_34x3<false> Mapper088;
|
typedef Mapper_Namco_34x3<false> Mapper088;
|
||||||
|
|
||||||
|
} // namespace quickerNES
|
||||||
} // namespace quickNES
|
|
|
@ -59,4 +59,4 @@ class Mapper089 : public Mapper
|
||||||
uint8_t regs;
|
uint8_t regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -58,4 +58,4 @@ class Mapper093 : public Mapper
|
||||||
uint8_t regs;
|
uint8_t regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -57,4 +57,4 @@ class Mapper094 : public Mapper
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -66,4 +66,4 @@ class Mapper097 : public Mapper
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -30,4 +30,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_AveNina<true> Mapper113;
|
typedef Mapper_AveNina<true> Mapper113;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -66,4 +66,4 @@ class Mapper140 : public Mapper
|
||||||
uint8_t regs;
|
uint8_t regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -26,4 +26,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_74x161x162x32<152> Mapper152;
|
typedef Mapper_74x161x162x32<152> Mapper152;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -30,4 +30,4 @@ namespace quickerNES
|
||||||
|
|
||||||
typedef Mapper_Namco_34x3<true> Mapper154;
|
typedef Mapper_Namco_34x3<true> Mapper154;
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -62,4 +62,4 @@ class Mapper156 : public Mapper, m156_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
||||||
|
|
|
@ -57,4 +57,4 @@ class Mapper180 : public Mapper
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -67,4 +67,4 @@ class Mapper184 : public Mapper
|
||||||
uint8_t regs;
|
uint8_t regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -57,4 +57,4 @@ class Mapper190 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -78,4 +78,4 @@ class Mapper193 : public Mapper
|
||||||
uint8_t regs[4];
|
uint8_t regs[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -100,4 +100,4 @@ class Mapper206 : public Mapper, namco_34xx_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -93,4 +93,4 @@ class Mapper207 : public Mapper, taito_x1005_state_t
|
||||||
virtual void write(nes_time_t, nes_addr_t addr, int data) {}
|
virtual void write(nes_time_t, nes_addr_t addr, int data) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -56,4 +56,4 @@ class Mapper232 : public Mapper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -66,4 +66,4 @@ class Mapper240 : public Mapper
|
||||||
uint8_t regs;
|
uint8_t regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -55,4 +55,4 @@ class Mapper241 : public Mapper
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -72,4 +72,4 @@ class Mapper244 : public Mapper, mapper244_state_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
|
@ -77,4 +77,4 @@ class Mapper246 : public Mapper
|
||||||
uint8_t regs[8];
|
uint8_t regs[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickerNES
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue