EVENTRECORDER: Change file format to big-endian

Previously the file format had all chunks, offsets and values stored in
little-endian format. The one exception was screenshots, which used the
existing THMB code in graphics/thumbnail.cpp, that is entirely
big-endian. Any tooling which attempts to parse the Event Recorder file
format must make a special exception for THMB chunks, and read the chunk
size and contents as big-endian.

In the interests of making the file format more consistant
to parse, and given that backwards compatibility is not required for
this iteration of Event Recorder, this patch changes everything to
big-endian.
This commit is contained in:
Scott Percival 2021-09-07 00:35:56 +08:00 committed by Martin Gerhardy
parent 1040bd2862
commit fb421a0ca7
2 changed files with 93 additions and 93 deletions

View File

@ -132,7 +132,7 @@ bool PlaybackFile::parseHeader() {
}
bool PlaybackFile::checkPlaybackFileVersion() {
_version = _readStream->readUint32LE();
_version = _readStream->readUint32BE();
switch (_version) {
case 2:
break;
@ -167,8 +167,8 @@ String PlaybackFile::readString(int len) {
}
bool PlaybackFile::readChunkHeader(PlaybackFile::ChunkHeader &nextChunk) {
nextChunk.id = (FileTag)_readStream->readUint32LE();
nextChunk.len = _readStream->readUint32LE();
nextChunk.id = (FileTag)_readStream->readUint32BE();
nextChunk.len = _readStream->readUint32BE();
return !_readStream->err() && !_readStream->eos();
}
@ -286,7 +286,7 @@ void PlaybackFile::readHashMap(ChunkHeader chunk) {
void PlaybackFile::processRndSeedRecord(ChunkHeader chunk) {
String randomSourceName = readString(chunk.len - 4);
uint32 randomSourceSeed = _readStream->readUint32LE();
uint32 randomSourceSeed = _readStream->readUint32BE();
_header.randomSourceRecords[randomSourceName] = randomSourceSeed;
}
@ -381,32 +381,32 @@ void PlaybackFile::readEvent(RecorderEvent& event) {
event.recordedtype = (RecorderEventType)_tmpPlaybackFile.readByte();
switch (event.recordedtype) {
case kRecorderEventTypeTimer:
event.time = _tmpPlaybackFile.readUint32LE();
event.time = _tmpPlaybackFile.readUint32BE();
break;
case kRecorderEventTypeTimeDate:
event.timeDate.tm_sec = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_min = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_hour = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_mday = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_mon = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_year = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_wday = _tmpPlaybackFile.readSint32LE();
event.timeDate.tm_sec = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_min = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_hour = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_mday = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_mon = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_year = _tmpPlaybackFile.readSint32BE();
event.timeDate.tm_wday = _tmpPlaybackFile.readSint32BE();
break;
case kRecorderEventTypeScreenUpdate:
event.time = _tmpPlaybackFile.readUint32LE();
event.time = _tmpPlaybackFile.readUint32BE();
break;
default:
// fallthrough intended
case kRecorderEventTypeNormal:
event.type = (EventType)_tmpPlaybackFile.readUint32LE();
event.type = (EventType)_tmpPlaybackFile.readUint32BE();
switch (event.type) {
case EVENT_KEYDOWN:
event.kbdRepeat = _tmpPlaybackFile.readByte();
// fallthrough
case EVENT_KEYUP:
event.time = _tmpPlaybackFile.readUint32LE();
event.kbd.keycode = (KeyCode)_tmpPlaybackFile.readSint32LE();
event.kbd.ascii = _tmpPlaybackFile.readUint16LE();
event.time = _tmpPlaybackFile.readUint32BE();
event.kbd.keycode = (KeyCode)_tmpPlaybackFile.readSint32BE();
event.kbd.ascii = _tmpPlaybackFile.readUint16BE();
event.kbd.flags = _tmpPlaybackFile.readByte();
break;
case EVENT_MOUSEMOVE:
@ -422,27 +422,27 @@ void PlaybackFile::readEvent(RecorderEvent& event) {
case EVENT_X1BUTTONUP:
case EVENT_X2BUTTONDOWN:
case EVENT_X2BUTTONUP:
event.time = _tmpPlaybackFile.readUint32LE();
event.mouse.x = _tmpPlaybackFile.readSint16LE();
event.mouse.y = _tmpPlaybackFile.readSint16LE();
event.time = _tmpPlaybackFile.readUint32BE();
event.mouse.x = _tmpPlaybackFile.readSint16BE();
event.mouse.y = _tmpPlaybackFile.readSint16BE();
break;
case EVENT_CUSTOM_BACKEND_ACTION_START:
case EVENT_CUSTOM_BACKEND_ACTION_END:
case EVENT_CUSTOM_ENGINE_ACTION_START:
case EVENT_CUSTOM_ENGINE_ACTION_END:
event.time = _tmpPlaybackFile.readUint32LE();
event.customType = _tmpPlaybackFile.readUint32LE();
event.time = _tmpPlaybackFile.readUint32BE();
event.customType = _tmpPlaybackFile.readUint32BE();
break;
case EVENT_JOYAXIS_MOTION:
case EVENT_JOYBUTTON_UP:
case EVENT_JOYBUTTON_DOWN:
event.time = _tmpPlaybackFile.readUint32LE();
event.time = _tmpPlaybackFile.readUint32BE();
event.joystick.axis = _tmpPlaybackFile.readByte();
event.joystick.button = _tmpPlaybackFile.readByte();
event.joystick.position = _tmpPlaybackFile.readSint16LE();
event.joystick.position = _tmpPlaybackFile.readSint16BE();
break;
default:
event.time = _tmpPlaybackFile.readUint32LE();
event.time = _tmpPlaybackFile.readUint32BE();
break;
}
break;
@ -459,8 +459,8 @@ void PlaybackFile::readEventsToBuffer(uint32 size) {
void PlaybackFile::saveScreenShot(Graphics::Surface &screen, byte md5[16]) {
dumpRecordsToFile();
_writeStream->writeUint32LE(kMD5Tag);
_writeStream->writeUint32LE(16);
_writeStream->writeUint32BE(kMD5Tag);
_writeStream->writeUint32BE(16);
_writeStream->write(md5, 16);
Graphics::saveThumbnail(*_writeStream, screen);
}
@ -473,21 +473,21 @@ void PlaybackFile::dumpRecordsToFile() {
if (_recordCount == 0) {
return;
}
_writeStream->writeUint32LE(kEventTag);
_writeStream->writeUint32LE(_tmpRecordFile.pos());
_writeStream->writeUint32BE(kEventTag);
_writeStream->writeUint32BE(_tmpRecordFile.pos());
_writeStream->write(_tmpBuffer.data(), _tmpRecordFile.pos());
_tmpRecordFile.seek(0);
_recordCount = 0;
}
void PlaybackFile::dumpHeaderToFile() {
_writeStream->writeUint32LE(kFormatIdTag);
_writeStream->writeUint32BE(kFormatIdTag);
// Specify size for first tag as NULL since we cannot calculate
// size of the file at time of the header dumping
_writeStream->writeUint32LE(0);
_writeStream->writeUint32LE(kVersionTag);
_writeStream->writeUint32LE(4);
_writeStream->writeUint32LE(RECORD_VERSION);
_writeStream->writeUint32BE(0);
_writeStream->writeUint32BE(kVersionTag);
_writeStream->writeUint32BE(4);
_writeStream->writeUint32BE(RECORD_VERSION);
writeHeaderSection();
writeGameHash();
writeRandomRecords();
@ -509,21 +509,21 @@ void PlaybackFile::writeHeaderSection() {
if (headerSize == 0) {
return;
}
_writeStream->writeUint32LE(kHeaderSectionTag);
_writeStream->writeUint32LE(headerSize);
_writeStream->writeUint32BE(kHeaderSectionTag);
_writeStream->writeUint32BE(headerSize);
if (!_header.author.empty()) {
_writeStream->writeUint32LE(kAuthorTag);
_writeStream->writeUint32LE(_header.author.size());
_writeStream->writeUint32BE(kAuthorTag);
_writeStream->writeUint32BE(_header.author.size());
_writeStream->writeString(_header.author);
}
if (!_header.notes.empty()) {
_writeStream->writeUint32LE(kCommentsTag);
_writeStream->writeUint32LE(_header.notes.size());
_writeStream->writeUint32BE(kCommentsTag);
_writeStream->writeUint32BE(_header.notes.size());
_writeStream->writeString(_header.notes);
}
if (!_header.name.empty()) {
_writeStream->writeUint32LE(kNameTag);
_writeStream->writeUint32LE(_header.name.size());
_writeStream->writeUint32BE(kNameTag);
_writeStream->writeUint32BE(_header.name.size());
_writeStream->writeString(_header.name);
}
}
@ -536,11 +536,11 @@ void PlaybackFile::writeGameHash() {
if (_header.hashRecords.size() == 0) {
return;
}
_writeStream->writeUint32LE(kHashSectionTag);
_writeStream->writeUint32LE(hashSectionSize);
_writeStream->writeUint32BE(kHashSectionTag);
_writeStream->writeUint32BE(hashSectionSize);
for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) {
_writeStream->writeUint32LE(kHashRecordTag);
_writeStream->writeUint32LE(i->_key.size() + i->_value.size());
_writeStream->writeUint32BE(kHashRecordTag);
_writeStream->writeUint32BE(i->_key.size() + i->_value.size());
_writeStream->writeString(i->_key);
_writeStream->writeString(i->_value);
}
@ -554,13 +554,13 @@ void PlaybackFile::writeRandomRecords() {
if (_header.randomSourceRecords.size() == 0) {
return;
}
_writeStream->writeUint32LE(kRandomSectionTag);
_writeStream->writeUint32LE(randomSectionSize);
_writeStream->writeUint32BE(kRandomSectionTag);
_writeStream->writeUint32BE(randomSectionSize);
for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) {
_writeStream->writeUint32LE(kRandomRecordTag);
_writeStream->writeUint32LE(i->_key.size() + 4);
_writeStream->writeUint32BE(kRandomRecordTag);
_writeStream->writeUint32BE(i->_key.size() + 4);
_writeStream->writeString(i->_key);
_writeStream->writeUint32LE(i->_value);
_writeStream->writeUint32BE(i->_value);
}
}
@ -570,32 +570,32 @@ void PlaybackFile::writeEvent(const RecorderEvent &event) {
_tmpRecordFile.writeByte(event.recordedtype);
switch (event.recordedtype) {
case kRecorderEventTypeTimer:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeUint32BE(event.time);
break;
case kRecorderEventTypeTimeDate:
_tmpRecordFile.writeSint32LE(event.timeDate.tm_sec);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_min);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_hour);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_mday);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_mon);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_year);
_tmpRecordFile.writeSint32LE(event.timeDate.tm_wday);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_sec);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_min);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_hour);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_mday);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_mon);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_year);
_tmpRecordFile.writeSint32BE(event.timeDate.tm_wday);
break;
case kRecorderEventTypeScreenUpdate:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeUint32BE(event.time);
break;
default:
// fallthrough intended
case kRecorderEventTypeNormal:
_tmpRecordFile.writeUint32LE((uint32)event.type);
_tmpRecordFile.writeUint32BE((uint32)event.type);
switch(event.type) {
case EVENT_KEYDOWN:
_tmpRecordFile.writeByte(event.kbdRepeat);
// fallthrough
case EVENT_KEYUP:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeSint32LE(event.kbd.keycode);
_tmpRecordFile.writeUint16LE(event.kbd.ascii);
_tmpRecordFile.writeUint32BE(event.time);
_tmpRecordFile.writeSint32BE(event.kbd.keycode);
_tmpRecordFile.writeUint16BE(event.kbd.ascii);
_tmpRecordFile.writeByte(event.kbd.flags);
break;
case EVENT_MOUSEMOVE:
@ -611,27 +611,27 @@ void PlaybackFile::writeEvent(const RecorderEvent &event) {
case EVENT_X1BUTTONUP:
case EVENT_X2BUTTONDOWN:
case EVENT_X2BUTTONUP:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeSint16LE(event.mouse.x);
_tmpRecordFile.writeSint16LE(event.mouse.y);
_tmpRecordFile.writeUint32BE(event.time);
_tmpRecordFile.writeSint16BE(event.mouse.x);
_tmpRecordFile.writeSint16BE(event.mouse.y);
break;
case EVENT_CUSTOM_BACKEND_ACTION_START:
case EVENT_CUSTOM_BACKEND_ACTION_END:
case EVENT_CUSTOM_ENGINE_ACTION_START:
case EVENT_CUSTOM_ENGINE_ACTION_END:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeUint32LE(event.customType);
_tmpRecordFile.writeUint32BE(event.time);
_tmpRecordFile.writeUint32BE(event.customType);
break;
case EVENT_JOYAXIS_MOTION:
case EVENT_JOYBUTTON_UP:
case EVENT_JOYBUTTON_DOWN:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeUint32BE(event.time);
_tmpRecordFile.writeByte(event.joystick.axis);
_tmpRecordFile.writeByte(event.joystick.button);
_tmpRecordFile.writeSint16LE(event.joystick.position);
_tmpRecordFile.writeSint16BE(event.joystick.position);
break;
default:
_tmpRecordFile.writeUint32LE(event.time);
_tmpRecordFile.writeUint32BE(event.time);
break;
}
break;
@ -644,20 +644,20 @@ void PlaybackFile::writeEvent(const RecorderEvent &event) {
}
void PlaybackFile::writeGameSettings() {
_writeStream->writeUint32LE(kSettingsSectionTag);
_writeStream->writeUint32BE(kSettingsSectionTag);
uint32 settingsSectionSize = 0;
for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
settingsSectionSize += i->_key.size() + i->_value.size() + 24;
}
_writeStream->writeUint32LE(settingsSectionSize);
_writeStream->writeUint32BE(settingsSectionSize);
for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
_writeStream->writeUint32LE(kSettingsRecordTag);
_writeStream->writeUint32LE(i->_key.size() + i->_value.size() + 16);
_writeStream->writeUint32LE(kSettingsRecordKeyTag);
_writeStream->writeUint32LE(i->_key.size());
_writeStream->writeUint32BE(kSettingsRecordTag);
_writeStream->writeUint32BE(i->_key.size() + i->_value.size() + 16);
_writeStream->writeUint32BE(kSettingsRecordKeyTag);
_writeStream->writeUint32BE(i->_key.size());
_writeStream->writeString(i->_key);
_writeStream->writeUint32LE(kSettingsRecordValueTag);
_writeStream->writeUint32LE(i->_value.size());
_writeStream->writeUint32BE(kSettingsRecordValueTag);
_writeStream->writeUint32BE(i->_value.size());
_writeStream->writeString(i->_value);
}
}
@ -678,14 +678,14 @@ int PlaybackFile::getScreensCount() {
bool PlaybackFile::skipToNextScreenshot() {
while (!_readStream->eos() && !_readStream->err()) {
FileTag id = (FileTag)_readStream->readUint32LE();
FileTag id = (FileTag)_readStream->readUint32BE();
if (_readStream->eos() || _readStream->err()) {
break;
}
if (id == kScreenShotTag) {
return true;
}
uint32 size = _readStream->readUint32LE();
uint32 size = _readStream->readUint32BE();
_readStream->skip(size);
}
return false;
@ -743,7 +743,7 @@ void PlaybackFile::updateHeader() {
void PlaybackFile::skipHeader() {
while (true) {
uint32 id = _readStream->readUint32LE();
uint32 id = _readStream->readUint32BE();
if (_readStream->eos()) {
break;
}
@ -752,7 +752,7 @@ void PlaybackFile::skipHeader() {
return;
}
else {
uint32 size = _readStream->readUint32LE();
uint32 size = _readStream->readUint32BE();
_readStream->skip(size);
}
}
@ -775,16 +775,16 @@ void PlaybackFile::writeSaveFilesSection() {
if (size == 0) {
return;
}
_writeStream->writeSint32LE(kSaveTag);
_writeStream->writeSint32LE(size);
_writeStream->writeSint32BE(kSaveTag);
_writeStream->writeSint32BE(size);
for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
_writeStream->writeSint32LE(kSaveRecordTag);
_writeStream->writeSint32LE(i->_key.size() + i->_value.size + 16);
_writeStream->writeSint32LE(kSaveRecordNameTag);
_writeStream->writeSint32LE(i->_key.size());
_writeStream->writeSint32BE(kSaveRecordTag);
_writeStream->writeSint32BE(i->_key.size() + i->_value.size + 16);
_writeStream->writeSint32BE(kSaveRecordNameTag);
_writeStream->writeSint32BE(i->_key.size());
_writeStream->writeString(i->_key);
_writeStream->writeSint32LE(kSaveRecordBufferTag);
_writeStream->writeSint32LE(i->_value.size);
_writeStream->writeSint32BE(kSaveRecordBufferTag);
_writeStream->writeSint32BE(i->_value.size);
_writeStream->write(i->_value.buffer, i->_value.size);
}
}

View File

@ -103,7 +103,7 @@ class PlaybackFile {
kHashSectionTag = MKTAG('H','A','S','H'),
kRandomSectionTag = MKTAG('R','A','N','D'),
kEventTag = MKTAG('E','V','N','T'),
kScreenShotTag = MKTAG('B','M','H','T'),
kScreenShotTag = MKTAG('T','H','M','B'),
kSettingsSectionTag = MKTAG('S','E','T','T'),
kAuthorTag = MKTAG('H','A','U','T'),
kCommentsTag = MKTAG('H','C','M','T'),