mirror of
https://github.com/imaginaryPineapple/OpenRayman.git
synced 2024-10-19 22:47:37 -04:00
Add more sections to the dsb decompiler
This commit is contained in:
parent
ce39ade17f
commit
d2a4f6d5b5
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,6 @@ namespace openrayman
|
|||
{
|
||||
bool data_extractor::extract(const std::string& install_folder)
|
||||
{
|
||||
// TODO: is this how c++ works even?!?
|
||||
return
|
||||
check_prerequisites(install_folder) &&
|
||||
create_base() &&
|
||||
|
@ -78,6 +77,6 @@ namespace openrayman
|
|||
{
|
||||
std::cout << "[openrayman::data_extractor] Decompiling Game.dsb" << std::endl;
|
||||
dsb_decompiler decompiler;
|
||||
return decompiler.decompile_dsb(install_folder + "/Data/Game.dsb", m_backend_specifics.get_data_path() + "/games/rayman2/game.db");
|
||||
return decompiler.decompile_dsb(install_folder + "/Data/Game.dsb", m_backend_specifics.get_data_path() + "/games/rayman2/game.odsb", dsb_format::openrayman);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#include <data_extractor/dsb/dsb_decompiler.h>
|
||||
#include <data_extractor/data_decoder.h>
|
||||
#include <info.h>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
bool dsb_decompiler::decompile_dsb(const std::string& source, const std::string& target)
|
||||
bool dsb_decompiler::decompile_dsb(const std::string& source, const std::string& target, dsb_format fmt)
|
||||
{
|
||||
std::cout << "[openrayman::dsb_decompiler] Reading dsb " << source << " to " << target << std::endl;
|
||||
std::ifstream source_stream(source, std::ifstream::in | std::ifstream::binary);
|
||||
|
@ -28,12 +30,13 @@ namespace openrayman
|
|||
decoder.set_virtual_position(0);
|
||||
decoder.decode_array(buffer, length - 4);
|
||||
|
||||
// TODO: decompile DSB
|
||||
|
||||
std::ofstream target_stream(target, std::ofstream::out | std::ofstream::binary);
|
||||
if(target_stream.is_open())
|
||||
{
|
||||
decompile_ids(buffer, length - 4, target_stream);
|
||||
if(fmt == dsb_format::openrayman)
|
||||
decompile_sections(buffer, length - 4, target_stream);
|
||||
else
|
||||
target_stream.write(buffer, length - 4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +51,10 @@ namespace openrayman
|
|||
}
|
||||
};
|
||||
|
||||
// different "sections"?!?
|
||||
void dsb_decompiler::decompile_ids(char* source, std::size_t source_length, std::ofstream& target)
|
||||
void dsb_decompiler::decompile_sections(char* source, std::size_t source_length, std::ofstream& target)
|
||||
{
|
||||
target << "# Generated by OpenRayman " << openrayman::version << "\n";
|
||||
target << "\n";
|
||||
memorybuf streambuf(source, source + source_length);
|
||||
std::istream in(&streambuf);
|
||||
std::int32_t id;
|
||||
|
@ -58,23 +62,21 @@ namespace openrayman
|
|||
while(id != 0xFFFF)
|
||||
{
|
||||
|
||||
#define DECOMPILE_ID(id, name, function) \
|
||||
#define DECOMPILE_SECTION(id, name, function) \
|
||||
case (id): \
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_sections: decompiling " << std::hex << "0x" << (id) << " \"" << (name) << "\"" << std::endl; \
|
||||
target << "section " << (name) << "\n"; \
|
||||
target << "{\n"; \
|
||||
(function)(in, target); \
|
||||
target << "}\n\n"; \
|
||||
target << "\n"; \
|
||||
break;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
DECOMPILE_ID(0x00, "alloc", decompile_alloc);
|
||||
DECOMPILE_ID(0x1E, "levels", decompile_lvl_list);
|
||||
DECOMPILE_ID(0x28, "data_directories", decompile_data_directories);
|
||||
case 0x20:
|
||||
break;
|
||||
case 0x46:
|
||||
break;
|
||||
DECOMPILE_SECTION(0x00, "alloc", decompile_alloc);
|
||||
DECOMPILE_SECTION(0x1E, "levels", decompile_lvl_list);
|
||||
DECOMPILE_SECTION(0x28, "data_directories", decompile_data_directories);
|
||||
DECOMPILE_SECTION(0x20, "unknown_blob_0x20", decompile_unknown_blob_0x20);
|
||||
DECOMPILE_SECTION(0x46, "vignette", decompile_vignette);
|
||||
case 0x40:
|
||||
break;
|
||||
case 0x5A:
|
||||
|
@ -106,7 +108,7 @@ namespace openrayman
|
|||
std::int32_t a, b;
|
||||
source.read((char*)&a, sizeof(std::int32_t));
|
||||
source.read((char*)&b, sizeof(std::int32_t));
|
||||
target << std::to_string(a) << ", " << std::to_string(b) << ");\n";
|
||||
target << std::to_string(a) << ", " << std::to_string(b) << ")\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,7 +118,7 @@ namespace openrayman
|
|||
source.read((char*)&a, sizeof(std::int32_t));
|
||||
if(a == 0xFFFF)
|
||||
return;
|
||||
target << std::to_string(a) << ");\n";
|
||||
target << std::to_string(a) << ")\n";
|
||||
}
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
}
|
||||
|
@ -142,7 +144,7 @@ namespace openrayman
|
|||
target << c;
|
||||
source.read(&c, 1);
|
||||
}
|
||||
target << " \");";
|
||||
target << " \")";
|
||||
}
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
}
|
||||
|
@ -179,7 +181,115 @@ namespace openrayman
|
|||
source.read(str, str_length);
|
||||
// dir(name, path);
|
||||
if(dir != "")
|
||||
target << " dir(" << dir << ", \"" << str << "\");\n";
|
||||
target << " dir(" << dir << ", \"" << str << "\")\n";
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: what is this?!?
|
||||
// is this ever found?!?!
|
||||
void dsb_decompiler::decompile_unknown_blob_0x20(std::istream& source, std::ofstream& target)
|
||||
{
|
||||
std::uint32_t size;
|
||||
source.read((char*)&size, sizeof(std::uint32_t));
|
||||
target << " size(" << size << ")\n";
|
||||
std::int32_t id;
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
std::unordered_map<std::int32_t, int> encountered_ids;
|
||||
while(id != 0xFFFF)
|
||||
{
|
||||
if(encountered_ids.count(id) == 0)
|
||||
encountered_ids[id] = 0;
|
||||
encountered_ids[id]++;
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
}
|
||||
for(std::pair<std::int32_t, int> pair : encountered_ids)
|
||||
target << " id_encounter(" << std::hex << "0x" << pair.first << std::dec << ", " << pair.second << ")\n";
|
||||
}
|
||||
|
||||
// vignettes are basically loading screens
|
||||
// TODO: there are some .pgbs in rayman 2 /data
|
||||
void dsb_decompiler::decompile_vignette(std::istream& source, std::ofstream& target)
|
||||
{
|
||||
std::int32_t id;
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
while(id != 0xFFFF)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case 71:
|
||||
{
|
||||
target << " load_img(\"";
|
||||
char c;
|
||||
source.read(&c, 1);
|
||||
while(c != '\0')
|
||||
{
|
||||
target << c;
|
||||
source.read(&c, 1);
|
||||
}
|
||||
target << "\")\n";
|
||||
break;
|
||||
}
|
||||
case 72:
|
||||
{
|
||||
std::uint16_t length;
|
||||
source.read((char*)&length, sizeof(std::uint16_t));
|
||||
char str[length];
|
||||
source.read(str, length);
|
||||
target << " load_img(\"" << str << "\")\n";
|
||||
break;
|
||||
}
|
||||
case 75:
|
||||
{
|
||||
target << " display()\n";
|
||||
break;
|
||||
}
|
||||
case 76:
|
||||
case 77:
|
||||
{
|
||||
std::int32_t tmp;
|
||||
// skip these three
|
||||
// TODO
|
||||
for(int n = 0; n < 3; n++)
|
||||
source.read((char*)&tmp, sizeof(std::int32_t));
|
||||
std::uint8_t r, g, b, a;
|
||||
source.read((char*)&r, 1); source.read((char*)&g, 1); source.read((char*)&b, 1); source.read((char*)&a, 1);
|
||||
target << " color("
|
||||
<< (id == 76 ? "outline" : "inline")
|
||||
<< ", " << std::to_string(r)
|
||||
<< ", " << std::to_string(g)
|
||||
<< ", " << std::to_string(b)
|
||||
<< ", " << std::to_string(a)
|
||||
<< ")\n";
|
||||
break;
|
||||
}
|
||||
case 78:
|
||||
{
|
||||
char tmp[16 * 4];
|
||||
// four pairs of 16?!?!
|
||||
source.read(tmp, 16 * 4);
|
||||
break;
|
||||
}
|
||||
case 79:
|
||||
{
|
||||
char tmp[sizeof(std::int32_t) * 4];
|
||||
// four pairs of int32_t?!?!
|
||||
source.read(tmp, sizeof(std::int32_t) * 4);
|
||||
break;
|
||||
}
|
||||
case 80:
|
||||
{
|
||||
target << " add_bar()\n";
|
||||
break;
|
||||
}
|
||||
case 81:
|
||||
{
|
||||
std::int32_t max;
|
||||
source.read((char*)&max, sizeof(std::int32_t));
|
||||
target << " set_bar_max(" << max << ")\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
source.read((char*)&id, sizeof(std::int32_t));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,19 +8,39 @@
|
|||
|
||||
namespace openrayman
|
||||
{
|
||||
// Decodes and decompiles DSB files into database files.
|
||||
enum class dsb_format
|
||||
{
|
||||
// The default format.
|
||||
// This is a more human readable/editable format than the binary format used by Rayman 2.
|
||||
// This can be interpreted by the dsb engine.
|
||||
// Uses the extension .odsb
|
||||
openrayman,
|
||||
|
||||
// The format used by the Rayman 2: The Great Escape engine, decoded.
|
||||
// This is a binary format.
|
||||
// This can not be interpreted by OpenRayman.
|
||||
// The only operation that is performed by the dsb decompiler when this format is specified
|
||||
// is to decode the dsb.
|
||||
// Uses the extension .rdsb
|
||||
rayman2_decoded
|
||||
};
|
||||
|
||||
// Decodes and optionally decompiles DSB files.
|
||||
// This is all heavily adapted from Rayman2Lib's DSBDecompiler
|
||||
class dsb_decompiler
|
||||
{
|
||||
public:
|
||||
// Decompiles the specified DSB file into the target file.
|
||||
// Decodes and optionally decompiles the specified DSB file into the target file.
|
||||
// This function assumes that the source file exists and that the target location is accessible.
|
||||
// Returns true if the decompilation succeeded.
|
||||
bool decompile_dsb(const std::string& source, const std::string& target);
|
||||
// Returns true if the function succeeded.
|
||||
bool decompile_dsb(const std::string& source, const std::string& target, dsb_format fmt);
|
||||
private:
|
||||
void decompile_ids(char* source, std::size_t source_length, std::ofstream& target);
|
||||
void decompile_sections(char* source, std::size_t source_length, std::ofstream& target);
|
||||
void decompile_alloc(std::istream& source, std::ofstream& target);
|
||||
void decompile_lvl_list(std::istream& source, std::ofstream& target);
|
||||
void decompile_data_directories(std::istream& source, std::ofstream& target);
|
||||
void decompile_unknown_blob_0x20(std::istream& source, std::ofstream& target);
|
||||
void decompile_vignette(std::istream& source, std::ofstream& target);
|
||||
|
||||
data_decoder m_decoder;
|
||||
};
|
||||
|
|
58
src/main.cc
58
src/main.cc
|
@ -2,6 +2,7 @@
|
|||
#include <iostream>
|
||||
#include <info.h>
|
||||
#include <engine.h>
|
||||
#include <data_extractor/dsb/dsb_decompiler.h>
|
||||
|
||||
bool console_open = false;
|
||||
|
||||
|
@ -30,8 +31,7 @@ int main(int argc, char** argv)
|
|||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open();
|
||||
std::cout << "No game was specified." << std::endl;
|
||||
make_sure_console_open(); std::cout << "No game was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string game(argv[n]);
|
||||
|
@ -42,13 +42,59 @@ int main(int argc, char** argv)
|
|||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open();
|
||||
std::cout << "No install folder was specified." << std::endl;
|
||||
make_sure_console_open(); std::cout << "No install folder was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string install_folder(argv[n]);
|
||||
selected_install_folder = install_folder;
|
||||
}
|
||||
if(str == "--decompile")
|
||||
{
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No type was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string type(argv[n]);
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No path was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string path(argv[n]);
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No target was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string target(argv[n]);
|
||||
if(type == "odsb" || type == "rdsb")
|
||||
{
|
||||
openrayman::dsb_decompiler decompiler;
|
||||
if(decompiler.decompile_dsb(
|
||||
path,
|
||||
target,
|
||||
type == "odsb" ?
|
||||
openrayman::dsb_format::openrayman :
|
||||
openrayman::dsb_format::rayman2_decoded))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Operation failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
make_sure_console_open(); std::cout << "Invalid type specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
// Follow GNU format
|
||||
if(str == "--help")
|
||||
{
|
||||
|
@ -62,6 +108,10 @@ int main(int argc, char** argv)
|
|||
std::cout << " This is needed to ease modding support" << std::endl;
|
||||
std::cout << " This can also be done by starting the game without extracted data" << std::endl;
|
||||
std::cout << " In that case, you will get a directory picker" << std::endl;
|
||||
std::cout << " --decompile \"type\" \"path\" \"target\" Decompiles the specified file into target." << std::endl;
|
||||
std::cout << " Type can be any of:" << std::endl;
|
||||
std::cout << " \"odsb\": Creates an OpenRayman dsb file" << std::endl;
|
||||
std::cout << " \"rdsb\": Decodes a dsb file" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if(str == "--version")
|
||||
|
|
Loading…
Reference in a new issue