From 8c8fc98d1988d524e398c9783497412e5567a255 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Mon, 19 Sep 2011 21:45:35 +0300 Subject: [PATCH] Fix rerecord counting This also fixes the off-by-one in rerecord count. --- generic/mainloop.cpp | 8 ++++++++ generic/moviedata.cpp | 1 + generic/moviefile.cpp | 29 +++++++------------------- generic/moviefile.hpp | 4 ++++ generic/rrdata.cpp | 48 ++++++++++++++++++++++++++++--------------- generic/rrdata.hpp | 15 ++++++++++++-- 6 files changed, 65 insertions(+), 40 deletions(-) diff --git a/generic/mainloop.cpp b/generic/mainloop.cpp index 072b772f..7ee178df 100644 --- a/generic/mainloop.cpp +++ b/generic/mainloop.cpp @@ -514,6 +514,14 @@ class my_interface : public SNES::Interface namespace { + function_ptr_command<> count_rerecords("count-rerecords", "Count rerecords", + "Syntax: count-rerecords\nCounts rerecords.\n", + []() throw(std::bad_alloc, std::runtime_error) { + std::vector tmp; + uint64_t x = rrdata::write(tmp); + messages << x << " rerecord(s)" << std::endl; + }); + function_ptr_command quit_emulator("quit-emulator", "Quit the emulator", "Syntax: quit-emulator [/y]\nQuits emulator (/y => don't ask for confirmation).\n", [](const std::string& args) throw(std::bad_alloc, std::runtime_error) { diff --git a/generic/moviedata.cpp b/generic/moviedata.cpp index 4db3f44b..7df60f45 100644 --- a/generic/moviedata.cpp +++ b/generic/moviedata.cpp @@ -210,6 +210,7 @@ void do_load_state(struct moviefile& _movie, int lmode) //Negative return. rrdata::read_base(_movie.projectid); + rrdata::read(_movie.c_rrdata); rrdata::add_internal(); try { our_rom->region = gtype::toromregion(_movie.gametype); diff --git a/generic/moviefile.cpp b/generic/moviefile.cpp index 4841f05b..87ea4782 100644 --- a/generic/moviefile.cpp +++ b/generic/moviefile.cpp @@ -99,18 +99,10 @@ void read_authors_file(zip_reader& r, std::vector& out) throw(std::bad_alloc, std::runtime_error) { - std::istream& m = r["rrdata"]; - uint64_t count; - try { - rrdata::read_base(projectid); - count = rrdata::read(m); - delete &m; - } catch(...) { - delete &m; - throw; - } + out = read_raw_file(r, "rrdata"); + uint64_t count = rrdata::count(out); std::ostringstream x; x << count; return x.str(); @@ -118,17 +110,10 @@ std::string read_rrdata(zip_reader& r, const std::string& projectid) throw(std:: void write_rrdata(zip_writer& w) throw(std::bad_alloc, std::runtime_error) { - std::ostream& m = w.create_file("rrdata"); uint64_t count; - try { - count = rrdata::write(m); - if(!m) - throw std::runtime_error("Can't write ZIP file member"); - w.close_file(); - } catch(...) { - w.close_file(); - throw; - } + std::vector out; + count = rrdata::write(out); + write_raw_file(w, "rrdata", out); std::ostream& m2 = w.create_file("rerecords"); try { m2 << count << std::endl; @@ -254,7 +239,7 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim port2 = port_type::lookup(tmp, true).ptype; read_linefile(r, "gamename", gamename, true); read_linefile(r, "projectid", projectid); - rerecords = read_rrdata(r, projectid); + rerecords = read_rrdata(r, c_rrdata); read_linefile(r, "coreversion", coreversion); read_linefile(r, "rom.sha256", rom_sha256, true); read_linefile(r, "romxml.sha256", romxml_sha256, true); diff --git a/generic/moviefile.hpp b/generic/moviefile.hpp index 8b814b59..5d200da6 100644 --- a/generic/moviefile.hpp +++ b/generic/moviefile.hpp @@ -128,6 +128,10 @@ struct moviefile * State of movie code (if is_savestate is true). */ std::vector movie_state; +/** + * Compressed rrdata. + */ + std::vector c_rrdata; /** * Input for each (sub)frame. */ diff --git a/generic/rrdata.cpp b/generic/rrdata.cpp index c9e2e5a8..c0cbf0c4 100644 --- a/generic/rrdata.cpp +++ b/generic/rrdata.cpp @@ -111,7 +111,7 @@ void rrdata::close() throw() void rrdata::add(const struct rrdata::instance& i) throw(std::bad_alloc) { - if(rrset.insert(i).second) { + if(rrset.insert(i).second && handle_open) { //std::cerr << "New symbol: " << i << std::endl; ohandle.write(reinterpret_cast(i.bytes), RRDATA_BYTES); ohandle.flush(); @@ -127,7 +127,7 @@ void rrdata::add_internal() throw(std::bad_alloc) namespace { - void flush_symbol(std::ostream& strm, const rrdata::instance& base, const rrdata::instance& predicted, + void flush_symbol(std::vector& strm, const rrdata::instance& base, const rrdata::instance& predicted, unsigned count) { char opcode; @@ -158,13 +158,15 @@ namespace buf2[1] = (count - bias) >> 8; buf2[2] = (count - bias); memcpy(buf1 + (RRDATA_BYTES - j + 1), buf2 + (3 - (opcode >> 5)), opcode >> 5); - strm.write(buf1, (RRDATA_BYTES - j + 1) + (opcode >> 5)); + for(size_t s = 0; s < (RRDATA_BYTES - j + 1) + (opcode >> 5); s++) + strm.push_back(buf1[s]); //std::cerr << "Encoding " << count << " symbols starting from " << base << std::endl; } } -uint64_t rrdata::write(std::ostream& strm) throw(std::bad_alloc) +uint64_t rrdata::write(std::vector& strm) throw(std::bad_alloc) { + strm.clear(); uint64_t count = 0; instance last_encode_end; memset(last_encode_end.bytes, 0, RRDATA_BYTES); @@ -194,28 +196,33 @@ uint64_t rrdata::write(std::ostream& strm) throw(std::bad_alloc) } if(encode_count > 0) flush_symbol(strm, encode_base, last_encode_end, encode_count); - return count; + if(count) + return count - 1; + else + return 0; } -uint64_t rrdata::read(std::istream& strm) throw(std::bad_alloc) +uint64_t rrdata::read(std::vector& strm, bool dummy) throw(std::bad_alloc) { uint64_t count = 0; instance decoding; + uint64_t ptr = 0; memset(decoding.bytes, 0, RRDATA_BYTES); - while(strm) { + while(ptr < strm.size()) { char opcode; char buf1[RRDATA_BYTES]; char buf2[3]; - strm.read(&opcode, 1); - if(!strm) - continue; + opcode = strm[ptr++]; unsigned validbytes = (opcode & 0x1F); unsigned lengthbytes = (opcode & 0x60) >> 5; unsigned repeat = 1; - strm.read(buf1, RRDATA_BYTES - validbytes); + memcpy(buf1, &strm[ptr], RRDATA_BYTES - validbytes); + ptr += (RRDATA_BYTES - validbytes); memcpy(decoding.bytes + validbytes, buf1, RRDATA_BYTES - validbytes); - if(lengthbytes > 0) - strm.read(buf2, lengthbytes); + if(lengthbytes > 0) { + memcpy(buf2, &strm[ptr], lengthbytes); + ptr += lengthbytes; + } if(lengthbytes == 1) repeat = 2 + buf2[0]; if(lengthbytes == 2) @@ -224,11 +231,20 @@ uint64_t rrdata::read(std::istream& strm) throw(std::bad_alloc) repeat = 65794 + static_cast(buf2[0]) * 65536 + static_cast(buf2[1]) * 256 + buf2[2]; //std::cerr << "Decoding " << count << " symbols starting from " << decoding << std::endl; - for(unsigned i = 0; i < repeat; i++) - rrdata::add(decoding++); + if(!dummy) + for(unsigned i = 0; i < repeat; i++) + rrdata::add(decoding++); count += repeat; } - return count; + if(count) + return count - 1; + else + return 0; +} + +uint64_t rrdata::count(std::vector& strm) throw(std::bad_alloc) +{ + return read(strm, true); } const char* hexes = "0123456789ABCDEF"; diff --git a/generic/rrdata.hpp b/generic/rrdata.hpp index e4d31301..c1bc8862 100644 --- a/generic/rrdata.hpp +++ b/generic/rrdata.hpp @@ -4,6 +4,7 @@ #define RRDATA_BYTES 32 #include #include +#include /** * Set of load IDs @@ -90,17 +91,27 @@ public: * Write compressed representation of current load ID set to stream. * * parameter strm: The stream to write to. + * returns: Rerecord count. * throws std::bad_alloc: Not enough memory. */ - static uint64_t write(std::ostream& strm) throw(std::bad_alloc); + static uint64_t write(std::vector& strm) throw(std::bad_alloc); /** * Load compressed representation of load ID set from stream and union it with current set to form new current * set. * * parameter strm: The stream to read from. + * returns: Rerecord count. * throws std::bad_alloc: Not enough memory. */ - static uint64_t read(std::istream& strm) throw(std::bad_alloc); + static uint64_t read(std::vector& strm, bool dummy = false) throw(std::bad_alloc); +/** + * Load compressed representation of load ID set from stream, but don't do anything to it. + * + * parameter strm: The stream to read from. + * returns: Rerecord count. + * throws std::bad_alloc: Not enough memory. + */ + static uint64_t count(std::vector& strm) throw(std::bad_alloc); /** * Internal pointer used by add_internal. */