Merge pull request #4 from SergioMartin86/controllers

Controllers
This commit is contained in:
Sergio Martin 2024-01-21 16:42:10 +01:00 committed by GitHub
commit 8886aad9a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 203124 additions and 197359 deletions

4
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "extern/QuickNES_Core"]
[submodule "source/quickNES/QuickNES_Core"]
path = source/quickNES/QuickNES_Core
url = https://github.com/libretro/QuickNES_Core.git
url = git@github.com:SergioMartin86/QuickNES_Core.git

View File

@ -12,16 +12,16 @@ quickerNES is an attempt to modernizing [quickNES](https://github.com/kode54/Qui
The main aim is to improve the performance of headless re-recording for TASing and botting (See: [JaffarPlus](https://github.com/SergioMartin86/jaffarPlus)) purposes. However, if this work can help regular play emulation, then much better.
Changes
--------
Improvements
-------------
- Optimizations made in the CPU emulation core, including:
+ Forced alignment at the start of a page to prevent crossing cache line boundaries
+ Simplifying the 6502 CPU instruction fetching and decoding
+ Multiple branch optimizations
- Minimize compiled code size to reduce pressure on L1i cache
- Assuming little endiannes to reduce unnecessary conversion operations (not portable to big endian systems)
- Reduce heap allocations
+ Assuming little endiannes to reduce unnecessary conversion operations (not portable to big endian systems)
+ Minimize compiled code size to reduce pressure on L1i cache
- Added support for FourScore controller
- General code reorganization (make it header only to help compiler optimizations)
Credits

206
source/controller.hpp Normal file
View File

@ -0,0 +1,206 @@
#pragma once
// Base controller class
// by eien86
#include <cstdint>
#include <string>
#include <sstream>
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
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;
};

View File

@ -2,6 +2,7 @@
#include "sha1/sha1.hpp"
#include <utils.hpp>
#include <controller.hpp>
#define _LOW_MEM_SIZE 0x800
#define _HIGH_MEM_SIZE 0x2000
@ -14,74 +15,50 @@ static const uint16_t image_height = 240;
class EmuInstance
{
public:
typedef uint8_t inputType;
// Deleting default constructors
EmuInstance() = default;
virtual ~EmuInstance() = default;
// Controller input bits
// 0 - A / 1
// 1 - B / 2
// 2 - Select / 4
// 3 - Start / 8
// 4 - Up / 16
// 5 - Down / 32
// 6 - Left / 64
// 7 - Right / 128
// Move Format:
// RLDUTSBA
// ........
static inline inputType moveStringToCode(const std::string &move)
{
inputType moveCode = 0;
for (size_t i = 0; i < move.size(); i++) switch (move[i])
{
case 'U': moveCode |= 0b00010000; break;
case 'D': moveCode |= 0b00100000; break;
case 'L': moveCode |= 0b01000000; break;
case 'R': moveCode |= 0b10000000; break;
case 'S': moveCode |= 0b00001000; break;
case 's': moveCode |= 0b00000100; break;
case 'B': moveCode |= 0b00000010; break;
case 'A': moveCode |= 0b00000001; break;
case 'r': break;
case '.': break;
case '|': break;
default: EXIT_WITH_ERROR("Move provided cannot be parsed: '%s', unrecognized character: '%c'\n", move.c_str(), move[i]);
}
return moveCode;
}
static inline std::string moveCodeToString(const inputType move)
{
#ifndef _NES_PLAYER_2
std::string moveString = "|..|";
#else
std::string moveString = "|..|........|";
#endif
if (move & 0b00010000) moveString += 'U'; else moveString += '.';
if (move & 0b00100000) moveString += 'D'; else moveString += '.';
if (move & 0b01000000) moveString += 'L'; else moveString += '.';
if (move & 0b10000000) moveString += 'R'; else moveString += '.';
if (move & 0b00001000) moveString += 'S'; else moveString += '.';
if (move & 0b00000100) moveString += 's'; else moveString += '.';
if (move & 0b00000010) moveString += 'B'; else moveString += '.';
if (move & 0b00000001) moveString += 'A'; else moveString += '.';
moveString += "|";
return moveString;
}
inline void advanceState(const std::string &move)
{
if (move.find("r") != std::string::npos) doSoftReset();
bool isInputValid = _controller.parseInputString(move);
if (isInputValid == false) EXIT_WITH_ERROR("Move provided cannot be parsed: '%s'\n", move.c_str());
advanceStateImpl(moveStringToCode(move), 0);
// Parsing power
if (_controller.getPowerButtonState() == true) EXIT_WITH_ERROR("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(Controller::controller_t::none); isTypeRecognized = true; }
if (type == "Joypad") { _controller.setController1Type(Controller::controller_t::joypad); isTypeRecognized = true; }
if (type == "FourScore1") { _controller.setController1Type(Controller::controller_t::fourscore1); isTypeRecognized = true; }
if (type == "FourScore2") { _controller.setController1Type(Controller::controller_t::fourscore2); isTypeRecognized = true; }
if (isTypeRecognized == false) EXIT_WITH_ERROR("Input type not recognized: '%s'\n", type.c_str());
}
inline void setController2Type(const std::string& type)
{
bool isTypeRecognized = false;
if (type == "None") { _controller.setController2Type(Controller::controller_t::none); isTypeRecognized = true; }
if (type == "Joypad") { _controller.setController2Type(Controller::controller_t::joypad); isTypeRecognized = true; }
if (type == "FourScore1") { _controller.setController2Type(Controller::controller_t::fourscore1); isTypeRecognized = true; }
if (type == "FourScore2") { _controller.setController2Type(Controller::controller_t::fourscore2); isTypeRecognized = true; }
if (isTypeRecognized == false) EXIT_WITH_ERROR("Input type not recognized: '%s'\n", type.c_str());
}
inline std::string getRomSHA1() const { return _romSHA1String; }
@ -142,7 +119,7 @@ class EmuInstance
// Virtual functions
virtual bool loadROMFileImpl(const std::string &romFilePath) = 0;
virtual void advanceStateImpl(const inputType controller1, const inputType controller2) = 0;
virtual void advanceStateImpl(const Controller::port_t controller1, const Controller::port_t controller2) = 0;
virtual uint8_t *getLowMem() const = 0;
virtual uint8_t *getNametableMem() const = 0;
virtual uint8_t *getHighMem() const = 0;
@ -163,7 +140,6 @@ class EmuInstance
virtual void *getInternalEmulatorPointer() const = 0;
protected:
EmuInstance() = default;
// Storage for the light state size
size_t _liteStateSize;
@ -180,4 +156,7 @@ class EmuInstance
// SHA1 rom hash
std::string _romSHA1String;
// Controller class for input parsing
Controller _controller;
};

View File

@ -39,6 +39,14 @@ int main(int argc, char *argv[])
.default_value(false)
.implicit_value(true);
program.add_argument("--controller1")
.help("Specifies the controller 1 type.")
.default_value(std::string("Joypad"));
program.add_argument("--controller2")
.help("Specifies the controller 2 type.")
.default_value(std::string("None"));
// Try to parse arguments
try
{
@ -64,6 +72,12 @@ int main(int argc, char *argv[])
// Getting reproduce flag
bool disableRender = program.get<bool>("--disableRender");
// Getting controller 1 Type
std::string controller1Type = program.get<std::string>("--controller1");
// Getting controller 2 Type
std::string controller2Type = program.get<std::string>("--controller2");
// Loading sequence file
std::string inputSequence;
auto status = loadStringFromFile(inputSequence, sequenceFilePath.c_str());
@ -93,6 +107,10 @@ int main(int argc, char *argv[])
auto e = quickerNES::QuickerNESInstance();
#endif
// Setting controller types
e.setController1Type(controller1Type);
e.setController2Type(controller2Type);
// Loading ROM File
e.loadROMFile(romFilePath);

@ -1 +1 @@
Subproject commit 058d66516ed3f1260b69e5b71cd454eb7e9234a3
Subproject commit cedf1f63cc904a2737d26cd1ed006915ecadac22

View File

@ -76,7 +76,7 @@ class QuickNESInstance : public EmuInstance
return w.size();
}
void advanceStateImpl(const inputType controller1, const inputType controller2) override
void advanceStateImpl(const Controller::port_t controller1, const Controller::port_t controller2) override
{
if (_doRendering == true) _nes->emulate_frame(controller1, controller2);
if (_doRendering == false) _nes->emulate_skip_frame(controller1, controller2);

View File

@ -406,6 +406,7 @@ class Core : private Cpu
pos += headerSize;
memcpy((void *)ppu.impl->chr_ram, &buffer[pos], blockSize);
pos += blockSize;
ppu.all_tiles_modified();
}
if (sram_present)
@ -740,10 +741,10 @@ size_t serializeLiteState(uint8_t *buffer) const
error_count = 0;
}
nes_time_t emulate_frame(int joypad1, int joypad2)
nes_time_t emulate_frame(uint32_t joypad1, uint32_t joypad2)
{
current_joypad[0] = (joypad1 |= ~0xFF);
current_joypad[1] = (joypad2 |= ~0xFF);
current_joypad[0] = joypad1;
current_joypad[1] = joypad2;
cpu_time_offset = ppu.begin_frame(nes.timestamp) - 1;
ppu_2002_time = 0;
@ -812,7 +813,7 @@ size_t serializeLiteState(uint8_t *buffer) const
bool sram_present;
public:
unsigned long current_joypad[2];
uint32_t current_joypad[2];
Cart const *cart;
Mapper *mapper;
nes_state_t nes;

View File

@ -103,7 +103,7 @@ void Emu::set_palette_range( int begin, int end )
host_palette_size = end - emu.ppu.palette_begin;
}
const char * Emu::emulate_skip_frame( int joypad1, int joypad2 )
const char * Emu::emulate_skip_frame( uint32_t joypad1, uint32_t joypad2 )
{
char *old_host_pixels = host_pixels;
host_pixels = NULL;
@ -112,7 +112,7 @@ const char * Emu::emulate_skip_frame( int joypad1, int joypad2 )
return 0;
}
const char * Emu::emulate_frame( int joypad1, int joypad2 )
const char * Emu::emulate_frame( uint32_t joypad1, uint32_t joypad2 )
{
emu.ppu.host_pixels = NULL;

View File

@ -61,11 +61,11 @@ class Emu
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
// and sound are available for output using the accessors below.
virtual const char *emulate_frame(int joypad1, int joypad2 = 0);
virtual const char *emulate_frame(uint32_t joypad1, uint32_t joypad2 = 0);
// Emulate one video frame using joypad1 and joypad2 as input, but skips drawing.
// Afterwards, audio is available for output using the accessors below.
virtual const char *emulate_skip_frame(int joypad1, int joypad2 = 0);
virtual const char *emulate_skip_frame(uint32_t joypad1, uint32_t joypad2 = 0);
// Maximum size of palette that can be generated
static const uint16_t max_palette_size = 256;

View File

@ -48,7 +48,7 @@ class QuickerNESInstance : public EmuInstance
void enableLiteStateBlock(const std::string& block) override { _nes->enableLiteStateBlock(block); };
void disableLiteStateBlock(const std::string& block) override { _nes->disableLiteStateBlock(block); };
void advanceStateImpl(const inputType controller1, const inputType controller2) override
void advanceStateImpl(const Controller::port_t controller1, const Controller::port_t controller2) override
{
if (_doRendering == true) _nes->emulate_frame(controller1, controller2);
if (_doRendering == false) _nes->emulate_skip_frame(controller1, controller2);

View File

@ -90,6 +90,16 @@ int main(int argc, char *argv[])
stateDisabledBlocksOutput += entry.get<std::string>() + std::string(" ");
}
// Getting Controller 1 type
if (scriptJson.contains("Controller 1 Type") == false) EXIT_WITH_ERROR("Script file missing 'Controller 1 Type' entry\n");
if (scriptJson["Controller 1 Type"].is_string() == false) EXIT_WITH_ERROR("Script file 'Controller 1 Type' entry is not a string\n");
std::string controller1Type = scriptJson["Controller 1 Type"].get<std::string>();
// Getting Controller 2 type
if (scriptJson.contains("Controller 2 Type") == false) EXIT_WITH_ERROR("Script file missing 'Controller 2 Type' entry\n");
if (scriptJson["Controller 2 Type"].is_string() == false) EXIT_WITH_ERROR("Script file 'Controller 2 Type' entry is not a string\n");
std::string controller2Type = scriptJson["Controller 2 Type"].get<std::string>();
// Creating emulator instance
#ifdef _USE_QUICKNES
auto e = QuickNESInstance();
@ -99,6 +109,10 @@ int main(int argc, char *argv[])
auto e = quickerNES::QuickerNESInstance();
#endif
// Setting controller types
e.setController1Type(controller1Type);
e.setController2Type(controller2Type);
// Disabling requested blocks from light state serialization
for (const auto& block : stateDisabledBlocks) e.disableLiteStateBlock(block);
@ -139,6 +153,7 @@ 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 SHA1: '%s'\n", romSHA1.c_str());
printf("[] Sequence File: '%s'\n", sequenceFilePath.c_str());
printf("[] Sequence Length: %lu\n", sequenceLength);

View File

@ -39428,4 +39428,4 @@
|..|........|
|..|........|
|..|...R....|
|..|...R....|
|..|...R....|

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
"Initial State File": "",
"Sequence File": "arkanoid.warpless.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
"Initial State File": "",
"Sequence File": "arkanoid.warps.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
"Initial State File": "",
"Sequence File": "castlevania1.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
"Initial State File": "",
"Sequence File": "castlevania1.pacifist.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "DA54C223D79FA59EB95437854B677CF69B5CAC8A",
"Initial State File": "",
"Sequence File": "galaga.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "97B79E432F62403FB9F877090850C41112A9A168",
"Initial State File": "",
"Sequence File": "ironSword.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -20,6 +20,7 @@ protectedTestSet = [
'ninjaGaiden2.pacifist.test',
'novaTheSquirrel.anyPercent.test',
'princeOfPersia.anyPercent.test',
'rcProAmII.race1.test',
'saintSeiyaKanketsuHen.anyPercent.test',
'saintSeiyaOugonDensetsu.anyPercent.test',
'saiyuukiWorld.anyPercent.test',

View File

@ -1726,5 +1726,4 @@
|..|........|
|..|........|
|..|........|
|..|........|
|..|........|

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "ECF39EC5A33E6A6F832F03E8FFC61C5D53F4F90B",
"Initial State File": "",
"Sequence File": "metroid.playaround.sol",
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "BBE5CF2DFA0B5422776A530D6F1B617238A8569F",
"Initial State File": "",
"Sequence File": "nigelMansell.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
"Initial State File": "",
"Sequence File": "ninjaGaiden.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
"Initial State File": "",
"Sequence File": "ninjaGaiden.pacifist.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
"Initial State File": "",
"Sequence File": "ninjaGaiden2.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
"Initial State File": "",
"Sequence File": "ninjaGaiden2.pacifist.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "B6B07EE76492ED475F39167C89B342353F999231",
"Initial State File": "",
"Sequence File": "novaTheSquirrel.anyPercent.sol",
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "6B58F149F34FA829135619C58700CAAA95B9CDE3",
"Initial State File": "",
"Sequence File": "princeOfPersia.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

5482
tests/rcProAmII.race1.sol Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
{
"Rom File": "roms/R.C. Pro-Am II (U) [!].nes",
"Expected ROM SHA1": "8C68582BDAA32FBC8C7CD858991D4E00D3B1569C",
"Initial State File": "",
"Sequence File": "rcProAmII.race1.sol",
"Disable State Blocks": [ ],
"Controller 1 Type": "FourScore1",
"Controller 2 Type": "FourScore2"
}

View File

@ -31,11 +31,13 @@ quickNESHashFile="/tmp/quickNES.${folder}.${script}.${mode}.${pid}.hash"
rm -f ${quickerNESHashFile}
rm -f ${quickNESHashFile}
set -x
# Running script on quickerNES
${quickerNESExecutable} ${script} --hashOutputFile ${quickerNESHashFile} ${testerArgs}
# Running script on quickNES
${quickNESExecutable} ${script} --hashOutputFile ${quickNESHashFile} ${testerArgs}
set +x
# Comparing hashes
quickerNESHash=`cat ${quickerNESHashFile}`

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "F871D9B3DAFDDCDAD5F2ACD71044292E5169064E",
"Initial State File": "",
"Sequence File": "saintSeiyaKanketsuHen.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "3F3B499CF50386084E053BCA096AE8E52330CFAE",
"Initial State File": "",
"Sequence File": "saintSeiyaKanketsuHen.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
"Initial State File": "",
"Sequence File": "saiyuukiWorld.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
"Initial State File": "saiyuukiWorld.lastHalf.state",
"Sequence File": "saiyuukiWorld.lastHalf.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -1,7 +1,11 @@
{
"Rom File": "roms/Solar Jetman - Hunt for the Golden Warpship (U) [!].nes",
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None",
"Expected ROM SHA1": "872B91A2F7A2F635061EF43F79E7F7E9F59F5C50",
"Initial State File": "",
"Sequence File": "solarJetman.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "6EC09B9B51320A536A786D3D4719432B714C5779",
"Initial State File": "",
"Sequence File": "sprilo.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

File diff suppressed because it is too large Load Diff

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "EA343F4E445A9050D4B4FBAC2C77D0693B1D0922",
"Initial State File": "",
"Sequence File": "superMarioBros.warpless.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

File diff suppressed because it is too large Load Diff

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "EA343F4E445A9050D4B4FBAC2C77D0693B1D0922",
"Initial State File": "",
"Sequence File": "superMarioBros.warps.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "A03E7E526E79DF222E048AE22214BCA2BC49C449",
"Initial State File": "",
"Sequence File": "superMarioBros3.warps.sol",
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}

File diff suppressed because it is too large Load Diff

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "57919B685B55EE3ED3AD98FB1D25626B98BE7D39",
"Initial State File": "",
"Sequence File": "superOffroad.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "Joypad"
}

View File

@ -3,5 +3,7 @@
"Expected ROM SHA1": "80D99C035E6A5AB9718E413EC25CBE094F085962",
"Initial State File": "",
"Sequence File": "tennis.anyPercent.sol",
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ],
"Controller 1 Type": "Joypad",
"Controller 2 Type": "None"
}