mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 06:54:31 -04:00
d3cc739e43
This attempts to get into master whatever work was done in this PR / it's earlier PR https://github.com/open-goal/jak-project/pull/3965 I don't want this work to be lost / floating around in massive PRs. However the changes are: - switch to ntsc_v1 instead of PAL as the development target, as we have done for all other games - remove most of the copied-from-jak2/3 changes as they need to be confirmed during the decompilation process not just assumed - avoids committing any changes to `game/kernel/common` as it was not clear to me if these were changes made in jak x's kernel that were not properly broken out into it's own functions. We don't want to accidentally introduce bugs into jak1-3's kernel code. - in other words, if the change in the kernel only happens in jak x...it should likely be specific to jak x's kernel, not common. --------- Co-authored-by: VodBox <dillon@vodbox.io> Co-authored-by: yodah <greenboyyodah@gmail.com>
968 lines
35 KiB
C++
968 lines
35 KiB
C++
#include "sparticle_decompile.h"
|
|
|
|
#include "common/goos/PrettyPrinter.h"
|
|
#include "common/util/Assert.h"
|
|
#include "common/util/print_float.h"
|
|
|
|
#include "decompiler/util/data_decompile.h"
|
|
|
|
#include "fmt/format.h"
|
|
|
|
namespace decompiler {
|
|
// sparticle fields.
|
|
// should match the enum in the game.
|
|
enum class FieldId {
|
|
MISC_FIELDS_START = 0,
|
|
SPT_TEXTURE = 1,
|
|
SPT_ANIM = 2,
|
|
SPT_ANIM_SPEED = 3,
|
|
SPT_BIRTH_FUNC = 4,
|
|
SPT_JOINT_REFPOINT = 5,
|
|
SPT_NUM = 6,
|
|
SPT_SOUND = 7,
|
|
MISC_FIELDS_END = 8,
|
|
SPRITE_FIELDS_START = 9,
|
|
SPT_X = 10,
|
|
SPT_Y = 11,
|
|
SPT_Z = 12,
|
|
SPT_SCALE_X = 13,
|
|
SPT_ROT_X = 14,
|
|
SPT_ROT_Y = 15,
|
|
SPT_ROT_Z = 16,
|
|
SPT_SCALE_Y = 17,
|
|
SPT_R = 18,
|
|
SPT_G = 19,
|
|
SPT_B = 20,
|
|
SPT_A = 21,
|
|
SPRITE_FIELDS_END = 22,
|
|
CPU_FIELDS_START = 23,
|
|
SPT_OMEGA = 24,
|
|
SPT_VEL_X = 25,
|
|
SPT_VEL_Y = 26,
|
|
SPT_VEL_Z = 27,
|
|
SPT_SCALEVEL_X = 28,
|
|
SPT_ROTVEL_X = 29,
|
|
SPT_ROTVEL_Y = 30,
|
|
SPT_ROTVEL_Z = 31,
|
|
SPT_SCALEVEL_Y = 32,
|
|
SPT_FADE_R = 33,
|
|
SPT_FADE_G = 34,
|
|
SPT_FADE_B = 35,
|
|
SPT_FADE_A = 36,
|
|
SPT_ACCEL_X = 37,
|
|
SPT_ACCEL_Y = 38,
|
|
SPT_ACCEL_Z = 39,
|
|
SPT_DUMMY = 40,
|
|
SPT_QUAT_X = 41,
|
|
SPT_QUAT_Y = 42,
|
|
SPT_QUAT_Z = 43,
|
|
SPT_QUAD_W = 44,
|
|
SPT_FRICTION = 45,
|
|
SPT_TIMER = 46,
|
|
SPT_FLAGS = 47,
|
|
SPT_USERDATA = 48,
|
|
SPT_FUNC = 49,
|
|
SPT_NEXT_TIME = 50,
|
|
SPT_NEXT_LAUNCHER = 51,
|
|
CPU_FIELDS_END = 52,
|
|
LAUNCH_FIELDS_START = 53,
|
|
SPT_LAUNCHROT_X = 54,
|
|
SPT_LAUNCHROT_Y = 55,
|
|
SPT_LAUNCHROT_Z = 56,
|
|
SPT_LAUNCHROT_W = 57,
|
|
SPT_CONEROT_X = 58,
|
|
SPT_CONEROT_Y = 59,
|
|
SPT_CONEROT_Z = 60,
|
|
SPT_CONEROT_W = 61,
|
|
SPT_CONEROT_RADIUS = 62,
|
|
SPT_ROTATE_Y = 63,
|
|
LAUNCH_FIELDS_END = 64,
|
|
SPT_SCALE = 65,
|
|
SPT_SCALEVEL = 66,
|
|
SPT_END = 67,
|
|
};
|
|
|
|
// jak2 version
|
|
enum class FieldId2 {
|
|
MISC_FIELDS_START = 0,
|
|
SPT_TEXTURE = 1,
|
|
SPT_ANIM = 2,
|
|
SPT_ANIM_SPEED = 3,
|
|
SPT_BIRTH_FUNC = 4,
|
|
SPT_JOINT_REFPOINT = 5,
|
|
SPT_NUM = 6,
|
|
SPT_SOUND = 7,
|
|
MISC_FIELDS_END = 8,
|
|
SPRITE_FIELDS_START = 9,
|
|
SPT_X = 10,
|
|
SPT_Y = 11,
|
|
SPT_Z = 12,
|
|
SPT_SCALE_X = 13,
|
|
SPT_ROT_X = 14,
|
|
SPT_ROT_Y = 15,
|
|
SPT_ROT_Z = 16,
|
|
SPT_SCALE_Y = 17,
|
|
SPT_R = 18,
|
|
SPT_G = 19,
|
|
SPT_B = 20,
|
|
SPT_A = 21,
|
|
SPRITE_FIELDS_END = 22,
|
|
CPU_FIELDS_START = 23,
|
|
SPT_OMEGA = 24,
|
|
SPT_VEL_X = 25,
|
|
SPT_VEL_Y = 26,
|
|
SPT_VEL_Z = 27,
|
|
SPT_SCALEVEL_X = 28,
|
|
SPT_ROTVEL_X = 29,
|
|
SPT_ROTVEL_Y = 30,
|
|
SPT_ROTVEL_Z = 31,
|
|
SPT_SCALEVEL_Y = 32,
|
|
SPT_FADE_R = 33,
|
|
SPT_FADE_G = 34,
|
|
SPT_FADE_B = 35,
|
|
SPT_FADE_A = 36,
|
|
SPT_ACCEL_X = 37,
|
|
SPT_ACCEL_Y = 38,
|
|
SPT_ACCEL_Z = 39,
|
|
SPT_DUMMY = 40,
|
|
SPT_QUAT_X = 41,
|
|
SPT_QUAT_Y = 42,
|
|
SPT_QUAT_Z = 43,
|
|
SPT_QUAD_W = 44,
|
|
SPT_FRICTION = 45,
|
|
SPT_TIMER = 46,
|
|
SPT_FLAGS = 47,
|
|
SPT_USERDATA = 48,
|
|
SPT_FUNC = 49,
|
|
SPT_NEXT_TIME = 50,
|
|
SPT_NEXT_LAUNCHER = 51,
|
|
CPU_FIELDS_END = 52,
|
|
LAUNCH_FIELDS_START = 53,
|
|
SPT_LAUNCHROT_X = 54,
|
|
SPT_LAUNCHROT_Y = 55,
|
|
SPT_LAUNCHROT_Z = 56,
|
|
SPT_LAUNCHROT_W = 57,
|
|
SPT_CONEROT_X = 58,
|
|
SPT_CONEROT_Y = 59,
|
|
SPT_CONEROT_Z = 60,
|
|
SPT_CONEROT_W = 61,
|
|
SPT_ROTATE_X = 62,
|
|
SPT_ROTATE_Y = 63,
|
|
SPT_ROTATE_Z = 64,
|
|
SPT_CONEROT_RADIUS = 65,
|
|
SPT_MAT_SCALE_X = 66,
|
|
SPT_MAT_SCALE_Y = 67,
|
|
SPT_MAT_SCALE_Z = 68,
|
|
LAUNCH_FIELDS_END = 69,
|
|
SPT_SCALE = 70,
|
|
SPT_SCALEVEL = 71,
|
|
SPT_END = 72,
|
|
};
|
|
|
|
// jakx version
|
|
enum class FieldIdX {
|
|
MISC_FIELDS_START = 0,
|
|
SPT_TEXTURE = 1,
|
|
SPT_ANIM = 2,
|
|
SPT_ANIM_SPEED = 3,
|
|
SPT_BIRTH_FUNC = 4,
|
|
SPT_JOINT_REFPOINT = 5,
|
|
SPT_NUM = 6,
|
|
MISC_FIELDS_END = 7,
|
|
SPRITE_FIELDS_START = 8,
|
|
SPT_X = 9,
|
|
SPT_Y = 10,
|
|
SPT_Z = 11,
|
|
SPT_SCALE_X = 12,
|
|
SPT_ROT_X = 13,
|
|
SPT_ROT_Y = 14,
|
|
SPT_ROT_Z = 15,
|
|
SPT_SCALE_Y = 16,
|
|
SPT_R = 17,
|
|
SPT_G = 18,
|
|
SPT_B = 19,
|
|
SPT_A = 20,
|
|
SPRITE_FIELDS_END = 21,
|
|
CPU_FIELDS_START = 22,
|
|
SPT_OMEGA = 23,
|
|
SPT_VEL_X = 24,
|
|
SPT_VEL_Y = 25,
|
|
SPT_VEL_Z = 26,
|
|
SPT_SCALEVEL_X = 27,
|
|
SPT_ROTVEL_X = 28,
|
|
SPT_ROTVEL_Y = 29,
|
|
SPT_ROTVEL_Z = 30,
|
|
SPT_SCALEVEL_Y = 31,
|
|
SPT_FADE_R = 32,
|
|
SPT_FADE_G = 33,
|
|
SPT_FADE_B = 34,
|
|
SPT_FADE_A = 35,
|
|
SPT_ACCEL_X = 36,
|
|
SPT_ACCEL_Y = 37,
|
|
SPT_ACCEL_Z = 38,
|
|
SPT_DUMMY = 39,
|
|
SPT_QUAT_X = 40,
|
|
SPT_QUAT_Y = 41,
|
|
SPT_QUAT_Z = 42,
|
|
SPT_QUAD_W = 43,
|
|
SPT_FRICTION = 44,
|
|
SPT_TIMER = 45,
|
|
SPT_FLAGS = 46,
|
|
SPT_USERDATA = 47,
|
|
SPT_FUNC = 48,
|
|
SPT_NEXT_TIME = 49,
|
|
SPT_NEXT_LAUNCHER = 50,
|
|
CPU_FIELDS_END = 51,
|
|
LAUNCH_FIELDS_START = 52,
|
|
SPT_LAUNCHROT_X = 53,
|
|
SPT_LAUNCHROT_Y = 54,
|
|
SPT_LAUNCHROT_Z = 55,
|
|
SPT_LAUNCHROT_W = 56,
|
|
SPT_CONEROT_X = 57,
|
|
SPT_CONEROT_Y = 58,
|
|
SPT_CONEROT_Z = 59,
|
|
SPT_CONEROT_W = 60,
|
|
SPT_ROTATE_X = 61,
|
|
SPT_ROTATE_Y = 62,
|
|
SPT_ROTATE_Z = 63,
|
|
SPT_CONEROT_RADIUS = 64,
|
|
SPT_MAT_SCALE_X = 65,
|
|
SPT_MAT_SCALE_Y = 66,
|
|
SPT_MAT_SCALE_Z = 67,
|
|
LAUNCH_FIELDS_END = 68,
|
|
SPT_SCALE = 69,
|
|
SPT_SCALEVEL = 70,
|
|
SPT_END = 71,
|
|
};
|
|
|
|
// NOTE : "per second" here means it's in 1/60th instead of the usual 1/300ths
|
|
constexpr bool allow_per_sec = false;
|
|
|
|
enum class FieldKind {
|
|
TEXTURE_ID,
|
|
INT,
|
|
SECONDS,
|
|
FLOAT,
|
|
FLOAT_PER_SEC,
|
|
METERS,
|
|
METERS_PER_SEC,
|
|
DEGREES,
|
|
DEGREES_PER_SEC,
|
|
CPUINFO_FLAGS,
|
|
END_FLAG,
|
|
LAUNCHER_BY_ID,
|
|
NO_FANCY_DECOMP,
|
|
FUNCTION,
|
|
USERDATA,
|
|
ROT_X,
|
|
SOUND_SPEC,
|
|
INVALID
|
|
};
|
|
|
|
struct SparticleFieldDecomp {
|
|
bool known = false; // error if we try to decomp one that isn't known
|
|
FieldKind kind = FieldKind::INVALID;
|
|
};
|
|
|
|
const SparticleFieldDecomp field_kind_jak1[68] = {
|
|
{false}, // MISC_FIELDS_START = 0
|
|
{true, FieldKind::TEXTURE_ID}, // SPT_TEXTURE = 1
|
|
{false}, // SPT_ANIM = 2
|
|
{false}, // SPT_ANIM_SPEED = 3
|
|
{true, FieldKind::FUNCTION}, // SPT_BIRTH_FUNC = 4
|
|
{false}, // SPT_JOINT/REFPOINT = 5
|
|
{true, FieldKind::FLOAT}, // SPT_NUM = 6
|
|
{true, FieldKind::SOUND_SPEC}, // SPT_SOUND = 7
|
|
{false}, // MISC_FIELDS_END = 8
|
|
{false}, // SPRITE_FIELDS_START = 9
|
|
{true, FieldKind::METERS}, // SPT_X = 10
|
|
{true, FieldKind::METERS}, // SPT_Y = 11
|
|
{true, FieldKind::METERS}, // SPT_Z = 12
|
|
{true, FieldKind::METERS}, // SPT_SCALE_X = 13
|
|
{true, FieldKind::ROT_X}, // SPT_ROT_X = 14
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Y = 15
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Z = 16
|
|
{true, FieldKind::METERS}, // SPT_SCALE_Y = 17
|
|
{true, FieldKind::FLOAT}, // SPT_R = 18
|
|
{true, FieldKind::FLOAT}, // SPT_G = 19
|
|
{true, FieldKind::FLOAT}, // SPT_B = 20
|
|
{true, FieldKind::FLOAT}, // SPT_A = 21
|
|
{false}, // SPRITE_FIELDS_END = 22
|
|
{false}, // CPU_FIELDS_START = 23
|
|
{true, FieldKind::FLOAT}, // SPT_OMEGA = 24
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_X = 25 (likely m/s)
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Y = 26
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Z = 27
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_X = 28
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_X = 29
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Y = 30
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Z = 31
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_Y = 32
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_R = 33
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_G = 34
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_B = 35
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_A = 36
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_X = 37
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Y = 38
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Z = 39
|
|
{false}, // SPT_DUMMY = 40
|
|
{false}, // SPT_QUAT_X = 41
|
|
{false}, // SPT_QUAT_Y = 42
|
|
{false}, // SPT_QUAT_Z = 43
|
|
{false}, // SPT_QUAD_W = 44
|
|
{true, FieldKind::FLOAT}, // SPT_FRICTION = 45
|
|
{true, FieldKind::SECONDS}, // SPT_TIMER = 46
|
|
{true, FieldKind::CPUINFO_FLAGS}, // SPT_FLAGS = 47
|
|
{true, FieldKind::USERDATA}, // SPT_USERDATA = 48
|
|
{true, FieldKind::FUNCTION}, // SPT_FUNC = 49
|
|
{true, FieldKind::SECONDS}, // SPT_NEXT_TIME = 50
|
|
{true, FieldKind::LAUNCHER_BY_ID}, // SPT_NEXT_LAUNCHER = 51
|
|
{false}, // CPU_FIELDS_END = 52
|
|
{false}, // LAUNCH_FIELDS_START = 53
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_X = 54
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Y = 55
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Z = 56
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_W = 57
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_X = 58
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Y = 59
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Z = 60
|
|
{false}, // SPT_CONEROT_W = 61
|
|
{true, FieldKind::METERS}, // SPT_CONEROT_RADIUS = 62
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_Y = 63
|
|
{false}, // LAUNCH_FIELDS_END = 64
|
|
{false}, // SPT_SCALE = 65
|
|
{false}, // SPT_SCALEVEL = 66
|
|
{true, FieldKind::END_FLAG} // SPT_END = 67
|
|
};
|
|
|
|
const SparticleFieldDecomp field_kind_jak2[73] = {
|
|
{false}, // MISC_FIELDS_START = 0
|
|
{true, FieldKind::TEXTURE_ID}, // SPT_TEXTURE = 1
|
|
{false}, // SPT_ANIM = 2
|
|
{false}, // SPT_ANIM_SPEED = 3
|
|
{true, FieldKind::FUNCTION}, // SPT_BIRTH_FUNC = 4
|
|
{false}, // SPT_JOINT/REFPOINT = 5
|
|
{true, FieldKind::FLOAT}, // SPT_NUM = 6
|
|
{true, FieldKind::SOUND_SPEC}, // SPT_SOUND = 7
|
|
{false}, // MISC_FIELDS_END = 8
|
|
{false}, // SPRITE_FIELDS_START = 9
|
|
{true, FieldKind::METERS}, // SPT_X = 10
|
|
{true, FieldKind::METERS}, // SPT_Y = 11
|
|
{true, FieldKind::METERS}, // SPT_Z = 12
|
|
{true, FieldKind::METERS}, // SPT_SCALE_X = 13
|
|
{true, FieldKind::ROT_X}, // SPT_ROT_X = 14
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Y = 15
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Z = 16
|
|
{true, FieldKind::METERS}, // SPT_SCALE_Y = 17
|
|
{true, FieldKind::FLOAT}, // SPT_R = 18
|
|
{true, FieldKind::FLOAT}, // SPT_G = 19
|
|
{true, FieldKind::FLOAT}, // SPT_B = 20
|
|
{true, FieldKind::FLOAT}, // SPT_A = 21
|
|
{false}, // SPRITE_FIELDS_END = 22
|
|
{false}, // CPU_FIELDS_START = 23
|
|
{true, FieldKind::DEGREES}, // SPT_OMEGA = 24
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_X = 25 (likely m/s)
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Y = 26
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Z = 27
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_X = 28
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_X = 29
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Y = 30
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Z = 31
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_Y = 32
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_R = 33
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_G = 34
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_B = 35
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_A = 36
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_X = 37
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Y = 38
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Z = 39
|
|
{false}, // SPT_DUMMY = 40
|
|
{false}, // SPT_QUAT_X = 41
|
|
{false}, // SPT_QUAT_Y = 42
|
|
{false}, // SPT_QUAT_Z = 43
|
|
{false}, // SPT_QUAD_W = 44
|
|
{true, FieldKind::FLOAT}, // SPT_FRICTION = 45
|
|
{true, FieldKind::SECONDS}, // SPT_TIMER = 46
|
|
{true, FieldKind::CPUINFO_FLAGS}, // SPT_FLAGS = 47
|
|
{true, FieldKind::USERDATA}, // SPT_USERDATA = 48
|
|
{true, FieldKind::FUNCTION}, // SPT_FUNC = 49
|
|
{true, FieldKind::SECONDS}, // SPT_NEXT_TIME = 50
|
|
{true, FieldKind::LAUNCHER_BY_ID}, // SPT_NEXT_LAUNCHER = 51
|
|
{false}, // CPU_FIELDS_END = 52
|
|
{false}, // LAUNCH_FIELDS_START = 53
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_X = 54
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Y = 55
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Z = 56
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_W = 57
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_X = 58
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Y = 59
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Z = 60
|
|
{false}, // SPT_CONEROT_W = 61
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_X = 62
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_Y = 63
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_Z = 64
|
|
{true, FieldKind::METERS}, // SPT_CONEROT_RADIUS = 65
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 66
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 67
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 68
|
|
{false}, // LAUNCH_FIELDS_END = 69
|
|
{false}, // SPT_SCALE = 70
|
|
{false}, // SPT_SCALEVEL = 71
|
|
{true, FieldKind::END_FLAG} // SPT_END = 72
|
|
};
|
|
|
|
const SparticleFieldDecomp field_kind_jakx[72] = {
|
|
{false}, // MISC_FIELDS_START = 0
|
|
{true, FieldKind::TEXTURE_ID}, // SPT_TEXTURE = 1
|
|
{false}, // SPT_ANIM = 2
|
|
{false}, // SPT_ANIM_SPEED = 3
|
|
{true, FieldKind::FUNCTION}, // SPT_BIRTH_FUNC = 4
|
|
{false}, // SPT_JOINT/REFPOINT = 5
|
|
{true, FieldKind::FLOAT}, // SPT_NUM = 6
|
|
{false}, // MISC_FIELDS_END = 7
|
|
{false}, // SPRITE_FIELDS_START = 8
|
|
{true, FieldKind::METERS}, // SPT_X = 9
|
|
{true, FieldKind::METERS}, // SPT_Y = 10
|
|
{true, FieldKind::METERS}, // SPT_Z = 11
|
|
{true, FieldKind::METERS}, // SPT_SCALE_X = 12
|
|
{true, FieldKind::ROT_X}, // SPT_ROT_X = 13
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Y = 14
|
|
{true, FieldKind::DEGREES}, // SPT_ROT_Z = 15
|
|
{true, FieldKind::METERS}, // SPT_SCALE_Y = 16
|
|
{true, FieldKind::FLOAT}, // SPT_R = 17
|
|
{true, FieldKind::FLOAT}, // SPT_G = 18
|
|
{true, FieldKind::FLOAT}, // SPT_B = 19
|
|
{true, FieldKind::FLOAT}, // SPT_A = 20
|
|
{false}, // SPRITE_FIELDS_END = 21
|
|
{false}, // CPU_FIELDS_START = 22
|
|
{true, FieldKind::DEGREES}, // SPT_OMEGA = 23
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_X = 24 (likely m/s)
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Y = 25
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_VEL_Z = 26
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_X = 27
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_X = 28
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Y = 29
|
|
{true, FieldKind::DEGREES_PER_SEC}, // SPT_ROTVEL_Z = 30
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_SCALEVEL_Y = 31
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_R = 32
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_G = 33
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_B = 34
|
|
{true, FieldKind::FLOAT_PER_SEC}, // SPT_FADE_A = 35
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_X = 36
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Y = 37
|
|
{true, FieldKind::METERS_PER_SEC}, // SPT_ACCEL_Z = 38
|
|
{false}, // SPT_DUMMY = 39
|
|
{false}, // SPT_QUAT_X = 40
|
|
{false}, // SPT_QUAT_Y = 41
|
|
{false}, // SPT_QUAT_Z = 42
|
|
{false}, // SPT_QUAD_W = 43
|
|
{true, FieldKind::FLOAT}, // SPT_FRICTION = 44
|
|
{true, FieldKind::SECONDS}, // SPT_TIMER = 45
|
|
{true, FieldKind::CPUINFO_FLAGS}, // SPT_FLAGS = 46
|
|
{true, FieldKind::USERDATA}, // SPT_USERDATA = 47
|
|
{true, FieldKind::FUNCTION}, // SPT_FUNC = 48
|
|
{true, FieldKind::SECONDS}, // SPT_NEXT_TIME = 49
|
|
{true, FieldKind::LAUNCHER_BY_ID}, // SPT_NEXT_LAUNCHER = 50
|
|
{false}, // CPU_FIELDS_END = 51
|
|
{false}, // LAUNCH_FIELDS_START = 52
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_X = 53
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Y = 54
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_Z = 55
|
|
{true, FieldKind::DEGREES}, // SPT_LAUNCHROT_W = 56
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_X = 57
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Y = 58
|
|
{true, FieldKind::DEGREES}, // SPT_CONEROT_Z = 59
|
|
{false}, // SPT_CONEROT_W = 60
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_X = 61
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_Y = 62
|
|
{true, FieldKind::DEGREES}, // SPT_ROTATE_Z = 63
|
|
{true, FieldKind::METERS}, // SPT_CONEROT_RADIUS = 64
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 65
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 66
|
|
{true, FieldKind::METERS}, // SPT_MAT_SCALE_X = 67
|
|
{false}, // LAUNCH_FIELDS_END = 68
|
|
{false}, // SPT_SCALE = 69
|
|
{false}, // SPT_SCALEVEL = 70
|
|
{true, FieldKind::END_FLAG} // SPT_END = 71
|
|
};
|
|
|
|
const std::unordered_map<GameVersion, const SparticleFieldDecomp*> field_kinds = {
|
|
{GameVersion::Jak1, field_kind_jak1},
|
|
{GameVersion::Jak2, field_kind_jak2},
|
|
{GameVersion::Jak3, field_kind_jak2},
|
|
{GameVersion::JakX, field_kind_jakx}};
|
|
|
|
float word_as_float(const LinkedWord& w) {
|
|
ASSERT(w.kind() == LinkedWord::PLAIN_DATA);
|
|
float v;
|
|
memcpy(&v, &w.data, 4);
|
|
return v;
|
|
}
|
|
|
|
void assert_spec_flag_int_single_field(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).data == 0);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).data == 0);
|
|
ASSERT(flag_name == "int");
|
|
}
|
|
|
|
void assert_spec_flag_int(const std::vector<LinkedWord>& words, const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(flag_name == "int");
|
|
}
|
|
|
|
void assert_spec_flag_int_no_rand(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).data == 0);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).data == 1);
|
|
ASSERT(flag_name == "int");
|
|
}
|
|
|
|
void assert_spec_flag_launcher(const std::vector<LinkedWord>& words, const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).data == 0);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).data == 0);
|
|
ASSERT(flag_name == "launcher");
|
|
}
|
|
|
|
void assert_spec_flag_copy_from_other(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).data == 0);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).data == 1);
|
|
ASSERT(flag_name == "copy-from-other");
|
|
}
|
|
|
|
void assert_spec_flag_float(const std::vector<LinkedWord>& words, const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(word_as_float(words.at(2)) != 0.f || word_as_float(words.at(3)) == 1.f);
|
|
ASSERT(flag_name == "float" || flag_name == "float-int-rand" || flag_name == "float-store");
|
|
}
|
|
|
|
std::string decompile_sparticle_texture(const std::vector<LinkedWord>& words,
|
|
const TypeSystem& ts,
|
|
const std::string& flag_name,
|
|
const Env& env) {
|
|
assert_spec_flag_int_single_field(words, flag_name);
|
|
|
|
// try to use texture constants
|
|
auto textures = env.dts->textures;
|
|
auto combo_id = words.at(1).data;
|
|
u16 tpage = (combo_id & 0xfff00000) >> 20;
|
|
u16 idx = (combo_id & 0x000fff00) >> 8;
|
|
auto fixed_id = tpage << 16 | idx;
|
|
if (!textures.empty() && textures.find(fixed_id) != textures.end()) {
|
|
auto tex = textures.at(fixed_id);
|
|
return pretty_print::build_list(tex.name, tex.tpage_name).print();
|
|
}
|
|
|
|
// default to texture id if it fails
|
|
const auto tex_id_type = TypeSpec("texture-id");
|
|
auto tex_id_str = bitfield_defs_print(
|
|
tex_id_type, decompile_bitfield_from_int(tex_id_type, ts, words.at(1).data));
|
|
|
|
return tex_id_str.print();
|
|
}
|
|
|
|
s32 word_as_s32(const LinkedWord& w) {
|
|
ASSERT(w.kind() == LinkedWord::PLAIN_DATA);
|
|
return w.data;
|
|
}
|
|
|
|
std::string decompile_sparticle_func(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
ASSERT(words.at(1).kind() == LinkedWord::SYM_PTR);
|
|
ASSERT(words.at(2).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(2).data == 0);
|
|
ASSERT(words.at(3).kind() == LinkedWord::PLAIN_DATA);
|
|
ASSERT(words.at(3).data == 0);
|
|
ASSERT(flag_name == "symbol");
|
|
return fmt::format("'{}", words.at(1).symbol_name());
|
|
}
|
|
|
|
std::string decompile_sparticle_end(const std::vector<LinkedWord>& words,
|
|
const std::string& field_name,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_int_single_field(words, flag_name);
|
|
ASSERT(words.at(1).data == 0);
|
|
ASSERT(field_name == "spt-end");
|
|
return "";
|
|
}
|
|
|
|
std::string decompile_sparticle_float(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name,
|
|
bool per_sec) {
|
|
assert_spec_flag_float(words, flag_name);
|
|
|
|
per_sec = per_sec && allow_per_sec;
|
|
float base = word_as_float(words.at(1));
|
|
float range = word_as_float(words.at(2));
|
|
float mult = word_as_float(words.at(3));
|
|
if (per_sec) {
|
|
base *= 60;
|
|
}
|
|
|
|
if (flag_name == "float-int-rand") {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("{} {} {}", float_to_string(base), word_as_s32(words.at(2)),
|
|
float_to_string(mult));
|
|
}
|
|
|
|
if (range == 0.f && mult == 1.f) {
|
|
return fmt::format("{}", float_to_string(base));
|
|
} else if (mult != 1.f) {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("{} {} {}", float_to_string(base), float_to_string(range),
|
|
float_to_string(mult));
|
|
} else {
|
|
if (per_sec) {
|
|
range *= 60;
|
|
}
|
|
return fmt::format("{} {}", float_to_string(base), float_to_string(range));
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_userdata(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name,
|
|
const goos::Object& original) {
|
|
if (flag_name == "float-int-rand" || flag_name == "float") {
|
|
return decompile_sparticle_float(words, flag_name, false);
|
|
} else {
|
|
return original.print();
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_int_init(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_int_no_rand(words, flag_name);
|
|
return fmt::format("{}", word_as_s32(words.at(1)));
|
|
}
|
|
|
|
std::string decompile_sparticle_int(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_int(words, flag_name);
|
|
|
|
int base = word_as_s32(words.at(1));
|
|
int range = word_as_s32(words.at(2));
|
|
int mult = word_as_s32(words.at(3));
|
|
|
|
if (range == 0 && mult == 1) {
|
|
return fmt::format("{}", base);
|
|
} else if (mult != 1) {
|
|
return fmt::format("{} {} {}", base, range, mult);
|
|
} else {
|
|
return fmt::format("{} {}", base, range);
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_seconds(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_int(words, flag_name);
|
|
|
|
int base = word_as_s32(words.at(1));
|
|
int range = word_as_s32(words.at(2));
|
|
int mult = word_as_s32(words.at(3));
|
|
|
|
if (range == 0 && mult == 1) {
|
|
return fmt::format("(seconds {})", seconds_to_string(base));
|
|
} else if (mult != 1) {
|
|
return fmt::format("(seconds {}) {} (seconds {})", seconds_to_string(base), range,
|
|
seconds_to_string(mult));
|
|
} else {
|
|
return fmt::format("(seconds {}) (seconds {})", seconds_to_string(base),
|
|
seconds_to_string(range));
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_launcher_by_id(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_launcher(words, flag_name);
|
|
return fmt::format("{}", word_as_s32(words.at(1)));
|
|
}
|
|
|
|
std::string decompile_sparticle_flags(const std::vector<LinkedWord>& words,
|
|
const TypeSystem& ts,
|
|
const std::string& /*field_name*/,
|
|
const std::string& flag_name) {
|
|
assert_spec_flag_int_no_rand(words, flag_name);
|
|
|
|
auto flag_def =
|
|
decompile_bitfield_enum_from_int(TypeSpec("sp-cpuinfo-flag"), ts, word_as_s32(words.at(1)));
|
|
std::string result = "(";
|
|
for (const auto& def : flag_def) {
|
|
if (result.length() > 1) {
|
|
result += ' ';
|
|
}
|
|
result += def;
|
|
}
|
|
result += ')';
|
|
return result;
|
|
}
|
|
|
|
std::string decompile_sparticle_from_other(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name,
|
|
u16 field_id,
|
|
const TypeSystem& ts) {
|
|
assert_spec_flag_copy_from_other(words, flag_name);
|
|
int diff = word_as_s32(words.at(1));
|
|
// naughty dog messed up sometimes
|
|
// ASSERT(diff < 0);
|
|
return fmt::format(
|
|
":copy {}",
|
|
decompile_int_enum_from_int(TypeSpec("sp-field-id"), ts, field_id + diff).substr(4));
|
|
}
|
|
|
|
std::string decompile_sparticle_meters(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name,
|
|
bool per_sec) {
|
|
assert_spec_flag_float(words, flag_name);
|
|
|
|
per_sec = per_sec && allow_per_sec;
|
|
float base = word_as_float(words.at(1));
|
|
float range = word_as_float(words.at(2));
|
|
float mult = word_as_float(words.at(3));
|
|
if (per_sec) {
|
|
base *= 60;
|
|
}
|
|
|
|
if (flag_name == "float-int-rand") {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("(meters {}) {} (meters {})", meters_to_string(base),
|
|
word_as_s32(words.at(2)), meters_to_string(mult));
|
|
}
|
|
|
|
if (range == 0.f && mult == 1.f) {
|
|
return fmt::format("(meters {})", meters_to_string(base));
|
|
} else if (mult != 1.f) {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("(meters {}) {} (meters {})", meters_to_string(base), float_to_string(range),
|
|
meters_to_string(mult));
|
|
} else {
|
|
if (per_sec) {
|
|
range *= 60;
|
|
}
|
|
return fmt::format("(meters {}) (meters {})", meters_to_string(base), meters_to_string(range));
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_degrees(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name,
|
|
bool per_sec) {
|
|
assert_spec_flag_float(words, flag_name);
|
|
|
|
per_sec = per_sec && allow_per_sec;
|
|
float base = word_as_float(words.at(1));
|
|
float range = word_as_float(words.at(2));
|
|
float mult = word_as_float(words.at(3));
|
|
if (per_sec) {
|
|
base *= 60;
|
|
}
|
|
|
|
if (flag_name == "float-int-rand") {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("(degrees {}) {} (degrees {})", degrees_to_string(base),
|
|
word_as_s32(words.at(2)), degrees_to_string(mult));
|
|
}
|
|
|
|
if (range == 0.f && mult == 1.f) {
|
|
return fmt::format("(degrees {})", degrees_to_string(base));
|
|
} else if (mult != 1.f) {
|
|
if (per_sec) {
|
|
mult *= 60;
|
|
}
|
|
return fmt::format("(degrees {}) {} (degrees {})", degrees_to_string(base),
|
|
float_to_string(range), degrees_to_string(mult));
|
|
} else {
|
|
if (per_sec) {
|
|
range *= 60;
|
|
}
|
|
return fmt::format("(degrees {}) (degrees {})", degrees_to_string(base),
|
|
degrees_to_string(range));
|
|
}
|
|
}
|
|
|
|
std::string decompile_sparticle_rot_x(const std::vector<LinkedWord>& words,
|
|
const std::string& flag_name) {
|
|
if (flag_name == "float-int-rand" || flag_name == "float" || flag_name == "float-store") {
|
|
return decompile_sparticle_degrees(words, flag_name, false);
|
|
} else {
|
|
return decompile_sparticle_int_init(words, flag_name);
|
|
}
|
|
}
|
|
|
|
goos::Object decompile_sparticle_sound_spec(const std::vector<LinkedWord>& /*words*/,
|
|
const std::string& flag_name,
|
|
const goos::Object& original) {
|
|
ASSERT(flag_name == "object");
|
|
return original;
|
|
}
|
|
|
|
goos::Object decompile_sparticle_field_init(const std::vector<decompiler::LinkedWord>& words,
|
|
u16 field_id,
|
|
u16 flags,
|
|
goos::Object sound_spec,
|
|
goos::Object userdata,
|
|
const TypeSystem& ts,
|
|
GameVersion version,
|
|
const Env& env) {
|
|
auto field_name = decompile_int_enum_from_int(TypeSpec("sp-field-id"), ts, field_id);
|
|
const auto& field_info = field_kinds.at(version)[field_id];
|
|
if (!field_info.known) {
|
|
throw std::runtime_error("Unknown sparticle field: " + field_name);
|
|
}
|
|
|
|
auto flag_name = decompile_int_enum_from_int(TypeSpec("sp-flag"), ts, flags);
|
|
std::string result;
|
|
|
|
// first, handle some specific flags
|
|
if (flag_name == "copy-from-other") {
|
|
result = decompile_sparticle_from_other(words, flag_name, field_id, ts);
|
|
} else if (flag_name == "symbol") {
|
|
// a symbol
|
|
result = decompile_sparticle_func(words, flag_name);
|
|
} else if (flag_name == "object") {
|
|
// static data
|
|
if (field_info.kind == FieldKind::SOUND_SPEC) {
|
|
return pretty_print::build_list(
|
|
pretty_print::to_symbol(fmt::format(":{}", field_name.substr(4))), sound_spec);
|
|
} else {
|
|
return pretty_print::build_list(
|
|
pretty_print::to_symbol(fmt::format(":{}", field_name.substr(4))),
|
|
pretty_print::to_symbol(":data"), sound_spec);
|
|
}
|
|
} else {
|
|
// let's handle things on a more specific level now
|
|
switch (field_info.kind) {
|
|
case FieldKind::TEXTURE_ID:
|
|
result = decompile_sparticle_texture(words, ts, flag_name, env);
|
|
break;
|
|
case FieldKind::FLOAT:
|
|
result = decompile_sparticle_float(words, flag_name, false);
|
|
break;
|
|
case FieldKind::FLOAT_PER_SEC:
|
|
result = decompile_sparticle_float(words, flag_name, true);
|
|
break;
|
|
case FieldKind::METERS:
|
|
result = decompile_sparticle_meters(words, flag_name, false);
|
|
break;
|
|
case FieldKind::METERS_PER_SEC:
|
|
result = decompile_sparticle_meters(words, flag_name, true);
|
|
break;
|
|
case FieldKind::DEGREES:
|
|
result = decompile_sparticle_degrees(words, flag_name, false);
|
|
break;
|
|
case FieldKind::DEGREES_PER_SEC:
|
|
result = decompile_sparticle_degrees(words, flag_name, true);
|
|
break;
|
|
case FieldKind::INT:
|
|
result = decompile_sparticle_int(words, flag_name);
|
|
break;
|
|
case FieldKind::SECONDS:
|
|
result = decompile_sparticle_seconds(words, flag_name);
|
|
break;
|
|
case FieldKind::CPUINFO_FLAGS:
|
|
result = decompile_sparticle_flags(words, ts, field_name, flag_name);
|
|
break;
|
|
case FieldKind::END_FLAG:
|
|
result = decompile_sparticle_end(words, field_name, flag_name);
|
|
break;
|
|
case FieldKind::LAUNCHER_BY_ID:
|
|
result = decompile_sparticle_launcher_by_id(words, flag_name);
|
|
break;
|
|
case FieldKind::NO_FANCY_DECOMP:
|
|
ASSERT(false);
|
|
break;
|
|
case FieldKind::FUNCTION:
|
|
ASSERT(false);
|
|
break;
|
|
case FieldKind::USERDATA:
|
|
result = decompile_sparticle_userdata(words, flag_name, userdata);
|
|
break;
|
|
case FieldKind::ROT_X:
|
|
result = decompile_sparticle_rot_x(words, flag_name);
|
|
break;
|
|
default:
|
|
ASSERT(false);
|
|
}
|
|
}
|
|
|
|
// lg::print("Result: {}\n\n", result.print());
|
|
if (flag_name == "float-store") {
|
|
result = fmt::format("(:{} {} :store)", field_name.substr(4), result);
|
|
} else {
|
|
result = fmt::format("(:{} {})", field_name.substr(4), result);
|
|
}
|
|
return pretty_print::to_symbol(result);
|
|
}
|
|
|
|
std::string debug_print(const LinkedWord& word) {
|
|
switch (word.kind()) {
|
|
case LinkedWord::PLAIN_DATA:
|
|
return fmt::format("0x{:08x}", word.data);
|
|
case LinkedWord::TYPE_PTR:
|
|
return fmt::format("type: {}\n", word.symbol_name());
|
|
case LinkedWord::EMPTY_PTR:
|
|
return fmt::format("'()");
|
|
case LinkedWord::HI_PTR:
|
|
return fmt::format("hi ptr");
|
|
case LinkedWord::LO_PTR:
|
|
return fmt::format("lo ptr");
|
|
case LinkedWord::PTR:
|
|
return fmt::format("ptr");
|
|
case LinkedWord::SYM_OFFSET:
|
|
return fmt::format("offset '{}", word.symbol_name());
|
|
case LinkedWord::SYM_PTR:
|
|
return fmt::format("ptr '{}", word.symbol_name());
|
|
case LinkedWord::SYM_VAL_OFFSET:
|
|
return fmt::format("val-ptr '{}", word.symbol_name());
|
|
default:
|
|
ASSERT(false);
|
|
}
|
|
}
|
|
} // namespace decompiler
|
|
|
|
/*
|
|
(deftype sp-field-init-spec (structure)
|
|
((field sp-field-id :offset-assert 0)
|
|
(flags sp-flag :offset-assert 2)
|
|
(initial-valuef float :offset-assert 4)
|
|
(random-rangef float :offset-assert 8)
|
|
(random-multf float :offset-assert 12)
|
|
(initial-value int32 :offset 4)
|
|
(random-range int32 :offset 8)
|
|
(random-mult int32 :offset 12)
|
|
(sym symbol :offset 4) ;; moved
|
|
(func function :offset 4)
|
|
(tex uint32 :offset 4)
|
|
(pntr pointer :offset 4)
|
|
;; gap
|
|
(sound basic :offset 4)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x10
|
|
:flag-assert #x900000010
|
|
)
|
|
*/
|