Fix savestate-related bugs
- Properly save and restore the framebuffer. Avoids display glitches one frame after loading. - Save and restore the base class of channel 4 LFSR (to avoid desyncs).
This commit is contained in:
parent
c10621e3b3
commit
03554f8722
2 changed files with 23 additions and 19 deletions
|
@ -1,4 +1,4 @@
|
||||||
From 58e7bcf988a64733c22337e21b74b31d2de7b64b Mon Sep 17 00:00:00 2001
|
From 0c061244bc907dc3f3202f62b771759105825b1f Mon Sep 17 00:00:00 2001
|
||||||
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
|
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
|
||||||
Date: Thu, 12 Jul 2012 20:49:57 +0300
|
Date: Thu, 12 Jul 2012 20:49:57 +0300
|
||||||
Subject: [PATCH] Changes to make libgambatte rerecording-friendly
|
Subject: [PATCH] Changes to make libgambatte rerecording-friendly
|
||||||
|
@ -41,7 +41,7 @@ Subject: [PATCH] Changes to make libgambatte rerecording-friendly
|
||||||
libgambatte/src/sound/channel3.cpp | 41 +++-
|
libgambatte/src/sound/channel3.cpp | 41 +++-
|
||||||
libgambatte/src/sound/channel3.h | 27 ++-
|
libgambatte/src/sound/channel3.h | 27 ++-
|
||||||
libgambatte/src/sound/channel4.cpp | 59 ++++--
|
libgambatte/src/sound/channel4.cpp | 59 ++++--
|
||||||
libgambatte/src/sound/channel4.h | 39 +++--
|
libgambatte/src/sound/channel4.h | 40 +++--
|
||||||
libgambatte/src/sound/duty_unit.cpp | 34 +++-
|
libgambatte/src/sound/duty_unit.cpp | 34 +++-
|
||||||
libgambatte/src/sound/duty_unit.h | 29 ++-
|
libgambatte/src/sound/duty_unit.h | 29 ++-
|
||||||
libgambatte/src/sound/envelope_unit.cpp | 19 ++-
|
libgambatte/src/sound/envelope_unit.cpp | 19 ++-
|
||||||
|
@ -66,7 +66,7 @@ Subject: [PATCH] Changes to make libgambatte rerecording-friendly
|
||||||
libgambatte/src/video/ppu.h | 84 ++++++---
|
libgambatte/src/video/ppu.h | 84 ++++++---
|
||||||
libgambatte/src/video/sprite_mapper.cpp | 17 +-
|
libgambatte/src/video/sprite_mapper.cpp | 17 +-
|
||||||
libgambatte/src/video/sprite_mapper.h | 53 ++++--
|
libgambatte/src/video/sprite_mapper.h | 53 ++++--
|
||||||
62 files changed, 2150 insertions(+), 603 deletions(-)
|
62 files changed, 2151 insertions(+), 603 deletions(-)
|
||||||
create mode 100644 Makefile
|
create mode 100644 Makefile
|
||||||
create mode 100644 libgambatte/Makefile
|
create mode 100644 libgambatte/Makefile
|
||||||
create mode 100644 libgambatte/src/loadsave.cpp
|
create mode 100644 libgambatte/src/loadsave.cpp
|
||||||
|
@ -3504,7 +3504,7 @@ index 35c3c00..9d89db7 100644
|
||||||
+
|
+
|
||||||
}
|
}
|
||||||
diff --git a/libgambatte/src/sound/channel4.h b/libgambatte/src/sound/channel4.h
|
diff --git a/libgambatte/src/sound/channel4.h b/libgambatte/src/sound/channel4.h
|
||||||
index 00b0b5a..cb923b8 100644
|
index 00b0b5a..d52d9f7 100644
|
||||||
--- a/libgambatte/src/sound/channel4.h
|
--- a/libgambatte/src/sound/channel4.h
|
||||||
+++ b/libgambatte/src/sound/channel4.h
|
+++ b/libgambatte/src/sound/channel4.h
|
||||||
@@ -24,6 +24,11 @@
|
@@ -24,6 +24,11 @@
|
||||||
|
@ -3519,7 +3519,7 @@ index 00b0b5a..cb923b8 100644
|
||||||
|
|
||||||
namespace gambatte {
|
namespace gambatte {
|
||||||
|
|
||||||
@@ -31,26 +36,32 @@ struct SaveState;
|
@@ -31,26 +36,33 @@ struct SaveState;
|
||||||
|
|
||||||
class Channel4 {
|
class Channel4 {
|
||||||
class Lfsr : public SoundUnit {
|
class Lfsr : public SoundUnit {
|
||||||
|
@ -3552,6 +3552,7 @@ index 00b0b5a..cb923b8 100644
|
||||||
- void reviveCounter(unsigned long cc);
|
- void reviveCounter(unsigned long cc);
|
||||||
+ void reviveCounter(unsigned cc);
|
+ void reviveCounter(unsigned cc);
|
||||||
+ void loadOrSave(loadsave& state) {
|
+ void loadOrSave(loadsave& state) {
|
||||||
|
+ loadOrSave2(state);
|
||||||
+ state(backupCounter);
|
+ state(backupCounter);
|
||||||
+ state(reg);
|
+ state(reg);
|
||||||
+ state(nr3);
|
+ state(nr3);
|
||||||
|
@ -3560,7 +3561,7 @@ index 00b0b5a..cb923b8 100644
|
||||||
};
|
};
|
||||||
|
|
||||||
class Ch4MasterDisabler : public MasterDisabler {
|
class Ch4MasterDisabler : public MasterDisabler {
|
||||||
@@ -70,9 +81,9 @@ class Channel4 {
|
@@ -70,9 +82,9 @@ class Channel4 {
|
||||||
|
|
||||||
SoundUnit *nextEventUnit;
|
SoundUnit *nextEventUnit;
|
||||||
|
|
||||||
|
@ -3573,7 +3574,7 @@ index 00b0b5a..cb923b8 100644
|
||||||
|
|
||||||
unsigned char nr4;
|
unsigned char nr4;
|
||||||
bool master;
|
bool master;
|
||||||
@@ -86,15 +97,17 @@ public:
|
@@ -86,15 +98,17 @@ public:
|
||||||
void setNr3(unsigned data) { lfsr.nr3Change(data, cycleCounter); /*setEvent();*/ }
|
void setNr3(unsigned data) { lfsr.nr3Change(data, cycleCounter); /*setEvent();*/ }
|
||||||
void setNr4(unsigned data);
|
void setNr4(unsigned data);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "core/window.hpp"
|
#include "core/window.hpp"
|
||||||
#include "library/pixfmt-rgb32.hpp"
|
#include "library/pixfmt-rgb32.hpp"
|
||||||
#include "library/string.hpp"
|
#include "library/string.hpp"
|
||||||
|
#include "library/serialization.hpp"
|
||||||
#include "library/minmax.hpp"
|
#include "library/minmax.hpp"
|
||||||
#include "library/framebuffer.hpp"
|
#include "library/framebuffer.hpp"
|
||||||
#define HAVE_CSTDINT
|
#define HAVE_CSTDINT
|
||||||
|
@ -53,6 +54,7 @@ namespace
|
||||||
gambatte::GB* instance;
|
gambatte::GB* instance;
|
||||||
unsigned frame_overflow = 0;
|
unsigned frame_overflow = 0;
|
||||||
std::vector<unsigned char> romdata;
|
std::vector<unsigned char> romdata;
|
||||||
|
uint32_t primary_framebuffer[160*144];
|
||||||
|
|
||||||
time_t walltime_fn()
|
time_t walltime_fn()
|
||||||
{
|
{
|
||||||
|
@ -95,6 +97,7 @@ namespace
|
||||||
new(instance) gambatte::GB;
|
new(instance) gambatte::GB;
|
||||||
instance->setInputGetter(&getinput);
|
instance->setInputGetter(&getinput);
|
||||||
instance->set_walltime_fn(walltime_fn);
|
instance->set_walltime_fn(walltime_fn);
|
||||||
|
memset(primary_framebuffer, 0, sizeof(primary_framebuffer));
|
||||||
frame_overflow = 0;
|
frame_overflow = 0;
|
||||||
|
|
||||||
rtc_fixed = true;
|
rtc_fixed = true;
|
||||||
|
@ -296,13 +299,9 @@ void core_emulate_frame()
|
||||||
static uint32_t accumulator_r = 0;
|
static uint32_t accumulator_r = 0;
|
||||||
static unsigned accumulator_s = 0;
|
static unsigned accumulator_s = 0;
|
||||||
uint32_t samplebuffer[SAMPLES_PER_FRAME + 2064];
|
uint32_t samplebuffer[SAMPLES_PER_FRAME + 2064];
|
||||||
uint32_t videobuf[160*144];
|
|
||||||
static uint32_t old_videobuf[160*144];
|
|
||||||
while(true) {
|
while(true) {
|
||||||
unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
|
unsigned samples_emitted = SAMPLES_PER_FRAME - frame_overflow;
|
||||||
long ret = instance->runFor(videobuf, 160, samplebuffer, samples_emitted);
|
long ret = instance->runFor(primary_framebuffer, 160, samplebuffer, samples_emitted);
|
||||||
if(ret >= 0)
|
|
||||||
memcpy(old_videobuf, videobuf, sizeof(old_videobuf));
|
|
||||||
for(unsigned i = 0; i < samples_emitted; i++) {
|
for(unsigned i = 0; i < samples_emitted; i++) {
|
||||||
uint32_t l = (int32_t)(int16_t)(samplebuffer[i]) + 32768;
|
uint32_t l = (int32_t)(int16_t)(samplebuffer[i]) + 32768;
|
||||||
uint32_t r = (int32_t)(int16_t)(samplebuffer[i] >> 16) + 32768;
|
uint32_t r = (int32_t)(int16_t)(samplebuffer[i] >> 16) + 32768;
|
||||||
|
@ -327,7 +326,7 @@ void core_emulate_frame()
|
||||||
}
|
}
|
||||||
framebuffer_info inf;
|
framebuffer_info inf;
|
||||||
inf.type = &_pixel_format_rgb32;
|
inf.type = &_pixel_format_rgb32;
|
||||||
inf.mem = const_cast<char*>(reinterpret_cast<const char*>(old_videobuf));
|
inf.mem = const_cast<char*>(reinterpret_cast<const char*>(primary_framebuffer));
|
||||||
inf.physwidth = 160;
|
inf.physwidth = 160;
|
||||||
inf.physheight = 144;
|
inf.physheight = 144;
|
||||||
inf.physstride = 640;
|
inf.physstride = 640;
|
||||||
|
@ -458,23 +457,27 @@ function_ptr_command<> cmp_save2("do-cmp-save", "", "\n", []() throw(std::bad_al
|
||||||
void core_serialize(std::vector<char>& out)
|
void core_serialize(std::vector<char>& out)
|
||||||
{
|
{
|
||||||
instance->saveState(out);
|
instance->saveState(out);
|
||||||
|
size_t osize = out.size();
|
||||||
|
out.resize(osize + 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]));
|
||||||
|
for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
|
||||||
|
write32ube(&out[osize + 4 * i], primary_framebuffer[i]);
|
||||||
out.push_back(frame_overflow >> 8);
|
out.push_back(frame_overflow >> 8);
|
||||||
out.push_back(frame_overflow);
|
out.push_back(frame_overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_unserialize(const char* in, size_t insize)
|
void core_unserialize(const char* in, size_t insize)
|
||||||
{
|
{
|
||||||
|
size_t foffset = insize - 2 - 4 * sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]);
|
||||||
std::vector<char> tmp;
|
std::vector<char> tmp;
|
||||||
tmp.resize(insize - 2);
|
tmp.resize(foffset);
|
||||||
memcpy(&tmp[0], in, insize - 2);
|
memcpy(&tmp[0], in, foffset);
|
||||||
instance->loadState(tmp);
|
instance->loadState(tmp);
|
||||||
|
for(size_t i = 0; i < sizeof(primary_framebuffer) / sizeof(primary_framebuffer[0]); i++)
|
||||||
|
primary_framebuffer[i] = read32ube(&in[foffset + 4 * i]);
|
||||||
|
|
||||||
unsigned x1 = (unsigned char)in[insize - 2];
|
unsigned x1 = (unsigned char)in[insize - 2];
|
||||||
unsigned x2 = (unsigned char)in[insize - 1];
|
unsigned x2 = (unsigned char)in[insize - 1];
|
||||||
frame_overflow = x1 * 256 + x2;
|
frame_overflow = x1 * 256 + x2;
|
||||||
std::vector<char> cmpx;
|
|
||||||
core_serialize(cmpx);
|
|
||||||
if(cmpx.size() != insize || memcmp(&cmpx[0], in, insize))
|
|
||||||
throw std::runtime_error("Loading and resaving won't roundtrip");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
|
std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
|
||||||
|
|
Loading…
Add table
Reference in a new issue