diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index 53d5050542..b4f13e3f90 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -438,38 +438,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy throw new Exception("gambatte_newstateload() returned false"); } - /// - /// handles the core-portion of savestating - /// - /// private binary data corresponding to a savestate - 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; - } - - /// - /// handles the core portion of loadstating - /// - /// private binary data previously returned from SaveCoreBinary() - 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(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs index 0412969116..78302aee1f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -271,33 +271,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int gambatte_savesavedatalength(IntPtr core); - /// - /// Saves emulator state to a byte array - /// - /// opaque state pointer - /// private savestate data returned by the core - /// the length of the data in bytes - /// success - [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool gambatte_savestate(IntPtr core, ref IntPtr data, ref uint len); - - /// - /// destroy data returned by gambatte_savestate() to avoid memory leaks - /// - /// pointer from gambatte_savestate() - [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void gambatte_savestate_destroy(IntPtr data); - - /// - /// Loads emulator state from a byte array - /// - /// opaque state pointer - /// savestate data - /// length of the savestate data in bytes - /// success - [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool gambatte_loadstate(IntPtr core, byte[] data, uint len); - /// /// new savestate method /// diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index 1aaea2333d..8652739799 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -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; diff --git a/libgambatte/libgambatte.vcxproj b/libgambatte/libgambatte.vcxproj index f87ce0bcba..434d1c23c3 100644 --- a/libgambatte/libgambatte.vcxproj +++ b/libgambatte/libgambatte.vcxproj @@ -115,7 +115,6 @@ - @@ -144,7 +143,6 @@ - diff --git a/libgambatte/libgambatte.vcxproj.filters b/libgambatte/libgambatte.vcxproj.filters index 52ac8d5a4d..5571702c18 100644 --- a/libgambatte/libgambatte.vcxproj.filters +++ b/libgambatte/libgambatte.vcxproj.filters @@ -21,9 +21,6 @@ Header Files - - Header Files - Header Files @@ -140,9 +137,6 @@ Source Files - - Source Files - Source Files diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index 8df32e33fb..f5c0987a29 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -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; diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 46b3973c92..7fbe2c8647 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -19,7 +19,6 @@ #include "gambatte.h" #include "cpu.h" #include "savestate.h" -#include "statesaver.h" #include "initstate.h" #include #include @@ -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]; diff --git a/libgambatte/src/initstate.h b/libgambatte/src/initstate.h index aa33d90a91..8d8ed5aaf6 100644 Binary files a/libgambatte/src/initstate.h and b/libgambatte/src/initstate.h differ diff --git a/libgambatte/src/statesaver.cpp b/libgambatte/src/statesaver.cpp deleted file mode 100644 index d8c3131a13..0000000000 --- a/libgambatte/src/statesaver.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include - -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(data)); -} - -static void write(std::ostream &file, const unsigned char *data, const unsigned long sz) { - put24(file, sz); - file.write(reinterpret_cast(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(data), sz); - file.ignore(size - sz); - - if (static_cast(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 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(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 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; -} - -} diff --git a/libgambatte/src/statesaver.h b/libgambatte/src/statesaver.h deleted file mode 100644 index 46f2817603..0000000000 --- a/libgambatte/src/statesaver.h +++ /dev/null @@ -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 - -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 diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index 30a1066e82..f9e2cf48cf 100644 Binary files a/output/dll/libgambatte.dll and b/output/dll/libgambatte.dll differ