mirror of
https://github.com/imaginaryPineapple/OpenRayman.git
synced 2024-10-19 22:47:37 -04:00
Add basic DSB interpreter
We might need to replace this with something more sophisticated if some scripts use more flow control (e.g. if, while)
This commit is contained in:
parent
ff22900319
commit
ae50ccf7f6
4
.editorconfig
Normal file
4
.editorconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
[*.{cc, h, cpp, hpp}]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
|
@ -1,7 +1,7 @@
|
|||
project(OpenRayman)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "The type of build")
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "The type of build")
|
||||
set(USE_LIBRETRO OFF CACHE BOOL "If OpenRayman should be built as a libretro core (TODO)")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
This file attempts to document the Rayman 2: The Great Escape file formats and engine as best possible.
|
||||
|
||||
|
||||
You should probably check out https://drive.google.com/folderview?id=0Bzt0AW9Obi4-Tjg2MVAyLWNUVXM&usp=sharing, too.
|
||||
|
||||
|
||||
Note: OpenRayman could not have been possible without the amazing szymski on GitHub (https://github.com/szymski/Rayman2Lib), who seems to have reverse engineered the encoding algorithm used in Rayman 2 and the file formats that are used within the engine. Most of this information was scrapped together from the Rayman2Lib repository.
|
||||
|
||||
|
||||
|
@ -16,26 +19,6 @@ Note: some of this information may not be incorrect, as i have not verified any
|
|||
## Formats
|
||||
|
||||
|
||||
.cnt = archive
|
||||
|
||||
|
||||
.gf (graphics file?) (TODO: rayman2lib has both gf3 and gf?) = textures
|
||||
|
||||
|
||||
.sna = ? scripts / events / level / everything?!?! (TODO: figure out what rayman2lib is doing with seeking)
|
||||
|
||||
|
||||
.dat = pointers to file?!? file database?!?!
|
||||
|
||||
|
||||
.dsb = same?!? scripts?!?!
|
||||
|
||||
|
||||
.gpt = ?!?!?!?
|
||||
|
||||
|
||||
.bnm = probably sound files (based off of rayman2lib)
|
||||
|
||||
|
||||
## Decoding
|
||||
|
||||
|
|
5
src/.clang_complete
Normal file
5
src/.clang_complete
Normal file
|
@ -0,0 +1,5 @@
|
|||
-I.
|
||||
-I../lib/lodepng
|
||||
-I../lib/gl3w/include
|
||||
-I../lib/json/src
|
||||
-std=gnu++11
|
|
@ -1,5 +1,8 @@
|
|||
#include <data_extractor/data_extractor.h>
|
||||
#include <data_extractor/dsb/dsb_decompiler.h>
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
#include <dsb_interpreter/dsb_interpreter.h>
|
||||
#include <dsb_interpreter/instructions/all.h>
|
||||
#include <platform/message_box.h>
|
||||
#include <platform/file.h>
|
||||
#include <json.hpp>
|
||||
|
@ -10,14 +13,11 @@ namespace openrayman
|
|||
{
|
||||
bool data_extractor::extract(const std::string& install_folder)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AllocConsole();
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
#endif
|
||||
return
|
||||
check_prerequisites(install_folder) &&
|
||||
create_base() &&
|
||||
decompile_game_dsb(install_folder);
|
||||
decompile_game_dsb(install_folder) &&
|
||||
make_game_resources(install_folder);
|
||||
}
|
||||
|
||||
bool data_extractor::check_prerequisites(const std::string& install_folder)
|
||||
|
@ -83,4 +83,20 @@ namespace openrayman
|
|||
dsb_decompiler decompiler;
|
||||
return decompiler.decompile_dsb(install_folder + "/Data/Game.dsb", m_backend_specifics.get_data_path() + "/games/rayman2/game.odsb", dsb_format::openrayman);
|
||||
}
|
||||
|
||||
bool data_extractor::make_game_resources(const std::string& install_folder)
|
||||
{
|
||||
dsb_interpreter interpreter(m_backend_specifics.get_data_path() + "/games/rayman2/game.odsb");
|
||||
if(interpreter.success())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
dsb_instruction_invalid_dsb* error_reason = interpreter.get_instruction<dsb_instruction_invalid_dsb>
|
||||
(dsb_instruction_type::invalid_dsb);
|
||||
message_box::display("[openrayman::data_extractor] Error!", "The DSB interpreter failed to interpret the file game.odsb.\n\n" +
|
||||
std::to_string(error_reason->line) + " : " + std::to_string(error_reason->column) + "\n" +
|
||||
error_reason->error + "\n" +
|
||||
error_reason->trace, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ private:
|
|||
bool check_prerequisites(const std::string& install_folder);
|
||||
bool create_base();
|
||||
bool decompile_game_dsb(const std::string& install_folder);
|
||||
bool make_game_resources(const std::string& install_folder);
|
||||
|
||||
const backend_specifics& m_backend_specifics;
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <info.h>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <iomanip>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
|
@ -62,11 +63,11 @@ namespace openrayman
|
|||
while(!in.eof() && id != 0xFFFF)
|
||||
{
|
||||
|
||||
#define DECOMPILE_SECTION(id, name, function) \
|
||||
#define DECOMPILE_SECTION(id, name, function) \
|
||||
case (id): \
|
||||
{ \
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_sections: decompiling " \
|
||||
<< std::hex << "0x" << (id) \
|
||||
std::cout << "[openrayman::dsb_decompiler] Decompiling " \
|
||||
<< std::hex << "0x" << std::setfill('0') << std::setw(2) << (id) \
|
||||
<< " (decimal " << std::dec << id << ") \"" \
|
||||
<< (name) << "\"" << std::endl; \
|
||||
target << "section " << (name) << "\n"; \
|
||||
|
@ -90,7 +91,7 @@ namespace openrayman
|
|||
DECOMPILE_SECTION(0x5C, "load_sound_banks", decompile_load_sound_banks);
|
||||
default:
|
||||
{
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_sections: Encountered unknown id 0x"
|
||||
std::cout << "[openrayman::dsb_decompiler] Encountered unknown id 0x"
|
||||
<< std::hex << id
|
||||
<< " (decimal " << std::dec << id << ")"
|
||||
<< std::endl;
|
||||
|
@ -180,7 +181,7 @@ namespace openrayman
|
|||
source.read((char*)&str_length, sizeof(std::uint16_t));
|
||||
char str[str_length];
|
||||
source.read(str, str_length);
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_data_directories: " << std::hex << "0x" << id << ": " << str << std::endl;
|
||||
std::cout << "[openrayman::dsb_decompiler] Data directory " << std::hex << "0x" << id << ": " << str << std::endl;
|
||||
// dir(name, path);
|
||||
if(dir != "")
|
||||
target << " dir(" << dir << ", \"" << str << "\")\n";
|
||||
|
@ -192,7 +193,7 @@ namespace openrayman
|
|||
// is this ever found?!?!
|
||||
void dsb_decompiler::decompile_unknown_blob_0x20(std::istream& source, std::ofstream& target)
|
||||
{
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_unknown_blob_0x20: Warning! encountered 0x20" << std::endl;
|
||||
std::cout << "[openrayman::dsb_decompiler] Warning! encountered 0x20" << std::endl;
|
||||
std::uint32_t size;
|
||||
source.read((char*)&size, sizeof(std::uint32_t));
|
||||
target << " size(" << size << ")\n";
|
||||
|
@ -243,7 +244,7 @@ namespace openrayman
|
|||
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")
|
||||
<< (id == 76 ? "outline" : "inside")
|
||||
<< ", " << std::to_string(r)
|
||||
<< ", " << std::to_string(g)
|
||||
<< ", " << std::to_string(b)
|
||||
|
@ -311,7 +312,7 @@ namespace openrayman
|
|||
|
||||
void dsb_decompiler::decompile_unknown_blob_0x6e(std::istream& source, std::ofstream& target)
|
||||
{
|
||||
std::cout << "[openrayman::dsb_decompiler].decompile_unknown_blob_0x6e: Warning! encountered 0x6e" << std::endl;
|
||||
std::cout << "[openrayman::dsb_decompiler] Warning! encountered 0x6e" << std::endl;
|
||||
std::uint8_t tmp = 0x00;
|
||||
while(tmp != 0xFF)
|
||||
source.read((char*)&tmp, 1);
|
||||
|
|
|
@ -26,7 +26,8 @@ namespace openrayman
|
|||
};
|
||||
|
||||
// Decodes and optionally decompiles DSB files.
|
||||
// This is all heavily adapted from Rayman2Lib's DSBDecompiler
|
||||
// DSB files are compiled scripts, with different sections.
|
||||
// This is all heavily adapted from Rayman2Lib.
|
||||
class dsb_decompiler
|
||||
{
|
||||
public:
|
||||
|
|
217
src/dsb_interpreter/dsb_instruction.h
Normal file
217
src/dsb_interpreter/dsb_instruction.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
#ifndef DSB_INSTRUCTION_H
|
||||
#define DSB_INSTRUCTION_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
enum class dsb_instruction_type
|
||||
{
|
||||
// Special value used to specify that no instruction could be provided.
|
||||
none,
|
||||
|
||||
// This instruction implies that the DSB could not be interpreted for some reason.
|
||||
// It is paried with a dsb_instruction_invalid_dsb, which specifies a string that describes what went
|
||||
// wrong during interpretation, and at what line / column.
|
||||
// No instructions should follow or precede this one.
|
||||
invalid_dsb,
|
||||
|
||||
// This instruction specifies that a comment was specified in the DSB.
|
||||
// It is paried with a dsb_instruction_comment, which specifies the comment encountered.
|
||||
comment,
|
||||
|
||||
// This instruction implies the start of a new section in the DSB.
|
||||
// It is paired with a dsb_instruction_begin_section, which specifies what
|
||||
// type of section is starting.
|
||||
// An instruction of this type that starts a "none" section implies
|
||||
// the end of the instruction array.
|
||||
begin_section,
|
||||
|
||||
// This instruction sets a data directory to a path.
|
||||
// It is paried with a dsb_instruction_set_data_dir, which specifies what data directory to set
|
||||
// and which path to set it to.
|
||||
set_data_dir,
|
||||
|
||||
// This instruction sets a texture file id to an archive.
|
||||
// It is paried with a dsb_instruction_set_texture_file, which specifies what texture file id to set
|
||||
// and which archive to set it to.
|
||||
set_texture_file,
|
||||
|
||||
// This instruction loads a background image into the vignette.
|
||||
// This can contain "random" expression, in the format "Random<img, ?, ?, ...>".
|
||||
// We don't currently know how to interpret this, so we just use the first image.
|
||||
// Additionally, names can contain .bmp. Ignore this.
|
||||
// TODO: is this ok?!? probably
|
||||
// It is paired with a dsb_instruction_vignette_load_img, which specifies image file to load.
|
||||
vignette_load_img,
|
||||
|
||||
// This instruction sets one of several color values.
|
||||
// It is paried with a dsb_instruction_vignette_set_color, which specifies what id to set
|
||||
// and what color(s) to set.
|
||||
vignette_set_color,
|
||||
|
||||
// This instruction creates a bar with the current specifed colors.
|
||||
// It is paried with a dsb_instruction_vignette_create_bar, which specifies the position and size of
|
||||
// the vignette.
|
||||
vignette_create_bar,
|
||||
|
||||
// This instruction adds a bar to the vignette.
|
||||
// It is not paired with a class, as it doesn't need any additional values.
|
||||
vignette_add_bar,
|
||||
|
||||
// This instruction displays the vignette on the screen.
|
||||
// It is not paired with a class, as it doesn't need any additional values.
|
||||
vignette_display,
|
||||
|
||||
// This instruction adds a level.
|
||||
// It is paired with a dsb_instruction_level_add, which specifies what level to add.
|
||||
level_add
|
||||
};
|
||||
|
||||
inline std::string instruction_to_string(dsb_instruction_type instruction)
|
||||
{
|
||||
#define VALID_INSTRUCTION_TO(name) \
|
||||
if(instruction == dsb_instruction_type::name) \
|
||||
return #name;
|
||||
|
||||
VALID_INSTRUCTION_TO(invalid_dsb);
|
||||
VALID_INSTRUCTION_TO(comment);
|
||||
VALID_INSTRUCTION_TO(begin_section);
|
||||
VALID_INSTRUCTION_TO(set_data_dir);
|
||||
VALID_INSTRUCTION_TO(set_texture_file);
|
||||
VALID_INSTRUCTION_TO(vignette_load_img);
|
||||
VALID_INSTRUCTION_TO(vignette_set_color);
|
||||
VALID_INSTRUCTION_TO(vignette_create_bar);
|
||||
VALID_INSTRUCTION_TO(vignette_add_bar);
|
||||
VALID_INSTRUCTION_TO(vignette_display);
|
||||
VALID_INSTRUCTION_TO(level_add);
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
inline dsb_instruction_type string_to_instruction(const std::string& instruction)
|
||||
{
|
||||
#define VALID_INSTRUCTION_FROM(name) \
|
||||
if(instruction == #name) \
|
||||
return dsb_instruction_type::name;
|
||||
|
||||
VALID_INSTRUCTION_FROM(invalid_dsb);
|
||||
VALID_INSTRUCTION_FROM(comment);
|
||||
VALID_INSTRUCTION_FROM(begin_section);
|
||||
VALID_INSTRUCTION_FROM(set_data_dir);
|
||||
VALID_INSTRUCTION_FROM(set_texture_file);
|
||||
VALID_INSTRUCTION_FROM(vignette_load_img);
|
||||
VALID_INSTRUCTION_FROM(vignette_set_color);
|
||||
VALID_INSTRUCTION_FROM(vignette_create_bar);
|
||||
VALID_INSTRUCTION_FROM(vignette_add_bar);
|
||||
VALID_INSTRUCTION_FROM(vignette_display);
|
||||
VALID_INSTRUCTION_FROM(level_add);
|
||||
|
||||
return dsb_instruction_type::none;
|
||||
}
|
||||
|
||||
enum class dsb_section_type
|
||||
{
|
||||
// Special value used to specify that no section could be provided.
|
||||
none,
|
||||
|
||||
// Section to allocate values into slots.
|
||||
// This section is not present in a raw Rayman 2: The Great Escape .pgb.
|
||||
// Unused.
|
||||
alloc,
|
||||
|
||||
// Section to set data directories.
|
||||
// This is only used by the data extractor to find game data in a
|
||||
// valid Rayman 2: The Great Escape installation.
|
||||
data_directories,
|
||||
|
||||
// Section to set texture archives.
|
||||
// This is only used by the data extractor to find game data in a
|
||||
// valid Rayman 2: The Great Escape installation.
|
||||
texture_files,
|
||||
|
||||
// Section that builds a vignette.
|
||||
vignette,
|
||||
|
||||
// Unknown section.
|
||||
// Unused.
|
||||
unknown_blob_0x6e,
|
||||
|
||||
// Unknown section.
|
||||
// Unused.
|
||||
unknown_blob_0x20,
|
||||
|
||||
// Section that specifies what game option files to use.
|
||||
// Unused.
|
||||
game_options,
|
||||
|
||||
// Sections that adds levels.
|
||||
// This is only used by the data extractor to find game data in a
|
||||
// valid Rayman 2: The Great Escape installation.
|
||||
levels,
|
||||
|
||||
// Unknown section (for now).
|
||||
// Unused.
|
||||
sound_banks,
|
||||
|
||||
// Unknown section (for now).
|
||||
// Unused.
|
||||
load_sound_banks
|
||||
};
|
||||
|
||||
inline std::string section_to_string(dsb_section_type section)
|
||||
{
|
||||
#define VALID_SECTION_TO(name) \
|
||||
if(section == dsb_section_type::name) \
|
||||
return #name;
|
||||
|
||||
VALID_SECTION_TO(alloc);
|
||||
VALID_SECTION_TO(data_directories);
|
||||
VALID_SECTION_TO(texture_files);
|
||||
VALID_SECTION_TO(vignette);
|
||||
VALID_SECTION_TO(unknown_blob_0x6e);
|
||||
VALID_SECTION_TO(unknown_blob_0x20);
|
||||
VALID_SECTION_TO(game_options);
|
||||
VALID_SECTION_TO(levels);
|
||||
VALID_SECTION_TO(sound_banks);
|
||||
VALID_SECTION_TO(load_sound_banks);
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
inline dsb_section_type string_to_section(const std::string& section)
|
||||
{
|
||||
#define VALID_SECTION_FROM(name) \
|
||||
if(section == #name) \
|
||||
return dsb_section_type::name;
|
||||
|
||||
VALID_SECTION_FROM(alloc);
|
||||
VALID_SECTION_FROM(data_directories);
|
||||
VALID_SECTION_FROM(texture_files);
|
||||
VALID_SECTION_FROM(vignette);
|
||||
VALID_SECTION_FROM(unknown_blob_0x6e);
|
||||
VALID_SECTION_FROM(unknown_blob_0x20);
|
||||
VALID_SECTION_FROM(game_options);
|
||||
VALID_SECTION_FROM(levels);
|
||||
VALID_SECTION_FROM(sound_banks);
|
||||
VALID_SECTION_FROM(load_sound_banks);
|
||||
|
||||
return dsb_section_type::none;
|
||||
}
|
||||
|
||||
struct dsb_instruction
|
||||
{
|
||||
dsb_instruction(dsb_instruction_type type) :
|
||||
type(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// The type of instruction that this class holds.
|
||||
// The class should be cast via static_cast<dsb_instruction_?> or similar.
|
||||
dsb_instruction_type type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
127
src/dsb_interpreter/dsb_interpreter.cc
Normal file
127
src/dsb_interpreter/dsb_interpreter.cc
Normal file
|
@ -0,0 +1,127 @@
|
|||
#include <dsb_interpreter/dsb_interpreter.h>
|
||||
#include <dsb_interpreter/dsb_interpreter_string_utils.h>
|
||||
#include <dsb_interpreter/instructions/all.h>
|
||||
#include <platform/file.h>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
dsb_interpreter::dsb_interpreter(const std::string& odsb_path)
|
||||
{
|
||||
std::ifstream stream(file::fix_string(odsb_path), std::ifstream::in);
|
||||
if(!stream.is_open())
|
||||
{
|
||||
set_error(0, 0, "The file \"" + odsb_path + "\" does not exist.", dsb_section_type::none, "dsb_interpreter::dsb_interpreter (constructor)");
|
||||
return;
|
||||
}
|
||||
interpret_sections(stream);
|
||||
}
|
||||
|
||||
void dsb_interpreter::set_error(std::size_t line, std::size_t column, const std::string& error, dsb_section_type current_section, const std::string& function)
|
||||
{
|
||||
std::stringstream trace;
|
||||
trace << "Occured when section was: " << std::hex << "0x" << std::setfill('0') << std::setw(2) << (int)current_section << " (" << section_to_string(current_section) << ")" << "\n";
|
||||
trace << "Originated from function: " << function;
|
||||
m_interpreted_dsb.clear();
|
||||
m_interpreted_dsb.push_back(new dsb_instruction_invalid_dsb(line, column, error, trace.str()));
|
||||
}
|
||||
|
||||
void dsb_interpreter::interpret_sections(std::ifstream& stream)
|
||||
{
|
||||
dsb_section_type current_section = dsb_section_type::none;
|
||||
std::string line;
|
||||
std::size_t line_n = 0;
|
||||
while(std::getline(stream, line))
|
||||
{
|
||||
std::size_t n = 0;
|
||||
n += skip_whitespace(line, n);
|
||||
// if the string wasn't all whitespace
|
||||
if(line.length() > 0 && n != line.length() - 1)
|
||||
{
|
||||
bool comment = false;
|
||||
if(line[n] == '#')
|
||||
{
|
||||
n++;
|
||||
n += skip_whitespace(line, n);
|
||||
comment = true;
|
||||
}
|
||||
if(comment)
|
||||
{
|
||||
std::string comment_string = read_until_end(line, n);
|
||||
if(comment_string.length() > 0)
|
||||
m_interpreted_dsb.push_back(new dsb_instruction_comment(line_n, comment_string));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(read_ahead_match(line, n, "section"))
|
||||
{
|
||||
n += sizeof("section");
|
||||
n += skip_whitespace(line, n);
|
||||
std::string section = read_until_end(line, n);
|
||||
dsb_section_type new_section = string_to_section(section);
|
||||
|
||||
if(new_section == dsb_section_type::none)
|
||||
{
|
||||
set_error(line_n, n, "Invalid syntax (expected section type, got \"" + section + "\").", current_section, "dsb_interpreter::interpret_sections");
|
||||
return;
|
||||
}
|
||||
|
||||
m_interpreted_dsb.push_back(new dsb_instruction_begin_section(current_section, new_section));
|
||||
current_section = new_section;
|
||||
}
|
||||
else if(current_section == dsb_section_type::none)
|
||||
{
|
||||
set_error(line_n, n, "Invalid syntax (expected section, got \"" + read_until_whitespace(line, n) + "\").", current_section, "dsb_interpreter::interpret_sections");
|
||||
return;
|
||||
}
|
||||
else
|
||||
interpret_line(current_section, line, n, line_n);
|
||||
}
|
||||
}
|
||||
line_n++;
|
||||
}
|
||||
// end of instruction array
|
||||
if(m_interpreted_dsb.size() == 0)
|
||||
set_error(0, 0, "No valid instructions could be interpreted from the specified file.", current_section, "dsb_interpreter::interpret_sections");
|
||||
else
|
||||
m_interpreted_dsb.push_back(new dsb_instruction_begin_section(current_section, dsb_section_type::none));
|
||||
}
|
||||
|
||||
void dsb_interpreter::interpret_line(dsb_section_type current_section, const std::string& line, std::size_t statement_begins_at, std::size_t line_n)
|
||||
{
|
||||
std::size_t n = statement_begins_at;
|
||||
std::string function_name = read_until_char(line, n, '(');
|
||||
n += function_name.length() + 1;
|
||||
std::vector<std::string> function_args;
|
||||
n += skip_whitespace(line, n);
|
||||
std::string arg = "";
|
||||
while(n < line.length())
|
||||
{
|
||||
if(line[n] == '"')
|
||||
{
|
||||
arg = read_quote_escaped_string(line, n);
|
||||
n += arg.length() + 1;
|
||||
}
|
||||
else if(line[n] != ',' && line[n] != ')')
|
||||
arg += line[n];
|
||||
if(line[n] == ',')
|
||||
{
|
||||
function_args.push_back(arg);
|
||||
arg = "";
|
||||
n++;
|
||||
n += skip_whitespace(line, n);
|
||||
}
|
||||
else if(line[n] == ')')
|
||||
break;
|
||||
else
|
||||
n++;
|
||||
}
|
||||
if(arg.length() > 0)
|
||||
function_args.push_back(arg);
|
||||
std::cout << "[openrayman::dsb_interpreter] Function: \"" << function_name << "\", " << function_args.size() << std::endl;
|
||||
for(const std::string& str : function_args)
|
||||
std::cout << " Argument: \"" << str << "\"" << std::endl;
|
||||
}
|
||||
}
|
86
src/dsb_interpreter/dsb_interpreter.h
Normal file
86
src/dsb_interpreter/dsb_interpreter.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
#ifndef DSB_INTERPRETER_H
|
||||
#define DSB_INTERPRETER_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
// DSB interpreter.
|
||||
// Builds an array of instructions from a valid odsb file.
|
||||
class dsb_interpreter
|
||||
{
|
||||
public:
|
||||
dsb_interpreter(const std::string& odsb_path);
|
||||
|
||||
~dsb_interpreter()
|
||||
{
|
||||
for(dsb_instruction* instruction : m_interpreted_dsb)
|
||||
delete instruction;
|
||||
}
|
||||
|
||||
// If this DSB was interpreted successfully.
|
||||
inline bool success() const
|
||||
{
|
||||
return section_count(dsb_instruction_type::invalid_dsb) == 0;
|
||||
}
|
||||
|
||||
// Returns the number of times that the specified section type occurs in this DSB.
|
||||
inline std::size_t section_count(dsb_instruction_type type) const
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for(dsb_instruction* instruction : m_interpreted_dsb)
|
||||
{
|
||||
if(instruction->type == type)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Returns the first instance of the specified instruction type, or nullptr if one doesn't exist.
|
||||
template<typename T>
|
||||
inline T* get_instruction(dsb_instruction_type type) const
|
||||
{
|
||||
for(dsb_instruction* instruction : m_interpreted_dsb)
|
||||
{
|
||||
if(instruction->type == type)
|
||||
return static_cast<T*>(instruction);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns all instances of the specified instruction type.
|
||||
template<typename T>
|
||||
inline std::vector<T*> get_instructions(dsb_instruction_type type) const
|
||||
{
|
||||
std::vector<T*> values;
|
||||
for(dsb_instruction* instruction : m_interpreted_dsb)
|
||||
{
|
||||
if(instruction->type == type)
|
||||
values.push_back(static_cast<T*>(instruction));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// Returns a reference to the raw instruction array.
|
||||
// This can be manually searched and interpreted.
|
||||
inline const std::vector<dsb_instruction*>& get_complete_instruction_array() const
|
||||
{
|
||||
return m_interpreted_dsb;
|
||||
}
|
||||
private:
|
||||
void interpret_sections(std::ifstream& stream);
|
||||
void interpret_line(dsb_section_type current_section, const std::string& line, std::size_t statement_begins_at, std::size_t line_n);
|
||||
|
||||
// Sets the error at the top of the dsb instruction array.
|
||||
void set_error(std::size_t line, std::size_t column, const std::string& error, dsb_section_type current_section, const std::string& function);
|
||||
|
||||
std::vector<dsb_instruction*> m_interpreted_dsb;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
88
src/dsb_interpreter/dsb_interpreter_debugger.cc
Normal file
88
src/dsb_interpreter/dsb_interpreter_debugger.cc
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include <dsb_interpreter/dsb_interpreter_debugger.h>
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
#include <dsb_interpreter/instructions/all.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
void dsb_interpreter_debugger::print_summary() const
|
||||
{
|
||||
if(m_interpreter.success())
|
||||
{
|
||||
std::cout << std::endl << "DSB interpreted -> "
|
||||
<< m_interpreter.get_complete_instruction_array().size() << " instructions emitted" << std::endl << std::endl;
|
||||
for(dsb_instruction* instruction : m_interpreter.get_complete_instruction_array())
|
||||
{
|
||||
std::cout << " dsb_instruction_type::" << instruction_to_string(instruction->type) << std::endl;
|
||||
switch(instruction->type)
|
||||
{
|
||||
case dsb_instruction_type::comment:
|
||||
{
|
||||
dsb_instruction_comment* cast = static_cast<dsb_instruction_comment*>(instruction);
|
||||
std::cout << " comment -> \"" << cast->comment << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::begin_section:
|
||||
{
|
||||
dsb_instruction_begin_section* cast = static_cast<dsb_instruction_begin_section*>(instruction);
|
||||
std::cout << " end -> dsb_section_type::" << section_to_string(cast->end) << std::endl;
|
||||
std::cout << " begin -> dsb_section_type::" << section_to_string(cast->begin) << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::set_data_dir:
|
||||
{
|
||||
dsb_instruction_set_data_dir* cast = static_cast<dsb_instruction_set_data_dir*>(instruction);
|
||||
std::cout << " directory -> dsb_data_directory::" << data_directory_to_string(cast->directory) << std::endl;
|
||||
std::cout << " path -> \"" << cast->path << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::set_texture_file:
|
||||
{
|
||||
dsb_instruction_set_texture_file* cast = static_cast<dsb_instruction_set_texture_file*>(instruction);
|
||||
std::cout << " id -> dsb_texture_file_id::" << (cast->id == dsb_texture_file_id::vignettes ? "vignettes" : "textures") << std::endl;
|
||||
std::cout << " archive -> \"" << cast->archive << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::vignette_load_img:
|
||||
{
|
||||
dsb_instruction_vignette_load_img* cast = static_cast<dsb_instruction_vignette_load_img*>(instruction);
|
||||
std::cout << " image -> \"" << cast->image << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::vignette_set_color:
|
||||
{
|
||||
dsb_instruction_vignette_set_color* cast = static_cast<dsb_instruction_vignette_set_color*>(instruction);
|
||||
std::cout << " id -> dsb_vignette_id::" << vignette_id_to_string(cast->id) << std::endl;
|
||||
std::cout << " pair1 -> [" << cast->r << ", " << cast->g << ", " << cast->b << ", " << cast->a << "]" << std::endl;
|
||||
std::cout << " pair2 -> [" << cast->pair2_r << ", " << cast->pair2_g << ", " << cast->pair2_b << ", " << cast->pair2_a << "]" << std::endl;
|
||||
std::cout << " pair3 -> [" << cast->pair3_r << ", " << cast->pair3_g << ", " << cast->pair3_b << ", " << cast->pair3_a << "]" << std::endl;
|
||||
std::cout << " pair4 -> [" << cast->pair4_r << ", " << cast->pair4_g << ", " << cast->pair4_b << ", " << cast->pair4_a << "]" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::vignette_create_bar:
|
||||
{
|
||||
dsb_instruction_vignette_create_bar* cast = static_cast<dsb_instruction_vignette_create_bar*>(instruction);
|
||||
std::cout << " pos -> [" << cast->x << ", " << cast->y << ", " << cast->w << ", " << cast->h << "]" << std::endl;
|
||||
break;
|
||||
}
|
||||
case dsb_instruction_type::level_add:
|
||||
{
|
||||
dsb_instruction_level_add* cast = static_cast<dsb_instruction_level_add*>(instruction);
|
||||
std::cout << " level -> \"" << cast->level << "\"" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Operation failed" << std::endl;
|
||||
dsb_instruction_invalid_dsb* error_reason = m_interpreter.get_instruction<dsb_instruction_invalid_dsb>
|
||||
(dsb_instruction_type::invalid_dsb);
|
||||
std::cout << "At " << error_reason->line << " : " << error_reason->column << std::endl;
|
||||
std::cout << error_reason->error << std::endl;
|
||||
std::cout << error_reason->trace << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
23
src/dsb_interpreter/dsb_interpreter_debugger.h
Normal file
23
src/dsb_interpreter/dsb_interpreter_debugger.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef DSB_INTERPRETER_DEBUGGER_H
|
||||
#define DSB_INTERPRETER_DEBUGGER_H
|
||||
|
||||
#include <dsb_interpreter/dsb_interpreter.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
// Used for printing some information about an interpreted DSB.
|
||||
class dsb_interpreter_debugger
|
||||
{
|
||||
public:
|
||||
dsb_interpreter_debugger(const dsb_interpreter& interpreter) :
|
||||
m_interpreter(interpreter)
|
||||
{
|
||||
}
|
||||
|
||||
void print_summary() const;
|
||||
private:
|
||||
const dsb_interpreter& m_interpreter;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
83
src/dsb_interpreter/dsb_interpreter_string_utils.h
Normal file
83
src/dsb_interpreter/dsb_interpreter_string_utils.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef DSB_INTERPRETER_STRING_UTILS_H
|
||||
#define DSB_INTERPRETER_STRING_UTILS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
// Reads ahead in the string and returns true if a match is found.
|
||||
bool read_ahead_match(const std::string& source, std::size_t begin_at, const std::string& match)
|
||||
{
|
||||
if((int)source.length() - (int)begin_at + (int)match.length() < 0)
|
||||
return false;
|
||||
for(std::size_t n = 0; n < match.length(); n++)
|
||||
{
|
||||
if(source[n + begin_at] != match[n])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the difference needed to skip whitespace from the point "at".
|
||||
std::size_t skip_whitespace(const std::string& source, std::size_t at)
|
||||
{
|
||||
std::size_t new_at = at;
|
||||
while((source[new_at] == ' ' || source[new_at] == '\t') && new_at < source.length())
|
||||
new_at++;
|
||||
return new_at - at;
|
||||
}
|
||||
|
||||
// Returns the string in the range from point "at" to whitespace.
|
||||
std::string read_until_whitespace(const std::string& source, std::size_t at)
|
||||
{
|
||||
std::string result = "";
|
||||
while((source[at] != ' ' && source[at] != '\t') && at < source.length())
|
||||
{
|
||||
result += source[at];
|
||||
at++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the string from point "at" until the specified character is found.
|
||||
std::string read_until_char(const std::string& source, std::size_t at, char until)
|
||||
{
|
||||
std::string result = "";
|
||||
while((source[at] != until) && at < source.length())
|
||||
{
|
||||
result += source[at];
|
||||
at++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the string in the range from point "at" to end.
|
||||
std::string read_until_end(const std::string& source, std::size_t at)
|
||||
{
|
||||
std::string result = "";
|
||||
while(at < source.length())
|
||||
{
|
||||
result += source[at];
|
||||
at++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Reads a quote escaped string that starts at point "at".
|
||||
std::string read_quote_escaped_string(const std::string& source, std::size_t at)
|
||||
{
|
||||
std::string result = "";
|
||||
at++;
|
||||
bool next_escaped = false;
|
||||
while(at < source.length())
|
||||
{
|
||||
if(source[at] == '"')
|
||||
break;
|
||||
result += source[at];
|
||||
at++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
9
src/dsb_interpreter/instructions/all.h
Normal file
9
src/dsb_interpreter/instructions/all.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <dsb_interpreter/instructions/begin_section/dsb_instruction_begin_section.h>
|
||||
#include <dsb_interpreter/instructions/comment/dsb_instruction_comment.h>
|
||||
#include <dsb_interpreter/instructions/invalid_dsb/dsb_instruction_invalid_dsb.h>
|
||||
#include <dsb_interpreter/instructions/level_add/dsb_instruction_level_add.h>
|
||||
#include <dsb_interpreter/instructions/set_data_dir/dsb_instruction_set_data_dir.h>
|
||||
#include <dsb_interpreter/instructions/set_texture_file/dsb_instruction_set_texture_file.h>
|
||||
#include <dsb_interpreter/instructions/vignette/create_bar/dsb_instruction_vignette_create_bar.h>
|
||||
#include <dsb_interpreter/instructions/vignette/load_img/dsb_instruction_vignette_load_img.h>
|
||||
#include <dsb_interpreter/instructions/vignette/set_color/dsb_instruction_vignette_set_color.h>
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef DSB_INSTRUCTION_BEGIN_SECTION_H
|
||||
#define DSB_INSTRUCTION_BEGIN_SECTION_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_begin_section : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_begin_section(dsb_section_type end, dsb_section_type begin) :
|
||||
dsb_instruction(dsb_instruction_type::begin_section),
|
||||
end(end), begin(begin)
|
||||
{
|
||||
}
|
||||
|
||||
// The previous section that is ending.
|
||||
dsb_section_type end;
|
||||
|
||||
// The section that is following this instruction.
|
||||
dsb_section_type begin;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef DSB_INSTRUCTION_COMMENT_H
|
||||
#define DSB_INSTRUCTION_COMMENT_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_comment : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_comment(std::size_t line, const std::string& comment) :
|
||||
dsb_instruction(dsb_instruction_type::comment),
|
||||
line(line), comment(comment)
|
||||
{
|
||||
}
|
||||
|
||||
// The line that the interpreter encountered the comment.
|
||||
std::size_t line;
|
||||
|
||||
// The user specified comment that was found.
|
||||
std::string comment;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef DSB_INSTRUCTION_INVALID_DSB_H
|
||||
#define DSB_INSTRUCTION_INVALID_DSB_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_invalid_dsb : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_invalid_dsb(std::size_t line, std::size_t column, const std::string& error, const std::string& trace) :
|
||||
dsb_instruction(dsb_instruction_type::invalid_dsb),
|
||||
line(line), column(column), error(error), trace(trace)
|
||||
{
|
||||
}
|
||||
|
||||
// The line that the interpreter encountered the error.
|
||||
std::size_t line;
|
||||
|
||||
// The column that the interpreter encountered the error.
|
||||
std::size_t column;
|
||||
|
||||
// The error that the interpreter encountered.
|
||||
std::string error;
|
||||
|
||||
// Trace info about the error.
|
||||
std::string trace;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef DSB_INSTRUCTION_LEVEL_ADD_H
|
||||
#define DSB_INSTRUCTION_LEVEL_ADD_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_level_add : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_level_add(const std::string& level) :
|
||||
dsb_instruction(dsb_instruction_type::level_add),
|
||||
level(level)
|
||||
{
|
||||
}
|
||||
|
||||
// The level name, relative to the levels folder.
|
||||
std::string level;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,92 @@
|
|||
#ifndef DSB_INSTRUCTION_SET_DATA_DIR_H
|
||||
#define DSB_INSTRUCTION_SET_DATA_DIR_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
enum class dsb_data_directory
|
||||
{
|
||||
// Special value used to specify that no directory could be provided.
|
||||
none,
|
||||
|
||||
// Specifies the directory where engine dlls are located.
|
||||
dll,
|
||||
|
||||
// Specifies the root of game data.
|
||||
// This seems to be incorrect in Rayman 2?!?
|
||||
root,
|
||||
|
||||
// Specifies the directory where data related to the game world is located.
|
||||
world,
|
||||
|
||||
// Specifies the directory where levels are located.
|
||||
levels,
|
||||
|
||||
// Specifies the directory where sound files are located.
|
||||
sound,
|
||||
|
||||
// Specifies the directory where save files are located.
|
||||
saves,
|
||||
|
||||
// Specifies the directory where "vignettes" are located.
|
||||
// Vignettes are 2D textures that are used in loading screens.
|
||||
vignette,
|
||||
|
||||
// Specifies the directory where user options are saved.
|
||||
options
|
||||
};
|
||||
|
||||
inline std::string data_directory_to_string(dsb_data_directory dir)
|
||||
{
|
||||
#define VALID_DIRECTORY_TO(name) \
|
||||
if(dir == dsb_data_directory::name) \
|
||||
return #name;
|
||||
|
||||
VALID_DIRECTORY_TO(dll);
|
||||
VALID_DIRECTORY_TO(root);
|
||||
VALID_DIRECTORY_TO(world);
|
||||
VALID_DIRECTORY_TO(levels);
|
||||
VALID_DIRECTORY_TO(sound);
|
||||
VALID_DIRECTORY_TO(saves);
|
||||
VALID_DIRECTORY_TO(vignette);
|
||||
VALID_DIRECTORY_TO(options);
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
inline dsb_data_directory string_to_data_directory(const std::string& dir)
|
||||
{
|
||||
#define VALID_DIRECTORY_FROM(name) \
|
||||
if(dir == #name) \
|
||||
return dsb_data_directory::name;
|
||||
|
||||
VALID_DIRECTORY_FROM(dll);
|
||||
VALID_DIRECTORY_FROM(root);
|
||||
VALID_DIRECTORY_FROM(world);
|
||||
VALID_DIRECTORY_FROM(levels);
|
||||
VALID_DIRECTORY_FROM(sound);
|
||||
VALID_DIRECTORY_FROM(saves);
|
||||
VALID_DIRECTORY_FROM(vignette);
|
||||
VALID_DIRECTORY_FROM(options);
|
||||
|
||||
return dsb_data_directory::none;
|
||||
}
|
||||
|
||||
struct dsb_instruction_set_data_dir : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_set_data_dir(dsb_data_directory directory, const std::string& path) :
|
||||
dsb_instruction(dsb_instruction_type::set_data_dir),
|
||||
directory(directory), path(path)
|
||||
{
|
||||
}
|
||||
|
||||
// The data directory to set.
|
||||
dsb_data_directory directory;
|
||||
|
||||
// The path which it should be set to.
|
||||
std::string path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef DSB_INSTRUCTION_SET_TEXTURE_FILE_H
|
||||
#define DSB_INSTRUCTION_SET_TEXTURE_FILE_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
enum class dsb_texture_file_id
|
||||
{
|
||||
// Stores vignettes.
|
||||
vignettes,
|
||||
|
||||
// Stores all other (world, etc) textures.
|
||||
textures
|
||||
};
|
||||
|
||||
struct dsb_instruction_set_texture_file : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_set_texture_file(dsb_texture_file_id id, const std::string& archive) :
|
||||
dsb_instruction(dsb_instruction_type::set_texture_file),
|
||||
id(id), archive(archive)
|
||||
{
|
||||
}
|
||||
|
||||
// The texture file to set.
|
||||
dsb_texture_file_id id;
|
||||
|
||||
// The archive which it should be set to.
|
||||
std::string archive;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef DSB_INSTRUCTION_VIGNETTE_CREATE_BAR_H
|
||||
#define DSB_INSTRUCTION_VIGNETTE_CREATE_BAR_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_vignette_create_bar : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_vignette_create_bar(int x, int y, int w, int h) :
|
||||
dsb_instruction(dsb_instruction_type::vignette_create_bar),
|
||||
x(x), y(y), w(w), h(h)
|
||||
{
|
||||
}
|
||||
|
||||
int x, y, w, h;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef DSB_INSTRUCTION_VIGNETTE_LOAD_IMG_H
|
||||
#define DSB_INSTRUCTION_VIGNETTE_LOAD_IMG_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
struct dsb_instruction_vignette_load_img : public dsb_instruction
|
||||
{
|
||||
dsb_instruction_vignette_load_img(const std::string& image) :
|
||||
dsb_instruction(dsb_instruction_type::vignette_load_img),
|
||||
image(image)
|
||||
{
|
||||
}
|
||||
|
||||
std::string image;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||
#ifndef DSB_INSTRUCTION_VIGNETTE_SET_COLOR_H
|
||||
#define DSB_INSTRUCTION_VIGNETTE_SET_COLOR_H
|
||||
|
||||
#include <dsb_interpreter/dsb_instruction.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace openrayman
|
||||
{
|
||||
enum class dsb_vignette_id
|
||||
{
|
||||
none,
|
||||
// TODO: document these
|
||||
outline,
|
||||
inside,
|
||||
bar
|
||||
};
|
||||
|
||||
inline std::string vignette_id_to_string(dsb_vignette_id id)
|
||||
{
|
||||
#define VALID_ID_TO(name) \
|
||||
if(id == dsb_vignette_id::name) \
|
||||
return #name;
|
||||
|
||||
VALID_ID_TO(outline);
|
||||
VALID_ID_TO(inside);
|
||||
VALID_ID_TO(bar);
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
inline dsb_vignette_id string_to_vignette_id(const std::string& id)
|
||||
{
|
||||
#define VALID_ID_FROM(name) \
|
||||
if(id == #name) \
|
||||
return dsb_vignette_id::name;
|
||||
|
||||
VALID_ID_FROM(outline);
|
||||
VALID_ID_FROM(inside);
|
||||
VALID_ID_FROM(bar);
|
||||
|
||||
return dsb_vignette_id::none;
|
||||
}
|
||||
|
||||
struct dsb_instruction_vignette_set_color : public dsb_instruction
|
||||
{
|
||||
// TODO: refactor this..........
|
||||
// ugh
|
||||
dsb_instruction_vignette_set_color(dsb_vignette_id id,
|
||||
std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) :
|
||||
dsb_instruction(dsb_instruction_type::vignette_set_color),
|
||||
r(r), g(g), b(b), a(a)
|
||||
{
|
||||
}
|
||||
|
||||
// The id of the color to set.
|
||||
dsb_vignette_id id;
|
||||
|
||||
// The first pair of colors.
|
||||
std::uint8_t r, g, b, a;
|
||||
|
||||
// The second pair of colors.
|
||||
// Only used when id is bar, to specify gradient.
|
||||
std::uint8_t pair2_r, pair2_g, pair2_b, pair2_a;
|
||||
|
||||
// The third pair of colors.
|
||||
// Only used when id is bar, to specify gradient.
|
||||
std::uint8_t pair3_r, pair3_g, pair3_b, pair3_a;
|
||||
|
||||
// The fourth pair of colors.
|
||||
// Only used when id is bar, to specify gradient.
|
||||
std::uint8_t pair4_r, pair4_g, pair4_b, pair4_a;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -103,18 +103,18 @@ namespace openrayman
|
|||
if(m_current_input.command(input_command::toggle_fullscreen) && !m_last_input.command(input_command::toggle_fullscreen))
|
||||
m_config.fullscreen = !m_config.fullscreen;
|
||||
|
||||
std::cout << "Update: " << m_current_delta_time * 1000 << "ms, " << m_total_frames << std::endl;
|
||||
std::cout << "[openrayman::engine] Update: " << m_current_delta_time * 1000 << "ms, " << m_total_frames << std::endl;
|
||||
m_total_frames++;
|
||||
m_accumulated_frames_fps++;
|
||||
if(m_accumulated_time_fps >= 1)
|
||||
{
|
||||
m_fps = m_accumulated_frames_fps;
|
||||
std::cout << "FPS: " << m_fps << std::endl;
|
||||
std::cout << "[openrayman::engine] FPS: " << m_fps << std::endl;
|
||||
m_accumulated_time_fps = m_accumulated_frames_fps = 0;
|
||||
}
|
||||
while(m_accumulated_time_fixed >= 1 / 60.0)
|
||||
{
|
||||
std::cout << "Fixed update: " << m_total_fixed_updates << std::endl;
|
||||
std::cout << "[openrayman::engine] Fixed update: " << m_total_fixed_updates << std::endl;
|
||||
m_total_fixed_updates++;
|
||||
m_accumulated_time_fixed -= 1 / 60.0;
|
||||
}
|
||||
|
|
80
src/main.cc
80
src/main.cc
|
@ -3,6 +3,8 @@
|
|||
#include <info.h>
|
||||
#include <engine.h>
|
||||
#include <data_extractor/dsb/dsb_decompiler.h>
|
||||
#include <dsb_interpreter/dsb_interpreter.h>
|
||||
#include <dsb_interpreter/dsb_interpreter_debugger.h>
|
||||
|
||||
bool console_open = false;
|
||||
|
||||
|
@ -19,6 +21,12 @@ void make_sure_console_open()
|
|||
#endif
|
||||
}
|
||||
|
||||
int fail_and_print(const std::string& msg)
|
||||
{
|
||||
make_sure_console_open(); std::cout << msg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::string selected_game = "";
|
||||
|
@ -30,10 +38,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No game was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return fail_and_print("No game was specified");;
|
||||
std::string game(argv[n]);
|
||||
selected_game = game;
|
||||
}
|
||||
|
@ -41,59 +46,61 @@ int main(int argc, char** argv)
|
|||
{
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No install folder was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return fail_and_print("No install folder was specified");
|
||||
std::string install_folder(argv[n]);
|
||||
selected_install_folder = install_folder;
|
||||
}
|
||||
if(str == "--decompile")
|
||||
if(str == "--convert-to")
|
||||
{
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No type was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string type(argv[n]);
|
||||
return fail_and_print("No format was specified");
|
||||
std::string format(argv[n]);
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No path was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return fail_and_print("No path was specified");
|
||||
std::string path(argv[n]);
|
||||
n++;
|
||||
if(n >= argc)
|
||||
{
|
||||
make_sure_console_open(); std::cout << "No target was specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return fail_and_print("No target was specified");
|
||||
std::string target(argv[n]);
|
||||
if(type == "odsb" || type == "rdsb")
|
||||
if(format == "odsb" || format == "rdsb")
|
||||
{
|
||||
openrayman::dsb_decompiler decompiler;
|
||||
if(decompiler.decompile_dsb(
|
||||
path,
|
||||
target,
|
||||
type == "odsb" ?
|
||||
format == "odsb" ?
|
||||
openrayman::dsb_format::openrayman :
|
||||
openrayman::dsb_format::rayman2_decoded))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Operation failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return fail_and_print("Operation failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
make_sure_console_open(); std::cout << "Invalid type specified." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
return fail_and_print("Invalid format specified");
|
||||
}
|
||||
if(str == "--inspect")
|
||||
{
|
||||
n++;
|
||||
if(n >= argc)
|
||||
return fail_and_print("No format was specified");
|
||||
std::string format(argv[n]);
|
||||
n++;
|
||||
if(n >= argc)
|
||||
return fail_and_print("No path was specified");
|
||||
std::string path(argv[n]);
|
||||
if(format == "odsb")
|
||||
{
|
||||
openrayman::dsb_interpreter interpreter(path);
|
||||
openrayman::dsb_interpreter_debugger debugger(interpreter);
|
||||
debugger.print_summary();
|
||||
return interpreter.success() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
return fail_and_print("Invalid format was specified");
|
||||
}
|
||||
// Follow GNU format
|
||||
if(str == "--help")
|
||||
|
@ -108,10 +115,13 @@ 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;
|
||||
std::cout << " --convert-to \"format\" \"path\" \"target\" Converts the specified file into the target format" << std::endl;
|
||||
std::cout << " Format 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;
|
||||
std::cout << " --inspect \"format\" \"path\" Inspects and prints info about the specified file" << std::endl;
|
||||
std::cout << " Format can be any of:" << std::endl;
|
||||
std::cout << " \"odsb\": Interprets the DSB and outputs all instructions" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if(str == "--version")
|
||||
|
|
Loading…
Reference in a new issue