mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
PRIVATE: integrated first version of the decompiler
This commit is contained in:
parent
f10fb7fbad
commit
6c80b049af
@ -1,53 +1,49 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "decompiler.h"
|
||||
#include "private/decompiler.h"
|
||||
|
||||
namespace Private {
|
||||
|
||||
Decompiler::~Decompiler() {
|
||||
}
|
||||
Decompiler::Decompiler(char *buf, uint32 fileSize, bool mac) {
|
||||
|
||||
Decompiler::Decompiler(const std::string &fileName, bool mac) {
|
||||
std::ifstream infile(fileName);
|
||||
if (!infile.good())
|
||||
throw std::invalid_argument("File does not exist");
|
||||
std::ifstream input(fileName, std::ios::binary);
|
||||
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
|
||||
decompile(buffer, mac);
|
||||
}
|
||||
Decompiler::Decompiler(std::vector<unsigned char> &buffer, bool mac) {
|
||||
decompile(buffer, mac);
|
||||
}
|
||||
|
||||
void Decompiler::decompile(std::vector<unsigned char> &buffer, bool mac) {
|
||||
std::vector<unsigned char>::iterator it = buffer.begin();
|
||||
|
||||
std::string firstBytes(it, it + kHeader.length());
|
||||
if (firstBytes != kHeader) {
|
||||
throw std::invalid_argument("Not a precompiled game matrix");
|
||||
Common::Array<unsigned char> array;
|
||||
uint32 i = 0;
|
||||
while (i < fileSize) {
|
||||
array.push_back(buf[i]);
|
||||
i++;
|
||||
}
|
||||
decompile(array, mac);
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
void Decompiler::decompile(Common::Array<unsigned char> &buffer, bool mac) {
|
||||
Common::Array<unsigned char>::iterator it = buffer.begin();
|
||||
|
||||
Common::String firstBytes((const char *) it, (const char *) it + kHeader.size());
|
||||
//debug("first bytes \"%s\"", firstBytes.c_str());
|
||||
|
||||
if (firstBytes != kHeader) {
|
||||
error("Not a precompiled game matrix");
|
||||
}
|
||||
|
||||
Common::String ss;
|
||||
bool inDefineRects = false;
|
||||
for (it += kHeader.length() ; it != buffer.end() ; ) {
|
||||
for (it += kHeader.size() ; it != buffer.end() ; ) {
|
||||
unsigned char byte = *it++;
|
||||
if (byte == kCodeString) {
|
||||
unsigned char len = *it++;
|
||||
std::string s(it,it+len);
|
||||
Common::String s((const char *)it,(const char *)it+len);
|
||||
it += len;
|
||||
ss << "\"" << s << "\"";
|
||||
ss += Common::String::format("\"%s\"", s.c_str());
|
||||
} else if (byte == kCodeShortLiteral || byte == kCodeShortId) {
|
||||
unsigned char b1 = *it++;
|
||||
unsigned char b2 = *it++;
|
||||
unsigned int number = mac ? b2 + (b1 << 8) : b1 + (b2 << 8);
|
||||
if (byte == kCodeShortId) ss << "k";
|
||||
ss << number;
|
||||
if (byte == kCodeShortId) ss += "k";
|
||||
ss += Common::String::format("%d", number);
|
||||
} else if (byte == kCodeRect && inDefineRects) {
|
||||
ss << "RECT"; // override CRect
|
||||
} else if (byte <= kCodeShortId && kCodeTable[byte].length() > 0) {
|
||||
ss << kCodeTable[byte];
|
||||
ss += "RECT"; // override CRect
|
||||
} else if (byte <= kCodeShortId && strlen(kCodeTable[byte]) > 0) {
|
||||
ss += kCodeTable[byte];
|
||||
} else {
|
||||
throw std::invalid_argument("Unknown byte code");
|
||||
error("Unknown byte code");
|
||||
}
|
||||
|
||||
if (byte == kCodeRects) {
|
||||
@ -56,11 +52,11 @@ void Decompiler::decompile(std::vector<unsigned char> &buffer, bool mac) {
|
||||
inDefineRects = false;
|
||||
}
|
||||
}
|
||||
_result = ss.str();
|
||||
_result = ss;
|
||||
}
|
||||
|
||||
void Decompiler::getResult(std::string &result) const {
|
||||
result = _result;
|
||||
Common::String Decompiler::getResult() const {
|
||||
return _result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#ifndef PRIVATE_DECOMPILER_H
|
||||
#define PRIVATE_DECOMPILER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace Private {
|
||||
|
||||
const std::string kHeader("Precompiled Game Matrix");
|
||||
const Common::String kHeader = "Precompiled Game Matrix";
|
||||
|
||||
const unsigned char kCodeString = 0x01;
|
||||
const unsigned char kCodeShortLiteral = 0x02;
|
||||
@ -12,7 +16,7 @@ const unsigned char kCodeRect = 0x2e;
|
||||
const unsigned char kCodeRects = 0x4f;
|
||||
const unsigned char kCodeShortId = 0x50;
|
||||
|
||||
const std::vector<std::string> kCodeTable = {"", //
|
||||
const static char *kCodeTable[] = {"", //
|
||||
"", // 0x01 (string)
|
||||
"", // 0x02 (short literal)
|
||||
" {\n", // 0x03
|
||||
@ -92,18 +96,19 @@ const std::vector<std::string> kCodeTable = {"", //
|
||||
"", //
|
||||
"", //
|
||||
"rects", // 0x4f
|
||||
""}; // 0x50 (short id)
|
||||
""
|
||||
}; // 0x50 (short id)
|
||||
|
||||
|
||||
class Decompiler {
|
||||
public:
|
||||
Decompiler(const std::string &filename, bool mac = false);
|
||||
Decompiler(std::vector<unsigned char> &buffer, bool mac = false);
|
||||
virtual ~Decompiler();
|
||||
void getResult(std::string &result) const;
|
||||
Decompiler(char *buf, uint32 fileSize, bool mac = false);
|
||||
Common::String getResult() const;
|
||||
private:
|
||||
void decompile(std::vector<unsigned char> &buffer, bool mac);
|
||||
std::string _result;
|
||||
void decompile(Common::Array<unsigned char> &buffer, bool mac);
|
||||
Common::String _result;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -65,7 +65,7 @@ static const ADGameDescription gameDescriptions[] = {
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_UNSUPPORTED,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
@ -75,7 +75,7 @@ static const ADGameDescription gameDescriptions[] = {
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO | ADGF_TESTING,
|
||||
ADGF_DEMO | ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
@ -100,32 +100,32 @@ static const ADGameDescription gameDescriptions[] = {
|
||||
},
|
||||
{
|
||||
"private-eye", // EU release (ES)
|
||||
"It uses different file format for the assest",
|
||||
"Demo",
|
||||
AD_ENTRY2s("pvteye.ex_", "f41770550ab717086b2d0c805fef4b8f", 498176,
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_UNSUPPORTED,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
"private-eye", // Demo from the EU release (ES)
|
||||
"It uses different file format for the assest",
|
||||
"private-eye", // Demo from the EU release (ES)
|
||||
"Demo",
|
||||
AD_ENTRY2s("pvtdemo.ex_", "048f751acd7a0f1a87b20d6dc5229210", 497152,
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO | ADGF_UNSUPPORTED,
|
||||
ADGF_DEMO | ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
"private-eye", // EU release (FR)
|
||||
"It uses different file format for the assest",
|
||||
"Demo",
|
||||
AD_ENTRY2s("pvteye.ex_", "ae0dec43b2f54d45c8a1c93e97092141", 600576,
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_UNSUPPORTED,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
@ -139,13 +139,13 @@ static const ADGameDescription gameDescriptions[] = {
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
{
|
||||
"private-eye", // Demo from the EU release
|
||||
"private-eye", // Demo from the EU release (UK)
|
||||
"Demo",
|
||||
AD_ENTRY2s("Private Eye Demo", "", 284129,
|
||||
"bklynlgo.bmp", "1dfb703349a46f8ec183de107992b7f5", 33118),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO | ADGF_UNSUPPORTED,
|
||||
ADGF_DEMO | ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
/*
|
||||
|
@ -3,6 +3,7 @@ MODULE := engines/private
|
||||
MODULE_OBJS := \
|
||||
code.o \
|
||||
cursors.o \
|
||||
decompiler.o \
|
||||
funcs.o \
|
||||
grammar.o \
|
||||
lexer.o \
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "private/private.h"
|
||||
#include "private/tokens.h"
|
||||
#include "private/grammar.h"
|
||||
#include "private/decompiler.h"
|
||||
|
||||
namespace Private {
|
||||
|
||||
@ -122,40 +123,50 @@ void PrivateEngine::initializePath(const Common::FSNode &gamePath) {
|
||||
|
||||
Common::Error PrivateEngine::run() {
|
||||
|
||||
assert(_installerArchive.open("SUPPORT/ASSETS.Z"));
|
||||
Common::File *test = new Common::File();
|
||||
Common::SeekableReadStream *file = NULL;
|
||||
// if the full game is used
|
||||
if (!isDemo()) {
|
||||
assert(_installerArchive.hasFile("GAME.DAT"));
|
||||
file = _installerArchive.createReadStreamForMember("GAME.DAT");
|
||||
} else {
|
||||
// if the demo from archive.org is used
|
||||
if (_installerArchive.hasFile("GAME.TXT"))
|
||||
file = _installerArchive.createReadStreamForMember("GAME.TXT");
|
||||
|
||||
// if the demo from the full retail CDROM is used
|
||||
else if (_installerArchive.hasFile("DEMOGAME.DAT"))
|
||||
file = _installerArchive.createReadStreamForMember("DEMOGAME.DAT");
|
||||
else {
|
||||
Common::File *f = new Common::File();
|
||||
f->open("SUPPORT/GAME.DUMP");
|
||||
file = f;
|
||||
if (isDemo() && test->open("SUPPORT/ASSETS/DEMOGAME.WIN")) {
|
||||
file = (Common::SeekableReadStream *) test;
|
||||
} else {
|
||||
|
||||
assert(_installerArchive.open("SUPPORT/ASSETS.Z"));
|
||||
// if the full game is used
|
||||
if (!isDemo()) {
|
||||
assert(_installerArchive.hasFile("GAME.DAT"));
|
||||
file = _installerArchive.createReadStreamForMember("GAME.DAT");
|
||||
} else {
|
||||
// if the demo from archive.org is used
|
||||
if (_installerArchive.hasFile("GAME.TXT"))
|
||||
file = _installerArchive.createReadStreamForMember("GAME.TXT");
|
||||
|
||||
// if the demo from the full retail CDROM is used
|
||||
else if (_installerArchive.hasFile("DEMOGAME.DAT"))
|
||||
file = _installerArchive.createReadStreamForMember("DEMOGAME.DAT");
|
||||
else {
|
||||
debug("unknown version");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Read assets file
|
||||
assert(file != NULL);
|
||||
const int32 fileSize = file->size();
|
||||
const uint32 fileSize = file->size();
|
||||
char *buf = (char *)malloc(fileSize + 1);
|
||||
file->read(buf, fileSize);
|
||||
buf[fileSize] = '\0';
|
||||
|
||||
Decompiler decomp(buf, fileSize, false);
|
||||
free(buf);
|
||||
|
||||
buf = (char*) decomp.getResult().c_str();
|
||||
debug("%s", buf);
|
||||
|
||||
// Initialize stuff
|
||||
Gen::g_vm = new Gen::VM();
|
||||
Settings::g_setts = new Settings::SettingMaps();
|
||||
|
||||
initFuncs();
|
||||
parse(buf);
|
||||
free(buf);
|
||||
delete file;
|
||||
assert(maps.constants.size() > 0);
|
||||
|
||||
|
@ -118,6 +118,14 @@ Symbol *SymbolMaps::lookupRect(Common::String *n) {
|
||||
return lookup(*n, rects);
|
||||
}
|
||||
|
||||
Symbol *SymbolMaps::lookupVariable(Common::String *n) {
|
||||
debug("looking variable up %s", n->c_str());
|
||||
|
||||
assert(variables.contains(*n));
|
||||
return lookup(*n, variables);
|
||||
}
|
||||
|
||||
|
||||
/* lookup some name in some symbol table */
|
||||
Symbol *SymbolMaps::lookupName(const char *n) {
|
||||
debug("looking up %s", n);
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
NameList locationList;
|
||||
|
||||
Symbol *constant(int t, int d, const char *s);
|
||||
Symbol *lookupVariable(Common::String *n);
|
||||
Symbol *lookupRect(Common::String *n);
|
||||
Symbol *lookupName(const char *n);
|
||||
void installAll(const char *n);
|
||||
|
Loading…
Reference in New Issue
Block a user