Fix rerecord counting
This also fixes the off-by-one in rerecord count.
This commit is contained in:
parent
d9ed993a4a
commit
8c8fc98d19
6 changed files with 65 additions and 40 deletions
|
@ -514,6 +514,14 @@ class my_interface : public SNES::Interface
|
||||||
|
|
||||||
namespace
|
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<char> tmp;
|
||||||
|
uint64_t x = rrdata::write(tmp);
|
||||||
|
messages << x << " rerecord(s)" << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
function_ptr_command<const std::string&> quit_emulator("quit-emulator", "Quit the emulator",
|
function_ptr_command<const std::string&> quit_emulator("quit-emulator", "Quit the emulator",
|
||||||
"Syntax: quit-emulator [/y]\nQuits emulator (/y => don't ask for confirmation).\n",
|
"Syntax: quit-emulator [/y]\nQuits emulator (/y => don't ask for confirmation).\n",
|
||||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||||
|
|
|
@ -210,6 +210,7 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
||||||
|
|
||||||
//Negative return.
|
//Negative return.
|
||||||
rrdata::read_base(_movie.projectid);
|
rrdata::read_base(_movie.projectid);
|
||||||
|
rrdata::read(_movie.c_rrdata);
|
||||||
rrdata::add_internal();
|
rrdata::add_internal();
|
||||||
try {
|
try {
|
||||||
our_rom->region = gtype::toromregion(_movie.gametype);
|
our_rom->region = gtype::toromregion(_movie.gametype);
|
||||||
|
|
|
@ -99,18 +99,10 @@ void read_authors_file(zip_reader& r, std::vector<std::pair<std::string, std::st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string read_rrdata(zip_reader& r, const std::string& projectid) throw(std::bad_alloc, std::runtime_error)
|
std::string read_rrdata(zip_reader& r, std::vector<char>& out) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
std::istream& m = r["rrdata"];
|
out = read_raw_file(r, "rrdata");
|
||||||
uint64_t count;
|
uint64_t count = rrdata::count(out);
|
||||||
try {
|
|
||||||
rrdata::read_base(projectid);
|
|
||||||
count = rrdata::read(m);
|
|
||||||
delete &m;
|
|
||||||
} catch(...) {
|
|
||||||
delete &m;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
std::ostringstream x;
|
std::ostringstream x;
|
||||||
x << count;
|
x << count;
|
||||||
return x.str();
|
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)
|
void write_rrdata(zip_writer& w) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
std::ostream& m = w.create_file("rrdata");
|
|
||||||
uint64_t count;
|
uint64_t count;
|
||||||
try {
|
std::vector<char> out;
|
||||||
count = rrdata::write(m);
|
count = rrdata::write(out);
|
||||||
if(!m)
|
write_raw_file(w, "rrdata", out);
|
||||||
throw std::runtime_error("Can't write ZIP file member");
|
|
||||||
w.close_file();
|
|
||||||
} catch(...) {
|
|
||||||
w.close_file();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
std::ostream& m2 = w.create_file("rerecords");
|
std::ostream& m2 = w.create_file("rerecords");
|
||||||
try {
|
try {
|
||||||
m2 << count << std::endl;
|
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;
|
port2 = port_type::lookup(tmp, true).ptype;
|
||||||
read_linefile(r, "gamename", gamename, true);
|
read_linefile(r, "gamename", gamename, true);
|
||||||
read_linefile(r, "projectid", projectid);
|
read_linefile(r, "projectid", projectid);
|
||||||
rerecords = read_rrdata(r, projectid);
|
rerecords = read_rrdata(r, c_rrdata);
|
||||||
read_linefile(r, "coreversion", coreversion);
|
read_linefile(r, "coreversion", coreversion);
|
||||||
read_linefile(r, "rom.sha256", rom_sha256, true);
|
read_linefile(r, "rom.sha256", rom_sha256, true);
|
||||||
read_linefile(r, "romxml.sha256", romxml_sha256, true);
|
read_linefile(r, "romxml.sha256", romxml_sha256, true);
|
||||||
|
|
|
@ -128,6 +128,10 @@ struct moviefile
|
||||||
* State of movie code (if is_savestate is true).
|
* State of movie code (if is_savestate is true).
|
||||||
*/
|
*/
|
||||||
std::vector<char> movie_state;
|
std::vector<char> movie_state;
|
||||||
|
/**
|
||||||
|
* Compressed rrdata.
|
||||||
|
*/
|
||||||
|
std::vector<char> c_rrdata;
|
||||||
/**
|
/**
|
||||||
* Input for each (sub)frame.
|
* Input for each (sub)frame.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -111,7 +111,7 @@ void rrdata::close() throw()
|
||||||
|
|
||||||
void rrdata::add(const struct rrdata::instance& i) throw(std::bad_alloc)
|
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;
|
//std::cerr << "New symbol: " << i << std::endl;
|
||||||
ohandle.write(reinterpret_cast<const char*>(i.bytes), RRDATA_BYTES);
|
ohandle.write(reinterpret_cast<const char*>(i.bytes), RRDATA_BYTES);
|
||||||
ohandle.flush();
|
ohandle.flush();
|
||||||
|
@ -127,7 +127,7 @@ void rrdata::add_internal() throw(std::bad_alloc)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void flush_symbol(std::ostream& strm, const rrdata::instance& base, const rrdata::instance& predicted,
|
void flush_symbol(std::vector<char>& strm, const rrdata::instance& base, const rrdata::instance& predicted,
|
||||||
unsigned count)
|
unsigned count)
|
||||||
{
|
{
|
||||||
char opcode;
|
char opcode;
|
||||||
|
@ -158,13 +158,15 @@ namespace
|
||||||
buf2[1] = (count - bias) >> 8;
|
buf2[1] = (count - bias) >> 8;
|
||||||
buf2[2] = (count - bias);
|
buf2[2] = (count - bias);
|
||||||
memcpy(buf1 + (RRDATA_BYTES - j + 1), buf2 + (3 - (opcode >> 5)), opcode >> 5);
|
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;
|
//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<char>& strm) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
strm.clear();
|
||||||
uint64_t count = 0;
|
uint64_t count = 0;
|
||||||
instance last_encode_end;
|
instance last_encode_end;
|
||||||
memset(last_encode_end.bytes, 0, RRDATA_BYTES);
|
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)
|
if(encode_count > 0)
|
||||||
flush_symbol(strm, encode_base, last_encode_end, encode_count);
|
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<char>& strm, bool dummy) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
uint64_t count = 0;
|
uint64_t count = 0;
|
||||||
instance decoding;
|
instance decoding;
|
||||||
|
uint64_t ptr = 0;
|
||||||
memset(decoding.bytes, 0, RRDATA_BYTES);
|
memset(decoding.bytes, 0, RRDATA_BYTES);
|
||||||
while(strm) {
|
while(ptr < strm.size()) {
|
||||||
char opcode;
|
char opcode;
|
||||||
char buf1[RRDATA_BYTES];
|
char buf1[RRDATA_BYTES];
|
||||||
char buf2[3];
|
char buf2[3];
|
||||||
strm.read(&opcode, 1);
|
opcode = strm[ptr++];
|
||||||
if(!strm)
|
|
||||||
continue;
|
|
||||||
unsigned validbytes = (opcode & 0x1F);
|
unsigned validbytes = (opcode & 0x1F);
|
||||||
unsigned lengthbytes = (opcode & 0x60) >> 5;
|
unsigned lengthbytes = (opcode & 0x60) >> 5;
|
||||||
unsigned repeat = 1;
|
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);
|
memcpy(decoding.bytes + validbytes, buf1, RRDATA_BYTES - validbytes);
|
||||||
if(lengthbytes > 0)
|
if(lengthbytes > 0) {
|
||||||
strm.read(buf2, lengthbytes);
|
memcpy(buf2, &strm[ptr], lengthbytes);
|
||||||
|
ptr += lengthbytes;
|
||||||
|
}
|
||||||
if(lengthbytes == 1)
|
if(lengthbytes == 1)
|
||||||
repeat = 2 + buf2[0];
|
repeat = 2 + buf2[0];
|
||||||
if(lengthbytes == 2)
|
if(lengthbytes == 2)
|
||||||
|
@ -224,11 +231,20 @@ uint64_t rrdata::read(std::istream& strm) throw(std::bad_alloc)
|
||||||
repeat = 65794 + static_cast<unsigned>(buf2[0]) * 65536 + static_cast<unsigned>(buf2[1]) *
|
repeat = 65794 + static_cast<unsigned>(buf2[0]) * 65536 + static_cast<unsigned>(buf2[1]) *
|
||||||
256 + buf2[2];
|
256 + buf2[2];
|
||||||
//std::cerr << "Decoding " << count << " symbols starting from " << decoding << std::endl;
|
//std::cerr << "Decoding " << count << " symbols starting from " << decoding << std::endl;
|
||||||
|
if(!dummy)
|
||||||
for(unsigned i = 0; i < repeat; i++)
|
for(unsigned i = 0; i < repeat; i++)
|
||||||
rrdata::add(decoding++);
|
rrdata::add(decoding++);
|
||||||
count += repeat;
|
count += repeat;
|
||||||
}
|
}
|
||||||
return count;
|
if(count)
|
||||||
|
return count - 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t rrdata::count(std::vector<char>& strm) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
return read(strm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* hexes = "0123456789ABCDEF";
|
const char* hexes = "0123456789ABCDEF";
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define RRDATA_BYTES 32
|
#define RRDATA_BYTES 32
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of load IDs
|
* Set of load IDs
|
||||||
|
@ -90,17 +91,27 @@ public:
|
||||||
* Write compressed representation of current load ID set to stream.
|
* Write compressed representation of current load ID set to stream.
|
||||||
*
|
*
|
||||||
* parameter strm: The stream to write to.
|
* parameter strm: The stream to write to.
|
||||||
|
* returns: Rerecord count.
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
*/
|
*/
|
||||||
static uint64_t write(std::ostream& strm) throw(std::bad_alloc);
|
static uint64_t write(std::vector<char>& strm) throw(std::bad_alloc);
|
||||||
/**
|
/**
|
||||||
* Load compressed representation of load ID set from stream and union it with current set to form new current
|
* Load compressed representation of load ID set from stream and union it with current set to form new current
|
||||||
* set.
|
* set.
|
||||||
*
|
*
|
||||||
* parameter strm: The stream to read from.
|
* parameter strm: The stream to read from.
|
||||||
|
* returns: Rerecord count.
|
||||||
* throws std::bad_alloc: Not enough memory.
|
* throws std::bad_alloc: Not enough memory.
|
||||||
*/
|
*/
|
||||||
static uint64_t read(std::istream& strm) throw(std::bad_alloc);
|
static uint64_t read(std::vector<char>& 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<char>& strm) throw(std::bad_alloc);
|
||||||
/**
|
/**
|
||||||
* Internal pointer used by add_internal.
|
* Internal pointer used by add_internal.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue