Merge pull request #3 from SergioMartin86/lightStates2
Added light states: ones that do not copy certain blocks of the NES state for faster/smaller serialization
This commit is contained in:
commit
9b276f8b70
|
@ -26,4 +26,5 @@ jobs:
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: meson-logs
|
name: meson-logs
|
||||||
path: build/meson-logs/
|
path: build/meson-logs/
|
||||||
|
|
|
@ -47,7 +47,7 @@ quickerNESTester = executable('quickerNESTester',
|
||||||
|
|
||||||
quickNESTester = executable('quickNESTester',
|
quickNESTester = executable('quickNESTester',
|
||||||
'source/tester.cpp',
|
'source/tester.cpp',
|
||||||
cpp_args : [ commonCompileArgs, '-Wno-multichar', '-DDISABLE_AUTO_FILE', '-D__LIBRETRO__', '-DNDEBUG', '-DBLARGG_NONPORTABLE' ],
|
cpp_args : [ commonCompileArgs, '-w', '-DDISABLE_AUTO_FILE', '-D__LIBRETRO__', '-DNDEBUG', '-DBLARGG_NONPORTABLE' ],
|
||||||
dependencies : [ quickNESDependency, toolDependency ],
|
dependencies : [ quickNESDependency, toolDependency ],
|
||||||
include_directories : include_directories(['../extern/json'])
|
include_directories : include_directories(['../extern/json'])
|
||||||
)
|
)
|
||||||
|
|
|
@ -64,38 +64,14 @@ class EmuInstance
|
||||||
std::string moveString = "|..|........|";
|
std::string moveString = "|..|........|";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (move & 0b00010000)
|
if (move & 0b00010000) moveString += 'U'; else moveString += '.';
|
||||||
moveString += 'U';
|
if (move & 0b00100000) moveString += 'D'; else moveString += '.';
|
||||||
else
|
if (move & 0b01000000) moveString += 'L'; else moveString += '.';
|
||||||
moveString += '.';
|
if (move & 0b10000000) moveString += 'R'; else moveString += '.';
|
||||||
if (move & 0b00100000)
|
if (move & 0b00001000) moveString += 'S'; else moveString += '.';
|
||||||
moveString += 'D';
|
if (move & 0b00000100) moveString += 's'; else moveString += '.';
|
||||||
else
|
if (move & 0b00000010) moveString += 'B'; else moveString += '.';
|
||||||
moveString += '.';
|
if (move & 0b00000001) moveString += 'A'; 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 += "|";
|
moveString += "|";
|
||||||
return moveString;
|
return moveString;
|
||||||
|
@ -108,8 +84,6 @@ class EmuInstance
|
||||||
advanceStateImpl(moveStringToCode(move), 0);
|
advanceStateImpl(moveStringToCode(move), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t getStateSize() const { return _stateSize; }
|
|
||||||
inline size_t getLiteStateSize() const { return _liteStateSize; }
|
|
||||||
inline std::string getRomSHA1() const { return _romSHA1String; }
|
inline std::string getRomSHA1() const { return _romSHA1String; }
|
||||||
|
|
||||||
inline hash_t getStateHash() const
|
inline hash_t getStateHash() const
|
||||||
|
@ -117,9 +91,9 @@ class EmuInstance
|
||||||
MetroHash128 hash;
|
MetroHash128 hash;
|
||||||
|
|
||||||
hash.Update(getLowMem(), _LOW_MEM_SIZE);
|
hash.Update(getLowMem(), _LOW_MEM_SIZE);
|
||||||
hash.Update(getHighMem(), _HIGH_MEM_SIZE);
|
// hash.Update(getHighMem(), _HIGH_MEM_SIZE);
|
||||||
hash.Update(getNametableMem(), _NAMETABLES_MEM_SIZE);
|
// hash.Update(getNametableMem(), _NAMETABLES_MEM_SIZE);
|
||||||
hash.Update(getChrMem(), getChrMemSize());
|
// hash.Update(getChrMem(), getChrMemSize());
|
||||||
|
|
||||||
hash_t result;
|
hash_t result;
|
||||||
hash.Finalize(reinterpret_cast<uint8_t *>(&result));
|
hash.Finalize(reinterpret_cast<uint8_t *>(&result));
|
||||||
|
@ -134,14 +108,14 @@ class EmuInstance
|
||||||
std::string stateData;
|
std::string stateData;
|
||||||
bool status = loadStringFromFile(stateData, stateFilePath);
|
bool status = loadStringFromFile(stateData, stateFilePath);
|
||||||
if (status == false) EXIT_WITH_ERROR("Could not find/read state file: %s\n", stateFilePath.c_str());
|
if (status == false) EXIT_WITH_ERROR("Could not find/read state file: %s\n", stateFilePath.c_str());
|
||||||
deserializeState((uint8_t *)stateData.data());
|
deserializeFullState((uint8_t *)stateData.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void saveStateFile(const std::string &stateFilePath) const
|
inline void saveStateFile(const std::string &stateFilePath) const
|
||||||
{
|
{
|
||||||
std::string stateData;
|
std::string stateData;
|
||||||
stateData.resize(_stateSize);
|
stateData.resize(_fullStateSize);
|
||||||
serializeState((uint8_t *)stateData.data());
|
serializeFullState((uint8_t *)stateData.data());
|
||||||
saveStringToFile(stateData, stateFilePath.c_str());
|
saveStringToFile(stateData, stateFilePath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,10 +133,10 @@ class EmuInstance
|
||||||
if (status == false) EXIT_WITH_ERROR("Could not process ROM file: %s\n", romFilePath.c_str());
|
if (status == false) EXIT_WITH_ERROR("Could not process ROM file: %s\n", romFilePath.c_str());
|
||||||
|
|
||||||
// Detecting full state size
|
// Detecting full state size
|
||||||
_stateSize = getStateSizeImpl();
|
_fullStateSize = getFullStateSize();
|
||||||
|
|
||||||
// Detecting lite state size
|
// Detecting lite state size
|
||||||
_liteStateSize = getLiteStateSizeImpl();
|
_liteStateSize = getLiteStateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Virtual functions
|
// Virtual functions
|
||||||
|
@ -174,10 +148,15 @@ class EmuInstance
|
||||||
virtual uint8_t *getHighMem() const = 0;
|
virtual uint8_t *getHighMem() const = 0;
|
||||||
virtual const uint8_t *getChrMem() const = 0;
|
virtual const uint8_t *getChrMem() const = 0;
|
||||||
virtual size_t getChrMemSize() const = 0;
|
virtual size_t getChrMemSize() const = 0;
|
||||||
virtual void serializeState(uint8_t *state) const = 0;
|
virtual void serializeFullState(uint8_t *state) const = 0;
|
||||||
virtual void deserializeState(const uint8_t *state) = 0;
|
virtual void deserializeFullState(const uint8_t *state) = 0;
|
||||||
virtual size_t getStateSizeImpl() const = 0;
|
virtual void serializeLiteState(uint8_t *state) const = 0;
|
||||||
virtual size_t getLiteStateSizeImpl() const { return getStateSizeImpl(); };
|
virtual void deserializeLiteState(const uint8_t *state) = 0;
|
||||||
|
virtual size_t getFullStateSize() const = 0;
|
||||||
|
virtual size_t getLiteStateSize() const = 0;
|
||||||
|
virtual void enableLiteStateBlock(const std::string& block) = 0;
|
||||||
|
virtual void disableLiteStateBlock(const std::string& block) = 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;
|
||||||
|
@ -190,7 +169,7 @@ class EmuInstance
|
||||||
size_t _liteStateSize;
|
size_t _liteStateSize;
|
||||||
|
|
||||||
// Storage for the full state size
|
// Storage for the full state size
|
||||||
size_t _stateSize;
|
size_t _fullStateSize;
|
||||||
|
|
||||||
// Flag to determine whether to enable/disable rendering
|
// Flag to determine whether to enable/disable rendering
|
||||||
bool _doRendering = true;
|
bool _doRendering = true;
|
||||||
|
|
|
@ -29,13 +29,16 @@ struct stepData_t
|
||||||
|
|
||||||
class PlaybackInstance
|
class PlaybackInstance
|
||||||
{
|
{
|
||||||
|
static const uint16_t image_width = 256;
|
||||||
|
static const uint16_t image_height = 240;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void addStep(const std::string &input)
|
void addStep(const std::string &input)
|
||||||
{
|
{
|
||||||
stepData_t step;
|
stepData_t step;
|
||||||
step.input = input;
|
step.input = input;
|
||||||
step.stateData = (uint8_t *)malloc(_emu->getStateSize());
|
step.stateData = (uint8_t *)malloc(_emu->getFullStateSize());
|
||||||
_emu->serializeState(step.stateData);
|
_emu->serializeFullState(step.stateData);
|
||||||
step.hash = _emu->getStateHash();
|
step.hash = _emu->getStateHash();
|
||||||
|
|
||||||
// Adding the step into the sequence
|
// Adding the step into the sequence
|
||||||
|
@ -50,8 +53,8 @@ class PlaybackInstance
|
||||||
|
|
||||||
// Loading Emulator instance HQN
|
// Loading Emulator instance HQN
|
||||||
_hqnState.setEmulatorPointer(_emu->getInternalEmulatorPointer());
|
_hqnState.setEmulatorPointer(_emu->getInternalEmulatorPointer());
|
||||||
static uint8_t video_buffer[emulator_t::image_width * emulator_t::image_height];
|
static uint8_t video_buffer[image_width * image_height];
|
||||||
_hqnState.m_emu->set_pixels(video_buffer, emulator_t::image_width + 8);
|
_hqnState.m_emu->set_pixels(video_buffer, image_width + 8);
|
||||||
|
|
||||||
// Building sequence information
|
// Building sequence information
|
||||||
for (const auto &input : sequence)
|
for (const auto &input : sequence)
|
||||||
|
@ -166,7 +169,7 @@ class PlaybackInstance
|
||||||
if (stepId > 0)
|
if (stepId > 0)
|
||||||
{
|
{
|
||||||
const auto stateData = getStateData(stepId - 1);
|
const auto stateData = getStateData(stepId - 1);
|
||||||
_emu->deserializeState(stateData);
|
_emu->deserializeFullState(stateData);
|
||||||
_emu->advanceState(getStateInput(stepId - 1));
|
_emu->advanceState(getStateInput(stepId - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ int main(int argc, char *argv[])
|
||||||
auto p = PlaybackInstance(&e, sequence);
|
auto p = PlaybackInstance(&e, sequence);
|
||||||
|
|
||||||
// Getting state size
|
// Getting state size
|
||||||
auto stateSize = e.getStateSize();
|
auto stateSize = e.getFullStateSize();
|
||||||
|
|
||||||
// Flag to continue running playback
|
// Flag to continue running playback
|
||||||
bool continueRunning = true;
|
bool continueRunning = true;
|
||||||
|
|
|
@ -45,20 +45,37 @@ class QuickNESInstance : public EmuInstance
|
||||||
const uint8_t *getChrMem() const override { return _nes->chr_mem(); };
|
const uint8_t *getChrMem() const override { return _nes->chr_mem(); };
|
||||||
size_t getChrMemSize() const override { return _nes->chr_size(); };
|
size_t getChrMemSize() const override { return _nes->chr_size(); };
|
||||||
|
|
||||||
void serializeState(uint8_t *state) const override
|
void serializeLiteState(uint8_t *state) const override { serializeFullState(state); }
|
||||||
|
void deserializeLiteState(const uint8_t *state) override { deserializeFullState(state); }
|
||||||
|
inline size_t getLiteStateSize() const override { return getFullStateSize(); }
|
||||||
|
|
||||||
|
void enableLiteStateBlock(const std::string& block) override {};
|
||||||
|
void disableLiteStateBlock(const std::string& block) override {};
|
||||||
|
|
||||||
|
void serializeFullState(uint8_t *state) const override
|
||||||
{
|
{
|
||||||
Mem_Writer w(state, _stateSize, 0);
|
Mem_Writer w(state, _fullStateSize, 0);
|
||||||
Auto_File_Writer a(w);
|
Auto_File_Writer a(w);
|
||||||
_nes->save_state(a);
|
_nes->save_state(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserializeState(const uint8_t *state) override
|
void deserializeFullState(const uint8_t *state) override
|
||||||
{
|
{
|
||||||
Mem_File_Reader r(state, _stateSize);
|
Mem_File_Reader r(state, _fullStateSize);
|
||||||
Auto_File_Reader a(r);
|
Auto_File_Reader a(r);
|
||||||
_nes->load_state(a);
|
_nes->load_state(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t getFullStateSize() const override
|
||||||
|
{
|
||||||
|
uint8_t *data = (uint8_t *)malloc(_DUMMY_SIZE);
|
||||||
|
Mem_Writer w(data, _DUMMY_SIZE);
|
||||||
|
Auto_File_Writer a(w);
|
||||||
|
_nes->save_state(a);
|
||||||
|
free(data);
|
||||||
|
return w.size();
|
||||||
|
}
|
||||||
|
|
||||||
void advanceStateImpl(const inputType controller1, const inputType controller2) override
|
void advanceStateImpl(const inputType controller1, const inputType controller2) override
|
||||||
{
|
{
|
||||||
if (_doRendering == true) _nes->emulate_frame(controller1, controller2);
|
if (_doRendering == true) _nes->emulate_frame(controller1, controller2);
|
||||||
|
@ -72,15 +89,6 @@ class QuickNESInstance : public EmuInstance
|
||||||
void *getInternalEmulatorPointer() const override { return _nes; }
|
void *getInternalEmulatorPointer() const override { return _nes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline size_t getStateSizeImpl() const override
|
|
||||||
{
|
|
||||||
uint8_t *data = (uint8_t *)malloc(_DUMMY_SIZE);
|
|
||||||
Mem_Writer w(data, _DUMMY_SIZE);
|
|
||||||
Auto_File_Writer a(w);
|
|
||||||
_nes->save_state(a);
|
|
||||||
free(data);
|
|
||||||
return w.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video buffer
|
// Video buffer
|
||||||
uint8_t *video_buffer;
|
uint8_t *video_buffer;
|
||||||
|
|
|
@ -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 "Blip_Buffer.hpp"
|
#include <climits>
|
||||||
#include <limits.h>
|
#include <cmath>
|
||||||
#include <math.h>
|
#include <cstdlib>
|
||||||
#include <stdlib.h>
|
#include <cstring>
|
||||||
#include <string.h>
|
#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
|
|
@ -3,8 +3,8 @@
|
||||||
// NES non-linear audio buffer
|
// NES non-linear audio buffer
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Multi_Buffer.hpp"
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "multiBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// 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 "Multi_Buffer.hpp"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "multiBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/blipBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
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 "Multi_Buffer.hpp"
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "multiBuffer.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
|
|
@ -4,7 +4,7 @@
|
||||||
// Multi-channel sound buffer interface, and basic mono and stereo buffers
|
// Multi-channel sound buffer interface, and basic mono and stereo buffers
|
||||||
// Blip_Buffer 0.4.0
|
// Blip_Buffer 0.4.0
|
||||||
|
|
||||||
#include "Blip_Buffer.hpp"
|
#include "blipBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
|
@ -2,7 +2,7 @@
|
||||||
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/namco/apu.hpp"
|
#include "apu/namco/apu.hpp"
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/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
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Private oscillators used by Apu
|
// Private oscillators used by Apu
|
||||||
// Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include "Blip_Buffer.hpp"
|
#include "blipBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/blipBuffer.hpp"
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// 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 <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/blipBuffer.hpp"
|
||||||
#include "apu/vrc7/emu2413_state.hpp"
|
#include "apu/vrc7/emu2413_state.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
|
|
|
@ -48,6 +48,13 @@ struct nes_state_t
|
||||||
uint32_t frame_count; // number of frames emulated since power-up
|
uint32_t frame_count; // number of frames emulated since power-up
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nes_state_lite_t
|
||||||
|
{
|
||||||
|
uint16_t timestamp; // CPU clocks * 15 (for NTSC)
|
||||||
|
uint8_t frame_count; // number of frames emulated since power-up
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct joypad_state_t
|
struct joypad_state_t
|
||||||
{
|
{
|
||||||
uint32_t joypad_latches[2]; // joypad 1 & 2 shift registers
|
uint32_t joypad_latches[2]; // joypad 1 & 2 shift registers
|
||||||
|
@ -73,6 +80,20 @@ class Core : private Cpu
|
||||||
typedef Cpu cpu;
|
typedef Cpu cpu;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Flags for lite state storage
|
||||||
|
bool TIMEBlockEnabled = true;
|
||||||
|
bool CPURBlockEnabled = true;
|
||||||
|
bool PPURBlockEnabled = true;
|
||||||
|
bool APURBlockEnabled = true;
|
||||||
|
bool CTRLBlockEnabled = true;
|
||||||
|
bool MAPRBlockEnabled = true;
|
||||||
|
bool LRAMBlockEnabled = true;
|
||||||
|
bool SPRTBlockEnabled = true;
|
||||||
|
bool NTABBlockEnabled = true;
|
||||||
|
bool CHRRBlockEnabled = true;
|
||||||
|
bool SRAMBlockEnabled = true;
|
||||||
|
|
||||||
Core() : ppu(this)
|
Core() : ppu(this)
|
||||||
{
|
{
|
||||||
cart = NULL;
|
cart = NULL;
|
||||||
|
@ -129,93 +150,7 @@ class Core : private Cpu
|
||||||
reset(true, true);
|
reset(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getLiteStateSize() const
|
size_t serializeFullState(uint8_t *buffer) const
|
||||||
{
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
size += sizeof(nes_state_t);
|
|
||||||
size += sizeof(registers_t);
|
|
||||||
size += sizeof(ppu_state_t);
|
|
||||||
size += sizeof(Apu::apu_state_t);
|
|
||||||
size += sizeof(joypad_state_t);
|
|
||||||
size += mapper->state_size;
|
|
||||||
size += low_ram_size;
|
|
||||||
size += Ppu::spr_ram_size;
|
|
||||||
size_t nametable_size = 0x800;
|
|
||||||
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
|
||||||
size += nametable_size;
|
|
||||||
if (ppu.chr_is_writable) size += ppu.chr_size;
|
|
||||||
if (sram_present) size += impl->sram_size;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getStateSize() const
|
|
||||||
{
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // NESS Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // TIME Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += sizeof(nes_state_t);
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // CPUR Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += sizeof(registers_t);
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // PPUR Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += sizeof(ppu_state_t);
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // APUR Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += sizeof(Apu::apu_state_t);
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // CTRL Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += sizeof(joypad_state_t);
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // MAPR Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += mapper->state_size;
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // LRAM Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += low_ram_size;
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // SPRT Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += Ppu::spr_ram_size;
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // NTAB Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size_t nametable_size = 0x800;
|
|
||||||
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
|
||||||
size += nametable_size;
|
|
||||||
|
|
||||||
if (ppu.chr_is_writable)
|
|
||||||
{
|
|
||||||
size += sizeof(char[4]); // CHRR Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += ppu.chr_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sram_present)
|
|
||||||
{
|
|
||||||
size += sizeof(char[4]); // SRAM Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
size += impl->sram_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size += sizeof(char[4]); // gend Block
|
|
||||||
size += sizeof(uint32_t); // Block Size
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t serializeState(uint8_t *buffer) const
|
|
||||||
{
|
{
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
std::string headerCode;
|
std::string headerCode;
|
||||||
|
@ -225,9 +160,9 @@ class Core : private Cpu
|
||||||
|
|
||||||
headerCode = "NESS"; // NESS Block
|
headerCode = "NESS"; // NESS Block
|
||||||
blockSize = 0xFFFFFFFF;
|
blockSize = 0xFFFFFFFF;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
|
|
||||||
headerCode = "TIME"; // TIME Block
|
headerCode = "TIME"; // TIME Block
|
||||||
|
@ -235,11 +170,11 @@ class Core : private Cpu
|
||||||
state.timestamp *= 5;
|
state.timestamp *= 5;
|
||||||
blockSize = sizeof(nes_state_t);
|
blockSize = sizeof(nes_state_t);
|
||||||
dataSource = (void *)&state;
|
dataSource = (void *)&state;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "CPUR"; // CPUR Block
|
headerCode = "CPUR"; // CPUR Block
|
||||||
|
@ -253,72 +188,72 @@ class Core : private Cpu
|
||||||
s.p = r.status;
|
s.p = r.status;
|
||||||
blockSize = sizeof(cpu_state_t);
|
blockSize = sizeof(cpu_state_t);
|
||||||
dataSource = (void *)&s;
|
dataSource = (void *)&s;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "PPUR"; // PPUR Block
|
headerCode = "PPUR"; // PPUR Block
|
||||||
blockSize = sizeof(ppu_state_t);
|
blockSize = sizeof(ppu_state_t);
|
||||||
dataSource = (void *)&ppu;
|
dataSource = (void *)&ppu;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "APUR"; // APUR Block
|
headerCode = "APUR"; // APUR Block
|
||||||
Apu::apu_state_t apuState;
|
Apu::apu_state_t apuState;
|
||||||
impl->apu.save_state(&apuState);
|
impl->apu.save_state(&apuState);
|
||||||
blockSize = sizeof(Apu::apu_state_t);
|
blockSize = sizeof(Apu::apu_state_t);
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &apuState, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &apuState, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "CTRL"; // CTRL Block
|
headerCode = "CTRL"; // CTRL Block
|
||||||
blockSize = sizeof(joypad_state_t);
|
blockSize = sizeof(joypad_state_t);
|
||||||
dataSource = (void *)&joypad;
|
dataSource = (void *)&joypad;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "MAPR"; // MAPR Block
|
headerCode = "MAPR"; // MAPR Block
|
||||||
blockSize = mapper->state_size;
|
blockSize = mapper->state_size;
|
||||||
dataSource = (void *)mapper->state;
|
dataSource = (void *)mapper->state;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "LRAM"; // LRAM Block
|
headerCode = "LRAM"; // LRAM Block
|
||||||
blockSize = low_ram_size;
|
blockSize = low_ram_size;
|
||||||
dataSource = (void *)low_mem;
|
dataSource = (void *)low_mem;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "SPRT"; // SPRT Block
|
headerCode = "SPRT"; // SPRT Block
|
||||||
blockSize = Ppu::spr_ram_size;
|
blockSize = Ppu::spr_ram_size;
|
||||||
dataSource = (void *)ppu.spr_ram;
|
dataSource = (void *)ppu.spr_ram;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "NTAB"; // NTAB Block
|
headerCode = "NTAB"; // NTAB Block
|
||||||
|
@ -326,11 +261,11 @@ class Core : private Cpu
|
||||||
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
||||||
blockSize = nametable_size;
|
blockSize = nametable_size;
|
||||||
dataSource = (void *)ppu.impl->nt_ram;
|
dataSource = (void *)ppu.impl->nt_ram;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
if (ppu.chr_is_writable)
|
if (ppu.chr_is_writable)
|
||||||
|
@ -338,11 +273,11 @@ class Core : private Cpu
|
||||||
headerCode = "CHRR"; // CHRR Block
|
headerCode = "CHRR"; // CHRR Block
|
||||||
blockSize = ppu.chr_size;
|
blockSize = ppu.chr_size;
|
||||||
dataSource = (void *)ppu.impl->chr_ram;
|
dataSource = (void *)ppu.impl->chr_ram;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,25 +286,25 @@ class Core : private Cpu
|
||||||
headerCode = "SRAM"; // SRAM Block
|
headerCode = "SRAM"; // SRAM Block
|
||||||
blockSize = impl->sram_size;
|
blockSize = impl->sram_size;
|
||||||
dataSource = (void *)impl->sram;
|
dataSource = (void *)impl->sram;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], dataSource, blockSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
headerCode = "gend"; // gend Block
|
headerCode = "gend"; // gend Block
|
||||||
blockSize = 0;
|
blockSize = 0;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
if (buffer != nullptr) memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
|
|
||||||
return pos; // Bytes written
|
return pos; // Bytes written
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t deserializeState(const uint8_t *buffer)
|
size_t deserializeFullState(const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
disable_rendering();
|
disable_rendering();
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
|
@ -491,6 +426,275 @@ class Core : private Cpu
|
||||||
return pos; // Bytes read
|
return pos; // Bytes read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void enableLiteStateBlock(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; }
|
||||||
|
|
||||||
|
if (recognizedBlock == false) { fprintf(stderr, "Unrecognized block type: %s\n", block.c_str()); exit(-1);}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void disableLiteStateBlock(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);}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
size_t serializeLiteState(uint8_t *buffer) const
|
||||||
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
uint32_t blockSize = 0;
|
||||||
|
void *dataSource;
|
||||||
|
|
||||||
|
if (TIMEBlockEnabled == true)
|
||||||
|
{
|
||||||
|
nes_state_lite_t state;
|
||||||
|
state.timestamp = nes.timestamp;
|
||||||
|
state.frame_count = (uint8_t)nes.frame_count;
|
||||||
|
state.timestamp *= 5;
|
||||||
|
blockSize = sizeof(nes_state_lite_t);
|
||||||
|
dataSource = (void *)&state;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CPURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(cpu::registers_t);
|
||||||
|
dataSource = (void *)&r;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PPURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(ppu_state_t);
|
||||||
|
dataSource = (void *)&ppu;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (APURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
Apu::apu_state_t apuState;
|
||||||
|
impl->apu.save_state(&apuState);
|
||||||
|
blockSize = sizeof(Apu::apu_state_t);
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], &apuState, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTRLBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(joypad_state_t);
|
||||||
|
dataSource = (void *)&joypad;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAPRBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = mapper->state_size;
|
||||||
|
dataSource = (void *)mapper->state;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LRAMBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = low_ram_size;
|
||||||
|
dataSource = (void *)low_mem;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPRTBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = Ppu::spr_ram_size;
|
||||||
|
dataSource = (void *)ppu.spr_ram;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NTABBlockEnabled == true)
|
||||||
|
{
|
||||||
|
size_t nametable_size = 0x800;
|
||||||
|
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
||||||
|
blockSize = nametable_size;
|
||||||
|
dataSource = (void *)ppu.impl->nt_ram;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHRRBlockEnabled == true)
|
||||||
|
{
|
||||||
|
if (ppu.chr_is_writable)
|
||||||
|
{
|
||||||
|
blockSize = ppu.chr_size;
|
||||||
|
dataSource = (void *)ppu.impl->chr_ram;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SRAMBlockEnabled == true)
|
||||||
|
{
|
||||||
|
if (sram_present)
|
||||||
|
{
|
||||||
|
blockSize = impl->sram_size;
|
||||||
|
dataSource = (void *)impl->sram;
|
||||||
|
if (buffer != nullptr) memcpy(&buffer[pos], dataSource, blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos; // Bytes written
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t deserializeLiteState(const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
disable_rendering();
|
||||||
|
error_count = 0;
|
||||||
|
ppu.burst_phase = 0; // avoids shimmer when seeking to same time over and over
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
uint32_t blockSize = 0;
|
||||||
|
|
||||||
|
// TIME Block
|
||||||
|
if (TIMEBlockEnabled == true)
|
||||||
|
{
|
||||||
|
nes_state_lite_t nesState;
|
||||||
|
blockSize = sizeof(nes_state_lite_t);
|
||||||
|
memcpy(&nesState, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
nes.frame_count = nesState.frame_count;
|
||||||
|
nes.timestamp = nesState.timestamp;
|
||||||
|
nes.timestamp /= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPUR Block
|
||||||
|
if (CPURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(cpu::registers_t);
|
||||||
|
memcpy((void *)&r, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PPUR Block
|
||||||
|
if (PPURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(ppu_state_t);
|
||||||
|
memcpy((void *)&ppu, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// APUR Block
|
||||||
|
if (APURBlockEnabled == true)
|
||||||
|
{
|
||||||
|
Apu::apu_state_t apuState;
|
||||||
|
blockSize = sizeof(Apu::apu_state_t);
|
||||||
|
memcpy(&apuState, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
impl->apu.load_state(apuState);
|
||||||
|
impl->apu.end_frame(-(int)nes.timestamp / ppu_overclock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTRL Block
|
||||||
|
if (CTRLBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = sizeof(joypad_state_t);
|
||||||
|
memcpy((void *)&joypad, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAPR Block
|
||||||
|
if (MAPRBlockEnabled == true)
|
||||||
|
{
|
||||||
|
mapper->default_reset_state();
|
||||||
|
blockSize = mapper->state_size;
|
||||||
|
memcpy((void *)mapper->state, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
mapper->apply_mapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LRAM Block
|
||||||
|
if (LRAMBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = low_ram_size;
|
||||||
|
memcpy((void *)low_mem, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPRT Block
|
||||||
|
if (SPRTBlockEnabled == true)
|
||||||
|
{
|
||||||
|
blockSize = Ppu::spr_ram_size;
|
||||||
|
memcpy((void *)ppu.spr_ram, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NTAB Block
|
||||||
|
if (NTABBlockEnabled == true)
|
||||||
|
{
|
||||||
|
size_t nametable_size = 0x800;
|
||||||
|
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
||||||
|
blockSize = nametable_size;
|
||||||
|
memcpy((void *)ppu.impl->nt_ram, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHRRBlockEnabled == true)
|
||||||
|
{
|
||||||
|
if (ppu.chr_is_writable)
|
||||||
|
{
|
||||||
|
// CHRR Block
|
||||||
|
blockSize = ppu.chr_size;
|
||||||
|
memcpy((void *)ppu.impl->chr_ram, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SRAMBlockEnabled == true)
|
||||||
|
{
|
||||||
|
if (sram_present)
|
||||||
|
{
|
||||||
|
// SRAM Block
|
||||||
|
blockSize = impl->sram_size;
|
||||||
|
memcpy((void *)impl->sram, &buffer[pos], blockSize);
|
||||||
|
pos += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sram_present) enable_sram(true);
|
||||||
|
|
||||||
|
return pos; // Bytes read
|
||||||
|
}
|
||||||
|
|
||||||
void reset(bool full_reset, bool erase_battery_ram)
|
void reset(bool full_reset, bool erase_battery_ram)
|
||||||
{
|
{
|
||||||
if (full_reset)
|
if (full_reset)
|
||||||
|
|
|
@ -121,10 +121,11 @@ imm##op: \
|
||||||
#define BRANCH( cond ) \
|
#define BRANCH( cond ) \
|
||||||
{ \
|
{ \
|
||||||
pc++; \
|
pc++; \
|
||||||
if ( (cond) == false ) [[likely]] {clock_count--; goto loop; } \
|
int offset = (int8_t) data; \
|
||||||
int32_t offset = (int8_t) data; \
|
int extra_clock = (pc & 0xFF) + offset; \
|
||||||
int32_t extra_clock = (pc & 0xFF) + offset; \
|
if ( !(cond) ) {clock_count--; goto loop; } \
|
||||||
pc += offset; \
|
pc += offset; \
|
||||||
|
pc = uint16_t( pc ); \
|
||||||
clock_count += (extra_clock >> 8) & 1; \
|
clock_count += (extra_clock >> 8) & 1; \
|
||||||
goto loop; \
|
goto loop; \
|
||||||
}
|
}
|
||||||
|
@ -201,7 +202,26 @@ inline void Cpu::write( nes_addr_t addr, int value )
|
||||||
}
|
}
|
||||||
|
|
||||||
// status flags
|
// status flags
|
||||||
extern uint8_t clock_table [256];
|
uint8_t clock_table [256] = {
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
|
||||||
|
6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
|
||||||
|
6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
|
||||||
|
6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
|
||||||
|
2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
|
||||||
|
3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
|
||||||
|
2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
|
||||||
|
3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
|
||||||
|
2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
|
||||||
|
2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
|
||||||
|
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
__attribute__((optimize("align-functions=" _PAGE_SIZE)))
|
__attribute__((optimize("align-functions=" _PAGE_SIZE)))
|
||||||
Cpu::result_t Cpu::run ( nes_time_t end )
|
Cpu::result_t Cpu::run ( nes_time_t end )
|
||||||
|
@ -1148,24 +1168,5 @@ end:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t clock_table [256] = {
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
||||||
7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
|
|
||||||
6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
|
|
||||||
6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
|
|
||||||
6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
|
|
||||||
2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
|
|
||||||
3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
|
|
||||||
2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
|
|
||||||
3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
|
|
||||||
2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
|
|
||||||
2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
|
|
||||||
3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "cart.hpp"
|
#include "cart.hpp"
|
||||||
#include "core.hpp"
|
#include "core.hpp"
|
||||||
#include "apu/Multi_Buffer.hpp"
|
#include "apu/multiBuffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -44,8 +44,18 @@ class Emu
|
||||||
|
|
||||||
const uint8_t *getHostPixels() const { return emu.ppu.host_pixels; }
|
const uint8_t *getHostPixels() const { return emu.ppu.host_pixels; }
|
||||||
|
|
||||||
size_t getLiteStateSize() const { return emu.getLiteStateSize(); }
|
// Save emulator state variants
|
||||||
size_t getStateSize() const { return emu.getStateSize(); }
|
size_t serializeFullState(uint8_t *buffer) const { return emu.serializeFullState(buffer); }
|
||||||
|
size_t serializeLiteState(uint8_t *buffer) const { return emu.serializeLiteState(buffer); }
|
||||||
|
|
||||||
|
size_t deserializeFullState(const uint8_t *buffer) { return emu.deserializeFullState(buffer); }
|
||||||
|
size_t deserializeLiteState(const uint8_t *buffer) { return emu.deserializeLiteState(buffer); }
|
||||||
|
|
||||||
|
size_t getLiteStateSize() const { return emu.serializeLiteState(nullptr); }
|
||||||
|
size_t getFullStateSize() const { return emu.serializeFullState(nullptr); }
|
||||||
|
|
||||||
|
void enableLiteStateBlock(const std::string& block) { emu.enableLiteStateBlock(block); };
|
||||||
|
void disableLiteStateBlock(const std::string& block) { emu.disableLiteStateBlock(block); };
|
||||||
|
|
||||||
// Basic emulation
|
// Basic emulation
|
||||||
|
|
||||||
|
@ -141,10 +151,6 @@ class Emu
|
||||||
|
|
||||||
// File save/load
|
// File save/load
|
||||||
|
|
||||||
// Save emulator state
|
|
||||||
size_t serializeState(uint8_t *buffer) const { return emu.serializeState(buffer); }
|
|
||||||
size_t deserializeState(const uint8_t *buffer) { return emu.deserializeState(buffer); }
|
|
||||||
|
|
||||||
// True if current cartridge claims it uses battery-backed memory
|
// True if current cartridge claims it uses battery-backed memory
|
||||||
bool has_battery_ram() const { return cart()->has_battery_ram(); }
|
bool has_battery_ram() const { return cart()->has_battery_ram(); }
|
||||||
|
|
||||||
|
@ -231,8 +237,8 @@ class Emu
|
||||||
virtual const char *init_();
|
virtual const char *init_();
|
||||||
|
|
||||||
virtual void loading_state(State const &) {}
|
virtual void loading_state(State const &) {}
|
||||||
long timestamp() const { return emu.nes.frame_count; }
|
long timestamp() const { return 0; }
|
||||||
void set_timestamp(long t) { emu.nes.frame_count = t; }
|
void set_timestamp(long t) { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
|
|
|
@ -4,10 +4,10 @@ quickerNESAPUSrc = [
|
||||||
'apu/apu.cpp',
|
'apu/apu.cpp',
|
||||||
'apu/oscs.cpp',
|
'apu/oscs.cpp',
|
||||||
'apu/buffer.cpp',
|
'apu/buffer.cpp',
|
||||||
'apu/Blip_Buffer.cpp',
|
'apu/blipBuffer.cpp',
|
||||||
'apu/NESEffectsBuffer.cpp',
|
'apu/NESEffectsBuffer.cpp',
|
||||||
'apu/effectsBuffer.cpp',
|
'apu/effectsBuffer.cpp',
|
||||||
'apu/Multi_Buffer.cpp',
|
'apu/multiBuffer.cpp',
|
||||||
'apu/namco/apu.cpp',
|
'apu/namco/apu.cpp',
|
||||||
'apu/vrc6/apu.cpp',
|
'apu/vrc6/apu.cpp',
|
||||||
'apu/vrc7/emu2413.cpp',
|
'apu/vrc7/emu2413.cpp',
|
||||||
|
|
|
@ -36,15 +36,17 @@ class QuickerNESInstance : public EmuInstance
|
||||||
const uint8_t *getChrMem() const override { return _nes->chr_mem(); };
|
const uint8_t *getChrMem() const override { return _nes->chr_mem(); };
|
||||||
size_t getChrMemSize() const override { return _nes->chr_size(); };
|
size_t getChrMemSize() const override { return _nes->chr_size(); };
|
||||||
|
|
||||||
void serializeState(uint8_t *state) const override
|
void serializeFullState(uint8_t *state) const override { _nes->serializeFullState(state); }
|
||||||
{
|
void deserializeFullState(const uint8_t *state) override { _nes->deserializeFullState(state); }
|
||||||
_nes->serializeState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deserializeState(const uint8_t *state) override
|
void serializeLiteState(uint8_t *state) const override { _nes->serializeLiteState(state); }
|
||||||
{
|
void deserializeLiteState(const uint8_t *state) override { _nes->deserializeLiteState(state); }
|
||||||
_nes->deserializeState(state);
|
|
||||||
}
|
size_t getFullStateSize() const override { return _nes->getFullStateSize(); }
|
||||||
|
size_t getLiteStateSize() const override { return _nes->getLiteStateSize(); }
|
||||||
|
|
||||||
|
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 inputType controller1, const inputType controller2) override
|
||||||
{
|
{
|
||||||
|
@ -58,17 +60,6 @@ class QuickerNESInstance : public EmuInstance
|
||||||
|
|
||||||
void *getInternalEmulatorPointer() const override { return _nes; }
|
void *getInternalEmulatorPointer() const override { return _nes; }
|
||||||
|
|
||||||
private:
|
|
||||||
inline size_t getStateSizeImpl() const override
|
|
||||||
{
|
|
||||||
return _nes->getStateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t getLiteStateSizeImpl() const override
|
|
||||||
{
|
|
||||||
return _nes->getLiteStateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video buffer
|
// Video buffer
|
||||||
uint8_t *video_buffer;
|
uint8_t *video_buffer;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef _USE_QUICKNES
|
#ifdef _USE_QUICKNES
|
||||||
#include "quickNESInstance.hpp"
|
#include "quickNESInstance.hpp"
|
||||||
|
@ -76,14 +78,29 @@ int main(int argc, char *argv[])
|
||||||
if (scriptJson["Expected ROM SHA1"].is_string() == false) EXIT_WITH_ERROR("Script file 'Expected ROM SHA1' entry is not a string\n");
|
if (scriptJson["Expected ROM SHA1"].is_string() == false) EXIT_WITH_ERROR("Script file 'Expected ROM SHA1' entry is not a string\n");
|
||||||
std::string expectedROMSHA1 = scriptJson["Expected ROM SHA1"].get<std::string>();
|
std::string expectedROMSHA1 = scriptJson["Expected ROM SHA1"].get<std::string>();
|
||||||
|
|
||||||
// Creating emulator instance
|
// Parsing disabled blocks in lite state serialization
|
||||||
#ifdef _USE_QUICKNES
|
std::vector<std::string> stateDisabledBlocks;
|
||||||
|
std::string stateDisabledBlocksOutput;
|
||||||
|
if (scriptJson.contains("Disable State Blocks") == false) EXIT_WITH_ERROR("Script file missing 'Disable State Blocks' entry\n");
|
||||||
|
if (scriptJson["Disable State Blocks"].is_array() == false) EXIT_WITH_ERROR("Script file 'Disable State Blocks' is not an array\n");
|
||||||
|
for (const auto& entry : scriptJson["Disable State Blocks"])
|
||||||
|
{
|
||||||
|
if (entry.is_string() == false) EXIT_WITH_ERROR("Script file 'Disable State Blocks' entry is not a string\n");
|
||||||
|
stateDisabledBlocks.push_back(entry.get<std::string>());
|
||||||
|
stateDisabledBlocksOutput += entry.get<std::string>() + std::string(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating emulator instance
|
||||||
|
#ifdef _USE_QUICKNES
|
||||||
auto e = QuickNESInstance();
|
auto e = QuickNESInstance();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _USE_QUICKERNES
|
#ifdef _USE_QUICKERNES
|
||||||
auto e = quickerNES::QuickerNESInstance();
|
auto e = quickerNES::QuickerNESInstance();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Disabling requested blocks from light state serialization
|
||||||
|
for (const auto& block : stateDisabledBlocks) e.disableLiteStateBlock(block);
|
||||||
|
|
||||||
// Loading ROM File
|
// Loading ROM File
|
||||||
e.loadROMFile(romFilePath);
|
e.loadROMFile(romFilePath);
|
||||||
|
@ -94,12 +111,6 @@ int main(int argc, char *argv[])
|
||||||
// Disable rendering
|
// Disable rendering
|
||||||
e.disableRendering();
|
e.disableRendering();
|
||||||
|
|
||||||
// Getting initial hash
|
|
||||||
auto initialHash = e.getStateHash();
|
|
||||||
|
|
||||||
// Getting full state size
|
|
||||||
const auto stateSize = e.getStateSize();
|
|
||||||
|
|
||||||
// Getting lite state size
|
// Getting lite state size
|
||||||
const auto liteStateSize = e.getLiteStateSize();
|
const auto liteStateSize = e.getLiteStateSize();
|
||||||
|
|
||||||
|
@ -128,19 +139,22 @@ int main(int argc, char *argv[])
|
||||||
printf("[] Cycle Type: '%s'\n", cycleType.c_str());
|
printf("[] Cycle Type: '%s'\n", cycleType.c_str());
|
||||||
printf("[] Emulation Core: '%s'\n", emulationCoreName.c_str());
|
printf("[] Emulation Core: '%s'\n", emulationCoreName.c_str());
|
||||||
printf("[] ROM File: '%s'\n", romFilePath.c_str());
|
printf("[] ROM File: '%s'\n", romFilePath.c_str());
|
||||||
printf("[] ROM SHA1: '%s'\n", romSHA1.c_str());
|
//printf("[] ROM SHA1: '%s'\n", romSHA1.c_str());
|
||||||
printf("[] Sequence File: '%s'\n", sequenceFilePath.c_str());
|
printf("[] Sequence File: '%s'\n", sequenceFilePath.c_str());
|
||||||
printf("[] Sequence Length: %lu\n", sequenceLength);
|
printf("[] Sequence Length: %lu\n", sequenceLength);
|
||||||
printf("[] Initial State Hash: 0x%lX%lX\n", initialHash.first, initialHash.second);
|
#ifdef _USE_QUICKNES
|
||||||
printf("[] Full State Size: %lu bytes\n", stateSize);
|
printf("[] State Size: %lu bytes\n", e.getFullStateSize());
|
||||||
printf("[] Lite State Size: %lu bytes\n", liteStateSize);
|
#endif
|
||||||
|
#ifdef _USE_QUICKERNES
|
||||||
|
printf("[] State Size: %lu bytes - Disabled Blocks: [ %s ]\n", e.getLiteStateSize(), stateDisabledBlocksOutput.c_str());
|
||||||
|
#endif
|
||||||
printf("[] ********** Running Test **********\n");
|
printf("[] ********** Running Test **********\n");
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
// Serializing initial state
|
// Serializing initial state
|
||||||
uint8_t *currentState = (uint8_t *)malloc(stateSize);
|
uint8_t *currentState = (uint8_t *)malloc(liteStateSize);
|
||||||
e.serializeState(currentState);
|
e.serializeLiteState(currentState);
|
||||||
|
|
||||||
// Check whether to perform each action
|
// Check whether to perform each action
|
||||||
bool doPreAdvance = cycleType == "Full";
|
bool doPreAdvance = cycleType == "Full";
|
||||||
|
@ -152,9 +166,9 @@ int main(int argc, char *argv[])
|
||||||
for (const std::string &input : sequence)
|
for (const std::string &input : sequence)
|
||||||
{
|
{
|
||||||
if (doPreAdvance == true) e.advanceState(input);
|
if (doPreAdvance == true) e.advanceState(input);
|
||||||
if (doDeserialize == true) e.deserializeState(currentState);
|
if (doDeserialize == true) e.deserializeLiteState(currentState);
|
||||||
e.advanceState(input);
|
e.advanceState(input);
|
||||||
if (doSerialize == true) e.serializeState(currentState);
|
if (doSerialize == true) e.serializeLiteState(currentState);
|
||||||
}
|
}
|
||||||
auto tf = std::chrono::high_resolution_clock::now();
|
auto tf = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,5 @@
|
||||||
test.sol
|
test.sol
|
||||||
*.hash
|
*.hash
|
||||||
*.out
|
*.out
|
||||||
|
*.sh
|
||||||
|
|
||||||
|
|
|
@ -1 +1,20 @@
|
||||||
Some of the sequences hosted in this folder correspond to movies published in tasvideos.org under the Creative Commons 2.0 license. These movies were created by the author of this code (Sergio Martin, a.k.a. eien86), unless stated otherwise.
|
Some of the sequences hosted in this folder correspond to movies published in tasvideos.org under the Creative Commons 2.0 license. These movies were created by the author of this code (Sergio Martin, a.k.a. eien86) and collaborators, unless otherwise stated.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
Sprilo is a open-source free game. This rom was obtained from
|
||||||
|
- https://itch.io/jam/game-off-2017
|
||||||
|
- https://github.com/cbrwn/gameoff
|
||||||
|
- We use the movie https://tasvideos.org/3557G by MrTASer distributed under the CC2.0 license
|
||||||
|
|
||||||
|
Nova The Squirrel is a open-source free game. This rom was obtained from
|
||||||
|
- https://github.com/NovaSquirrel/NovaTheSquirrel
|
||||||
|
- https://novasquirrel.itch.io/nova-the-squirrel
|
||||||
|
- We use the movie https://tasvideos.org/5246M by Cephla distributed under the CC2.0 license
|
||||||
|
|
||||||
|
For Saiyuuki World
|
||||||
|
- We use the movie https://tasvideos.org/4422M by aiqiyou & J.Y distributed under the CC2.0 license
|
||||||
|
|
||||||
|
For Metroid
|
||||||
|
- We use part of the movie https://tasvideos.org/3666M by The8bitbeast distributed under the CC2.0 license
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Arkanoid (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "arkanoid.warpless.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Arkanoid (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "arkanoid.warps.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ]
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
game = 'arkanoid'
|
|
||||||
|
|
||||||
bash = find_program('bash')
|
|
||||||
|
|
||||||
goal = 'warpless'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
||||||
|
|
||||||
goal = 'warps'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Arkanoid (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "warpless.sol"
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Arkanoid (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "warps.sol"
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Castlevania (U) (PRG0) [!].nes",
|
||||||
|
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "castlevania1.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Castlevania (U) (PRG0) [!].nes",
|
||||||
|
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "castlevania1.pacifist.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Castlevania (U) (PRG0) [!].nes",
|
|
||||||
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
game = 'castlevania1'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
||||||
|
|
||||||
goal = 'pacifist'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Castlevania (U) (PRG0) [!].nes",
|
|
||||||
"Expected ROM SHA1": "A31B8BD5B370A9103343C866F3C2B2998E889341",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Verification State File": "pacifist.final.state",
|
|
||||||
"Sequence File": "pacifist.sol"
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Galaga - Demons of Death (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "DA54C223D79FA59EB95437854B677CF69B5CAC8A",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "galaga.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Galaga - Demons of Death (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "DA54C223D79FA59EB95437854B677CF69B5CAC8A",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'galaga'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Ironsword - Wizards & Warriors II (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "97B79E432F62403FB9F877090850C41112A9A168",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "ironSword.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Ironsword - Wizards & Warriors II (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "97B79E432F62403FB9F877090850C41112A9A168",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'ironSword'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,30 +1,59 @@
|
||||||
nomalloc = environment({'MALLOC_PERTURB_': '0'})
|
nomalloc = environment({'MALLOC_PERTURB_': '0'})
|
||||||
|
|
||||||
bash = find_program('bash')
|
bash = find_program('bash')
|
||||||
testCommands = ['../run_test.sh', quickerNESTester.path(), quickNESTester.path() ]
|
testCommands = ['run_test.sh', quickerNESTester.path(), quickNESTester.path() ]
|
||||||
testTimeout = 120
|
testTimeout = 120
|
||||||
|
|
||||||
|
# Tests for copyrighted game roms (only for local testing or own CI runners)
|
||||||
|
protectedTestSet = [
|
||||||
|
'arkanoid.warpless.test',
|
||||||
|
'arkanoid.warps.test',
|
||||||
|
'castlevania1.anyPercent.test',
|
||||||
|
'castlevania1.pacifist.test',
|
||||||
|
'galaga.anyPercent.test',
|
||||||
|
'ironSword.anyPercent.test',
|
||||||
|
'metroid.playaround.test',
|
||||||
|
'nigelMansell.anyPercent.test',
|
||||||
|
'ninjaGaiden.anyPercent.test',
|
||||||
|
'ninjaGaiden.pacifist.test',
|
||||||
|
'ninjaGaiden2.anyPercent.test',
|
||||||
|
'ninjaGaiden2.pacifist.test',
|
||||||
|
'novaTheSquirrel.anyPercent.test',
|
||||||
|
'princeOfPersia.anyPercent.test',
|
||||||
|
'saintSeiyaKanketsuHen.anyPercent.test',
|
||||||
|
'saintSeiyaOugonDensetsu.anyPercent.test',
|
||||||
|
'saiyuukiWorld.anyPercent.test',
|
||||||
|
'saiyuukiWorld.lastHalf.test',
|
||||||
|
'solarJetman.anyPercent.test',
|
||||||
|
'sprilo.anyPercent.test',
|
||||||
|
'superMarioBros.warpless.test',
|
||||||
|
'superMarioBros.warps.test',
|
||||||
|
'superMarioBros3.warps.test',
|
||||||
|
'superOffroad.anyPercent.test',
|
||||||
|
'tennis.anyPercent.test',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Tests for open source free roms (for public cloud testing)
|
||||||
|
openSourceTestSet = [
|
||||||
|
'novaTheSquirrel.anyPercent.test',
|
||||||
|
'sprilo.anyPercent.test',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Creating test set based on whether copyrighted roms are to be used
|
||||||
|
testSet = openSourceTestSet
|
||||||
if get_option('onlyOpenSource') == false
|
if get_option('onlyOpenSource') == false
|
||||||
|
testSet += protectedTestSet
|
||||||
subdir('arkanoid')
|
|
||||||
subdir('castlevania1')
|
|
||||||
subdir('superOffroad')
|
|
||||||
subdir('princeOfPersia')
|
|
||||||
subdir('ninjaGaiden')
|
|
||||||
subdir('ninjaGaiden2')
|
|
||||||
subdir('ironSword')
|
|
||||||
subdir('solarJetman')
|
|
||||||
subdir('tennis')
|
|
||||||
subdir('nigelMansell')
|
|
||||||
subdir('galaga')
|
|
||||||
subdir('saintSeiyaOugonDensetsu')
|
|
||||||
subdir('saintSeiyaKanketsuHen')
|
|
||||||
subdir('superMarioBros')
|
|
||||||
subdir('superMarioBros3')
|
|
||||||
subdir('saiyuukiWorld')
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Open source games
|
# Adding tests to the suite
|
||||||
subdir('sprilo')
|
foreach testFile : testSet
|
||||||
subdir('novaTheSquirrel')
|
testSuite = testFile.split('.')[0]
|
||||||
|
testName = testFile.split('.')[1]
|
||||||
|
test(testName,
|
||||||
|
bash,
|
||||||
|
workdir : meson.current_source_dir(),
|
||||||
|
timeout: testTimeout,
|
||||||
|
args : [ testCommands, testFile, '--cycleType', 'Full'],
|
||||||
|
suite : [ testSuite ])
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Metroid (U) (PRG0) [!].nes",
|
||||||
|
"Expected ROM SHA1": "ECF39EC5A33E6A6F832F03E8FFC61C5D53F4F90B",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "metroid.playaround.sol",
|
||||||
|
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Nigel Mansell's World Championship Challenge (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "BBE5CF2DFA0B5422776A530D6F1B617238A8569F",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "nigelMansell.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Nigel Mansell's World Championship Challenge (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "BBE5CF2DFA0B5422776A530D6F1B617238A8569F",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'nigelMansell'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Ninja Gaiden (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "ninjaGaiden.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Ninja Gaiden (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "ninjaGaiden.pacifist.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Ninja Gaiden (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
game = 'ninjaGaiden'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
||||||
|
|
||||||
goal = 'pacifist'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Ninja Gaiden (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "CA513F841D75EFEB33BB8099FB02BEEB39F6BB9C",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "pacifist.sol"
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Ninja Gaiden II - The Dark Sword of Chaos (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "ninjaGaiden2.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Ninja Gaiden II - The Dark Sword of Chaos (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "ninjaGaiden2.pacifist.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Ninja Gaiden II - The Dark Sword of Chaos (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
game = 'ninjaGaiden2'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
||||||
|
|
||||||
goal = 'pacifist'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Ninja Gaiden II - The Dark Sword of Chaos (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "B1796660E4A4CEFC72181D4BF4F97999BC048A77",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "pacifist.sol"
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/nova.nes",
|
||||||
|
"Expected ROM SHA1": "B6B07EE76492ED475F39167C89B342353F999231",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "novaTheSquirrel.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
Nova The Squirrel is a open-source free game. This rom was obtained from
|
|
||||||
https://github.com/NovaSquirrel/NovaTheSquirrel
|
|
||||||
https://novasquirrel.itch.io/nova-the-squirrel
|
|
||||||
|
|
||||||
We use the movie https://tasvideos.org/5246M by Cephla distributed under the CC2.0 license
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/nova.nes",
|
|
||||||
"Expected ROM SHA1": "B6B07EE76492ED475F39167C89B342353F999231",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'novaTheSquirrel'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Prince of Persia (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "6B58F149F34FA829135619C58700CAAA95B9CDE3",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "princeOfPersia.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Prince of Persia (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "6B58F149F34FA829135619C58700CAAA95B9CDE3",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'princeOfPersia'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -1,27 +1,19 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Finding all test scripts
|
# Finding all test scripts
|
||||||
testScriptList=`find . -type f -name *.test`
|
testScriptList=`find . -type f -name "*.test"`
|
||||||
|
|
||||||
# Iterating over the scripts
|
# Iterating over the scripts
|
||||||
for script in ${testScriptList}; do
|
for script in ${testScriptList}; do
|
||||||
|
|
||||||
# Getting base folder
|
|
||||||
folder=`dirname ${script}`
|
|
||||||
|
|
||||||
# Getting filename
|
# Getting filename
|
||||||
fileName=`basename ${script}`
|
fileName=`basename ${script}`
|
||||||
|
|
||||||
# Going to folder
|
|
||||||
pushd ${folder}
|
|
||||||
|
|
||||||
# Running script on quickerNES
|
# Running script on quickerNES
|
||||||
quickerNESTester ${fileName} --cycleType Rerecord
|
quickerNESTester ${fileName} --cycleType Rerecord
|
||||||
|
|
||||||
# Running script on quickerNES
|
# Running script on quickerNES
|
||||||
quickNESTester ${fileName} --cycleType Rerecord
|
quickNESTester ${fileName} --cycleType Rerecord
|
||||||
|
|
||||||
# Coming back
|
|
||||||
popd
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Saint Seiya - Ougon Densetsu Kanketsu Hen (J) [!].nes",
|
||||||
|
"Expected ROM SHA1": "F871D9B3DAFDDCDAD5F2ACD71044292E5169064E",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "saintSeiyaKanketsuHen.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Saint Seiya - Ougon Densetsu Kanketsu Hen (J) [!].nes",
|
|
||||||
"Expected ROM SHA1": "F871D9B3DAFDDCDAD5F2ACD71044292E5169064E",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'saintSeiyaKanketsuHen'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Saint Seiya - Ougon Densetsu (J) [!].nes",
|
||||||
|
"Expected ROM SHA1": "3F3B499CF50386084E053BCA096AE8E52330CFAE",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "saintSeiyaKanketsuHen.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Saint Seiya - Ougon Densetsu (J) [!].nes",
|
|
||||||
"Expected ROM SHA1": "3F3B499CF50386084E053BCA096AE8E52330CFAE",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'saintSeiyaOugonDensetsu'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Saiyuuki World (J).nes",
|
||||||
|
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "saiyuukiWorld.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Saiyuuki World (J).nes",
|
||||||
|
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
|
||||||
|
"Initial State File": "saiyuukiWorld.lastHalf.state",
|
||||||
|
"Sequence File": "saiyuukiWorld.lastHalf.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Saiyuuki World (J).nes",
|
|
||||||
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol",
|
|
||||||
"Credits": "https://tasvideos.org/4422M by aiqiyou & J.Y"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Saiyuuki World (J).nes",
|
|
||||||
"Expected ROM SHA1": "C2F12D915A4D0B1FFDF8A64AE1092CE6A2D08770",
|
|
||||||
"Initial State File": "lastHalf.state",
|
|
||||||
"Sequence File": "anyPercent.sol",
|
|
||||||
"Credits": "https://tasvideos.org/4422M by aiqiyou & J.Y"
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
game = 'saiyuukiWorld'
|
|
||||||
|
|
||||||
bash = find_program('bash')
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal + '-FullCycle', bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
||||||
|
|
||||||
goal = 'lastHalf'
|
|
||||||
test(goal + '-FullCycle', bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Solar Jetman - Hunt for the Golden Warpship (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "872B91A2F7A2F635061EF43F79E7F7E9F59F5C50",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "solarJetman.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"Rom File": "../roms/Solar Jetman - Hunt for the Golden Warpship (U) [!].nes",
|
|
||||||
"Expected ROM SHA1": "872B91A2F7A2F635061EF43F79E7F7E9F59F5C50",
|
|
||||||
"Initial State File": "",
|
|
||||||
"Sequence File": "anyPercent.sol"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
game = 'solarJetman'
|
|
||||||
|
|
||||||
goal = 'anyPercent'
|
|
||||||
test(goal, bash, workdir : meson.current_source_dir(), timeout: testTimeout, args : [ testCommands, goal + '.test', '--cycleType', 'Full'], suite: [ game, goal ] )
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/sprilo.nes",
|
||||||
|
"Expected ROM SHA1": "6EC09B9B51320A536A786D3D4719432B714C5779",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "sprilo.anyPercent.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "CTRL" ]
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue