Adapting for pre-decoded inputs
This commit is contained in:
parent
67c93e664e
commit
6ca0537d45
|
@ -1 +1 @@
|
|||
Subproject commit 6db55ef68011a6777f980f878a54501f42b6c894
|
||||
Subproject commit e7fd15b6e3ffed9bd718c0bfc0b0a6247e5dfe76
|
|
@ -1,207 +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, input_t* decoded) const
|
||||
{
|
||||
// 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(decoded->reset, decoded->power, ss);
|
||||
|
||||
// Parsing controller 1 inputs
|
||||
isValid &= parseControllerInputs(_controller1Type, decoded->port1, ss);
|
||||
|
||||
// Parsing controller 1 inputs
|
||||
isValid &= parseControllerInputs(_controller2Type, decoded->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; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
controller_t _controller1Type;
|
||||
controller_t _controller2Type;
|
||||
|
||||
}; // class Controller
|
||||
|
||||
} // namespace quickNES
|
|
@ -0,0 +1,224 @@
|
|||
#pragma once
|
||||
|
||||
// Base controller class
|
||||
// by eien86
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <jaffarCommon/exceptions.hpp>
|
||||
#include <jaffarCommon/json.hpp>
|
||||
|
||||
namespace jaffar
|
||||
{
|
||||
|
||||
typedef uint32_t port_t;
|
||||
|
||||
struct input_t
|
||||
{
|
||||
bool power = false;
|
||||
bool reset = false;
|
||||
port_t port1 = 0;
|
||||
port_t port2 = 0;
|
||||
};
|
||||
|
||||
|
||||
class InputParser
|
||||
{
|
||||
public:
|
||||
|
||||
enum controller_t { none, joypad, fourscore1, fourscore2 };
|
||||
|
||||
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; }
|
||||
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
|
||||
parseControllerInputs(_controller1Type, input.port1, ss, inputString);
|
||||
|
||||
// Parsing controller 1 inputs
|
||||
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 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 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;
|
||||
}
|
||||
|
||||
controller_t _controller1Type;
|
||||
controller_t _controller2Type;
|
||||
|
||||
}; // class InputParser
|
||||
|
||||
} // namespace jaffar
|
|
@ -3,7 +3,7 @@
|
|||
#include "jaffarCommon/serializers/contiguous.hpp"
|
||||
#include "jaffarCommon/serializers/differential.hpp"
|
||||
#include "jaffarCommon/logger.hpp"
|
||||
#include "controller.hpp"
|
||||
#include "inputParser.hpp"
|
||||
|
||||
// Size of image generated in graphics buffer
|
||||
static const uint16_t image_width = 256;
|
||||
|
@ -13,71 +13,14 @@ class NESInstanceBase
|
|||
{
|
||||
public:
|
||||
|
||||
NESInstanceBase() = default;
|
||||
NESInstanceBase(const nlohmann::json& config)
|
||||
{
|
||||
_inputParser = std::make_unique<jaffar::InputParser>(config);
|
||||
}
|
||||
|
||||
virtual ~NESInstanceBase() = default;
|
||||
|
||||
inline void advanceState(const std::string &input)
|
||||
{
|
||||
// Storage for the decoded input
|
||||
quickNES::Controller::input_t decodedInput;
|
||||
|
||||
// Getting decoded input from the input string
|
||||
decodeInput(input, &decodedInput);
|
||||
|
||||
// Calling advance state with the decoded input
|
||||
advanceState(&decodedInput);
|
||||
}
|
||||
|
||||
inline void advanceState(const void* decodedInputBuffer)
|
||||
{
|
||||
// Casting decoded input to the right type
|
||||
const auto decodedInput = (quickNES::Controller::input_t*) decodedInputBuffer;
|
||||
|
||||
// Parsing power
|
||||
if (decodedInput->power == true) JAFFAR_THROW_LOGIC("Power button pressed, but not supported.");
|
||||
|
||||
// Parsing reset
|
||||
if (decodedInput->reset == true) doSoftReset();
|
||||
|
||||
// Running specified inputs
|
||||
advanceStateImpl(decodedInput->port1, decodedInput->port2);
|
||||
}
|
||||
|
||||
inline size_t getDecodedInputSize() const
|
||||
{
|
||||
return sizeof(quickNES::Controller::input_t);
|
||||
}
|
||||
|
||||
inline void decodeInput(const std::string &input, void* decodedInputBuffer) const
|
||||
{
|
||||
const auto decodedInput = (quickNES::Controller::input_t*) decodedInputBuffer;
|
||||
bool isInputValid = _controller.parseInputString(input, decodedInput);
|
||||
if (isInputValid == false) JAFFAR_THROW_LOGIC("Move provided cannot be parsed: '%s'\n", input.c_str());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
virtual void advanceState(const jaffar::input_t &input) = 0;
|
||||
|
||||
inline void enableRendering() { _doRendering = true; };
|
||||
inline void disableRendering() { _doRendering = false; };
|
||||
|
@ -114,6 +57,7 @@ class NESInstanceBase
|
|||
|
||||
virtual size_t getFullStateSize() const = 0;
|
||||
virtual size_t getDifferentialStateSize() const = 0;
|
||||
inline jaffar::InputParser* getInputParser() const { return _inputParser.get(); }
|
||||
|
||||
// Virtual functions
|
||||
|
||||
|
@ -134,7 +78,6 @@ class NESInstanceBase
|
|||
virtual void enableStateBlockImpl(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 void advanceStateImpl(const quickNES::Controller::port_t controller1, const quickNES::Controller::port_t controller2) = 0;
|
||||
|
||||
// Storage for the light state size
|
||||
size_t _stateSize;
|
||||
|
@ -144,6 +87,7 @@ class NESInstanceBase
|
|||
|
||||
private:
|
||||
|
||||
// Controller class for input parsing
|
||||
quickNES::Controller _controller;
|
||||
// Input parser instance
|
||||
std::unique_ptr<jaffar::InputParser> _inputParser;
|
||||
|
||||
};
|
||||
|
|
|
@ -112,12 +112,11 @@ int main(int argc, char *argv[])
|
|||
jaffarCommon::logger::refreshTerminal();
|
||||
|
||||
// Creating emulator instance
|
||||
nlohmann::json emulatorConfig;
|
||||
emulatorConfig["Controller 1 Type"] = controller1Type;
|
||||
emulatorConfig["Controller 2 Type"] = controller2Type;
|
||||
NESInstance e;
|
||||
|
||||
// Setting controller types
|
||||
e.setController1Type(controller1Type);
|
||||
e.setController2Type(controller2Type);
|
||||
|
||||
// Loading ROM File
|
||||
std::string romFileData;
|
||||
if (jaffarCommon::file::loadStringFromFile(romFileData, romFilePath) == false) JAFFAR_THROW_LOGIC("Could not rom file: %s\n", romFilePath.c_str());
|
||||
|
|
|
@ -17,7 +17,8 @@ extern void register_mapper_70();
|
|||
class NESInstance final : public NESInstanceBase
|
||||
{
|
||||
public:
|
||||
NESInstance() : NESInstanceBase()
|
||||
|
||||
NESInstance(const nlohmann::json& config) : NESInstanceBase(config)
|
||||
{
|
||||
// If running the original QuickNES, register extra mappers now
|
||||
register_misc_mappers();
|
||||
|
@ -60,6 +61,12 @@ class NESInstance final : public NESInstanceBase
|
|||
|
||||
void *getInternalEmulatorPointer() override { return &_nes; }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool loadROMImpl(const uint8_t* romData, const size_t romSize) override
|
||||
|
@ -74,11 +81,6 @@ class NESInstance final : public NESInstanceBase
|
|||
void enableStateBlockImpl(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:
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ class NESInstance final : public NESInstanceBase
|
|||
{
|
||||
public:
|
||||
|
||||
NESInstance(const nlohmann::json& config) : NESInstanceBase(config) {}
|
||||
|
||||
uint8_t *getLowMem() const override { return _nes.get_low_mem(); };
|
||||
size_t getLowMemSize() const override { return _nes.get_low_mem_size(); };
|
||||
|
||||
|
@ -50,6 +52,12 @@ class NESInstance final : public NESInstanceBase
|
|||
|
||||
void setNTABBlockSize(const size_t size) override { _nes.setNTABBlockSize(size); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool loadROMImpl(const uint8_t* romData, const size_t romSize) override
|
||||
|
@ -61,11 +69,7 @@ class NESInstance final : public NESInstanceBase
|
|||
|
||||
void enableStateBlockImpl(const std::string& block) override { _nes.enableStateBlock(block); };
|
||||
void disableStateBlockImpl(const std::string& block) override { _nes.disableStateBlock(block); };
|
||||
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:
|
||||
|
||||
|
|
|
@ -116,11 +116,7 @@ int main(int argc, char *argv[])
|
|||
const auto differentialCompressionUseZlib = differentialCompressionJs["Use Zlib"].get<bool>();
|
||||
|
||||
// Creating emulator instance
|
||||
NESInstance e;
|
||||
|
||||
// Setting controller types
|
||||
e.setController1Type(controller1Type);
|
||||
e.setController2Type(controller2Type);
|
||||
NESInstance e(scriptJson);
|
||||
|
||||
// Loading ROM File
|
||||
std::string romFileData;
|
||||
|
@ -165,6 +161,13 @@ int main(int argc, char *argv[])
|
|||
// Getting sequence lenght
|
||||
const auto sequenceLength = sequence.size();
|
||||
|
||||
// Getting input parser from the emulator
|
||||
const auto inputParser = e.getInputParser();
|
||||
|
||||
// Getting decoded emulator input for each entry in the sequence
|
||||
std::vector<jaffar::input_t> decodedSequence;
|
||||
for (const auto& inputString : sequence) decodedSequence.push_back(inputParser->parseInputString(inputString));
|
||||
|
||||
// Getting emulation core name
|
||||
std::string emulationCoreName = e.getCoreName();
|
||||
|
||||
|
@ -174,7 +177,6 @@ int main(int argc, char *argv[])
|
|||
printf("[] Cycle Type: '%s'\n", cycleType.c_str());
|
||||
printf("[] Emulation Core: '%s'\n", emulationCoreName.c_str());
|
||||
printf("[] ROM File: '%s'\n", romFilePath.c_str());
|
||||
printf("[] Controller Types: '%s' / '%s'\n", controller1Type.c_str(), controller2Type.c_str());
|
||||
printf("[] ROM Hash: 'SHA1: %s'\n", romSHA1.c_str());
|
||||
printf("[] Sequence File: '%s'\n", sequenceFilePath.c_str());
|
||||
printf("[] Sequence Length: %lu\n", sequenceLength);
|
||||
|
@ -218,7 +220,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
// Actually running the sequence
|
||||
auto t0 = std::chrono::high_resolution_clock::now();
|
||||
for (const std::string &input : sequence)
|
||||
for (const auto &input : decodedSequence)
|
||||
{
|
||||
if (doPreAdvance == true) e.advanceState(input);
|
||||
|
||||
|
|
Loading…
Reference in New Issue