Commit fb23c232 authored by salix5's avatar salix5 Committed by GitHub

Merge pull request #2359 from Fluorohydride/patch-replay

update class Replay
parents 990c6e5b 449e2993
...@@ -5,11 +5,13 @@ ...@@ -5,11 +5,13 @@
namespace ygo { namespace ygo {
Replay::Replay() { Replay::Replay()
is_recording = false; : fp(nullptr), pheader(), pdata(nullptr), replay_size(0), comp_size(0), is_recording(false), is_replaying(false) {
is_replaying = false; #ifdef _WIN32
replay_data = new unsigned char[0x20000]; recording_fp = nullptr;
comp_data = new unsigned char[0x2000]; #endif
replay_data = new unsigned char[MAX_REPLAY_SIZE];
comp_data = new unsigned char[MAX_COMP_SIZE];
} }
Replay::~Replay() { Replay::~Replay() {
delete[] replay_data; delete[] replay_data;
...@@ -32,6 +34,9 @@ void Replay::BeginRecord() { ...@@ -32,6 +34,9 @@ void Replay::BeginRecord() {
return; return;
#endif #endif
pdata = replay_data; pdata = replay_data;
replay_size = 0;
comp_size = 0;
is_replaying = false;
is_recording = true; is_recording = true;
} }
void Replay::WriteHeader(ReplayHeader& header) { void Replay::WriteHeader(ReplayHeader& header) {
...@@ -44,9 +49,11 @@ void Replay::WriteHeader(ReplayHeader& header) { ...@@ -44,9 +49,11 @@ void Replay::WriteHeader(ReplayHeader& header) {
fflush(fp); fflush(fp);
#endif #endif
} }
void Replay::WriteData(const void* data, unsigned int length, bool flush) { void Replay::WriteData(const void* data, int length, bool flush) {
if(!is_recording) if(!is_recording)
return; return;
if (length < 0 || (pdata - replay_data) + length > MAX_REPLAY_SIZE)
return;
memcpy(pdata, data, length); memcpy(pdata, data, length);
pdata += length; pdata += length;
#ifdef _WIN32 #ifdef _WIN32
...@@ -61,6 +68,8 @@ void Replay::WriteData(const void* data, unsigned int length, bool flush) { ...@@ -61,6 +68,8 @@ void Replay::WriteData(const void* data, unsigned int length, bool flush) {
void Replay::WriteInt32(int data, bool flush) { void Replay::WriteInt32(int data, bool flush) {
if(!is_recording) if(!is_recording)
return; return;
if ((pdata - replay_data) + 4 > MAX_REPLAY_SIZE)
return;
*((int*)(pdata)) = data; *((int*)(pdata)) = data;
pdata += 4; pdata += 4;
#ifdef _WIN32 #ifdef _WIN32
...@@ -75,6 +84,8 @@ void Replay::WriteInt32(int data, bool flush) { ...@@ -75,6 +84,8 @@ void Replay::WriteInt32(int data, bool flush) {
void Replay::WriteInt16(short data, bool flush) { void Replay::WriteInt16(short data, bool flush) {
if(!is_recording) if(!is_recording)
return; return;
if ((pdata - replay_data) + 2 > MAX_REPLAY_SIZE)
return;
*((short*)(pdata)) = data; *((short*)(pdata)) = data;
pdata += 2; pdata += 2;
#ifdef _WIN32 #ifdef _WIN32
...@@ -89,6 +100,8 @@ void Replay::WriteInt16(short data, bool flush) { ...@@ -89,6 +100,8 @@ void Replay::WriteInt16(short data, bool flush) {
void Replay::WriteInt8(char data, bool flush) { void Replay::WriteInt8(char data, bool flush) {
if(!is_recording) if(!is_recording)
return; return;
if ((pdata - replay_data) + 1 > MAX_REPLAY_SIZE)
return;
*pdata = data; *pdata = data;
pdata++; pdata++;
#ifdef _WIN32 #ifdef _WIN32
...@@ -116,11 +129,19 @@ void Replay::EndRecord() { ...@@ -116,11 +129,19 @@ void Replay::EndRecord() {
#else #else
fclose(fp); fclose(fp);
#endif #endif
pheader.datasize = pdata - replay_data; if(pdata - replay_data > 0 && pdata - replay_data <= MAX_REPLAY_SIZE)
replay_size = pdata - replay_data;
else
replay_size = 0;
pheader.datasize = replay_size;
pheader.flag |= REPLAY_COMPRESSED; pheader.flag |= REPLAY_COMPRESSED;
size_t propsize = 5; size_t propsize = 5;
comp_size = 0x1000; comp_size = MAX_COMP_SIZE;
LzmaCompress(comp_data, &comp_size, replay_data, pdata - replay_data, pheader.props, &propsize, 5, 1 << 24, 3, 0, 2, 32, 1); int ret = LzmaCompress(comp_data, &comp_size, replay_data, replay_size, pheader.props, &propsize, 5, 1 << 24, 3, 0, 2, 32, 1);
if (ret != SZ_OK) {
*((int*)(comp_data)) = ret;
comp_size = sizeof(ret);
}
is_recording = false; is_recording = false;
} }
void Replay::SaveReplay(const wchar_t* name) { void Replay::SaveReplay(const wchar_t* name) {
...@@ -162,22 +183,33 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -162,22 +183,33 @@ bool Replay::OpenReplay(const wchar_t* name) {
} }
if(!fp) if(!fp)
return false; return false;
pdata = replay_data;
is_recording = false;
is_replaying = false;
replay_size = 0;
comp_size = 0;
if(fread(&pheader, sizeof(pheader), 1, fp) < 1) { if(fread(&pheader, sizeof(pheader), 1, fp) < 1) {
fclose(fp); fclose(fp);
return false; return false;
} }
if(pheader.flag & REPLAY_COMPRESSED) { if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = fread(comp_data, 1, 0x1000, fp); comp_size = fread(comp_data, 1, MAX_COMP_SIZE, fp);
fclose(fp); fclose(fp);
if ((int)pheader.datasize < 0 && (int)pheader.datasize > MAX_REPLAY_SIZE)
return false;
replay_size = pheader.datasize; replay_size = pheader.datasize;
if(LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK) if (LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK)
return false;
if (replay_size != pheader.datasize) {
replay_size = 0;
return false; return false;
}
} else { } else {
comp_size = fread(replay_data, 1, 0x20000, fp); replay_size = fread(replay_data, 1, MAX_REPLAY_SIZE, fp);
fclose(fp); fclose(fp);
replay_size = comp_size; comp_size = 0;
} }
pdata = replay_data;
is_replaying = true; is_replaying = true;
return true; return true;
} }
...@@ -196,7 +228,7 @@ bool Replay::CheckReplay(const wchar_t* name) { ...@@ -196,7 +228,7 @@ bool Replay::CheckReplay(const wchar_t* name) {
ReplayHeader rheader; ReplayHeader rheader;
size_t count = fread(&rheader, sizeof(ReplayHeader), 1, rfp); size_t count = fread(&rheader, sizeof(ReplayHeader), 1, rfp);
fclose(rfp); fclose(rfp);
return count == 1 && rheader.id == 0x31707279 && rheader.version >= 0x12d0; return count == 1 && rheader.id == 0x31707279 && rheader.version >= 0x12d0u;
} }
bool Replay::DeleteReplay(const wchar_t* name) { bool Replay::DeleteReplay(const wchar_t* name) {
wchar_t fname[256]; wchar_t fname[256];
...@@ -245,7 +277,7 @@ void Replay::ReadName(wchar_t* data) { ...@@ -245,7 +277,7 @@ void Replay::ReadName(wchar_t* data) {
ReadData(buffer, 40); ReadData(buffer, 40);
BufferIO::CopyWStr(buffer, data, 20); BufferIO::CopyWStr(buffer, data, 20);
} }
void Replay::ReadData(void* data, unsigned int length) { void Replay::ReadData(void* data, int length) {
if(!is_replaying) if(!is_replaying)
return; return;
memcpy(data, pdata, length); memcpy(data, pdata, length);
......
...@@ -6,11 +6,16 @@ ...@@ -6,11 +6,16 @@
namespace ygo { namespace ygo {
// replay flag
#define REPLAY_COMPRESSED 0x1 #define REPLAY_COMPRESSED 0x1
#define REPLAY_TAG 0x2 #define REPLAY_TAG 0x2
#define REPLAY_DECODED 0x4 #define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8 #define REPLAY_SINGLE_MODE 0x8
// max size
#define MAX_REPLAY_SIZE 0x20000
#define MAX_COMP_SIZE 0x2000
struct ReplayHeader { struct ReplayHeader {
unsigned int id; unsigned int id;
unsigned int version; unsigned int version;
...@@ -19,21 +24,28 @@ struct ReplayHeader { ...@@ -19,21 +24,28 @@ struct ReplayHeader {
unsigned int datasize; unsigned int datasize;
unsigned int hash; unsigned int hash;
unsigned char props[8]; unsigned char props[8];
ReplayHeader()
: id(0), version(0), flag(0), seed(0), datasize(0), hash(0), props{ 0 } {}
}; };
class Replay { class Replay {
public: public:
Replay(); Replay();
~Replay(); ~Replay();
// record
void BeginRecord(); void BeginRecord();
void WriteHeader(ReplayHeader& header); void WriteHeader(ReplayHeader& header);
void WriteData(const void* data, unsigned int length, bool flush = true); void WriteData(const void* data, int length, bool flush = true);
void WriteInt32(int data, bool flush = true); void WriteInt32(int data, bool flush = true);
void WriteInt16(short data, bool flush = true); void WriteInt16(short data, bool flush = true);
void WriteInt8(char data, bool flush = true); void WriteInt8(char data, bool flush = true);
void Flush(); void Flush();
void EndRecord(); void EndRecord();
void SaveReplay(const wchar_t* name); void SaveReplay(const wchar_t* name);
// play
bool OpenReplay(const wchar_t* name); bool OpenReplay(const wchar_t* name);
static bool CheckReplay(const wchar_t* name); static bool CheckReplay(const wchar_t* name);
static bool DeleteReplay(const wchar_t* name); static bool DeleteReplay(const wchar_t* name);
...@@ -41,22 +53,25 @@ public: ...@@ -41,22 +53,25 @@ public:
bool ReadNextResponse(unsigned char resp[64]); bool ReadNextResponse(unsigned char resp[64]);
void ReadName(wchar_t* data); void ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header); void ReadHeader(ReplayHeader& header);
void ReadData(void* data, unsigned int length); void ReadData(void* data, int length);
int ReadInt32(); int ReadInt32();
short ReadInt16(); short ReadInt16();
char ReadInt8(); char ReadInt8();
void Rewind(); void Rewind();
FILE* fp; FILE* fp;
ReplayHeader pheader;
#ifdef _WIN32 #ifdef _WIN32
HANDLE recording_fp; HANDLE recording_fp;
#endif #endif
ReplayHeader pheader;
unsigned char* replay_data; unsigned char* replay_data;
unsigned char* comp_data; unsigned char* comp_data;
unsigned char* pdata;
size_t replay_size; size_t replay_size;
size_t comp_size; size_t comp_size;
private:
unsigned char* pdata;
bool is_recording; bool is_recording;
bool is_replaying; bool is_replaying;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment