Skip to content
Permalink
Browse files

Save state (#63)

* 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 committed Sep 17, 2019
1 parent b766eda commit e3ce3f8c71a7cc8f53db297267dc8e5fcf574fa4
Showing with 2,078 additions and 1,321 deletions.
  1. +14 βˆ’7 .github/ISSUE_TEMPLATE.md
  2. +3 βˆ’0 .gitmodules
  3. +5 βˆ’1 README.md
  4. +3 βˆ’0 data/state/.gitignore
  5. +1 βˆ’0 externals/cereal
  6. +19 βˆ’14 premake5.lua
  7. +11 βˆ’3 src/config.cpp
  8. +29 βˆ’14 src/cpu/cop0.h
  9. +16 βˆ’2 src/cpu/cpu.h
  10. +45 βˆ’27 src/cpu/gte/gte.cpp
  11. +63 βˆ’34 src/cpu/gte/gte.h
  12. +5 βˆ’0 src/cpu/gte/math.h
  13. +0 βˆ’1 src/cpu/instructions.cpp
  14. +0 βˆ’1 src/device/cdrom/cdrom.cpp
  15. +29 βˆ’0 src/device/cdrom/cdrom.h
  16. +5 βˆ’0 src/device/cdrom/fifo.h
  17. +6 βˆ’0 src/device/controller/controller.h
  18. +10 βˆ’2 src/device/device.h
  19. +8 βˆ’7 src/device/dma/dma.cpp
  20. +15 βˆ’11 src/device/dma/dma.h
  21. +3 βˆ’3 src/device/dma/dma0_channel.cpp
  22. +3 βˆ’3 src/device/dma/dma0_channel.h
  23. +3 βˆ’3 src/device/dma/dma1_channel.cpp
  24. +3 βˆ’3 src/device/dma/dma1_channel.h
  25. +3 βˆ’3 src/device/dma/dma2_channel.cpp
  26. +4 βˆ’4 src/device/dma/dma2_channel.h
  27. +3 βˆ’5 src/device/dma/dma3_channel.cpp
  28. +4 βˆ’5 src/device/dma/dma3_channel.h
  29. +3 βˆ’3 src/device/dma/dma4_channel.cpp
  30. +3 βˆ’3 src/device/dma/dma4_channel.h
  31. +5 βˆ’0 src/device/dma/dma5_channel.cpp
  32. +9 βˆ’0 src/device/dma/dma5_channel.h
  33. +3 βˆ’3 src/device/dma/dma6_channel.cpp
  34. +3 βˆ’3 src/device/dma/dma6_channel.h
  35. +19 βˆ’33 src/device/dma/dma_channel.cpp
  36. +13 βˆ’10 src/device/dma/dma_channel.h
  37. +32 βˆ’27 src/device/gpu/gpu.cpp
  38. +53 βˆ’11 src/device/gpu/gpu.h
  39. +15 βˆ’20 src/device/gpu/registers.h
  40. +0 βˆ’36 src/device/interrupt.cpp
  41. +16 βˆ’14 src/device/interrupt.h
  42. +10 βˆ’5 src/device/mdec/mdec.h
  43. +5 βˆ’0 src/device/memory_control.h
  44. +5 βˆ’0 src/device/serial.h
  45. +20 βˆ’17 src/device/spu/noise.cpp
  46. +9 βˆ’5 src/device/spu/noise.h
  47. +28 βˆ’0 src/device/spu/spu.h
  48. +22 βˆ’0 src/device/spu/voice.h
  49. +3 βˆ’1 src/device/timer.cpp
  50. +19 βˆ’9 src/device/timer.h
  51. +2 βˆ’2 src/disc/disc.cpp
  52. +1 βˆ’1 src/disc/empty.h
  53. +23 βˆ’0 src/disc/load.cpp
  54. +8 βˆ’0 src/disc/load.h
  55. +1 βˆ’1 src/disc/subchannel_q.cpp
  56. +7 βˆ’2 src/disc/subchannel_q.h
  57. +4 βˆ’7 src/platform/windows/file/file.cpp
  58. +1 βˆ’1 src/platform/windows/gui/debug/{cdrom β†’ }/cdrom.cpp
  59. +1 βˆ’1 src/platform/windows/gui/debug/{cdrom β†’ }/cdrom.h
  60. +110 βˆ’3 src/platform/windows/gui/debug/{cpu β†’ }/cpu.cpp
  61. +43 βˆ’0 src/platform/windows/gui/debug/cpu.h
  62. +0 βˆ’34 src/platform/windows/gui/debug/cpu/cpu.h
  63. +37 βˆ’302 src/platform/windows/gui/{debug.cpp β†’ debug/gpu.cpp}
  64. +33 βˆ’0 src/platform/windows/gui/debug/gpu.h
  65. +0 βˆ’32 src/platform/windows/gui/debug/gpu/gpu.cpp
  66. +0 βˆ’6 src/platform/windows/gui/debug/gpu/gpu.h
  67. +141 βˆ’0 src/platform/windows/gui/debug/gte.cpp
  68. +15 βˆ’0 src/platform/windows/gui/debug/gte.h
  69. +60 βˆ’0 src/platform/windows/gui/debug/io.cpp
  70. +16 βˆ’0 src/platform/windows/gui/debug/io.h
  71. +1 βˆ’0 src/platform/windows/gui/debug/{kernel β†’ }/kernel.cpp
  72. +7 βˆ’0 src/platform/windows/gui/debug/kernel.h
  73. +0 βˆ’6 src/platform/windows/gui/debug/kernel/kernel.h
  74. +45 βˆ’40 src/platform/windows/gui/{debug_spu.cpp β†’ debug/spu.cpp}
  75. +17 βˆ’0 src/platform/windows/gui/debug/spu.h
  76. +29 βˆ’26 src/platform/windows/gui/debug/{timers β†’ }/timers.cpp
  77. +19 βˆ’0 src/platform/windows/gui/debug/timers.h
  78. +0 βˆ’13 src/platform/windows/gui/debug/timers/timers.h
  79. +1 βˆ’1 src/platform/windows/gui/{ β†’ file}/file.cpp
  80. 0 src/platform/windows/gui/{ β†’ file}/file.h
  81. +166 βˆ’182 src/platform/windows/gui/gui.cpp
  82. +45 βˆ’14 src/platform/windows/gui/gui.h
  83. +18 βˆ’0 src/platform/windows/gui/help/about.cpp
  84. +12 βˆ’0 src/platform/windows/gui/help/about.h
  85. +1 βˆ’1 src/platform/windows/gui/options/{memory_card β†’ }/memory_card.cpp
  86. +1 βˆ’1 src/platform/windows/gui/options/{memory_card β†’ }/memory_card.h
  87. +3 βˆ’3 src/platform/windows/gui/{ β†’ options}/options.cpp
  88. 0 src/platform/windows/gui/{ β†’ options}/options.h
  89. +53 βˆ’0 src/platform/windows/gui/toasts.cpp
  90. +23 βˆ’0 src/platform/windows/gui/toasts.h
  91. +0 βˆ’28 src/platform/windows/gui/tools.cpp
  92. +0 βˆ’7 src/platform/windows/gui/tools.h
  93. +67 βˆ’229 src/platform/windows/main.cpp
  94. +1 βˆ’1 src/renderer/opengl/opengl.h
  95. +201 βˆ’0 src/state/state.cpp
  96. +24 βˆ’0 src/state/state.h
  97. +21 βˆ’19 src/system.cpp
  98. +24 βˆ’5 src/system.h
  99. +167 βˆ’0 src/system_tools.cpp
  100. +14 βˆ’0 src/system_tools.h
  101. +7 βˆ’0 src/utils/event.h
@@ -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)
@@ -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
@@ -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
@@ -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.

@@ -0,0 +1,3 @@
*

!.gitignore
Submodule cereal added at 51cbda
@@ -9,7 +9,7 @@ require "./premake/androidmk"

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

ndkstl "c++_static"
ndkplatform "android-24"
@@ -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++"
@@ -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"
@@ -146,6 +149,7 @@ project "core"
"externals/EventBus/lib/include",
"externals/magic_enum/include",
"externals/fmt/include",
"externals/cereal/include",
}

files {
@@ -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 {
@@ -252,7 +257,7 @@ project "avocado"


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

links {
"core"
}
}
14 src/config.cpp 100644 β†’ 100755
@@ -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", {
@@ -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() {
@@ -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);
}
};
@@ -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 {
@@ -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;

@@ -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
@@ -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 {
@@ -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;
@@ -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;
}
}

0 comments on commit e3ce3f8

Please sign in to comment.
You can’t perform that action at this time.