Skip to content

Commit

Permalink
Save state (#63)
Browse files Browse the repository at this point in the history
* savestate: serialize/deserialize emulator state #56

* debug: refactor debug classes

* gui: refactoring

* gui: refactored remaining windows

* system: moved system helpers to separate namespace

* github: update template to include save state info

* premake: use tabs
  • Loading branch information
JaCzekanski authored Sep 17, 2019
1 parent b766eda commit e3ce3f8
Show file tree
Hide file tree
Showing 100 changed files with 2,073 additions and 1,316 deletions.
21 changes: 14 additions & 7 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
* Build: specify what build of Avocado you're using.
* OS: which operational system you're running Avocado on.
* Hardware: CPU, GPU, RAM.
* Game: What game you're trying to play/test (including the game ID, listed as "Serial" here http://redump.org/discs/system/psx/)
* Behavior: give details about your issue with Avocado
* Screenshots/Videos: if possible (and when applicable), add a screenshot or video about the issue
* Log: DON'T copy-paste the log here, just save it on a text file (.txt) and drag the file to this window to add it
**Game**: What game you're trying to play/test (including the game ID, listed as "Serial" here http://redump.org/discs/system/psx/)


**Version**: specify what build of Avocado you're using. (see Help->About)

**Hardware**: CPU, GPU, RAM, Operating system


**Behavior**: give details about what is happening with game/emulator

**Attachments**:
* **Screenshots/Videos**: (if possible (and when applicable), add a screenshot or video about the issue)
* **Save state**: (use Backspace to rewind emulation few seconds before the issue happend and make quick save using F5, state can be found in data/state/GAME_ID_0.state)
* **Logs**: (if available)
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@
[submodule "externals/fmt"]
path = externals/fmt
url = https://github.com/fmtlib/fmt
[submodule "externals/cereal"]
path = externals/cereal
url = https://github.com/USCiLab/cereal.git
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ See [Avocado compatibility list](https://avocado-db.czekanski.info)

## Changelog

*16.09.2019* - Save states

*5.09.2019* - Vibration support

*2.09.2019* - Anti-Modchip and LibCrypt protected games support
Expand Down Expand Up @@ -85,8 +87,10 @@ PAL games with LibCrypt protection need additional subchannel info - download pr
- **F1** - hide GUI
- **F2** - soft reset
- **Shift-F2** - hard reset
- **F7** - single frame
- **F5** - quick save
- **F7** - quick load
- **Tab** - disable framelimiting
- **Backspace** - rewind one second

Configure controls under Options->Controller menu.

Expand Down
3 changes: 3 additions & 0 deletions data/state/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*

!.gitignore
1 change: 1 addition & 0 deletions externals/cereal
Submodule cereal added at 51cbda
33 changes: 19 additions & 14 deletions premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require "./premake/androidmk"

workspace "Avocado"
configurations { "debug", "release" }
startproject "avocado"
startproject "avocado"

ndkstl "c++_static"
ndkplatform "android-24"
Expand All @@ -22,31 +22,31 @@ filter "options:enable-io-log"
defines "ENABLE_IO_LOG"

newoption {
trigger = "asan",
description = "Build with Address Sanitizer enabled"
trigger = "asan",
description = "Build with Address Sanitizer enabled"
}
filter "options:asan"
symbols "On"
buildoptions {"-fsanitize=address"}
buildoptions {"-fsanitize=address"}
linkoptions {"-fsanitize=address"}

newoption {
trigger = "msan",
description = "Build with Memory Sanitizer enabled"
trigger = "msan",
description = "Build with Memory Sanitizer enabled"
}
filter "options:msan"
symbols "On"
buildoptions {"-fsanitize=memory"}
buildoptions {"-fsanitize=memory"}
linkoptions {"-fsanitize=memory"}

newoption {
trigger = "ubsan",
description = "Build with Undefined Behaviour Sanitizer enabled"
trigger = "ubsan",
description = "Build with Undefined Behaviour Sanitizer enabled"
}
filter "options:ubsan"
symbols "On"
buildoptions {"-fsanitize=undefined"}
linkoptions {"-fsanitize=undefined"}
buildoptions {"-fsanitize=undefined"}
linkoptions {"-fsanitize=undefined"}

filter {}
language "c++"
Expand Down Expand Up @@ -94,6 +94,9 @@ filter "action:gmake"

filter "action:vs*"
defines "_CRT_SECURE_NO_WARNINGS"

filter { "action:vs*", "configurations:Debug" }
defines "_ITERATOR_DEBUG_LEVEL=0"

filter "action:xcode*"
buildoptions "-fvisibility=hidden"
Expand Down Expand Up @@ -146,6 +149,7 @@ project "core"
"externals/EventBus/lib/include",
"externals/magic_enum/include",
"externals/fmt/include",
"externals/cereal/include",
}

files {
Expand Down Expand Up @@ -186,9 +190,10 @@ project "avocado"
"externals/stb",
"externals/libchdr/src",
"externals/filesystem/include",
"externals/EventBus/lib/include",
"externals/EventBus/lib/include",
"externals/magic_enum/include",
"externals/fmt/include",
"externals/cereal/include",
}

links {
Expand Down Expand Up @@ -252,7 +257,7 @@ project "avocado"


filter {"system:macosx"}
kind "WindowedApp"
kind "WindowedApp"
files {
"src/imgui/**.*",
"src/renderer/opengl/**.*",
Expand Down Expand Up @@ -327,4 +332,4 @@ project "avocado_autotest"

links {
"core"
}
}
14 changes: 11 additions & 3 deletions src/config.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,25 @@ const json defaultConfig = {
}},
{"vsync", false},
{"forceNtsc", false},
}}
}},
{"sound", {
{"enabled", true},
}},
{"emulator", {
{"preserveState", true},
{"timeTravel", true},
}},
}},
{"debug", {
{"log", {
{ "system",1u },
{ "system", 1u },
{ "bios", 0u },
{ "cdrom", 0u },
{ "memoryCard", 0u },
{ "controller", 0u },
{ "dma", 0u },
{ "mdec", 0u }
{ "mdec", 0u },
{ "gte", 0u},
}}
}},
{"memoryCard", {
Expand Down
43 changes: 29 additions & 14 deletions src/cpu/cop0.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,34 +87,34 @@ struct COP0 {
enum class Mode : uint32_t { kernel = 0, user = 1 };
enum class BootExceptionVectors { ram = 0, rom = 1 };
struct {
Bit interruptEnable : 1;
uint32_t interruptEnable : 1;
Mode mode : 1;

Bit previousInterruptEnable : 1;
uint32_t previousInterruptEnable : 1;
Mode previousMode : 1;

Bit oldInterruptEnable : 1;
uint32_t oldInterruptEnable : 1;
Mode oldMode : 1;

uint32_t : 2;

uint32_t interruptMask : 8;
Bit isolateCache : 1;
Bit swappedCache : 1;
Bit writeZeroAsParityBits : 1;
Bit : 1; // CM
Bit cacheParityError : 1;
Bit tlbShutdown : 1; // TS
uint32_t isolateCache : 1;
uint32_t swappedCache : 1;
uint32_t writeZeroAsParityBits : 1;
uint32_t : 1; // CM
uint32_t cacheParityError : 1;
uint32_t tlbShutdown : 1; // TS

BootExceptionVectors bootExceptionVectors : 1;
uint32_t : 2;
Bit reverseEndianness : 1;
uint32_t reverseEndianness : 1;
uint32_t : 2;

Bit cop0Enable : 1;
Bit cop1Enable : 1;
Bit cop2Enable : 1;
Bit cop3Enable : 1;
uint32_t cop0Enable : 1;
uint32_t cop1Enable : 1;
uint32_t cop2Enable : 1;
uint32_t cop3Enable : 1;
};

void enterException() {
Expand Down Expand Up @@ -169,4 +169,19 @@ struct COP0 {
std::pair<uint32_t, bool> read(int reg);
void write(int reg, uint32_t value);
void returnFromException();

template <class Archive>
void serialize(Archive& ar) {
ar(bpc);
ar(bda);
ar(tar);
ar(dcic._reg);
ar(bada);
ar(bdam);
ar(bpcm);
ar(status._reg);
ar(cause._reg);
ar(epc);
ar(prid);
}
};
18 changes: 16 additions & 2 deletions src/cpu/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ r31 ra - return address
*/

struct LoadSlot {
uint32_t reg : 5;
uint32_t reg;
uint32_t data;
uint32_t prevData;

template <class Archive>
void serialize(Archive& ar) {
ar(reg, data, prevData);
}
};

struct CPU {
Expand All @@ -62,9 +67,9 @@ struct CPU {
std::array<LoadSlot, 2> slots; // Load Delay slots

std::array<uint32_t, REGISTER_COUNT> reg;
uint32_t hi, lo;
COP0 cop0;
GTE gte;
uint32_t hi, lo;
System* sys;
Opcode _opcode;

Expand Down Expand Up @@ -110,5 +115,14 @@ struct CPU {
Breakpoint(bool singleTime) : singleTime(singleTime) {}
};
std::unordered_map<uint32_t, Breakpoint> breakpoints;

template <class Archive>
void serialize(Archive& ar) {
ar(PC, nextPC, inBranchDelay, branchTaken);
ar(slots);
ar(reg, hi, lo);
ar(cop0);
ar(gte);
}
};
}; // namespace mips
72 changes: 45 additions & 27 deletions src/cpu/gte/gte.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@ GTE::GTE() : unrTable(generateUnrTable()) {

GTE::~GTE() { bus.unlistenAll(busToken); }

void GTE::reload() { widescreenHack = config["options"]["graphics"]["forceWidescreen"]; }
constexpr std::array<uint8_t, 0x101> GTE::generateUnrTable() {
std::array<uint8_t, 0x101> table = {{0}};
for (int i = 0; i < (int)table.size(); i++) {
table[i] = std::max(0, (0x40000 / (i + 0x100) + 1) / 2 - 0x101);
}
return table;
}

void GTE::reload() {
widescreenHack = config["options"]["graphics"]["forceWidescreen"];
logging = config["debug"]["log"]["gte"].get<int>();
}

uint32_t GTE::read(uint8_t n) {
uint32_t ret = [this](uint8_t n) -> uint32_t {
Expand Down Expand Up @@ -92,12 +103,16 @@ uint32_t GTE::read(uint8_t n) {
}
}(n);

log.push_back({GTE_ENTRY::MODE::read, n, ret});
if (logging) {
log.push_back({GTE_ENTRY::MODE::read, n, ret});
}
return ret;
}

void GTE::write(uint8_t n, uint32_t d) {
log.push_back({GTE_ENTRY::MODE::write, n, d});
if (logging) {
log.push_back({GTE_ENTRY::MODE::write, n, d});
}
switch (n) {
case 0:
v[0].y = d >> 16;
Expand Down Expand Up @@ -245,34 +260,37 @@ void GTE::write(uint8_t n, uint32_t d) {
}
}

bool GTE::command(gte::Command& cmd) {
void GTE::command(gte::Command& cmd) {
if (logging) {
log.push_back({GTE_ENTRY::MODE::func, cmd.cmd, 0});
}

flag.reg = 0;
this->sf = cmd.sf;
this->lm = cmd.lm;

switch (cmd.cmd) {
case 0x01: rtps(); return true;
case 0x06: nclip(); return true;
case 0x0c: op(); return true;
case 0x10: dpcs(); return true;
case 0x11: intpl(); return true;
case 0x12: mvmva(cmd.mvmvaMultiplyMatrix, cmd.mvmvaMultiplyVector, cmd.mvmvaTranslationVector); return true;
case 0x13: ncds(); return true;
case 0x14: cdp(); return true;
case 0x16: ncdt(); return true;
case 0x1b: nccs(); return true;
case 0x1c: cc(); return true;
case 0x1e: ncs(); return true;
case 0x20: nct(); return true;
case 0x2a: dpct(); return true;
case 0x28: sqr(); return true;
case 0x29: dcpl(); return true;
case 0x2d: avsz3(); return true;
case 0x2e: avsz4(); return true;
case 0x30: rtpt(); return true;
case 0x3d: gpf(); return true;
case 0x3e: gpl(); return true;
case 0x3f: ncct(); return true;
default: return false;
case 0x01: rtps(); break;
case 0x06: nclip(); break;
case 0x0c: op(); break;
case 0x10: dpcs(); break;
case 0x11: intpl(); break;
case 0x12: mvmva(cmd.mvmvaMultiplyMatrix, cmd.mvmvaMultiplyVector, cmd.mvmvaTranslationVector); break;
case 0x13: ncds(); break;
case 0x14: cdp(); break;
case 0x16: ncdt(); break;
case 0x1b: nccs(); break;
case 0x1c: cc(); break;
case 0x1e: ncs(); break;
case 0x20: nct(); break;
case 0x2a: dpct(); break;
case 0x28: sqr(); break;
case 0x29: dcpl(); break;
case 0x2d: avsz3(); break;
case 0x2e: avsz4(); break;
case 0x30: rtpt(); break;
case 0x3d: gpf(); break;
case 0x3e: gpl(); break;
case 0x3f: ncct(); break;
}
}
Loading

0 comments on commit e3ce3f8

Please sign in to comment.