gambatte: eliminate some unused code

This commit is contained in:
goyuken 2014-05-11 15:40:02 +00:00
parent 467a8f37eb
commit 5710282ac6
11 changed files with 0 additions and 664 deletions

View File

@ -438,38 +438,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
throw new Exception("gambatte_newstateload() returned false");
}
/// <summary>
/// handles the core-portion of savestating
/// </summary>
/// <returns>private binary data corresponding to a savestate</returns>
byte[] SaveCoreBinary()
{
uint nlen = 0;
IntPtr ndata = IntPtr.Zero;
if (!LibGambatte.gambatte_savestate(GambatteState, ref ndata, ref nlen))
throw new Exception("Gambatte failed to save the savestate!");
if (nlen == 0)
throw new Exception("Gambatte returned a 0-length savestate?");
byte[] data = new byte[nlen];
System.Runtime.InteropServices.Marshal.Copy(ndata, data, 0, (int)nlen);
LibGambatte.gambatte_savestate_destroy(ndata);
return data;
}
/// <summary>
/// handles the core portion of loadstating
/// </summary>
/// <param name="data">private binary data previously returned from SaveCoreBinary()</param>
void LoadCoreBinary(byte[] data)
{
if (!LibGambatte.gambatte_loadstate(GambatteState, data, (uint)data.Length))
throw new Exception("Gambatte failed to load the savestate!");
}
public void SaveStateText(System.IO.TextWriter writer)
{
var temp = SaveStateBinary();

View File

@ -271,33 +271,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_savesavedatalength(IntPtr core);
/// <summary>
/// Saves emulator state to a byte array
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="data">private savestate data returned by the core</param>
/// <param name="len">the length of the data in bytes</param>
/// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_savestate(IntPtr core, ref IntPtr data, ref uint len);
/// <summary>
/// destroy data returned by gambatte_savestate() to avoid memory leaks
/// </summary>
/// <param name="data">pointer from gambatte_savestate()</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_savestate_destroy(IntPtr data);
/// <summary>
/// Loads emulator state from a byte array
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="data">savestate data</param>
/// <param name="len">length of the savestate data in bytes</param>
/// <returns>success</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gambatte_loadstate(IntPtr core, byte[] data, uint len);
/// <summary>
/// new savestate method
/// </summary>

View File

@ -107,19 +107,6 @@ public:
// 0 = vram, 1 = rom, 2 = wram, 3 = cartram, 4 = oam, 5 = hram
bool getMemoryArea(int which, unsigned char **data, int *length);
/** Saves emulator state to the file given by 'filepath'.
*
* @param videoBuf 160x144 RGB32 (native endian) video frame buffer or 0. Used for saving a thumbnail.
* @param pitch distance in number of pixels (not bytes) from the start of one line to the next in videoBuf.
* @return success
*/
bool saveState(std::ostream &file);
/** Loads emulator state from the file given by 'filepath'.
* @return success
*/
bool loadState(std::istream &file);
/** ROM header title of currently loaded ROM image. */
const std::string romTitle() const;

View File

@ -115,7 +115,6 @@
<ClInclude Include="src\sound\master_disabler.h" />
<ClInclude Include="src\sound\sound_unit.h" />
<ClInclude Include="src\sound\static_output_tester.h" />
<ClInclude Include="src\statesaver.h" />
<ClInclude Include="src\tima.h" />
<ClInclude Include="src\video.h" />
<ClInclude Include="src\video\lyc_irq.h" />
@ -144,7 +143,6 @@
<ClCompile Include="src\sound\duty_unit.cpp" />
<ClCompile Include="src\sound\envelope_unit.cpp" />
<ClCompile Include="src\sound\length_counter.cpp" />
<ClCompile Include="src\statesaver.cpp" />
<ClCompile Include="src\tima.cpp" />
<ClCompile Include="src\video.cpp" />
<ClCompile Include="src\video\lyc_irq.cpp" />

View File

@ -21,9 +21,6 @@
<ClInclude Include="include\gambatte.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\statesaver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\video.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -140,9 +137,6 @@
<ClCompile Include="src\gambatte.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\statesaver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\video.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -144,36 +144,6 @@ GBEXPORT int gambatte_savesavedatalength(void *core)
return g->saveSavedataLength();
}
GBEXPORT int gambatte_savestate(void *core, char **data, unsigned *len)
{
GB *g = (GB *) core;
std::ostringstream os = std::ostringstream(std::ios_base::binary | std::ios_base::out);
if (!g->saveState(os))
return 0;
os.flush();
std::string s = os.str();
char *ret = (char *) std::malloc(s.length());
std::memcpy(ret, s.data(), s.length());
*len = s.length();
*data = ret;
return 1;
}
GBEXPORT void gambatte_savestate_destroy(char *data)
{
std::free(data);
}
GBEXPORT int gambatte_loadstate(void *core, const char *data, unsigned len)
{
GB *g = (GB *) core;
// msvc allows using an Rvalue directly where an Lvalue is need, which is kind of cool and sort of makes sense, but no
std::istringstream iss(std::string(data, len), std::ios_base::binary | std::ios_base::in);
return g->loadState(iss);
}
GBEXPORT long gambatte_newstatelen(void *core)
{
GB *g = (GB *) core;

View File

@ -19,7 +19,6 @@
#include "gambatte.h"
#include "cpu.h"
#include "savestate.h"
#include "statesaver.h"
#include "initstate.h"
#include <sstream>
#include <cstring>
@ -195,37 +194,6 @@ void GB::setCgbPalette(unsigned *lut) {
p_->cpu.setCgbPalette(lut);
}
bool GB::loadState(std::istream &file) {
if (p_->cpu.loaded()) {
// p_->cpu.saveSavedata();
SaveState state;
p_->cpu.setStatePtrs(state);
if (StateSaver::loadState(state, file)) {
p_->cpu.loadState(state);
file.read((char *)p_->vbuff, 160 * 144 * 4); // yes, sloppy
return true;
}
}
return false;
}
bool GB::saveState(std::ostream &file) {
if (p_->cpu.loaded()) {
SaveState state;
p_->cpu.setStatePtrs(state);
p_->cpu.saveState(state);
bool ret = StateSaver::saveState(state, file);
if (ret)
file.write((const char *)p_->vbuff, 160 * 144 * 4); // yes, sloppy
return ret;
}
return false;
}
const std::string GB::romTitle() const {
if (p_->cpu.loaded()) {
char title[0x11];

Binary file not shown.

View File

@ -1,478 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "statesaver.h"
#include "savestate.h"
#include "array.h"
#include <vector>
#include <cstring>
#include <algorithm>
#include <ostream>
#include <istream>
namespace {
using namespace gambatte;
enum AsciiChar {
NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US,
SP, XCL, QOT, HSH, DLR, PRC, AMP, APO, LPA, RPA, AST, PLU, COM, HYP, STP, DIV,
NO0, NO1, NO2, NO3, NO4, NO5, NO6, NO7, NO8, NO9, CLN, SCL, LT, EQL, GT, QTN,
AT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O,
P, Q, R, S, T, U, V, W, X, Y, Z, LBX, BSL, RBX, CAT, UND,
ACN, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o,
p, q, r, s, t, u, v, w, x, y, z, LBR, BAR, RBR, TLD, DEL
};
struct Saver {
const char *label;
void (*save)(std::ostream &file, const SaveState &state);
void (*load)(std::istream &file, SaveState &state);
unsigned char labelsize;
};
static inline bool operator<(const Saver &l, const Saver &r) {
return std::strcmp(l.label, r.label) < 0;
}
static void put24(std::ostream &file, const unsigned long data) {
file.put(data >> 16 & 0xFF);
file.put(data >> 8 & 0xFF);
file.put(data & 0xFF);
}
static void put32(std::ostream &file, const unsigned long data) {
file.put(data >> 24 & 0xFF);
file.put(data >> 16 & 0xFF);
file.put(data >> 8 & 0xFF);
file.put(data & 0xFF);
}
static void write(std::ostream &file, const unsigned char data) {
static const char inf[] = { 0x00, 0x00, 0x01 };
file.write(inf, sizeof(inf));
file.put(data & 0xFF);
}
static void write(std::ostream &file, const unsigned short data) {
static const char inf[] = { 0x00, 0x00, 0x02 };
file.write(inf, sizeof(inf));
file.put(data >> 8 & 0xFF);
file.put(data & 0xFF);
}
static void write(std::ostream &file, const unsigned long data) {
static const char inf[] = { 0x00, 0x00, 0x04 };
file.write(inf, sizeof(inf));
put32(file, data);
}
static inline void write(std::ostream &file, const bool data) {
write(file, static_cast<unsigned char>(data));
}
static void write(std::ostream &file, const unsigned char *data, const unsigned long sz) {
put24(file, sz);
file.write(reinterpret_cast<const char*>(data), sz);
}
static void write(std::ostream &file, const bool *data, const unsigned long sz) {
put24(file, sz);
for (unsigned long i = 0; i < sz; ++i)
file.put(data[i]);
}
static unsigned long get24(std::istream &file) {
unsigned long tmp = file.get() & 0xFF;
tmp = tmp << 8 | (file.get() & 0xFF);
return tmp << 8 | (file.get() & 0xFF);
}
static unsigned long read(std::istream &file) {
unsigned long size = get24(file);
if (size > 4) {
file.ignore(size - 4);
size = 4;
}
unsigned long out = 0;
switch (size) {
case 4: out = (out | (file.get() & 0xFF)) << 8;
case 3: out = (out | (file.get() & 0xFF)) << 8;
case 2: out = (out | (file.get() & 0xFF)) << 8;
case 1: out = out | (file.get() & 0xFF);
}
return out;
}
static inline void read(std::istream &file, unsigned char &data) {
data = read(file) & 0xFF;
}
static inline void read(std::istream &file, unsigned short &data) {
data = read(file) & 0xFFFF;
}
static inline void read(std::istream &file, unsigned long &data) {
data = read(file);
}
static inline void read(std::istream &file, bool &data) {
data = read(file);
}
static void read(std::istream &file, unsigned char *data, unsigned long sz) {
const unsigned long size = get24(file);
if (size < sz)
sz = size;
file.read(reinterpret_cast<char*>(data), sz);
file.ignore(size - sz);
if (static_cast<unsigned char>(0x100)) {
for (unsigned long i = 0; i < sz; ++i)
data[i] &= 0xFF;
}
}
static void read(std::istream &file, bool *data, unsigned long sz) {
const unsigned long size = get24(file);
if (size < sz)
sz = size;
for (unsigned long i = 0; i < sz; ++i)
data[i] = file.get();
file.ignore(size - sz);
}
} // anon namespace
namespace gambatte {
class SaverList {
public:
typedef std::vector<Saver> list_t;
typedef list_t::const_iterator const_iterator;
private:
list_t list;
unsigned char maxLabelsize_;
public:
SaverList();
const_iterator begin() const { return list.begin(); }
const_iterator end() const { return list.end(); }
unsigned maxLabelsize() const { return maxLabelsize_; }
};
static void pushSaver(SaverList::list_t &list, const char *label,
void (*save)(std::ostream &file, const SaveState &state),
void (*load)(std::istream &file, SaveState &state), unsigned labelsize) {
const Saver saver = { label, save, load, labelsize };
list.push_back(saver);
}
SaverList::SaverList() {
#define ADD(arg) do { \
struct Func { \
static void save(std::ostream &file, const SaveState &state) { write(file, state.arg); } \
static void load(std::istream &file, SaveState &state) { read(file, state.arg); } \
}; \
\
pushSaver(list, label, Func::save, Func::load, sizeof label); \
} while (0)
#define ADDPTR(arg) do { \
struct Func { \
static void save(std::ostream &file, const SaveState &state) { write(file, state.arg.get(), state.arg.getSz()); } \
static void load(std::istream &file, SaveState &state) { read(file, state.arg.ptr, state.arg.getSz()); } \
}; \
\
pushSaver(list, label, Func::save, Func::load, sizeof label); \
} while (0)
#define ADDARRAY(arg) do { \
struct Func { \
static void save(std::ostream &file, const SaveState &state) { write(file, state.arg, sizeof(state.arg)); } \
static void load(std::istream &file, SaveState &state) { read(file, state.arg, sizeof(state.arg)); } \
}; \
\
pushSaver(list, label, Func::save, Func::load, sizeof label); \
} while (0)
{ static const char label[] = { c,c, NUL }; ADD(cpu.cycleCounter); }
{ static const char label[] = { p,c, NUL }; ADD(cpu.PC); }
{ static const char label[] = { s,p, NUL }; ADD(cpu.SP); }
{ static const char label[] = { a, NUL }; ADD(cpu.A); }
{ static const char label[] = { b, NUL }; ADD(cpu.B); }
{ static const char label[] = { c, NUL }; ADD(cpu.C); }
{ static const char label[] = { d, NUL }; ADD(cpu.D); }
{ static const char label[] = { e, NUL }; ADD(cpu.E); }
{ static const char label[] = { f, NUL }; ADD(cpu.F); }
{ static const char label[] = { h, NUL }; ADD(cpu.H); }
{ static const char label[] = { l, NUL }; ADD(cpu.L); }
{ static const char label[] = { s,k,i,p, NUL }; ADD(cpu.skip); }
{ static const char label[] = { h,a,l,t, NUL }; ADD(mem.halted); }
{ static const char label[] = { v,r,a,m, NUL }; ADDPTR(mem.vram); }
{ static const char label[] = { s,r,a,m, NUL }; ADDPTR(mem.sram); }
{ static const char label[] = { w,r,a,m, NUL }; ADDPTR(mem.wram); }
{ static const char label[] = { h,r,a,m, NUL }; ADDPTR(mem.ioamhram); }
{ static const char label[] = { l,d,i,v,u,p, NUL }; ADD(mem.divLastUpdate); }
{ static const char label[] = { l,t,i,m,a,u,p, NUL }; ADD(mem.timaLastUpdate); }
{ static const char label[] = { t,m,a,t,i,m,e, NUL }; ADD(mem.tmatime); }
{ static const char label[] = { s,e,r,i,a,l,t, NUL }; ADD(mem.nextSerialtime); }
{ static const char label[] = { l,o,d,m,a,u,p, NUL }; ADD(mem.lastOamDmaUpdate); }
{ static const char label[] = { m,i,n,i,n,t,t, NUL }; ADD(mem.minIntTime); }
{ static const char label[] = { u,n,h,a,l,t,t, NUL }; ADD(mem.unhaltTime); }
{ static const char label[] = { r,o,m,b,a,n,k, NUL }; ADD(mem.rombank); }
{ static const char label[] = { d,m,a,s,r,c, NUL }; ADD(mem.dmaSource); }
{ static const char label[] = { d,m,a,d,s,t, NUL }; ADD(mem.dmaDestination); }
{ static const char label[] = { r,a,m,b,a,n,k, NUL }; ADD(mem.rambank); }
{ static const char label[] = { o,d,m,a,p,o,s, NUL }; ADD(mem.oamDmaPos); }
{ static const char label[] = { i,m,e, NUL }; ADD(mem.IME); }
{ static const char label[] = { s,r,a,m,o,n, NUL }; ADD(mem.enableRam); }
{ static const char label[] = { r,a,m,b,m,o,d, NUL }; ADD(mem.rambankMode); }
{ static const char label[] = { h,d,m,a, NUL }; ADD(mem.hdmaTransfer); }
{ static const char label[] = { b,g,p, NUL }; ADDPTR(ppu.bgpData); }
{ static const char label[] = { o,b,j,p, NUL }; ADDPTR(ppu.objpData); }
{ static const char label[] = { s,p,o,s,b,u,f, NUL }; ADDPTR(ppu.oamReaderBuf); }
{ static const char label[] = { s,p,s,z,b,u,f, NUL }; ADDPTR(ppu.oamReaderSzbuf); }
{ static const char label[] = { s,p,a,t,t,r, NUL }; ADDARRAY(ppu.spAttribList); }
{ static const char label[] = { s,p,b,y,t,e,NO0, NUL }; ADDARRAY(ppu.spByte0List); }
{ static const char label[] = { s,p,b,y,t,e,NO1, NUL }; ADDARRAY(ppu.spByte1List); }
{ static const char label[] = { v,c,y,c,l,e,s, NUL }; ADD(ppu.videoCycles); }
{ static const char label[] = { e,d,M,NO0,t,i,m, NUL }; ADD(ppu.enableDisplayM0Time); }
{ static const char label[] = { m,NO0,t,i,m,e, NUL }; ADD(ppu.lastM0Time); }
{ static const char label[] = { n,m,NO0,i,r,q, NUL }; ADD(ppu.nextM0Irq); }
{ static const char label[] = { b,g,t,w, NUL }; ADD(ppu.tileword); }
{ static const char label[] = { b,g,n,t,w, NUL }; ADD(ppu.ntileword); }
{ static const char label[] = { w,i,n,y,p,o,s, NUL }; ADD(ppu.winYPos); }
{ static const char label[] = { x,p,o,s, NUL }; ADD(ppu.xpos); }
{ static const char label[] = { e,n,d,x, NUL }; ADD(ppu.endx); }
{ static const char label[] = { p,p,u,r,NO0, NUL }; ADD(ppu.reg0); }
{ static const char label[] = { p,p,u,r,NO1, NUL }; ADD(ppu.reg1); }
{ static const char label[] = { b,g,a,t,r,b, NUL }; ADD(ppu.attrib); }
{ static const char label[] = { b,g,n,a,t,r,b, NUL }; ADD(ppu.nattrib); }
{ static const char label[] = { p,p,u,s,t,a,t, NUL }; ADD(ppu.state); }
{ static const char label[] = { n,s,p,r,i,t,e, NUL }; ADD(ppu.nextSprite); }
{ static const char label[] = { c,s,p,r,i,t,e, NUL }; ADD(ppu.currentSprite); }
{ static const char label[] = { l,y,c, NUL }; ADD(ppu.lyc); }
{ static const char label[] = { m,NO0,l,y,c, NUL }; ADD(ppu.m0lyc); }
{ static const char label[] = { o,l,d,w,y, NUL }; ADD(ppu.oldWy); }
{ static const char label[] = { w,i,n,d,r,a,w, NUL }; ADD(ppu.winDrawState); }
{ static const char label[] = { w,s,c,x, NUL }; ADD(ppu.wscx); }
{ static const char label[] = { w,e,m,a,s,t,r, NUL }; ADD(ppu.weMaster); }
{ static const char label[] = { l,c,d,s,i,r,q, NUL }; ADD(ppu.pendingLcdstatIrq); }
{ static const char label[] = { s,p,u,c,n,t,r, NUL }; ADD(spu.cycleCounter); }
{ static const char label[] = { s,w,p,c,n,t,r, NUL }; ADD(spu.ch1.sweep.counter); }
{ static const char label[] = { s,w,p,s,h,d,w, NUL }; ADD(spu.ch1.sweep.shadow); }
{ static const char label[] = { s,w,p,n,e,g, NUL }; ADD(spu.ch1.sweep.negging); }
{ static const char label[] = { d,u,t,NO1,c,t,r, NUL }; ADD(spu.ch1.duty.nextPosUpdate); }
{ static const char label[] = { d,u,t,NO1,p,o,s, NUL }; ADD(spu.ch1.duty.pos); }
{ static const char label[] = { e,n,v,NO1,c,t,r, NUL }; ADD(spu.ch1.env.counter); }
{ static const char label[] = { e,n,v,NO1,v,o,l, NUL }; ADD(spu.ch1.env.volume); }
{ static const char label[] = { l,e,n,NO1,c,t,r, NUL }; ADD(spu.ch1.lcounter.counter); }
{ static const char label[] = { l,e,n,NO1,v,a,l, NUL }; ADD(spu.ch1.lcounter.lengthCounter); }
{ static const char label[] = { n,r,NO1,NO0, NUL }; ADD(spu.ch1.sweep.nr0); }
{ static const char label[] = { n,r,NO1,NO3, NUL }; ADD(spu.ch1.duty.nr3); }
{ static const char label[] = { n,r,NO1,NO4, NUL }; ADD(spu.ch1.nr4); }
{ static const char label[] = { c,NO1,m,a,s,t,r, NUL }; ADD(spu.ch1.master); }
{ static const char label[] = { d,u,t,NO2,c,t,r, NUL }; ADD(spu.ch2.duty.nextPosUpdate); }
{ static const char label[] = { d,u,t,NO2,p,o,s, NUL }; ADD(spu.ch2.duty.pos); }
{ static const char label[] = { e,n,v,NO2,c,t,r, NUL }; ADD(spu.ch2.env.counter); }
{ static const char label[] = { e,n,v,NO2,v,o,l, NUL }; ADD(spu.ch2.env.volume); }
{ static const char label[] = { l,e,n,NO2,c,t,r, NUL }; ADD(spu.ch2.lcounter.counter); }
{ static const char label[] = { l,e,n,NO2,v,a,l, NUL }; ADD(spu.ch2.lcounter.lengthCounter); }
{ static const char label[] = { n,r,NO2,NO3, NUL }; ADD(spu.ch2.duty.nr3); }
{ static const char label[] = { n,r,NO2,NO4, NUL }; ADD(spu.ch2.nr4); }
{ static const char label[] = { c,NO2,m,a,s,t,r, NUL }; ADD(spu.ch2.master); }
{ static const char label[] = { w,a,v,e,r,a,m, NUL }; ADDPTR(spu.ch3.waveRam); }
{ static const char label[] = { l,e,n,NO3,c,t,r, NUL }; ADD(spu.ch3.lcounter.counter); }
{ static const char label[] = { l,e,n,NO3,v,a,l, NUL }; ADD(spu.ch3.lcounter.lengthCounter); }
{ static const char label[] = { w,a,v,e,c,t,r, NUL }; ADD(spu.ch3.waveCounter); }
{ static const char label[] = { l,w,a,v,r,d,t, NUL }; ADD(spu.ch3.lastReadTime); }
{ static const char label[] = { w,a,v,e,p,o,s, NUL }; ADD(spu.ch3.wavePos); }
{ static const char label[] = { w,a,v,s,m,p,l, NUL }; ADD(spu.ch3.sampleBuf); }
{ static const char label[] = { n,r,NO3,NO3, NUL }; ADD(spu.ch3.nr3); }
{ static const char label[] = { n,r,NO3,NO4, NUL }; ADD(spu.ch3.nr4); }
{ static const char label[] = { c,NO3,m,a,s,t,r, NUL }; ADD(spu.ch3.master); }
{ static const char label[] = { l,f,s,r,c,t,r, NUL }; ADD(spu.ch4.lfsr.counter); }
{ static const char label[] = { l,f,s,r,r,e,g, NUL }; ADD(spu.ch4.lfsr.reg); }
{ static const char label[] = { e,n,v,NO4,c,t,r, NUL }; ADD(spu.ch4.env.counter); }
{ static const char label[] = { e,n,v,NO4,v,o,l, NUL }; ADD(spu.ch4.env.volume); }
{ static const char label[] = { l,e,n,NO4,c,t,r, NUL }; ADD(spu.ch4.lcounter.counter); }
{ static const char label[] = { l,e,n,NO4,v,a,l, NUL }; ADD(spu.ch4.lcounter.lengthCounter); }
{ static const char label[] = { n,r,NO4,NO4, NUL }; ADD(spu.ch4.nr4); }
{ static const char label[] = { c,NO4,m,a,s,t,r, NUL }; ADD(spu.ch4.master); }
{ static const char label[] = { r,t,c,b,a,s,e, NUL }; ADD(rtc.baseTime); }
{ static const char label[] = { r,t,c,h,a,l,t, NUL }; ADD(rtc.haltTime); }
{ static const char label[] = { r,t,c,d,h, NUL }; ADD(rtc.dataDh); }
{ static const char label[] = { r,t,c,d,l, NUL }; ADD(rtc.dataDl); }
{ static const char label[] = { r,t,c,h, NUL }; ADD(rtc.dataH); }
{ static const char label[] = { r,t,c,m, NUL }; ADD(rtc.dataM); }
{ static const char label[] = { r,t,c,s, NUL }; ADD(rtc.dataS); }
{ static const char label[] = { r,t,c,l,l,d, NUL }; ADD(rtc.lastLatchData); }
#undef ADD
#undef ADDPTR
#undef ADDARRAY
list.resize(list.size());
std::sort(list.begin(), list.end());
maxLabelsize_ = 0;
for (std::size_t i = 0; i < list.size(); ++i) {
if (list[i].labelsize > maxLabelsize_)
maxLabelsize_ = list[i].labelsize;
}
}
}
namespace {
struct PxlSum { unsigned long rb, g; };
static void addPxlPairs(PxlSum *const sum, const uint_least32_t *const p) {
sum[0].rb += (p[0] & 0xFF00FF) + (p[3] & 0xFF00FF);
sum[0].g += (p[0] & 0x00FF00) + (p[3] & 0x00FF00);
sum[1].rb += (p[1] & 0xFF00FF) + (p[2] & 0xFF00FF);
sum[1].g += (p[1] & 0x00FF00) + (p[2] & 0x00FF00);
}
static void blendPxlPairs(PxlSum *const dst, const PxlSum *const sums) {
dst->rb = sums[1].rb * 8 + (sums[0].rb - sums[1].rb) * 3;
dst->g = sums[1].g * 8 + (sums[0].g - sums[1].g ) * 3;
}
static void writeSnapShot(std::ostream &file, const uint_least32_t *pixels, const int pitch) {
put24(file, pixels ? StateSaver::SS_WIDTH * StateSaver::SS_HEIGHT * sizeof(uint_least32_t) : 0);
if (pixels) {
uint_least32_t buf[StateSaver::SS_WIDTH];
for (unsigned h = StateSaver::SS_HEIGHT; h--;) {
for (unsigned x = 0; x < StateSaver::SS_WIDTH; ++x) {
const uint_least32_t *const p = pixels + x * StateSaver::SS_DIV;
PxlSum pxlsum[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
addPxlPairs(pxlsum , p );
addPxlPairs(pxlsum + 2, p + pitch );
addPxlPairs(pxlsum + 2, p + pitch * 2);
addPxlPairs(pxlsum , p + pitch * 3);
blendPxlPairs(pxlsum , pxlsum );
blendPxlPairs(pxlsum + 1, pxlsum + 2);
blendPxlPairs(pxlsum , pxlsum );
buf[x] = ((pxlsum[0].rb & 0xFF00FF00U) | (pxlsum[0].g & 0x00FF0000U)) >> 8;
}
file.write(reinterpret_cast<const char*>(buf), sizeof(buf));
pixels += pitch * StateSaver::SS_DIV;
}
}
}
static SaverList list;
} // anon namespace
namespace gambatte {
bool StateSaver::saveState(const SaveState &state, std::ostream &file) {
//std::ostream file(filename.c_str(), std::ios_base::binary);
if (file.fail())
return false;
//{ static const char ver[] = { 0, 1 }; file.write(ver, sizeof(ver)); }
// bump version as the screenshot is being removed
{ static const char ver[] = { 0, 2 }; file.write(ver, sizeof(ver)); }
//writeSnapShot(file, videoBuf, pitch);
for (SaverList::const_iterator it = list.begin(); it != list.end(); ++it) {
file.write(it->label, it->labelsize);
(*it->save)(file, state);
}
return !file.fail();
}
bool StateSaver::loadState(SaveState &state, std::istream &file) {
//std::istream file(filename.c_str(), std::ios_base::binary);
if (file.fail() || file.get() != 0)
return false;
int minor = file.get();
if (minor == 1) { // skip over screenshot
file.ignore();
file.ignore(get24(file));
}
else if (minor == 2) { // no screenshot
}
else
return false;
const Array<char> labelbuf(list.maxLabelsize());
const Saver labelbufSaver = { labelbuf, 0, 0, list.maxLabelsize() };
SaverList::const_iterator done = list.begin();
while (file.good() && done != list.end()) {
file.getline(labelbuf, list.maxLabelsize(), NUL);
SaverList::const_iterator it = done;
if (std::strcmp(labelbuf, it->label)) {
it = std::lower_bound(it + 1, list.end(), labelbufSaver);
if (it == list.end() || std::strcmp(labelbuf, it->label)) {
file.ignore(get24(file));
continue;
}
} else
++done;
(*it->load)(file, state);
}
state.cpu.cycleCounter &= 0x7FFFFFFF;
state.spu.cycleCounter &= 0x7FFFFFFF;
return true;
}
}

View File

@ -1,44 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef STATESAVER_H
#define STATESAVER_H
#include "gbint.h"
#include <string>
namespace gambatte {
struct SaveState;
class StateSaver {
StateSaver();
public:
enum { SS_SHIFT = 2 };
enum { SS_DIV = 1 << 2 };
enum { SS_WIDTH = 160 >> SS_SHIFT };
enum { SS_HEIGHT = 144 >> SS_SHIFT };
static bool saveState(const SaveState &state, std::ostream &file);
static bool loadState(SaveState &state, std::istream &file);
};
}
#endif

Binary file not shown.