mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 06:54:31 -04:00
[decompiler] setup before making IR2 type inspector (#1423)
This commit is contained in:
@@ -6,6 +6,7 @@ cmake-build-debug/*
|
||||
.idea/*
|
||||
build/*
|
||||
decompiler_out/*
|
||||
decompiler_out2/*
|
||||
logs/*
|
||||
|
||||
# wsl apparently builds to here?
|
||||
|
||||
@@ -211,6 +211,34 @@ void TypeSystem::forward_declare_type_method_count(const std::string& name, int
|
||||
m_forward_declared_method_counts[name] = num_methods;
|
||||
}
|
||||
|
||||
/*!
|
||||
* forward declare, but allow the method count to be too large by up to 3 because jak2 stores
|
||||
* method counts in v2/v4's like n*4 + 3.
|
||||
*/
|
||||
void TypeSystem::forward_declare_type_method_count_multiple_of_4(const std::string& name,
|
||||
int num_methods) {
|
||||
auto existing_fwd = m_forward_declared_method_counts.find(name);
|
||||
if (existing_fwd != m_forward_declared_method_counts.end() &&
|
||||
existing_fwd->second + 3 < num_methods) {
|
||||
throw_typesystem_error(
|
||||
"Type {} was originally forward declared with {} methods and is now being forward declared "
|
||||
"with {} methods",
|
||||
name, existing_fwd->second, num_methods);
|
||||
}
|
||||
|
||||
auto existing_type = m_types.find(name);
|
||||
if (existing_type != m_types.end()) {
|
||||
int existing_count = get_next_method_id(existing_type->second.get());
|
||||
if (existing_count + 3 < num_methods) {
|
||||
throw_typesystem_error(
|
||||
"Type {} was defined with {} methods and is now being forward declared with {} methods",
|
||||
name, existing_count, num_methods);
|
||||
}
|
||||
}
|
||||
|
||||
m_forward_declared_method_counts[name] = num_methods;
|
||||
}
|
||||
|
||||
int TypeSystem::get_type_method_count(const std::string& name) const {
|
||||
auto result = try_get_type_method_count(name);
|
||||
if (result) {
|
||||
|
||||
@@ -128,6 +128,8 @@ class TypeSystem {
|
||||
void forward_declare_type_as_type(const std::string& name);
|
||||
void forward_declare_type_as(const std::string& new_type, const std::string& parent_type);
|
||||
void forward_declare_type_method_count(const std::string& name, int num_methods);
|
||||
void forward_declare_type_method_count_multiple_of_4(const std::string& name, int num_methods);
|
||||
|
||||
int get_type_method_count(const std::string& name) const;
|
||||
std::optional<int> try_get_type_method_count(const std::string& name) const;
|
||||
std::string get_runtime_type(const TypeSpec& ts);
|
||||
|
||||
+23
-21
@@ -19,33 +19,35 @@ void assert_string_empty_after(const char* str, int size) {
|
||||
}
|
||||
|
||||
std::string get_object_file_name(const std::string& original_name, u8* data, int size) {
|
||||
const std::string art_group_text =
|
||||
fmt::format("/src/next/data/art-group{}/",
|
||||
versions::ART_FILE_VERSION); // todo, this may change in other games
|
||||
const std::string art_group_text_strings[] = {
|
||||
fmt::format("/src/next/data/art-group{}/", versions::jak1::ART_FILE_VERSION),
|
||||
fmt::format("/src/jak2/final/art-group{}/", versions::jak2::ART_FILE_VERSION)};
|
||||
const std::string suffix = "-ag.go";
|
||||
|
||||
int len = int(art_group_text.length());
|
||||
for (int start = 0; start < size; start++) {
|
||||
bool failed = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (start + i >= size || data[start + i] != art_group_text[i]) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
for (int i = 0; i < int(original_name.length()); i++) {
|
||||
if (start + len + i >= size || data[start + len + i] != original_name[i]) {
|
||||
ASSERT(false);
|
||||
for (auto& art_group_text : art_group_text_strings) {
|
||||
int len = int(art_group_text.length());
|
||||
for (int start = 0; start < size; start++) {
|
||||
bool failed = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (start + i >= size || data[start + i] != art_group_text[i]) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(int(suffix.length()) + start + len + int(original_name.length()) < size);
|
||||
ASSERT(
|
||||
!memcmp(data + start + len + original_name.length(), suffix.data(), suffix.length() + 1));
|
||||
if (!failed) {
|
||||
for (int i = 0; i < int(original_name.length()); i++) {
|
||||
if (start + len + i >= size || data[start + len + i] != original_name[i]) {
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
return original_name + "-ag";
|
||||
ASSERT(int(suffix.length()) + start + len + int(original_name.length()) < size);
|
||||
ASSERT(!memcmp(data + start + len + original_name.length(), suffix.data(),
|
||||
suffix.length() + 1));
|
||||
|
||||
return original_name + "-ag";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "common/common_types.h"
|
||||
#include "common/versions.h"
|
||||
|
||||
void assert_string_empty_after(const char* str, int size);
|
||||
std::string get_object_file_name(const std::string& original_name, u8* data, int size);
|
||||
+10
-1
@@ -14,12 +14,19 @@ constexpr s32 GOAL_VERSION_MINOR = 9;
|
||||
|
||||
constexpr int DECOMPILER_VERSION = 4;
|
||||
|
||||
namespace jak1 {
|
||||
// these versions are from the game
|
||||
constexpr u32 ART_FILE_VERSION = 6;
|
||||
constexpr u32 LEVEL_FILE_VERSION = 30;
|
||||
constexpr u32 DGO_FILE_VERSION = 1;
|
||||
constexpr u32 RES_FILE_VERSION = 1;
|
||||
constexpr u32 TX_PAGE_VERSION = 7;
|
||||
} // namespace jak1
|
||||
|
||||
namespace jak2 {
|
||||
constexpr u32 ART_FILE_VERSION = 7;
|
||||
}
|
||||
|
||||
} // namespace versions
|
||||
|
||||
// GOAL kernel version (OpenGOAL changes this version from the game's version)
|
||||
@@ -28,4 +35,6 @@ constexpr int KERNEL_VERSION_MINOR = 0;
|
||||
|
||||
// OVERLORD version returned by an RPC
|
||||
constexpr int IRX_VERSION_MAJOR = 2;
|
||||
constexpr int IRX_VERSION_MINOR = 0;
|
||||
constexpr int IRX_VERSION_MINOR = 0;
|
||||
|
||||
enum class GameVersion { Jak1 = 1, Jak2 = 2 };
|
||||
@@ -4,6 +4,7 @@
|
||||
* This is the part of the disassembler that decodes MIPS instructions.
|
||||
*/
|
||||
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "InstructionDecode.h"
|
||||
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
||||
#include "common/util/Assert.h"
|
||||
@@ -93,6 +94,7 @@ static InstructionKind decode_cop2(OpcodeFields fields) {
|
||||
return IK::CTC2;
|
||||
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
break;
|
||||
@@ -149,6 +151,10 @@ static InstructionKind decode_cop2(OpcodeFields fields) {
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VFTOI12;
|
||||
|
||||
case 0b00101111111:
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VFTOI15;
|
||||
|
||||
case 0b00100111100:
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VITOF0;
|
||||
@@ -197,10 +203,16 @@ static InstructionKind decode_cop2(OpcodeFields fields) {
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VOPMULA;
|
||||
|
||||
case 0b01011111101:
|
||||
return IK::VMSUBA;
|
||||
|
||||
case 0b01100111100:
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VMOVE;
|
||||
|
||||
case 0b01100111101:
|
||||
return IK::VMR32;
|
||||
|
||||
case 0b01110111100:
|
||||
ASSERT(fields.data & (1 << 25));
|
||||
return IK::VDIV;
|
||||
@@ -343,6 +355,7 @@ static InstructionKind decode_cop2(OpcodeFields fields) {
|
||||
ASSERT(fields.dest() == 0b0);
|
||||
return IK::VCALLMS;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown cop2 lower11 case 0b{:b}\n", fields.lower11()));
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -355,6 +368,7 @@ static InstructionKind decode_W(OpcodeFields fields) {
|
||||
ASSERT(fields.ft() == 0);
|
||||
return IK::CVTSW;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -416,6 +430,7 @@ static InstructionKind decode_S(OpcodeFields fields) {
|
||||
ASSERT(fields.fd() == 0);
|
||||
return IK::CLES;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -432,6 +447,7 @@ static InstructionKind decode_BC1(OpcodeFields fields) {
|
||||
case 0b00011:
|
||||
return IK::BC1TL;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -454,6 +470,7 @@ static InstructionKind decode_cop1(OpcodeFields fields) {
|
||||
case 0b10100:
|
||||
return decode_W(fields);
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -467,6 +484,7 @@ static InstructionKind decode_c0(OpcodeFields fields) {
|
||||
ASSERT(fields.sa() == 0 && fields.rd() == 0 && fields.rt() == 0);
|
||||
return IK::EI;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -486,6 +504,7 @@ static InstructionKind decode_mt0(OpcodeFields fields) {
|
||||
if (fields.rd() == 0b11001 && fields.sa() == 0 && (fields.data & 1) == 1) {
|
||||
return IK::MTPC;
|
||||
} else {
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -500,6 +519,7 @@ static InstructionKind decode_mf0(OpcodeFields fields) {
|
||||
if (fields.rd() == 0b11001 && fields.sa() == 0 && (fields.data & 1) == 1) {
|
||||
return IK::MFPC;
|
||||
} else {
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -514,6 +534,7 @@ static InstructionKind decode_cop0(OpcodeFields fields) {
|
||||
case 0b10000:
|
||||
return decode_c0(fields);
|
||||
default:
|
||||
ASSERT(false);
|
||||
return InstructionKind::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -533,6 +554,7 @@ static InstructionKind decode_mmi3(OpcodeFields fields) {
|
||||
ASSERT(fields.rs() == 0);
|
||||
return IK::PCPYH;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -546,6 +568,8 @@ static InstructionKind decode_mmi2(OpcodeFields fields) {
|
||||
return IK::PMADDH;
|
||||
case 0b10010:
|
||||
return IK::PAND;
|
||||
case 0b10011:
|
||||
return IK::PXOR;
|
||||
case 0b11100:
|
||||
return IK::PMULTH;
|
||||
case 0b11110:
|
||||
@@ -553,6 +577,7 @@ static InstructionKind decode_mmi2(OpcodeFields fields) {
|
||||
case 0b11111:
|
||||
return IK::PROT3W;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown mmi2: 0b{:b}\n", fields.MMI_func()));
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -576,7 +601,10 @@ static InstructionKind decode_mmi1(OpcodeFields fields) {
|
||||
return IK::PEXTUH;
|
||||
case 0b11010:
|
||||
return IK::PEXTUB;
|
||||
case 0b11011:
|
||||
return IK::QFSRV;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown mmi1: 0b{:b}\n", fields.MMI_func()));
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -594,8 +622,14 @@ static InstructionKind decode_mmi0(OpcodeFields fields) {
|
||||
return IK::PMAXW;
|
||||
case 0b00100:
|
||||
return IK::PADDH;
|
||||
case 0b00101:
|
||||
return IK::PSUBH;
|
||||
case 0b00111:
|
||||
return IK::PMAXH;
|
||||
case 0b01000:
|
||||
return IK::PADDB;
|
||||
case 0b01010:
|
||||
return IK::PCGTB;
|
||||
case 0b10010:
|
||||
return IK::PEXTLW;
|
||||
case 0b10011:
|
||||
@@ -609,6 +643,7 @@ static InstructionKind decode_mmi0(OpcodeFields fields) {
|
||||
case 0b11011:
|
||||
return IK::PPACB;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown mmi0: 0b{:b}\n", fields.MMI_func()));
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -631,6 +666,7 @@ static InstructionKind decode_pmfhl(OpcodeFields fields) {
|
||||
ASSERT(fields.rt() == 0);
|
||||
return IK::PMFHL_LH;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -675,13 +711,14 @@ static InstructionKind decode_mmi(OpcodeFields fields) {
|
||||
case 0b111111:
|
||||
return IK::PSRAW;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static InstructionKind decode_regimm(OpcodeFields files) {
|
||||
static InstructionKind decode_regimm(OpcodeFields fields) {
|
||||
typedef InstructionKind IK;
|
||||
switch (files.rt()) {
|
||||
switch (fields.rt()) {
|
||||
case 0b00000:
|
||||
return IK::BLTZ;
|
||||
case 0b00001:
|
||||
@@ -692,7 +729,10 @@ static InstructionKind decode_regimm(OpcodeFields files) {
|
||||
return IK::BGEZL;
|
||||
case 0b10001:
|
||||
return IK::BGEZAL;
|
||||
case 0b11000:
|
||||
return IK::MTSAB;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown regimm: 0b{:b}\n", fields.rt()));
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -710,6 +750,7 @@ static InstructionKind decode_sync(OpcodeFields fields) {
|
||||
} else if (stype == 0b10000) {
|
||||
return IK::SYNCP;
|
||||
} else {
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -855,6 +896,7 @@ static InstructionKind decode_special(OpcodeFields fields) {
|
||||
ASSERT(fields.rs() == 0);
|
||||
return IK::DSRA32;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -867,6 +909,7 @@ static InstructionKind decode_cache(OpcodeFields fields) {
|
||||
case 0b10100:
|
||||
return IK::CACHE_DXWBIN;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -988,6 +1031,7 @@ static InstructionKind decode_opcode(uint32_t code) {
|
||||
case 0b111111:
|
||||
return IK::SD;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return IK::UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
* The Instruction Decoder - converts a LinkedWord into a Instruction.
|
||||
* This is the part of the disassembler that decodes MIPS instructions.
|
||||
*/
|
||||
|
||||
#ifndef NEXT_INSTRUCTIONDECODE_H
|
||||
#define NEXT_INSTRUCTIONDECODE_H
|
||||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace decompiler {
|
||||
@@ -17,4 +13,3 @@ class LinkedObjectFile;
|
||||
|
||||
Instruction decode_instruction(LinkedWord& word, LinkedObjectFile& file, int seg_id, int word_id);
|
||||
} // namespace decompiler
|
||||
#endif // NEXT_INSTRUCTIONDECODE_H
|
||||
|
||||
@@ -278,12 +278,18 @@ void init_opcode_info() {
|
||||
def(IK::SYNCL, "sync.l"); // Synchronize Shared Memory (Load)
|
||||
def(IK::ERET, "eret"); // Exception Return
|
||||
def(IK::EI, "ei"); // Enable Interrupt
|
||||
def(IK::MTSAB, "mtsab")
|
||||
.src_gpr(FT::RS)
|
||||
.src(FT::ZIMM16, DT::IMM); // Move Byte Count to Shift Amount Register
|
||||
drd_srs_srt(def(IK::QFSRV, "qfsrv")).gpr128(); // Quadword Funnel Shift Right Variable
|
||||
|
||||
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::PADDB, "paddb").gpr128()); // Parallel Add Byte
|
||||
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::PSUBH, "psubh").gpr128()); // Parallel Subtract Halfword
|
||||
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
|
||||
@@ -293,6 +299,7 @@ void init_opcode_info() {
|
||||
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::PCGTB, "pcgtb").gpr128()); // Parallel Compare for Greater Than Byte
|
||||
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
|
||||
@@ -306,6 +313,7 @@ void init_opcode_info() {
|
||||
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_srs_srt(def(IK::PXOR, "pxor").gpr128()); // Parallel Exclusive Or
|
||||
|
||||
def(IK::PEXEW, "pexew").gpr128().dst_gpr(FT::RD).src_gpr(FT::RT); // Parallel Exchange Even Word
|
||||
|
||||
@@ -372,6 +380,7 @@ void init_opcode_info() {
|
||||
cd_dvft_svfs(def(IK::VFTOI0, "vftoi0")); // Conversion to Fixed Point
|
||||
cd_dvft_svfs(def(IK::VFTOI4, "vftoi4")); // Conversion to Fixed Point
|
||||
cd_dvft_svfs(def(IK::VFTOI12, "vftoi12")); // Conversion to Fixed Point
|
||||
cd_dvft_svfs(def(IK::VFTOI15, "vftoi15")); // Conversion to Fixed Point
|
||||
cd_dvft_svfs(def(IK::VITOF0, "vitof0")); // Conversion to Floating Point Number
|
||||
cd_dvft_svfs(def(IK::VITOF12, "vitof12")); // Conversion to Floating Point Number
|
||||
cd_dvft_svfs(def(IK::VITOF15, "vitof15")); // Conversion to Floating Point Number
|
||||
@@ -407,6 +416,7 @@ void init_opcode_info() {
|
||||
cd_dacc_svfs_svft(def(IK::VMULA, "vmula"));
|
||||
cd_dacc_svfs_svft(def(IK::VADDA, "vadda"));
|
||||
cd_dacc_svfs_svft(def(IK::VMADDA, "vmadda"));
|
||||
cd_dacc_svfs_svft(def(IK::VMSUBA, "vmsuba"));
|
||||
|
||||
cd_dacc_svfs_svft(def(IK::VOPMULA, "vopmula"));
|
||||
|
||||
@@ -431,6 +441,7 @@ void init_opcode_info() {
|
||||
.src(FT::ZERO, DT::VU_Q);
|
||||
|
||||
def(IK::VRGET, "vrget").src(FT::DEST, DT::DEST).dst_vf(FT::FT);
|
||||
def(IK::VMR32, "vmr32").src(FT::DEST, DT::DEST).src_vf(FT::FT).dst_vf(FT::FS);
|
||||
|
||||
// integer
|
||||
def(IK::VMTIR, "vmtir").dst(FT::RT, DT::VI).src_vf(FT::FS).src(FT::BC, DT::BC);
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
* Decoding info for each opcode.
|
||||
*/
|
||||
|
||||
#ifndef NEXT_OPCODEINFO_H
|
||||
#define NEXT_OPCODEINFO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace decompiler {
|
||||
@@ -128,6 +125,8 @@ enum class InstructionKind {
|
||||
EI,
|
||||
CACHE_DXWBIN,
|
||||
PREF,
|
||||
MTSAB,
|
||||
QFSRV,
|
||||
|
||||
// MMI unsorted
|
||||
PSLLW,
|
||||
@@ -144,6 +143,7 @@ enum class InstructionKind {
|
||||
PEXTLW,
|
||||
PPACH,
|
||||
PSUBW,
|
||||
PCGTB,
|
||||
PCGTW,
|
||||
PEXTLH,
|
||||
PEXTLB,
|
||||
@@ -153,6 +153,8 @@ enum class InstructionKind {
|
||||
PADDH,
|
||||
PMAXW,
|
||||
PPACW,
|
||||
PSUBH,
|
||||
PADDB,
|
||||
|
||||
// MMI 1
|
||||
PCEQW,
|
||||
@@ -171,6 +173,7 @@ enum class InstructionKind {
|
||||
PMADDH,
|
||||
PMULTH,
|
||||
PEXEW,
|
||||
PXOR,
|
||||
|
||||
// MMI 3
|
||||
POR,
|
||||
@@ -212,6 +215,7 @@ enum class InstructionKind {
|
||||
VFTOI0,
|
||||
VFTOI4,
|
||||
VFTOI12,
|
||||
VFTOI15,
|
||||
VITOF0,
|
||||
VITOF12,
|
||||
VITOF15,
|
||||
@@ -247,6 +251,7 @@ enum class InstructionKind {
|
||||
VMULA,
|
||||
VADDA,
|
||||
VMADDA,
|
||||
VMSUBA,
|
||||
|
||||
VOPMULA,
|
||||
VDIV,
|
||||
@@ -268,6 +273,7 @@ enum class InstructionKind {
|
||||
VRNEXT,
|
||||
VNOP,
|
||||
VWAITQ,
|
||||
VMR32,
|
||||
VCALLMS, // last cop2 macro instruction
|
||||
|
||||
EE_OP_MAX
|
||||
@@ -361,4 +367,3 @@ extern OpcodeInfo gOpcodeInfo[(uint32_t)InstructionKind::EE_OP_MAX];
|
||||
|
||||
void init_opcode_info();
|
||||
} // namespace decompiler
|
||||
#endif // NEXT_OPCODEINFO_H
|
||||
|
||||
@@ -444,6 +444,8 @@ void LinkedObjectFile::disassemble_functions() {
|
||||
decode_instruction(words_by_seg.at(seg).at(word), *this, seg, word));
|
||||
if (function.instructions.back().is_valid()) {
|
||||
stats.decoded_ops++;
|
||||
} else {
|
||||
lg::error("Failed to decode op: 0x{:08x}", words_by_seg.at(seg).at(word).data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -582,6 +584,9 @@ std::string LinkedObjectFile::print_function_disassembly(Function& func,
|
||||
result += " ;;";
|
||||
auto& word = words_by_seg[seg].at(func.start_word + i);
|
||||
append_word_to_string(result, word);
|
||||
} else {
|
||||
result += line;
|
||||
result += '\n';
|
||||
}
|
||||
|
||||
if (in_delay_slot) {
|
||||
|
||||
@@ -219,7 +219,8 @@ static uint32_t c_symlink3(LinkedObjectFile& f,
|
||||
static void link_v2_or_v4(LinkedObjectFile& f,
|
||||
const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts) {
|
||||
DecompilerTypeSystem& dts,
|
||||
GameVersion version) {
|
||||
const auto* header = (const LinkHeaderV4*)&data.at(0);
|
||||
ASSERT(header->version == 4 || header->version == 2);
|
||||
|
||||
@@ -251,6 +252,13 @@ static void link_v2_or_v4(LinkedObjectFile& f,
|
||||
const uint8_t* code_start = &data.at(code_offset);
|
||||
const uint8_t* code_end =
|
||||
&data.at(code_offset + code_size - 1) + 1; // get the pointer to one past the end.
|
||||
|
||||
if (version == GameVersion::Jak2) {
|
||||
while (((code_end - code_start) % 4)) {
|
||||
code_end++;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(((code_end - code_start) % 4) == 0);
|
||||
f.set_segment_count(1);
|
||||
for (auto x = code_start; x < code_end; x += 4) {
|
||||
@@ -605,7 +613,7 @@ static void link_v3(LinkedObjectFile& f,
|
||||
const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
GameVersion game_version) {
|
||||
auto header = (const LinkHeaderV3*)(&data.at(0));
|
||||
ASSERT(name == header->name);
|
||||
ASSERT(header->segments == 3);
|
||||
@@ -652,11 +660,11 @@ static void link_v3(LinkedObjectFile& f,
|
||||
// HACK!
|
||||
// why is this a thing?
|
||||
// HACK!
|
||||
if (game_version == 1 && name == "level-h" && seg_id == 0) {
|
||||
if (game_version == GameVersion::Jak1 && name == "level-h" && seg_id == 0) {
|
||||
segment_size++;
|
||||
}
|
||||
|
||||
if (game_version == 2) {
|
||||
if (game_version == GameVersion::Jak2) {
|
||||
bool adjusted = false;
|
||||
while (segment_size % 4) {
|
||||
segment_size++;
|
||||
@@ -756,7 +764,16 @@ static void link_v3(LinkedObjectFile& f,
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
} else {
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
dts.ts.forward_declare_type_method_count(s_name, reloc & 0x7f);
|
||||
switch (game_version) {
|
||||
case GameVersion::Jak1:
|
||||
dts.ts.forward_declare_type_method_count(s_name, (reloc & 0x7f));
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
dts.ts.forward_declare_type_method_count_multiple_of_4(s_name, (reloc & 0x7f) * 4 + 3);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
kind = SymbolLinkKind::TYPE;
|
||||
}
|
||||
|
||||
@@ -795,7 +812,7 @@ static void link_v3(LinkedObjectFile& f,
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
GameVersion game_version) {
|
||||
LinkedObjectFile result;
|
||||
const auto* header = (const LinkHeaderCommon*)&data.at(0);
|
||||
|
||||
@@ -805,7 +822,7 @@ LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
link_v3(result, data, name, dts, game_version);
|
||||
} else if (header->version == 4 || header->version == 2) {
|
||||
ASSERT(header->type_tag == 0xffffffff);
|
||||
link_v2_or_v4(result, data, name, dts);
|
||||
link_v2_or_v4(result, data, name, dts, game_version);
|
||||
} else if (header->version == 5) {
|
||||
link_v5(result, data, name, dts);
|
||||
} else {
|
||||
|
||||
@@ -13,5 +13,5 @@ class DecompilerTypeSystem;
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version);
|
||||
GameVersion game_version);
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -115,7 +115,7 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
Timer timer;
|
||||
|
||||
lg::info("-Loading types...");
|
||||
dts.parse_type_defs({"decompiler", "config", "all-types.gc"});
|
||||
dts.parse_type_defs({config.all_types_file});
|
||||
|
||||
if (!obj_file_name_map_file.empty()) {
|
||||
lg::info("-Loading obj name map file...");
|
||||
@@ -407,7 +407,9 @@ std::string ObjectFileDB::generate_obj_listing(const std::unordered_set<std::str
|
||||
// this check is extremely important. It makes sure we don't have any repeat names. This could
|
||||
// be caused by two files with the same name, in the same DGOs, but different data.
|
||||
if (int(all_unique_names.size()) != unique_count) {
|
||||
lg::error("Object files are not named properly, data will be lost!");
|
||||
lg::error(
|
||||
"Object files are not named properly, data will be lost! Got {} objs, but only {} names\n",
|
||||
unique_count, all_unique_names.size());
|
||||
}
|
||||
|
||||
if (unique_count > 0) {
|
||||
@@ -530,7 +532,7 @@ void ObjectFileDB::find_code(const Config& config) {
|
||||
obj.linked_data.find_functions();
|
||||
obj.linked_data.disassemble_functions();
|
||||
|
||||
if (config.game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
if (config.game_version == GameVersion::Jak1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
obj.linked_data.process_fp_relative_links();
|
||||
} else {
|
||||
lg::warn("Skipping process_fp_relative_links in {}", obj.to_unique_name().c_str());
|
||||
|
||||
@@ -34,12 +34,15 @@ Config read_config_file(const std::string& path_to_config_file,
|
||||
cfg[key] = val;
|
||||
}
|
||||
|
||||
config.game_version = cfg.at("game_version").get<int>();
|
||||
int version_int = cfg.at("game_version").get<int>();
|
||||
ASSERT(version_int == 1 || version_int == 2);
|
||||
config.game_version = (GameVersion)version_int;
|
||||
config.text_version = cfg.at("text_version").get<GameTextVersion>();
|
||||
config.game_name = cfg.at("game_name").get<std::string>();
|
||||
if (cfg.contains("expected_elf_name")) {
|
||||
config.expected_elf_name = cfg.at("expected_elf_name").get<std::string>();
|
||||
}
|
||||
config.all_types_file = cfg.at("all_types_file").get<std::string>();
|
||||
|
||||
auto inputs_json = read_json_file_from_config(cfg, "inputs_file");
|
||||
config.dgo_names = inputs_json.at("dgo_names").get<std::vector<std::string>>();
|
||||
|
||||
+3
-1
@@ -7,6 +7,7 @@
|
||||
#include <optional>
|
||||
#include "decompiler/Disasm/Register.h"
|
||||
#include "decompiler/data/game_text.h"
|
||||
#include "common/versions.h"
|
||||
|
||||
namespace decompiler {
|
||||
struct RegisterTypeCast {
|
||||
@@ -82,7 +83,7 @@ struct DecompileHacks {
|
||||
};
|
||||
|
||||
struct Config {
|
||||
int game_version = -1;
|
||||
GameVersion game_version = GameVersion::Jak1;
|
||||
std::vector<std::string> dgo_names;
|
||||
std::vector<std::string> object_file_names;
|
||||
std::vector<std::string> str_file_names;
|
||||
@@ -91,6 +92,7 @@ struct Config {
|
||||
std::vector<std::string> streamed_audio_file_names;
|
||||
|
||||
std::string obj_file_name_map_file;
|
||||
std::string all_types_file;
|
||||
|
||||
bool disassemble_code = false;
|
||||
bool decompile_code = false;
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"inputs_file": "decompiler/config/jak1_ntsc_black_label/inputs.jsonc",
|
||||
"art_info_file": "decompiler/config/jak1_ntsc_black_label/art_info.jsonc",
|
||||
"import_deps_file": "decompiler/config/jak1_ntsc_black_label/import_deps.jsonc",
|
||||
"all_types_file": "decompiler/config/all-types.gc",
|
||||
|
||||
// optional: a predetermined object file name map from a file.
|
||||
// this will make decompilation naming consistent even if you only run on some objects.
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
{
|
||||
"gkernel":[
|
||||
[16, "(function process symbol)"],
|
||||
[22, "(function process symbol)"],
|
||||
[25, "(function process symbol)"],
|
||||
[28, "(function process symbol)"],
|
||||
[30, "(function process symbol)"],
|
||||
[32, "(function process symbol)"]
|
||||
]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"files":{},
|
||||
"functions":{}
|
||||
}
|
||||
@@ -4,10 +4,7 @@
|
||||
////////////////////////////
|
||||
|
||||
"types_with_bad_inspect_methods": [
|
||||
"engine",
|
||||
"bsp-header",
|
||||
"joint-anim-matrix",
|
||||
"part-tracker"
|
||||
|
||||
],
|
||||
|
||||
"no_type_analysis_functions_by_name": [],
|
||||
@@ -16,368 +13,27 @@
|
||||
// the second argument is the name of the first condition in the cond. Use print_cfg to find it out.
|
||||
// The third argument is the number of cases. If you set it too small it may fail to build the CFG.
|
||||
"cond_with_else_max_lengths": [
|
||||
["(method 20 res-lump)", "b0", 2],
|
||||
["(method 11 res-lump)", "b0", 1],
|
||||
["(method 12 res-lump)", "b0", 1]
|
||||
|
||||
],
|
||||
|
||||
// if a cond with an else case is being used a value in a place where it looks wrong
|
||||
// you can add the function name to this list and it will more aggressively reject this rewrite.
|
||||
"aggressively_reject_cond_to_value_rewrite": [
|
||||
"(method 10 res-lump)",
|
||||
"(method 11 res-lump)",
|
||||
"(method 12 res-lump)",
|
||||
"(method 7 texture-page)"
|
||||
|
||||
],
|
||||
|
||||
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
|
||||
// currently it just leaves pcpyld as an asm op.
|
||||
"hint_inline_assembly_functions": ["matrix-transpose!"],
|
||||
"hint_inline_assembly_functions": [],
|
||||
|
||||
"asm_functions_by_name": [
|
||||
// gcommon
|
||||
"quad-copy!",
|
||||
|
||||
// gkernel
|
||||
"(method 11 cpu-thread)",
|
||||
"throw",
|
||||
"return-from-thread",
|
||||
"return-from-thread-dead",
|
||||
"reset-and-call",
|
||||
"(method 10 cpu-thread)",
|
||||
"(method 0 catch-frame)",
|
||||
"throw-dispatch",
|
||||
"set-to-run-bootstrap",
|
||||
"run-function-in-process", // not asm, but it uses the stack.
|
||||
|
||||
// pskernel
|
||||
"return-from-exception", // F: eret
|
||||
"kernel-read-function", // F: delay slot tricks
|
||||
"kernel-write-function", // F: delay slot tricks
|
||||
"kernel-copy-function",
|
||||
"kernel-check-hardwired-addresses",
|
||||
|
||||
// math
|
||||
"rand-uint31-gen",
|
||||
|
||||
// bounding box
|
||||
"(method 9 bounding-box)", // F: asm branching
|
||||
"(method 14 bounding-box)",
|
||||
|
||||
// matrix
|
||||
"(method 9 matrix)", // F: asm branching
|
||||
"matrix-axis-sin-cos!", // F: asm branching
|
||||
"matrix-axis-sin-cos-vu!",
|
||||
|
||||
// geometry
|
||||
"circle-circle-xz-intersect", // F: asm branching
|
||||
|
||||
// trigonometry
|
||||
"exp", // BUG: cfg is wrong.
|
||||
"atan0", // P: manual use of stack
|
||||
"sincos!", // P: manual use of stack
|
||||
"sincos-rad!",
|
||||
|
||||
// dma-h
|
||||
"dma-count-until-done", // F: asm branching
|
||||
"dma-sync-with-count", // F: asm branching
|
||||
"dma-send-no-scratch", // F: asm branching
|
||||
"dma-sync-fast",
|
||||
|
||||
// dma
|
||||
"symlink3", // F: asm branching
|
||||
"symlink2", // F: asm branching
|
||||
"dma-sync-hang",
|
||||
|
||||
// display
|
||||
"vblank-handler", // F: weird asm for interrupt handler
|
||||
"vif1-handler", // F: weird asm for interrupt handler
|
||||
"vif1-handler-debug",
|
||||
|
||||
// vector
|
||||
"vector=", // asm branching
|
||||
|
||||
// collide-mesh-h
|
||||
"(method 11 collide-mesh-cache)",
|
||||
|
||||
// collide-func
|
||||
"moving-sphere-triangle-intersect", // P: weird branching
|
||||
"collide-do-primitives", // P: asm branching
|
||||
|
||||
// joint
|
||||
"calc-animation-from-spr", // F: asm branching
|
||||
"decompress-frame-data-pair-to-accumulator", // P: asm calling
|
||||
"decompress-frame-data-to-accumulator", // P: asm calling
|
||||
"decompress-fixed-data-to-accumulator", // P: asm calling
|
||||
"normalize-frame-quaternions", // F: asm branching, return
|
||||
"clear-frame-accumulator", // F: asm branching
|
||||
"cspace<-parented-transformq-joint!",
|
||||
|
||||
// sprite
|
||||
|
||||
// merc-blend-shape
|
||||
"setup-blerc-chains-for-one-fragment", // F: asm branching
|
||||
"merc-dma-chain-to-spr", // F: asm branching
|
||||
"blerc-a-fragment",
|
||||
|
||||
// ripple
|
||||
"ripple-matrix-scale",
|
||||
"ripple-apply-wave-table",
|
||||
"ripple-create-wave-table",
|
||||
"ripple-execute-init",
|
||||
|
||||
// bones
|
||||
"draw-bones-hud",
|
||||
"draw-bones",
|
||||
"draw-bones-check-longest-edge-asm",
|
||||
"draw-bones-merc",
|
||||
"bones-mtx-calc-execute",
|
||||
"bones-mtx-calc",
|
||||
"texscroll-execute",
|
||||
|
||||
// generic-effect
|
||||
"generic-debug-light-proc",
|
||||
"generic-none-dma-wait",
|
||||
"generic-copy-vtx-dclr-dtex",
|
||||
"generic-light",
|
||||
"generic-envmap-only-proc",
|
||||
"generic-no-light",
|
||||
"generic-no-light+envmap",
|
||||
"generic-no-light-dproc",
|
||||
"generic-no-light-dproc-only",
|
||||
"generic-no-light-proc",
|
||||
"generic-interp-dproc",
|
||||
"generic-envmap-dproc",
|
||||
"generic-prepare-dma-single",
|
||||
"generic-prepare-dma-double",
|
||||
"generic-envmap-proc",
|
||||
"generic-light-proc",
|
||||
"generic-dma-from-spr",
|
||||
"upload-vu0-program",
|
||||
|
||||
// generic-merc
|
||||
"generic-merc-execute-all",
|
||||
"generic-merc-execute-asm", // CFG
|
||||
"high-speed-reject",
|
||||
"mercneric-convert",
|
||||
"mercneric-bittable-asm",
|
||||
"mercneric-shader-asm",
|
||||
"mercneric-matrix-asm",
|
||||
"generic-merc-init-asm",
|
||||
|
||||
// generic-tie
|
||||
"generic-tie-convert",
|
||||
"generic-tie-convert-proc",
|
||||
"generic-tie-upload-next",
|
||||
"generic-tie-decompress",
|
||||
"generic-tie-dma-to-spad-sync",
|
||||
|
||||
// shadow-cpu
|
||||
"shadow-execute",
|
||||
"shadow-add-double-edges",
|
||||
"shadow-add-double-tris",
|
||||
"shadow-add-single-edges",
|
||||
"shadow-add-facing-single-tris",
|
||||
"shadow-add-verts",
|
||||
"shadow-find-double-edges",
|
||||
"shadow-find-facing-double-tris",
|
||||
"shadow-find-single-edges",
|
||||
"shadow-find-facing-single-tris",
|
||||
"shadow-scissor-top",
|
||||
"shadow-scissor-edges",
|
||||
"shadow-calc-dual-verts",
|
||||
|
||||
// background
|
||||
"background-upload-vu0",
|
||||
|
||||
// draw-node
|
||||
"draw-node-cull",
|
||||
|
||||
// shrubbery
|
||||
"test-func",
|
||||
"draw-inline-array-instance-shrub",
|
||||
|
||||
// tfrag
|
||||
"stats-tfrag-asm",
|
||||
"draw-inline-array-tfrag-near",
|
||||
"draw-inline-array-tfrag",
|
||||
|
||||
// tie-methods
|
||||
"draw-inline-array-prototype-tie-near-asm",
|
||||
"draw-inline-array-prototype-tie-asm",
|
||||
"draw-inline-array-prototype-tie-generic-asm",
|
||||
"draw-inline-array-instance-tie",
|
||||
|
||||
// sparticle-launcher
|
||||
"sp-init-fields!",
|
||||
|
||||
// sparticle
|
||||
"memcpy",
|
||||
"sp-process-block-3d",
|
||||
"sp-process-block-2d",
|
||||
"sp-launch-particles-var",
|
||||
"particle-adgif",
|
||||
"sp-init-fields!",
|
||||
|
||||
// time-of-day
|
||||
"time-of-day-interp-colors-scratch",
|
||||
"time-of-day-interp-colors",
|
||||
|
||||
// sky-tng
|
||||
"clip-polygon-against-negative-hyperplane",
|
||||
"clip-polygon-against-positive-hyperplane",
|
||||
"draw-large-polygon",
|
||||
|
||||
// load-boundary
|
||||
"render-boundary-tri",
|
||||
"render-boundary-quad",
|
||||
"draw-boundary-polygon",
|
||||
|
||||
// collide-probe
|
||||
"collide-probe-instance-tie", // CFG
|
||||
"collide-probe-node", // CFG
|
||||
|
||||
// collide-edge-grab
|
||||
"(method 13 collide-edge-work)", // CFG
|
||||
"(method 17 collide-edge-work)", // CFG
|
||||
"(method 15 collide-edge-work)", // CFG
|
||||
"(method 16 collide-edge-work)", // CFG
|
||||
"(method 9 edge-grab-info)", // CFG
|
||||
"(method 18 collide-edge-work)", // CFG
|
||||
"(method 10 collide-edge-hold-list)", // CFG
|
||||
|
||||
// collide-shape
|
||||
"(method 15 collide-shape-prim-mesh)", // CFG
|
||||
"(method 15 collide-shape-prim-sphere)", // CFG
|
||||
"(method 16 collide-shape-prim)", // CFG
|
||||
"(method 15 collide-shape-prim-group)", // CFG
|
||||
"(method 18 collide-shape-prim-sphere)",
|
||||
"(method 23 collide-shape-prim-sphere)", // CFG
|
||||
"(method 23 collide-shape-prim-mesh)", // BUG - crash in variable pass
|
||||
"(method 24 collide-shape-prim)", // CFG
|
||||
"(method 23 collide-shape-prim-group)", // CFG
|
||||
"(method 42 collide-shape)", // CFG
|
||||
|
||||
// process-drawable BUG
|
||||
"cspace-inspect-tree",
|
||||
"(method 19 process-drawable)",
|
||||
|
||||
// ambient
|
||||
"ambient-inspect",
|
||||
|
||||
// target BUG
|
||||
"target-falling-anim-trans", // CFG resolution
|
||||
|
||||
// target2 BUG
|
||||
"look-for-points-of-interest", // Failed to split nested sc - looks like dead code to me
|
||||
|
||||
// drawable-tree
|
||||
"(method 16 drawable-tree)",
|
||||
|
||||
// collide-cache
|
||||
"(method 10 collide-puss-work)", // CFG
|
||||
"(method 9 collide-puss-work)", // decompiler crash
|
||||
"(method 19 collide-cache)", // decompiler crash
|
||||
"(method 10 collide-cache-prim)", // CFG
|
||||
"(method 9 collide-cache-prim)", // CFG
|
||||
"(method 30 collide-cache)", // unsupported asm - c.le.s
|
||||
"(method 13 collide-shape-prim-group)", // CFG
|
||||
"(method 13 collide-shape-prim-mesh)", // CFG
|
||||
"(method 14 collide-shape-prim-group)", // CFG
|
||||
"(method 14 collide-shape-prim-mesh)", // CFG
|
||||
"(method 12 collide-shape-prim-group)", // CFG
|
||||
"(method 12 collide-shape-prim-mesh)", // CFG
|
||||
"(method 27 collide-cache)", // CFG
|
||||
"(method 14 collide-cache)", // CFG
|
||||
"(method 28 collide-cache)", // CFG
|
||||
"(method 26 collide-cache)", // CFG
|
||||
"(method 21 collide-cache)", // CFG
|
||||
"(method 32 collide-cache)", // CFG
|
||||
|
||||
// memory-usage BUG
|
||||
//"(method 14 level)",
|
||||
|
||||
// navigate BUG
|
||||
"(method 32 nav-control)",
|
||||
|
||||
// ocean
|
||||
"draw-large-polygon-ocean", // CFG
|
||||
|
||||
// ocean-vu0
|
||||
"ocean-generate-verts", // crash
|
||||
"ocean-interp-wave",
|
||||
|
||||
// ropebridge BUG
|
||||
"(method 27 ropebridge)",
|
||||
|
||||
// all unchecked and in level DGO code
|
||||
"(anon-function 21 plant-boss)", // CFG
|
||||
// "(anon-function 10 ice-cube)",
|
||||
// "(anon-function 15 ice-cube)",
|
||||
"mistycannon-find-best-solution",
|
||||
"target-flut-falling-anim-trans", // CFG failure
|
||||
"kermit-check-to-hit-player?",
|
||||
"(anon-function 36 mistycannon)",
|
||||
"(anon-function 2 target-tube)",
|
||||
"(anon-function 5 orbit-plat)",
|
||||
"(anon-function 2 ogreboss)"
|
||||
|
||||
],
|
||||
|
||||
// these functions use pairs and the decompiler
|
||||
// will be less picky about types related to pairs.
|
||||
"pair_functions_by_name": [
|
||||
"ref",
|
||||
"last",
|
||||
"member",
|
||||
"nmember",
|
||||
"assoc",
|
||||
"assoce",
|
||||
"append!",
|
||||
"delete!",
|
||||
"delete-car!",
|
||||
"insert-cons!",
|
||||
"sort",
|
||||
"unload-package",
|
||||
"(method 4 pair)",
|
||||
"nassoc",
|
||||
"nassoce",
|
||||
"lookup-level-info",
|
||||
"(method 21 level-group)",
|
||||
"(method 12 level)",
|
||||
"update-sound-banks",
|
||||
"(method 16 level-group)",
|
||||
"bg",
|
||||
"(method 18 game-info)",
|
||||
"debug-menu-context-default-selection",
|
||||
"debug-menu-rebuild",
|
||||
"debug-menu-func-decode",
|
||||
"debug-menu-make-from-template",
|
||||
"debug-menu-render",
|
||||
"debug-menu-context-select-next-or-prev-item",
|
||||
"debug-menu-context-select-new-item",
|
||||
"debug-menu-send-msg",
|
||||
"debug-menu-find-from-template",
|
||||
"build-continue-menu",
|
||||
"(method 8 process-tree)",
|
||||
"(method 16 load-state)",
|
||||
"(method 15 load-state)",
|
||||
"build-continue-menu",
|
||||
"entity-remap-names",
|
||||
"(method 21 swamp-rat-nest-dummy-a)",
|
||||
"(method 21 swamp-rat-nest-dummy-b)",
|
||||
"(method 21 swamp-rat-nest-dummy-c)",
|
||||
"(method 27 battlecontroller)",
|
||||
"load-boundary-from-template",
|
||||
"command-get-time",
|
||||
"command-get-param",
|
||||
"command-get-quoted-param",
|
||||
"command-get-trans",
|
||||
"command-get-camera",
|
||||
"(method 14 camera-tracker)",
|
||||
"(enter billy-playing)",
|
||||
"(code target-continue)",
|
||||
"next-level"
|
||||
|
||||
],
|
||||
|
||||
// If format is used with the wrong number of arguments,
|
||||
@@ -385,108 +41,11 @@
|
||||
// that they used the correct number. This will override the decompiler's
|
||||
// automatic detection.
|
||||
"bad_format_strings": {
|
||||
"ERROR: dma tag has data in reserved bits ~X~%": 0,
|
||||
"#<surface f0:~m f1:~f tf+:~f tf-:~f sf:~f tvv:~m": 5,
|
||||
"ERROR<GMJ>: value of symbol ~A in task-controls is not a task-control~%": 0,
|
||||
"~0K~10,'-S--~5,'-DK-of-~5,'-DK--~5,'-DK-of-~5,'-DK--": 5,
|
||||
" bsp ~192H~5DK ~280Hdebug~456H~5DK~%": 2,
|
||||
" bsp-leaf-vis-iop ~192H~5DK~%": 1,
|
||||
" bsp-leaf-vis-adj ~192H~5DK~%": 1,
|
||||
" level-code ~192H~5DK~%": 1,
|
||||
" tfrag ~192H~5DK ~280Htfragment~456H~5DK~%": 2,
|
||||
" tie-proto ~192H~5DK ~280Hsky~456H~5DK~%": 2,
|
||||
" tie-instance ~192H~5DK ~280Htie-fragment~456H~5DK~%": 2,
|
||||
" shrub-proto ~192H~5DK ~280Htie-near~456H~5DK~%": 2,
|
||||
" shrub-instance ~192H~5DK ~280Hshrubbery~456H~5DK~%": 2,
|
||||
" collision ~192H~5DK ~280Htie-generic~456H~5DK~%": 2,
|
||||
" 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~%": 1,
|
||||
" 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,
|
||||
"money ~A was killed in pickup~%": 0
|
||||
|
||||
},
|
||||
|
||||
"blocks_ending_in_asm_branch": {
|
||||
"closest-pt-in-triangle": [17],
|
||||
|
||||
// this one is all asm branches
|
||||
"circle-circle-xz-intersect": [
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
|
||||
],
|
||||
|
||||
"find-knot-span": [0, 1, 2, 3, 5, 6, 7, 8, 9],
|
||||
|
||||
"curve-evaluate!": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
|
||||
"(method 9 texture-page-dir)": [4, 5],
|
||||
|
||||
"adgif-shader<-texture-with-update!": [0, 1],
|
||||
|
||||
"display-loop": [44, 49, 66, 96],
|
||||
|
||||
"load-game-text-info": [12, 13, 14, 16, 17, 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],
|
||||
"draw-string": [
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
||||
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
|
||||
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
|
||||
94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
|
||||
125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
|
||||
155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
|
||||
170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
|
||||
185, 186, 187, 188, 189
|
||||
],
|
||||
"get-string-length": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50
|
||||
],
|
||||
"unpack-comp-rle": [1, 3, 5, 6],
|
||||
"(method 16 level)": [1, 5, 13, 14, 15, 19, 26, 53],
|
||||
"unpack-comp-huf": [2, 4, 5, 6, 7, 8, 9],
|
||||
"blerc-execute": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
|
||||
],
|
||||
"(method 11 fact-info-target)": [42],
|
||||
"(anon-function 9 game-save)": [3, 4, 5, 6, 7, 8, 10],
|
||||
//"(anon-function 9 game-save)":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
|
||||
"particle-adgif": [0, 1, 2, 3, 4, 5, 7],
|
||||
"sp-launch-particles-var": [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, 62, 63, 64, 65, 66
|
||||
],
|
||||
"(method 11 sparticle-launch-control)": [27, 28, 35, 46, 48, 49, 77],
|
||||
"upload-vis-bits": [0, 1, 2, 3, 4, 5, 6],
|
||||
|
||||
"draw-drawable-tree-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-trans-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-dirt-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-ice-tfrag": [6, 8, 13, 15],
|
||||
|
||||
"birth-pickup-at-point": [0]
|
||||
},
|
||||
|
||||
// Sometimes the game might use format strings that are fetched dynamically,
|
||||
@@ -495,51 +54,26 @@
|
||||
// e.g. "function-name":[[op, argc], [op, argc], ...]
|
||||
// where "op" is the op number for the call to format.
|
||||
"dynamic_format_arg_counts": {
|
||||
"(method 35 progress)": [
|
||||
[44, 1],
|
||||
[92, 1]
|
||||
],
|
||||
"(method 49 progress)": [[35, 1]],
|
||||
"(method 37 progress)": [[41, 1]],
|
||||
"(method 38 progress)": [[106, 1]],
|
||||
"(method 39 progress)": [[41, 1]],
|
||||
"(method 41 progress)": [[73, 1]],
|
||||
"(method 42 progress)": [[41, 1]],
|
||||
"(method 43 progress)": [
|
||||
[51, 1],
|
||||
[94, 1]
|
||||
],
|
||||
"": []
|
||||
|
||||
},
|
||||
|
||||
"mips2c_functions_by_name": [
|
||||
"sp-init-fields!",
|
||||
"particle-adgif",
|
||||
"sp-launch-particles-var",
|
||||
"sp-process-block-2d",
|
||||
"sp-process-block-3d",
|
||||
"draw-large-polygon",
|
||||
"clip-polygon-against-positive-hyperplane",
|
||||
"clip-polygon-against-negative-hyperplane",
|
||||
"render-sky-quad",
|
||||
"render-sky-tri",
|
||||
"init-sky-regs",
|
||||
"set-tex-offset",
|
||||
"adgif-shader<-texture-with-update!",
|
||||
"init-boundary-regs",
|
||||
"draw-boundary-polygon",
|
||||
"render-boundary-quad",
|
||||
"render-boundary-tri",
|
||||
"draw-inline-array-tfrag",
|
||||
"stats-tfrag-asm",
|
||||
"time-of-day-interp-colors-scratch"
|
||||
|
||||
|
||||
],
|
||||
|
||||
"mips2c_jump_table_functions": {
|
||||
|
||||
},
|
||||
|
||||
// there are some missing textures. I don't know what the game actually does here.
|
||||
// the format for entries is [level, tpage, index]
|
||||
"missing_textures": [
|
||||
["finalboss", 1419, 3]
|
||||
"missing_textures": [],
|
||||
|
||||
// some object files have garbage pad data at the end which makes the decompiler
|
||||
// assume they must be different files, such as the art group for orb-cache-top.
|
||||
// this just suppresses a message.
|
||||
"expected_merged_objs": [
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
+160
-158
@@ -7,163 +7,163 @@
|
||||
// most objects are part of CGO/DGO files (both go in dgo_names). This includes levels and the engine
|
||||
// the DGOs will be processed in this order. Usually it's best to have KERNEL, ENGINE, then the levels when
|
||||
// you want to run on the entire game.
|
||||
"dgo_names": [/*
|
||||
"CGO/ART.CGO",
|
||||
"CGO/KERNEL.CGO",
|
||||
"CGO/ENGINE.CGO",
|
||||
"CGO/GAME.CGO",
|
||||
"CGO/COMMON.CGO",
|
||||
"DGO/LWIDEB.DGO",
|
||||
"DGO/LMEETBRT.DGO",
|
||||
"DGO/CTA.DGO",
|
||||
"DGO/PALOUT.DGO",
|
||||
"DGO/STD.DGO",
|
||||
"DGO/FOR.DGO",
|
||||
"DGO/CASEXT.DGO",
|
||||
"DGO/HIDEOUT.DGO",
|
||||
"DGO/LWIDESTA.DGO",
|
||||
"DGO/LRACELIT.DGO",
|
||||
"DGO/CTB.DGO",
|
||||
"DGO/KIOSK.DGO",
|
||||
"DGO/DG1.DGO",
|
||||
"DGO/FEB.DGO",
|
||||
"DGO/DMI.DGO",
|
||||
"DGO/ORACLE.DGO",
|
||||
"DGO/LERLTESS.DGO",
|
||||
"DGO/DRI.DGO",
|
||||
"DGO/LBRNERMK.DGO",
|
||||
"DGO/LRACECF.DGO",
|
||||
"DGO/CTC.DGO",
|
||||
"DGO/LTHRNOUT.DGO",
|
||||
"DGO/FRA.DGO",
|
||||
"DGO/LGARCSTA.DGO",
|
||||
"DGO/MTN.DGO",
|
||||
"DGO/INTROCST.DGO",
|
||||
"DGO/DRB.DGO",
|
||||
"DGO/ATE.DGO",
|
||||
"DGO/LERROL.DGO",
|
||||
"DGO/LTRNYSAM.DGO",
|
||||
"DGO/LOUTCSTB.DGO",
|
||||
"DGO/LASHTHRN.DGO",
|
||||
"DGO/TOC.DGO",
|
||||
"DGO/CFB.DGO",
|
||||
"DGO/CAB.DGO",
|
||||
"DGO/STC.DGO",
|
||||
"DGO/STR.DGO",
|
||||
"DGO/ATO.DGO",
|
||||
"DGO/SEB.DGO",
|
||||
"DGO/LPRSNCST.DGO",
|
||||
"DGO/SWB.DGO",
|
||||
"DGO/LPOWER.DGO",
|
||||
"DGO/FOB.DGO",
|
||||
"DGO/CIB.DGO",
|
||||
"DGO/LSHUTTLE.DGO",
|
||||
"DGO/LJAKDAX.DGO",
|
||||
"DGO/FORDUMPC.DGO",
|
||||
"DGO/LTRNTESS.DGO",
|
||||
"DGO/TBO.DGO",
|
||||
"DGO/THR.DGO",
|
||||
"DGO/PRI.DGO",
|
||||
"DGO/LKIDDOGE.DGO",
|
||||
"DGO/NESTT.DGO",
|
||||
"DGO/LWIDEC.DGO",
|
||||
"DGO/SAG.DGO",
|
||||
"DGO/NEB.DGO",
|
||||
"DGO/COB.DGO",
|
||||
"DGO/LBOMBBOT.DGO",
|
||||
"DGO/DEMO.DGO",
|
||||
"DGO/LRACEDF.DGO",
|
||||
"DGO/LERLCHAL.DGO",
|
||||
"DGO/LHIPOUT.DGO",
|
||||
"DGO/OUTROCST.DGO",
|
||||
"DGO/NES.DGO",
|
||||
"DGO/PAR.DGO",
|
||||
"DGO/LERBRNGD.DGO",
|
||||
"DGO/MTX.DGO",
|
||||
"DGO/FDA.DGO",
|
||||
"DGO/LKEIRIFT.DGO",
|
||||
"DGO/LWHACK.DGO",
|
||||
"DGO/LJKDXASH.DGO",
|
||||
"DGO/CAS.DGO",
|
||||
"DGO/COA.DGO",
|
||||
"DGO/LTESS.DGO",
|
||||
"DGO/CFA.DGO",
|
||||
"DGO/TOMBEXT.DGO",
|
||||
"DGO/LCGUARD.DGO",
|
||||
"DGO/TOE.DGO",
|
||||
"DGO/PALBOSS.DGO",
|
||||
"DGO/FRB.DGO",
|
||||
"DGO/PAE.DGO",
|
||||
"DGO/TITLE.DGO",
|
||||
"DGO/FORDUMPD.DGO",
|
||||
"DGO/D3A.DGO",
|
||||
"DGO/DRILLMTN.DGO",
|
||||
"DGO/PAC.DGO",
|
||||
"DGO/LTENTOB.DGO",
|
||||
"DGO/LRACEBF.DGO",
|
||||
"DGO/LPROTECT.DGO",
|
||||
"DGO/FEA.DGO",
|
||||
"DGO/ONINTENT.DGO",
|
||||
"DGO/STA.DGO",
|
||||
"DGO/CGC.DGO",
|
||||
"DGO/CMA.DGO",
|
||||
"DGO/FDB.DGO",
|
||||
"DGO/SKA.DGO",
|
||||
"DGO/LTRNKRKD.DGO",
|
||||
"DGO/CIA.DGO",
|
||||
"DGO/TOB.DGO",
|
||||
"DGO/LRACEDB.DGO",
|
||||
"DGO/LDJAKBRN.DGO",
|
||||
"DGO/TOA.DGO",
|
||||
"DGO/STADBLMP.DGO",
|
||||
"DGO/UND.DGO",
|
||||
"DGO/LYSKDCD.DGO",
|
||||
"DGO/HALFPIPE.DGO",
|
||||
"DGO/LSAMERGD.DGO",
|
||||
"DGO/PAS.DGO",
|
||||
"DGO/LBBUSH.DGO",
|
||||
"DGO/LPACKAGE.DGO",
|
||||
"DGO/LINTCSTB.DGO",
|
||||
"DGO/LPORTRUN.DGO",
|
||||
"DGO/LASHGRD.DGO",
|
||||
"DGO/CGB.DGO",
|
||||
"DGO/D3B.DGO",
|
||||
"DGO/STB.DGO",
|
||||
"DGO/GARAGE.DGO",
|
||||
"DGO/PORTWALL.DGO",
|
||||
"DGO/LHELLDOG.DGO",
|
||||
"DGO/SWE.DGO",
|
||||
"DGO/LRACECB.DGO",
|
||||
"DGO/GGA.DGO",
|
||||
"DGO/TOD.DGO",
|
||||
"DGO/MCN.DGO",
|
||||
"DGO/SEW.DGO",
|
||||
"DGO/VIN.DGO",
|
||||
"DGO/CGA.DGO",
|
||||
"DGO/CMB.DGO",
|
||||
"DGO/LGUARD.DGO",
|
||||
"DGO/CPA.DGO",
|
||||
"DGO/LCITYLOW.DGO",
|
||||
"DGO/LTENTOUT.DGO",
|
||||
"DGO/UNB.DGO",
|
||||
"DGO/CPO.DGO",
|
||||
"DGO/CAP.DGO",
|
||||
"DGO/CWI.DGO",
|
||||
"DGO/CTYKORA.DGO",
|
||||
"DGO/RUI.DGO",
|
||||
"DGO/LSACK.DGO",
|
||||
"DGO/CTYASHA.DGO",
|
||||
"DGO/LPRTRACE.DGO",
|
||||
"DGO/LWIDEA.DGO",
|
||||
"DGO/HIPHOG.DGO",
|
||||
"DGO/LSMYSBRT.DGO",
|
||||
"DGO/LRACEBB.DGO",
|
||||
"DGO/CASCITY.DGO",
|
||||
"DGO/LYSAMSAM.DGO",
|
||||
"DGO/VI1.DGO"*/
|
||||
],
|
||||
"dgo_names": [
|
||||
"./CGO/ART.CGO",
|
||||
"./CGO/KERNEL.CGO",
|
||||
"./CGO/ENGINE.CGO",
|
||||
"./CGO/GAME.CGO",
|
||||
"./CGO/COMMON.CGO",
|
||||
"./DGO/LWIDEB.DGO",
|
||||
"./DGO/LMEETBRT.DGO",
|
||||
"./DGO/CTA.DGO",
|
||||
"./DGO/PALOUT.DGO",
|
||||
"./DGO/STD.DGO",
|
||||
"./DGO/FOR.DGO",
|
||||
"./DGO/CASEXT.DGO",
|
||||
"./DGO/HIDEOUT.DGO",
|
||||
"./DGO/LWIDESTA.DGO",
|
||||
"./DGO/LRACELIT.DGO",
|
||||
"./DGO/CTB.DGO",
|
||||
"./DGO/KIOSK.DGO",
|
||||
"./DGO/DG1.DGO",
|
||||
"./DGO/FEB.DGO",
|
||||
"./DGO/DMI.DGO",
|
||||
"./DGO/ORACLE.DGO",
|
||||
"./DGO/LERLTESS.DGO",
|
||||
"./DGO/DRI.DGO",
|
||||
"./DGO/LBRNERMK.DGO",
|
||||
"./DGO/LRACECF.DGO",
|
||||
"./DGO/CTC.DGO",
|
||||
"./DGO/LTHRNOUT.DGO",
|
||||
"./DGO/FRA.DGO",
|
||||
"./DGO/LGARCSTA.DGO",
|
||||
"./DGO/MTN.DGO",
|
||||
"./DGO/INTROCST.DGO",
|
||||
"./DGO/DRB.DGO",
|
||||
"./DGO/ATE.DGO",
|
||||
"./DGO/LERROL.DGO",
|
||||
"./DGO/LTRNYSAM.DGO",
|
||||
"./DGO/LOUTCSTB.DGO",
|
||||
"./DGO/LASHTHRN.DGO",
|
||||
"./DGO/TOC.DGO",
|
||||
"./DGO/CFB.DGO",
|
||||
"./DGO/CAB.DGO",
|
||||
"./DGO/STC.DGO",
|
||||
"./DGO/STR.DGO",
|
||||
"./DGO/ATO.DGO",
|
||||
"./DGO/SEB.DGO",
|
||||
"./DGO/LPRSNCST.DGO",
|
||||
"./DGO/SWB.DGO",
|
||||
"./DGO/LPOWER.DGO",
|
||||
"./DGO/FOB.DGO",
|
||||
"./DGO/CIB.DGO",
|
||||
"./DGO/LSHUTTLE.DGO",
|
||||
"./DGO/LJAKDAX.DGO",
|
||||
"./DGO/FORDUMPC.DGO",
|
||||
"./DGO/LTRNTESS.DGO",
|
||||
"./DGO/TBO.DGO",
|
||||
"./DGO/THR.DGO",
|
||||
"./DGO/PRI.DGO",
|
||||
"./DGO/LKIDDOGE.DGO",
|
||||
"./DGO/NESTT.DGO",
|
||||
"./DGO/LWIDEC.DGO",
|
||||
"./DGO/SAG.DGO",
|
||||
"./DGO/NEB.DGO",
|
||||
"./DGO/COB.DGO",
|
||||
"./DGO/LBOMBBOT.DGO",
|
||||
"./DGO/DEMO.DGO",
|
||||
"./DGO/LRACEDF.DGO",
|
||||
"./DGO/LERLCHAL.DGO",
|
||||
"./DGO/LHIPOUT.DGO",
|
||||
"./DGO/OUTROCST.DGO",
|
||||
"./DGO/NES.DGO",
|
||||
"./DGO/PAR.DGO",
|
||||
"./DGO/LERBRNGD.DGO",
|
||||
"./DGO/MTX.DGO",
|
||||
"./DGO/FDA.DGO",
|
||||
"./DGO/LKEIRIFT.DGO",
|
||||
"./DGO/LWHACK.DGO",
|
||||
"./DGO/LJKDXASH.DGO",
|
||||
"./DGO/CAS.DGO",
|
||||
"./DGO/COA.DGO",
|
||||
"./DGO/LTESS.DGO",
|
||||
"./DGO/CFA.DGO",
|
||||
"./DGO/TOMBEXT.DGO",
|
||||
"./DGO/LCGUARD.DGO",
|
||||
"./DGO/TOE.DGO",
|
||||
"./DGO/PALBOSS.DGO",
|
||||
"./DGO/FRB.DGO",
|
||||
"./DGO/PAE.DGO",
|
||||
"./DGO/TITLE.DGO",
|
||||
"./DGO/FORDUMPD.DGO",
|
||||
"./DGO/D3A.DGO",
|
||||
"./DGO/DRILLMTN.DGO",
|
||||
"./DGO/PAC.DGO",
|
||||
"./DGO/LTENTOB.DGO",
|
||||
"./DGO/LRACEBF.DGO",
|
||||
"./DGO/LPROTECT.DGO",
|
||||
"./DGO/FEA.DGO",
|
||||
"./DGO/ONINTENT.DGO",
|
||||
"./DGO/STA.DGO",
|
||||
"./DGO/CGC.DGO",
|
||||
"./DGO/CMA.DGO",
|
||||
"./DGO/FDB.DGO",
|
||||
"./DGO/SKA.DGO",
|
||||
"./DGO/LTRNKRKD.DGO",
|
||||
"./DGO/CIA.DGO",
|
||||
"./DGO/TOB.DGO",
|
||||
"./DGO/LRACEDB.DGO",
|
||||
"./DGO/LDJAKBRN.DGO",
|
||||
"./DGO/TOA.DGO",
|
||||
"./DGO/STADBLMP.DGO",
|
||||
"./DGO/UND.DGO",
|
||||
"./DGO/LYSKDCD.DGO",
|
||||
"./DGO/HALFPIPE.DGO",
|
||||
"./DGO/LSAMERGD.DGO",
|
||||
"./DGO/PAS.DGO",
|
||||
"./DGO/LBBUSH.DGO",
|
||||
"./DGO/LPACKAGE.DGO",
|
||||
"./DGO/LINTCSTB.DGO",
|
||||
"./DGO/LPORTRUN.DGO",
|
||||
"./DGO/LASHGRD.DGO",
|
||||
"./DGO/CGB.DGO",
|
||||
"./DGO/D3B.DGO",
|
||||
"./DGO/STB.DGO",
|
||||
"./DGO/GARAGE.DGO",
|
||||
"./DGO/PORTWALL.DGO",
|
||||
"./DGO/LHELLDOG.DGO",
|
||||
"./DGO/SWE.DGO",
|
||||
"./DGO/LRACECB.DGO",
|
||||
"./DGO/GGA.DGO",
|
||||
"./DGO/TOD.DGO",
|
||||
"./DGO/MCN.DGO",
|
||||
"./DGO/SEW.DGO",
|
||||
"./DGO/VIN.DGO",
|
||||
"./DGO/CGA.DGO",
|
||||
"./DGO/CMB.DGO",
|
||||
"./DGO/LGUARD.DGO",
|
||||
"./DGO/CPA.DGO",
|
||||
"./DGO/LCITYLOW.DGO",
|
||||
"./DGO/LTENTOUT.DGO",
|
||||
"./DGO/UNB.DGO",
|
||||
"./DGO/CPO.DGO",
|
||||
"./DGO/CAP.DGO",
|
||||
"./DGO/CWI.DGO",
|
||||
"./DGO/CTYKORA.DGO",
|
||||
"./DGO/RUI.DGO",
|
||||
"./DGO/LSACK.DGO",
|
||||
"./DGO/CTYASHA.DGO",
|
||||
"./DGO/LPRTRACE.DGO",
|
||||
"./DGO/LWIDEA.DGO",
|
||||
"./DGO/HIPHOG.DGO",
|
||||
"./DGO/LSMYSBRT.DGO",
|
||||
"./DGO/LRACEBB.DGO",
|
||||
"./DGO/CASCITY.DGO",
|
||||
"./DGO/LYSAMSAM.DGO",
|
||||
"./DGO/VI1.DGO"
|
||||
],
|
||||
|
||||
// some objects are part of STR files (streaming data). In Jak 1 this is just animations
|
||||
// some objects are part of STR files (streaming data).
|
||||
"str_file_names": [
|
||||
],
|
||||
|
||||
@@ -177,11 +177,13 @@
|
||||
"TEXT/5COMMON.TXT",
|
||||
"TEXT/6COMMON.TXT",
|
||||
"TEXT/7COMMON.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", "VAGWAD.JAP"]
|
||||
"streamed_audio_file_names": [],
|
||||
|
||||
"levels_to_extract": []
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +1,4 @@
|
||||
{
|
||||
"(method 2 array)":[
|
||||
[23, "gp", "(array int32)"],
|
||||
[43, "gp", "(array uint32)"],
|
||||
[63, "gp", "(array int64)"],
|
||||
[83, "gp", "(array uint64)"],
|
||||
[102, "gp", "(array int8)"],
|
||||
[121, "gp", "(array uint8)"],
|
||||
[141, "gp", "(array int16)"],
|
||||
[161, "gp", "(array uint16)"],
|
||||
[185, "gp", "(array uint128)"],
|
||||
[203, "gp", "(array int32)"],
|
||||
[222, "gp", "(array float)"],
|
||||
[231, "gp", "(array float)"],
|
||||
[248, "gp", "(array basic)"],
|
||||
[257, "gp", "(array basic)"]
|
||||
],
|
||||
|
||||
"(method 3 array)":[
|
||||
[44, "gp", "(array int32)"],
|
||||
[62, "gp", "(array uint32)"],
|
||||
[80, "gp", "(array int64)"],
|
||||
[98, "gp", "(array uint64)"],
|
||||
[115, "gp", "(array int8)"],
|
||||
[132, "gp", "(array int8)"], // bug in game
|
||||
[150, "gp", "(array int16)"],
|
||||
[168, "gp", "(array uint16)"],
|
||||
[190, "gp", "(array uint128)"],
|
||||
[203, "gp", "(array int32)"],
|
||||
[225, "gp", "(array float)"],
|
||||
[242, "gp", "(array basic)"]
|
||||
],
|
||||
|
||||
"(method 2 handle)":[
|
||||
[10, "a3", "process"],
|
||||
[11, "v1", "int"],
|
||||
[15, "gp", "int"]
|
||||
],
|
||||
|
||||
"(method 3 handle)":[
|
||||
[10, "gp", "int"]
|
||||
],
|
||||
|
||||
"(method 0 cpu-thread)":[
|
||||
[13, "v0", "cpu-thread"]
|
||||
],
|
||||
|
||||
"(method 0 dead-pool-heap)":[
|
||||
[60, "v0", "int"], // a lie, actually the 115 is an align16 constant propagated on addr of heap start.
|
||||
[61, "v0", "dead-pool-heap"]
|
||||
],
|
||||
|
||||
"(method 21 dead-pool-heap)":[
|
||||
[5, "v1", "pointer"],
|
||||
[13, "a0", "pointer"],
|
||||
[25, "v1", "pointer"]
|
||||
],
|
||||
|
||||
"(method 5 dead-pool-heap)":[
|
||||
[3, "v1", "int"],
|
||||
[3, "a0", "int"]
|
||||
],
|
||||
|
||||
"remove-exit":[
|
||||
[0, "s6", "process"]
|
||||
],
|
||||
|
||||
"(method 0 process)":[
|
||||
[12, "a0", "int"],
|
||||
[13, "v0", "process"]
|
||||
],
|
||||
|
||||
"inspect-process-heap":[
|
||||
[4, "s5", "basic"],
|
||||
[17, "s5", "int"]
|
||||
],
|
||||
|
||||
"return-from-thread-dead":[
|
||||
[0, "s6", "process"]
|
||||
],
|
||||
|
||||
"(method 14 dead-pool)":[
|
||||
[23, "v1", "process"], // bad visit order with #f?
|
||||
[28, "s4", "(pointer process-tree)"] // bug in real game, see gkernel.gc
|
||||
],
|
||||
|
||||
"throw":[
|
||||
[20, "s4", "protect-frame"] // type case
|
||||
],
|
||||
|
||||
"(method 0 protect-frame)":[
|
||||
[0, "a0", "int"],
|
||||
[1, "v0", "protect-frame"]
|
||||
],
|
||||
|
||||
"(method 9 process)":[
|
||||
[43, "s5", "process"]
|
||||
],
|
||||
|
||||
"(method 10 process)":[
|
||||
[24, "s4", "protect-frame"]
|
||||
],
|
||||
|
||||
"enter-state":[
|
||||
[67, "s0", "protect-frame"]
|
||||
],
|
||||
|
||||
"name=":[
|
||||
[24, "a1", "symbol"],
|
||||
[39, "a0", "symbol"]
|
||||
],
|
||||
|
||||
"placeholder-do-not-add-below": []
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
"game_version": 2,
|
||||
"text_version": 20,
|
||||
|
||||
"game_name": "jak2",
|
||||
"expected_elf_name": "SCUS_972.65",
|
||||
|
||||
// if you want to filter to only some object names.
|
||||
// it will make the decompiler much faster.
|
||||
"allowed_objects": [],
|
||||
@@ -13,7 +16,7 @@
|
||||
|
||||
// set to true to generate plain .asm files with MIPS disassembly, with no fancy decompilation.
|
||||
// this is fast and should succeed 100% of the time.
|
||||
"disassemble_code": false,
|
||||
"disassemble_code": true,
|
||||
|
||||
// Run the decompiler
|
||||
"decompile_code": false,
|
||||
@@ -32,7 +35,9 @@
|
||||
// unpack game text to assets folder
|
||||
"process_game_text": true,
|
||||
// unpack game count to assets folder
|
||||
"process_game_count": false,
|
||||
"process_game_count": true,
|
||||
// write goal imports for art groups
|
||||
"process_art_groups": true,
|
||||
|
||||
///////////////////////////
|
||||
// WEIRD OPTIONS
|
||||
@@ -40,9 +45,6 @@
|
||||
|
||||
// these options are used rarely and should usually be left at false
|
||||
|
||||
// output a file type_defs.gc which is used for the types part of all-types.gc
|
||||
"regenerate_all_types": false,
|
||||
|
||||
// generate the symbol_map.json file.
|
||||
// this is a guess at where each symbol is first defined/used.
|
||||
"generate_symbol_definition_map": false,
|
||||
@@ -75,15 +77,24 @@
|
||||
"stack_structures_file": "decompiler/config/jak2/stack_structures.jsonc",
|
||||
"hacks_file": "decompiler/config/jak2/hacks.jsonc",
|
||||
"inputs_file": "decompiler/config/jak2/inputs.jsonc",
|
||||
"art_info_file": "decompiler/config/jak2/art_info.jsonc",
|
||||
"import_deps_file": "decompiler/config/jak2/import_deps.jsonc",
|
||||
"all_types_file": "decompiler/config/all-types2.gc",
|
||||
|
||||
|
||||
// optional: a predetermined object file name map from a file.
|
||||
// this will make decompilation naming consistent even if you only run on some objects.
|
||||
"obj_file_name_map_file": "",//"goal_src/build/all_objs.json",
|
||||
// "obj_file_name_map_file": "goal_src2/build/all_objs.json",
|
||||
|
||||
////////////////////////////
|
||||
// LEVEL EXTRACTION
|
||||
////////////////////////////
|
||||
|
||||
"levels_to_extract":[
|
||||
]
|
||||
// turn this on to extract level background graphics data
|
||||
"levels_extract": false,
|
||||
// turn this on if you want extracted levels to be saved out as .obj files
|
||||
"levels_convert_to_obj": false,
|
||||
// should we extract collision meshes?
|
||||
// these can be displayed in game, but makes the .fr3 files slightly larger
|
||||
"extract_collision": true
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ TexturePage read_texture_page(ObjectFileData& data,
|
||||
tpage.info_label = get_label(data, words.at(offset));
|
||||
tpage.info = read_file_info(data, words, label_to_word_offset(tpage.info_label, true));
|
||||
ASSERT(tpage.info.file_type == "texture-page");
|
||||
ASSERT(tpage.info.major_version == versions::TX_PAGE_VERSION);
|
||||
ASSERT(tpage.info.major_version == versions::jak1::TX_PAGE_VERSION);
|
||||
ASSERT(tpage.info.minor_version == 0);
|
||||
ASSERT(tpage.info.maya_file_name == "Unknown");
|
||||
ASSERT(tpage.info.mdb_file_name == 0);
|
||||
|
||||
@@ -278,7 +278,7 @@ char* DecodeFileName(const char* name) {
|
||||
* PC PORT NOTE : Changed some paths so that they work for us (namely, got rid of 'host')
|
||||
*/
|
||||
char* MakeFileName(int type, const char* name, int new_string) {
|
||||
using namespace versions;
|
||||
using namespace versions::jak1;
|
||||
// start with network filesystem
|
||||
// kstrcpy(buffer_633, "host:");
|
||||
kstrcpy(buffer_633, "");
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
(string 80)
|
||||
(array 81)
|
||||
(sprite 82)
|
||||
;;
|
||||
;;
|
||||
(debug-dma 84) ;; maybe
|
||||
(sky-dma 85) ;; maybe
|
||||
;;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
;; Some example uses:
|
||||
;; - a "foreground-engine" has connections to all foreground objects that need to be drawn on each frame.
|
||||
;; - when a process wants to change a game setting, it opens a connection to the settings engine to request a change.
|
||||
;; when the process is killed, the setting change is reverted.
|
||||
;; when the process is killed (or it stops requesting the change), the setting change is reverted.
|
||||
|
||||
;; A "connection" is really just a function that gets called when the engine runs, or a set of parameters that the engine can iterate through.
|
||||
|
||||
@@ -53,9 +53,8 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; this is the actual data for the connection.
|
||||
;; it may be used in multiple ways, but it appears like
|
||||
;; the first param0 is a function that receives
|
||||
;; the three other params as arguments, plus the engine it is connect to as a 4th.
|
||||
;; it may be used in multiple ways, but the most common is to use param0 as a function
|
||||
;; it receives param1, param2, param3, and the engine as the arugmetns.
|
||||
;; in some cases, the return value is checked for 'dead.
|
||||
|
||||
(declare-type engine basic)
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
(light-yellow 32)
|
||||
(red-orange 33)
|
||||
(another-orange-red 34)
|
||||
|
||||
|
||||
(red 3)
|
||||
(red2 4)
|
||||
(yellow 5)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
(defun get-current-time ()
|
||||
"Get the in game time. This advances when the game is unpaused.
|
||||
This increase at the same rate for PAL/NTSC and if the game is lagging."
|
||||
This increases at the same rate for PAL/NTSC and if the game is lagging."
|
||||
(-> *display* base-frame-counter)
|
||||
)
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
(defmethod set-time-ratios display ((obj display) (slowdown float))
|
||||
"Set the time ratios for the current game speed. For example, set slowdown = 1.0 if the game
|
||||
is running at full speed or slowdown = 2.0 if the game is running at half speed."
|
||||
|
||||
|
||||
;; don't allow slowdowns of more than 4x. This prevents the dt's in the physics
|
||||
;; calculations from getting huge.
|
||||
(let ((ratio (fmin 4.0 slowdown)))
|
||||
(set! (-> obj time-ratio) ratio)
|
||||
(case (get-video-mode)
|
||||
(case (get-video-mode)
|
||||
(('pal)
|
||||
(set! (-> obj time-adjust-ratio) (* 1.2 ratio))
|
||||
(set! (-> obj seconds-per-frame) (* 0.02 ratio))
|
||||
@@ -76,7 +76,7 @@
|
||||
fpb: the framebuffer."
|
||||
|
||||
;; these will eventually be consumed by a sony function. I think it just sets GS registers.
|
||||
|
||||
|
||||
;; set these to the mode that makes the GS actually work. Basically every game uses exactly this.
|
||||
(set! (-> env pmode)
|
||||
(new 'static 'gs-pmode :en1 #x1 :mmod #x1 :slbg #x1 :alp #xff)
|
||||
@@ -243,7 +243,8 @@
|
||||
(set! (-> disp integral-frame-counter) (seconds 1000))
|
||||
(set! (-> disp real-integral-frame-counter) (seconds 1000))
|
||||
|
||||
;; and the "old" version, which I think was their value on the last... frame?
|
||||
;; and fake the "old" versions. These are normally set to the value on the previous frame
|
||||
;; (which may jump due to saving/loading or lag)
|
||||
(set! (-> disp old-base-frame-counter) (+ (-> disp base-frame-counter) -1))
|
||||
(set! (-> disp old-game-frame-counter) (+ (-> disp game-frame-counter) -1))
|
||||
(set! (-> disp old-real-frame-counter) (+ (-> disp real-frame-counter) -1))
|
||||
@@ -458,7 +459,7 @@
|
||||
|
||||
(defun draw-sprite2d-xy ((buf dma-buffer) (x int) (y int) (w int) (h int) (color rgba))
|
||||
"Draw a sprite primitive with the given color and dimensions."
|
||||
|
||||
|
||||
;; create context and clip dimensions.
|
||||
(let* ((context (new 'stack 'draw-context x y w h color))
|
||||
(draw-x (max 1792 (min 2304 (+ (-> context orgx) 1792))))
|
||||
@@ -473,14 +474,14 @@
|
||||
;; remember the address of the first dma-tag
|
||||
)
|
||||
(with-cnt-vif-block (buf)
|
||||
|
||||
|
||||
(dma-buffer-add-gif-tag buf (new 'static 'gif-tag64 :nloop 1 :eop 1 :flg (gif-flag reg-list) :nreg 4)
|
||||
(gs-reg-list prim rgbaq xyzf2 xyzf2)
|
||||
)
|
||||
(dma-buffer-add-uint64 buf (new 'static 'gs-prim :prim (gs-prim-type sprite) :abe 1)
|
||||
(-> context color 0)
|
||||
(new 'static 'gs-xyzf :x (* draw-x 16) :y (* draw-y 16) :z #x3fffff)
|
||||
(new 'static 'gs-xyzf :x (* (minmax (+ draw-x draw-w) 1792 2304) 16)
|
||||
(new 'static 'gs-xyzf :x (* (minmax (+ draw-x draw-w) 1792 2304) 16)
|
||||
:y (* (minmax (+ draw-y draw-h) (-> *video-parms* screen-miny) (-> *video-parms* screen-maxy)) 16) :z #x3fffff)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
(beach-level-name #x221)
|
||||
(jungle-level-name #x222)
|
||||
(misty-level-name #x223)
|
||||
|
||||
|
||||
(jungleb-level-name #x225)
|
||||
|
||||
(beach-seagull-get #x22e)
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
constexpr GameVersion kGameVersion = GameVersion::Jak1;
|
||||
|
||||
/*!
|
||||
* Get the level data from a DGO File.
|
||||
* Will ignore all the other things in the level DGO and just return the bsp file.
|
||||
@@ -28,7 +30,8 @@ decompiler::LinkedObjectFile load_bsp_from_dgo(const std::string& file_name,
|
||||
fmt::print("Using level file: {}, size {} kB\n", level_file.internal_name,
|
||||
level_file.data.size() / 1024);
|
||||
|
||||
return decompiler::to_linked_object_file(level_file.data, level_file.internal_name, dts, 1);
|
||||
return decompiler::to_linked_object_file(level_file.data, level_file.internal_name, dts,
|
||||
kGameVersion);
|
||||
}
|
||||
|
||||
bool is_valid_bsp(const decompiler::LinkedObjectFile& file) {
|
||||
|
||||
Reference in New Issue
Block a user