mirror of
https://github.com/open-goal/jak-project
synced 2026-08-26 16:16:36 -04:00
Merge branch 'master' into decomp/nav-enemy
This commit is contained in:
@@ -82,6 +82,13 @@
|
||||
"projectTarget" : "memory_dump_tool.exe (bin\\memory_dump_tool.exe)",
|
||||
"name" : "Run - EE Memory Analyze",
|
||||
"args" : [ "${workspaceRoot}/eeMemory.bin", "${workspaceRoot}"]
|
||||
},
|
||||
{
|
||||
"type" : "default",
|
||||
"project" : "CMakeLists.txt",
|
||||
"projectTarget" : "dgo_unpacker.exe (bin\\dgo_unpacker.exe)",
|
||||
"name" : "Run - DGO Unpacker (test)",
|
||||
"args" : [ "C:\\GameData\\Jak1\\Backup\\DGO-PAL\\GAME", "C:\\GameData\\Jak1\\Backup\\DISC-PAL\\CGO\\GAME.CGO"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_library(common
|
||||
SHARED
|
||||
audio/audio_formats.cpp
|
||||
cross_os_debug/xdbg.cpp
|
||||
cross_sockets/xsocket.cpp
|
||||
goos/Interpreter.cpp
|
||||
@@ -9,9 +10,11 @@ add_library(common
|
||||
goos/Reader.cpp
|
||||
goos/TextDB.cpp
|
||||
goos/ReplUtils.cpp
|
||||
math/geometry.cpp
|
||||
log/log.cpp
|
||||
type_system/defenum.cpp
|
||||
type_system/deftype.cpp
|
||||
type_system/state.cpp
|
||||
type_system/Type.cpp
|
||||
type_system/TypeFieldLookup.cpp
|
||||
type_system/TypeSpec.cpp
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
#include "audio_formats.h"
|
||||
#include "common/util/BinaryWriter.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
/*!
|
||||
* Write a wave file from a vector of samples.
|
||||
*/
|
||||
void write_wave_file_mono(const std::vector<s16>& samples,
|
||||
s32 sample_rate,
|
||||
const std::string& name) {
|
||||
WaveFileHeader header;
|
||||
memcpy(header.chunk_id, "RIFF", 4);
|
||||
header.chunk_size = 36 + samples.size() * sizeof(s16);
|
||||
memcpy(header.format, "WAVE", 4);
|
||||
|
||||
// now the format
|
||||
memcpy(header.subchunk1_id, "fmt ", 4);
|
||||
header.subchunk1_size = 16;
|
||||
header.aud_format = 1;
|
||||
header.num_channels = 1; // mono
|
||||
header.sample_rate = sample_rate;
|
||||
header.byte_rate = sample_rate * header.num_channels * sizeof(s16);
|
||||
header.block_align = header.num_channels * sizeof(s16);
|
||||
header.bits_per_sample = 16;
|
||||
|
||||
memcpy(header.subchunk2_id, "data", 4);
|
||||
header.subchunk2_size = samples.size() * sizeof(s16);
|
||||
|
||||
BinaryWriter writer;
|
||||
writer.add(header);
|
||||
|
||||
for (auto& samp : samples) {
|
||||
writer.add(samp);
|
||||
}
|
||||
|
||||
writer.write_to_file(name);
|
||||
}
|
||||
|
||||
std::vector<s16> decode_adpcm(BinaryReader& reader) {
|
||||
std::vector<s16> decoded_samples;
|
||||
s32 sample_prev[2] = {0, 0};
|
||||
constexpr s32 f1[5] = {0, 60, 115, 98, 122};
|
||||
constexpr s32 f2[5] = {0, 0, -52, -55, -60};
|
||||
|
||||
int block_idx = 0;
|
||||
while (true) {
|
||||
if (!reader.bytes_left()) {
|
||||
break;
|
||||
}
|
||||
u8 shift_filter = reader.read<u8>();
|
||||
u8 flags = reader.read<u8>();
|
||||
u8 shift = shift_filter & 0b1111;
|
||||
u8 filter = shift_filter >> 4;
|
||||
|
||||
if (shift > 12) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (filter > 4) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (flags == 7) {
|
||||
break;
|
||||
}
|
||||
|
||||
u8 input_buffer[14];
|
||||
|
||||
for (int i = 0; i < 14; i++) {
|
||||
input_buffer[i] = reader.read<u8>();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 28; i++) {
|
||||
int16_t nibble = input_buffer[i / 2];
|
||||
if (i % 2 == 0) {
|
||||
nibble = (nibble & 0x0f);
|
||||
} else {
|
||||
nibble = (nibble & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
s32 sample = (s32)(s16)(nibble << 12);
|
||||
sample >>= shift;
|
||||
sample += (sample_prev[0] * f1[filter] + sample_prev[1] * f2[filter] + 32) / 64;
|
||||
|
||||
if (sample > 0x7fff) {
|
||||
sample = 0x7fff;
|
||||
}
|
||||
|
||||
if (sample < -0x8000) {
|
||||
sample = -0x8000;
|
||||
}
|
||||
|
||||
sample_prev[1] = sample_prev[0];
|
||||
sample_prev[0] = sample;
|
||||
|
||||
decoded_samples.push_back(sample);
|
||||
}
|
||||
block_idx++;
|
||||
}
|
||||
|
||||
return decoded_samples;
|
||||
}
|
||||
|
||||
// I attempted to write an encoder below, which works, but has some limitations.
|
||||
// - In some cases we can't recover the original data exactly because the decode saturates the
|
||||
// the output to fit in a signed 16-bit integer.
|
||||
// - There are some cases when there are multiple ways to encode the same data.
|
||||
// The break_filter_ties function attempts to handle this, but doesn't work 100% of the time.
|
||||
|
||||
template <typename T>
|
||||
T saturate(T in, T minimum, T maximum) {
|
||||
if (in < minimum) {
|
||||
return minimum;
|
||||
}
|
||||
if (in > maximum) {
|
||||
return maximum;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
constexpr int SAMPLES_PER_BLOCK = 28;
|
||||
|
||||
void encode_block_with_filter(int filter_idx,
|
||||
const s16* samples_in,
|
||||
s32* out,
|
||||
const s32* prev_samples_in) {
|
||||
constexpr s32 f1[5] = {0, 60, 115, 98, 122};
|
||||
constexpr s32 f2[5] = {0, 0, -52, -55, -60};
|
||||
s32 prev_samples[2] = {prev_samples_in[0], prev_samples_in[1]};
|
||||
|
||||
for (int sample_idx = 0; sample_idx < SAMPLES_PER_BLOCK; sample_idx++) {
|
||||
s32 sample = samples_in[sample_idx];
|
||||
s32 delta =
|
||||
sample - (prev_samples[0] * f1[filter_idx] + prev_samples[1] * f2[filter_idx] + 32) / 64;
|
||||
out[sample_idx] = delta;
|
||||
prev_samples[1] = prev_samples[0];
|
||||
prev_samples[0] = sample;
|
||||
}
|
||||
}
|
||||
|
||||
int get_shift_error(int shift, const s32* samples, bool /*debug*/) {
|
||||
int result = 0;
|
||||
|
||||
for (int sample_idx = 0; sample_idx < SAMPLES_PER_BLOCK; sample_idx++) {
|
||||
int left_shift = 32 - (12 + 4 - shift);
|
||||
assert(left_shift >= 0);
|
||||
s32 sample_left = samples[sample_idx] << left_shift;
|
||||
s32 sample_right = sample_left >> (32 - 4);
|
||||
s32 sample_compressed = sample_right << (12 - shift);
|
||||
|
||||
s32 err = std::abs(sample_compressed - samples[sample_idx]);
|
||||
|
||||
result += err;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_max_bits(s32 value) {
|
||||
int result = 0;
|
||||
if (value >= 0) {
|
||||
int last = 1;
|
||||
while (value) {
|
||||
result++;
|
||||
last = value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
if (last) {
|
||||
result++;
|
||||
}
|
||||
} else {
|
||||
int last = 0;
|
||||
while (value != -1) {
|
||||
result++;
|
||||
last = value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
if (!last) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int break_filter_ties(s32* errors, s32* filter_shifts) {
|
||||
s32 best_error = INT32_MAX;
|
||||
|
||||
for (int filter_idx = 0; filter_idx < 5; filter_idx++) {
|
||||
if (errors[filter_idx] < best_error) {
|
||||
best_error = errors[filter_idx];
|
||||
}
|
||||
}
|
||||
|
||||
s32 best_shift = INT32_MAX;
|
||||
int best_filter = -1;
|
||||
for (int filter_idx = 5; filter_idx-- > 0;) {
|
||||
if (errors[filter_idx] == best_error) {
|
||||
if (filter_shifts[filter_idx] <= best_shift) {
|
||||
best_shift = filter_shifts[filter_idx];
|
||||
best_filter = filter_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_filter;
|
||||
}
|
||||
|
||||
void test_encode_adpcm(const std::vector<s16>& samples,
|
||||
const std::vector<u8>& filter_debug,
|
||||
const std::vector<u8>& shift_debug) {
|
||||
// the data is made of blocks.
|
||||
// Each block decodes to 28 samples.
|
||||
// each block has a shift and FIR filter.
|
||||
// the window is continuous across blocks.
|
||||
|
||||
// we could try all combinations of filters / shifts and pick the best, but that's slow and
|
||||
// we don't know how to break ties if multiple are the same.
|
||||
// we will try all 5 filters, then be smart about picking the best shift from there.
|
||||
|
||||
// filter coefficients.
|
||||
// there are 5x FIR filters that you can pick between.
|
||||
|
||||
// last two samples from chosen encoding of the previous block
|
||||
// init to 0, like the decoder
|
||||
s32 prev_block_samples[2] = {0, 0};
|
||||
|
||||
// TODO - this will drop some samples at the end, if we don't use a multiple of 28.
|
||||
// probably best to go back and pad with zeros or something.
|
||||
int block_count = samples.size() / SAMPLES_PER_BLOCK;
|
||||
|
||||
for (int block_idx = 0; block_idx < block_count; block_idx++) {
|
||||
// try each filter
|
||||
s32 pre_shift_samples_per_filter[5][SAMPLES_PER_BLOCK];
|
||||
for (int filter_idx = 0; filter_idx < 5; filter_idx++) {
|
||||
encode_block_with_filter(filter_idx, samples.data() + SAMPLES_PER_BLOCK * block_idx,
|
||||
pre_shift_samples_per_filter[filter_idx], prev_block_samples);
|
||||
}
|
||||
|
||||
// this is somewhat arbitrary, but we will require that the largest delta in the previous encode
|
||||
// can be represented.
|
||||
|
||||
s32 filter_errors[5] = {0, 0, 0, 0, 0};
|
||||
s32 filter_shifts[5] = {-1, -1, -1, -1};
|
||||
for (int filter_idx = 0; filter_idx < 5; filter_idx++) {
|
||||
// find the largest value
|
||||
s32 max_sample = INT32_MIN;
|
||||
s32 min_sample = INT32_MAX;
|
||||
|
||||
bool debug = block_idx == 10966 && filter_idx == 4;
|
||||
|
||||
for (int sample_idx = 0; sample_idx < SAMPLES_PER_BLOCK; sample_idx++) {
|
||||
s32 s = pre_shift_samples_per_filter[filter_idx][sample_idx];
|
||||
max_sample = std::max(s, max_sample);
|
||||
min_sample = std::min(s, min_sample);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
fmt::print("Range: {}\n", max_sample - min_sample);
|
||||
}
|
||||
|
||||
// see how many bits we need and pick shift.
|
||||
auto bits_for_max = std::max(4, std::max(get_max_bits(min_sample), get_max_bits(max_sample)));
|
||||
|
||||
filter_shifts[filter_idx] = 4 + 12 - bits_for_max;
|
||||
|
||||
filter_errors[filter_idx] = get_shift_error(filter_shifts[filter_idx],
|
||||
pre_shift_samples_per_filter[filter_idx], debug);
|
||||
|
||||
if (filter_errors[filter_idx] == 0) {
|
||||
while (filter_shifts[filter_idx] >= 0) {
|
||||
int next_error = get_shift_error(filter_shifts[filter_idx] - 1,
|
||||
pre_shift_samples_per_filter[filter_idx], false);
|
||||
if (next_error == 0) {
|
||||
filter_shifts[filter_idx]--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int best_filter = break_filter_ties(filter_errors, filter_shifts);
|
||||
s32 best_shift = filter_shifts[best_filter];
|
||||
|
||||
if (filter_errors[best_filter] || best_filter != filter_debug[block_idx] ||
|
||||
best_shift != shift_debug[block_idx]) {
|
||||
fmt::print("Block {} me {}, {} : answer {} {}: ERR {}\n", block_idx, best_filter, best_shift,
|
||||
filter_debug[block_idx], shift_debug[block_idx], filter_errors[best_filter]);
|
||||
fmt::print("filter errors:\n");
|
||||
for (int i = 0; i < 5; i++) {
|
||||
fmt::print(" [{}] {} {}\n", i, filter_errors[i], filter_shifts[i]);
|
||||
}
|
||||
fmt::print("prev: {} {}\n", prev_block_samples[0], prev_block_samples[1]);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
prev_block_samples[0] = samples.at(block_idx * 28 + 27);
|
||||
prev_block_samples[1] = samples.at(block_idx * 28 + 26);
|
||||
|
||||
} // end loop over blocks
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/util/BinaryReader.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
// The header data for a simple wave file
|
||||
struct WaveFileHeader {
|
||||
// wave file header
|
||||
char chunk_id[4];
|
||||
s32 chunk_size;
|
||||
char format[4];
|
||||
|
||||
// format chunk
|
||||
char subchunk1_id[4];
|
||||
s32 subchunk1_size;
|
||||
s16 aud_format;
|
||||
s16 num_channels;
|
||||
s32 sample_rate;
|
||||
s32 byte_rate;
|
||||
s16 block_align;
|
||||
s16 bits_per_sample;
|
||||
|
||||
// data chunk
|
||||
char subchunk2_id[4];
|
||||
s32 subchunk2_size;
|
||||
};
|
||||
|
||||
void write_wave_file_mono(const std::vector<s16>& samples,
|
||||
s32 sample_rate,
|
||||
const std::string& name);
|
||||
|
||||
std::vector<s16> decode_adpcm(BinaryReader& reader);
|
||||
|
||||
std::vector<u8> encode_adpcm(const std::vector<s16>& samples);
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef JAK_GOAL_CONSTANTS_H
|
||||
#define JAK_GOAL_CONSTANTS_H
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
constexpr s32 BINTEGER_OFFSET = 0;
|
||||
@@ -36,4 +33,7 @@ constexpr u64 EE_MAIN_MEM_MAP = 0x2123000000; // intentionally > 32-bit to
|
||||
// so this should be used only for debugging.
|
||||
constexpr bool EE_MEM_LOW_MAP = false;
|
||||
|
||||
#endif // JAK_GOAL_CONSTANTS_H
|
||||
constexpr double METER_LENGTH = 4096.0;
|
||||
constexpr double DEGREES_PER_ROT = 65536.0;
|
||||
constexpr double DEGREES_LENGTH = DEGREES_PER_ROT / 360.0;
|
||||
constexpr u64 TICKS_PER_SECOND = 300.0;
|
||||
|
||||
@@ -72,7 +72,9 @@ Interpreter::Interpreter() {
|
||||
{"string-ref", &Interpreter::eval_string_ref},
|
||||
{"string-length", &Interpreter::eval_string_length},
|
||||
{"string-append", &Interpreter::eval_string_append},
|
||||
{"ash", &Interpreter::eval_ash}};
|
||||
{"ash", &Interpreter::eval_ash},
|
||||
{"symbol->string", &Interpreter::eval_symbol_to_string},
|
||||
{"string->symbol", &Interpreter::eval_string_to_symbol}};
|
||||
|
||||
string_to_type = {{"empty-list", ObjectType::EMPTY_LIST},
|
||||
{"integer", ObjectType::INTEGER},
|
||||
@@ -90,6 +92,17 @@ Interpreter::Interpreter() {
|
||||
load_goos_library();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a user defined special form. The given function will be called with unevaluated arguments.
|
||||
* Lookup from these forms occurs after special/builtin, but before any env lookups.
|
||||
*/
|
||||
void Interpreter::register_form(
|
||||
const std::string& name,
|
||||
const std::function<
|
||||
Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>& form) {
|
||||
m_custom_forms[name] = form;
|
||||
}
|
||||
|
||||
Interpreter::~Interpreter() {
|
||||
// There are some circular references that prevent shared_ptrs from cleaning up if we
|
||||
// don't do this.
|
||||
@@ -191,6 +204,19 @@ bool Interpreter::get_global_variable_by_name(const std::string& name, Object* d
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets the variable to the value. Overwrites an existing value, or creates a new global.
|
||||
*/
|
||||
void Interpreter::set_global_variable_by_name(const std::string& name, const Object& value) {
|
||||
auto sym = SymbolObject::make_new(reader.symbolTable, name).as_symbol();
|
||||
global_environment.as_env()->vars[sym] = value;
|
||||
}
|
||||
|
||||
void Interpreter::set_global_variable_to_symbol(const std::string& name, const std::string& value) {
|
||||
auto sym = SymbolObject::make_new(reader.symbolTable, value);
|
||||
set_global_variable_by_name(name, sym);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get arguments being passed to a form. Don't evaluate them. There are two modes, "varargs" and
|
||||
* "not varargs". With varargs enabled, any number of unnamed and named arguments can be given.
|
||||
@@ -525,6 +551,13 @@ Object Interpreter::eval_pair(const Object& obj, const std::shared_ptr<Environme
|
||||
return ((*this).*(kv_b->second))(obj, args, env);
|
||||
}
|
||||
|
||||
// try custom forms next
|
||||
auto kv_u = m_custom_forms.find(head_sym->name);
|
||||
if (kv_u != m_custom_forms.end()) {
|
||||
Arguments args = get_args(obj, rest, make_varargs());
|
||||
return (kv_u->second)(obj, args, env);
|
||||
}
|
||||
|
||||
// try macros next
|
||||
Object macro_obj;
|
||||
if (try_symbol_lookup(head, env, ¯o_obj) && macro_obj.is_macro()) {
|
||||
@@ -1586,10 +1619,24 @@ Object Interpreter::eval_ash(const Object& form,
|
||||
if (sa >= 0 && sa < 64) {
|
||||
return Object::make_integer(val << sa);
|
||||
} else if (sa > -64) {
|
||||
return Object::make_integer(val >> sa);
|
||||
return Object::make_integer(val >> -sa);
|
||||
} else {
|
||||
throw_eval_error(form, fmt::format("Shift amount {} is out of range", sa));
|
||||
return EmptyListObject::make_new();
|
||||
}
|
||||
}
|
||||
|
||||
Object Interpreter::eval_symbol_to_string(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>&) {
|
||||
vararg_check(form, args, {ObjectType::SYMBOL}, {});
|
||||
return StringObject::make_new(args.unnamed.at(0).as_symbol()->name);
|
||||
}
|
||||
|
||||
Object Interpreter::eval_string_to_symbol(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>&) {
|
||||
vararg_check(form, args, {ObjectType::STRING}, {});
|
||||
return SymbolObject::make_new(reader.symbolTable, args.unnamed.at(0).as_string()->data);
|
||||
}
|
||||
} // namespace goos
|
||||
|
||||
@@ -19,6 +19,8 @@ class Interpreter {
|
||||
void throw_eval_error(const Object& o, const std::string& err);
|
||||
Object eval_with_rewind(const Object& obj, const std::shared_ptr<EnvironmentObject>& env);
|
||||
bool get_global_variable_by_name(const std::string& name, Object* dest);
|
||||
void set_global_variable_by_name(const std::string& name, const Object& value);
|
||||
void set_global_variable_to_symbol(const std::string& name, const std::string& value);
|
||||
Object eval(Object obj, const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object intern(const std::string& name);
|
||||
void disable_printfs();
|
||||
@@ -36,6 +38,12 @@ class Interpreter {
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
bool truthy(const Object& o);
|
||||
|
||||
void register_form(
|
||||
const std::string& name,
|
||||
const std::function<
|
||||
Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>& form);
|
||||
void eval_args(Arguments* args, const std::shared_ptr<EnvironmentObject>& env);
|
||||
|
||||
Reader reader;
|
||||
Object global_environment;
|
||||
Object goal_env;
|
||||
@@ -59,7 +67,6 @@ class Interpreter {
|
||||
const std::unordered_map<std::string, std::pair<bool, std::optional<ObjectType>>>& named);
|
||||
|
||||
Object eval_pair(const Object& o, const std::shared_ptr<EnvironmentObject>& env);
|
||||
void eval_args(Arguments* args, const std::shared_ptr<EnvironmentObject>& env);
|
||||
ArgumentSpec parse_arg_spec(const Object& form, Object& rest);
|
||||
|
||||
Object quasiquote_helper(const Object& form, const std::shared_ptr<EnvironmentObject>& env);
|
||||
@@ -198,6 +205,12 @@ class Interpreter {
|
||||
Object eval_ash(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_symbol_to_string(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
Object eval_string_to_symbol(const Object& form,
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env);
|
||||
|
||||
// specials
|
||||
Object eval_define(const Object& form,
|
||||
@@ -239,6 +252,11 @@ class Interpreter {
|
||||
Arguments& args,
|
||||
const std::shared_ptr<EnvironmentObject>& env)>
|
||||
builtin_forms;
|
||||
|
||||
std::unordered_map<
|
||||
std::string,
|
||||
std::function<Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>>
|
||||
m_custom_forms;
|
||||
std::unordered_map<std::string,
|
||||
Object (Interpreter::*)(const Object& form,
|
||||
const Object& rest,
|
||||
|
||||
@@ -304,4 +304,30 @@ bool Arguments::only_contains_named(const std::unordered_set<std::string>& names
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string escape_string(const std::string& in) {
|
||||
std::string result;
|
||||
result.reserve(in.size());
|
||||
|
||||
for (char c : in) {
|
||||
if (c == '"') {
|
||||
result.push_back('\\');
|
||||
result.push_back('"');
|
||||
} else {
|
||||
result.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string StringObject::print() const {
|
||||
return "\"" + escape_string(data) + "\"";
|
||||
}
|
||||
|
||||
std::string StringObject::inspect() const {
|
||||
return "[string] \"" + escape_string(data) + "\"\n";
|
||||
}
|
||||
|
||||
} // namespace goos
|
||||
|
||||
@@ -416,9 +416,8 @@ class StringObject : public HeapObject {
|
||||
return obj;
|
||||
}
|
||||
|
||||
std::string print() const override { return "\"" + data + "\""; }
|
||||
|
||||
std::string inspect() const override { return "[string] \"" + data + "\"\n"; }
|
||||
std::string print() const override;
|
||||
std::string inspect() const override;
|
||||
|
||||
~StringObject() override = default;
|
||||
};
|
||||
|
||||
@@ -444,6 +444,31 @@ PrettyPrinterNode* getNextListOrEmptyListOnLine(PrettyPrinterNode* start) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PrettyPrinterNode* get_case_start_case(PrettyPrinterNode* start) {
|
||||
auto node = start->next;
|
||||
while (node) {
|
||||
switch (node->tok->kind) {
|
||||
case FormToken::TokenKind::OPEN_PAREN:
|
||||
goto loop_end;
|
||||
break;
|
||||
case FormToken::TokenKind::WHITESPACE:
|
||||
break;
|
||||
default:
|
||||
return getNextListOnLine(start);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
loop_end:
|
||||
node = node->paren;
|
||||
while (node && (!node->tok || node->tok->kind != FormToken::TokenKind::OPEN_PAREN)) {
|
||||
node = node->next;
|
||||
}
|
||||
if (!node) {
|
||||
return getNextListOnLine(start);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the first open paren on the current line (can start in the middle of line, inclusive of
|
||||
* start) nullptr if there's no open parens on the rest of this line
|
||||
@@ -678,8 +703,15 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (name == "cond") {
|
||||
auto* start_of_case = getNextListOnLine(node);
|
||||
if (name == "cond" || name == "case") {
|
||||
PrettyPrinterNode* start_of_case;
|
||||
if (name == "cond") {
|
||||
start_of_case = getNextListOnLine(node);
|
||||
} else {
|
||||
start_of_case = get_case_start_case(node);
|
||||
insertNewlineBefore(pool, start_of_case, 0);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// let's break this case:
|
||||
assert(start_of_case->tok->kind == FormToken::TokenKind::OPEN_PAREN);
|
||||
@@ -708,7 +740,23 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) {
|
||||
}
|
||||
|
||||
// break cond into a multi-line always
|
||||
breakList(pool, node->paren);
|
||||
if (name == "case") {
|
||||
auto next = node->next;
|
||||
if (next) {
|
||||
next = next->next;
|
||||
}
|
||||
if (next->tok && next->tok->kind == FormToken::TokenKind::OPEN_PAREN) {
|
||||
next = next->paren;
|
||||
if (next) {
|
||||
next = next->next;
|
||||
}
|
||||
}
|
||||
if (next) {
|
||||
// insertNewlineAfter(pool, next, 0);
|
||||
}
|
||||
} else {
|
||||
breakList(pool, node->paren);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
namespace math {
|
||||
|
||||
template <typename T, int Size>
|
||||
class Vector {
|
||||
public:
|
||||
Vector() = default;
|
||||
static Vector<T, Size> zero() {
|
||||
Vector<T, Size> result;
|
||||
for (auto& x : result.m_data) {
|
||||
x = T(0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
Vector(Args... args) : m_data{T(args)...} {}
|
||||
|
||||
T* begin() { return &m_data[0]; }
|
||||
T* end() { return &m_data[Size]; }
|
||||
const T* begin() const { return &m_data[0]; }
|
||||
const T* end() const { return &m_data[Size]; }
|
||||
|
||||
T& x() { return m_data[0]; }
|
||||
|
||||
const T& x() const { return m_data[0]; }
|
||||
|
||||
T& y() {
|
||||
static_assert(Size >= 1, "Out of bounds");
|
||||
return m_data[1];
|
||||
}
|
||||
|
||||
const T& y() const {
|
||||
static_assert(Size >= 1, "Out of bounds");
|
||||
return m_data[1];
|
||||
}
|
||||
|
||||
T& z() {
|
||||
static_assert(Size >= 2, "Out of bounds");
|
||||
return m_data[2];
|
||||
}
|
||||
|
||||
const T& z() const {
|
||||
static_assert(Size >= 2, "Out of bounds");
|
||||
return m_data[2];
|
||||
}
|
||||
|
||||
T& w() {
|
||||
static_assert(Size >= 3, "Out of bounds");
|
||||
return m_data[3];
|
||||
}
|
||||
|
||||
const T& w() const {
|
||||
static_assert(Size >= 3, "Out of bounds");
|
||||
return m_data[3];
|
||||
}
|
||||
|
||||
const T squared_length() const {
|
||||
T sum = T(0);
|
||||
for (auto val : m_data) {
|
||||
sum += val * val;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
const T length() const { return std::sqrt(squared_length()); }
|
||||
|
||||
Vector<T, Size> operator+(const Vector<T, Size>& other) const {
|
||||
Vector<T, Size> result;
|
||||
for (int i = 0; i < Size; i++) {
|
||||
result[i] = m_data[i] + other[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector<T, Size> operator-(const Vector<T, Size>& other) const {
|
||||
Vector<T, Size> result;
|
||||
for (int i = 0; i < Size; i++) {
|
||||
result[i] = m_data[i] - other[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T dot(const Vector<T, Size>& other) const {
|
||||
T result(0);
|
||||
for (int i = 0; i < Size; i++) {
|
||||
result += m_data[i] * other[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T operator[](int idx) const { return m_data[idx]; }
|
||||
|
||||
T& operator[](int idx) { return m_data[idx]; }
|
||||
|
||||
Vector<T, Size> operator/(const T& val) const {
|
||||
Vector<T, Size> result;
|
||||
for (int i = 0; i < Size; i++) {
|
||||
result[i] = m_data[i] / val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector<T, Size> operator*(const T& val) const {
|
||||
Vector<T, Size> result;
|
||||
for (int i = 0; i < Size; i++) {
|
||||
result[i] = m_data[i] * val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector<T, Size> normalized(const T& norm = T(1)) const { return (*this) * (norm / length()); }
|
||||
|
||||
void normalize(const T& norm = T(1)) { *this = normalized(norm); }
|
||||
|
||||
std::string to_string_aligned() const {
|
||||
std::string result = "[";
|
||||
for (auto x : m_data) {
|
||||
result.append(fmt::format("{: 6.3f} ", x));
|
||||
}
|
||||
result.pop_back();
|
||||
return result + "]";
|
||||
}
|
||||
|
||||
private:
|
||||
T m_data[Size];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using Vector2 = Vector<T, 2>;
|
||||
|
||||
template <typename T>
|
||||
using Vector3 = Vector<T, 3>;
|
||||
|
||||
template <typename T>
|
||||
using Vector4 = Vector<T, 4>;
|
||||
|
||||
using Vector2f = Vector2<float>;
|
||||
using Vector3f = Vector3<float>;
|
||||
using Vector4f = Vector4<float>;
|
||||
using Vector2d = Vector2<double>;
|
||||
using Vector3d = Vector3<double>;
|
||||
using Vector4d = Vector4<double>;
|
||||
} // namespace math
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/math/Vector.h"
|
||||
|
||||
namespace math {
|
||||
|
||||
template <typename T>
|
||||
T squared(const T& in) {
|
||||
return in * in;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct RaySphereResult {
|
||||
bool hit = false;
|
||||
T u[2] = {0, 0};
|
||||
};
|
||||
|
||||
/*!
|
||||
* Check if a line intersects a sphere.
|
||||
*/
|
||||
template <typename T>
|
||||
RaySphereResult<T> ray_sphere_intersect(const Vector3<T>& ray_origin,
|
||||
const Vector3<T>& ray_direction_in,
|
||||
const Vector3<T>& sphere_origin,
|
||||
T sphere_radius) {
|
||||
RaySphereResult<T> result;
|
||||
Vector3<T> ray_direction = ray_direction_in.normalized();
|
||||
|
||||
Vector3<T> oc = ray_origin - sphere_origin;
|
||||
|
||||
T value_under_sqrt =
|
||||
squared(ray_direction.dot(oc)) - (oc.squared_length() - squared(sphere_radius));
|
||||
|
||||
if (value_under_sqrt < 0) {
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
T minus_b = -ray_direction.dot(oc);
|
||||
result.hit = true;
|
||||
T sqrt_val = std::sqrt(value_under_sqrt);
|
||||
|
||||
result.u[0] = minus_b + sqrt_val;
|
||||
result.u[1] = minus_b - sqrt_val;
|
||||
return result;
|
||||
}
|
||||
} // namespace math
|
||||
@@ -231,6 +231,8 @@ void try_reverse_lookup_array_like(const FieldReverseLookupInput& input,
|
||||
* - get something inside an object (variable idx)
|
||||
* - get a constant idx reference object (we pick this over just getting the array for idx = 0)
|
||||
* - get something inside a constant idx reference object
|
||||
*
|
||||
* Note: for an inline array of basics, the offset should include the basic offset.
|
||||
*/
|
||||
void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
|
||||
const TypeSystem& ts,
|
||||
@@ -264,7 +266,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
|
||||
FieldReverseLookupInput next_input;
|
||||
next_input.deref = input.deref;
|
||||
next_input.stride = 0;
|
||||
next_input.offset = input.offset;
|
||||
next_input.offset = input.offset; // includes the offset.
|
||||
next_input.base_type = di.result_type;
|
||||
try_reverse_lookup(next_input, ts, &var_idx_node, output, max_count);
|
||||
return;
|
||||
@@ -272,18 +274,17 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
|
||||
|
||||
// constant lookup, or accessing within the first one
|
||||
// which element we are in
|
||||
int elt_idx = input.offset / di.stride;
|
||||
// how many bytes into the element we look
|
||||
int elt_idx = (ts.lookup_type(di.result_type)->get_offset() + input.offset) / di.stride;
|
||||
// how many bytes into the element we look (including offset)
|
||||
int offset_into_elt = input.offset - (elt_idx * di.stride);
|
||||
// the expected number of bytes into the element we would look to grab a ref to the elt.
|
||||
int expected_offset_into_elt = ts.lookup_type(di.result_type)->get_offset();
|
||||
|
||||
ReverseLookupNode const_idx_node;
|
||||
const_idx_node.prev = parent;
|
||||
const_idx_node.token.kind = FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX;
|
||||
const_idx_node.token.idx = elt_idx;
|
||||
|
||||
if (offset_into_elt == expected_offset_into_elt && !input.deref.has_value()) {
|
||||
if (offset_into_elt == 0 && !input.deref.has_value() && !input.stride) {
|
||||
// just get an element (possibly zero, and we want to include the 0 if so)
|
||||
// for the degenerate inline-array case, it seems more likely that we get the zeroth object
|
||||
// rather than the array, so this goes before that case.
|
||||
@@ -295,7 +296,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
|
||||
}
|
||||
|
||||
// can we just return the array?
|
||||
if (expected_offset_into_elt == offset_into_elt && !input.deref.has_value() && elt_idx == 0) {
|
||||
if (offset_into_elt == 0 && !input.deref.has_value() && elt_idx == 0 && !input.stride) {
|
||||
auto parent_vec = parent_to_vector(parent);
|
||||
if (!parent_vec.empty()) {
|
||||
output->results.emplace_back(false, input.base_type, parent_to_vector(parent));
|
||||
@@ -311,8 +312,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
|
||||
FieldReverseLookupInput next_input;
|
||||
next_input.deref = input.deref;
|
||||
next_input.stride = input.stride;
|
||||
// try_reverse_lookup expects "offset_into_field - boxed_offset"
|
||||
next_input.offset = offset_into_elt - expected_offset_into_elt;
|
||||
next_input.offset = offset_into_elt;
|
||||
next_input.base_type = di.result_type;
|
||||
try_reverse_lookup(next_input, ts, &const_idx_node, output, max_count);
|
||||
}
|
||||
|
||||
@@ -965,6 +965,13 @@ void TypeSystem::add_builtin_types() {
|
||||
add_builtin_value_type("uinteger", "uint64", 8);
|
||||
add_builtin_value_type("uinteger", "uint128", 16, false, false, RegClass::INT_128);
|
||||
|
||||
// add special units types.
|
||||
add_builtin_value_type("float", "meters", 4, false, false, RegClass::FLOAT)
|
||||
->set_runtime_type("float");
|
||||
add_builtin_value_type("float", "degrees", 4, false, false, RegClass::FLOAT)
|
||||
->set_runtime_type("float");
|
||||
add_builtin_value_type("uint64", "seconds", 8, false, false)->set_runtime_type("uint64");
|
||||
|
||||
auto int_type = add_builtin_value_type("integer", "int", 8, false, true);
|
||||
int_type->disallow_in_runtime();
|
||||
auto uint_type = add_builtin_value_type("uinteger", "uint", 8, false, false);
|
||||
@@ -1352,8 +1359,23 @@ bool TypeSystem::typecheck_and_throw(const TypeSpec& expected,
|
||||
/*!
|
||||
* Is actual of type expected? For base types.
|
||||
*/
|
||||
bool TypeSystem::typecheck_base_types(const std::string& expected,
|
||||
bool TypeSystem::typecheck_base_types(const std::string& input_expected,
|
||||
const std::string& actual) const {
|
||||
std::string expected = input_expected;
|
||||
|
||||
// the unit types aren't picky.
|
||||
if (expected == "meters") {
|
||||
expected = "float";
|
||||
}
|
||||
|
||||
if (expected == "seconds") {
|
||||
expected = "uint";
|
||||
}
|
||||
|
||||
if (expected == "degrees") {
|
||||
expected = "float";
|
||||
}
|
||||
|
||||
// just to make sure it exists.
|
||||
lookup_type_allow_partial_def(expected);
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "state.h"
|
||||
|
||||
/*!
|
||||
* Convert a (state <blah> ...) to the function required to go. Must be state.
|
||||
*/
|
||||
TypeSpec state_to_go_function(const TypeSpec& state_type) {
|
||||
assert(state_type.base_type() == "state");
|
||||
std::vector<TypeSpec> arg_types;
|
||||
for (int i = 0; i < (int)state_type.arg_count() - 1; i++) {
|
||||
arg_types.push_back(state_type.get_arg(i));
|
||||
}
|
||||
|
||||
arg_types.push_back(TypeSpec("none")); // none for the return.
|
||||
return TypeSpec("function", arg_types);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/type_system/TypeSpec.h"
|
||||
|
||||
/*!
|
||||
* This contains type system utilities related to state and process
|
||||
*/
|
||||
|
||||
TypeSpec state_to_go_function(const TypeSpec& state_type);
|
||||
+15
-11
@@ -6,31 +6,35 @@
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include "common/util/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include <vector>
|
||||
|
||||
class BinaryReader {
|
||||
public:
|
||||
explicit BinaryReader(const std::vector<uint8_t>& _buffer) : buffer(_buffer) {}
|
||||
explicit BinaryReader(const std::vector<uint8_t>& _buffer) : m_buffer(_buffer) {}
|
||||
|
||||
template <typename T>
|
||||
T read() {
|
||||
assert(seek + sizeof(T) <= buffer.size());
|
||||
T& obj = *(T*)(buffer.data() + seek);
|
||||
seek += sizeof(T);
|
||||
assert(m_seek + sizeof(T) <= m_buffer.size());
|
||||
T obj;
|
||||
memcpy(&obj, m_buffer.data() + m_seek, sizeof(T));
|
||||
m_seek += sizeof(T);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void ffwd(int amount) {
|
||||
seek += amount;
|
||||
assert(seek <= buffer.size());
|
||||
m_seek += amount;
|
||||
assert(m_seek <= m_buffer.size());
|
||||
}
|
||||
|
||||
uint32_t bytes_left() const { return buffer.size() - seek; }
|
||||
uint8_t* here() { return buffer.data() + seek; }
|
||||
uint32_t get_seek() const { return seek; }
|
||||
uint32_t bytes_left() const { return m_buffer.size() - m_seek; }
|
||||
uint8_t* here() { return m_buffer.data() + m_seek; }
|
||||
uint32_t get_seek() const { return m_seek; }
|
||||
void set_seek(u32 seek) { m_seek = seek; }
|
||||
|
||||
private:
|
||||
std::vector<u8> buffer;
|
||||
uint32_t seek = 0;
|
||||
std::vector<u8> m_buffer;
|
||||
uint32_t m_seek = 0;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,17 @@ DgoReader::DgoReader(std::string file_name, const std::vector<u8>& data)
|
||||
|
||||
// get all obj files...
|
||||
for (uint32_t i = 0; i < header.object_count; i++) {
|
||||
auto obj_header = reader.read<ObjectHeader>();
|
||||
ObjectHeader obj_header = reader.read<ObjectHeader>();
|
||||
|
||||
if (reader.bytes_left() < obj_header.size && i == header.object_count - 1 &&
|
||||
obj_header.size - reader.bytes_left() <= 48) {
|
||||
printf(
|
||||
"Warning: final file %s in DGO %s has a size missing %d bytes. It will be adjusted from "
|
||||
"%d to %d bytes.\n",
|
||||
obj_header.name, header.name, obj_header.size - reader.bytes_left(), obj_header.size,
|
||||
(int)reader.bytes_left());
|
||||
obj_header.size = reader.bytes_left();
|
||||
}
|
||||
assert(reader.bytes_left() >= obj_header.size);
|
||||
assert_string_empty_after(obj_header.name, 60);
|
||||
|
||||
@@ -58,4 +68,4 @@ std::string DgoReader::description_as_json() const {
|
||||
}
|
||||
|
||||
return j.dump(4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "BinaryWriter.h"
|
||||
#include "common/common_types.h"
|
||||
#include "third-party/svpng.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "third-party/lzokay/lzokay.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -119,6 +120,21 @@ void write_text_file(const std::string& file_name, const std::string& text) {
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read_binary_file(const std::string& filename) {
|
||||
// make sure file exists and isn't a directory
|
||||
std::filesystem::path path(filename);
|
||||
|
||||
auto status = std::filesystem::status(std::filesystem::path(filename));
|
||||
|
||||
if (!std::filesystem::exists(status)) {
|
||||
throw std::runtime_error(fmt::format("File {} cannot be opened: does not exist.", filename));
|
||||
}
|
||||
|
||||
if (status.type() != std::filesystem::file_type::regular &&
|
||||
status.type() != std::filesystem::file_type::symlink) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("File {} cannot be opened: not a regular file or symlink.", filename));
|
||||
}
|
||||
|
||||
auto fp = fopen(filename.c_str(), "rb");
|
||||
if (!fp)
|
||||
throw std::runtime_error("File " + filename +
|
||||
|
||||
@@ -21,6 +21,8 @@ class Range {
|
||||
Range(const T& start, const T& end) : m_start(start), m_end(end) {}
|
||||
const T& first() const { return m_start; }
|
||||
const T& last() const { return m_end; }
|
||||
T& first() { return m_start; }
|
||||
T& last() { return m_end; }
|
||||
bool contains(T& val) const { return val >= m_start && val < m_end; }
|
||||
bool empty() const { return m_end <= m_start; }
|
||||
T size() const { return m_end - m_start; }
|
||||
|
||||
@@ -18,6 +18,7 @@ add_library(
|
||||
data/dir_tpages.cpp
|
||||
data/game_count.cpp
|
||||
data/game_text.cpp
|
||||
data/streamed_audio.cpp
|
||||
data/StrFileReader.cpp
|
||||
data/tpage.cpp
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "common/util/assert.h"
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
#include "common/common_types.h"
|
||||
#include "InstructionParser.h"
|
||||
|
||||
@@ -46,14 +47,24 @@ InstructionParser::InstructionParser() {
|
||||
InstructionKind::MFLO1, InstructionKind::SYNCL, InstructionKind::PCPYUD,
|
||||
InstructionKind::PEXTUW, InstructionKind::POR, InstructionKind::VMOVE,
|
||||
InstructionKind::VSUB, InstructionKind::LQC2, InstructionKind::SQC2,
|
||||
InstructionKind::MULAS, InstructionKind::MADDAS}) {
|
||||
InstructionKind::MULAS, InstructionKind::MADDAS, InstructionKind::QMTC2,
|
||||
InstructionKind::QMFC2, InstructionKind::VITOF0, InstructionKind::VFTOI0,
|
||||
InstructionKind::PSLLW, InstructionKind::PSRAW}) {
|
||||
auto& info = gOpcodeInfo[int(i)];
|
||||
if (info.defined) {
|
||||
m_opcode_name_lookup[info.name] = int(i);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
assert(added == int(m_opcode_name_lookup.size()));
|
||||
|
||||
for (auto i : {InstructionKind::VMUL_BC}) {
|
||||
auto& info = gOpcodeInfo[int(i)];
|
||||
if (info.defined) {
|
||||
m_opcode_name_broadcast_lookup[info.name] = int(i);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
assert(added == int(m_opcode_name_lookup.size()) + int(m_opcode_name_broadcast_lookup.size()));
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -89,6 +100,18 @@ std::string get_instr_name(std::string& instr) {
|
||||
}
|
||||
}
|
||||
auto name = instr.substr(0, i);
|
||||
|
||||
// qmXc2.i should not grab the i.
|
||||
if (name == "qmtc2.i") {
|
||||
name = "qmtc2"; // strip .i
|
||||
i -= 2; // leave the i for the next step.
|
||||
}
|
||||
|
||||
if (name == "qmfc2.i") {
|
||||
name = "qmfc2"; // strip .i
|
||||
i -= 2; // leave the i for the next step.
|
||||
}
|
||||
|
||||
if (i == instr.length()) {
|
||||
instr.clear();
|
||||
} else {
|
||||
@@ -220,14 +243,34 @@ Instruction InstructionParser::parse_single_instruction(
|
||||
std::string str,
|
||||
const std::vector<DecompilerLabel>& labels) {
|
||||
auto name = get_instr_name(str);
|
||||
|
||||
std::optional<int> op_idx;
|
||||
auto lookup = m_opcode_name_lookup.find(name);
|
||||
if (lookup == m_opcode_name_lookup.end()) {
|
||||
// it might be a VU with broadcast.
|
||||
if (!name.empty() && name.front() == 'v') {
|
||||
char last_char = name.back();
|
||||
if (last_char == 'x' || last_char == 'y' || last_char == 'z' || last_char == 'w') {
|
||||
str.insert(str.begin(), ' ');
|
||||
str.insert(str.begin(), last_char);
|
||||
name.pop_back();
|
||||
auto bc_lookup = m_opcode_name_broadcast_lookup.find(name);
|
||||
if (bc_lookup != m_opcode_name_broadcast_lookup.end()) {
|
||||
op_idx = bc_lookup->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
op_idx = lookup->second;
|
||||
}
|
||||
|
||||
if (!op_idx) {
|
||||
throw std::runtime_error("InstructionParser cannot handle opcode " + name);
|
||||
}
|
||||
|
||||
Instruction instr;
|
||||
instr.kind = InstructionKind(lookup->second);
|
||||
auto& info = gOpcodeInfo[lookup->second];
|
||||
instr.kind = InstructionKind(*op_idx);
|
||||
auto& info = gOpcodeInfo[*op_idx];
|
||||
for (u8 i = 0; i < info.step_count; i++) {
|
||||
auto& step = info.steps[i];
|
||||
switch (step.decode) {
|
||||
@@ -333,7 +376,36 @@ Instruction InstructionParser::parse_single_instruction(
|
||||
break;
|
||||
}
|
||||
|
||||
case DecodeType::IL: {
|
||||
auto thing = get_until_space(str);
|
||||
if (thing == "i") {
|
||||
instr.il = 1;
|
||||
} else if (thing == "ni") {
|
||||
instr.il = 0;
|
||||
} else {
|
||||
printf("Bad interlock specification. Got %s\n", thing.c_str());
|
||||
assert(false);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DecodeType::BC: {
|
||||
auto thing = get_until_space(str);
|
||||
if (thing == "x") {
|
||||
instr.cop2_bc = 0;
|
||||
} else if (thing == "y") {
|
||||
instr.cop2_bc = 1;
|
||||
} else if (thing == "z") {
|
||||
instr.cop2_bc = 2;
|
||||
} else if (thing == "w") {
|
||||
instr.cop2_bc = 3;
|
||||
} else {
|
||||
printf("Bad broadcast. Got %s\n", thing.c_str());
|
||||
assert(false);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
printf("missing DecodeType: %d\n", (int)step.decode);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@ class InstructionParser {
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, int> m_opcode_name_lookup;
|
||||
std::unordered_map<std::string, int> m_opcode_name_broadcast_lookup;
|
||||
};
|
||||
} // namespace decompiler
|
||||
@@ -253,16 +253,16 @@ void init_opcode_info() {
|
||||
.dst(FT::RD, DT::COP0); // Move to System Control Coprocessor
|
||||
def(IK::MFC0, "mfc0")
|
||||
.dst_gpr(FT::RT)
|
||||
.src(FT::RD, DT::COP0); // Move from System Control Coprocessor
|
||||
def(IK::MTDAB, "mtdab").src_gpr(FT::RT); // Move to Data Address Breakpoint Register
|
||||
def(IK::MTDABM, "mtdabm").src_gpr(FT::RT); // Move to Data Address Breakpoint Mask Register
|
||||
drd(def(IK::MFHI, "mfhi")); // Move from HI Register
|
||||
drd(def(IK::MFLO, "mflo")); // Move from LO Register
|
||||
def(IK::MTLO1, "mtlo1").src_gpr(FT::RS); // Move to LO1 Register
|
||||
drd(def(IK::MFLO1, "mflo1")); // Move from LO1 Register
|
||||
drd(def(IK::PMFHL_UW, "pmfhl.uw")); // Parallel Move From HI/LO Register
|
||||
drd(def(IK::PMFHL_LW, "pmfhl.lw"));
|
||||
drd(def(IK::PMFHL_LH, "pmfhl.lh"));
|
||||
.src(FT::RD, DT::COP0); // Move from System Control Coprocessor
|
||||
def(IK::MTDAB, "mtdab").src_gpr(FT::RT); // Move to Data Address Breakpoint Register
|
||||
def(IK::MTDABM, "mtdabm").src_gpr(FT::RT); // Move to Data Address Breakpoint Mask Register
|
||||
drd(def(IK::MFHI, "mfhi")); // Move from HI Register
|
||||
drd(def(IK::MFLO, "mflo")); // Move from LO Register
|
||||
def(IK::MTLO1, "mtlo1").src_gpr(FT::RS); // Move to LO1 Register
|
||||
drd(def(IK::MFLO1, "mflo1")); // Move from LO1 Register
|
||||
drd(def(IK::PMFHL_UW, "pmfhl.uw").gpr128()); // Parallel Move From HI/LO Register
|
||||
drd(def(IK::PMFHL_LW, "pmfhl.lw").gpr128());
|
||||
drd(def(IK::PMFHL_LH, "pmfhl.lh").gpr128());
|
||||
def(IK::MFPC, "mfpc").dst_gpr(FT::RT).src(FT::PCR, DT::PCR); // Move from Performance Counter
|
||||
def(IK::MTPC, "mtpc").src_gpr(FT::RT).dst(FT::PCR, DT::PCR); // Move to Performance Counter
|
||||
|
||||
@@ -279,45 +279,48 @@ void init_opcode_info() {
|
||||
def(IK::ERET, "eret"); // Exception Return
|
||||
def(IK::EI, "ei"); // Enable Interrupt
|
||||
|
||||
drd_srs_srt(def(IK::PPACB, "ppacb")); // Parallel Pack to Byte
|
||||
drd_srs_srt(def(IK::PPACH, "ppach")); // Parallel Pack to Halfword
|
||||
drd_srs_srt(def(IK::PPACW, "ppacw")); // Parallel Pack to Word
|
||||
drd_srs_srt(def(IK::PADDH, "paddh")); // Parallel Add Halfword
|
||||
drd_srs_srt(def(IK::PADDW, "paddw")); // Parallel Add Word
|
||||
drd_srs_srt(def(IK::PSUBW, "psubw")); // Parallel Subtract Word
|
||||
drd_srs_srt(def(IK::PMINH, "pminh")); // Parallel Minimize Halfword
|
||||
drd_srs_srt(def(IK::PMINW, "pminw")); // Parallel Minimize Word
|
||||
drd_srs_srt(def(IK::PMAXH, "pmaxh")); // Parallel Maximize Halfword
|
||||
drd_srs_srt(def(IK::PMAXW, "pmaxw")); // Parallel Maximize Word
|
||||
drd_srs_srt(def(IK::PEXTLB, "pextlb")); // Parallel Extend Lower from Byte
|
||||
drd_srs_srt(def(IK::PEXTLH, "pextlh")); // Parallel Extend Lower from Halfword
|
||||
drd_srs_srt(def(IK::PEXTLW, "pextlw")); // Parallel Extend Lower from Word
|
||||
drd_srs_srt(def(IK::PCGTW, "pcgtw")); // Parallel Compare for Greater Than Word
|
||||
drd_srs_srt(def(IK::PCEQB, "pceqb")); // Parallel Compare for Equal Byte
|
||||
drd_srs_srt(def(IK::PCEQW, "pceqw")); // Parallel Compare for Equal Word
|
||||
drd_srs_srt(def(IK::PEXTUB, "pextub")); // Parallel Extend Upper from Byte
|
||||
drd_srs_srt(def(IK::PEXTUH, "pextuh")); // Parallel Extend Upper from Halfword
|
||||
drd_srs_srt(def(IK::PEXTUW, "pextuw")); // Parallel Extend Upper from Word
|
||||
drd_srs_srt(def(IK::PCPYUD, "pcpyud")); // Parallel Copy Upper Doubleword
|
||||
drd_srs_srt(def(IK::PCPYLD, "pcpyld")); // Parallel Copy Lower Doubleword
|
||||
drd_srs_srt(def(IK::PMADDH, "pmaddh")); // Parallel Multiply-Add Halfword
|
||||
drd_srs_srt(def(IK::PMULTH, "pmulth")); // Parallel Multiply Halfword
|
||||
drd_srs_srt(def(IK::PEXEW, "pexew")); // Parallel Exchange Even Word
|
||||
drd_srs_srt(def(IK::PINTEH, "pinteh")); // Parallel Interleave Even Halfword
|
||||
drd_srs_srt(def(IK::PAND, "pand")); // Parallel And
|
||||
drd_srs_srt(def(IK::POR, "por")); // Parallel Or
|
||||
drd_srs_srt(def(IK::PNOR, "pnor")); // Parallel Not Or
|
||||
drd_srs_srt(def(IK::PPACB, "ppacb").gpr128()); // Parallel Pack to Byte
|
||||
drd_srs_srt(def(IK::PPACH, "ppach").gpr128()); // Parallel Pack to Halfword
|
||||
drd_srs_srt(def(IK::PPACW, "ppacw").gpr128()); // Parallel Pack to Word
|
||||
drd_srs_srt(def(IK::PADDH, "paddh").gpr128()); // Parallel Add Halfword
|
||||
drd_srs_srt(def(IK::PADDW, "paddw").gpr128()); // Parallel Add Word
|
||||
drd_srs_srt(def(IK::PSUBW, "psubw").gpr128()); // Parallel Subtract Word
|
||||
drd_srs_srt(def(IK::PMINH, "pminh").gpr128()); // Parallel Minimize Halfword
|
||||
drd_srs_srt(def(IK::PMINW, "pminw").gpr128()); // Parallel Minimize Word
|
||||
drd_srs_srt(def(IK::PMAXH, "pmaxh").gpr128()); // Parallel Maximize Halfword
|
||||
drd_srs_srt(def(IK::PMAXW, "pmaxw").gpr128()); // Parallel Maximize Word
|
||||
drd_srs_srt(def(IK::PEXTLB, "pextlb").gpr128()); // Parallel Extend Lower from Byte
|
||||
drd_srs_srt(def(IK::PEXTLH, "pextlh").gpr128()); // Parallel Extend Lower from Halfword
|
||||
drd_srs_srt(def(IK::PEXTLW, "pextlw").gpr128()); // Parallel Extend Lower from Word
|
||||
drd_srs_srt(def(IK::PCGTW, "pcgtw").gpr128()); // Parallel Compare for Greater Than Word
|
||||
drd_srs_srt(def(IK::PCEQB, "pceqb").gpr128()); // Parallel Compare for Equal Byte
|
||||
drd_srs_srt(def(IK::PCEQW, "pceqw").gpr128()); // Parallel Compare for Equal Word
|
||||
drd_srs_srt(def(IK::PEXTUB, "pextub").gpr128()); // Parallel Extend Upper from Byte
|
||||
drd_srs_srt(def(IK::PEXTUH, "pextuh").gpr128()); // Parallel Extend Upper from Halfword
|
||||
drd_srs_srt(def(IK::PEXTUW, "pextuw").gpr128()); // Parallel Extend Upper from Word
|
||||
drd_srs_srt(def(IK::PCPYUD, "pcpyud").gpr128()); // Parallel Copy Upper Doubleword
|
||||
drd_srs_srt(def(IK::PCPYLD, "pcpyld").gpr128()); // Parallel Copy Lower Doubleword
|
||||
drd_srs_srt(def(IK::PMADDH, "pmaddh").gpr128()); // Parallel Multiply-Add Halfword
|
||||
drd_srs_srt(def(IK::PMULTH, "pmulth").gpr128()); // Parallel Multiply Halfword
|
||||
drd_srs_srt(def(IK::PEXEW, "pexew").gpr128()); // Parallel Exchange Even Word
|
||||
drd_srs_srt(def(IK::PINTEH, "pinteh").gpr128()); // Parallel Interleave Even Halfword
|
||||
drd_srs_srt(def(IK::PAND, "pand").gpr128()); // Parallel And
|
||||
drd_srs_srt(def(IK::POR, "por").gpr128()); // Parallel Or
|
||||
drd_srs_srt(def(IK::PNOR, "pnor").gpr128()); // Parallel Not Or
|
||||
|
||||
drd_srt_ssa(def(IK::PSLLW, "psllw")); // Parallel Shift Left Logical Word
|
||||
drd_srt_ssa(def(IK::PSLLH, "psllh")); // Parallel Shift Left Logical Halfword
|
||||
drd_srt_ssa(def(IK::PSRAW, "psraw")); // Parallel Shift Right Arithmetic Word
|
||||
drd_srt_ssa(def(IK::PSRAH, "psrah")); // Parallel Shift Right Arithmetic Halfword
|
||||
drd_srt_ssa(def(IK::PSRLH, "psrlh")); // Parallel Shift Right Logical Halfword
|
||||
drd_srt_ssa(def(IK::PSLLW, "psllw").gpr128()); // Parallel Shift Left Logical Word
|
||||
drd_srt_ssa(def(IK::PSLLH, "psllh").gpr128()); // Parallel Shift Left Logical Halfword
|
||||
drd_srt_ssa(def(IK::PSRAW, "psraw").gpr128()); // Parallel Shift Right Arithmetic Word
|
||||
drd_srt_ssa(def(IK::PSRAH, "psrah").gpr128()); // Parallel Shift Right Arithmetic Halfword
|
||||
drd_srt_ssa(def(IK::PSRLH, "psrlh").gpr128()); // Parallel Shift Right Logical Halfword
|
||||
|
||||
def(IK::PLZCW, "plzcw").dst_gpr(FT::RD).src_gpr(FT::RS); // Parallel Leading Zero Count Word
|
||||
def(IK::PABSW, "pabsw").dst_gpr(FT::RD).src_gpr(FT::RT); // Parallel Absolute Word
|
||||
def(IK::PROT3W, "prot3w").dst_gpr(FT::RD).src_gpr(FT::RT); // Parallel Rotate 3 Word
|
||||
def(IK::PCPYH, "pcpyh").dst_gpr(FT::RD).src_gpr(FT::RT); // Parallel Copy Halfword
|
||||
def(IK::PLZCW, "plzcw")
|
||||
.dst_gpr(FT::RD)
|
||||
.src_gpr(FT::RS)
|
||||
.gpr128(); // Parallel Leading Zero Count Word
|
||||
def(IK::PABSW, "pabsw").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Absolute Word
|
||||
def(IK::PROT3W, "prot3w").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Rotate 3 Word
|
||||
def(IK::PCPYH, "pcpyh").dst_gpr(FT::RD).src_gpr(FT::RT).gpr128(); // Parallel Copy Halfword
|
||||
|
||||
// COP1
|
||||
|
||||
@@ -436,7 +439,7 @@ void init_opcode_info() {
|
||||
def(IK::VIADDI, "viaddi").dst_vi(FT::FT).src_vi(FT::FS).src(FT::IMM5, DT::IMM);
|
||||
|
||||
def(IK::QMFC2, "qmfc2").src(FT::IL, DT::IL).dst_gpr(FT::RT).src_vf(FT::FS);
|
||||
def(IK::QMTC2, "qmtc2").src(FT::IL, DT::IL).src_gpr(FT::RT).dst_vf(FT::FS);
|
||||
def(IK::QMTC2, "qmtc2").src(FT::IL, DT::IL).dst_vf(FT::FS).src_gpr(FT::RT);
|
||||
def(IK::VSQRT, "vsqrt").dst(FT::ZERO, DT::VU_Q).src_vf(FT::FT).src(FT::FT_F, DT::VF_F);
|
||||
def(IK::VRXOR, "vrxor").src(FT::BC, DT::BC).src_vf(FT::FS);
|
||||
def(IK::VRNEXT, "vrnext").src(FT::DEST, DT::DEST).dst_vf(FT::FT);
|
||||
@@ -518,4 +521,9 @@ OpcodeInfo& OpcodeInfo::dst_vf(FieldType field) {
|
||||
OpcodeInfo& OpcodeInfo::dst_vi(FieldType field) {
|
||||
return dst(field, DT::VI);
|
||||
}
|
||||
|
||||
OpcodeInfo& OpcodeInfo::gpr128() {
|
||||
gpr_128 = true;
|
||||
return *this;
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -335,6 +335,7 @@ struct OpcodeInfo {
|
||||
bool is_store = false;
|
||||
bool is_load = false;
|
||||
bool has_delay_slot = false;
|
||||
bool gpr_128 = false; // does it requires 128-bit registers?
|
||||
|
||||
void step(DecodeStep& s);
|
||||
|
||||
@@ -350,6 +351,8 @@ struct OpcodeInfo {
|
||||
OpcodeInfo& dst_vf(FieldType field);
|
||||
OpcodeInfo& dst_vi(FieldType field);
|
||||
|
||||
OpcodeInfo& gpr128();
|
||||
|
||||
uint8_t step_count = 0;
|
||||
DecodeStep steps[MAX_DECODE_STEPS];
|
||||
};
|
||||
|
||||
@@ -280,6 +280,7 @@ goos::Object UntilLoop_single::to_form() const {
|
||||
}
|
||||
|
||||
int UntilLoop_single::get_first_block_id() const {
|
||||
return block->get_first_block_id();
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
@@ -537,6 +538,10 @@ bool ControlFlowGraph::is_until_loop(CfgVtx* b1, CfgVtx* b2) {
|
||||
if (!b1 || !b2)
|
||||
return false;
|
||||
|
||||
if (b2->end_branch.asm_branch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check next and prev
|
||||
if (b1->next != b2)
|
||||
return false;
|
||||
@@ -575,6 +580,10 @@ bool ControlFlowGraph::is_goto_not_end_and_unreachable(CfgVtx* b0, CfgVtx* b1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (b0->end_branch.asm_branch || b1->end_branch.asm_branch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// b0 should be an always branch, not likely.
|
||||
if (!b0->end_branch.has_branch || !b0->end_branch.branch_always || b0->end_branch.branch_likely) {
|
||||
return false;
|
||||
@@ -785,7 +794,7 @@ bool ControlFlowGraph::find_until1_loop() {
|
||||
bool found = false;
|
||||
|
||||
for_each_top_level_vtx([&](CfgVtx* vtx) {
|
||||
if (vtx->succ_branch == vtx && vtx->succ_ft) {
|
||||
if (vtx->succ_branch == vtx && vtx->succ_ft && !vtx->end_branch.asm_branch) {
|
||||
auto loop = alloc<UntilLoop_single>();
|
||||
loop->block = vtx;
|
||||
loop->pred = vtx->pred;
|
||||
@@ -903,6 +912,9 @@ bool ControlFlowGraph::find_infinite_continue() {
|
||||
|
||||
fmt::print("Considering {} as an infinite continue:\n", b0->to_string());
|
||||
|
||||
if (b0->end_branch.asm_branch) {
|
||||
return true;
|
||||
}
|
||||
if (dest_block >= my_block) {
|
||||
fmt::print(" Rejecting because destination block {} comes after me {}\n", dest_block,
|
||||
my_block);
|
||||
@@ -1041,6 +1053,10 @@ bool ControlFlowGraph::is_sequence(CfgVtx* b0, CfgVtx* b1, bool allow_self_loops
|
||||
if (!b0 || !b1)
|
||||
return false;
|
||||
|
||||
// if (b0->end_branch.asm_branch || b1->end_branch.asm_branch) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (b0->next != b1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -298,6 +298,8 @@ std::string get_simple_expression_op_name(SimpleExpression::Kind kind) {
|
||||
return "vector-!2";
|
||||
case SimpleExpression::Kind::VECTOR_FLOAT_PRODUCT:
|
||||
return "vector-float*!2";
|
||||
case SimpleExpression::Kind::VECTOR_CROSS:
|
||||
return "veccross";
|
||||
case SimpleExpression::Kind::SUBU_L32_S7:
|
||||
return "subu-s7";
|
||||
case SimpleExpression::Kind::VECTOR_3_DOT:
|
||||
@@ -356,6 +358,7 @@ int get_simple_expression_arg_count(SimpleExpression::Kind kind) {
|
||||
case SimpleExpression::Kind::VECTOR_PLUS:
|
||||
case SimpleExpression::Kind::VECTOR_MINUS:
|
||||
case SimpleExpression::Kind::VECTOR_FLOAT_PRODUCT:
|
||||
case SimpleExpression::Kind::VECTOR_CROSS:
|
||||
return 3;
|
||||
case SimpleExpression::Kind::SUBU_L32_S7:
|
||||
return 1;
|
||||
|
||||
@@ -226,6 +226,7 @@ class SimpleExpression {
|
||||
VECTOR_PLUS,
|
||||
VECTOR_MINUS,
|
||||
VECTOR_FLOAT_PRODUCT,
|
||||
VECTOR_CROSS,
|
||||
SUBU_L32_S7, // use SUBU X, src0, s7 to check if lower 32-bits are s7.
|
||||
VECTOR_3_DOT,
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "decompiler/util/TP_Type.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
#include "decompiler/IR2/bitfields.h"
|
||||
#include "common/type_system/state.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
@@ -81,6 +82,8 @@ TP_Type SimpleAtom::get_type(const TypeState& input,
|
||||
// which actually means that you get the first address in the symbol table.
|
||||
// it's not really a linked symbol, but the basic op builder represents it as one.
|
||||
return TP_Type::make_from_ts(TypeSpec("pointer"));
|
||||
} else if (m_string == "enter-state") {
|
||||
return TP_Type::make_enter_state();
|
||||
}
|
||||
|
||||
// look up the type of the symbol
|
||||
@@ -187,16 +190,17 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
|
||||
case Kind::XOR:
|
||||
case Kind::LEFT_SHIFT:
|
||||
case Kind::MUL_UNSIGNED:
|
||||
case Kind::PCPYLD:
|
||||
return get_type_int2(input, env, dts);
|
||||
case Kind::NEG:
|
||||
case Kind::LOGNOT:
|
||||
return get_type_int1(input, env, dts);
|
||||
case Kind::DIV_UNSIGNED:
|
||||
case Kind::MOD_UNSIGNED:
|
||||
case Kind::PCPYLD:
|
||||
return TP_Type::make_from_ts("uint");
|
||||
case Kind::VECTOR_PLUS:
|
||||
case Kind::VECTOR_MINUS:
|
||||
case Kind::VECTOR_CROSS:
|
||||
return TP_Type::make_from_ts("vector");
|
||||
case Kind::VECTOR_FLOAT_PRODUCT:
|
||||
return TP_Type::make_from_ts("vector");
|
||||
@@ -257,7 +261,8 @@ TP_Type get_stack_type_at_constant_offset(int offset,
|
||||
|
||||
if (offset == structure.hint.stack_offset) {
|
||||
// special case just getting the variable
|
||||
if (structure.hint.container_type == StackStructureHint::ContainerType::NONE) {
|
||||
if (structure.hint.container_type == StackStructureHint::ContainerType::NONE ||
|
||||
structure.hint.container_type == StackStructureHint::ContainerType::INLINE_ARRAY) {
|
||||
return TP_Type::make_from_ts(coerce_to_reg_type(structure.ref_type));
|
||||
}
|
||||
}
|
||||
@@ -427,6 +432,21 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input,
|
||||
break;
|
||||
}
|
||||
|
||||
if (arg0_type.kind == TP_Type::Kind::PCPYUD_BITFIELD &&
|
||||
(m_kind == Kind::AND || m_kind == Kind::OR)) {
|
||||
// anding a bitfield should return the bitfield type.
|
||||
return TP_Type::make_from_pcpyud_bitfield(arg0_type.get_bitfield_type());
|
||||
}
|
||||
|
||||
// this is right but breaks something else right now.
|
||||
if (m_kind == Kind::PCPYLD && arg0_type.kind == TP_Type::Kind::PCPYUD_BITFIELD) {
|
||||
return arg1_type;
|
||||
}
|
||||
|
||||
if (m_kind == Kind::PCPYLD) {
|
||||
return TP_Type::make_from_ts("uint");
|
||||
}
|
||||
|
||||
if (arg0_type.kind == TP_Type::Kind::INTEGER_CONSTANT_PLUS_VAR_MULT && m_kind == Kind::ADD) {
|
||||
FieldReverseLookupInput rd_in;
|
||||
rd_in.offset = arg0_type.get_add_int_constant();
|
||||
@@ -554,6 +574,14 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input,
|
||||
return TP_Type::make_from_ts(arg1_type.typespec());
|
||||
}
|
||||
|
||||
if (m_kind == Kind::ADD && tc(dts, TypeSpec("structure"), arg0_type) &&
|
||||
arg1_type.is_integer_constant()) {
|
||||
auto type_info = dts.ts.lookup_type(arg0_type.typespec());
|
||||
if ((u64)type_info->get_size_in_memory() == arg1_type.get_integer_constant()) {
|
||||
return TP_Type::make_from_ts(arg0_type.typespec());
|
||||
}
|
||||
}
|
||||
|
||||
if (tc(dts, TypeSpec("structure"), arg1_type) && !m_args[0].is_int() &&
|
||||
is_int_or_uint(dts, arg0_type)) {
|
||||
if (arg1_type.typespec() == TypeSpec("symbol") &&
|
||||
@@ -775,9 +803,18 @@ TypeState SetVarConditionOp::propagate_types_internal(const TypeState& input,
|
||||
TypeState StoreOp::propagate_types_internal(const TypeState& input,
|
||||
const Env& env,
|
||||
DecompilerTypeSystem& dts) {
|
||||
TypeState output = input;
|
||||
|
||||
// look for setting the next state of the current process
|
||||
IR2_RegOffset ro;
|
||||
if (get_as_reg_offset(m_addr, &ro)) {
|
||||
if (ro.reg == Register(Reg::GPR, Reg::S6) && ro.offset == 72) {
|
||||
output.next_state_type = m_value.get_type(input, env, dts);
|
||||
}
|
||||
}
|
||||
(void)env;
|
||||
(void)dts;
|
||||
return input;
|
||||
return output;
|
||||
}
|
||||
|
||||
TP_Type LoadVarOp::get_src_type(const TypeState& input,
|
||||
@@ -1090,6 +1127,26 @@ TypeState CallOp::propagate_types_internal(const TypeState& input,
|
||||
throw std::runtime_error("Called something that was not a function: " + in_type.print());
|
||||
}
|
||||
|
||||
// If we call enter-state, update our type.
|
||||
if (in_tp.kind == TP_Type::Kind::ENTER_STATE_FUNCTION) {
|
||||
// this is a GO!
|
||||
auto state_type = input.next_state_type.typespec();
|
||||
if (state_type.base_type() != "state") {
|
||||
throw std::runtime_error(
|
||||
fmt::format("At op {}, called enter-state, but the current next-state has type {}, which "
|
||||
"is not a valid state.",
|
||||
m_my_idx, input.next_state_type.print()));
|
||||
}
|
||||
|
||||
if (state_type.arg_count() == 0) {
|
||||
throw std::runtime_error(fmt::format(
|
||||
"At op {}, tried to enter-state, but the type of (-> s6 next-state) is just a plain "
|
||||
"state. The decompiler must know the specific state type.",
|
||||
m_my_idx));
|
||||
}
|
||||
in_type = state_to_go_function(state_type);
|
||||
}
|
||||
|
||||
if (in_type.arg_count() < 1) {
|
||||
throw std::runtime_error("Called a function, but we do not know its type");
|
||||
}
|
||||
@@ -1189,8 +1246,11 @@ void FunctionEndOp::mark_function_as_no_return_value() {
|
||||
}
|
||||
|
||||
TypeState AsmBranchOp::propagate_types_internal(const TypeState& input,
|
||||
const Env&,
|
||||
DecompilerTypeSystem&) {
|
||||
const Env& env,
|
||||
DecompilerTypeSystem& dts) {
|
||||
if (m_branch_delay) {
|
||||
return m_branch_delay->propagate_types(input, env, dts);
|
||||
}
|
||||
// for now, just make everything uint
|
||||
TypeState output = input;
|
||||
for (auto x : m_write_regs) {
|
||||
@@ -1198,6 +1258,7 @@ TypeState AsmBranchOp::propagate_types_internal(const TypeState& input,
|
||||
output.get(x) = TP_Type::make_from_ts("uint");
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -1207,8 +1268,8 @@ TypeState StackSpillLoadOp::propagate_types_internal(const TypeState& input,
|
||||
// stack slot load
|
||||
auto info = env.stack_spills().lookup(m_offset);
|
||||
if (info.size != m_size) {
|
||||
env.func->warnings.general_warning(
|
||||
"Stack slot load mismatch: defined as size {}, got size {}\n", info.size, m_size);
|
||||
env.func->warnings.general_warning("Stack slot load mismatch: defined as size {}, got size {}",
|
||||
info.size, m_size);
|
||||
}
|
||||
|
||||
if (info.is_signed != m_is_signed) {
|
||||
|
||||
+30
-18
@@ -117,6 +117,10 @@ goos::Object Env::get_variable_name_with_cast(const RegisterAccess& access) cons
|
||||
}
|
||||
}
|
||||
|
||||
std::string Env::get_variable_name(const RegisterAccess& access) const {
|
||||
return get_variable_and_cast(access).name;
|
||||
}
|
||||
|
||||
VariableWithCast Env::get_variable_and_cast(const RegisterAccess& access) const {
|
||||
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
|
||||
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
|
||||
@@ -250,19 +254,6 @@ std::optional<TypeSpec> Env::get_user_cast_for_access(const RegisterAccess& acce
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string Env::get_variable_name(const RegisterAccess& access) const {
|
||||
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
|
||||
std::string lookup_name = m_var_names.lookup(access.reg(), access.idx(), access.mode()).name();
|
||||
auto remapped = m_var_remap.find(lookup_name);
|
||||
if (remapped != m_var_remap.end()) {
|
||||
lookup_name = remapped->second;
|
||||
}
|
||||
return lookup_name;
|
||||
} else {
|
||||
throw std::runtime_error("Cannot store a variable in this reg");
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the type of the variable currently in the register.
|
||||
* NOTE: this is _NOT_ the most specific type known to the decompiler, but instead the type
|
||||
@@ -527,12 +518,12 @@ void Env::set_stack_structure_hints(const std::vector<StackStructureHint>& hints
|
||||
for (auto& hint : hints) {
|
||||
StackStructureEntry entry;
|
||||
entry.hint = hint;
|
||||
// parse the type spec.
|
||||
TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
|
||||
auto type_info = dts->ts.lookup_type(base_typespec);
|
||||
|
||||
switch (hint.container_type) {
|
||||
case StackStructureHint::ContainerType::NONE:
|
||||
case StackStructureHint::ContainerType::NONE: {
|
||||
// parse the type spec.
|
||||
TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
|
||||
auto type_info = dts->ts.lookup_type(base_typespec);
|
||||
// just a plain object on the stack.
|
||||
if (!type_info->is_reference()) {
|
||||
throw std::runtime_error(
|
||||
@@ -549,8 +540,29 @@ void Env::set_stack_structure_hints(const std::vector<StackStructureHint>& hints
|
||||
entry.ref_type.print(), entry.hint.stack_offset,
|
||||
type_info->get_in_memory_alignment());
|
||||
}
|
||||
} break;
|
||||
|
||||
break;
|
||||
case StackStructureHint::ContainerType::INLINE_ARRAY: {
|
||||
TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
|
||||
auto type_info = dts->ts.lookup_type(base_typespec);
|
||||
if (!type_info->is_reference()) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("Stack inline-array element type {} is not a reference and cannot be "
|
||||
"stored in an inline-array. Use an array instead.",
|
||||
base_typespec.print()));
|
||||
}
|
||||
|
||||
entry.ref_type = TypeSpec("inline-array", {TypeSpec(base_typespec)});
|
||||
entry.size = 1; // we assume that there is no constant propagation into this array and
|
||||
// make this only trigger in get_stack_type if we hit exactly.
|
||||
// sanity check the alignment
|
||||
if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) !=
|
||||
entry.hint.stack_offset) {
|
||||
lg::error("Misaligned stack variable of type {} offset {} required align {}\n",
|
||||
entry.ref_type.print(), entry.hint.stack_offset,
|
||||
type_info->get_in_memory_alignment());
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ class Env {
|
||||
VariableWithCast get_variable_and_cast(const RegisterAccess& access) const;
|
||||
std::optional<TypeSpec> get_user_cast_for_access(const RegisterAccess& access) const;
|
||||
TypeSpec get_variable_type(const RegisterAccess& access, bool using_user_var_types) const;
|
||||
TP_Type get_variable_tp_type(const RegisterAccess& access, bool using_user_var_types) const;
|
||||
|
||||
/*!
|
||||
* Get the types in registers _after_ the given operation has completed.
|
||||
|
||||
+139
-4
@@ -454,6 +454,13 @@ goos::Object SetFormFormElement::to_form_internal(const Env& env) const {
|
||||
|
||||
goos::Object SetFormFormElement::to_form_for_define(const Env& env) const {
|
||||
if (m_cast_for_define) {
|
||||
// for vu-function, we just put a 0. These aren't supported
|
||||
if (*m_cast_for_define == TypeSpec("vu-function")) {
|
||||
return pretty_print::build_list(
|
||||
fmt::format("define"), m_dst->to_form(env),
|
||||
pretty_print::build_list(fmt::format("the-as {}", m_cast_for_define->print()),
|
||||
pretty_print::to_symbol("0")));
|
||||
}
|
||||
return pretty_print::build_list(
|
||||
fmt::format("define"), m_dst->to_form(env),
|
||||
pretty_print::build_list(fmt::format("the-as {}", m_cast_for_define->print()),
|
||||
@@ -939,9 +946,13 @@ goos::Object BreakElement::to_form_internal(const Env& env) const {
|
||||
forms.push_back(pretty_print::build_list(return_code->to_form(env)));
|
||||
forms.push_back(pretty_print::build_list(dead_code->to_form(env)));
|
||||
} else {
|
||||
forms.push_back(pretty_print::to_symbol("begin"));
|
||||
return_code->inline_forms(forms, env);
|
||||
forms.push_back(pretty_print::build_list(fmt::format("goto cfg-{}", lid)));
|
||||
if (return_code->try_as_element<EmptyElement>()) {
|
||||
return pretty_print::build_list(fmt::format("goto cfg-{}", lid));
|
||||
} else {
|
||||
forms.push_back(pretty_print::to_symbol("begin"));
|
||||
return_code->inline_forms(forms, env);
|
||||
forms.push_back(pretty_print::build_list(fmt::format("goto cfg-{}", lid)));
|
||||
}
|
||||
}
|
||||
return pretty_print::build_list(forms);
|
||||
}
|
||||
@@ -1363,6 +1374,107 @@ void CondNoElseElement::get_modified_regs(RegSet& regs) const {
|
||||
}
|
||||
}
|
||||
|
||||
CaseElement::CaseElement(Form* value, const std::vector<Entry>& entries, Form* else_body)
|
||||
: m_value(value), m_entries(entries), m_else_body(else_body) {
|
||||
m_value->parent_element = this;
|
||||
for (auto& entry : m_entries) {
|
||||
for (auto& val : entry.vals) {
|
||||
val->parent_element = this;
|
||||
}
|
||||
entry.body->parent_element = this;
|
||||
}
|
||||
if (m_else_body) {
|
||||
m_else_body->parent_element = this;
|
||||
}
|
||||
}
|
||||
|
||||
goos::Object CaseElement::to_form_internal(const Env& env) const {
|
||||
std::vector<goos::Object> list;
|
||||
list.push_back(pretty_print::to_symbol("case"));
|
||||
list.push_back(m_value->to_form(env));
|
||||
for (auto& e : m_entries) {
|
||||
std::vector<goos::Object> entry;
|
||||
|
||||
// cases
|
||||
std::vector<goos::Object> cases;
|
||||
for (auto& val : e.vals) {
|
||||
cases.push_back(val->to_form(env));
|
||||
}
|
||||
entry.push_back(pretty_print::build_list(cases));
|
||||
|
||||
// body
|
||||
e.body->inline_forms(entry, env);
|
||||
list.push_back(pretty_print::build_list(entry));
|
||||
}
|
||||
|
||||
if (m_else_body) {
|
||||
std::vector<goos::Object> entry;
|
||||
entry.push_back(pretty_print::to_symbol("else"));
|
||||
m_else_body->inline_forms(entry, env);
|
||||
list.push_back(pretty_print::build_list(entry));
|
||||
}
|
||||
return pretty_print::build_list(list);
|
||||
}
|
||||
|
||||
void CaseElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
f(this);
|
||||
m_value->apply(f);
|
||||
for (auto& e : m_entries) {
|
||||
for (auto& val : e.vals) {
|
||||
val->apply(f);
|
||||
}
|
||||
e.body->apply(f);
|
||||
}
|
||||
|
||||
if (m_else_body) {
|
||||
m_else_body->apply(f);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseElement::apply_form(const std::function<void(Form*)>& f) {
|
||||
m_value->apply_form(f);
|
||||
for (auto& e : m_entries) {
|
||||
for (auto& val : e.vals) {
|
||||
val->apply_form(f);
|
||||
}
|
||||
e.body->apply_form(f);
|
||||
}
|
||||
|
||||
if (m_else_body) {
|
||||
m_else_body->apply_form(f);
|
||||
}
|
||||
}
|
||||
|
||||
void CaseElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
||||
if (recursive) {
|
||||
m_value->collect_vars(vars, recursive);
|
||||
for (auto& e : m_entries) {
|
||||
for (auto& val : e.vals) {
|
||||
val->collect_vars(vars, recursive);
|
||||
}
|
||||
e.body->collect_vars(vars, recursive);
|
||||
}
|
||||
|
||||
if (m_else_body) {
|
||||
m_else_body->collect_vars(vars, recursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaseElement::get_modified_regs(RegSet& regs) const {
|
||||
m_value->get_modified_regs(regs);
|
||||
for (auto& e : m_entries) {
|
||||
for (auto& val : e.vals) {
|
||||
val->get_modified_regs(regs);
|
||||
}
|
||||
e.body->get_modified_regs(regs);
|
||||
}
|
||||
|
||||
if (m_else_body) {
|
||||
m_else_body->get_modified_regs(regs);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// AbsElement
|
||||
/////////////////////////////
|
||||
@@ -1634,14 +1746,26 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
||||
return "fmax";
|
||||
case FixedOperatorKind::LOGAND:
|
||||
return "logand";
|
||||
case FixedOperatorKind::LOGAND_IN_PLACE:
|
||||
return "logand!";
|
||||
case FixedOperatorKind::LOGIOR:
|
||||
return "logior";
|
||||
case FixedOperatorKind::LOGIOR_IN_PLACE:
|
||||
return "logior!";
|
||||
case FixedOperatorKind::LOGXOR:
|
||||
return "logxor";
|
||||
case FixedOperatorKind::LOGNOR:
|
||||
return "lognor";
|
||||
case FixedOperatorKind::LOGNOT:
|
||||
return "lognot";
|
||||
case FixedOperatorKind::LOGCLEAR:
|
||||
return "logclear";
|
||||
case FixedOperatorKind::LOGCLEAR_IN_PLACE:
|
||||
return "logclear!";
|
||||
case FixedOperatorKind::LOGTEST:
|
||||
return "logtest?";
|
||||
case FixedOperatorKind::LOGTESTA:
|
||||
return "logtesta?";
|
||||
case FixedOperatorKind::SHL:
|
||||
return "shl";
|
||||
case FixedOperatorKind::SHR:
|
||||
@@ -1696,6 +1820,8 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
||||
return "vector-!";
|
||||
case FixedOperatorKind::VECTOR_PLUS:
|
||||
return "vector+!";
|
||||
case FixedOperatorKind::VECTOR_CROSS:
|
||||
return "vector-cross!";
|
||||
case FixedOperatorKind::VECTOR_FLOAT_PRODUCT:
|
||||
return "vector-float*!";
|
||||
case FixedOperatorKind::L32_NOT_FALSE_CBOOL:
|
||||
@@ -1799,10 +1925,11 @@ void GenericElement::get_modified_regs(RegSet& regs) const {
|
||||
|
||||
CastElement::CastElement(TypeSpec type, Form* source, bool numeric)
|
||||
: m_type(std::move(type)), m_source(source), m_numeric(numeric) {
|
||||
source->parent_element = this;
|
||||
m_source->parent_element = this;
|
||||
}
|
||||
|
||||
goos::Object CastElement::to_form_internal(const Env& env) const {
|
||||
// assert(m_source->parent_element == this);
|
||||
auto atom = form_as_atom(m_source);
|
||||
if (atom && atom->is_var()) {
|
||||
return pretty_print::build_list(
|
||||
@@ -1814,21 +1941,25 @@ goos::Object CastElement::to_form_internal(const Env& env) const {
|
||||
}
|
||||
|
||||
void CastElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
// assert(m_source->parent_element == this);
|
||||
f(this);
|
||||
m_source->apply(f);
|
||||
}
|
||||
|
||||
void CastElement::apply_form(const std::function<void(Form*)>& f) {
|
||||
// assert(m_source->parent_element == this);
|
||||
m_source->apply_form(f);
|
||||
}
|
||||
|
||||
void CastElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
||||
// assert(m_source->parent_element == this);
|
||||
if (recursive) {
|
||||
m_source->collect_vars(vars, recursive);
|
||||
}
|
||||
}
|
||||
|
||||
void CastElement::get_modified_regs(RegSet& regs) const {
|
||||
assert(m_source->parent_element == this);
|
||||
m_source->get_modified_regs(regs);
|
||||
}
|
||||
|
||||
@@ -2486,6 +2617,10 @@ goos::Object StackStructureDefElement::to_form_internal(const Env&) const {
|
||||
case StackStructureHint::ContainerType::NONE:
|
||||
return pretty_print::build_list(
|
||||
fmt::format("new 'stack-no-clear '{}", m_entry.ref_type.print()));
|
||||
case StackStructureHint::ContainerType::INLINE_ARRAY:
|
||||
return pretty_print::build_list(fmt::format("new 'stack-no-clear 'inline-array '{} {}",
|
||||
m_entry.ref_type.get_single_arg().print(),
|
||||
m_entry.hint.container_size));
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
+42
-7
@@ -54,6 +54,10 @@ class FormElement {
|
||||
bool allow_side_effects);
|
||||
bool is_popped() const { return m_popped; }
|
||||
|
||||
FormElement() = default;
|
||||
FormElement(const FormElement& other) = delete;
|
||||
FormElement& operator=(const FormElement& other) = delete;
|
||||
|
||||
void mark_popped() {
|
||||
assert(!m_popped);
|
||||
m_popped = true;
|
||||
@@ -185,6 +189,11 @@ class SimpleExpressionElement : public FormElement {
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
FormElement* update_from_stack_logor_or_logand_helper(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_logor_or_logand(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
@@ -196,12 +205,12 @@ class SimpleExpressionElement : public FormElement {
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_vector_plus_minus(bool is_add,
|
||||
const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_vector_plus_minus_cross(FixedOperatorKind op_kind,
|
||||
const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_vector_float_product(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
@@ -842,6 +851,27 @@ class CondNoElseElement : public FormElement {
|
||||
bool allow_in_if() const override { return false; }
|
||||
};
|
||||
|
||||
class CaseElement : public FormElement {
|
||||
public:
|
||||
struct Entry {
|
||||
std::vector<Form*> vals;
|
||||
Form* body = nullptr;
|
||||
};
|
||||
|
||||
CaseElement(Form* value, const std::vector<Entry>& entries, Form* else_body);
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
void collect_vars(RegAccessSet& vars, bool recursive) const override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
bool allow_in_if() const override { return false; }
|
||||
|
||||
private:
|
||||
Form* m_value = nullptr;
|
||||
std::vector<Entry> m_entries;
|
||||
Form* m_else_body = nullptr; // may be nullptr, if no else.
|
||||
};
|
||||
|
||||
/*!
|
||||
* Represents a (abs x) expression.
|
||||
*/
|
||||
@@ -1253,6 +1283,7 @@ class ConstantFloatElement : public FormElement {
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) override;
|
||||
float value() const { return m_value; }
|
||||
|
||||
private:
|
||||
float m_value;
|
||||
@@ -1749,5 +1780,9 @@ GenericElement* alloc_generic_token_op(const std::string& name,
|
||||
const std::vector<Form*>& args,
|
||||
FormPool& pool);
|
||||
Form* alloc_var_form(const RegisterAccess& var, FormPool& pool);
|
||||
Form* try_cast_simplify(Form* in, const TypeSpec& new_type, FormPool& pool, const Env& env);
|
||||
Form* try_cast_simplify(Form* in,
|
||||
const TypeSpec& new_type,
|
||||
FormPool& pool,
|
||||
const Env& env,
|
||||
bool tc_pass = false);
|
||||
} // namespace decompiler
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -349,9 +349,9 @@ std::vector<FormElement*> FormStack::rewrite(FormPool& pool, const Env& env) con
|
||||
|
||||
auto elt = pool.alloc_element<SetVarElement>(*e.destination, simplified_source,
|
||||
e.sequence_point, type, e.set_info);
|
||||
e.source->parent_element = elt;
|
||||
|
||||
auto final_elt = try_rewrites_in_place(elt, env, pool);
|
||||
simplified_source->parent_element = final_elt;
|
||||
result.push_back(final_elt);
|
||||
} else {
|
||||
result.push_back(e.elt);
|
||||
@@ -411,7 +411,6 @@ std::optional<RegisterAccess> rewrite_to_get_var(std::vector<FormElement*>& defa
|
||||
return {};
|
||||
} else {
|
||||
for (auto x : result) {
|
||||
x->parent_form = nullptr;
|
||||
default_result.push_back(x);
|
||||
}
|
||||
return result_access;
|
||||
|
||||
@@ -119,10 +119,16 @@ enum class FixedOperatorKind {
|
||||
FMIN,
|
||||
FMAX,
|
||||
LOGAND,
|
||||
LOGAND_IN_PLACE,
|
||||
LOGIOR,
|
||||
LOGIOR_IN_PLACE,
|
||||
LOGXOR,
|
||||
LOGNOR,
|
||||
LOGNOT,
|
||||
LOGCLEAR,
|
||||
LOGCLEAR_IN_PLACE,
|
||||
LOGTEST,
|
||||
LOGTESTA,
|
||||
SHL,
|
||||
SHR,
|
||||
SAR,
|
||||
@@ -150,6 +156,7 @@ enum class FixedOperatorKind {
|
||||
ASM_MADDS,
|
||||
VECTOR_PLUS,
|
||||
VECTOR_MINUS,
|
||||
VECTOR_CROSS,
|
||||
VECTOR_FLOAT_PRODUCT,
|
||||
L32_NOT_FALSE_CBOOL,
|
||||
VECTOR_3_DOT,
|
||||
|
||||
@@ -12,7 +12,28 @@ const std::map<InstructionKind, OpenGOALAsm::Function> MIPS_ASM_TO_OPEN_GOAL_FUN
|
||||
{InstructionKind::PSRAW, {".pw.sra", {}}},
|
||||
{InstructionKind::PSUBW, {".psubw", {}}},
|
||||
|
||||
// Boolean Arithmetic - or / not or / and
|
||||
{InstructionKind::POR, {".por", {}}},
|
||||
{InstructionKind::PNOR, {".pnor", {}}},
|
||||
{InstructionKind::PAND, {".pand", {}}},
|
||||
|
||||
// Parallel Pack
|
||||
{InstructionKind::PPACH, {".ppach", {}}},
|
||||
|
||||
// Parallel Compares
|
||||
{InstructionKind::PCEQB, {".pceqb", {}}},
|
||||
// {InstructionKind::PCEQH, {".pceqh", {}}},
|
||||
{InstructionKind::PCEQW, {".pceqw", {}}},
|
||||
// {InstructionKind::PCGTB, {".pcgtb", {}}},
|
||||
// {InstructionKind::PCGTH, {".pcgth", {}}},
|
||||
{InstructionKind::PCGTW, {".pcgtw", {}}},
|
||||
|
||||
// Parallel Extends
|
||||
{InstructionKind::PEXTUB, {".pextub", {}}},
|
||||
{InstructionKind::PEXTUH, {".pextuh", {}}},
|
||||
{InstructionKind::PEXTUW, {".pextuw", {}}},
|
||||
{InstructionKind::PEXTLB, {".pextlb", {}}},
|
||||
{InstructionKind::PEXTLH, {".pextlh", {}}},
|
||||
{InstructionKind::PEXTLW, {".pextlw", {}}},
|
||||
{InstructionKind::PCPYLD, {".pcpyld", {}}},
|
||||
{InstructionKind::PCPYUD, {".pcpyud", {}}},
|
||||
@@ -109,13 +130,11 @@ const std::map<InstructionKind, OpenGOALAsm::Function> MIPS_ASM_TO_OPEN_GOAL_FUN
|
||||
//// Fixed point conversions
|
||||
{InstructionKind::VFTOI0, {".ftoi.vf", {MOD::DEST_MASK}}},
|
||||
{InstructionKind::VITOF0, {".itof.vf", {MOD::DEST_MASK}}},
|
||||
|
||||
{InstructionKind::VFTOI4, {"TODO.VFTOI4", {}}},
|
||||
|
||||
{InstructionKind::VITOF12, {"TODO.VITOF12", {}}},
|
||||
{InstructionKind::VFTOI12, {"TODO.VFTOI12", {}}},
|
||||
|
||||
{InstructionKind::VITOF15, {"TODO.VITOF15", {}}},
|
||||
// NOTE - Only the .xyzw mask is supported via macros!
|
||||
{InstructionKind::VFTOI4, {"vftoi4.xyzw", {MOD::DEST_MASK}}},
|
||||
{InstructionKind::VITOF12, {"vitof12.xyzw", {MOD::DEST_MASK}}},
|
||||
{InstructionKind::VFTOI12, {"vftoi12.xyzw", {MOD::DEST_MASK}}},
|
||||
{InstructionKind::VITOF15, {"vitof15.xyzw", {MOD::DEST_MASK}}},
|
||||
|
||||
//// Status Checks
|
||||
{InstructionKind::VCLIP, {"TODO.VCLIP", {}}},
|
||||
@@ -174,7 +193,7 @@ std::vector<goos::Object> OpenGOALAsm::get_args(const std::vector<DecompilerLabe
|
||||
|
||||
if (v.has_value()) {
|
||||
// Normal register / constant args
|
||||
args.push_back(v.value().to_form(env));
|
||||
args.push_back(v.value().to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST));
|
||||
} else if (atom.kind == InstructionAtom::AtomKind::VF_FIELD) {
|
||||
// Handle FTF/FSF operations
|
||||
if (func.allows_modifier(MOD::FTF) && func.allows_modifier(MOD::FSF)) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/util/BitUtils.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
#include "decompiler/IR2/GenericElementMatcher.h"
|
||||
#include "decompiler/Function/Function.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
@@ -84,8 +85,12 @@ void BitfieldStaticDefElement::get_modified_regs(RegSet& regs) const {
|
||||
ModifiedCopyBitfieldElement::ModifiedCopyBitfieldElement(
|
||||
const TypeSpec& type,
|
||||
Form* base,
|
||||
bool from_pcpyud,
|
||||
const std::vector<BitFieldDef>& field_modifications)
|
||||
: m_type(type), m_base(base), m_field_modifications(field_modifications) {
|
||||
: m_type(type),
|
||||
m_base(base),
|
||||
m_field_modifications(field_modifications),
|
||||
m_from_pcpyud(from_pcpyud) {
|
||||
m_base->parent_element = this;
|
||||
for (auto& mod : m_field_modifications) {
|
||||
if (mod.value) {
|
||||
@@ -95,13 +100,23 @@ ModifiedCopyBitfieldElement::ModifiedCopyBitfieldElement(
|
||||
}
|
||||
|
||||
goos::Object ModifiedCopyBitfieldElement::to_form_internal(const Env& env) const {
|
||||
std::vector<goos::Object> result = {pretty_print::to_symbol("copy-and-set-bf")};
|
||||
result.push_back(m_base->to_form(env));
|
||||
for (auto& def : m_field_modifications) {
|
||||
result.push_back(pretty_print::to_symbol(fmt::format(":{}", def.field_name)));
|
||||
result.push_back(def.value->to_form(env));
|
||||
if (m_field_modifications.size() == 1) {
|
||||
std::vector<goos::Object> result = {pretty_print::to_symbol("copy-and-set-field")};
|
||||
result.push_back(m_base->to_form(env));
|
||||
for (auto& def : m_field_modifications) {
|
||||
result.push_back(pretty_print::to_symbol(fmt::format("{}", def.field_name)));
|
||||
result.push_back(def.value->to_form(env));
|
||||
}
|
||||
return pretty_print::build_list(result);
|
||||
} else {
|
||||
std::vector<goos::Object> result = {pretty_print::to_symbol("copy-and-set-bf-multi")};
|
||||
result.push_back(m_base->to_form(env));
|
||||
for (auto& def : m_field_modifications) {
|
||||
result.push_back(pretty_print::to_symbol(fmt::format(":{}", def.field_name)));
|
||||
result.push_back(def.value->to_form(env));
|
||||
}
|
||||
return pretty_print::build_list(result);
|
||||
}
|
||||
return pretty_print::build_list(result);
|
||||
}
|
||||
|
||||
void ModifiedCopyBitfieldElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
@@ -220,7 +235,8 @@ BitField find_field(const TypeSystem& ts,
|
||||
namespace {
|
||||
std::optional<BitField> find_field_from_mask(const TypeSystem& ts,
|
||||
const BitFieldType* type,
|
||||
uint64_t mask) {
|
||||
uint64_t mask,
|
||||
bool upper_64) {
|
||||
// try to find a field that is masked by this:
|
||||
auto mask_range = get_bit_range(mask);
|
||||
if (!mask_range) {
|
||||
@@ -228,6 +244,10 @@ std::optional<BitField> find_field_from_mask(const TypeSystem& ts,
|
||||
return {};
|
||||
}
|
||||
|
||||
if (upper_64) {
|
||||
mask_range = Range<int>(mask_range->first() + 64, mask_range->last() + 64);
|
||||
}
|
||||
|
||||
return find_field(ts, type, mask_range->first(), mask_range->size(), {});
|
||||
}
|
||||
|
||||
@@ -241,7 +261,8 @@ Form* strip_int_or_uint_cast(Form* in) {
|
||||
|
||||
std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
|
||||
const BitFieldType* type,
|
||||
const TypeSystem& ts) {
|
||||
const TypeSystem& ts,
|
||||
int offset_in_bitfield) {
|
||||
// (shr (shl arg1 59) 44) for example
|
||||
{
|
||||
auto matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHR),
|
||||
@@ -255,7 +276,7 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
|
||||
int right = mr.maps.ints.at(2);
|
||||
int size = 64 - left;
|
||||
int offset = left - right;
|
||||
auto f = find_field(ts, type, offset, size, {});
|
||||
auto f = find_field(ts, type, offset + offset_in_bitfield, size, {});
|
||||
BitFieldDef def;
|
||||
def.value = value;
|
||||
def.field_name = f.name();
|
||||
@@ -278,7 +299,7 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
|
||||
int right = *power_of_two;
|
||||
int size = 64 - left;
|
||||
int offset = left - right;
|
||||
auto f = find_field(ts, type, offset, size, {});
|
||||
auto f = find_field(ts, type, offset + offset_in_bitfield, size, {});
|
||||
BitFieldDef def;
|
||||
def.value = value;
|
||||
def.field_name = f.name();
|
||||
@@ -298,7 +319,7 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
|
||||
int right = 0;
|
||||
int size = 64 - left;
|
||||
int offset = left - right;
|
||||
auto f = find_field(ts, type, offset, size, {});
|
||||
auto f = find_field(ts, type, offset + offset_in_bitfield, size, {});
|
||||
BitFieldDef def;
|
||||
def.value = value;
|
||||
def.field_name = f.name();
|
||||
@@ -313,7 +334,7 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
|
||||
auto value = mr_sllv.maps.forms.at(0);
|
||||
int size = 32;
|
||||
int offset = 0;
|
||||
auto f = find_field(ts, type, offset, size, {});
|
||||
auto f = find_field(ts, type, offset + offset_in_bitfield, size, {});
|
||||
BitFieldDef def;
|
||||
def.value = value;
|
||||
def.field_name = f.name();
|
||||
@@ -345,6 +366,19 @@ void BitfieldAccessElement::push_pcpyud(const TypeSystem& ts, FormPool& pool, co
|
||||
}
|
||||
}
|
||||
|
||||
std::string BitfieldAccessElement::debug_print(const Env& env) const {
|
||||
std::string result = "BitfieldAccessElement:";
|
||||
if (m_got_pcpyud) {
|
||||
result += "pcpyud";
|
||||
}
|
||||
result += '\n';
|
||||
result += fmt::format("base: {}\n", m_base->to_string(env));
|
||||
for (auto& step : m_steps) {
|
||||
result += fmt::format(" {}\n", step.print());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a step to the bitfield access. If this completes the access, returns a form representing the
|
||||
* access
|
||||
@@ -434,9 +468,7 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
|
||||
if (m_steps.empty() && step.kind == BitfieldManip::Kind::LOGAND_WITH_CONSTANT_INT) {
|
||||
// and with mask
|
||||
if (m_got_pcpyud) {
|
||||
throw std::runtime_error("unknown pcpyud LOGAND_WITH_CONSTANT_INT sequence in bitfield");
|
||||
}
|
||||
// no need to do anything with pcpyud here.
|
||||
m_steps.push_back(step);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -449,7 +481,7 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
auto type = ts.lookup_type(m_type);
|
||||
auto as_bitfield = dynamic_cast<BitFieldType*>(type);
|
||||
assert(as_bitfield);
|
||||
auto field = find_field_from_mask(ts, as_bitfield, m_steps.at(0).amount);
|
||||
auto field = find_field_from_mask(ts, as_bitfield, m_steps.at(0).amount, false); // todo PCPYUP
|
||||
if (field) {
|
||||
auto get_field = pool.alloc_element<DerefElement>(m_base, false,
|
||||
DerefToken::make_field_name(field->name()));
|
||||
@@ -462,9 +494,6 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
|
||||
if (m_steps.size() == 1 && m_steps.at(0).kind == BitfieldManip::Kind::LOGAND_WITH_CONSTANT_INT &&
|
||||
step.kind == BitfieldManip::Kind::LOGIOR_WITH_CONSTANT_INT) {
|
||||
if (m_got_pcpyud) {
|
||||
throw std::runtime_error("unknown pcpyud LOGIOR_WITH_CONSTANT_INT sequence in bitfield");
|
||||
}
|
||||
// this is setting a bitfield to a constant.
|
||||
// first, let's check that the mask is used properly:
|
||||
u64 mask = m_steps.at(0).amount;
|
||||
@@ -477,7 +506,7 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
auto as_bitfield = dynamic_cast<BitFieldType*>(type);
|
||||
assert(as_bitfield);
|
||||
// use the mask to figure out the field.
|
||||
auto field = find_field_from_mask(ts, as_bitfield, ~mask);
|
||||
auto field = find_field_from_mask(ts, as_bitfield, ~mask, m_got_pcpyud);
|
||||
assert(field);
|
||||
bool is_signed =
|
||||
ts.tc(TypeSpec("int"), field->type()) && !ts.tc(TypeSpec("uint"), field->type());
|
||||
@@ -485,24 +514,21 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
// use the field to figure out what value is being set.
|
||||
u64 set_value;
|
||||
if (is_signed) {
|
||||
set_value = extract_bitfield<s64>(value, field->offset(), field->size());
|
||||
set_value = extract_bitfield<s64>(value, field->offset() - pcpyud_offset, field->size());
|
||||
} else {
|
||||
set_value = extract_bitfield<u64>(value, field->offset(), field->size());
|
||||
set_value = extract_bitfield<u64>(value, field->offset() - pcpyud_offset, field->size());
|
||||
}
|
||||
|
||||
BitFieldDef def;
|
||||
def.field_name = field->name();
|
||||
def.value = pool.alloc_single_element_form<SimpleAtomElement>(
|
||||
nullptr, SimpleAtom::make_int_constant(set_value));
|
||||
return pool.alloc_element<ModifiedCopyBitfieldElement>(m_type, m_base,
|
||||
return pool.alloc_element<ModifiedCopyBitfieldElement>(m_type, m_base, m_got_pcpyud,
|
||||
std::vector<BitFieldDef>{def});
|
||||
}
|
||||
|
||||
if (m_steps.size() == 1 && m_steps.at(0).kind == BitfieldManip::Kind::LOGAND_WITH_CONSTANT_INT &&
|
||||
step.kind == BitfieldManip::Kind::LOGIOR_WITH_FORM) {
|
||||
if (m_got_pcpyud) {
|
||||
throw std::runtime_error("unknown pcpyud LOGIOR_WITH_FORM sequence in bitfield");
|
||||
}
|
||||
// this is setting a bitfield to a variable
|
||||
u64 mask = m_steps.at(0).amount;
|
||||
|
||||
@@ -510,10 +536,10 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
auto as_bitfield = dynamic_cast<BitFieldType*>(type);
|
||||
assert(as_bitfield);
|
||||
// use the mask to figure out the field.
|
||||
auto field = find_field_from_mask(ts, as_bitfield, ~mask);
|
||||
auto field = find_field_from_mask(ts, as_bitfield, ~mask, m_got_pcpyud);
|
||||
assert(field);
|
||||
|
||||
auto val = get_bitfield_initial_set(step.value, as_bitfield, ts);
|
||||
auto val = get_bitfield_initial_set(step.value, as_bitfield, ts, pcpyud_offset);
|
||||
|
||||
if (!val) {
|
||||
throw std::runtime_error(
|
||||
@@ -524,7 +550,7 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
throw std::runtime_error("Incompatible bitfield set");
|
||||
}
|
||||
|
||||
return pool.alloc_element<ModifiedCopyBitfieldElement>(m_type, m_base,
|
||||
return pool.alloc_element<ModifiedCopyBitfieldElement>(m_type, m_base, m_got_pcpyud,
|
||||
std::vector<BitFieldDef>{*val});
|
||||
}
|
||||
|
||||
@@ -532,7 +558,10 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
|
||||
for (auto& old_step : m_steps) {
|
||||
lg::error(" {}", old_step.print());
|
||||
}
|
||||
lg::error("Current: {}\n", step.print());
|
||||
lg::error("Current: {}", step.print());
|
||||
if (m_got_pcpyud) {
|
||||
lg::error("Got pcpyud\n");
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown state in BitfieldReadElement");
|
||||
}
|
||||
@@ -595,6 +624,22 @@ std::optional<u64> get_goal_integer_constant(Form* in, const Env&) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// also (shl (shl <something> 16) 32)
|
||||
// why.
|
||||
matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL),
|
||||
{Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL),
|
||||
{Matcher::any(1), Matcher::integer(16)}),
|
||||
Matcher::integer(32)});
|
||||
mr = match(matcher, in);
|
||||
if (mr.matched) {
|
||||
auto arg_as_atom = form_as_atom(mr.maps.forms.at(1));
|
||||
if (arg_as_atom && arg_as_atom->is_int()) {
|
||||
u64 result = arg_as_atom->get_int();
|
||||
result <<= 48ull;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -602,7 +647,14 @@ BitFieldDef BitFieldDef::from_constant(const BitFieldConstantDef& constant, Form
|
||||
BitFieldDef bfd;
|
||||
bfd.field_name = constant.field_name;
|
||||
bfd.is_signed = constant.is_signed;
|
||||
if (constant.enum_constant) {
|
||||
if (constant.nested_field) {
|
||||
std::vector<BitFieldDef> defs;
|
||||
for (auto& x : constant.nested_field->fields) {
|
||||
defs.push_back(BitFieldDef::from_constant(x, pool));
|
||||
}
|
||||
bfd.value = pool.alloc_single_element_form<BitfieldStaticDefElement>(
|
||||
nullptr, constant.nested_field->field_type, defs);
|
||||
} else if (constant.enum_constant) {
|
||||
bfd.value =
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, *constant.enum_constant);
|
||||
} else {
|
||||
@@ -625,8 +677,8 @@ Form* cast_sound_name(FormPool& pool, const Env& env, Form* in) {
|
||||
auto hi = mr.maps.forms.at(1);
|
||||
auto lo = mr.maps.forms.at(0);
|
||||
|
||||
auto hi_int = get_goal_integer_constant(hi, env);
|
||||
auto lo_int = get_goal_integer_constant(lo, env);
|
||||
auto hi_int = get_goal_integer_constant(strip_int_or_uint_cast(hi), env);
|
||||
auto lo_int = get_goal_integer_constant(strip_int_or_uint_cast(lo), env);
|
||||
if (!hi_int || !lo_int) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -713,8 +765,9 @@ Form* cast_to_bitfield(const BitFieldType* type_info,
|
||||
|
||||
// now variables
|
||||
for (auto& arg : args) {
|
||||
// it's a 64-bit constant so correct to set offset 0 here.
|
||||
auto maybe_field =
|
||||
get_bitfield_initial_set(strip_int_or_uint_cast(arg), type_info, env.dts->ts);
|
||||
get_bitfield_initial_set(strip_int_or_uint_cast(arg), type_info, env.dts->ts, 0);
|
||||
if (!maybe_field) {
|
||||
// failed, just return cast.
|
||||
return pool.alloc_single_element_form<CastElement>(nullptr, typespec, in);
|
||||
|
||||
@@ -101,6 +101,8 @@ class BitfieldAccessElement : public FormElement {
|
||||
FormPool& pool,
|
||||
const Env& env);
|
||||
void push_pcpyud(const TypeSystem& ts, FormPool& pool, const Env& env);
|
||||
std::string debug_print(const Env& env) const;
|
||||
bool has_pcpyud() const { return m_got_pcpyud; }
|
||||
|
||||
private:
|
||||
bool m_got_pcpyud = false;
|
||||
@@ -155,6 +157,7 @@ class ModifiedCopyBitfieldElement : public FormElement {
|
||||
public:
|
||||
ModifiedCopyBitfieldElement(const TypeSpec& type,
|
||||
Form* base,
|
||||
bool from_pcpyud,
|
||||
const std::vector<BitFieldDef>& field_modifications);
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
@@ -164,11 +167,17 @@ class ModifiedCopyBitfieldElement : public FormElement {
|
||||
|
||||
Form* base() const { return m_base; }
|
||||
const std::vector<BitFieldDef> mods() const { return m_field_modifications; }
|
||||
bool from_pcpyud() const { return m_from_pcpyud; }
|
||||
void clear_pcpyud_flag() {
|
||||
assert(m_from_pcpyud);
|
||||
m_from_pcpyud = false;
|
||||
}
|
||||
|
||||
private:
|
||||
TypeSpec m_type;
|
||||
Form* m_base = nullptr;
|
||||
std::vector<BitFieldDef> m_field_modifications;
|
||||
bool m_from_pcpyud = false;
|
||||
};
|
||||
|
||||
Form* cast_to_bitfield(const BitFieldType* type_info,
|
||||
|
||||
@@ -961,4 +961,4 @@ const DecompilerLabel& LinkedObjectFile::get_label_by_name(const std::string& na
|
||||
}
|
||||
throw std::runtime_error("Cannot find label " + name);
|
||||
}
|
||||
} // namespace decompiler
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -157,7 +157,7 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
|
||||
lg::info("ObjectFileDB Initialized\n");
|
||||
if (obj_files_by_name.empty()) {
|
||||
lg::die(
|
||||
lg::error(
|
||||
"No object files have been added. Check that there are input files and the allowed_objects "
|
||||
"list.");
|
||||
}
|
||||
@@ -580,6 +580,7 @@ std::string ObjectFileDB::process_tpages() {
|
||||
|
||||
if (tpage_dir_count == 0) {
|
||||
lg::warn("Did not find tpage-dir.");
|
||||
return {};
|
||||
}
|
||||
|
||||
lg::info("Processed {} / {} textures {:.2f}% in {:.2f} ms", success, total,
|
||||
@@ -612,6 +613,9 @@ std::string ObjectFileDB::process_game_text_files() {
|
||||
lg::info("Processed {} text files ({} strings, {} characters) in {:.2f} ms", file_count,
|
||||
string_count, char_count, timer.getMs());
|
||||
|
||||
if (text_by_language_by_id.empty()) {
|
||||
return {};
|
||||
}
|
||||
return write_game_text(text_by_language_by_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ class ObjectFileDB {
|
||||
bool print_hex);
|
||||
|
||||
void analyze_functions_ir1(const Config& config);
|
||||
void analyze_functions_ir2(const std::string& output_dir, const Config& config);
|
||||
void analyze_functions_ir2(const std::string& output_dir,
|
||||
const Config& config,
|
||||
bool skip_debug_output = false);
|
||||
void ir2_top_level_pass(const Config& config);
|
||||
void ir2_stack_spill_slot_pass();
|
||||
void ir2_basic_block_pass(const Config& config);
|
||||
|
||||
@@ -30,7 +30,9 @@ namespace decompiler {
|
||||
* At this point, we assume that the files are loaded and we've run find_code to locate all
|
||||
* functions, but nothing else.
|
||||
*/
|
||||
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir, const Config& config) {
|
||||
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir,
|
||||
const Config& config,
|
||||
bool skip_debug_output) {
|
||||
lg::info("Using IR2 analysis...");
|
||||
lg::info("Processing top-level functions...");
|
||||
ir2_top_level_pass(config);
|
||||
@@ -55,8 +57,11 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir, const Co
|
||||
lg::info("Initial structuring...");
|
||||
ir2_cfg_build_pass();
|
||||
|
||||
lg::info("Storing temporary form result...");
|
||||
ir2_store_current_forms();
|
||||
if (!skip_debug_output) {
|
||||
lg::info("Storing temporary form result...");
|
||||
ir2_store_current_forms();
|
||||
}
|
||||
|
||||
lg::info("Expression building...");
|
||||
ir2_build_expressions(config);
|
||||
lg::info("Re-writing inline asm instructions...");
|
||||
@@ -301,8 +306,17 @@ void ObjectFileDB::ir2_atomic_op_pass(const Config& config) {
|
||||
bool inline_asm =
|
||||
config.hacks.hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
|
||||
config.hacks.hint_inline_assembly_functions.end();
|
||||
|
||||
std::unordered_set<int> blocks_ending_in_asm_branch;
|
||||
auto asm_branch_it = config.hacks.blocks_ending_in_asm_branch_by_func_name.find(
|
||||
func.guessed_name.to_string());
|
||||
|
||||
if (asm_branch_it != config.hacks.blocks_ending_in_asm_branch_by_func_name.end()) {
|
||||
blocks_ending_in_asm_branch = asm_branch_it->second;
|
||||
}
|
||||
|
||||
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings,
|
||||
inline_asm);
|
||||
inline_asm, blocks_ending_in_asm_branch);
|
||||
func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
|
||||
func.ir2.atomic_ops_succeeded = true;
|
||||
func.ir2.env.set_end_var(func.ir2.atomic_ops->end_op().return_var());
|
||||
@@ -610,7 +624,12 @@ void ObjectFileDB::ir2_insert_anonymous_functions() {
|
||||
(void)segment_id;
|
||||
(void)data;
|
||||
if (func.ir2.top_form && func.ir2.env.has_type_analysis()) {
|
||||
total += insert_static_refs(func.ir2.top_form, *func.ir2.form_pool, func, dts);
|
||||
try {
|
||||
total += insert_static_refs(func.ir2.top_form, *func.ir2.form_pool, func, dts);
|
||||
} catch (std::exception& e) {
|
||||
func.warnings.general_warning("Failed static ref finding: {}\n", e.what());
|
||||
lg::error("Function {} failed static ref: {}\n", func.guessed_name.to_string(), e.what());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ namespace decompiler {
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx, bool hint_inline_asm);
|
||||
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0,
|
||||
int idx,
|
||||
bool hint_inline_asm,
|
||||
bool force_asm_branch);
|
||||
|
||||
//////////////////////
|
||||
// Register Helpers
|
||||
@@ -364,7 +367,9 @@ std::unique_ptr<AtomicOp> make_asm_op(const Instruction& i0, int idx) {
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_1_allow_asm(const Instruction& i0, int idx) {
|
||||
auto as_normal = convert_1(i0, idx, false);
|
||||
// only used for delay slots, so fine to assume that this can never be an asm branch itself
|
||||
// as there are no branches in delay slots anywhere.
|
||||
auto as_normal = convert_1(i0, idx, false, false);
|
||||
if (as_normal) {
|
||||
return as_normal;
|
||||
}
|
||||
@@ -426,15 +431,6 @@ std::unique_ptr<AtomicOp> make_branch(const IR2_Condition& condition,
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> make_branch_no_delay(const IR2_Condition& condition,
|
||||
bool likely,
|
||||
int dest_label,
|
||||
int my_idx) {
|
||||
assert(likely);
|
||||
IR2_BranchDelay delay(IR2_BranchDelay::Kind::NO_DELAY);
|
||||
return std::make_unique<BranchOp>(likely, condition, dest_label, delay, my_idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> make_asm_branch_no_delay(const IR2_Condition& condition,
|
||||
bool likely,
|
||||
int dest_label,
|
||||
@@ -443,6 +439,19 @@ std::unique_ptr<AtomicOp> make_asm_branch_no_delay(const IR2_Condition& conditio
|
||||
return std::make_unique<AsmBranchOp>(likely, condition, dest_label, nullptr, my_idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> make_branch_no_delay(const IR2_Condition& condition,
|
||||
bool likely,
|
||||
int dest_label,
|
||||
int my_idx,
|
||||
bool force_asm_branch) {
|
||||
if (force_asm_branch) {
|
||||
return make_asm_branch_no_delay(condition, likely, dest_label, my_idx);
|
||||
}
|
||||
assert(likely);
|
||||
IR2_BranchDelay delay(IR2_BranchDelay::Kind::NO_DELAY);
|
||||
return std::make_unique<BranchOp>(likely, condition, dest_label, delay, my_idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> make_asm_branch(const IR2_Condition& condition,
|
||||
const Instruction& delay,
|
||||
bool likely,
|
||||
@@ -532,7 +541,8 @@ std::unique_ptr<AtomicOp> convert_mfc1_1(const Instruction& i0, int idx) {
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_lw_1(const Instruction& i0, int idx) {
|
||||
if (i0.get_dst(0).is_reg(rra()) || i0.get_dst(0).is_reg(make_gpr(Reg::AT))) {
|
||||
if (i0.get_dst(0).is_reg(rra()) ||
|
||||
(i0.get_dst(0).is_reg(make_gpr(Reg::AT)) && !i0.get_src(1).is_reg(rs7()))) {
|
||||
return std::make_unique<AsmOp>(i0, idx);
|
||||
}
|
||||
if (i0.get_dst(0).is_reg(rr0()) && i0.get_src(0).is_imm(2) && i0.get_src(1).is_reg(rr0())) {
|
||||
@@ -705,12 +715,16 @@ std::unique_ptr<AtomicOp> convert_dsrl32_1(const Instruction& i0, int idx) {
|
||||
std::unique_ptr<AtomicOp> convert_likely_branch_1(const Instruction& i0,
|
||||
IR2_Condition::Kind kind,
|
||||
bool likely,
|
||||
int idx) {
|
||||
int idx,
|
||||
bool force_asm) {
|
||||
return make_branch_no_delay(IR2_Condition(kind, make_src_atom(i0.get_src(0).get_reg(), idx)),
|
||||
likely, i0.get_src(1).get_label(), idx);
|
||||
likely, i0.get_src(1).get_label(), idx, force_asm);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_beql_1(const Instruction& i0, int idx, bool likely) {
|
||||
std::unique_ptr<AtomicOp> convert_beql_1(const Instruction& i0,
|
||||
int idx,
|
||||
bool likely,
|
||||
bool force_asm) {
|
||||
auto s0 = i0.get_src(0).get_reg();
|
||||
auto s1 = i0.get_src(1).get_reg();
|
||||
auto dest = i0.get_src(2).get_label();
|
||||
@@ -735,10 +749,13 @@ std::unique_ptr<AtomicOp> convert_beql_1(const Instruction& i0, int idx, bool li
|
||||
IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx));
|
||||
condition.make_flipped();
|
||||
}
|
||||
return make_branch_no_delay(condition, likely, dest, idx);
|
||||
return make_branch_no_delay(condition, likely, dest, idx, force_asm);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_bnel_1(const Instruction& i0, int idx, bool likely) {
|
||||
std::unique_ptr<AtomicOp> convert_bnel_1(const Instruction& i0,
|
||||
int idx,
|
||||
bool likely,
|
||||
bool force_asm) {
|
||||
auto s0 = i0.get_src(0).get_reg();
|
||||
auto s1 = i0.get_src(1).get_reg();
|
||||
auto dest = i0.get_src(2).get_label();
|
||||
@@ -756,7 +773,7 @@ std::unique_ptr<AtomicOp> convert_bnel_1(const Instruction& i0, int idx, bool li
|
||||
make_src_atom(s1, idx));
|
||||
condition.make_flipped();
|
||||
}
|
||||
return make_branch_no_delay(condition, likely, dest, idx);
|
||||
return make_branch_no_delay(condition, likely, dest, idx, force_asm);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_subu_1(const Instruction& i0, int idx) {
|
||||
@@ -771,7 +788,10 @@ std::unique_ptr<AtomicOp> convert_subu_1(const Instruction& i0, int idx) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx, bool hint_inline_asm) {
|
||||
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0,
|
||||
int idx,
|
||||
bool hint_inline_asm,
|
||||
bool force_asm_branch) {
|
||||
switch (i0.kind) {
|
||||
case InstructionKind::OR:
|
||||
return convert_or_1(i0, idx);
|
||||
@@ -895,15 +915,18 @@ std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx, bool hint_in
|
||||
case InstructionKind::MOVZ:
|
||||
return convert_cmov_1(i0, idx);
|
||||
case InstructionKind::BGTZL:
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::GREATER_THAN_ZERO_SIGNED, true, idx);
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::GREATER_THAN_ZERO_SIGNED, true, idx,
|
||||
force_asm_branch);
|
||||
case InstructionKind::BGEZL:
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::GEQ_ZERO_SIGNED, true, idx);
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::GEQ_ZERO_SIGNED, true, idx,
|
||||
force_asm_branch);
|
||||
case InstructionKind::BLTZL:
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::LESS_THAN_ZERO_SIGNED, true, idx);
|
||||
return convert_likely_branch_1(i0, IR2_Condition::Kind::LESS_THAN_ZERO_SIGNED, true, idx,
|
||||
force_asm_branch);
|
||||
case InstructionKind::BEQL:
|
||||
return convert_beql_1(i0, idx, true);
|
||||
return convert_beql_1(i0, idx, true, force_asm_branch);
|
||||
case InstructionKind::BNEL:
|
||||
return convert_bnel_1(i0, idx, true);
|
||||
return convert_bnel_1(i0, idx, true, force_asm_branch);
|
||||
case InstructionKind::SUBU:
|
||||
return convert_subu_1(i0, idx); // may fail
|
||||
default:
|
||||
@@ -1469,6 +1492,26 @@ std::unique_ptr<AtomicOp> convert_dsll32_4(const Instruction& i0,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_fp_branch_with_nop(const Instruction& i0,
|
||||
const Instruction& i1,
|
||||
const Instruction& i2,
|
||||
const Instruction& i3,
|
||||
IR2_Condition::Kind kind,
|
||||
int idx) {
|
||||
if (i1.kind != InstructionKind::VNOP) {
|
||||
return nullptr;
|
||||
}
|
||||
if (i2.kind == InstructionKind::BC1T || i2.kind == InstructionKind::BC1F) {
|
||||
IR2_Condition condition(kind, make_src_atom(i0.get_src(0).get_reg(), idx),
|
||||
make_src_atom(i0.get_src(1).get_reg(), idx));
|
||||
if (i2.kind == InstructionKind::BC1F) {
|
||||
condition.invert();
|
||||
}
|
||||
return make_branch(condition, i3, false, i2.get_src(0).get_label(), idx);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_4(const Instruction& i0,
|
||||
const Instruction& i1,
|
||||
const Instruction& i2,
|
||||
@@ -1477,6 +1520,8 @@ std::unique_ptr<AtomicOp> convert_4(const Instruction& i0,
|
||||
switch (i0.kind) {
|
||||
case InstructionKind::DSLL32:
|
||||
return convert_dsll32_4(i0, i1, i2, i3, idx);
|
||||
case InstructionKind::CEQS:
|
||||
return convert_fp_branch_with_nop(i0, i1, i2, i3, IR2_Condition::Kind::FLOAT_EQUAL, idx);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1580,6 +1625,53 @@ std::unique_ptr<AtomicOp> convert_vector_minus(const Instruction& i0,
|
||||
idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_vector_cross(const Instruction& i0,
|
||||
const Instruction& i1,
|
||||
const Instruction& i2,
|
||||
const Instruction& i3,
|
||||
const Instruction& i4,
|
||||
int idx) {
|
||||
// lqc2 vf1, 0(v1) (src1)
|
||||
if (i0.kind != InstructionKind::LQC2 || i0.get_dst(0).get_reg() != make_vf(1) ||
|
||||
!i0.get_src(0).is_imm(0)) {
|
||||
return nullptr;
|
||||
}
|
||||
Register src1 = i0.get_src(1).get_reg();
|
||||
|
||||
// lqc2 vf5, 0(a2) (src2)
|
||||
if (i1.kind != InstructionKind::LQC2 || i1.get_dst(0).get_reg() != make_vf(2) ||
|
||||
!i1.get_src(0).is_imm(0)) {
|
||||
return nullptr;
|
||||
}
|
||||
Register src2 = i1.get_src(1).get_reg();
|
||||
|
||||
// vopmula.xyz acc, vf1, vf2
|
||||
if (i2.kind != InstructionKind::VOPMULA || i2.get_src(0).get_reg() != make_vf(1) ||
|
||||
i2.get_src(1).get_reg() != make_vf(2) || i2.cop2_dest != 14) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// vopmsub.xyz vf3, vf2, vf1
|
||||
if (i3.kind != InstructionKind::VOPMSUB || i3.get_dst(0).get_reg() != make_vf(3) ||
|
||||
i3.get_src(0).get_reg() != make_vf(2) || i3.get_src(1).get_reg() != make_vf(1) ||
|
||||
i3.cop2_dest != 14) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// sqc2 vf3, 0(a0)
|
||||
if (i4.kind != InstructionKind::SQC2 || i4.get_src(0).get_reg() != make_vf(3) ||
|
||||
!i4.get_src(1).is_imm(0)) {
|
||||
return nullptr;
|
||||
}
|
||||
Register dst = i4.get_src(2).get_reg();
|
||||
|
||||
return std::make_unique<SetVarOp>(
|
||||
make_dst_var(dst, idx),
|
||||
SimpleExpression(SimpleExpression::Kind::VECTOR_CROSS, make_src_atom(dst, idx),
|
||||
make_src_atom(src1, idx), make_src_atom(src2, idx)),
|
||||
idx);
|
||||
}
|
||||
|
||||
std::unique_ptr<AtomicOp> convert_5(const Instruction& i0,
|
||||
const Instruction& i1,
|
||||
const Instruction& i2,
|
||||
@@ -1607,6 +1699,11 @@ std::unique_ptr<AtomicOp> convert_5(const Instruction& i0,
|
||||
if (as_vector_minus) {
|
||||
return as_vector_minus;
|
||||
}
|
||||
|
||||
auto as_vector_cross = convert_vector_cross(i0, i1, i2, i3, i4, idx);
|
||||
if (as_vector_cross) {
|
||||
return as_vector_cross;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1787,7 +1884,8 @@ int convert_block_to_atomic_ops(int begin_idx,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
FunctionAtomicOps* container,
|
||||
DecompWarnings& warnings,
|
||||
bool hint_inline_asm) {
|
||||
bool hint_inline_asm,
|
||||
bool block_ends_in_asm_branch) {
|
||||
container->block_id_to_first_atomic_op.push_back(container->ops.size());
|
||||
for (auto& instr = begin; instr < end;) {
|
||||
// how many instructions can we look at, at most?
|
||||
@@ -1859,7 +1957,8 @@ int convert_block_to_atomic_ops(int begin_idx,
|
||||
|
||||
if (!converted) {
|
||||
// try 1 instruction
|
||||
op = convert_1(*instr, op_idx, hint_inline_asm);
|
||||
bool force_asm_branch = n_instr == 1 && block_ends_in_asm_branch;
|
||||
op = convert_1(*instr, op_idx, hint_inline_asm, force_asm_branch);
|
||||
if (op) {
|
||||
converted = true;
|
||||
length = 1;
|
||||
@@ -1899,10 +1998,12 @@ int convert_block_to_atomic_ops(int begin_idx,
|
||||
return int(container->ops.size());
|
||||
}
|
||||
|
||||
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
DecompWarnings& warnings,
|
||||
bool hint_inline_asm) {
|
||||
FunctionAtomicOps convert_function_to_atomic_ops(
|
||||
const Function& func,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
DecompWarnings& warnings,
|
||||
bool hint_inline_asm,
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_branches) {
|
||||
FunctionAtomicOps result;
|
||||
|
||||
int last_op = 0;
|
||||
@@ -1912,8 +2013,9 @@ FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
|
||||
if (block.end_word > block.start_word) {
|
||||
auto begin = func.instructions.begin() + block.start_word;
|
||||
auto end = func.instructions.begin() + block.end_word;
|
||||
last_op = convert_block_to_atomic_ops(block.start_word, begin, end, labels, &result, warnings,
|
||||
hint_inline_asm);
|
||||
last_op = convert_block_to_atomic_ops(
|
||||
block.start_word, begin, end, labels, &result, warnings, hint_inline_asm,
|
||||
blocks_ending_in_asm_branches.find(i) != blocks_ending_in_asm_branches.end());
|
||||
if (i == int(func.basic_blocks.size()) - 1) {
|
||||
// we're the last block. insert the function end op.
|
||||
result.ops.push_back(std::make_unique<FunctionEndOp>(int(result.ops.size())));
|
||||
|
||||
@@ -48,13 +48,16 @@ int convert_block_to_atomic_ops(int begin_idx,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
FunctionAtomicOps* container,
|
||||
DecompWarnings& warnings,
|
||||
bool inline_asm_hint = false);
|
||||
bool inline_asm_hint = false,
|
||||
bool block_ends_in_asm_branch = false);
|
||||
|
||||
/*!
|
||||
* Convert an entire function to AtomicOps
|
||||
*/
|
||||
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
DecompWarnings& warnings,
|
||||
bool hint_inline_asm);
|
||||
FunctionAtomicOps convert_function_to_atomic_ops(
|
||||
const Function& func,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
DecompWarnings& warnings,
|
||||
bool hint_inline_asm,
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_branches);
|
||||
} // namespace decompiler
|
||||
@@ -611,7 +611,14 @@ bool try_splitting_nested_sc(FormPool& pool, Function& func, ShortCircuitElement
|
||||
* if there is a case like (and a (or b c))
|
||||
*/
|
||||
void clean_up_sc(FormPool& pool, Function& func, ShortCircuitElement* ir) {
|
||||
assert(ir->entries.size() > 1);
|
||||
assert(ir->entries.size() > 0);
|
||||
if (ir->entries.size() == 1) {
|
||||
// need to fake the final entry.
|
||||
ShortCircuitElement::Entry empty_final;
|
||||
empty_final.condition = pool.alloc_single_element_form<EmptyElement>(ir);
|
||||
ir->entries.push_back(empty_final);
|
||||
}
|
||||
|
||||
if (!try_clean_up_sc_as_and(pool, func, ir)) {
|
||||
if (!try_clean_up_sc_as_or(pool, func, ir)) {
|
||||
if (!try_splitting_nested_sc(pool, func, ir)) {
|
||||
@@ -1615,9 +1622,6 @@ Form* cfg_to_ir_helper(FormPool& pool, Function& f, const CfgVtx* vtx) {
|
||||
return as_abs;
|
||||
}
|
||||
|
||||
if (svtx->entries.size() == 1) {
|
||||
throw std::runtime_error("Weird short circuit form.");
|
||||
}
|
||||
// now try as a normal and/or
|
||||
std::vector<ShortCircuitElement::Entry> entries;
|
||||
for (auto& x : svtx->entries) {
|
||||
|
||||
@@ -85,10 +85,15 @@ bool convert_to_expressions(
|
||||
if (!dts.ts.tc(f.type.last_arg(), return_type)) {
|
||||
// we need to cast the final value.
|
||||
auto to_cast = new_entries.back();
|
||||
new_entries.pop_back();
|
||||
auto cast = pool.alloc_element<CastElement>(f.type.last_arg(),
|
||||
pool.alloc_single_form(nullptr, to_cast));
|
||||
new_entries.push_back(cast);
|
||||
auto as_cast = dynamic_cast<CastElement*>(to_cast);
|
||||
if (as_cast) {
|
||||
as_cast->set_type(f.type.last_arg());
|
||||
} else {
|
||||
new_entries.pop_back();
|
||||
auto cast = pool.alloc_element<CastElement>(f.type.last_arg(),
|
||||
pool.alloc_single_form(nullptr, to_cast));
|
||||
new_entries.push_back(cast);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// or just get all the expressions
|
||||
|
||||
@@ -36,7 +36,7 @@ If the previous let variables appear in the definition of new one, make the let
|
||||
*/
|
||||
|
||||
namespace {
|
||||
std::vector<Form*> path_up_tree(Form* in, const Env& env) {
|
||||
std::vector<Form*> path_up_tree(Form* in, const Env&) {
|
||||
std::vector<Form*> path;
|
||||
|
||||
while (in) {
|
||||
@@ -79,8 +79,8 @@ Form* lca_form(Form* a, Form* b, const Env& env) {
|
||||
bi--;
|
||||
}
|
||||
if (!result) {
|
||||
auto* bad = b->parent_element;
|
||||
fmt::print("bad form is {} {}\n", bad->to_string(env), (void*)bad);
|
||||
fmt::print("{} bad form is {}\n\n{}\n", env.func->guessed_name.to_string(), a->to_string(env),
|
||||
b->to_string(env));
|
||||
}
|
||||
assert(result);
|
||||
|
||||
@@ -357,6 +357,265 @@ FormElement* rewrite_empty_let(LetElement* in, const Env&, FormPool&) {
|
||||
return in->entries().at(0).src->try_as_single_element();
|
||||
}
|
||||
|
||||
Form* strip_truthy(Form* in) {
|
||||
auto as_ge = in->try_as_element<GenericElement>();
|
||||
if (as_ge) {
|
||||
if (as_ge->op().kind() == GenericOperator::Kind::CONDITION_OPERATOR &&
|
||||
as_ge->op().condition_kind() == IR2_Condition::Kind::TRUTHY) {
|
||||
in = as_ge->elts().at(0);
|
||||
}
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
FormElement* rewrite_set_vector(LetElement* in, const Env& env, FormPool& pool) {
|
||||
if (in->entries().size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto in_vec = env.get_variable_name(in->entries().at(0).dest);
|
||||
|
||||
auto& body_elts = in->body()->elts();
|
||||
if (body_elts.size() != 4) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Form*> sources;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto elt_as_form_form = dynamic_cast<SetFormFormElement*>(body_elts.at(i));
|
||||
if (!elt_as_form_form) {
|
||||
return nullptr;
|
||||
}
|
||||
auto dst = elt_as_form_form->dst();
|
||||
sources.push_back(elt_as_form_form->src());
|
||||
Matcher dst_matcher = Matcher::deref(Matcher::any_reg(0), false,
|
||||
{DerefTokenMatcher::string(std::string(1, "xyzw"[i]))});
|
||||
auto mr = match(dst_matcher, dst);
|
||||
if (!mr.matched) {
|
||||
return nullptr;
|
||||
}
|
||||
if (in_vec != env.get_variable_name(*mr.maps.regs.at(0))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Form*> args;
|
||||
args.push_back(in->entries().at(0).src);
|
||||
for (auto& src : sources) {
|
||||
args.push_back(src);
|
||||
}
|
||||
|
||||
auto op = GenericOperator::make_function(
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "set-vector!"));
|
||||
return pool.alloc_element<GenericElement>(op, args);
|
||||
}
|
||||
|
||||
FormElement* rewrite_set_vector_2(LetElement* in, const Env& env, FormPool& pool) {
|
||||
if (in->entries().size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto in_vec = env.get_variable_name(in->entries().at(0).dest);
|
||||
auto src_as_deref = in->entries().at(0).src->try_as_element<DerefElement>();
|
||||
if (!src_as_deref) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto& body_elts = in->body()->elts();
|
||||
if (body_elts.size() != 4) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Form*> sources;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto elt_as_form_form = dynamic_cast<SetFormFormElement*>(body_elts.at(i));
|
||||
if (!elt_as_form_form) {
|
||||
return nullptr;
|
||||
}
|
||||
auto dst = elt_as_form_form->dst();
|
||||
sources.push_back(elt_as_form_form->src());
|
||||
Matcher dst_matcher = Matcher::deref(
|
||||
Matcher::any_reg(0), false,
|
||||
{DerefTokenMatcher::integer(0), DerefTokenMatcher::string(std::string(1, "xyzw"[i]))});
|
||||
auto mr = match(dst_matcher, dst);
|
||||
if (!mr.matched) {
|
||||
return nullptr;
|
||||
}
|
||||
if (in_vec != env.get_variable_name(*mr.maps.regs.at(0))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
src_as_deref->tokens().push_back(DerefToken::make_int_constant(0));
|
||||
|
||||
std::vector<Form*> args;
|
||||
args.push_back(in->entries().at(0).src);
|
||||
for (auto& src : sources) {
|
||||
args.push_back(src);
|
||||
}
|
||||
|
||||
auto op = GenericOperator::make_function(
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "set-vector!"));
|
||||
return pool.alloc_element<GenericElement>(op, args);
|
||||
}
|
||||
|
||||
ShortCircuitElement* get_or(Form* in) {
|
||||
// strip off truthy
|
||||
in = strip_truthy(in);
|
||||
|
||||
return in->try_as_element<ShortCircuitElement>();
|
||||
}
|
||||
|
||||
FormElement* rewrite_as_case_no_else(LetElement* in, const Env& env, FormPool& pool) {
|
||||
if (in->entries().size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* cond = in->body()->try_as_element<CondNoElseElement>();
|
||||
if (!cond) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto case_var = in->entries().at(0).dest;
|
||||
auto& case_var_uses = env.get_use_def_info(case_var);
|
||||
int found_uses = 0;
|
||||
if (case_var_uses.def_count() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
auto case_var_name = env.get_variable_name(case_var);
|
||||
|
||||
std::vector<CaseElement::Entry> entries;
|
||||
|
||||
for (auto& e : cond->entries) {
|
||||
// first, lets see if its just (= case_var <expr>)
|
||||
auto single_matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::EQ),
|
||||
{Matcher::any_reg(0), Matcher::any(1)});
|
||||
|
||||
auto single_matcher_result = match(single_matcher, e.condition);
|
||||
|
||||
Form* single_value = nullptr;
|
||||
if (single_matcher_result.matched) {
|
||||
auto var_name = env.get_variable_name(*single_matcher_result.maps.regs.at(0));
|
||||
if (var_name == case_var_name) {
|
||||
single_value = single_matcher_result.maps.forms.at(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (single_value) {
|
||||
entries.push_back({{single_value}, e.body});
|
||||
found_uses++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// try as an or (or (= case_var <expr>) ...)
|
||||
auto* as_or = get_or(e.condition);
|
||||
if (!as_or) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CaseElement::Entry current_entry;
|
||||
for (auto& or_case : as_or->entries) {
|
||||
auto or_single_matcher_result = match(single_matcher, strip_truthy(or_case.condition));
|
||||
if (!or_single_matcher_result.matched) {
|
||||
return nullptr;
|
||||
}
|
||||
auto var_name = env.get_variable_name(*or_single_matcher_result.maps.regs.at(0));
|
||||
if (var_name != case_var_name) {
|
||||
return nullptr;
|
||||
}
|
||||
found_uses++;
|
||||
current_entry.vals.push_back(or_single_matcher_result.maps.forms.at(1));
|
||||
}
|
||||
current_entry.body = e.body;
|
||||
entries.push_back(current_entry);
|
||||
|
||||
// no match
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
if (found_uses != case_var_uses.use_count()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pool.alloc_element<CaseElement>(in->entries().at(0).src, entries, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FormElement* rewrite_as_case_with_else(LetElement* in, const Env& env, FormPool& pool) {
|
||||
if (in->entries().size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* cond = in->body()->try_as_element<CondWithElseElement>();
|
||||
if (!cond) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto case_var = in->entries().at(0).dest;
|
||||
auto& case_var_uses = env.get_use_def_info(case_var);
|
||||
int found_uses = 0;
|
||||
if (case_var_uses.def_count() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
auto case_var_name = env.get_variable_name(case_var);
|
||||
|
||||
std::vector<CaseElement::Entry> entries;
|
||||
|
||||
for (auto& e : cond->entries) {
|
||||
// first, lets see if its just (= case_var <expr>)
|
||||
auto single_matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::EQ),
|
||||
{Matcher::any_reg(0), Matcher::any(1)});
|
||||
|
||||
auto single_matcher_result = match(single_matcher, e.condition);
|
||||
|
||||
Form* single_value = nullptr;
|
||||
if (single_matcher_result.matched) {
|
||||
auto var_name = env.get_variable_name(*single_matcher_result.maps.regs.at(0));
|
||||
if (var_name == case_var_name) {
|
||||
single_value = single_matcher_result.maps.forms.at(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (single_value) {
|
||||
entries.push_back({{single_value}, e.body});
|
||||
found_uses++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// try as an or (or (= case_var <expr>) ...)
|
||||
auto* as_or = get_or(e.condition);
|
||||
if (!as_or) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CaseElement::Entry current_entry;
|
||||
for (auto& or_case : as_or->entries) {
|
||||
auto or_single_matcher_result = match(single_matcher, strip_truthy(or_case.condition));
|
||||
if (!or_single_matcher_result.matched) {
|
||||
return nullptr;
|
||||
}
|
||||
auto var_name = env.get_variable_name(*or_single_matcher_result.maps.regs.at(0));
|
||||
if (var_name != case_var_name) {
|
||||
return nullptr;
|
||||
}
|
||||
found_uses++;
|
||||
current_entry.vals.push_back(or_single_matcher_result.maps.forms.at(1));
|
||||
}
|
||||
current_entry.body = e.body;
|
||||
entries.push_back(current_entry);
|
||||
|
||||
// no match
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
if (found_uses != case_var_uses.use_count()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pool.alloc_element<CaseElement>(in->entries().at(0).src, entries, cond->else_ir);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Attempt to rewrite a let as another form. If it cannot be rewritten, this will return nullptr.
|
||||
*/
|
||||
@@ -386,6 +645,26 @@ FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool) {
|
||||
return as_unused;
|
||||
}
|
||||
|
||||
auto as_case_no_else = rewrite_as_case_no_else(in, env, pool);
|
||||
if (as_case_no_else) {
|
||||
return as_case_no_else;
|
||||
}
|
||||
|
||||
auto as_case_with_else = rewrite_as_case_with_else(in, env, pool);
|
||||
if (as_case_with_else) {
|
||||
return as_case_with_else;
|
||||
}
|
||||
|
||||
auto as_set_vector = rewrite_set_vector(in, env, pool);
|
||||
if (as_set_vector) {
|
||||
return as_set_vector;
|
||||
}
|
||||
|
||||
auto as_set_vector2 = rewrite_set_vector_2(in, env, pool);
|
||||
if (as_set_vector2) {
|
||||
return as_set_vector2;
|
||||
}
|
||||
|
||||
// nothing matched.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -78,12 +78,15 @@ struct StackInstrInfo {
|
||||
constexpr StackInstrInfo stack_instrs[] = {{InstructionKind::SQ, false, 16, false},
|
||||
{InstructionKind::LQ, true, 16, false},
|
||||
{InstructionKind::SW, false, 4, false},
|
||||
{InstructionKind::SH, false, 2, false},
|
||||
{InstructionKind::SB, false, 1, false},
|
||||
{InstructionKind::LBU, true, 1, false},
|
||||
//{InstructionKind::LWU, true, 4, false}
|
||||
{InstructionKind::SD, false, 8, false},
|
||||
{InstructionKind::SWC1, false, 4, false},
|
||||
{InstructionKind::LWC1, true, 4, false}};
|
||||
{InstructionKind::LWC1, true, 4, false},
|
||||
{InstructionKind::SB, false, 1, false},
|
||||
{InstructionKind::LBU, true, 1, false}};
|
||||
} // namespace
|
||||
|
||||
StackSpillMap build_spill_map(const std::vector<Instruction>& instructions, Range<int> range) {
|
||||
@@ -111,4 +114,4 @@ StackSpillMap build_spill_map(const std::vector<Instruction>& instructions, Rang
|
||||
map.finalize();
|
||||
return map;
|
||||
}
|
||||
} // namespace decompiler
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -15,7 +15,8 @@ TypeState construct_initial_typestate(const TypeSpec& f_ts, const Env& env) {
|
||||
}
|
||||
|
||||
// todo, more specific process types for behaviors.
|
||||
result.get(Register(Reg::GPR, Reg::S6)) = TP_Type::make_from_ts(TypeSpec("process"));
|
||||
result.get(Register(Reg::GPR, Reg::S6)) =
|
||||
TP_Type::make_from_ts(TypeSpec(f_ts.try_get_tag("behavior").value_or("process")));
|
||||
|
||||
// initialize stack slots as uninitialized
|
||||
for (auto slot_info : env.stack_spills().map()) {
|
||||
@@ -91,6 +92,7 @@ bool run_type_analysis_ir2(const TypeSpec& my_type, DecompilerTypeSystem& dts, F
|
||||
}
|
||||
|
||||
std::vector<TypeState> block_init_types, op_types;
|
||||
std::vector<bool> block_needs_update(func.basic_blocks.size(), true);
|
||||
block_init_types.resize(func.basic_blocks.size());
|
||||
op_types.resize(func.ir2.atomic_ops->ops.size());
|
||||
auto& aop = func.ir2.atomic_ops;
|
||||
@@ -111,6 +113,9 @@ bool run_type_analysis_ir2(const TypeSpec& my_type, DecompilerTypeSystem& dts, F
|
||||
run_again = false;
|
||||
// do each block in the topological sort order:
|
||||
for (auto block_id : order.vist_order) {
|
||||
if (!block_needs_update.at(block_id)) {
|
||||
continue;
|
||||
}
|
||||
auto& block = func.basic_blocks.at(block_id);
|
||||
TypeState* init_types = &block_init_types.at(block_id);
|
||||
for (int op_id = aop->block_id_to_first_atomic_op.at(block_id);
|
||||
@@ -145,6 +150,7 @@ bool run_type_analysis_ir2(const TypeSpec& my_type, DecompilerTypeSystem& dts, F
|
||||
// for the next op...
|
||||
init_types = &op_types.at(op_id);
|
||||
}
|
||||
block_needs_update.at(block_id) = false;
|
||||
|
||||
// propagate the types: for each possible succ
|
||||
for (auto succ_block_id : {block.succ_ft, block.succ_branch}) {
|
||||
@@ -153,6 +159,7 @@ bool run_type_analysis_ir2(const TypeSpec& my_type, DecompilerTypeSystem& dts, F
|
||||
if (dts.tp_lca(&block_init_types.at(succ_block_id), *init_types)) {
|
||||
// if something changed, run again!
|
||||
run_again = true;
|
||||
block_needs_update.at(succ_block_id) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,6 +730,25 @@ void SSA::make_vars(const Function& function, const DecompilerTypeSystem& dts) {
|
||||
}
|
||||
}
|
||||
|
||||
// if (function.type.last_arg() != TypeSpec("none")) {
|
||||
// auto return_var = function.ir2.atomic_ops->end_op().return_var();
|
||||
// auto return_reg = return_var.reg();
|
||||
// const auto& last_block = blocks.at(blocks.size() - 1);
|
||||
// const auto& last_ins = last_block.ins.at(last_block.ins.size() - 1);
|
||||
// assert(last_ins.src.size() == 1);
|
||||
// auto return_idx = map.var_id(last_ins.src.at(0));
|
||||
//
|
||||
// if (!program_read_vars[return_reg].empty()) {
|
||||
// program_read_vars[return_reg].at(return_idx).type =
|
||||
// TP_Type::make_from_ts(function.type.last_arg());
|
||||
// }
|
||||
//
|
||||
// if (!program_write_vars[return_reg].empty()) {
|
||||
// program_write_vars[return_reg].at(return_idx).type =
|
||||
// TP_Type::make_from_ts(function.type.last_arg());
|
||||
// }
|
||||
// }
|
||||
|
||||
merge_infos(program_write_vars, program_read_vars, dts);
|
||||
|
||||
// copy types from input argument coloring moves:
|
||||
@@ -897,6 +916,104 @@ std::unordered_map<RegId, UseDefInfo, RegId::hash> SSA::get_use_def_info(
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
VariableNames::VarInfo* try_lookup_read(VariableNames* in, RegId var_id) {
|
||||
auto kv = in->read_vars.find(var_id.reg);
|
||||
if (kv != in->read_vars.end()) {
|
||||
if ((int)kv->second.size() > var_id.id) {
|
||||
auto& entry = kv->second.at(var_id.id);
|
||||
if (entry.initialized) {
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VariableNames::VarInfo* try_lookup_write(VariableNames* in, RegId var_id) {
|
||||
auto kv = in->write_vars.find(var_id.reg);
|
||||
if (kv != in->write_vars.end()) {
|
||||
if ((int)kv->second.size() > var_id.id) {
|
||||
auto& entry = kv->second.at(var_id.id);
|
||||
if (entry.initialized) {
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool is_128bit(const TP_Type& type, const DecompilerTypeSystem& dts) {
|
||||
if (dts.ts.tc(TypeSpec("uint128"), type.typespec())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dts.ts.tc(TypeSpec("int128"), type.typespec())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.kind == TP_Type::Kind::PCPYUD_BITFIELD) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.kind == TP_Type::Kind::PCPYUD_BITFIELD_AND) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void promote_register_class(const Function& func,
|
||||
VariableNames* result,
|
||||
const DecompilerTypeSystem& dts) {
|
||||
enum class PromotionType { PROMOTE_64, PROMOTE_128 };
|
||||
std::unordered_map<RegId, PromotionType, RegId::hash> promote_map;
|
||||
// here we loop through ops and find cases where we need to adjust types.
|
||||
|
||||
auto& ao = func.ir2.atomic_ops;
|
||||
for (size_t op_idx = 0; op_idx < ao->ops.size() - 1; op_idx++) {
|
||||
auto* op = ao->ops.at(op_idx).get();
|
||||
auto op_as_asm = dynamic_cast<AsmOp*>(op);
|
||||
if (op_as_asm) {
|
||||
auto& instr = op_as_asm->instruction();
|
||||
if (gOpcodeInfo[(int)instr.kind].gpr_128) {
|
||||
for (auto& reg : op_as_asm->write_regs()) {
|
||||
if (reg.get_kind() == Reg::GPR) {
|
||||
auto& info = result->lookup(reg, op_idx, AccessMode::WRITE);
|
||||
promote_map[info.reg_id] = PromotionType::PROMOTE_128;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& reg : op_as_asm->read_regs()) {
|
||||
if (reg.get_kind() == Reg::GPR) {
|
||||
auto& info = result->lookup(reg, op_idx, AccessMode::READ);
|
||||
promote_map[info.reg_id] = PromotionType::PROMOTE_128;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& promotion : promote_map) {
|
||||
// fmt::print("Promote {} to {}\n", promotion.first.print(), "uint128");
|
||||
|
||||
// first reads:
|
||||
auto read_info = try_lookup_read(result, promotion.first);
|
||||
auto write_info = try_lookup_write(result, promotion.first);
|
||||
assert(read_info || write_info);
|
||||
|
||||
if (read_info && !is_128bit(read_info->type, dts)) {
|
||||
read_info->type = TP_Type::make_from_ts("uint128");
|
||||
}
|
||||
|
||||
if (write_info && !is_128bit(write_info->type, dts)) {
|
||||
write_info->type = TP_Type::make_from_ts("uint128");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::optional<VariableNames> run_variable_renaming(const Function& function,
|
||||
const RegUsageInfo& rui,
|
||||
const FunctionAtomicOps& ops,
|
||||
@@ -982,6 +1099,8 @@ std::optional<VariableNames> run_variable_renaming(const Function& function,
|
||||
//
|
||||
auto result = ssa.get_vars();
|
||||
result.use_def_info = ssa.get_use_def_info(ssa_mapping);
|
||||
|
||||
promote_register_class(function, &result, dts);
|
||||
return result;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
|
||||
@@ -33,6 +33,9 @@ Config read_config_file(const std::string& path_to_config_file) {
|
||||
config.dgo_names = inputs_json.at("dgo_names").get<std::vector<std::string>>();
|
||||
config.object_file_names = inputs_json.at("object_file_names").get<std::vector<std::string>>();
|
||||
config.str_file_names = inputs_json.at("str_file_names").get<std::vector<std::string>>();
|
||||
config.audio_dir_file_name = inputs_json.at("audio_dir_file_name").get<std::string>();
|
||||
config.streamed_audio_file_names =
|
||||
inputs_json.at("streamed_audio_file_names").get<std::vector<std::string>>();
|
||||
|
||||
if (cfg.contains("obj_file_name_map_file")) {
|
||||
config.obj_file_name_map_file = cfg.at("obj_file_name_map_file").get<std::string>();
|
||||
|
||||
@@ -68,6 +68,9 @@ struct Config {
|
||||
std::vector<std::string> object_file_names;
|
||||
std::vector<std::string> str_file_names;
|
||||
|
||||
std::string audio_dir_file_name;
|
||||
std::vector<std::string> streamed_audio_file_names;
|
||||
|
||||
std::string obj_file_name_map_file;
|
||||
|
||||
bool disassemble_code = false;
|
||||
|
||||
+2498
-2794
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@
|
||||
"hexdump_code": false,
|
||||
"hexdump_data": false,
|
||||
// dump raw obj files
|
||||
"dump_objs": false,
|
||||
"dump_objs": true,
|
||||
// print control flow graph
|
||||
"print_cfgs": false,
|
||||
|
||||
|
||||
@@ -572,6 +572,17 @@
|
||||
[3, "(function basic symbol)"],
|
||||
[2, "(function process symbol)"]
|
||||
],
|
||||
|
||||
"anim-tester": [
|
||||
[11, "(function none :behavior anim-tester)"],
|
||||
[12, "(function none :behavior anim-tester)"],
|
||||
[13, "(function none :behavior anim-tester)"]
|
||||
],
|
||||
|
||||
"cam-combiner": [
|
||||
[1, "(function none :behavior camera-combiner)"],
|
||||
[2, "(function basic int basic event-message-block object :behavior camera-combiner)"]
|
||||
],
|
||||
|
||||
"nav-enemy": [
|
||||
[8, "(function none)"], // TODO - NECK!
|
||||
|
||||
@@ -97,23 +97,12 @@
|
||||
// vector
|
||||
"vector=", // asm branching
|
||||
|
||||
// texture
|
||||
// "adgif-shader<-texture-with-update!", // F: asm branching
|
||||
// "(method 9 texture-page-dir)",
|
||||
|
||||
// collide-mesh-h
|
||||
"(method 11 collide-mesh-cache)",
|
||||
|
||||
// actor-link-h (BUG)
|
||||
"(method 21 actor-link-info)", // BUG: sc cfg / cfg-ir bug
|
||||
"(method 20 actor-link-info)",
|
||||
|
||||
// collide-func
|
||||
"moving-sphere-triangle-intersect", // P: weird branching
|
||||
"collide-do-primitives", // P: asm branching
|
||||
"ray-triangle-intersect", // F: asm branching
|
||||
"ray-cylinder-intersect", // F: asm branching
|
||||
"raw-ray-sphere-intersect",
|
||||
|
||||
// joint
|
||||
"calc-animation-from-spr", // F: asm branching
|
||||
@@ -124,10 +113,8 @@
|
||||
"clear-frame-accumulator", // F: asm branching
|
||||
"cspace<-parented-transformq-joint!",
|
||||
|
||||
// bsp
|
||||
"level-remap-texture", // BUG: probably missing branch case?
|
||||
"bsp-camera-asm", // F: asm branching
|
||||
"sprite-draw-distorters",
|
||||
// sprite
|
||||
"add-to-sprite-aux-list", // fine, but don't know types yet.
|
||||
|
||||
// merc-blend-shape
|
||||
"setup-blerc-chains-for-one-fragment", // F: asm branching
|
||||
@@ -207,7 +194,7 @@
|
||||
"draw-string",
|
||||
|
||||
// decomp
|
||||
"(method 16 level)", // BUG: cfg fails
|
||||
//"(method 16 level)", // BUG: cfg fails
|
||||
"unpack-comp-huf",
|
||||
"unpack-comp-rle",
|
||||
|
||||
@@ -245,9 +232,6 @@
|
||||
"sp-process-block-2d",
|
||||
"sp-get-particle",
|
||||
|
||||
// loader BUG
|
||||
"(method 10 external-art-buffer)",
|
||||
|
||||
// game-info BUG
|
||||
"(method 11 fact-info-target)",
|
||||
|
||||
@@ -277,9 +261,6 @@
|
||||
"render-boundary-quad",
|
||||
"draw-boundary-polygon",
|
||||
|
||||
// text BUG
|
||||
"load-game-text-info",
|
||||
|
||||
// collide-probe
|
||||
"collide-probe-instance-tie",
|
||||
"collide-probe-node",
|
||||
@@ -348,9 +329,6 @@
|
||||
"(anon-function 67 target2)", // BUG:
|
||||
"look-for-points-of-interest",
|
||||
|
||||
// menu BUG
|
||||
"debug-menu-item-var-render",
|
||||
|
||||
// drawable-tree
|
||||
"(method 16 drawable-tree)",
|
||||
|
||||
@@ -395,9 +373,6 @@
|
||||
"ocean-generate-verts",
|
||||
"ocean-interp-wave",
|
||||
|
||||
// anim-tester BUG
|
||||
"anim-tester-add-newobj",
|
||||
|
||||
// nav-enemy BUG
|
||||
"(anon-function 28 nav-enemy)",
|
||||
|
||||
@@ -431,18 +406,8 @@
|
||||
"(anon-function 43 maincave-obs)",
|
||||
"(anon-function 2 target-tube)",
|
||||
"(anon-function 5 orbit-plat)",
|
||||
"(anon-function 2 ogreboss)",
|
||||
"(anon-function 2 ogreboss)"
|
||||
|
||||
// not enough type info to decompile these
|
||||
// (these are NOT actually asm functions)
|
||||
"(method 15 sync-info)", // NEED *res-static-buf*
|
||||
"(method 15 sync-info-eased)", // NEED *res-static-buf*
|
||||
"(method 15 sync-info-paused)", // NEED *res-static-buf*
|
||||
|
||||
// stats-h
|
||||
// May or may not be inline-asm but they are related to perf counter registers that only live on the PS2
|
||||
"(method 11 perf-stat)",
|
||||
"(method 12 perf-stat)"
|
||||
],
|
||||
|
||||
// these functions use pairs and the decompiler
|
||||
@@ -480,7 +445,9 @@
|
||||
"debug-menu-send-msg",
|
||||
"debug-menu-find-from-template",
|
||||
"build-continue-menu",
|
||||
"(method 8 process-tree)"
|
||||
"(method 8 process-tree)",
|
||||
"(method 16 load-state)",
|
||||
"(method 15 load-state)"
|
||||
],
|
||||
|
||||
// If format is used with the wrong number of arguments,
|
||||
@@ -505,8 +472,11 @@
|
||||
" pris-geo ~192H~5DK ~280Hpris-fragment~456H~5DK~%": 2,
|
||||
" pris-anim ~192H~5DK ~280Hpris-generic~456H~5DK~%": 2,
|
||||
" textures ~192H~5DK ~280Htextures~456H~5DK~%": 2,
|
||||
" entity ~192H~5DK~%":2,
|
||||
" misc ~192H~5DK ~280Hsprite~456H~5DK~%":2
|
||||
" entity ~192H~5DK~%": 2,
|
||||
" misc ~192H~5DK ~280Hsprite~456H~5DK~%": 2,
|
||||
"ERROR: <asg> ~A in spool anim loop for ~A ~D, but not loaded.~": 3,
|
||||
"~0k~5d/~d ~6d/~d ~6d/~d ": 6,
|
||||
"~0k~s~%": 1
|
||||
},
|
||||
|
||||
"blocks_ending_in_asm_branch": {
|
||||
@@ -538,6 +508,22 @@
|
||||
|
||||
"adgif-shader<-texture-with-update!": [0, 1],
|
||||
|
||||
"display-loop": [44, 49, 66, 96]
|
||||
"display-loop": [44, 49, 66, 96],
|
||||
|
||||
"load-game-text-info": [12, 13, 14, 18],
|
||||
|
||||
"real-main-draw-hook": [75, 77],
|
||||
|
||||
"(method 12 perf-stat)": [0],
|
||||
"(method 11 perf-stat)": [0],
|
||||
"raw-ray-sphere-intersect": [0, 1, 2, 3, 4, 5],
|
||||
"ray-cylinder-intersect": [0, 1, 2, 3, 4, 5],
|
||||
"ray-triangle-intersect": [0, 1, 2, 3, 4],
|
||||
"bsp-camera-asm": [1, 2, 3],
|
||||
"level-remap-texture": [2, 3, 4, 5, 6],
|
||||
"start-perf-stat-collection": [26],
|
||||
"end-perf-stat-collection": [0],
|
||||
|
||||
"sprite-draw-distorters": [4, 5]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,5 +256,13 @@
|
||||
"TEXT/4COMMON.TXT",
|
||||
"TEXT/5COMMON.TXT",
|
||||
"TEXT/6COMMON.TXT"
|
||||
],
|
||||
|
||||
// uncomment the next line to extract audio to wave files.
|
||||
//"audio_dir_file_name": "jak1/VAG",
|
||||
"audio_dir_file_name": "",
|
||||
|
||||
"streamed_audio_file_names": [
|
||||
"VAGWAD.ENG"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
"ocean-h": [["L2", "ocean-work", true]],
|
||||
|
||||
"ocean-trans-tables": [
|
||||
["L1", "(pointer float)", true, 16],
|
||||
["L1", "(inline-array vector)", true, 4],
|
||||
["L2", "(pointer float)", true, 160],
|
||||
["L3", "(pointer float)", true, 100],
|
||||
["L4", "(pointer float)", true, 72],
|
||||
@@ -144,25 +144,28 @@
|
||||
|
||||
"ocean-tables": [
|
||||
// see comment in ocean-tables.gc
|
||||
// ["L26", "ocean-spheres", true],
|
||||
// ["L18", "ocean-spheres", true],
|
||||
// ["L25", "ocean-colors", true],
|
||||
// ["L17", "ocean-colors", true],
|
||||
// ["L23", "ocean-near-indices", true],
|
||||
// ["L15", "ocean-near-indices", true],
|
||||
// ["L9", "ocean-near-indices", true],
|
||||
// ["L22", "ocean-trans-indices", true],
|
||||
// ["L14", "ocean-trans-indices", true],
|
||||
// ["L8", "ocean-trans-indices", true],
|
||||
// ["L21", "ocean-mid-indices", true],
|
||||
// ["L13", "ocean-mid-indices", true],
|
||||
// ["L7", "ocean-mid-indices", true],
|
||||
// ["L19", "ocean-mid-masks", true],
|
||||
// ["L11", "ocean-mid-masks", true],
|
||||
// ["L5", "ocean-mid-masks", true],
|
||||
// ["L4", "ocean-map", true],
|
||||
// ["L3", "ocean-map", true],
|
||||
// ["L2", "ocean-map", true]
|
||||
["L26", "ocean-spheres", true],
|
||||
["L25", "ocean-colors", true],
|
||||
["L23", "ocean-near-indices", true], // ok
|
||||
["L22", "ocean-trans-indices", true],
|
||||
["L21", "ocean-mid-indices", true],
|
||||
["L19", "ocean-mid-masks", true],
|
||||
["L18", "ocean-spheres", true],
|
||||
["L17", "ocean-colors", true],
|
||||
["L15", "ocean-near-indices", true],
|
||||
["L9", "ocean-near-indices", true],
|
||||
|
||||
["L14", "ocean-trans-indices", true],
|
||||
["L8", "ocean-trans-indices", true],
|
||||
|
||||
["L13", "ocean-mid-indices", true],
|
||||
["L7", "ocean-mid-indices", true],
|
||||
|
||||
["L11", "ocean-mid-masks", true],
|
||||
["L5", "ocean-mid-masks", true],
|
||||
["L4", "ocean-map", true],
|
||||
["L3", "ocean-map", true],
|
||||
["L2", "ocean-map", true]
|
||||
],
|
||||
|
||||
"ocean-frames": [["L1", "(pointer uint32)", true, 16384]],
|
||||
@@ -450,7 +453,12 @@
|
||||
|
||||
"trajectory": [["L18", "uint64", true]],
|
||||
|
||||
"res": [["L150", "uint64", true]],
|
||||
"res": [
|
||||
["L150", "uint64", true],
|
||||
["L152", "uint64", true],
|
||||
["L151", "uint64", true],
|
||||
["L153", "uint64", true]
|
||||
],
|
||||
|
||||
"ripple": [
|
||||
["L73", "float", true],
|
||||
@@ -489,12 +497,18 @@
|
||||
|
||||
"cam-update-h": [["L2", "bfloat", true]],
|
||||
|
||||
"collide-func": [["L41", "float", true]],
|
||||
"collide-func": [
|
||||
["L41", "float", true],
|
||||
["L40", "float", true]
|
||||
],
|
||||
|
||||
"cylinder": [
|
||||
["L27", "float", true],
|
||||
["L54", "vector", true],
|
||||
["L60", "float", true]
|
||||
["L60", "float", true],
|
||||
["L57", "vector", true],
|
||||
["L56", "vector", true],
|
||||
["L53", "vector", true]
|
||||
],
|
||||
|
||||
"debug-sphere": [["L10", "debug-sphere-table", true]],
|
||||
@@ -556,11 +570,29 @@
|
||||
["L12", "uint64", true]
|
||||
],
|
||||
|
||||
"shadow-cpu": [["L122", "shadow-data", true]],
|
||||
|
||||
"entity-table": [["L8", "(array entity-info)", true]],
|
||||
|
||||
"main": [["L230", "_lambda_", true], ["L309", "float", true]],
|
||||
"main": [
|
||||
["L230", "_lambda_", true],
|
||||
["L309", "float", true],
|
||||
["L306", "screen-filter", true],
|
||||
["L311", "uint64", true],
|
||||
["L312", "uint64", true],
|
||||
["L317", "uint64", true],
|
||||
["L316", "uint64", true],
|
||||
["L320", "uint64", true],
|
||||
["L314", "uint64", true],
|
||||
["L313", "uint64", true],
|
||||
["L315", "uint64", true]
|
||||
],
|
||||
|
||||
"geometry": [["L125", "float", true], ["L126", "float", true], ["L112", "(pointer float)", true, 4]],
|
||||
"geometry": [
|
||||
["L125", "float", true],
|
||||
["L126", "float", true],
|
||||
["L112", "(pointer float)", true, 4]
|
||||
],
|
||||
|
||||
"level": [
|
||||
["L452", "_auto_", true],
|
||||
@@ -583,7 +615,11 @@
|
||||
["L255", "float", true]
|
||||
],
|
||||
|
||||
"load-boundary": [["L327", "(inline-array lbvtx)", true, 3]],
|
||||
"load-boundary": [
|
||||
["L327", "(inline-array lbvtx)", true, 3],
|
||||
["L336", "float", true],
|
||||
["L337", "float", true]
|
||||
],
|
||||
|
||||
"shrub-work": [["L3", "instance-shrub-work", true]],
|
||||
|
||||
@@ -1163,9 +1199,7 @@
|
||||
["L38", "uint64", true],
|
||||
["L39", "uint64", true]
|
||||
],
|
||||
"memory-usage": [
|
||||
["L15", "_lambda_", true]
|
||||
],
|
||||
"memory-usage": [["L15", "_lambda_", true]],
|
||||
|
||||
"path": [
|
||||
["L47", "float", true],
|
||||
@@ -1174,6 +1208,211 @@
|
||||
["L79", "rgba", true]
|
||||
],
|
||||
|
||||
"loader": [
|
||||
["L279", "float", true],
|
||||
["L283", "float", true],
|
||||
["L285", "float", true],
|
||||
["L286", "float", true],
|
||||
["L280", "float", true],
|
||||
["L281", "float", true],
|
||||
["L278", "float", true]
|
||||
],
|
||||
|
||||
"yakow": [
|
||||
["L150", "float", true],
|
||||
["L162", "float", true],
|
||||
["L160", "float", true],
|
||||
["L155", "float", true],
|
||||
["L163", "float", true],
|
||||
["L159", "float", true],
|
||||
["L154", "float", true],
|
||||
["L153", "float", true],
|
||||
["L169", "float", true],
|
||||
["L161", "float", true],
|
||||
["L152", "float", true],
|
||||
["L149", "float", true]
|
||||
],
|
||||
|
||||
"farmer": [["L50", "float", true]],
|
||||
|
||||
"bsp": [
|
||||
["L54", "rgba", true],
|
||||
["L85", "rgba", true],
|
||||
["L86", "rgba", true],
|
||||
["L55", "rgba", true],
|
||||
["L53", "uint64", true],
|
||||
["L56", "uint64", true]
|
||||
],
|
||||
|
||||
"subdivide": [
|
||||
["L129", "float", true],
|
||||
["L128", "float", true],
|
||||
["L114", "rgba", true],
|
||||
["L113", "uint64", true]
|
||||
],
|
||||
|
||||
"sprite": [
|
||||
["L93", "uint64", true],
|
||||
["L92", "uint64", true],
|
||||
["L83", "uint64", true],
|
||||
["L90", "uint64", true],
|
||||
["L91", "uint64", true],
|
||||
["L84", "uint64", true],
|
||||
["L89", "uint64", true],
|
||||
["L88", "uint64", true],
|
||||
["L86", "uint64", true],
|
||||
["L82", "uint64", true],
|
||||
["L94", "uint64", true],
|
||||
["L87", "uint64", true],
|
||||
["L85", "uint64", true]
|
||||
],
|
||||
|
||||
"sprite-distort": [
|
||||
["L42", "uint64", true],
|
||||
["L39", "uint64", true],
|
||||
["L41", "uint64", true],
|
||||
["L40", "uint64", true],
|
||||
["L37", "uint64", true],
|
||||
["L38", "uint64", true]
|
||||
],
|
||||
|
||||
"anim-tester": [
|
||||
["L615", "_auto_", true],
|
||||
["L592", "_auto_", true],
|
||||
["L509", "(inline-array list-field)", true, 12],
|
||||
["L123", "_lambda_", true],
|
||||
["L119", "_lambda_", true],
|
||||
["L86", "_lambda_", true],
|
||||
["L652", "float", true]
|
||||
],
|
||||
|
||||
"default-menu": [
|
||||
["L519", "pair", true],
|
||||
["L1550", "pair", true],
|
||||
["L1552", "pair", true]
|
||||
],
|
||||
|
||||
"generic-vu1": [
|
||||
["L12", "gif-tag64", true],
|
||||
["L15", "gif-tag64", true],
|
||||
["L14", "gif-tag-regs", true]
|
||||
],
|
||||
|
||||
"main-collide": [
|
||||
["L5", "rgba", true]
|
||||
],
|
||||
|
||||
"camera": [
|
||||
["L257", "(inline-array qword)", true, 1],
|
||||
["L258", "(inline-array qword)", true, 1],
|
||||
["L271", "float", true],
|
||||
["L278", "float", true],
|
||||
["L279", "float", true],
|
||||
["L285", "float", true],
|
||||
["L287", "float", true],
|
||||
["L288", "float", true],
|
||||
["L291", "float", true],
|
||||
["L292", "float", true],
|
||||
["L293", "float", true],
|
||||
["L297", "float", true],
|
||||
["L299", "float", true],
|
||||
["L301", "float", true],
|
||||
["L302", "float", true],
|
||||
["L312", "float", true],
|
||||
["L314", "float", true],
|
||||
["L315", "float", true],
|
||||
["L317", "float", true],
|
||||
["L321", "float", true],
|
||||
["L323", "float", true]
|
||||
],
|
||||
|
||||
"cam-combiner": [
|
||||
["L4", "_lambda_", true],
|
||||
["L54", "_lambda_", true],
|
||||
["L77", "state", true],
|
||||
["L90", "float", true]
|
||||
],
|
||||
|
||||
"cam-master": [
|
||||
["L369", "float", true],
|
||||
["L370", "float", true],
|
||||
["L371", "float", true]
|
||||
],
|
||||
|
||||
"cam-update": [
|
||||
["L82", "float", true],
|
||||
["L84", "float", true],
|
||||
["L88", "rgba", true]
|
||||
],
|
||||
|
||||
"cam-states-dbg": [
|
||||
["L90", "float", true],
|
||||
["L91", "float", true],
|
||||
["L92", "float", true],
|
||||
["L93", "float", true],
|
||||
["L94", "float", true],
|
||||
["L98", "float", true],
|
||||
["L99", "float", true]
|
||||
],
|
||||
|
||||
"mood": [
|
||||
["L256", "vector", true],
|
||||
["L257", "vector", true],
|
||||
["L258", "vector", true],
|
||||
["L259", "vector", true],
|
||||
["L260", "vector", true],
|
||||
["L261", "vector", true],
|
||||
["L262", "(inline-array vector)", true, 2],
|
||||
["L263", "light-ellipse", true],
|
||||
["L264", "(inline-array vector)", true, 4],
|
||||
["L265", "vector", true],
|
||||
["L266", "(inline-array vector)", true, 11],
|
||||
["L267", "vector", true],
|
||||
["L268", "vector", true],
|
||||
["L269", "vector", true],
|
||||
["L270", "vector", true],
|
||||
["L271", "vector", true],
|
||||
["L272", "vector", true],
|
||||
["L273", "vector", true],
|
||||
["L274", "vector", true],
|
||||
["L275", "vector", true],
|
||||
["L276", "vector", true],
|
||||
["L277", "vector", true],
|
||||
["L278", "vector", true],
|
||||
["L279", "vector", true],
|
||||
["L287", "(array float)", true],
|
||||
["L286", "(array float)", true],
|
||||
["L285", "(array float)", true],
|
||||
["L284", "(array float)", true],
|
||||
["L283", "(array float)", true],
|
||||
["L282", "(array float)", true],
|
||||
["L281", "(array float)", true],
|
||||
["L280", "(array float)", true],
|
||||
["L290", "float", true],
|
||||
["L291", "float", true],
|
||||
["L392", "float", true],
|
||||
["L393", "float", true],
|
||||
["L404", "float", true],
|
||||
["L419", "float", true],
|
||||
["L420", "float", true],
|
||||
["L421", "float", true],
|
||||
["L429", "float", true],
|
||||
["L450", "float", true],
|
||||
["L452", "float", true],
|
||||
["L453", "float", true],
|
||||
["L454", "float", true],
|
||||
["L455", "float", true],
|
||||
["L460", "float", true],
|
||||
["L461", "float", true],
|
||||
["L463", "float", true],
|
||||
["L465", "float", true],
|
||||
["L471", "float", true],
|
||||
["L480", "float", true],
|
||||
["L494", "float", true],
|
||||
["L497", "float", true],
|
||||
["L508", "float", true]
|
||||
],
|
||||
|
||||
"nav-enemy": [
|
||||
["L353", "float", true],
|
||||
["L354", "float", true],
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
"make-light-kit": [[16, "matrix"]],
|
||||
|
||||
"matrix<-parented-transformq!": [[16, "quaternion"]],
|
||||
"matrix<-parented-transformq!": [[16, "vector"]],
|
||||
|
||||
"(method 20 trsqv)": [[16, "vector"]],
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "quaternion"]
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"(method 16 trsqv)": [
|
||||
@@ -216,8 +216,6 @@
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"make-light-kit": [[16, "matrix"]],
|
||||
|
||||
"(method 23 trsqv)": [[16, "vector"]],
|
||||
"(method 24 trsqv)": [[16, "vector"]],
|
||||
|
||||
@@ -334,6 +332,8 @@
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"(method 20 actor-link-info)": [[16, "event-message-block"]],
|
||||
"(method 21 actor-link-info)": [[16, "event-message-block"]],
|
||||
"(method 23 actor-link-info)": [[16, "event-message-block"]],
|
||||
|
||||
"(method 24 actor-link-info)": [[16, "event-message-block"]],
|
||||
@@ -394,9 +394,14 @@
|
||||
[32, "tracking-spline-sampler"]
|
||||
],
|
||||
|
||||
"draw-ocean-transition": [[16, "sphere"]],
|
||||
"draw-ocean-transition": [
|
||||
[16, "sphere"]
|
||||
],
|
||||
|
||||
"dm-cam-mode-func": [[16, "event-message-block"]],
|
||||
"ocean-trans-add-upload-table": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"dm-cam-settings-func": [[16, "event-message-block"]],
|
||||
|
||||
@@ -421,6 +426,7 @@
|
||||
"(method 22 level)": [[16, "event-message-block"]],
|
||||
"(method 9 level)": [[16, "event-message-block"]],
|
||||
"(method 10 load-state)": [[16, "event-message-block"]],
|
||||
"cam-slave-get-rot": [[16, "quaternion"]],
|
||||
|
||||
"draw-joint-spheres": [[16, "vector"]],
|
||||
"(method 16 process-drawable)": [
|
||||
@@ -497,9 +503,7 @@
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"vector-plane-distance": [
|
||||
[16, "vector"]
|
||||
],
|
||||
"vector-plane-distance": [[16, "vector"]],
|
||||
|
||||
"curve-length": [
|
||||
[16, "vector"],
|
||||
@@ -521,17 +525,11 @@
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"mem-size": [
|
||||
[16, "memory-usage-block"]
|
||||
],
|
||||
"mem-size": [[16, "memory-usage-block"]],
|
||||
|
||||
"display-loop": [
|
||||
[16, "sphere"]
|
||||
],
|
||||
"display-loop": [[16, "sphere"]],
|
||||
|
||||
"(method 14 curve-control)": [
|
||||
[16, "vector"]
|
||||
],
|
||||
"(method 14 curve-control)": [[16, "vector"]],
|
||||
|
||||
"(method 19 path-control)": [
|
||||
[16, "vector"],
|
||||
@@ -540,6 +538,289 @@
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"progress-allowed?": [[16, "event-message-block"]],
|
||||
|
||||
"(method 9 align-control)": [
|
||||
[16, "matrix"],
|
||||
[80, "quaternion"]
|
||||
],
|
||||
|
||||
"(method 10 align-control)": [[16, "vector"]],
|
||||
|
||||
"(method 15 load-state)": [
|
||||
[16, "event-message-block"],
|
||||
[96, "event-message-block"]
|
||||
],
|
||||
|
||||
"(method 43 farmer)": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"yakow-post": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "vector"],
|
||||
[80, "vector"],
|
||||
[96, "vector"]
|
||||
],
|
||||
|
||||
"anim-tester-save-object-seqs": [
|
||||
[16, "file-stream"]
|
||||
],
|
||||
|
||||
"anim-test-obj-list-handler": [[16, "event-message-block"]],
|
||||
"anim-test-anim-list-handler": [[16, "event-message-block"]],
|
||||
"anim-test-sequence-list-handler": [[16, "event-message-block"]],
|
||||
"anim-test-edit-sequence-list-handler": [[16, "event-message-block"]],
|
||||
"anim-test-edit-seq-insert-item": [[16, "event-message-block"]],
|
||||
"anim-test-edit-sequence-list-handler": [
|
||||
[112, "event-message-block"],
|
||||
[16, "font-context"]
|
||||
],
|
||||
"anim-tester-add-newobj": [[16, "event-message-block"]],
|
||||
"anim-tester-start": [[16, "event-message-block"]],
|
||||
"anim-tester-add-sequence": [[16, "event-message-block"]],
|
||||
|
||||
"(anon-function 28 task-control)": [[16, "event-message-block"]],
|
||||
|
||||
"instance-tfragment-add-debug-sphere": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"(method 10 game-save)": [[16, "file-stream"]],
|
||||
|
||||
"cam-state-from-entity": [[16, "curve"]],
|
||||
|
||||
"(method 9 cam-index)": [[16, "vector"]],
|
||||
|
||||
"(method 10 cam-index)": [[16, "vector"]],
|
||||
|
||||
"(method 15 tracking-spline)": [
|
||||
[16, "tracking-spline-sampler"],
|
||||
[32, "tracking-point"]
|
||||
],
|
||||
|
||||
"(method 16 tracking-spline)": [
|
||||
[16, "tracking-spline-sampler"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"(method 18 tracking-spline)": [
|
||||
[16, "tracking-spline-sampler"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"(method 20 tracking-spline)": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"(method 21 tracking-spline)": [
|
||||
[16, "tracking-spline-sampler"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"(method 22 tracking-spline)": [
|
||||
[16, "tracking-spline-sampler"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"cam-slave-init": [[16, "event-message-block"]],
|
||||
|
||||
"cam-curve-pos": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"]
|
||||
],
|
||||
|
||||
"curve-length": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"curve-closest-point": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"cam-calc-follow!": [
|
||||
[16, "event-message-block"],
|
||||
[96, "vector"],
|
||||
[112, "vector"],
|
||||
[128, "vector"],
|
||||
[144, "vector"]
|
||||
],
|
||||
|
||||
"mat-remove-z-rot": [
|
||||
[16, "vector"],
|
||||
[32, "matrix"]
|
||||
],
|
||||
|
||||
"slave-matrix-blend-2": [
|
||||
[16, "vector"],
|
||||
[32, "quaternion"],
|
||||
[48, "quaternion"],
|
||||
[64, "quaternion"]
|
||||
],
|
||||
|
||||
"vector-into-frustum-nosmooth!": [
|
||||
[16, "matrix"],
|
||||
[80, "vector"],
|
||||
[96, "vector"]
|
||||
],
|
||||
|
||||
"slave-set-rotation!": [
|
||||
[16, "vector"],
|
||||
[32, "matrix"],
|
||||
[96, "vector"],
|
||||
[112, "matrix"], // guess
|
||||
[176, "vector"] // guess
|
||||
],
|
||||
|
||||
"v-slrp2!": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "matrix"],
|
||||
[128, "vector"]
|
||||
],
|
||||
|
||||
"v-slrp3!": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "matrix"],
|
||||
[128, "vector"]
|
||||
],
|
||||
|
||||
"(anon-function 1 cam-combiner)": [
|
||||
[16, "vector"],
|
||||
[32, "matrix"],
|
||||
[80, "vector"],
|
||||
[96, "matrix"]
|
||||
],
|
||||
|
||||
"cam-master-init": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"plane-from-points": [[16, "vector"]],
|
||||
|
||||
"update-view-planes": [
|
||||
[16, "view-frustum"],
|
||||
[144, "vector"],
|
||||
[160, "vector"],
|
||||
[176, "vector"],
|
||||
[192, "vector"],
|
||||
[208, "vector"],
|
||||
[224, "vector"]
|
||||
],
|
||||
|
||||
"move-camera-from-pad": [[16, "vector"]],
|
||||
|
||||
"cam-free-floating-move": [[16, "camera-free-floating-move-info"]],
|
||||
|
||||
"update-camera": [
|
||||
[16, "vector"],
|
||||
[32, "quaternion"],
|
||||
[48, "vector"]
|
||||
],
|
||||
|
||||
"ocean-make-trans-camera-masks": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"(anon-function 28 task-control)": [[16, "event-message-block"]],
|
||||
|
||||
"update-mood-prt-color": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-swamp": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-village1": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-maincave": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-ogre": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-finalboss": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-darkcave": [
|
||||
[16, "vector"],
|
||||
[32, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-citadel": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "vector"],
|
||||
[80, "vector"],
|
||||
[96, "vector"],
|
||||
[112, "vector"],
|
||||
[128, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-jungleb": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-sunken": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-village2": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "vector"]
|
||||
],
|
||||
|
||||
"update-mood-rolling": [
|
||||
[16, "vector"] // TODO - really not sure about this one
|
||||
],
|
||||
|
||||
"update-mood-village3": [
|
||||
[16, "vector"],
|
||||
[32, "vector"],
|
||||
[48, "vector"],
|
||||
[64, "vector"],
|
||||
[80, "vector"],
|
||||
[96, "vector"]
|
||||
],
|
||||
|
||||
"ocean-transition-check": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"ocean-trans-add-upload-strip": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"draw-ocean-transition-seams": [
|
||||
[16, "sphere"]
|
||||
],
|
||||
|
||||
"(method 50 nav-enemy)": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
@@ -206,7 +206,24 @@
|
||||
"default-buffer-init": [
|
||||
[[8, 15], "a1", "dma-gif-packet"],
|
||||
[[18, 24], "a1", "gs-gif-tag"],
|
||||
[[29, 64], "a1", "(pointer uint64)"],
|
||||
[29, "a1", "(pointer gs-alpha)"],
|
||||
[31, "a1", "(pointer gs-reg64)"],
|
||||
[33, "a1", "(pointer gs-zbuf)"],
|
||||
[35, "a1", "(pointer gs-reg64)"],
|
||||
[37, "a1", "(pointer gs-test)"],
|
||||
[39, "a1", "(pointer gs-reg64)"],
|
||||
[40, "a1", "(pointer uint64)"],
|
||||
[42, "a1", "(pointer gs-reg64)"],
|
||||
[44, "a1", "(pointer gs-clamp)"],
|
||||
[46, "a1", "(pointer gs-reg64)"],
|
||||
[48, "a1", "(pointer gs-tex1)"],
|
||||
[50, "a1", "(pointer gs-reg64)"],
|
||||
[53, "a1", "(pointer gs-texa)"],
|
||||
[55, "a1", "(pointer gs-reg64)"],
|
||||
[57, "a1", "(pointer gs-texclut)"],
|
||||
[59, "a1", "(pointer gs-reg64)"],
|
||||
[61, "a1", "(pointer gs-fogcol)"],
|
||||
[63, "a1", "(pointer gs-reg64)"],
|
||||
[[69, 72], "a0", "dma-packet"]
|
||||
],
|
||||
|
||||
@@ -407,15 +424,15 @@
|
||||
|
||||
"adgif-shader<-texture-simple!": [[5, "v1", "uint"]],
|
||||
|
||||
"display-frame-start": [
|
||||
[4, "v1", "(pointer uint32)"]
|
||||
],
|
||||
"display-frame-start": [[4, "v1", "(pointer uint32)"]],
|
||||
|
||||
"display-loop": [
|
||||
[152, "v1", "(pointer int32)"],
|
||||
[157, "a0", "(pointer process-drawable)"]
|
||||
],
|
||||
|
||||
"load-game-text-info": [[4, "v1", "game-text-info"]],
|
||||
|
||||
"texture-relocate": [
|
||||
[[17, 21], "t4", "dma-packet"],
|
||||
[[27, 30], "t4", "gs-gif-tag"],
|
||||
@@ -504,12 +521,46 @@
|
||||
[22, "t1", "(pointer uint64)"],
|
||||
[29, "t2", "(pointer uint64)"]
|
||||
],
|
||||
"(method 18 res-lump)": [["_stack_", 16, "res-tag"]],
|
||||
"(method 18 res-lump)": [["_stack_", 16, "object"]],
|
||||
"(method 21 res-lump)": [
|
||||
["_stack_", 16, "res-tag"],
|
||||
["_stack_", 32, "res-tag"]
|
||||
],
|
||||
|
||||
"(method 15 sync-info)": [
|
||||
["_stack_", 16, "res-tag"],
|
||||
[[19, 24], "v1", "(pointer float)"]
|
||||
],
|
||||
|
||||
"(method 15 sync-info-eased)": [
|
||||
["_stack_", 16, "res-tag"],
|
||||
[[44, 49], "v1", "(pointer float)"],
|
||||
[[26, 35], "v1", "(pointer float)"]
|
||||
],
|
||||
|
||||
"(method 15 sync-info-paused)": [
|
||||
["_stack_", 16, "res-tag"],
|
||||
[[44, 49], "v1", "(pointer float)"],
|
||||
[[26, 35], "v1", "(pointer float)"]
|
||||
],
|
||||
|
||||
"(method 15 res-lump)": [[132, "s5", "res-tag-pair"]],
|
||||
|
||||
"(method 17 res-lump)": [[22, "s4", "(pointer pointer)"]],
|
||||
|
||||
"(method 20 res-lump)": [[331, "a3", "(inline-array vector)"]],
|
||||
|
||||
"(method 8 res-lump)": [
|
||||
[215, "s0", "array"],
|
||||
[[0, 100], "s0", "basic"],
|
||||
[[102, 120], "s0", "basic"],
|
||||
[[147, 150], "s0", "collide-mesh"],
|
||||
[[157, 200], "s0", "(array object)"],
|
||||
//[[197, 199], "s0", "(array basic)"],
|
||||
//[[236, 240], "a0", "basic"]
|
||||
[235, "s0", "basic"]
|
||||
],
|
||||
|
||||
// SHADOW-CPU-H
|
||||
"(method 10 shadow-control)": [[1, "v1", "int"]],
|
||||
|
||||
@@ -527,7 +578,7 @@
|
||||
|
||||
"(method 0 fact-info)": [
|
||||
[81, "v0", "float"],
|
||||
[16, "t9", "(function string none)"],
|
||||
//[16, "t9", "(function string none)"],
|
||||
["_stack_", 16, "res-tag"],
|
||||
[[32, 43], "v1", "(pointer int32)"],
|
||||
[86, "gp", "fact-info"]
|
||||
@@ -535,10 +586,7 @@
|
||||
|
||||
"(method 0 fact-info-target)": [[[3, 20], "gp", "fact-info-target"]],
|
||||
|
||||
"(method 0 align-control)": [
|
||||
[[8, 13], "t9", "(function object object)"],
|
||||
[[14, 18], "v0", "align-control"]
|
||||
],
|
||||
"(method 0 align-control)": [[[14, 18], "v0", "align-control"]],
|
||||
|
||||
"str-load": [[[20, 36], "s2", "load-chunk-msg"]],
|
||||
|
||||
@@ -581,8 +629,6 @@
|
||||
[[11, 18], "v0", "collide-shape-prim-group"]
|
||||
],
|
||||
|
||||
"camera-teleport-to-entity": [[9, "a0", "transform"]],
|
||||
|
||||
"entity-actor-count": [["_stack_", 16, "res-tag"]],
|
||||
|
||||
"entity-actor-lookup": [
|
||||
@@ -592,8 +638,7 @@
|
||||
|
||||
"(method 11 joint-mod)": [
|
||||
[15, "s3", "process-drawable"],
|
||||
[[26, 66], "s3", "fact-info-enemy"],
|
||||
[[45, 50], "v1", "(pointer process)"]
|
||||
[[26, 66], "s3", "fact-info-enemy"]
|
||||
],
|
||||
|
||||
"joint-mod-look-at-handler": [[[2, 254], "gp", "joint-mod"]],
|
||||
@@ -622,8 +667,6 @@
|
||||
|
||||
"num-func-chan": [[8, "v1", "joint-control-channel"]],
|
||||
|
||||
"cspace-by-name-no-fail": [[[0, 100], "v0", "cspace"]],
|
||||
|
||||
"shrubbery-login-post-texture": [
|
||||
//[[13, 41], "a3", "qword"],
|
||||
// [[13, 41], "a2", "qword"]
|
||||
@@ -641,8 +684,6 @@
|
||||
|
||||
"(method 3 sparticle-cpuinfo)": [[106, "f0", "float"]],
|
||||
|
||||
"cspace-by-name-no-fail": [[[0, 100], "v0", "cspace"]],
|
||||
|
||||
"camera-teleport-to-entity": [[9, "a0", "transform"]],
|
||||
|
||||
"add-debug-sphere-from-table": [[[9, 18], "s1", "(inline-array vector)"]],
|
||||
@@ -704,7 +745,6 @@
|
||||
"actor-link-subtask-complete-hook": [[1, "v1", "entity-links"]],
|
||||
|
||||
"(method 0 vol-control)": [
|
||||
[[9, 14], "t9", "(function object object)"],
|
||||
[30, "s5", "res-lump"],
|
||||
[36, "s5", "res-lump"],
|
||||
[58, "s5", "res-lump"],
|
||||
@@ -729,10 +769,7 @@
|
||||
],
|
||||
"(method 12 art-group)": [[13, "a0", "art-joint-anim"]],
|
||||
|
||||
"(method 0 path-control)": [
|
||||
[15, "t9", "(function string none)"],
|
||||
["_stack_", 16, "res-tag"]
|
||||
],
|
||||
"(method 0 path-control)": [["_stack_", 16, "res-tag"]],
|
||||
|
||||
"(method 0 curve-control)": [[[13, 55], "s3", "entity"]],
|
||||
|
||||
@@ -746,8 +783,6 @@
|
||||
[77, "a0", "entity-links"]
|
||||
],
|
||||
|
||||
"(method 0 nav-control)": [[17, "t9", "(function string none)"]],
|
||||
|
||||
"add-debug-point": [
|
||||
[125, "a3", "pointer"],
|
||||
[[27, 144], "a0", "(pointer uint64)"],
|
||||
@@ -790,7 +825,12 @@
|
||||
"debug-pad-display": [[[70, 75], "v1", "dma-packet"]],
|
||||
"internal-draw-debug-text-3d": [[[54, 59], "v1", "dma-packet"]],
|
||||
"drawable-frag-count": [[[14, 20], "s5", "drawable-group"]],
|
||||
"generic-init-buffers": [[[39, 44], "v1", "dma-packet"]],
|
||||
|
||||
"generic-init-buffers": [
|
||||
[[39, 44], "v1", "dma-packet"],
|
||||
[25, "s5", "gs-zbuf"],
|
||||
[32, "gp", "gs-zbuf"]
|
||||
],
|
||||
|
||||
"(method 13 drawable-inline-array-collide-fragment)": [
|
||||
[[1, 5], "v1", "collide-fragment"]
|
||||
@@ -804,7 +844,10 @@
|
||||
[[1, 5], "v1", "collide-fragment"]
|
||||
],
|
||||
|
||||
"main-cheats": [[1221, "t9", "(function cpu-thread function none)"]],
|
||||
"main-cheats": [
|
||||
[1221, "t9", "(function cpu-thread function none)"],
|
||||
[[1123, 1126], "v1", "dma-packet"]
|
||||
],
|
||||
"on": [[33, "t9", "(function cpu-thread function none)"]],
|
||||
|
||||
"bg": [[37, "a0", "symbol"]],
|
||||
@@ -885,7 +928,6 @@
|
||||
[[115, 154], "s3", "continue-point"]
|
||||
],
|
||||
"(method 20 level)": [[[43, 45], "s3", "ramdisk-rpc-fill"]],
|
||||
//"bg": [[[25, 52], "a0", "string"]],
|
||||
|
||||
"(anon-function 29 process-drawable)": [
|
||||
[[0, 99999], "s6", "process-drawable"]
|
||||
@@ -1072,6 +1114,72 @@
|
||||
[[203, 210], "s4", "game-save-tag"]
|
||||
],
|
||||
|
||||
"drawable-load": [
|
||||
[17, "s5", "drawable"],
|
||||
[18, "s5", "drawable"],
|
||||
[20, "s5", "drawable"],
|
||||
[25, "s5", "drawable"],
|
||||
[27, "s5", "drawable"]
|
||||
],
|
||||
"art-load": [
|
||||
[9, "s5", "art"],
|
||||
[13, "s5", "art"],
|
||||
[15, "s5", "art"]
|
||||
],
|
||||
"art-group-load-check": [
|
||||
[22, "s3", "art-group"],
|
||||
[31, "s3", "art-group"],
|
||||
[43, "s3", "art-group"],
|
||||
[50, "s3", "art-group"],
|
||||
[52, "s3", "art-group"]
|
||||
],
|
||||
"(method 13 art-group)": [[16, "s3", "art-joint-anim"]],
|
||||
"(method 14 art-group)": [[16, "s3", "art-joint-anim"]],
|
||||
"(method 9 external-art-control)": [
|
||||
[171, "s4", "external-art-buffer"],
|
||||
[172, "s4", "external-art-buffer"],
|
||||
[173, "s4", "external-art-buffer"],
|
||||
[177, "s4", "external-art-buffer"],
|
||||
[183, "s4", "external-art-buffer"],
|
||||
[190, "s4", "external-art-buffer"],
|
||||
|
||||
[233, "s4", "spool-anim"],
|
||||
[240, "s4", "spool-anim"],
|
||||
[243, "s4", "spool-anim"],
|
||||
[248, "s4", "spool-anim"],
|
||||
[249, "s4", "spool-anim"],
|
||||
[253, "s4", "spool-anim"],
|
||||
[257, "s4", "spool-anim"]
|
||||
],
|
||||
|
||||
"(method 10 external-art-control)": [[18, "v1", "spool-anim"]],
|
||||
|
||||
"(method 16 external-art-control)": [
|
||||
[37, "a0", "process"],
|
||||
[17, "s5", "process-drawable"]
|
||||
],
|
||||
|
||||
"ja-play-spooled-anim": [
|
||||
[154, "a0", "process"],
|
||||
[286, "s2", "art-joint-anim"],
|
||||
[294, "s2", "art-joint-anim"],
|
||||
[295, "s2", "art-joint-anim"],
|
||||
[306, "s2", "art-joint-anim"],
|
||||
[320, "s2", "art-joint-anim"],
|
||||
[324, "s2", "art-joint-anim"]
|
||||
],
|
||||
|
||||
"(method 11 external-art-control)": [
|
||||
[127, "a0", "process"],
|
||||
[151, "a0", "process"],
|
||||
[168, "a0", "process"],
|
||||
[18, "s5", "process-drawable"]
|
||||
],
|
||||
|
||||
"debug-menu-item-var-make-float": [
|
||||
[30, "t9", "(function int int float float int)"]
|
||||
],
|
||||
|
||||
"debug-menu-item-var-update-display-str": [
|
||||
[[44, 49], "v1", "int"],
|
||||
[[61, 69], "v1", "int"]
|
||||
@@ -1085,11 +1193,9 @@
|
||||
],
|
||||
|
||||
"debug-menu-item-var-joypad-handler": [
|
||||
[29, "t9", "(function int int float float float)"],
|
||||
[[39, 42], "a2", "int"],
|
||||
[[40, 42], "a3", "int"],
|
||||
[41, "t9", "(function int int int int int)"],
|
||||
[175, "t9", "(function int int float float float)"],
|
||||
[200, "t9", "(function int int int int int)"],
|
||||
[138, "v1", "int"],
|
||||
[143, "v1", "int"],
|
||||
@@ -1130,10 +1236,7 @@
|
||||
[[106, 110], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"debug-menu-item-var-msg": [
|
||||
[52, "t9", "(function int int float float float)"],
|
||||
[64, "t9", "(function int int int int int)"]
|
||||
],
|
||||
"debug-menu-item-var-msg": [[64, "t9", "(function int int int int int)"]],
|
||||
|
||||
"debug-menu-item-var-make-int": [
|
||||
[21, "t9", "(function int int int int int)"]
|
||||
@@ -1154,6 +1257,536 @@
|
||||
[6, "a3", "symbol"]
|
||||
],
|
||||
|
||||
"(method 9 align-control)": [
|
||||
[[27, 31], "t9", "(function object object object object)"]
|
||||
],
|
||||
|
||||
"(method 8 tie-fragment)": [
|
||||
[150, "a0", "(pointer int32)"],
|
||||
[[157, 160], "a0", "basic"]
|
||||
],
|
||||
|
||||
"letterbox": [[[29, 33], "v1", "dma-packet"]],
|
||||
|
||||
"blackout": [[[20, 24], "v1", "dma-packet"]],
|
||||
|
||||
"(method 10 external-art-control)": [[18, "v1", "pointer"]],
|
||||
|
||||
"(method 15 load-state)": [
|
||||
[31, "t9", "(function int)"],
|
||||
[291, "s5", "entity-actor"],
|
||||
[370, "s3", "process-drawable"]
|
||||
],
|
||||
|
||||
"yakow-default-event-handler": [
|
||||
[27, "a0", "collide-shape"],
|
||||
[32, "a0", "collide-shape"]
|
||||
],
|
||||
|
||||
"(method 11 yakow)": [
|
||||
[184, "v1", "vector"],
|
||||
[186, "v1", "vector"],
|
||||
[189, "v1", "vector"]
|
||||
],
|
||||
|
||||
"yakow-post": [
|
||||
[114, "a0", "collide-shape-moving"],
|
||||
[130, "a0", "collide-shape-moving"]
|
||||
],
|
||||
|
||||
"raw-ray-sphere-intersect": [
|
||||
[23, "v1", "float"],
|
||||
[36, "v1", "uint"]
|
||||
],
|
||||
|
||||
"(method 0 anim-test-obj)": [
|
||||
[9, "s4", "anim-test-obj"],
|
||||
[10, "s4", "anim-test-obj"],
|
||||
[13, "s4", "anim-test-obj"],
|
||||
[15, "s4", "anim-test-obj"]
|
||||
],
|
||||
|
||||
"(method 0 anim-test-sequence)": [
|
||||
[8, "s5", "anim-test-sequence"],
|
||||
[11, "s5", "anim-test-sequence"],
|
||||
[13, "s5", "anim-test-sequence"]
|
||||
],
|
||||
|
||||
"(method 0 anim-test-seq-item)": [
|
||||
[8, "v1", "anim-test-seq-item"],
|
||||
[10, "v0", "anim-test-seq-item"],
|
||||
[11, "v0", "anim-test-seq-item"],
|
||||
[14, "v0", "anim-test-seq-item"],
|
||||
[17, "v0", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"(method 3 anim-tester)": [
|
||||
[12, "s5", "anim-test-obj"],
|
||||
[15, "s5", "anim-test-obj"],
|
||||
[148, "s5", "anim-test-obj"],
|
||||
[150, "s5", "anim-test-obj"],
|
||||
[22, "s4", "anim-test-sequence"],
|
||||
[28, "s4", "anim-test-sequence"],
|
||||
[38, "s4", "anim-test-sequence"],
|
||||
[48, "s4", "anim-test-sequence"],
|
||||
[59, "s4", "anim-test-sequence"],
|
||||
[137, "s4", "anim-test-sequence"],
|
||||
[139, "s4", "anim-test-sequence"],
|
||||
[66, "s3", "anim-test-seq-item"],
|
||||
[70, "s3", "anim-test-seq-item"],
|
||||
[75, "s3", "anim-test-seq-item"],
|
||||
[79, "s3", "anim-test-seq-item"],
|
||||
[88, "s3", "anim-test-seq-item"],
|
||||
[94, "s3", "anim-test-seq-item"],
|
||||
[104, "s3", "anim-test-seq-item"],
|
||||
[114, "s3", "anim-test-seq-item"],
|
||||
[126, "s3", "anim-test-seq-item"],
|
||||
[128, "s3", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-test-obj-item-valid?": [
|
||||
[5, "s5", "anim-test-sequence"],
|
||||
[12, "s5", "anim-test-sequence"],
|
||||
[17, "s5", "anim-test-sequence"],
|
||||
[36, "s5", "anim-test-sequence"],
|
||||
[38, "s5", "anim-test-sequence"],
|
||||
[20, "v1", "anim-test-seq-item"],
|
||||
[26, "v1", "anim-test-seq-item"],
|
||||
[28, "v1", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-test-obj-remove-invalid": [
|
||||
[84, "v1", "anim-test-sequence"],
|
||||
[88, "v1", "anim-test-sequence"],
|
||||
[90, "v1", "anim-test-sequence"],
|
||||
[92, "v1", "anim-test-sequence"],
|
||||
[93, "v1", "anim-test-sequence"],
|
||||
[91, "a0", "anim-test-sequence"],
|
||||
[5, "s5", "anim-test-sequence"],
|
||||
[8, "s5", "anim-test-sequence"],
|
||||
[11, "s5", "anim-test-sequence"],
|
||||
[30, "s5", "anim-test-sequence"],
|
||||
[44, "s5", "anim-test-sequence"],
|
||||
[51, "s5", "anim-test-sequence"],
|
||||
[58, "s5", "anim-test-sequence"],
|
||||
[67, "s5", "anim-test-sequence"],
|
||||
[70, "s4", "anim-test-sequence"],
|
||||
[71, "s5", "anim-test-sequence"],
|
||||
[72, "s5", "anim-test-sequence"],
|
||||
[15, "s3", "anim-test-seq-item"],
|
||||
[18, "s3", "anim-test-seq-item"],
|
||||
[24, "s3", "anim-test-seq-item"],
|
||||
[31, "s3", "anim-test-seq-item"],
|
||||
[34, "s2", "anim-test-seq-item"],
|
||||
[35, "s3", "anim-test-seq-item"],
|
||||
[36, "s3", "anim-test-seq-item"],
|
||||
[61, "a0", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-tester-reset": [
|
||||
[14, "v1", "anim-test-obj"],
|
||||
[30, "v1", "anim-test-obj"],
|
||||
[33, "v1", "anim-test-obj"],
|
||||
[36, "v1", "anim-test-obj"],
|
||||
[43, "v1", "anim-test-obj"],
|
||||
[[50, 53], "v1", "anim-test-obj"]
|
||||
],
|
||||
|
||||
"anim-tester-save-all-objects": [
|
||||
[[4, 19], "gp", "anim-test-obj"],
|
||||
[17, "v1", "anim-test-obj"]
|
||||
],
|
||||
|
||||
"anim-tester-save-object-seqs": [
|
||||
[63, "s5", "anim-test-sequence"],
|
||||
[69, "s5", "anim-test-sequence"],
|
||||
[65, "s5", "anim-test-sequence"],
|
||||
[75, "s5", "anim-test-sequence"],
|
||||
[79, "s5", "anim-test-sequence"],
|
||||
[133, "s5", "anim-test-sequence"],
|
||||
[141, "s5", "anim-test-sequence"],
|
||||
[142, "v1", "anim-test-sequence"],
|
||||
[143, "s5", "anim-test-sequence"],
|
||||
[83, "s4", "anim-test-seq-item"],
|
||||
[89, "s4", "anim-test-seq-item"],
|
||||
[91, "s4", "anim-test-seq-item"],
|
||||
[92, "s4", "anim-test-seq-item"],
|
||||
[96, "s4", "anim-test-seq-item"],
|
||||
[105, "s4", "anim-test-seq-item"],
|
||||
[111, "s4", "anim-test-seq-item"],
|
||||
[120, "s4", "anim-test-seq-item"],
|
||||
[121, "v1", "anim-test-seq-item"],
|
||||
[122, "s4", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-test-obj-list-handler": [
|
||||
[25, "s5", "anim-test-obj"],
|
||||
[31, "s5", "anim-test-obj"],
|
||||
[110, "s5", "anim-test-obj"],
|
||||
[166, "s5", "anim-test-obj"],
|
||||
[112, "v1", "anim-tester"]
|
||||
],
|
||||
|
||||
"anim-test-anim-list-handler": [
|
||||
[2, "s5", "anim-test-obj"],
|
||||
[25, "s5", "anim-test-obj"],
|
||||
[65, "s5", "anim-test-obj"],
|
||||
[227, "s5", "anim-test-obj"],
|
||||
[90, "v1", "anim-test-obj"],
|
||||
[91, "v1", "anim-test-obj"],
|
||||
[100, "v1", "anim-test-obj"],
|
||||
[105, "v1", "anim-test-obj"],
|
||||
[130, "v1", "anim-test-obj"],
|
||||
[131, "v1", "anim-test-obj"],
|
||||
[140, "v1", "anim-test-obj"],
|
||||
[145, "v1", "anim-test-obj"],
|
||||
[167, "v1", "anim-test-obj"],
|
||||
[169, "v1", "anim-test-obj"],
|
||||
[171, "v1", "anim-test-obj"],
|
||||
[173, "v1", "anim-test-obj"]
|
||||
],
|
||||
|
||||
"anim-test-sequence-list-handler": [
|
||||
[2, "s5", "anim-test-sequence"],
|
||||
[25, "s5", "anim-test-sequence"],
|
||||
[31, "s5", "anim-test-sequence"],
|
||||
[71, "s5", "anim-test-sequence"],
|
||||
[231, "s5", "anim-test-sequence"],
|
||||
[96, "v1", "anim-test-sequence"],
|
||||
[97, "v1", "anim-test-sequence"],
|
||||
[106, "v1", "anim-test-sequence"],
|
||||
[111, "v1", "anim-test-sequence"],
|
||||
[136, "v1", "anim-test-sequence"],
|
||||
[137, "v1", "anim-test-sequence"],
|
||||
[146, "v1", "anim-test-sequence"],
|
||||
[151, "v1", "anim-test-sequence"]
|
||||
],
|
||||
|
||||
"anim-test-edit-sequence-list-handler": [
|
||||
[[122, 965], "s4", "anim-test-sequence"],
|
||||
[129, "v1", "glst-named-node"],
|
||||
[[128, 909], "gp", "anim-test-seq-item"],
|
||||
[380, "v0", "anim-test-obj"],
|
||||
[381, "v0", "anim-test-obj"],
|
||||
[382, "v0", "anim-test-obj"],
|
||||
[389, "v0", "anim-test-obj"],
|
||||
[483, "s3", "anim-test-seq-item"],
|
||||
[491, "s3", "anim-test-seq-item"],
|
||||
[502, "s3", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-tester-interface": [
|
||||
[[34, 48], "gp", "anim-test-obj"],
|
||||
[[95, 109], "gp", "anim-test-obj"],
|
||||
[[156, 160], "v1", "anim-test-obj"],
|
||||
[[162, 165], "v1", "anim-test-sequence"]
|
||||
],
|
||||
|
||||
"anim-tester-get-playing-item": [
|
||||
[7, "v0", "anim-test-seq-item"],
|
||||
[[5, 22], "s5", "anim-test-seq-item"],
|
||||
[21, "v0", "anim-test-seq-item"],
|
||||
[25, "v0", "anim-test-seq-item"]
|
||||
],
|
||||
|
||||
"anim-tester-add-newobj": [
|
||||
[[2, 185], "s2", "anim-test-obj"],
|
||||
[[70, 193], "s5", "anim-test-obj"],
|
||||
[149, "v1", "anim-test-sequence"],
|
||||
[154, "v1", "anim-test-sequence"],
|
||||
[160, "v1", "anim-test-sequence"],
|
||||
[164, "a0", "art-joint-anim"],
|
||||
[170, "a0", "art-joint-anim"]
|
||||
],
|
||||
|
||||
"anim-tester-start": [[20, "t9", "(function process function none)"]],
|
||||
|
||||
"anim-tester-set-name": [
|
||||
[[34, 51], "s3", "anim-test-obj"],
|
||||
[[40, 63], "s5", "anim-test-sequence"]
|
||||
],
|
||||
|
||||
"anim-tester-add-sequence": [[[33, 102], "s5", "anim-test-obj"]],
|
||||
|
||||
"(anon-function 11 anim-tester)": [
|
||||
[[23, 113], "s4", "anim-test-obj"],
|
||||
[[83, 338], "gp", "anim-test-sequence"],
|
||||
[[123, 187], "s4", "art-joint-anim"]
|
||||
],
|
||||
|
||||
"(method 10 bsp-header)": [
|
||||
[[51, 61], "a0", "(pointer uint128)"],
|
||||
[[51, 61], "a1", "(pointer uint128)"],
|
||||
[133, "v1", "terrain-bsp"],
|
||||
[141, "v1", "terrain-bsp"],
|
||||
[148, "v1", "terrain-bsp"],
|
||||
[5, "a0", "terrain-bsp"],
|
||||
[8, "a0", "terrain-bsp"]
|
||||
],
|
||||
|
||||
"(method 15 bsp-header)": [
|
||||
[5, "a0", "terrain-bsp"],
|
||||
[8, "a0", "terrain-bsp"]
|
||||
],
|
||||
|
||||
"bsp-camera-asm": [
|
||||
[[4, 14], "a1", "bsp-node"],
|
||||
[[0, 9], "v1", "bsp-node"],
|
||||
[[12, 16], "v1", "bsp-node"]
|
||||
],
|
||||
|
||||
"level-remap-texture": [
|
||||
[15, "t0", "(pointer int32)"],
|
||||
[21, "t0", "(pointer int32)"],
|
||||
[19, "t0", "(pointer uint64)"],
|
||||
[12, "v1", "int"]
|
||||
],
|
||||
|
||||
"sprite-add-matrix-data": [
|
||||
[[5, 15], "a2", "dma-packet"],
|
||||
[[24, 29], "a1", "matrix"],
|
||||
[[47, 57], "a2", "dma-packet"],
|
||||
[[60, 97], "a1", "matrix"],
|
||||
[[116, 129], "a1", "vector"]
|
||||
],
|
||||
|
||||
"sprite-add-frame-data": [[[8, 16], "a0", "dma-packet"]],
|
||||
|
||||
"sprite-add-2d-chunk": [
|
||||
[[12, 20], "a0", "dma-packet"],
|
||||
[[45, 52], "a0", "dma-packet"],
|
||||
[[69, 76], "a0", "dma-packet"],
|
||||
[[80, 87], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"sprite-add-3d-chunk": [
|
||||
[[11, 19], "a0", "dma-packet"],
|
||||
[[44, 51], "a0", "dma-packet"],
|
||||
[[68, 75], "a0", "dma-packet"],
|
||||
[[79, 87], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"sprite-add-shadow-chunk": [
|
||||
[[11, 19], "a0", "dma-packet"],
|
||||
[[37, 44], "a0", "dma-packet"],
|
||||
[[49, 77], "a0", "(inline-array vector)"],
|
||||
[[93, 100], "a0", "dma-packet"],
|
||||
[[105, 121], "s1", "adgif-shader"],
|
||||
[[130, 138], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"sprite-draw": [
|
||||
[[33, 37], "a0", "dma-packet"],
|
||||
[[43, 46], "a0", "gs-gif-tag"],
|
||||
[51, "a0", "(pointer gs-test)"],
|
||||
[53, "a0", "(pointer gs-reg64)"],
|
||||
[55, "a0", "(pointer gs-clamp)"],
|
||||
[57, "a0", "(pointer gs-reg64)"],
|
||||
[[78, 87], "a0", "dma-packet"],
|
||||
[[92, 97], "a0", "dma-packet"],
|
||||
[[125, 129], "a0", "dma-packet"],
|
||||
[[143, 146], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"sprite-init-distorter": [
|
||||
[59, "a3", "uint"],
|
||||
[[3, 7], "a2", "dma-packet"],
|
||||
[[13, 16], "a2", "gs-gif-tag"],
|
||||
[21, "a2", "(pointer gs-zbuf)"],
|
||||
[23, "a2", "(pointer gs-reg64)"],
|
||||
[29, "a2", "(pointer gs-tex0)"],
|
||||
[31, "a2", "(pointer gs-reg64)"],
|
||||
[33, "a2", "(pointer gs-tex1)"],
|
||||
[35, "a2", "(pointer gs-reg64)"],
|
||||
[36, "a2", "(pointer gs-miptbp)"],
|
||||
[38, "a2", "(pointer gs-reg64)"],
|
||||
[45, "a2", "(pointer gs-clamp)"],
|
||||
[47, "a2", "(pointer gs-reg64)"],
|
||||
[49, "a2", "(pointer gs-alpha)"],
|
||||
[51, "a2", "(pointer gs-reg64)"],
|
||||
[[62, 67], "a1", "dma-packet"]
|
||||
],
|
||||
|
||||
"sprite-draw-distorters": [
|
||||
[[70, 90], "a0", "vector"],
|
||||
[72, "v1", "vector"],
|
||||
[93, "v1", "vector"],
|
||||
[96, "v1", "vector"],
|
||||
[115, "v1", "(pointer int32)"],
|
||||
[119, "a0", "(pointer int32)"],
|
||||
[124, "v1", "vector"],
|
||||
[154, "v1", "vector"],
|
||||
[[172, 189], "a1", "dma-packet"]
|
||||
],
|
||||
|
||||
"debug-menu-make-from-template": [
|
||||
[[20, 30], "s5", "string"],
|
||||
[[31, 60], "s5", "string"],
|
||||
[[61, 71], "s5", "string"],
|
||||
[[72, 81], "s5", "string"],
|
||||
[[82, 107], "s5", "string"],
|
||||
[[108, 135], "s5", "string"],
|
||||
[[136, 152], "s5", "string"],
|
||||
[[153, 183], "s5", "string"],
|
||||
[[186, 224], "s5", "string"],
|
||||
[[225, 246], "s5", "string"],
|
||||
[[249, 321], "s5", "string"]
|
||||
],
|
||||
|
||||
"debug-menu-item-var-render": [[[94, 98], "v1", "dma-packet"]],
|
||||
|
||||
"generic-add-constants": [[[8, 17], "a0", "dma-packet"]],
|
||||
|
||||
"generic-init-buf": [
|
||||
[[14, 19], "a0", "dma-packet"],
|
||||
[[24, 28], "a0", "gs-gif-tag"],
|
||||
[32, "a0", "(pointer gs-test)"],
|
||||
[34, "a0", "(pointer uint64)"],
|
||||
[34, "a1", "gs-reg"],
|
||||
[35, "a0", "(pointer gs-zbuf)"],
|
||||
[37, "a0", "(pointer uint64)"],
|
||||
[37, "a1", "gs-reg"],
|
||||
[[47, 53], "a0", "dma-packet"],
|
||||
[[56, 62], "v1", "(pointer vif-tag)"],
|
||||
[[62, 66], "v1", "(pointer int32)"]
|
||||
],
|
||||
|
||||
"cam-standard-event-handler": [
|
||||
[[0, 999], "s6", "camera-slave"],
|
||||
[[16, 30], "s5", "state"],
|
||||
[41, "a0", "vector"],
|
||||
[[5, 8], "t9", "(function object)"],
|
||||
[[19, 22], "t9", "(function object)"],
|
||||
[[30, 32], "t9", "(function object)"]
|
||||
],
|
||||
|
||||
"cam-curve-pos": [[[0, 224], "s6", "camera-slave"]],
|
||||
|
||||
"cam-combiner-init": [
|
||||
[[0, 999], "s6", "camera-combiner"],
|
||||
[[28, 33], "t9", "(function object)"]
|
||||
],
|
||||
|
||||
"(anon-function 1 cam-combiner)": [[[0, 999], "s6", "camera-combiner"]],
|
||||
|
||||
"(anon-function 2 cam-combiner)": [
|
||||
[10, "a0", "vector"],
|
||||
[[0, 20], "s6", "camera-slave"],
|
||||
[[20, 231], "s6", "camera-combiner"],
|
||||
[[99, 127], "gp", "camera-slave"],
|
||||
[[187, 231], "gp", "camera-slave"]
|
||||
],
|
||||
|
||||
"cam-start": [
|
||||
[[18, 22], "t9", "(function process object function)"],
|
||||
[[38, 42], "t9", "(function process object function)"]
|
||||
],
|
||||
|
||||
"cam-master-init": [
|
||||
[[0, 999], "s6", "camera-master"],
|
||||
[[111, 115], "t9", "(function cpu-thread function)"],
|
||||
[[139, 145], "t9", "(function cpu-thread function object object)"],
|
||||
[[163, 167], "t9", "(function object)"]
|
||||
],
|
||||
|
||||
"cam-curve-setup": [[[0, 82], "s6", "camera-slave"]],
|
||||
|
||||
"(method 15 tracking-spline)": [
|
||||
[[57, 59], "a2", "vector"],
|
||||
[[57, 59], "a3", "vector"]
|
||||
],
|
||||
|
||||
"(method 16 tracking-spline)": [
|
||||
[[40, 42], "a0", "vector"],
|
||||
[[40, 42], "a1", "vector"]
|
||||
],
|
||||
|
||||
"cam-slave-init-vars": [[[0, 999], "s6", "camera-slave"]],
|
||||
|
||||
"cam-slave-get-vector-with-offset": [[[52, 65], "s3", "vector"]],
|
||||
|
||||
"cam-slave-go": [[[3, 6], "t9", "(function object)"]],
|
||||
|
||||
"cam-slave-init": [
|
||||
[[0, 999], "s6", "camera-slave"],
|
||||
[[47, 50], "t9", "(function object object)"],
|
||||
[[54, 58], "t9", "(function object object)"]
|
||||
],
|
||||
|
||||
"update-mood-village3": [
|
||||
[[236, 245], "s0", "(array float)"],
|
||||
[245, "s0", "(array int8)"],
|
||||
[[246, 297], "s0", "(array float)"],
|
||||
[[297, 309], "s0", "(array uint8)"],
|
||||
[[309, 314], "s0", "matrix"] // TODO - there is no way this is correct lol
|
||||
],
|
||||
|
||||
"update-mood-citadel": [
|
||||
[291, "s5", "(pointer float)"],
|
||||
[298, "s5", "(pointer float)"],
|
||||
[300, "s5", "(pointer float)"],
|
||||
[304, "s5", "(pointer float)"],
|
||||
[307, "s5", "(pointer float)"],
|
||||
[318, "s5", "(pointer float)"]
|
||||
],
|
||||
|
||||
"update-mood-finalboss": [
|
||||
[40, "s4", "(pointer int64)"],
|
||||
[44, "s4", "(pointer int64)"],
|
||||
[174, "s4", "(pointer int64)"],
|
||||
[251, "s4", "(pointer int64)"],
|
||||
[255, "s4", "(pointer int64)"],
|
||||
[347, "s4", "(pointer int64)"]
|
||||
],
|
||||
|
||||
"update-mood-ogre": [
|
||||
[57, "s4", "(pointer float)"],
|
||||
[64, "s4", "(pointer float)"],
|
||||
[90, "s4", "(pointer float)"],
|
||||
[92, "s4", "(pointer float)"],
|
||||
[95, "s4", "(pointer float)"],
|
||||
[98, "s4", "(pointer float)"],
|
||||
[100, "s4", "(pointer float)"],
|
||||
[105, "s4", "(pointer float)"],
|
||||
[144, "s4", "(pointer float)"]
|
||||
],
|
||||
|
||||
"update-mood-snow": [
|
||||
[93, "s5", "vector"],
|
||||
[110, "s5", "vector"]
|
||||
],
|
||||
|
||||
"ocean-trans-add-upload-table": [
|
||||
[44, "a0", "dma-packet"],
|
||||
[46, "a0", "dma-packet"],
|
||||
[51, "a0", "dma-packet"],
|
||||
[[55, 59], "v1", "vector4w"], // TODO - very likely wrong, but it's something that has 4 int32's,
|
||||
[[87, 228], "v1", "(inline-array vector)"],
|
||||
[241, "a0", "dma-packet"],
|
||||
[243, "a0", "dma-packet"],
|
||||
[248, "a0", "dma-packet"]
|
||||
],
|
||||
|
||||
"ocean-trans-add-upload-strip": [
|
||||
[39, "a0", "dma-packet"],
|
||||
[41, "a0", "dma-packet"],
|
||||
[46, "a0", "dma-packet"],
|
||||
[[57, 61], "v1", "vector4w"], // TODO - very likely wrong, but it's something that has 4 int32's,
|
||||
[[64, 147], "v1", "(inline-array vector)"], // TODO - very likely wrong, but it's something that has 4 int32's,
|
||||
[166, "a0", "dma-packet"],
|
||||
[168, "a0", "dma-packet"],
|
||||
[173, "a0", "dma-packet"]
|
||||
],
|
||||
|
||||
"ocean-trans-add-constants": [
|
||||
[7, "a1", "dma-packet"],
|
||||
[9, "a1", "dma-packet"],
|
||||
[14, "a1", "dma-packet"],
|
||||
[[17, 46], "v1", "matrix"]
|
||||
],
|
||||
|
||||
"draw-ocean-transition": [[255, "v1", "ocean-mid-mask"]],
|
||||
|
||||
"(method 42 nav-enemy)": [
|
||||
[[5, 9], "t9", "(function object object)"]
|
||||
],
|
||||
|
||||
@@ -1215,7 +1215,7 @@
|
||||
"sv-48": "page-id",
|
||||
"s0-0": "upload-chunk-idx",
|
||||
"sv-52": "current-dest-chunk",
|
||||
"sv-56": "allow-cached",
|
||||
"sv-56": "need-tex",
|
||||
"gp-0": "total-upload-size",
|
||||
"a0-21": ["dma", "dma-packet"],
|
||||
"a0-23": ["gif", "gs-gif-tag"],
|
||||
@@ -1385,24 +1385,22 @@
|
||||
},
|
||||
|
||||
"display-loop": {
|
||||
"vars": {
|
||||
|
||||
}
|
||||
"vars": {}
|
||||
},
|
||||
|
||||
"adgif-shader-login": {
|
||||
"args":"shader",
|
||||
"args": "shader",
|
||||
"vars": {
|
||||
"s5-0":"tex"
|
||||
"s5-0": "tex"
|
||||
}
|
||||
},
|
||||
|
||||
"adgif-shader-login-fast": {
|
||||
"args":["shader"],
|
||||
"vars":{
|
||||
"v1-4":"tex-id",
|
||||
"a0-9":"dir-entry",
|
||||
"s5-0":"tex"
|
||||
"args": ["shader"],
|
||||
"vars": {
|
||||
"v1-4": "tex-id",
|
||||
"a0-9": "dir-entry",
|
||||
"s5-0": "tex"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1713,6 +1711,16 @@
|
||||
}
|
||||
},
|
||||
|
||||
"(method 20 actor-link-info)": {
|
||||
"args": ["obj", "message"],
|
||||
"vars": {
|
||||
"s4-0": "iter",
|
||||
"s5-0": "result",
|
||||
"a0-1": "proc",
|
||||
"a1-1": "msg-block"
|
||||
}
|
||||
},
|
||||
|
||||
// LEVEL
|
||||
"lookup-level-info": {
|
||||
"args": ["name"],
|
||||
@@ -1800,7 +1808,28 @@
|
||||
},
|
||||
"(method 15 res-lump)": {
|
||||
"vars": {
|
||||
"s5-0": ["tag-pair", "res-tag-pair"]
|
||||
"s5-0": ["tag-pair", "res-tag-pair"],
|
||||
"s2-0": "existing-tag",
|
||||
"s3-0": "data-size",
|
||||
"v1-25": "resource-mem"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 17 res-lump)": {
|
||||
"vars": {
|
||||
"a0-2": "new-tag",
|
||||
"s4-0": "tag-mem"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 8 res-lump)": {
|
||||
"args": ["obj", "block", "flags"],
|
||||
"vars": {
|
||||
"s3-0": "mem-use-id",
|
||||
"s2-0": "mem-use-name",
|
||||
"v1-22": "obj-size",
|
||||
"s1-0": "tag-idx",
|
||||
"s0-0": "tag-data"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1820,8 +1849,7 @@
|
||||
"vars": {
|
||||
"gp-0": ["obj", "fact-info"],
|
||||
"s5-0": "ent",
|
||||
"sv-16": "tag",
|
||||
"t9-1": ["go-func", "(function string none)"]
|
||||
"sv-16": "tag"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1963,8 +1991,7 @@
|
||||
"vars": {
|
||||
"s1-0": "proc-drawable",
|
||||
"s3-1": ["enemy-facts", "fact-info-enemy"],
|
||||
"f30-0": "dist",
|
||||
"v1-12": ["ppointer", "(pointer process)"]
|
||||
"f30-0": "dist"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2135,6 +2162,7 @@
|
||||
},
|
||||
|
||||
"add-debug-point": {
|
||||
"args": ["enable-draw", "bucket", "pt"],
|
||||
"vars": {
|
||||
"a0-6": ["a0-6", "(pointer uint64)"],
|
||||
"a0-7": ["a0-7", "dma-packet"],
|
||||
@@ -2143,7 +2171,8 @@
|
||||
"a3-4": ["a3-4", "vector4w-2"],
|
||||
"a3-6": ["a3-6", "vector4w-2"],
|
||||
"a3-8": ["a3-8", "vector4w-2"],
|
||||
"a1-30": ["a1-30", "vector4w-2"]
|
||||
"a1-30": ["a1-30", "vector4w-2"],
|
||||
"v1-7": "buf"
|
||||
}
|
||||
},
|
||||
"internal-draw-debug-line": {
|
||||
@@ -2195,7 +2224,9 @@
|
||||
|
||||
"generic-init-buffers": {
|
||||
"vars": {
|
||||
"v1-8": ["packet", "dma-packet"]
|
||||
"v1-8": ["packet", "dma-packet"],
|
||||
"gp-0": ["gp-0", "gs-zbuf"],
|
||||
"s5-0": ["s5-0", "gs-zbuf"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2317,5 +2348,696 @@
|
||||
"vars": {
|
||||
"v0-0": ["ret-val", "symbol"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"letterbox": {
|
||||
"vars": {
|
||||
"s5-0": "dma-buf",
|
||||
"v1-5": ["pkt", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"blackout": {
|
||||
"vars": {
|
||||
"s5-0": "dma-buf",
|
||||
"gp-0": "sprite-dma-data",
|
||||
"v1-4": ["pkt", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"set-master-mode": {
|
||||
"args": ["new-mode"],
|
||||
"vars": { "v1-3": "mode" }
|
||||
},
|
||||
|
||||
"main-cheats": {
|
||||
"vars": {
|
||||
"v1-13": "cheatmode-state",
|
||||
"v1-158": "cheatmode-debug-state",
|
||||
"v1-303": "cheat-language-state",
|
||||
"v1-394": "cheat-pal-state",
|
||||
"s5-9": "dma-buff",
|
||||
"gp-9": "dma-start",
|
||||
"v1-533": ["dma-pkt", "dma-packet"],
|
||||
"gp-10": "timeout",
|
||||
"v1-548": "inactive-timeout",
|
||||
"gp-11": "game-end-proc"
|
||||
}
|
||||
},
|
||||
|
||||
"load-game-text-info": {
|
||||
"args": ["txt-name", "curr-text", "heap"],
|
||||
"vars": {
|
||||
"sv-16": "heap-sym-heap",
|
||||
"sv-24": "lang",
|
||||
"sv-32": "load-status",
|
||||
"sv-40": "heap-free"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 13 art-group)": {
|
||||
"vars": {
|
||||
"s3-0": "art-elt",
|
||||
"s4-0": "janim",
|
||||
"v1-9": "janim-group",
|
||||
"s2-0": "success"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 14 art-group)": {
|
||||
"vars": {
|
||||
"s3-0": "art-elt",
|
||||
"s4-0": "janim",
|
||||
"v1-9": "janim-group",
|
||||
"s3-1": "success"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 16 process-drawable)": {
|
||||
"vars": {
|
||||
"s3-0": "body-T-world",
|
||||
"s0-0": "world-T-body",
|
||||
"s2-0": "grav-rt-body",
|
||||
"a1-5": "vel-rt-body"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 11 cam-float-seeker)": {
|
||||
"args": ["obj", "offset"],
|
||||
"vars": {
|
||||
"f1-2": "pos-error",
|
||||
"f0-5": "partial-velocity-limit",
|
||||
"f1-3": "daccel",
|
||||
"f1-6": "abs-vel",
|
||||
"f0-6": "abs-vel-limit",
|
||||
"f0-10": "dpos"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 9 trsqv)": {
|
||||
"args": ["obj", "dir", "vel", "frame-count"],
|
||||
"vars": {
|
||||
"f0-0": "yaw-error",
|
||||
"f1-2": "yaw-limit",
|
||||
"f30-0": "saturated-yaw",
|
||||
"a1-2": "quat",
|
||||
"f0-2": "old-diff"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 13 trsqv)": {
|
||||
"args": ["obj", "yaw", "vel", "frame-count"]
|
||||
},
|
||||
|
||||
"(method 16 trsqv)": {
|
||||
"vars": {
|
||||
"s5-0": "quat",
|
||||
"s1-0": "grav",
|
||||
"s3-0": "rot-mat",
|
||||
"s4-0": "dir-z",
|
||||
"a0-4": "dir-x"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 25 trsqv)": {
|
||||
"vars": {
|
||||
"s5-0": "quat",
|
||||
"gp-0": "dir-z",
|
||||
"s5-1": "dir-y",
|
||||
"a1-2": "dir-grav",
|
||||
"v1-2": "grav-z-plane",
|
||||
"f0-1": "grav-dot"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 17 trsqv)": {
|
||||
"args": ["obj", "target", "y-rate", "z-rate"],
|
||||
"vars": {
|
||||
"gp-0": "quat",
|
||||
"s5-0": "temp-quat"
|
||||
}
|
||||
},
|
||||
|
||||
"raw-ray-sphere-intersect": {
|
||||
"vars": {
|
||||
"v0-0": ["result", "float"],
|
||||
"v1-0": ["v1-0", "float"]
|
||||
}
|
||||
},
|
||||
|
||||
"ray-sphere-intersect": {
|
||||
"args": ["ray-origin", "ray-dir", "sph-origin", "radius"]
|
||||
},
|
||||
|
||||
"ray-circle-intersect": {
|
||||
"args": ["ray-origin", "ray-dir", "circle-origin", "radius"]
|
||||
},
|
||||
|
||||
"ray-cylinder-intersect": {
|
||||
"args": [
|
||||
"ray-origin",
|
||||
"ray-dir",
|
||||
"cyl-origin",
|
||||
"cyl-axis",
|
||||
"cyl-rad",
|
||||
"cyl-len"
|
||||
]
|
||||
},
|
||||
|
||||
"(method 10 cylinder)": {
|
||||
"args": ["obj", "probe-origin", "probe-dir"],
|
||||
"vars": {
|
||||
"f30-0": "result",
|
||||
"f0-5": "u-origin-sph",
|
||||
"s4-0": "end-pt",
|
||||
"f0-8": "u-end-sphere"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 10 cylinder-flat)": {
|
||||
"args": ["obj", "probe-origin", "probe-dir"],
|
||||
"vars": {
|
||||
"f30-0": "result",
|
||||
"f0-5": "u-origin-circle",
|
||||
"s5-0": "end-pt",
|
||||
"f0-8": "u-end-circle"
|
||||
}
|
||||
},
|
||||
|
||||
"ray-arbitrary-circle-intersect": {
|
||||
"args": [
|
||||
"probe-origin",
|
||||
"probe-dir",
|
||||
"circle-origin",
|
||||
"circle-normal",
|
||||
"radius"
|
||||
]
|
||||
},
|
||||
|
||||
"print-tr-stat": {
|
||||
"args": ["stat", "name", "dest"]
|
||||
},
|
||||
|
||||
"update-subdivide-settings!": {
|
||||
"args": ["settings", "math-cam", "idx"]
|
||||
},
|
||||
|
||||
"start-perf-stat-collection": {
|
||||
"vars": {
|
||||
"v1-2": "frame-idx",
|
||||
"v1-5": "bucket",
|
||||
"a0-2": "which-stat",
|
||||
"a0-7": "stat-idx"
|
||||
}
|
||||
},
|
||||
|
||||
"ja-play-spooled-anim": {
|
||||
"vars": {
|
||||
"sv-16": "spool-part",
|
||||
"sv-28": "old-skel-status",
|
||||
"sv-64": "spool-sound"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 3 anim-tester)": {
|
||||
"vars": {
|
||||
"s5-0": ["s5-0", "anim-test-obj"],
|
||||
"s4-0": ["s4-0", "anim-test-sequence"],
|
||||
"s3-0": ["s3-0", "anim-test-seq-item"]
|
||||
}
|
||||
},
|
||||
|
||||
"anim-test-obj-item-valid?": {
|
||||
"vars": {
|
||||
"s5-0": ["s5-0", "anim-test-sequence"]
|
||||
}
|
||||
},
|
||||
|
||||
"anim-test-obj-remove-invalid": {
|
||||
"vars": {
|
||||
//"s5-0": ["s5-0", "anim-test-sequence"],
|
||||
"v1-31": ["v1-31", "anim-test-sequence"],
|
||||
"s3-0": ["s3-0", "anim-test-seq-item"],
|
||||
"s2-0": ["s2-0", "anim-test-seq-item"]
|
||||
}
|
||||
},
|
||||
|
||||
"anim-tester-reset": {
|
||||
"vars": {
|
||||
"v1-1": ["v1-1", "anim-test-obj"]
|
||||
}
|
||||
},
|
||||
|
||||
"anim-tester-save-object-seqs": {
|
||||
"vars": {
|
||||
"s4-2": ["s4-2", "anim-test-seq-item"]
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-setup-header": {
|
||||
"args": ["hdr", "num-sprites"]
|
||||
},
|
||||
|
||||
"(method 0 sprite-aux-list)": {
|
||||
"args": ["allocation", "type-to-make", "size"]
|
||||
},
|
||||
|
||||
"sprite-setup-frame-data": {
|
||||
"args": ["data", "tbp-offset"]
|
||||
},
|
||||
|
||||
"(method 0 sprite-array-2d)": {
|
||||
"args": ["allocation", "type-to-make", "group-0-size", "group-1-size"],
|
||||
"vars": {
|
||||
"v1-0": "sprite-count",
|
||||
"s4-0": "vec-data-size",
|
||||
"a2-3": "adgif-data-size"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 0 sprite-array-3d)": {
|
||||
"args": ["allocation", "type-to-make", "group-0-size", "group-1-size"],
|
||||
"vars": {
|
||||
"v1-0": "sprite-count",
|
||||
"s4-0": "vec-data-size",
|
||||
"a2-3": "adgif-data-size"
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-set-3d-quaternion": {
|
||||
"args": ["data", "quat"]
|
||||
},
|
||||
"sprite-get-3d-quaternion": {
|
||||
"args": ["data", "quat"]
|
||||
},
|
||||
"sprite-add-matrix-data": {
|
||||
"args": ["dma-buff", "matrix-mode"],
|
||||
"vars": {
|
||||
"v1-0": "count",
|
||||
"a2-1": ["pkt1", "dma-packet"],
|
||||
"a1-2": ["mtx", "matrix"],
|
||||
"a2-9": ["pkt2", "dma-packet"],
|
||||
"a1-11": "mtx2",
|
||||
"a1-20": "hvdf-idx"
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-frame-data": {
|
||||
"args": ["dma-buff", "tbp-offset"],
|
||||
"vars": {
|
||||
"a0-1": ["pkt", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-2d-chunk": {
|
||||
"args": [
|
||||
"sprites",
|
||||
"start-sprite-idx",
|
||||
"num-sprites",
|
||||
"dma-buff",
|
||||
"mscal-addr"
|
||||
],
|
||||
"vars": {
|
||||
"a0-1": ["pkt1", "dma-packet"],
|
||||
"s1-0": "qwc-pkt1",
|
||||
"a1-7": "qwc-pkt2",
|
||||
"a0-5": ["pkt2", "dma-packet"],
|
||||
"a1-11": "qwc-pkt3",
|
||||
"a0-7": ["pkt3", "dma-packet"],
|
||||
"v1-7": ["pkt4", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-2d-all": {
|
||||
"args": ["sprites", "dma-buff", "group-idx"],
|
||||
"vars": {
|
||||
"s4-0": "current-sprite-idx",
|
||||
"s2-0": "remaining-sprites",
|
||||
"s3-0": "mscal-addr"
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-3d-chunk": {
|
||||
"args": ["sprites", "start-sprite-idx", "num-sprites", "dma-buff"],
|
||||
"vars": {
|
||||
"a0-1": ["pkt1", "dma-packet"],
|
||||
"s2-0": "qwc-pkt1",
|
||||
"a1-7": "qwc-pkt2",
|
||||
"a0-5": ["pkt2", "dma-packet"],
|
||||
"a1-11": "qwc-pkt3",
|
||||
"a0-7": ["pkt3", "dma-packet"],
|
||||
"v1-7": ["pkt4", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-3d-all": {
|
||||
"args": ["sprites", "dma-buff", "group-idx"],
|
||||
"vars": {
|
||||
"s4-0": "current-sprite-idx",
|
||||
"s3-0": "remaining-sprites"
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-shadow-chunk": {
|
||||
"args": ["shadow-buff", "start-idx", "num-sprites", "dma-buff"],
|
||||
"vars": {
|
||||
"s2-0": "qwc-pkt1",
|
||||
"a0-1": ["pkt1", "dma-packet"],
|
||||
"a1-7": "qwc-pkt2",
|
||||
"a0-5": ["pkt2", "dma-packet"],
|
||||
"v1-5": "sprite-idx",
|
||||
"a0-7": "dma-vec-data",
|
||||
"a1-14": "in-vec-data",
|
||||
"a1-15": "qwc-pkt3",
|
||||
"a0-11": ["pkt3", "dma-packet"],
|
||||
"s2-1": "si",
|
||||
"s1-0": "dma-adgif-data",
|
||||
"s0-0": "in-adgif-data",
|
||||
"v1-21": ["pkt4", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-add-shadow-all": {
|
||||
"args": ["shadow-buff", "dma-buff"],
|
||||
"vars": {
|
||||
"s4-0": "current-shadow",
|
||||
"s3-0": "remaining-shadows"
|
||||
}
|
||||
},
|
||||
|
||||
"sprite-draw": {
|
||||
"args": "disp",
|
||||
"vars": {
|
||||
"gp-0": "dma-mem-begin",
|
||||
"s4-0": "dma-buff",
|
||||
"s5-0": "dma-bucket-begin",
|
||||
"a0-9": ["pkt1", "dma-packet"],
|
||||
"a0-11": ["giftag", "gs-gif-tag"],
|
||||
"a0-17": ["pkt2", "dma-packet"],
|
||||
"a0-19": ["pkt3", "dma-packet"],
|
||||
"a0-26": ["pkt4", "dma-packet"],
|
||||
"v1-26": ["pkt5", "dma-packet"],
|
||||
"v1-31": "mem-use"
|
||||
}
|
||||
},
|
||||
|
||||
"mem-usage-bsp-tree": {
|
||||
"args": ["header", "node", "mem-use", "flags"]
|
||||
},
|
||||
|
||||
"(method 8 bsp-header)": {
|
||||
"args": ["obj", "mem-use", "flags"]
|
||||
},
|
||||
|
||||
"(method 10 bsp-header)": {
|
||||
"args": ["obj", "other-draw", "disp-frame"],
|
||||
"vars": {
|
||||
"s4-0": "lev",
|
||||
"a2-3": "vis-list-qwc",
|
||||
"v1-15": "vis-list-qwc2",
|
||||
"a0-9": ["vis-list-spad", "(pointer uint128)"],
|
||||
"a1-5": ["vis-list-lev", "(pointer uint128)"],
|
||||
"a2-4": "current-qw"
|
||||
}
|
||||
},
|
||||
|
||||
"bsp-camera-asm": {
|
||||
"args": ["bsp-hdr", "camera-pos"],
|
||||
"vars": {
|
||||
"v1-0": ["next-node", "bsp-node"],
|
||||
"a1-1": "real-node"
|
||||
}
|
||||
},
|
||||
|
||||
"level-remap-texture": {
|
||||
"args": ["tex-id"],
|
||||
"vars": {
|
||||
"v1-1": "bsp-hdr",
|
||||
"a3-0": "table-size",
|
||||
"v1-2": ["table-data-start", "(pointer uint64)"],
|
||||
"t0-0": "table-data-ptr",
|
||||
"a1-1": "mask1",
|
||||
"a2-1": "masked-tex-id",
|
||||
"a3-2": "table-data-end",
|
||||
"t0-3": "midpoint",
|
||||
"t1-1": "diff"
|
||||
}
|
||||
},
|
||||
|
||||
"debug-menu-make-from-template": {
|
||||
"vars": {
|
||||
"s5-1": ["s5-1", "string"]
|
||||
}
|
||||
},
|
||||
|
||||
"debug-menu-item-var-render": {
|
||||
"vars": {
|
||||
"v1-14": ["v1-14", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"generic-add-constants": {
|
||||
"vars": {
|
||||
"a0-1": ["a0-1", "dma-packet"]
|
||||
}
|
||||
},
|
||||
|
||||
"generic-init-buf": {
|
||||
"vars": {
|
||||
"a0-2": ["a0-2", "dma-packet"],
|
||||
"a0-4": ["a0-4", "gs-gif-tag"],
|
||||
"a0-9": ["a0-9", "dma-packet"],
|
||||
"v1-7": ["v1-7", "(pointer int32)"]
|
||||
}
|
||||
},
|
||||
|
||||
"(anon-function 1 cam-combiner)": {
|
||||
"vars": {
|
||||
"pp": ["pp", "process"]
|
||||
}
|
||||
},
|
||||
|
||||
"(anon-function 2 cam-combiner)": {
|
||||
"vars": {
|
||||
"a0-3": ["vec", "(pointer vector)"]
|
||||
}
|
||||
},
|
||||
|
||||
"(method 14 sync-info)": {
|
||||
"args": ["obj", "period", "phase"],
|
||||
"vars": {
|
||||
"f0-1": "period-float",
|
||||
"f1-1": "value"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 14 sync-info-eased)": {
|
||||
"args": ["obj", "period", "phase", "out-param", "in-param"],
|
||||
"vars": {
|
||||
"f0-9": "total-easing-phase",
|
||||
"f1-11": "total-normal-phase",
|
||||
"f0-1": "period-float",
|
||||
"f1-1": "value",
|
||||
"f3-4": "y-end"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 14 sync-info-paused)": {
|
||||
"args": ["obj", "period", "phase", "out-param", "in-param"]
|
||||
},
|
||||
|
||||
"(method 15 sync-info)": {
|
||||
"args": [
|
||||
"obj",
|
||||
"proc",
|
||||
"default-period",
|
||||
"default-phase",
|
||||
"default-out",
|
||||
"default-in"
|
||||
]
|
||||
},
|
||||
|
||||
"(method 15 sync-info-eased)": {
|
||||
"args": [
|
||||
"obj",
|
||||
"proc",
|
||||
"default-period",
|
||||
"default-phase",
|
||||
"default-out",
|
||||
"default-in"
|
||||
]
|
||||
},
|
||||
|
||||
"(method 15 sync-info-paused)": {
|
||||
"args": [
|
||||
"obj",
|
||||
"proc",
|
||||
"default-period",
|
||||
"default-phase",
|
||||
"default-out",
|
||||
"default-in"
|
||||
]
|
||||
},
|
||||
|
||||
"(method 10 sync-info)": {
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f0-1": "period-float",
|
||||
"f1-2": "current-time"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 16 sync-info)": {
|
||||
"args": ["obj", "user-time-offset"],
|
||||
"vars": {
|
||||
"a2-0": "period",
|
||||
"f0-1": "period-float",
|
||||
"v1-0": "wrapped-user-offset",
|
||||
"f1-4": "current-time",
|
||||
"f1-6": "current-time-wrapped",
|
||||
"f1-10": "combined-offset",
|
||||
"f0-3": "combined-offset-wrapped"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 11 sync-info)": {
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f0-1": "period-float",
|
||||
"f1-2": "current-time"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 11 sync-info-paused)": {
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f1-0": "period-float",
|
||||
"f0-1": "max-phase",
|
||||
"f2-2": "current-time"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 9 sync-info)": {
|
||||
"args": ["obj", "max-val"],
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f0-1": "period-float",
|
||||
"f1-2": "current-time"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 13 sync-info)": {
|
||||
"args": ["obj"],
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f1-0": "period-float",
|
||||
"f2-2": "current-time",
|
||||
"f0-1": "max-val",
|
||||
"f0-2": "phase-out-of-2"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 13 sync-info-eased)": {
|
||||
"args": ["obj"],
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f1-0": "period-float",
|
||||
"f0-1": "max-val",
|
||||
"f2-2": "current-time",
|
||||
"f0-2": "current-val",
|
||||
"v1-2": "in-mirror?",
|
||||
"f1-4": "tlo",
|
||||
"f0-7": "eased-phase"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 12 sync-info)": {
|
||||
"args": ["obj", "max-out-val"],
|
||||
"vars": {
|
||||
"v1-0": "period",
|
||||
"f1-0": "period-float",
|
||||
"f0-1": "max-val",
|
||||
"f2-2": "current-time",
|
||||
"f0-2": "current-val"
|
||||
}
|
||||
},
|
||||
|
||||
"(method 12 sync-info-eased)": {
|
||||
"args": ["obj", "max-out-val"]
|
||||
},
|
||||
"(method 12 sync-info-paused)": {
|
||||
"args": ["obj", "max-out-val"]
|
||||
},
|
||||
|
||||
"(method 9 delayed-rand-float)": {
|
||||
"args": ["obj", "min-tim", "max-time", "max-times-two"]
|
||||
},
|
||||
|
||||
"(method 10 oscillating-float)": {
|
||||
"args": ["obj", "target-offset"],
|
||||
"vars": { "f0-3": "acc" }
|
||||
},
|
||||
|
||||
"(method 9 oscillating-float)": {
|
||||
"args": ["obj", "init-val", "accel", "max-vel", "damping"]
|
||||
},
|
||||
|
||||
"(method 9 bouncing-float)": {
|
||||
"args": [
|
||||
"obj",
|
||||
"init-val",
|
||||
"max-val",
|
||||
"min-val",
|
||||
"elast",
|
||||
"accel",
|
||||
"max-vel",
|
||||
"damping"
|
||||
]
|
||||
},
|
||||
|
||||
"(method 9 delayed-rand-vector)": {
|
||||
"args": ["obj", "min-time", "max-time", "xz-range", "y-range"]
|
||||
},
|
||||
|
||||
"(method 9 oscillating-vector)": {
|
||||
"args": ["obj", "init-val", "accel", "max-vel", "damping"]
|
||||
},
|
||||
|
||||
"(method 10 oscillating-vector)": {
|
||||
"args": ["obj", "target-offset"],
|
||||
"vars": { "f0-2": "vel" }
|
||||
},
|
||||
|
||||
"(method 9 trajectory)": {
|
||||
"args": ["obj", "time", "result"]
|
||||
},
|
||||
|
||||
"(method 10 trajectory)": {
|
||||
"args": ["obj", "time", "result"]
|
||||
},
|
||||
|
||||
"(method 11 trajectory)": {
|
||||
"args": ["obj", "from", "to", "duration", "grav"],
|
||||
"vars": { "f0-3": "xz-vel" }
|
||||
},
|
||||
|
||||
"(method 12 trajectory)": {
|
||||
"args": ["obj", "from", "to", "xz-vel", "grav"],
|
||||
"vars": { "f0-1": "duration" }
|
||||
},
|
||||
|
||||
"(method 13 trajectory)": {
|
||||
"args": ["obj", "from", "to", "y-vel", "grav"]
|
||||
},
|
||||
|
||||
"(method 15 trajectory)": {
|
||||
"vars":{
|
||||
"s5-0":"prev-pos",
|
||||
"s4-0":"pos",
|
||||
"s3-0":"num-segments",
|
||||
"f0-1":"t-eval"
|
||||
}
|
||||
},
|
||||
|
||||
"aaaaaaaaaaaaaaaaaaaaaaa": {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/BinaryReader.h"
|
||||
#include "common/audio/audio_formats.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
#include "streamed_audio.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
// number of bytes per "audio page" in the VAG directory file.
|
||||
constexpr int AUDIO_PAGE_SIZE = 2048;
|
||||
|
||||
// Swap endian of 32-bit value.
|
||||
uint32_t swap32(uint32_t in) {
|
||||
return ((in << 24) | ((in & 0xff00) << 8) | ((in & 0xff0000) >> 8) | (in >> 24));
|
||||
}
|
||||
|
||||
/*!
|
||||
* A processed version of the VAGDIR file containing a map from 8-char name to location in the
|
||||
* WAD files.
|
||||
*/
|
||||
struct AudioDir {
|
||||
struct Entry {
|
||||
std::string name;
|
||||
s64 start_byte = -1;
|
||||
s64 end_byte = -1;
|
||||
};
|
||||
|
||||
std::vector<Entry> entries;
|
||||
|
||||
void set_file_size(u64 size) {
|
||||
if (!entries.empty()) {
|
||||
entries.back().end_byte = size;
|
||||
}
|
||||
}
|
||||
|
||||
int entry_count() const { return entries.size(); }
|
||||
|
||||
void debug_print() const {
|
||||
for (auto& e : entries) {
|
||||
fmt::print("\"{}\" 0x{:07x} - 0x{:07x}\n", e.name, e.start_byte, e.end_byte);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Read an entry from a WAD and return the binary data.
|
||||
*/
|
||||
std::vector<u8> read_entry(const AudioDir& dir, const std::vector<u8>& data, int entry_idx) {
|
||||
const auto& entry = dir.entries.at(entry_idx);
|
||||
assert(entry.end_byte > 0);
|
||||
return std::vector<u8>(data.begin() + entry.start_byte, data.begin() + entry.end_byte);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Matches the format in file.
|
||||
*/
|
||||
struct VagFileHeader {
|
||||
char magic[4];
|
||||
u32 version;
|
||||
u32 zero;
|
||||
u32 channel_size;
|
||||
u32 sample_rate;
|
||||
u32 z[3];
|
||||
char name[16];
|
||||
|
||||
VagFileHeader swapped_endian() const {
|
||||
VagFileHeader result(*this);
|
||||
result.version = swap32(result.version);
|
||||
result.channel_size = swap32(result.channel_size);
|
||||
result.sample_rate = swap32(result.sample_rate);
|
||||
return result;
|
||||
}
|
||||
|
||||
void debug_print() {
|
||||
char temp_name[17];
|
||||
memcpy(temp_name, name, 16);
|
||||
temp_name[16] = '\0';
|
||||
fmt::print("{}{}{}{} v {} zero {} chan {} samp {} z {} {} {} name {}\n", magic[0], magic[1],
|
||||
magic[2], magic[3], version, zero, channel_size, sample_rate, z[0], z[1], z[2],
|
||||
temp_name);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Read the DIR file into an AudioDir
|
||||
*/
|
||||
AudioDir read_audio_dir(const std::string& path) {
|
||||
// matches the format in file.
|
||||
struct DirEntry {
|
||||
char name[8];
|
||||
u32 value;
|
||||
};
|
||||
auto data = file_util::read_binary_file(path);
|
||||
lg::info("Got {} bytes of audio dir.\n", data.size());
|
||||
auto reader = BinaryReader(data);
|
||||
|
||||
u32 count = reader.read<u32>();
|
||||
u32 data_end = sizeof(u32) + sizeof(DirEntry) * count;
|
||||
assert(data_end <= data.size());
|
||||
std::vector<DirEntry> entries;
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
entries.push_back(reader.read<DirEntry>());
|
||||
}
|
||||
|
||||
while (reader.bytes_left()) {
|
||||
assert(reader.read<u8>() == 0);
|
||||
}
|
||||
|
||||
AudioDir result;
|
||||
|
||||
assert(!entries.empty());
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
AudioDir::Entry e;
|
||||
for (auto c : entries[i].name) {
|
||||
// padded with spaces, no null terminator.
|
||||
e.name.push_back(c);
|
||||
e.start_byte = AUDIO_PAGE_SIZE * entries[i].value;
|
||||
if (i + 1 < (entries.size())) {
|
||||
e.end_byte = AUDIO_PAGE_SIZE * entries[i + 1].value;
|
||||
} else {
|
||||
e.end_byte = -1;
|
||||
}
|
||||
}
|
||||
result.entries.push_back(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string remove_trailing_spaces(const std::string& in) {
|
||||
auto short_name = in;
|
||||
while (!short_name.empty() && short_name.back() == ' ') {
|
||||
short_name.pop_back();
|
||||
}
|
||||
return short_name;
|
||||
}
|
||||
|
||||
struct AudioFileInfo {
|
||||
std::string filename;
|
||||
double length_seconds;
|
||||
};
|
||||
|
||||
AudioFileInfo process_audio_file(const std::vector<u8>& data,
|
||||
const std::string& name,
|
||||
const std::string& suffix) {
|
||||
BinaryReader reader(data);
|
||||
|
||||
auto header = reader.read<VagFileHeader>();
|
||||
if (header.magic[0] == 'V') {
|
||||
header = header.swapped_endian();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
header.debug_print();
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assert(reader.read<u8>() == 0);
|
||||
}
|
||||
|
||||
std::vector<s16> decoded_samples = decode_adpcm(reader);
|
||||
|
||||
while (reader.bytes_left()) {
|
||||
assert(reader.read<u8>() == 0);
|
||||
}
|
||||
|
||||
auto file_name = fmt::format("{}_{}.wav", remove_trailing_spaces(name), suffix);
|
||||
write_wave_file_mono(decoded_samples, header.sample_rate,
|
||||
file_util::get_file_path({"assets", "streaming_audio", file_name}));
|
||||
|
||||
std::string vag_filename;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (header.name[i]) {
|
||||
vag_filename.push_back(header.name[i]);
|
||||
}
|
||||
}
|
||||
return {vag_filename, (double)decoded_samples.size() / header.sample_rate};
|
||||
}
|
||||
|
||||
void process_streamed_audio(const std::string& dir, const std::vector<std::string>& audio_files) {
|
||||
auto dir_file_name = file_util::combine_path(dir, "VAGDIR.AYB");
|
||||
lg::info("Streaming audio: {}\n", dir_file_name);
|
||||
file_util::create_dir_if_needed(file_util::get_file_path({"assets", "streaming_audio"}));
|
||||
auto dir_data = read_audio_dir(file_util::get_file_path({"iso_data", dir_file_name}));
|
||||
double audio_len = 0.f;
|
||||
|
||||
std::vector<std::string> langs;
|
||||
std::vector<std::vector<std::string>> filename_data;
|
||||
for (auto& e : dir_data.entries) {
|
||||
std::vector<std::string> placeholders = {remove_trailing_spaces(e.name)};
|
||||
for (size_t i = 0; i < audio_files.size(); i++) {
|
||||
placeholders.push_back("????");
|
||||
}
|
||||
filename_data.push_back(placeholders);
|
||||
}
|
||||
|
||||
for (size_t lang_id = 0; lang_id < audio_files.size(); lang_id++) {
|
||||
auto& file = audio_files[lang_id];
|
||||
auto wad_data = file_util::read_binary_file(file_util::get_file_path({"iso_data", dir, file}));
|
||||
auto suffix = std::filesystem::path(file).extension().u8string().substr(1);
|
||||
langs.push_back(suffix);
|
||||
dir_data.set_file_size(wad_data.size());
|
||||
for (int i = 3; i < dir_data.entry_count(); i++) {
|
||||
auto audio_data = read_entry(dir_data, wad_data, i);
|
||||
lg::info("File {}, total {:.2f} minutes", dir_data.entries.at(i).name, audio_len / 60.0);
|
||||
auto info = process_audio_file(audio_data, dir_data.entries.at(i).name, suffix);
|
||||
audio_len += info.length_seconds;
|
||||
filename_data[i][lang_id + 1] = info.filename;
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json file_list;
|
||||
file_list["names"] = filename_data;
|
||||
file_list["languages"] = langs;
|
||||
|
||||
file_util::write_text_file(
|
||||
file_util::get_file_path({"assets", "streaming_audio", "file_list.txt"}), file_list.dump(2));
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace decompiler {
|
||||
void process_streamed_audio(const std::string& dir, const std::vector<std::string>& audio_files);
|
||||
}
|
||||
+14
-3
@@ -6,6 +6,7 @@
|
||||
#include "config.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/versions.h"
|
||||
#include "decompiler/data/streamed_audio.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using namespace decompiler;
|
||||
@@ -100,17 +101,27 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (config.process_game_text) {
|
||||
auto result = db.process_game_text_files();
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "game_text.txt"}), result);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "game_text.txt"}), result);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.process_tpages) {
|
||||
auto result = db.process_tpages();
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "tpage-dir.txt"}), result);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "tpage-dir.txt"}), result);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.process_game_count) {
|
||||
auto result = db.process_game_count_file();
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "game_count.txt"}), result);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(file_util::get_file_path({"assets", "game_count.txt"}), result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.audio_dir_file_name.empty()) {
|
||||
process_streamed_audio(config.audio_dir_file_name, config.streamed_audio_file_names);
|
||||
}
|
||||
|
||||
lg::info("Disassembly has completed successfully.");
|
||||
|
||||
@@ -379,6 +379,13 @@ bool DecompilerTypeSystem::tp_lca(TypeState* combined, const TypeState& add) {
|
||||
}
|
||||
}
|
||||
|
||||
bool diff = false;
|
||||
auto new_type = tp_lca(combined->next_state_type, add.next_state_type, &diff);
|
||||
if (diff) {
|
||||
result = true;
|
||||
combined->next_state_type = new_type;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -407,6 +414,11 @@ int DecompilerTypeSystem::get_format_arg_count(const std::string& str) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ~0k
|
||||
if (i + 1 < str.length() && (str.at(i) == '0') && str.at(i + 1) == 'k') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ~2j
|
||||
if (i + 1 < str.length() && (str.at(i) == '2') && str.at(i + 1) == 'j') {
|
||||
continue;
|
||||
@@ -434,4 +446,21 @@ TypeSpec DecompilerTypeSystem::lookup_symbol_type(const std::string& name) const
|
||||
return kv->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool DecompilerTypeSystem::should_attempt_cast_simplify(const TypeSpec& expected,
|
||||
const TypeSpec& actual) const {
|
||||
if (expected == TypeSpec("meters") && actual == TypeSpec("float")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expected == TypeSpec("seconds") && actual == TypeSpec("uint64")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expected == TypeSpec("degrees") && actual == TypeSpec("float")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !ts.tc(expected, actual);
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace decompiler {
|
||||
class TP_Type;
|
||||
struct TypeState;
|
||||
class TypeState;
|
||||
|
||||
class DecompilerTypeSystem {
|
||||
public:
|
||||
@@ -43,6 +43,7 @@ class DecompilerTypeSystem {
|
||||
int get_format_arg_count(const std::string& str) const;
|
||||
int get_format_arg_count(const TP_Type& type) const;
|
||||
TypeSpec lookup_symbol_type(const std::string& name) const;
|
||||
bool should_attempt_cast_simplify(const TypeSpec& expected, const TypeSpec& actual) const;
|
||||
|
||||
// todo - totally eliminate this.
|
||||
struct {
|
||||
|
||||
@@ -67,8 +67,12 @@ std::string TP_Type::print() const {
|
||||
}
|
||||
case Kind::PCPYUD_BITFIELD:
|
||||
return fmt::format("<pcpyud {}>", m_ts.print());
|
||||
case Kind::PCPYUD_BITFIELD_AND:
|
||||
return fmt::format("<pcpyud-and {}>", m_ts.print());
|
||||
case Kind::LABEL_ADDR:
|
||||
return "<label-addr>";
|
||||
case Kind::ENTER_STATE_FUNCTION:
|
||||
return "<enter-state-func>";
|
||||
case Kind::INVALID:
|
||||
default:
|
||||
assert(false);
|
||||
@@ -119,7 +123,10 @@ bool TP_Type::operator==(const TP_Type& other) const {
|
||||
return m_int == other.m_int && m_ts == other.m_ts && m_pcpyud == other.m_pcpyud;
|
||||
case Kind::PCPYUD_BITFIELD:
|
||||
return m_pcpyud == other.m_pcpyud && m_ts == other.m_ts;
|
||||
case Kind::PCPYUD_BITFIELD_AND:
|
||||
return m_pcpyud == other.m_pcpyud && m_ts == other.m_ts;
|
||||
case Kind::LABEL_ADDR:
|
||||
case Kind::ENTER_STATE_FUNCTION:
|
||||
return true;
|
||||
case Kind::INVALID:
|
||||
default:
|
||||
@@ -177,8 +184,13 @@ TypeSpec TP_Type::typespec() const {
|
||||
return TypeSpec("int"); // ideally this is never used.
|
||||
case Kind::PCPYUD_BITFIELD:
|
||||
return TypeSpec("int");
|
||||
case Kind::PCPYUD_BITFIELD_AND:
|
||||
return TypeSpec("int");
|
||||
case Kind::LABEL_ADDR:
|
||||
return TypeSpec("pointer"); // ?
|
||||
case Kind::ENTER_STATE_FUNCTION:
|
||||
// give a general function so we can't call it normally.
|
||||
return TypeSpec("function");
|
||||
case Kind::INVALID:
|
||||
default:
|
||||
assert(false);
|
||||
|
||||
@@ -33,8 +33,10 @@ class TP_Type {
|
||||
VIRTUAL_METHOD,
|
||||
NON_VIRTUAL_METHOD,
|
||||
PCPYUD_BITFIELD,
|
||||
PCPYUD_BITFIELD_AND,
|
||||
LEFT_SHIFTED_BITFIELD, // (bitfield << some-constant)
|
||||
LABEL_ADDR,
|
||||
ENTER_STATE_FUNCTION,
|
||||
INVALID
|
||||
} kind = Kind::UNINITIALIZED;
|
||||
TP_Type() = default;
|
||||
@@ -62,7 +64,9 @@ class TP_Type {
|
||||
case Kind::NON_VIRTUAL_METHOD:
|
||||
case Kind::LEFT_SHIFTED_BITFIELD:
|
||||
case Kind::PCPYUD_BITFIELD:
|
||||
case Kind::PCPYUD_BITFIELD_AND:
|
||||
case Kind::LABEL_ADDR:
|
||||
case Kind::ENTER_STATE_FUNCTION:
|
||||
return false;
|
||||
case Kind::UNINITIALIZED:
|
||||
case Kind::OBJECT_NEW_METHOD:
|
||||
@@ -244,6 +248,20 @@ class TP_Type {
|
||||
return result;
|
||||
}
|
||||
|
||||
static TP_Type make_from_pcpyud_and_bitfield(const TypeSpec& ts) {
|
||||
TP_Type result;
|
||||
result.kind = Kind::PCPYUD_BITFIELD_AND;
|
||||
result.m_ts = ts;
|
||||
result.m_pcpyud = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
static TP_Type make_enter_state() {
|
||||
TP_Type result;
|
||||
result.kind = Kind::ENTER_STATE_FUNCTION;
|
||||
return result;
|
||||
}
|
||||
|
||||
static TP_Type make_label_addr() {
|
||||
TP_Type result;
|
||||
result.kind = Kind::LABEL_ADDR;
|
||||
@@ -296,7 +314,8 @@ class TP_Type {
|
||||
}
|
||||
|
||||
const TypeSpec& get_bitfield_type() const {
|
||||
assert(kind == Kind::LEFT_SHIFTED_BITFIELD || kind == Kind::PCPYUD_BITFIELD);
|
||||
assert(kind == Kind::LEFT_SHIFTED_BITFIELD || kind == Kind::PCPYUD_BITFIELD ||
|
||||
kind == Kind::PCPYUD_BITFIELD_AND);
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
@@ -335,11 +354,13 @@ class TP_Type {
|
||||
int64_t m_extra_multiplier = 0;
|
||||
};
|
||||
|
||||
struct TypeState {
|
||||
class TypeState {
|
||||
private:
|
||||
public:
|
||||
std::unordered_map<int, TP_Type> spill_slots;
|
||||
TP_Type gpr_types[32];
|
||||
TP_Type fpr_types[32];
|
||||
std::unordered_map<int, TP_Type> spill_slots;
|
||||
|
||||
TP_Type next_state_type;
|
||||
std::string print_gpr_masked(u32 mask) const;
|
||||
TP_Type& get(const Register& r) {
|
||||
switch (r.get_kind()) {
|
||||
|
||||
@@ -275,6 +275,150 @@ std::string print_def(const goos::Object& obj) {
|
||||
}
|
||||
return obj.print();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start at start_byte, and find the location of the next label.
|
||||
* Will only check labels that are in the given segment.
|
||||
*/
|
||||
int index_of_closest_following_label_in_segment(int start_byte,
|
||||
int seg,
|
||||
const std::vector<DecompilerLabel>& labels) {
|
||||
int result_idx = -1;
|
||||
int closest_byte = -1;
|
||||
for (int i = 0; i < (int)labels.size(); i++) {
|
||||
const auto& label = labels.at(i);
|
||||
if (label.target_segment == seg) {
|
||||
if (result_idx == -1) {
|
||||
result_idx = i;
|
||||
closest_byte = label.offset;
|
||||
} else {
|
||||
if (label.offset > start_byte && label.offset < closest_byte) {
|
||||
result_idx = i;
|
||||
closest_byte = label.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result_idx;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Attempt to decompile a reference to an inline array, without knowing the size.
|
||||
*/
|
||||
goos::Object decomp_ref_to_inline_array_guess_size(
|
||||
const std::vector<LinkedWord>& words,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
int my_seg,
|
||||
int field_location,
|
||||
const TypeSystem& ts,
|
||||
const Field& data_field,
|
||||
const std::vector<std::vector<LinkedWord>>& all_words,
|
||||
const LinkedObjectFile* file,
|
||||
const TypeSpec& array_elt_type,
|
||||
int stride) {
|
||||
fmt::print("Decomp decomp_ref_to_inline_array_guess_size {}\n", array_elt_type.print());
|
||||
|
||||
// verify that the field is the right type.
|
||||
assert(data_field.type() == TypeSpec("inline-array", {array_elt_type}));
|
||||
|
||||
// verify the stride matches the type system
|
||||
auto elt_type_info = ts.lookup_type(array_elt_type);
|
||||
assert(stride == align(elt_type_info->get_size_in_memory(),
|
||||
elt_type_info->get_inline_array_stride_alignment()));
|
||||
|
||||
// the input is the location of the data field.
|
||||
// we expect that to be a label:
|
||||
assert((field_location % 4) == 0);
|
||||
auto pointer_to_data = words.at(field_location / 4);
|
||||
assert(pointer_to_data.kind == LinkedWord::PTR);
|
||||
|
||||
// the data shouldn't have any labels in the middle of it, so we can find the end of the array
|
||||
// by searching for the label after the start label.
|
||||
const auto& start_label = labels.at(pointer_to_data.label_id);
|
||||
int end_label_idx =
|
||||
index_of_closest_following_label_in_segment(start_label.offset, my_seg, labels);
|
||||
assert(end_label_idx >= 0);
|
||||
const auto& end_label = labels.at(end_label_idx);
|
||||
fmt::print("Data is from {} to {}\n", start_label.name, end_label.name);
|
||||
|
||||
// now we can figure out the size
|
||||
int size_bytes = end_label.offset - start_label.offset;
|
||||
int size_elts = size_bytes / stride; // 32 bytes per ocean-near-index
|
||||
int leftover_bytes = size_bytes % stride;
|
||||
fmt::print("Size is {} bytes: {} elts, {} left over\n", size_bytes, size_elts, leftover_bytes);
|
||||
|
||||
// if we have leftover, should verify that its all zeros, or that it's the type pointer
|
||||
// of the next basic in the data section.
|
||||
// ex:
|
||||
// .word <data>
|
||||
// .type <some-other-basic's type tag>
|
||||
// L21: ; label some other basic
|
||||
// <other basic's data>
|
||||
int padding_start = end_label.offset - leftover_bytes;
|
||||
int padding_end = end_label.offset;
|
||||
for (int pad_byte_idx = padding_start; pad_byte_idx < padding_end; pad_byte_idx++) {
|
||||
auto& word = all_words.at(my_seg).at(pad_byte_idx / 4);
|
||||
switch (word.kind) {
|
||||
case LinkedWord::PLAIN_DATA:
|
||||
assert(word.get_byte(pad_byte_idx) == 0);
|
||||
break;
|
||||
case LinkedWord::TYPE_PTR:
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// now disassemble:
|
||||
std::vector<goos::Object> array_def = {pretty_print::to_symbol(
|
||||
fmt::format("new 'static 'inline-array {} {}", array_elt_type.print(), size_elts))};
|
||||
|
||||
for (int elt = 0; elt < size_elts; elt++) {
|
||||
// for each element, create a fake temporary label at the start to identify it
|
||||
DecompilerLabel fake_label;
|
||||
fake_label.target_segment = my_seg; // same segment
|
||||
fake_label.offset = start_label.offset + elt * stride;
|
||||
array_def.push_back(
|
||||
decompile_at_label(array_elt_type, fake_label, labels, all_words, ts, file));
|
||||
}
|
||||
|
||||
// build into a list.
|
||||
return pretty_print::build_list(array_def);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Decompile the data field of ocean-near-indices, which is an (inline-array ocean-near-index).
|
||||
* This is like a C++ ocean_near_index*, meaning we don't know how long the array is.
|
||||
* We know all the data in a ocean_near_index is just integers, so we can guess that the end
|
||||
* of the array is just the location of the next label.
|
||||
* There's a chance that this will include some padding in the array and make it too long,
|
||||
* but there is no harm in that.
|
||||
*/
|
||||
goos::Object ocean_near_indices_decompile(const std::vector<LinkedWord>& words,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
int my_seg,
|
||||
int field_location,
|
||||
const TypeSystem& ts,
|
||||
const Field& data_field,
|
||||
const std::vector<std::vector<LinkedWord>>& all_words,
|
||||
const LinkedObjectFile* file) {
|
||||
return decomp_ref_to_inline_array_guess_size(words, labels, my_seg, field_location, ts,
|
||||
data_field, all_words, file,
|
||||
TypeSpec("ocean-near-index"), 32);
|
||||
}
|
||||
|
||||
goos::Object ocean_mid_masks_decompile(const std::vector<LinkedWord>& words,
|
||||
const std::vector<DecompilerLabel>& labels,
|
||||
int my_seg,
|
||||
int field_location,
|
||||
const TypeSystem& ts,
|
||||
const Field& data_field,
|
||||
const std::vector<std::vector<LinkedWord>>& all_words,
|
||||
const LinkedObjectFile* file) {
|
||||
return decomp_ref_to_inline_array_guess_size(words, labels, my_seg, field_location, ts,
|
||||
data_field, all_words, file,
|
||||
TypeSpec("ocean-mid-mask"), 8);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
goos::Object decompile_structure(const TypeSpec& type,
|
||||
@@ -325,11 +469,18 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
|
||||
// check alignment
|
||||
if (offset_location % 8) {
|
||||
throw std::runtime_error(fmt::format(
|
||||
"Tried to decompile a structure with type type {} (type offset {}) at label {}, but it has "
|
||||
"alignment {}, which is not valid. {}",
|
||||
std::string error = fmt::format(
|
||||
"Decompiling a structure with type type {} (type offset {}) at label {}, but it has "
|
||||
"alignment {}, which is not valid. This might be okay for a packed inline array, but "
|
||||
"shouldn't happen for basics. {}",
|
||||
type_info->get_name(), type_info->get_offset(), label.name, (offset_location % 8),
|
||||
(offset_location & 0b10) ? "Maybe it is actually a pair?" : ""));
|
||||
(offset_location & 0b10) ? "Maybe it is actually a pair?" : "");
|
||||
|
||||
if (is_basic || !type_info->is_packed()) {
|
||||
throw std::runtime_error(error);
|
||||
} else {
|
||||
// fmt::print("{}\n", error);
|
||||
}
|
||||
}
|
||||
|
||||
// check enough room
|
||||
@@ -448,11 +599,22 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
fmt::format("Dynamic value field {} in static data type {} not yet implemented",
|
||||
field.name(), actual_type.print()));
|
||||
} else {
|
||||
std::vector<u8> bytes_out;
|
||||
for (int byte_idx = field_start; byte_idx < field_end; byte_idx++) {
|
||||
bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
|
||||
if (field.name() == "data" && type.print() == "ocean-near-indices") {
|
||||
// first, get the label:
|
||||
field_defs_out.emplace_back(
|
||||
field.name(), ocean_near_indices_decompile(obj_words, labels, label.target_segment,
|
||||
field_start, ts, field, words, file));
|
||||
} else if (field.name() == "data" && type.print() == "ocean-mid-masks") {
|
||||
field_defs_out.emplace_back(
|
||||
field.name(), ocean_mid_masks_decompile(obj_words, labels, label.target_segment,
|
||||
field_start, ts, field, words, file));
|
||||
} else {
|
||||
std::vector<u8> bytes_out;
|
||||
for (int byte_idx = field_start; byte_idx < field_end; byte_idx++) {
|
||||
bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
|
||||
}
|
||||
field_defs_out.emplace_back(field.name(), decompile_value(field.type(), bytes_out, ts));
|
||||
}
|
||||
field_defs_out.emplace_back(field.name(), decompile_value(field.type(), bytes_out, ts));
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -695,11 +857,35 @@ goos::Object decompile_value(const TypeSpec& type,
|
||||
} else {
|
||||
return pretty_print::to_symbol(fmt::format("{}", value));
|
||||
}
|
||||
} else if (type == TypeSpec("seconds")) {
|
||||
assert(bytes.size() == 8);
|
||||
u64 value;
|
||||
memcpy(&value, bytes.data(), 8);
|
||||
|
||||
// only rewrite if exact.
|
||||
u64 seconds = value / TICKS_PER_SECOND;
|
||||
if (seconds * TICKS_PER_SECOND == value) {
|
||||
return pretty_print::to_symbol(fmt::format("(seconds {})", seconds));
|
||||
}
|
||||
|
||||
return pretty_print::to_symbol(fmt::format("#x{:x}", value));
|
||||
} else if (ts.tc(TypeSpec("uint64"), type)) {
|
||||
assert(bytes.size() == 8);
|
||||
u64 value;
|
||||
memcpy(&value, bytes.data(), 8);
|
||||
return pretty_print::to_symbol(fmt::format("#x{:x}", value));
|
||||
} else if (type == TypeSpec("meters")) {
|
||||
assert(bytes.size() == 4);
|
||||
float value;
|
||||
memcpy(&value, bytes.data(), 4);
|
||||
double meters = (double)value / METER_LENGTH;
|
||||
return pretty_print::build_list("meters", pretty_print::float_representation(meters));
|
||||
} else if (type == TypeSpec("degrees")) {
|
||||
assert(bytes.size() == 4);
|
||||
float value;
|
||||
memcpy(&value, bytes.data(), 4);
|
||||
double degrees = (double)value / DEGREES_LENGTH;
|
||||
return pretty_print::build_list("degrees", pretty_print::float_representation(degrees));
|
||||
} else if (ts.tc(TypeSpec("float"), type)) {
|
||||
assert(bytes.size() == 4);
|
||||
float value;
|
||||
@@ -997,6 +1183,14 @@ std::optional<std::vector<BitFieldConstantDef>> try_decompile_bitfield_from_int(
|
||||
auto name = decompile_int_enum_from_int(field.type(), ts, bitfield_value);
|
||||
def.enum_constant = fmt::format("({} {})", field.type().print(), name);
|
||||
}
|
||||
|
||||
auto nested_bitfield_type = dynamic_cast<BitFieldType*>(ts.lookup_type(field.type()));
|
||||
if (nested_bitfield_type) {
|
||||
BitFieldConstantDef::NestedField nested;
|
||||
nested.field_type = field.type();
|
||||
nested.fields = *try_decompile_bitfield_from_int(field.type(), ts, bitfield_value, true);
|
||||
def.nested_field = nested;
|
||||
}
|
||||
result.push_back(def);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,13 @@ struct BitFieldConstantDef {
|
||||
u64 value = -1;
|
||||
std::optional<std::string> enum_constant;
|
||||
std::string field_name;
|
||||
|
||||
struct NestedField {
|
||||
TypeSpec field_type;
|
||||
std::vector<BitFieldConstantDef> fields;
|
||||
};
|
||||
|
||||
std::optional<NestedField> nested_field;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"jak1": {
|
||||
"locPercentage": {
|
||||
"value": 103209,
|
||||
"value": 117858,
|
||||
"label": "Lines of Code"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/jak-project/favicon.png"><title>OpenGOAL Tooling</title><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css"><link href="/jak-project/css/about.8d0e9591.css" rel="prefetch"><link href="/jak-project/js/about.c7b7de46.js" rel="prefetch"><link href="/jak-project/css/chunk-vendors.b018c88a.css" rel="preload" as="style"><link href="/jak-project/js/app.5b8d0e0d.js" rel="preload" as="script"><link href="/jak-project/js/chunk-vendors.492c07dc.js" rel="preload" as="script"><link href="/jak-project/css/chunk-vendors.b018c88a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but docs-and-tooling doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/jak-project/js/chunk-vendors.492c07dc.js"></script><script src="/jak-project/js/app.5b8d0e0d.js"></script></body></html>
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/jak-project/favicon.png"><title>OpenGOAL Tooling</title><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css"><link href="/jak-project/css/about.8d0e9591.css" rel="prefetch"><link href="/jak-project/js/about.93743c22.js" rel="prefetch"><link href="/jak-project/css/chunk-vendors.b018c88a.css" rel="preload" as="style"><link href="/jak-project/js/app.1e67702b.js" rel="preload" as="script"><link href="/jak-project/js/chunk-vendors.f27e8f37.js" rel="preload" as="script"><link href="/jak-project/css/chunk-vendors.b018c88a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but docs-and-tooling doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/jak-project/js/chunk-vendors.f27e8f37.js"></script><script src="/jak-project/js/app.1e67702b.js"></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
|
||||
(function(e){function t(t){for(var n,o,i=t[0],c=t[1],l=t[2],s=0,p=[];s<i.length;s++)o=i[s],Object.prototype.hasOwnProperty.call(a,o)&&a[o]&&p.push(a[o][0]),a[o]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);f&&f(t);while(p.length)p.shift()();return u.push.apply(u,l||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,o=1;o<r.length;o++){var i=r[o];0!==a[i]&&(n=!1)}n&&(u.splice(t--,1),e=c(c.s=r[0]))}return e}var n={},o={app:0},a={app:0},u=[];function i(e){return c.p+"js/"+({about:"about"}[e]||e)+"."+{about:"c7b7de46"}[e]+".js"}function c(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,c),r.l=!0,r.exports}c.e=function(e){var t=[],r={about:1};o[e]?t.push(o[e]):0!==o[e]&&r[e]&&t.push(o[e]=new Promise((function(t,r){for(var n="css/"+({about:"about"}[e]||e)+"."+{about:"8d0e9591"}[e]+".css",a=c.p+n,u=document.getElementsByTagName("link"),i=0;i<u.length;i++){var l=u[i],s=l.getAttribute("data-href")||l.getAttribute("href");if("stylesheet"===l.rel&&(s===n||s===a))return t()}var p=document.getElementsByTagName("style");for(i=0;i<p.length;i++){l=p[i],s=l.getAttribute("data-href");if(s===n||s===a)return t()}var f=document.createElement("link");f.rel="stylesheet",f.type="text/css",f.onload=t,f.onerror=function(t){var n=t&&t.target&&t.target.src||a,u=new Error("Loading CSS chunk "+e+" failed.\n("+n+")");u.code="CSS_CHUNK_LOAD_FAILED",u.request=n,delete o[e],f.parentNode.removeChild(f),r(u)},f.href=a;var d=document.getElementsByTagName("head")[0];d.appendChild(f)})).then((function(){o[e]=0})));var n=a[e];if(0!==n)if(n)t.push(n[2]);else{var u=new Promise((function(t,r){n=a[e]=[t,r]}));t.push(n[2]=u);var l,s=document.createElement("script");s.charset="utf-8",s.timeout=120,c.nc&&s.setAttribute("nonce",c.nc),s.src=i(e);var p=new Error;l=function(t){s.onerror=s.onload=null,clearTimeout(f);var r=a[e];if(0!==r){if(r){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;p.message="Loading chunk "+e+" failed.\n("+n+": "+o+")",p.name="ChunkLoadError",p.type=n,p.request=o,r[1](p)}a[e]=void 0}};var f=setTimeout((function(){l({type:"timeout",target:s})}),12e4);s.onerror=s.onload=l,document.head.appendChild(s)}return Promise.all(t)},c.m=e,c.c=n,c.d=function(e,t,r){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},c.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(c.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)c.d(r,n,function(t){return e[t]}.bind(null,n));return r},c.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="/jak-project/",c.oe=function(e){throw console.error(e),e};var l=window["webpackJsonp"]=window["webpackJsonp"]||[],s=l.push.bind(l);l.push=t,l=l.slice();for(var p=0;p<l.length;p++)t(l[p]);var f=s;u.push([0,"chunk-vendors"]),r()})({0:function(e,t,r){e.exports=r("56d7")},"56d7":function(e,t,r){"use strict";r.r(t);r("e260"),r("e6cf"),r("cca6"),r("a79d");var n=r("2b0e"),o=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("v-app",[r("v-main",[r("router-view")],1)],1)},a=[],u={name:"App",components:{},data:function(){return{}}},i=u,c=r("2877"),l=r("6544"),s=r.n(l),p=r("7496"),f=r("f6c4"),d=Object(c["a"])(i,o,a,!1,null,null,null),h=d.exports;s()(d,{VApp:p["a"],VMain:f["a"]});var m=r("f309");n["a"].use(m["a"]);var v=new m["a"]({theme:{dark:!0}}),b=(r("d3b7"),r("3ca3"),r("ddb0"),r("8c4f"));n["a"].use(b["a"]);var g=[{path:"/",name:"Home",component:function(){return r.e("about").then(r.bind(null,"bb51"))}}],y=new b["a"]({mode:"history",base:"/jak-project/",routes:g}),w=y;n["a"].config.productionTip=!1,new n["a"]({vuetify:v,router:w,render:function(e){return e(h)}}).$mount("#app")}});
|
||||
//# sourceMappingURL=app.5b8d0e0d.js.map
|
||||
(function(e){function t(t){for(var n,o,i=t[0],c=t[1],l=t[2],s=0,p=[];s<i.length;s++)o=i[s],Object.prototype.hasOwnProperty.call(a,o)&&a[o]&&p.push(a[o][0]),a[o]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);f&&f(t);while(p.length)p.shift()();return u.push.apply(u,l||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,o=1;o<r.length;o++){var i=r[o];0!==a[i]&&(n=!1)}n&&(u.splice(t--,1),e=c(c.s=r[0]))}return e}var n={},o={app:0},a={app:0},u=[];function i(e){return c.p+"js/"+({about:"about"}[e]||e)+"."+{about:"93743c22"}[e]+".js"}function c(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,c),r.l=!0,r.exports}c.e=function(e){var t=[],r={about:1};o[e]?t.push(o[e]):0!==o[e]&&r[e]&&t.push(o[e]=new Promise((function(t,r){for(var n="css/"+({about:"about"}[e]||e)+"."+{about:"8d0e9591"}[e]+".css",a=c.p+n,u=document.getElementsByTagName("link"),i=0;i<u.length;i++){var l=u[i],s=l.getAttribute("data-href")||l.getAttribute("href");if("stylesheet"===l.rel&&(s===n||s===a))return t()}var p=document.getElementsByTagName("style");for(i=0;i<p.length;i++){l=p[i],s=l.getAttribute("data-href");if(s===n||s===a)return t()}var f=document.createElement("link");f.rel="stylesheet",f.type="text/css",f.onload=t,f.onerror=function(t){var n=t&&t.target&&t.target.src||a,u=new Error("Loading CSS chunk "+e+" failed.\n("+n+")");u.code="CSS_CHUNK_LOAD_FAILED",u.request=n,delete o[e],f.parentNode.removeChild(f),r(u)},f.href=a;var d=document.getElementsByTagName("head")[0];d.appendChild(f)})).then((function(){o[e]=0})));var n=a[e];if(0!==n)if(n)t.push(n[2]);else{var u=new Promise((function(t,r){n=a[e]=[t,r]}));t.push(n[2]=u);var l,s=document.createElement("script");s.charset="utf-8",s.timeout=120,c.nc&&s.setAttribute("nonce",c.nc),s.src=i(e);var p=new Error;l=function(t){s.onerror=s.onload=null,clearTimeout(f);var r=a[e];if(0!==r){if(r){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;p.message="Loading chunk "+e+" failed.\n("+n+": "+o+")",p.name="ChunkLoadError",p.type=n,p.request=o,r[1](p)}a[e]=void 0}};var f=setTimeout((function(){l({type:"timeout",target:s})}),12e4);s.onerror=s.onload=l,document.head.appendChild(s)}return Promise.all(t)},c.m=e,c.c=n,c.d=function(e,t,r){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},c.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(c.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)c.d(r,n,function(t){return e[t]}.bind(null,n));return r},c.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="/jak-project/",c.oe=function(e){throw console.error(e),e};var l=window["webpackJsonp"]=window["webpackJsonp"]||[],s=l.push.bind(l);l.push=t,l=l.slice();for(var p=0;p<l.length;p++)t(l[p]);var f=s;u.push([0,"chunk-vendors"]),r()})({0:function(e,t,r){e.exports=r("56d7")},"56d7":function(e,t,r){"use strict";r.r(t);r("e260"),r("e6cf"),r("cca6"),r("a79d");var n=r("2b0e"),o=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("v-app",[r("v-main",[r("router-view")],1)],1)},a=[],u={name:"App",components:{},data:function(){return{}}},i=u,c=r("2877"),l=r("6544"),s=r.n(l),p=r("7496"),f=r("f6c4"),d=Object(c["a"])(i,o,a,!1,null,null,null),h=d.exports;s()(d,{VApp:p["a"],VMain:f["a"]});var m=r("f309");n["a"].use(m["a"]);var v=new m["a"]({theme:{dark:!0}}),b=(r("d3b7"),r("3ca3"),r("ddb0"),r("8c4f"));n["a"].use(b["a"]);var g=[{path:"/",name:"Home",component:function(){return r.e("about").then(r.bind(null,"bb51"))}}],y=new b["a"]({mode:"history",base:"/jak-project/",routes:g}),w=y;n["a"].config.productionTip=!1,new n["a"]({vuetify:v,router:w,render:function(e){return e(h)}}).$mount("#app")}});
|
||||
//# sourceMappingURL=app.1e67702b.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -91,7 +91,7 @@ The `state` system is used to control a process. Each process can be in a `stat
|
||||
|
||||
For example, we can create a simple test state like this:
|
||||
```
|
||||
(defstate test-state
|
||||
(defstate test-state (process)
|
||||
:enter (lambda () (format #t "enter!~%"))
|
||||
:exit (lambda () (format #t "exit!~%"))
|
||||
:trans (lambda () (format #t "trans!~%"))
|
||||
|
||||
@@ -175,4 +175,16 @@
|
||||
- Methods can now be `:replace`d to override their type from their parent. Use this with extreme care.
|
||||
- TypeSpecs now support "tags". This can specify a `:behavior` tag for a function.
|
||||
- Lambdas and methods now support `:behavior` to specify the current process type.
|
||||
- `defbehavior` has been added to define a global behavior.
|
||||
- `defbehavior` has been added to define a global behavior.
|
||||
- Auto-generated inspect methods of process now start by calling the parent type's inspect, like in GOAL.
|
||||
- Fields with type `(inline-array thing)` can now be set in statics.
|
||||
- `meters`, `degrees`, and `seconds` types have been added.
|
||||
- Bitfields with `symbol` fields used in an immediate `(new 'static ...)` can now define the symbol in the `new` form.
|
||||
- Bitfields with `float` fields used in an immediate `(new 'static ...)` in code can use a non-constant floating point value.
|
||||
- Multiple variables assigned to the same register using `:reg` in `rlet` (or overlapping with `self` in a behavior) will now be merged to a single variable instead of causing a compiler error. Variables will have their own type, but they will all be an alias of the same exact register.
|
||||
- Stack arrays of uint128 will now be 16-byte aligned instead of sometimes only 8.
|
||||
- Inline arrays of structures are now allowed with `stack-no-clear`.
|
||||
- Creating arrays on the stack now must be done with `stack-no-clear` as they are not memset to 0 or constructed in any way.
|
||||
- The register allocator has been dramatically improved and generates ~5x fewer spill instructions and is able to eliminate more moves.
|
||||
- Added a `(print-debug-compiler-stats)` form to print out statistics related to register allocation and move elimination
|
||||
- Added `get-enum-vals` which returns a list of pairs. Each pair is the name (symbol) and value (int) for each value in the enum
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
//! Supported languages.
|
||||
enum class Language {
|
||||
English = 0,
|
||||
French = 1,
|
||||
German = 2,
|
||||
Spanish = 3,
|
||||
Italian = 4,
|
||||
Japanese = 5,
|
||||
UK_English = 6,
|
||||
// uk english?
|
||||
};
|
||||
@@ -54,7 +54,7 @@ void Loop(std::function<bool()> f) {
|
||||
// exit if display window was closed
|
||||
if (glfwWindowShouldClose(Display::display)) {
|
||||
// Display::KillDisplay(Display::display);
|
||||
MasterExit = 1;
|
||||
MasterExit = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "game/common/game_common_types.h"
|
||||
#include "game/sce/libscf.h"
|
||||
#include "kboot.h"
|
||||
#include "kmachine.h"
|
||||
|
||||
@@ -5,23 +5,8 @@
|
||||
* GOAL Boot. Contains the "main" function to launch GOAL runtime.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_KBOOT_H
|
||||
#define RUNTIME_KBOOT_H
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
//! Supported languages.
|
||||
enum class Language {
|
||||
English = 0,
|
||||
French = 1,
|
||||
German = 2,
|
||||
Spanish = 3,
|
||||
Italian = 4,
|
||||
Japanese = 5,
|
||||
UK_English = 6,
|
||||
// uk english?
|
||||
};
|
||||
|
||||
struct MasterConfig {
|
||||
u16 language; //! GOAL language 0
|
||||
u16 aspect; //! SCE_ASPECT 2
|
||||
@@ -76,5 +61,3 @@ void KernelCheckAndDispatch();
|
||||
void KernelShutdown();
|
||||
|
||||
extern u32 MasterUseKernel;
|
||||
|
||||
#endif // RUNTIME_KBOOT_H
|
||||
|
||||
@@ -364,7 +364,7 @@ void load_and_link_dgo_from_c(const char* name, Ptr<kheapinfo> heap, u32 linkFla
|
||||
|
||||
char objName[64];
|
||||
strcpy(objName, (dgoObj + 4).cast<char>().c()); // name from dgo object header
|
||||
lg::debug("[link and exec] {} {}", objName, lastObjectLoaded);
|
||||
lg::debug("[link and exec] {} {} {}", objName, lastObjectLoaded, objSize);
|
||||
link_and_exec(obj, objName, objSize, heap, linkFlag); // link now!
|
||||
|
||||
// inform IOP we are done
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
//#include "ps2/common_types.h"
|
||||
//#include "kernel/kmachine.h"
|
||||
#include "kmemcard.h"
|
||||
#include <cstdio>
|
||||
|
||||
// static s32 next;
|
||||
// static s32 language;
|
||||
static s32 language;
|
||||
// static MemoryCardOperation op;
|
||||
// static mc_info mc[2];
|
||||
|
||||
void kmemcard_init_globals() {
|
||||
// next = 0;
|
||||
language = 0;
|
||||
}
|
||||
|
||||
///*!
|
||||
@@ -65,14 +67,14 @@ void kmemcard_init_globals() {
|
||||
//
|
||||
//}
|
||||
//
|
||||
///*!
|
||||
// * Set the language or something.
|
||||
// */
|
||||
// void MC_set_language(s32 l) {
|
||||
// printf("Language set to %d\n", l);
|
||||
// language = l;
|
||||
//}
|
||||
//
|
||||
/*!
|
||||
* Set the language or something.
|
||||
*/
|
||||
void MC_set_language(s32 l) {
|
||||
printf("Language set to %d\n", l);
|
||||
language = l;
|
||||
}
|
||||
|
||||
// u64 MC_format(s32 param) {
|
||||
// u64 can_add = op.operation == NO_OP;
|
||||
// if(can_add) {
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
* Memory card interface. Very messy code.
|
||||
*/
|
||||
|
||||
#ifndef JAK_KMEMCARD_H
|
||||
#define JAK_KMEMCARD_H
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "kmachine.h"
|
||||
|
||||
@@ -79,5 +76,3 @@ u64 MC_load(s32 param, s32 param2, Ptr<u8> data);
|
||||
void MC_makefile(s32 port, s32 size);
|
||||
u32 MC_check_result();
|
||||
void MC_get_status(s32 slot, Ptr<mc_slot_info> info);
|
||||
|
||||
#endif // JAK_KMEMCARD_H
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "kmalloc.h"
|
||||
#include "kprint.h"
|
||||
#include "fileio.h"
|
||||
#include "kmemcard.h"
|
||||
#include "kboot.h"
|
||||
#include "kdsnetm.h"
|
||||
#include "kdgo.h"
|
||||
@@ -1947,7 +1948,7 @@ s32 InitHeapAndSymbol() {
|
||||
// make_function_symbol_from_c("mc-check-result", &CKernel::not_yet_implemented);
|
||||
// make_function_symbol_from_c("mc-get-slot-info", &CKernel::not_yet_implemented);
|
||||
// make_function_symbol_from_c("mc-makefile", &CKernel::not_yet_implemented);
|
||||
// make_function_symbol_from_c("kset-language", &CKernel::not_yet_implemented);
|
||||
make_function_symbol_from_c("kset-language", (void*)MC_set_language);
|
||||
|
||||
// set *debug-segment*
|
||||
auto ds_symbol = intern_from_c("*debug-segment*");
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "srpc.h"
|
||||
#include "game/sce/iop.h"
|
||||
#include "game/common/loader_rpc_types.h"
|
||||
#include "game/common/game_common_types.h"
|
||||
#include "common/versions.h"
|
||||
#include "sbank.h"
|
||||
#include "iso_api.h"
|
||||
@@ -16,11 +17,16 @@ uint8_t gLoaderBuf[SRPC_MESSAGE_SIZE];
|
||||
int32_t gSoundEnable = 1;
|
||||
u32 gInfoEE = 0; // EE address where we should send info on each frame.
|
||||
|
||||
// english, french, germain, spanish, italian, japanese, uk.
|
||||
static const char* languages[] = {"ENG", "FRE", "GER", "SPA", "ITA", "JAP", "UKE"};
|
||||
const char* gLanguage = nullptr;
|
||||
|
||||
void srpc_init_globals() {
|
||||
memset((void*)&gMusicTweakInfo, 0, sizeof(gMusicTweakInfo));
|
||||
memset((void*)gLoaderBuf, 0, sizeof(gLoaderBuf));
|
||||
gSoundEnable = 1;
|
||||
gInfoEE = 0;
|
||||
gLanguage = languages[(int)Language::English];
|
||||
}
|
||||
|
||||
// todo Thread_Player
|
||||
@@ -71,6 +77,11 @@ void* RPC_Loader(unsigned int /*fno*/, void* data, int size) {
|
||||
gInfoEE = cmd->irx_version.ee_addr;
|
||||
return cmd;
|
||||
} break;
|
||||
case SoundCommand::SET_LANGUAGE: {
|
||||
gLanguage = languages[cmd->set_language.langauge_id];
|
||||
printf("IOP language: %s\n", gLanguage); // added.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("Unhandled RPC Loader command %d\n", (int)cmd->command);
|
||||
assert(false);
|
||||
|
||||
@@ -52,12 +52,17 @@ struct SoundRpcBankCommand {
|
||||
char bank_name[16];
|
||||
};
|
||||
|
||||
struct SoundRpcSetLanguageCommand {
|
||||
u32 langauge_id; // game_common_types.h, Language
|
||||
};
|
||||
|
||||
struct SoundRpcCommand {
|
||||
u16 rsvd1;
|
||||
SoundCommand command;
|
||||
union {
|
||||
SoundRpcGetIrxVersion irx_version;
|
||||
SoundRpcBankCommand load_bank;
|
||||
SoundRpcSetLanguageCommand set_language;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace ee {
|
||||
int sceScfGetAspect() {
|
||||
return SCE_ASPECT_169;
|
||||
return SCE_ASPECT_43;
|
||||
}
|
||||
|
||||
int sceScfGetLanguage() {
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
("ENGINE.CGO"
|
||||
("types-h.o" "types-h")
|
||||
("vu1-macros.o" "vu1-macros")
|
||||
|
||||
;; the "math" section
|
||||
("math.o" "math")
|
||||
("vector-h.o" "vector-h")
|
||||
("gravity-h.o" "gravity-h")
|
||||
("bounding-box-h.o" "bounding-box-h")
|
||||
("matrix-h.o" "matrix-h")
|
||||
("quaternion-h.o" "quaternion-h")
|
||||
("euler-h.o" "euler-h")
|
||||
("transform-h.o" "transform-h")
|
||||
("geometry-h.o" "geometry-h")
|
||||
("trigonometry-h.o" "trigonometry-h")
|
||||
("transformq-h.o" "transformq-h")
|
||||
("bounding-box.o" "bounding-box")
|
||||
("matrix.o" "matrix")
|
||||
("transform.o" "transform")
|
||||
("quaternion.o" "quaternion")
|
||||
("euler.o" "euler")
|
||||
("geometry.o" "geometry")
|
||||
("trigonometry.o" "trigonometry")
|
||||
|
||||
|
||||
("gsound-h.o" "gsound-h")
|
||||
("timer-h.o" "timer-h")
|
||||
("timer.o" "timer")
|
||||
("vif-h.o" "vif-h")
|
||||
("dma-h.o" "dma-h")
|
||||
("video-h.o" "video-h")
|
||||
("vu1-user-h.o" "vu1-user-h")
|
||||
("dma.o" "dma")
|
||||
("dma-buffer.o" "dma-buffer")
|
||||
("dma-bucket.o" "dma-bucket")
|
||||
("dma-disasm.o" "dma-disasm")
|
||||
("pad.o" "pad")
|
||||
("gs.o" "gs")
|
||||
("display-h.o" "display-h")
|
||||
("vector.o" "vector")
|
||||
("file-io.o" "file-io")
|
||||
("loader-h.o" "loader-h")
|
||||
("texture-h.o" "texture-h")
|
||||
("level-h.o" "level-h")
|
||||
("math-camera-h.o" "math-camera-h")
|
||||
("math-camera.o" "math-camera")
|
||||
("font-h.o" "font-h")
|
||||
("decomp-h.o" "decomp-h")
|
||||
("display.o" "display")
|
||||
("connect.o" "connect")
|
||||
("text-h.o" "text-h")
|
||||
("settings-h.o" "settings-h")
|
||||
("capture.o" "capture")
|
||||
("memory-usage-h.o" "memory-usage-h")
|
||||
("texture.o" "texture")
|
||||
("main-h.o" "main-h")
|
||||
("mspace-h.o" "mspace-h")
|
||||
("drawable-h.o" "drawable-h")
|
||||
("drawable-group-h.o" "drawable-group-h")
|
||||
("drawable-inline-array-h.o" "drawable-inline-array-h")
|
||||
("draw-node-h.o" "draw-node-h")
|
||||
("drawable-tree-h.o" "drawable-tree-h")
|
||||
("drawable-actor-h.o" "drawable-actor-h")
|
||||
("drawable-ambient-h.o" "drawable-ambient-h")
|
||||
("game-task-h.o" "game-task-h")
|
||||
("hint-control-h.o" "hint-control-h")
|
||||
("generic-h.o" "generic-h")
|
||||
("lights-h.o" "lights-h")
|
||||
("ocean-h.o" "ocean-h")
|
||||
("ocean-trans-tables.o" "ocean-trans-tables")
|
||||
("ocean-tables.o" "ocean-tables")
|
||||
("ocean-frames.o" "ocean-frames")
|
||||
("sky-h.o" "sky-h")
|
||||
("mood-h.o" "mood-h")
|
||||
("time-of-day-h.o" "time-of-day-h")
|
||||
("art-h.o" "art-h")
|
||||
("generic-vu1-h.o" "generic-vu1-h")
|
||||
("merc-h.o" "merc-h")
|
||||
("generic-merc-h.o" "generic-merc-h")
|
||||
("generic-tie-h.o" "generic-tie-h")
|
||||
("generic-work-h.o" "generic-work-h")
|
||||
("shadow-cpu-h.o" "shadow-cpu-h")
|
||||
("shadow-vu1-h.o" "shadow-vu1-h")
|
||||
("memcard-h.o" "memcard-h")
|
||||
("game-info-h.o" "game-info-h")
|
||||
("wind-h.o" "wind-h")
|
||||
("prototype-h.o" "prototype-h")
|
||||
("joint-h.o" "joint-h")
|
||||
("bones-h.o" "bones-h")
|
||||
("engines.o" "engines")
|
||||
("res-h.o" "res-h")
|
||||
("res.o" "res")
|
||||
("lights.o" "lights")
|
||||
("dynamics-h.o" "dynamics-h")
|
||||
("surface-h.o" "surface-h")
|
||||
("pat-h.o" "pat-h")
|
||||
("fact-h.o" "fact-h")
|
||||
("aligner-h.o" "aligner-h")
|
||||
("game-h.o" "game-h")
|
||||
("generic-obs-h.o" "generic-obs-h")
|
||||
("pov-camera-h.o" "pov-camera-h")
|
||||
("sync-info-h.o" "sync-info-h")
|
||||
("smush-control-h.o" "smush-control-h")
|
||||
("trajectory-h.o" "trajectory-h")
|
||||
("debug-h.o" "debug-h")
|
||||
("joint-mod-h.o" "joint-mod-h")
|
||||
("collide-func-h.o" "collide-func-h")
|
||||
("collide-mesh-h.o" "collide-mesh-h")
|
||||
("collide-shape-h.o" "collide-shape-h")
|
||||
("collide-target-h.o" "collide-target-h")
|
||||
("collide-touch-h.o" "collide-touch-h")
|
||||
("collide-edge-grab-h.o" "collide-edge-grab-h")
|
||||
("process-drawable-h.o" "process-drawable-h")
|
||||
("effect-control-h.o" "effect-control-h")
|
||||
("collide-frag-h.o" "collide-frag-h")
|
||||
("projectiles-h.o" "projectiles-h")
|
||||
("target-h.o" "target-h")
|
||||
("depth-cue-h.o" "depth-cue-h")
|
||||
("stats-h.o" "stats-h")
|
||||
("bsp-h.o" "bsp-h")
|
||||
("collide-cache-h.o" "collide-cache-h")
|
||||
("collide-h.o" "collide-h")
|
||||
("shrubbery-h.o" "shrubbery-h")
|
||||
("tie-h.o" "tie-h")
|
||||
("tfrag-h.o" "tfrag-h")
|
||||
("background-h.o" "background-h")
|
||||
("subdivide-h.o" "subdivide-h")
|
||||
("entity-h.o" "entity-h")
|
||||
("sprite-h.o" "sprite-h")
|
||||
("shadow-h.o" "shadow-h")
|
||||
("eye-h.o" "eye-h")
|
||||
("sparticle-launcher-h.o" "sparticle-launcher-h")
|
||||
("sparticle-h.o" "sparticle-h")
|
||||
("actor-link-h.o" "actor-link-h")
|
||||
("camera-h.o" "camera-h")
|
||||
("cam-debug-h.o" "cam-debug-h")
|
||||
("cam-interface-h.o" "cam-interface-h")
|
||||
("cam-update-h.o" "cam-update-h")
|
||||
("assert-h.o" "assert-h")
|
||||
("hud-h.o" "hud-h")
|
||||
("progress-h.o" "progress-h")
|
||||
("rpc-h.o" "rpc-h")
|
||||
("path-h.o" "path-h")
|
||||
("navigate-h.o" "navigate-h")
|
||||
("load-dgo.o" "load-dgo")
|
||||
("ramdisk.o" "ramdisk")
|
||||
("gsound.o" "gsound")
|
||||
("transformq.o" "transformq")
|
||||
("collide-func.o" "collide-func")
|
||||
("joint.o" "joint")
|
||||
("cylinder.o" "cylinder")
|
||||
("wind.o" "wind")
|
||||
("bsp.o" "bsp")
|
||||
("subdivide.o" "subdivide")
|
||||
("sprite.o" "sprite")
|
||||
("sprite-distort.o" "sprite-distort")
|
||||
("debug-sphere.o" "debug-sphere")
|
||||
("debug.o" "debug")
|
||||
("merc-vu1.o" "merc-vu1")
|
||||
("merc-blend-shape.o" "merc-blend-shape")
|
||||
("merc.o" "merc")
|
||||
("ripple.o" "ripple")
|
||||
("bones.o" "bones")
|
||||
("generic-vu0.o" "generic-vu0")
|
||||
("generic.o" "generic")
|
||||
("generic-vu1.o" "generic-vu1")
|
||||
("generic-effect.o" "generic-effect")
|
||||
("generic-merc.o" "generic-merc")
|
||||
("generic-tie.o" "generic-tie")
|
||||
("shadow-cpu.o" "shadow-cpu")
|
||||
("shadow-vu1.o" "shadow-vu1")
|
||||
("depth-cue.o" "depth-cue")
|
||||
("font.o" "font")
|
||||
("decomp.o" "decomp")
|
||||
("background.o" "background")
|
||||
("draw-node.o" "draw-node")
|
||||
("shrubbery.o" "shrubbery")
|
||||
("shrub-work.o" "shrub-work")
|
||||
("tfrag-near.o" "tfrag-near")
|
||||
("tfrag.o" "tfrag")
|
||||
("tfrag-methods.o" "tfrag-methods")
|
||||
("tfrag-work.o" "tfrag-work")
|
||||
("tie.o" "tie")
|
||||
("tie-near.o" "tie-near")
|
||||
("tie-work.o" "tie-work")
|
||||
("tie-methods.o" "tie-methods")
|
||||
("sync-info.o" "sync-info")
|
||||
("trajectory.o" "trajectory")
|
||||
("sparticle-launcher.o" "sparticle-launcher")
|
||||
("sparticle.o" "sparticle")
|
||||
("entity-table.o" "entity-table")
|
||||
("loader.o" "loader")
|
||||
("task-control-h.o" "task-control-h")
|
||||
("game-info.o" "game-info")
|
||||
("game-save.o" "game-save")
|
||||
("settings.o" "settings")
|
||||
("mood-tables.o" "mood-tables")
|
||||
("mood.o" "mood")
|
||||
("weather-part.o" "weather-part")
|
||||
("time-of-day.o" "time-of-day")
|
||||
("sky-utils.o" "sky-utils")
|
||||
("sky.o" "sky")
|
||||
("sky-tng.o" "sky-tng")
|
||||
("load-boundary-h.o" "load-boundary-h")
|
||||
("load-boundary.o" "load-boundary")
|
||||
("load-boundary-data.o" "load-boundary-data")
|
||||
("level-info.o" "level-info")
|
||||
("level.o" "level")
|
||||
("text.o" "text")
|
||||
("collide-probe.o" "collide-probe")
|
||||
("collide-frag.o" "collide-frag")
|
||||
("collide-mesh.o" "collide-mesh")
|
||||
("collide-touch.o" "collide-touch")
|
||||
("collide-edge-grab.o" "collide-edge-grab")
|
||||
("collide-shape.o" "collide-shape")
|
||||
("collide-shape-rider.o" "collide-shape-rider")
|
||||
("collide.o" "collide")
|
||||
("collide-planes.o" "collide-planes")
|
||||
("merc-death.o" "merc-death")
|
||||
("water-h.o" "water-h")
|
||||
("camera.o" "camera")
|
||||
("cam-interface.o" "cam-interface")
|
||||
("cam-master.o" "cam-master")
|
||||
("cam-states.o" "cam-states")
|
||||
("cam-states-dbg.o" "cam-states-dbg")
|
||||
("cam-combiner.o" "cam-combiner")
|
||||
("cam-update.o" "cam-update")
|
||||
("vol-h.o" "vol-h")
|
||||
("cam-layout.o" "cam-layout")
|
||||
("cam-debug.o" "cam-debug")
|
||||
("cam-start.o" "cam-start")
|
||||
("process-drawable.o" "process-drawable")
|
||||
("hint-control.o" "hint-control")
|
||||
("ambient.o" "ambient")
|
||||
("assert.o" "assert")
|
||||
("generic-obs.o" "generic-obs")
|
||||
("target-util.o" "target-util")
|
||||
("target-part.o" "target-part")
|
||||
("collide-reaction-target.o" "collide-reaction-target")
|
||||
("logic-target.o" "logic-target")
|
||||
("sidekick.o" "sidekick")
|
||||
("voicebox.o" "voicebox")
|
||||
("target-handler.o" "target-handler")
|
||||
("target.o" "target")
|
||||
("target2.o" "target2")
|
||||
("target-death.o" "target-death")
|
||||
("menu.o" "menu")
|
||||
("drawable.o" "drawable")
|
||||
("drawable-group.o" "drawable-group")
|
||||
("drawable-inline-array.o" "drawable-inline-array")
|
||||
("drawable-tree.o" "drawable-tree")
|
||||
("prototype.o" "prototype")
|
||||
("main-collide.o" "main-collide")
|
||||
("video.o" "video")
|
||||
("main.o" "main")
|
||||
("collide-cache.o" "collide-cache")
|
||||
("relocate.o" "relocate")
|
||||
("memory-usage.o" "memory-usage")
|
||||
("entity.o" "entity")
|
||||
("path.o" "path")
|
||||
("vol.o" "vol")
|
||||
("navigate.o" "navigate")
|
||||
("aligner.o" "aligner")
|
||||
("effect-control.o" "effect-control")
|
||||
("water.o" "water")
|
||||
("collectables-part.o" "collectables-part")
|
||||
("collectables.o" "collectables")
|
||||
("task-control.o" "task-control")
|
||||
("process-taskable.o" "process-taskable")
|
||||
("pov-camera.o" "pov-camera")
|
||||
("powerups.o" "powerups")
|
||||
("crates.o" "crates")
|
||||
("hud.o" "hud")
|
||||
("hud-classes.o" "hud-classes")
|
||||
("progress-static.o" "progress-static")
|
||||
("progress-part.o" "progress-part")
|
||||
("progress-draw.o" "progress-draw")
|
||||
("progress.o" "progress")
|
||||
("credits.o" "credits")
|
||||
("projectiles.o" "projectiles")
|
||||
("ocean.o" "ocean")
|
||||
("ocean-vu0.o" "ocean-vu0")
|
||||
("ocean-texture.o" "ocean-texture")
|
||||
("ocean-mid.o" "ocean-mid")
|
||||
("ocean-transition.o" "ocean-transition")
|
||||
("ocean-near.o" "ocean-near")
|
||||
("shadow.o" "shadow")
|
||||
("eye.o" "eye")
|
||||
("glist-h.o" "glist-h")
|
||||
("glist.o" "glist")
|
||||
("anim-tester.o" "anim-tester")
|
||||
("viewer.o" "viewer")
|
||||
("part-tester.o" "part-tester")
|
||||
("default-menu.o" "default-menu")
|
||||
)
|
||||
@@ -0,0 +1,330 @@
|
||||
("GAME.CGO"
|
||||
("types-h.o" "types-h")
|
||||
("vu1-macros.o" "vu1-macros")
|
||||
("math.o" "math")
|
||||
("vector-h.o" "vector-h")
|
||||
("gravity-h.o" "gravity-h")
|
||||
("bounding-box-h.o" "bounding-box-h")
|
||||
("matrix-h.o" "matrix-h")
|
||||
("quaternion-h.o" "quaternion-h")
|
||||
("euler-h.o" "euler-h")
|
||||
("transform-h.o" "transform-h")
|
||||
("geometry-h.o" "geometry-h")
|
||||
("trigonometry-h.o" "trigonometry-h")
|
||||
("transformq-h.o" "transformq-h")
|
||||
("bounding-box.o" "bounding-box")
|
||||
("matrix.o" "matrix")
|
||||
("transform.o" "transform")
|
||||
("quaternion.o" "quaternion")
|
||||
("euler.o" "euler")
|
||||
("geometry.o" "geometry")
|
||||
("trigonometry.o" "trigonometry")
|
||||
("gsound-h.o" "gsound-h")
|
||||
("timer-h.o" "timer-h")
|
||||
("timer.o" "timer")
|
||||
("vif-h.o" "vif-h")
|
||||
("dma-h.o" "dma-h")
|
||||
("video-h.o" "video-h")
|
||||
("vu1-user-h.o" "vu1-user-h")
|
||||
("dma.o" "dma")
|
||||
("dma-buffer.o" "dma-buffer")
|
||||
("dma-bucket.o" "dma-bucket")
|
||||
("dma-disasm.o" "dma-disasm")
|
||||
("pad.o" "pad")
|
||||
("gs.o" "gs")
|
||||
("display-h.o" "display-h")
|
||||
("vector.o" "vector")
|
||||
("file-io.o" "file-io")
|
||||
("loader-h.o" "loader-h")
|
||||
("texture-h.o" "texture-h")
|
||||
("level-h.o" "level-h")
|
||||
("math-camera-h.o" "math-camera-h")
|
||||
("math-camera.o" "math-camera")
|
||||
("font-h.o" "font-h")
|
||||
("decomp-h.o" "decomp-h")
|
||||
("display.o" "display")
|
||||
("connect.o" "connect")
|
||||
("text-h.o" "text-h")
|
||||
("settings-h.o" "settings-h")
|
||||
("capture.o" "capture")
|
||||
("memory-usage-h.o" "memory-usage-h")
|
||||
("texture.o" "texture")
|
||||
("main-h.o" "main-h")
|
||||
("mspace-h.o" "mspace-h")
|
||||
("drawable-h.o" "drawable-h")
|
||||
("drawable-group-h.o" "drawable-group-h")
|
||||
("drawable-inline-array-h.o" "drawable-inline-array-h")
|
||||
("draw-node-h.o" "draw-node-h")
|
||||
("drawable-tree-h.o" "drawable-tree-h")
|
||||
("drawable-actor-h.o" "drawable-actor-h")
|
||||
("drawable-ambient-h.o" "drawable-ambient-h")
|
||||
("game-task-h.o" "game-task-h")
|
||||
("hint-control-h.o" "hint-control-h")
|
||||
("generic-h.o" "generic-h")
|
||||
("lights-h.o" "lights-h")
|
||||
("ocean-h.o" "ocean-h")
|
||||
("ocean-trans-tables.o" "ocean-trans-tables")
|
||||
("ocean-tables.o" "ocean-tables")
|
||||
("ocean-frames.o" "ocean-frames")
|
||||
("sky-h.o" "sky-h")
|
||||
("mood-h.o" "mood-h")
|
||||
("time-of-day-h.o" "time-of-day-h")
|
||||
("art-h.o" "art-h")
|
||||
("generic-vu1-h.o" "generic-vu1-h")
|
||||
("merc-h.o" "merc-h")
|
||||
("generic-merc-h.o" "generic-merc-h")
|
||||
("generic-tie-h.o" "generic-tie-h")
|
||||
("generic-work-h.o" "generic-work-h")
|
||||
("shadow-cpu-h.o" "shadow-cpu-h")
|
||||
("shadow-vu1-h.o" "shadow-vu1-h")
|
||||
("memcard-h.o" "memcard-h")
|
||||
("game-info-h.o" "game-info-h")
|
||||
("wind-h.o" "wind-h")
|
||||
("prototype-h.o" "prototype-h")
|
||||
("joint-h.o" "joint-h")
|
||||
("bones-h.o" "bones-h")
|
||||
("engines.o" "engines")
|
||||
("res-h.o" "res-h")
|
||||
("res.o" "res")
|
||||
("lights.o" "lights")
|
||||
("dynamics-h.o" "dynamics-h")
|
||||
("surface-h.o" "surface-h")
|
||||
("pat-h.o" "pat-h")
|
||||
("fact-h.o" "fact-h")
|
||||
("aligner-h.o" "aligner-h")
|
||||
("game-h.o" "game-h")
|
||||
("generic-obs-h.o" "generic-obs-h")
|
||||
("pov-camera-h.o" "pov-camera-h")
|
||||
("sync-info-h.o" "sync-info-h")
|
||||
("smush-control-h.o" "smush-control-h")
|
||||
("trajectory-h.o" "trajectory-h")
|
||||
("debug-h.o" "debug-h")
|
||||
("joint-mod-h.o" "joint-mod-h")
|
||||
("collide-func-h.o" "collide-func-h")
|
||||
("collide-mesh-h.o" "collide-mesh-h")
|
||||
("collide-shape-h.o" "collide-shape-h")
|
||||
("collide-target-h.o" "collide-target-h")
|
||||
("collide-touch-h.o" "collide-touch-h")
|
||||
("collide-edge-grab-h.o" "collide-edge-grab-h")
|
||||
("process-drawable-h.o" "process-drawable-h")
|
||||
("effect-control-h.o" "effect-control-h")
|
||||
("collide-frag-h.o" "collide-frag-h")
|
||||
("projectiles-h.o" "projectiles-h")
|
||||
("target-h.o" "target-h")
|
||||
("depth-cue-h.o" "depth-cue-h")
|
||||
("stats-h.o" "stats-h")
|
||||
("bsp-h.o" "bsp-h")
|
||||
("collide-cache-h.o" "collide-cache-h")
|
||||
("collide-h.o" "collide-h")
|
||||
("shrubbery-h.o" "shrubbery-h")
|
||||
("tie-h.o" "tie-h")
|
||||
("tfrag-h.o" "tfrag-h")
|
||||
("background-h.o" "background-h")
|
||||
("subdivide-h.o" "subdivide-h")
|
||||
("entity-h.o" "entity-h")
|
||||
("sprite-h.o" "sprite-h")
|
||||
("shadow-h.o" "shadow-h")
|
||||
("eye-h.o" "eye-h")
|
||||
("sparticle-launcher-h.o" "sparticle-launcher-h")
|
||||
("sparticle-h.o" "sparticle-h")
|
||||
("actor-link-h.o" "actor-link-h")
|
||||
("camera-h.o" "camera-h")
|
||||
("cam-debug-h.o" "cam-debug-h")
|
||||
("cam-interface-h.o" "cam-interface-h")
|
||||
("cam-update-h.o" "cam-update-h")
|
||||
("assert-h.o" "assert-h")
|
||||
("hud-h.o" "hud-h")
|
||||
("progress-h.o" "progress-h")
|
||||
("rpc-h.o" "rpc-h")
|
||||
("path-h.o" "path-h")
|
||||
("navigate-h.o" "navigate-h")
|
||||
("load-dgo.o" "load-dgo")
|
||||
("ramdisk.o" "ramdisk")
|
||||
("gsound.o" "gsound")
|
||||
("transformq.o" "transformq")
|
||||
("collide-func.o" "collide-func")
|
||||
("joint.o" "joint")
|
||||
("cylinder.o" "cylinder")
|
||||
("wind.o" "wind")
|
||||
("bsp.o" "bsp")
|
||||
("subdivide.o" "subdivide")
|
||||
("sprite.o" "sprite")
|
||||
("sprite-distort.o" "sprite-distort")
|
||||
("debug-sphere.o" "debug-sphere")
|
||||
("debug.o" "debug")
|
||||
("merc-vu1.o" "merc-vu1")
|
||||
("merc-blend-shape.o" "merc-blend-shape")
|
||||
("merc.o" "merc")
|
||||
("ripple.o" "ripple")
|
||||
("bones.o" "bones")
|
||||
("generic-vu0.o" "generic-vu0")
|
||||
("generic.o" "generic")
|
||||
("generic-vu1.o" "generic-vu1")
|
||||
("generic-effect.o" "generic-effect")
|
||||
("generic-merc.o" "generic-merc")
|
||||
("generic-tie.o" "generic-tie")
|
||||
("shadow-cpu.o" "shadow-cpu")
|
||||
("shadow-vu1.o" "shadow-vu1")
|
||||
("depth-cue.o" "depth-cue")
|
||||
("font.o" "font")
|
||||
("decomp.o" "decomp")
|
||||
("background.o" "background")
|
||||
("draw-node.o" "draw-node")
|
||||
("shrubbery.o" "shrubbery")
|
||||
("shrub-work.o" "shrub-work")
|
||||
("tfrag-near.o" "tfrag-near")
|
||||
("tfrag.o" "tfrag")
|
||||
("tfrag-methods.o" "tfrag-methods")
|
||||
("tfrag-work.o" "tfrag-work")
|
||||
("tie.o" "tie")
|
||||
("tie-near.o" "tie-near")
|
||||
("tie-work.o" "tie-work")
|
||||
("tie-methods.o" "tie-methods")
|
||||
("sync-info.o" "sync-info")
|
||||
("trajectory.o" "trajectory")
|
||||
("sparticle-launcher.o" "sparticle-launcher")
|
||||
("sparticle.o" "sparticle")
|
||||
("entity-table.o" "entity-table")
|
||||
("loader.o" "loader")
|
||||
("task-control-h.o" "task-control-h")
|
||||
("game-info.o" "game-info")
|
||||
("game-save.o" "game-save")
|
||||
("settings.o" "settings")
|
||||
("mood-tables.o" "mood-tables")
|
||||
("mood.o" "mood")
|
||||
("weather-part.o" "weather-part")
|
||||
("time-of-day.o" "time-of-day")
|
||||
("sky-utils.o" "sky-utils")
|
||||
("sky.o" "sky")
|
||||
("sky-tng.o" "sky-tng")
|
||||
("load-boundary-h.o" "load-boundary-h")
|
||||
("load-boundary.o" "load-boundary")
|
||||
("load-boundary-data.o" "load-boundary-data")
|
||||
("level-info.o" "level-info")
|
||||
("level.o" "level")
|
||||
("text.o" "text")
|
||||
("collide-probe.o" "collide-probe")
|
||||
("collide-frag.o" "collide-frag")
|
||||
("collide-mesh.o" "collide-mesh")
|
||||
("collide-touch.o" "collide-touch")
|
||||
("collide-edge-grab.o" "collide-edge-grab")
|
||||
("collide-shape.o" "collide-shape")
|
||||
("collide-shape-rider.o" "collide-shape-rider")
|
||||
("collide.o" "collide")
|
||||
("collide-planes.o" "collide-planes")
|
||||
("merc-death.o" "merc-death")
|
||||
("water-h.o" "water-h")
|
||||
("camera.o" "camera")
|
||||
("cam-interface.o" "cam-interface")
|
||||
("cam-master.o" "cam-master")
|
||||
("cam-states.o" "cam-states")
|
||||
("cam-states-dbg.o" "cam-states-dbg")
|
||||
("cam-combiner.o" "cam-combiner")
|
||||
("cam-update.o" "cam-update")
|
||||
("vol-h.o" "vol-h")
|
||||
("cam-layout.o" "cam-layout")
|
||||
("cam-debug.o" "cam-debug")
|
||||
("cam-start.o" "cam-start")
|
||||
("process-drawable.o" "process-drawable")
|
||||
("hint-control.o" "hint-control")
|
||||
("ambient.o" "ambient")
|
||||
("assert.o" "assert")
|
||||
("generic-obs.o" "generic-obs")
|
||||
("target-util.o" "target-util")
|
||||
("target-part.o" "target-part")
|
||||
("collide-reaction-target.o" "collide-reaction-target")
|
||||
("logic-target.o" "logic-target")
|
||||
("sidekick.o" "sidekick")
|
||||
("voicebox.o" "voicebox")
|
||||
("target-handler.o" "target-handler")
|
||||
("target.o" "target")
|
||||
("target2.o" "target2")
|
||||
("target-death.o" "target-death")
|
||||
("menu.o" "menu")
|
||||
("drawable.o" "drawable")
|
||||
("drawable-group.o" "drawable-group")
|
||||
("drawable-inline-array.o" "drawable-inline-array")
|
||||
("drawable-tree.o" "drawable-tree")
|
||||
("prototype.o" "prototype")
|
||||
("main-collide.o" "main-collide")
|
||||
("video.o" "video")
|
||||
("main.o" "main")
|
||||
("collide-cache.o" "collide-cache")
|
||||
("relocate.o" "relocate")
|
||||
("memory-usage.o" "memory-usage")
|
||||
("entity.o" "entity")
|
||||
("path.o" "path")
|
||||
("vol.o" "vol")
|
||||
("navigate.o" "navigate")
|
||||
("aligner.o" "aligner")
|
||||
("effect-control.o" "effect-control")
|
||||
("water.o" "water")
|
||||
("collectables-part.o" "collectables-part")
|
||||
("collectables.o" "collectables")
|
||||
("task-control.o" "task-control")
|
||||
("process-taskable.o" "process-taskable")
|
||||
("pov-camera.o" "pov-camera")
|
||||
("powerups.o" "powerups")
|
||||
("crates.o" "crates")
|
||||
("hud.o" "hud")
|
||||
("hud-classes.o" "hud-classes")
|
||||
("progress-static.o" "progress-static")
|
||||
("progress-part.o" "progress-part")
|
||||
("progress-draw.o" "progress-draw")
|
||||
("progress.o" "progress")
|
||||
("credits.o" "credits")
|
||||
("projectiles.o" "projectiles")
|
||||
("ocean.o" "ocean")
|
||||
("ocean-vu0.o" "ocean-vu0")
|
||||
("ocean-texture.o" "ocean-texture")
|
||||
("ocean-mid.o" "ocean-mid")
|
||||
("ocean-transition.o" "ocean-transition")
|
||||
("ocean-near.o" "ocean-near")
|
||||
("shadow.o" "shadow")
|
||||
("eye.o" "eye")
|
||||
("glist-h.o" "glist-h")
|
||||
("glist.o" "glist")
|
||||
("anim-tester.o" "anim-tester")
|
||||
("viewer.o" "viewer")
|
||||
("part-tester.o" "part-tester")
|
||||
("default-menu.o" "default-menu")
|
||||
("dir-tpages.go" "dir-tpages")
|
||||
("tpage-463.go" "tpage-463")
|
||||
("tpage-2.go" "tpage-2")
|
||||
("tpage-880.go" "tpage-880")
|
||||
("tpage-256.go" "tpage-256")
|
||||
("tpage-1278.go" "tpage-1278")
|
||||
("texture-upload.o" "texture-upload")
|
||||
("tpage-1032.go" "tpage-1032")
|
||||
("tpage-62.go" "tpage-62")
|
||||
("tpage-1532.go" "tpage-1532")
|
||||
("fuel-cell-ag.go" "fuel-cell")
|
||||
("money-ag.go" "money")
|
||||
("buzzer-ag.go" "buzzer")
|
||||
("ecovalve-ag-ART-GAME.go" "ecovalve")
|
||||
("crate-ag.go" "crate")
|
||||
("speaker-ag.go" "speaker")
|
||||
("fuelcell-naked-ag.go" "fuelcell-naked")
|
||||
("eichar-ag.go" "eichar")
|
||||
("sidekick-ag.go" "sidekick")
|
||||
("deathcam-ag.go" "deathcam")
|
||||
("game-cnt.go" "game-cnt")
|
||||
("rigid-body-h.o" "rigid-body-h")
|
||||
("water-anim.o" "water-anim")
|
||||
("dark-eco-pool.o" "dark-eco-pool")
|
||||
("rigid-body.o" "rigid-body")
|
||||
("nav-enemy-h.o" "nav-enemy-h")
|
||||
("nav-enemy.o" "nav-enemy")
|
||||
("baseplat.o" "baseplat")
|
||||
("basebutton.o" "basebutton")
|
||||
("tippy.o" "tippy")
|
||||
("joint-exploder.o" "joint-exploder")
|
||||
("babak.o" "babak")
|
||||
("sharkey.o" "sharkey")
|
||||
("orb-cache.o" "orb-cache")
|
||||
("plat.o" "plat")
|
||||
("plat-button.o" "plat-button")
|
||||
("plat-eco.o" "plat-eco")
|
||||
("ropebridge.o" "ropebridge")
|
||||
("ticky.o" "ticky")
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
("KERNEL.CGO"
|
||||
("gcommon.o" "gcommon")
|
||||
("gstring-h.o" "gstring-h")
|
||||
("gkernel-h.o" "gkernel-h")
|
||||
("gkernel.o" "gkernel")
|
||||
("pskernel.o" "pskernel")
|
||||
("gstring.o" "gstring")
|
||||
("dgo-h.o" "dgo-h")
|
||||
("gstate.o" "gstate")
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
("VI1.DGO"
|
||||
("villagep-obs.o" "villagep-obs")
|
||||
("oracle.o" "oracle")
|
||||
("farmer.o" "farmer")
|
||||
("explorer.o" "explorer")
|
||||
("assistant.o" "assistant")
|
||||
("sage.o" "sage")
|
||||
("yakow.o" "yakow")
|
||||
("village-obs-VI1.o" "village-obs")
|
||||
("fishermans-boat.o" "fishermans-boat")
|
||||
("village1-part.o" "village1-part")
|
||||
("village1-part2.o" "village1-part2")
|
||||
("sequence-a-village1.o" "sequence-a-village1")
|
||||
("tpage-398.go" "tpage-398")
|
||||
("tpage-400.go" "tpage-400")
|
||||
("tpage-399.go" "tpage-399")
|
||||
("tpage-401.go" "tpage-401")
|
||||
("tpage-1470.go" "tpage-1470")
|
||||
("assistant-ag.go" "assistant")
|
||||
("evilplant-ag.go" "evilplant")
|
||||
("explorer-ag.go" "explorer")
|
||||
("farmer-ag.go" "farmer")
|
||||
("fishermans-boat-ag.go" "fishermans-boat")
|
||||
("hutlamp-ag.go" "hutlamp")
|
||||
("mayorgears-ag.go" "mayorgears")
|
||||
("medres-beach-ag.go" "medres-beach")
|
||||
("medres-beach1-ag.go" "medres-beach1")
|
||||
("medres-beach2-ag.go" "medres-beach2")
|
||||
("medres-beach3-ag.go" "medres-beach3")
|
||||
("medres-jungle-ag.go" "medres-jungle")
|
||||
("medres-jungle1-ag.go" "medres-jungle1")
|
||||
("medres-jungle2-ag.go" "medres-jungle2")
|
||||
("medres-misty-ag.go" "medres-misty")
|
||||
("medres-training-ag.go" "medres-training")
|
||||
("medres-village11-ag.go" "medres-village11")
|
||||
("medres-village12-ag.go" "medres-village12")
|
||||
("medres-village13-ag.go" "medres-village13")
|
||||
("oracle-ag-VI1.go" "oracle")
|
||||
("orb-cache-top-ag-VI1.go" "orb-cache-top")
|
||||
("reflector-middle-ag.go" "reflector-middle")
|
||||
("revcycle-ag.go" "revcycle")
|
||||
("revcycleprop-ag.go" "revcycleprop")
|
||||
("ropebridge-32-ag.go" "ropebridge-32")
|
||||
("sage-ag.go" "sage")
|
||||
("sagesail-ag.go" "sagesail")
|
||||
("sharkey-ag-VI1.go" "sharkey")
|
||||
("villa-starfish-ag.go" "villa-starfish")
|
||||
("village-cam-ag-VI1.go" "village-cam")
|
||||
("village1cam-ag.go" "village1cam")
|
||||
("warp-gate-switch-ag-VI1-VI3.go" "warp-gate-switch")
|
||||
("warpgate-ag.go" "warpgate")
|
||||
("water-anim-village1-ag.go" "water-anim-village1")
|
||||
("windmill-sail-ag.go" "windmill-sail")
|
||||
("windspinner-ag.go" "windspinner")
|
||||
("yakow-ag.go" "yakow")
|
||||
("village1-vis.go" "village1-vis")
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user