mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 22:22:21 -04:00
[graphics] First part of shrub extraction (#1258)
* decompile 90% of shrubbery * some more progress * some more * big function decompiled * went through `draw-prototype-inline-array-shrub` and made more notes * shrub: start implementing extract_shrub * read through current notes and add the info to current decomp * decomp: allow skipping inline-asm from output * add code to BspHeader to get GOAL types for shrubs * add doc * wip * fix bad merge Co-authored-by: Tyler Wilding <xtvaser@gmail.com> Co-authored-by: Tyler Wilding <xTVaser@users.noreply.github.com>
This commit is contained in:
@@ -60,6 +60,7 @@ add_library(
|
||||
level_extractor/extract_tfrag.cpp
|
||||
level_extractor/extract_tie.cpp
|
||||
level_extractor/BspHeader.cpp
|
||||
level_extractor/extract_shrub.cpp
|
||||
|
||||
ObjectFile/LinkedObjectFile.cpp
|
||||
ObjectFile/LinkedObjectFileCreation.cpp
|
||||
|
||||
@@ -8,6 +8,16 @@ typedef OpenGOALAsm::InstructionModifiers MOD;
|
||||
|
||||
const std::map<InstructionKind, OpenGOALAsm::Function> MIPS_ASM_TO_OPEN_GOAL_FUNCS = {
|
||||
// ----- EE -------
|
||||
// Instructions that are nopped
|
||||
// {InstructionKind::MTC0,
|
||||
// {".nop", {MOD::SKIP_IT}}}, // they only use this for performance counters / Count /
|
||||
// Debug
|
||||
// {InstructionKind::MTPC, {".nop", {MOD::SKIP_IT}}},
|
||||
// {InstructionKind::MFPC, {".nop", {MOD::SKIP_IT}}},
|
||||
// {InstructionKind::SYNCP, {".nop", {MOD::SKIP_IT}}},
|
||||
// {InstructionKind::SYNCL, {".nop", {MOD::SKIP_IT}}},
|
||||
|
||||
// Shifts and such
|
||||
{InstructionKind::PSLLW, {".pw.sll", {}}},
|
||||
{InstructionKind::PSRAW, {".pw.sra", {}}},
|
||||
{InstructionKind::PSUBW, {".psubw", {}}},
|
||||
@@ -156,6 +166,10 @@ OpenGOALAsm::OpenGOALAsm(Instruction _instr) : m_instr(_instr) {
|
||||
if (func.funcTemplate.rfind("TODO", 0) == 0) {
|
||||
todo = true;
|
||||
}
|
||||
if (std::find(func.modifiers.begin(), func.modifiers.end(), InstructionModifiers::SKIP_IT) !=
|
||||
func.modifiers.end()) {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +184,10 @@ OpenGOALAsm::OpenGOALAsm(Instruction _instr,
|
||||
if (func.funcTemplate.rfind("TODO", 0) == 0) {
|
||||
todo = true;
|
||||
}
|
||||
if (std::find(func.modifiers.begin(), func.modifiers.end(), InstructionModifiers::SKIP_IT) !=
|
||||
func.modifiers.end()) {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ struct OpenGOALAsm {
|
||||
OFFSET,
|
||||
SWAP_FIRST_TWO_SOURCE_ARGS,
|
||||
ACC_THIRD_SRC_ARG,
|
||||
QWORD_CAST
|
||||
QWORD_CAST,
|
||||
SKIP_IT
|
||||
};
|
||||
|
||||
struct Function {
|
||||
@@ -41,6 +42,7 @@ struct OpenGOALAsm {
|
||||
|
||||
bool valid = true;
|
||||
bool todo = false;
|
||||
bool skip = false;
|
||||
Instruction m_instr;
|
||||
std::optional<RegisterAccess> m_dst;
|
||||
std::vector<std::optional<RegisterAccess>> m_src;
|
||||
|
||||
@@ -45,6 +45,8 @@ bool rewrite_inline_asm_instructions(Form* top_level_form,
|
||||
asmOp.m_instr.to_string(f.ir2.env.file->labels));
|
||||
new_entries.push_back(entry);
|
||||
continue;
|
||||
} else if (asmOp.skip) {
|
||||
continue;
|
||||
} else if (asmOp.todo) {
|
||||
// If its an invalid or unsupported exception, skip it
|
||||
/*lg::warn("[ASM Re-Write] - Inline assembly instruction marked with TODO - [{}]",
|
||||
|
||||
@@ -9497,11 +9497,11 @@
|
||||
;; - Types
|
||||
|
||||
(deftype prototype-bucket (basic)
|
||||
((name basic :offset-assert 4)
|
||||
((name string :offset-assert 4)
|
||||
(flags uint32 :offset-assert 8)
|
||||
(in-level uint16 :offset-assert 12)
|
||||
(utextures uint16 :offset-assert 14)
|
||||
(geometry drawable 4 :offset-assert 16)
|
||||
(geometry drawable 4 :offset-assert 16) ;; 15, 20, 24
|
||||
(dists vector :inline :offset-assert 32)
|
||||
(rdists vector :inline :offset-assert 48)
|
||||
(next uint32 4 :offset-assert 64)
|
||||
@@ -9515,6 +9515,10 @@
|
||||
(rlength-mid float :offset 56)
|
||||
(stiffness float :offset 60)
|
||||
(next-clear uint128 :offset 64)
|
||||
(next-clear-1 int32 :offset 64)
|
||||
(next-clear-2 int32 :offset 68)
|
||||
(next-clear-3 int32 :offset 72)
|
||||
(next-clear-4 int32 :offset 76)
|
||||
(count-clear uint64 :offset 80)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@@ -9523,8 +9527,14 @@
|
||||
)
|
||||
|
||||
(deftype prototype-bucket-shrub (prototype-bucket)
|
||||
((mod-count uint16 4 :offset-assert 88)
|
||||
(last uint32 4 :offset-assert 96)
|
||||
(;; Geometry Array
|
||||
;; - prototype-generic-shrub / shrub-near (drawn with generic)
|
||||
;; - prototype-shrubbery
|
||||
;; - prototype-trans-shrubbery
|
||||
;; - billboard
|
||||
(mod-count uint16 4 :offset-assert 88)
|
||||
(last dma-packet 4 :offset-assert 96)
|
||||
(count-clear-qword uint128 :offset 80)
|
||||
(last-clear uint128 :offset 96)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@@ -12791,6 +12801,7 @@
|
||||
|
||||
;; - Types
|
||||
|
||||
;; Single rectangle -- only one texture (aka adgif-shader)
|
||||
(deftype billboard (drawable)
|
||||
((flat adgif-shader :inline :offset-assert 32)
|
||||
)
|
||||
@@ -12800,18 +12811,19 @@
|
||||
)
|
||||
|
||||
(deftype shrub-view-data (structure)
|
||||
((data uint128 3 :offset-assert 0)
|
||||
(texture-giftag qword :inline :offset 0)
|
||||
((data uint128 3 :offset-assert 0)
|
||||
(texture-giftag gs-gif-tag :inline :offset 0)
|
||||
(consts vector :inline :offset 16)
|
||||
(fog-clamp vector :inline :offset 32)
|
||||
(tex-start-ptr int32 :offset 16)
|
||||
(gifbufsum float :offset 16)
|
||||
(mtx-buf-ptr int32 :offset 20)
|
||||
(exp23 float :offset 20)
|
||||
(fog-0 float :offset 24)
|
||||
(fog-1 float :offset 28)
|
||||
(fog-min float :offset 32)
|
||||
(fog-max float :offset 36)
|
||||
(tex-start-ptr int32 :score 999 :offset 16)
|
||||
(gifbufsum float :score 999 :offset 16)
|
||||
;; suspected to be part of hacks to get around VU's lack of integer operations
|
||||
(mtx-buf-ptr int32 :score 999 :offset 20)
|
||||
(exp23 float :score 999 :offset 20)
|
||||
(fog-0 float :score 999 :offset 24)
|
||||
(fog-1 float :score 999 :offset 28)
|
||||
(fog-min float :score 999 :offset 32)
|
||||
(fog-max float :score 999 :offset 36)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x30
|
||||
@@ -12820,11 +12832,19 @@
|
||||
|
||||
(deftype shrubbery (drawable)
|
||||
((textures (inline-array adgif-shader) :offset 4)
|
||||
;; header breakdown:
|
||||
;; [0] - number of textures / 2
|
||||
;; [1] - number of vertices
|
||||
;; [2] - number of triangle strips
|
||||
;; [3] - ??
|
||||
;;
|
||||
;; Number of Triangles in the Shrub = header[2] - 2 * header[1]
|
||||
(header qword :offset 8)
|
||||
(obj-qwc uint8 :offset 12)
|
||||
(vtx-qwc uint8 :offset 13)
|
||||
(col-qwc uint8 :offset 14)
|
||||
(stq-qwc uint8 :offset 15)
|
||||
;; start of static dma-chain
|
||||
(obj uint32 :score 999 :offset 16)
|
||||
(vtx uint32 :score 999 :offset 20)
|
||||
(col uint32 :score 999 :offset 24)
|
||||
@@ -12836,7 +12856,8 @@
|
||||
)
|
||||
|
||||
(deftype instance-shrubbery (instance)
|
||||
((flat-normal vector :inline :offset-assert 64)
|
||||
((color-indices uint32 :offset 8)
|
||||
(flat-normal vector :inline :offset-assert 64)
|
||||
(flat-hwidth float :offset 76)
|
||||
(color uint32 :offset 8)
|
||||
)
|
||||
@@ -12856,7 +12877,7 @@
|
||||
|
||||
(deftype drawable-tree-instance-shrub (drawable-tree)
|
||||
((info prototype-array-shrub-info :offset 8)
|
||||
(colors-added uint32 :offset 12) ;; added
|
||||
(colors-added time-of-day-palette :offset 12) ;; added
|
||||
)
|
||||
:method-count-assert #x12
|
||||
:size-assert #x24
|
||||
@@ -12866,6 +12887,8 @@
|
||||
(deftype generic-shrub-fragment (drawable)
|
||||
((textures (inline-array adgif-shader) :score 999 :offset 4)
|
||||
(vtx-cnt uint32 :score 999 :offset 8)
|
||||
;; the total size of the textures array
|
||||
;; - each texture is 5 qwords
|
||||
(cnt-qwc uint8 :score 999 :offset 12)
|
||||
(vtx-qwc uint8 :score 999 :offset 13)
|
||||
(col-qwc uint8 :score 999 :offset 14)
|
||||
@@ -12933,7 +12956,7 @@
|
||||
(chainb qword 8 :inline :offset-assert 176)
|
||||
(colors rgba 1024 :offset-assert 304)
|
||||
(matrix-tmpl qword 20 :inline :offset-assert 4400)
|
||||
(count-tmpl qword 20 :inline :offset-assert 4720)
|
||||
(count-tmpl vector4w 20 :inline :offset-assert 4720)
|
||||
(mscalf-tmpl dma-packet :inline :offset-assert 5040)
|
||||
(mscalf-ret-tmpl dma-packet :inline :offset-assert 5056)
|
||||
(adgif-tmpl dma-gif-packet :inline :offset-assert 5072)
|
||||
@@ -17058,19 +17081,19 @@
|
||||
;; - Functions
|
||||
|
||||
(define-extern upload-generic-shrub (function dma-buffer generic-shrub-fragment int int dma-buffer))
|
||||
(define-extern shrub-num-tris (function shrubbery int))
|
||||
(define-extern shrub-init-frame function)
|
||||
(define-extern shrub-upload-model function)
|
||||
(define-extern shrub-do-init-frame function)
|
||||
(define-extern shrub-upload-view-data function)
|
||||
(define-extern shrub-init-view-data function)
|
||||
(define-extern mem-usage-shrub-walk function)
|
||||
(define-extern shrub-make-perspective-matrix (function matrix none))
|
||||
(define-extern shrub-time function)
|
||||
(define-extern draw-inline-array-instance-shrub function)
|
||||
(define-extern draw-prototype-inline-array-shrub function)
|
||||
(define-extern shrub-num-tris (function shrubbery uint))
|
||||
(define-extern shrub-init-frame (function dma-buffer gs-test none))
|
||||
(define-extern shrub-upload-model (function shrubbery dma-buffer int symbol)) ;; third arg is `start-bank` from shrub-work
|
||||
(define-extern shrub-do-init-frame (function dma-buffer symbol))
|
||||
(define-extern shrub-upload-view-data (function dma-buffer symbol))
|
||||
(define-extern shrub-init-view-data (function shrub-view-data symbol))
|
||||
(define-extern mem-usage-shrub-walk (function draw-node int memory-usage-block int draw-node))
|
||||
(define-extern shrub-make-perspective-matrix (function matrix matrix))
|
||||
(define-extern shrub-time (function int int int int int int)) ;; unused
|
||||
(define-extern draw-inline-array-instance-shrub (function dma-buffer drawable int (inline-array prototype-bucket-shrub) none))
|
||||
(define-extern draw-prototype-inline-array-shrub (function int (inline-array prototype-bucket-shrub) pointer))
|
||||
(define-extern shrub-upload-test (function generic-shrub-fragment none))
|
||||
(define-extern test-func function)
|
||||
(define-extern test-func (function none))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
|
||||
@@ -189,8 +189,7 @@
|
||||
"draw-node-cull",
|
||||
|
||||
// shrubbery
|
||||
"test-func",
|
||||
"draw-inline-array-instance-shrub",
|
||||
"draw-inline-array-instance-shrub", // CFG
|
||||
|
||||
// tfrag
|
||||
"stats-tfrag-asm",
|
||||
@@ -423,7 +422,8 @@
|
||||
"draw-drawable-tree-dirt-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-ice-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-instance-tie": [10, 12, 18, 20, 26, 28, 37, 39],
|
||||
|
||||
"draw-drawable-tree-instance-shrub": [5, 7, 9, 11],
|
||||
|
||||
"birth-pickup-at-point": [0],
|
||||
"draw-bones": [0, 1, 2, 8, 81],
|
||||
"draw-bones-hud": [7, 8],
|
||||
|
||||
@@ -2106,6 +2106,9 @@
|
||||
],
|
||||
|
||||
"generic-vu0": [["L1", "vu-function"]],
|
||||
"shrubbery": [
|
||||
["L133", "vu-function"]
|
||||
],
|
||||
|
||||
// please do not add things after this entry! git is dumb.
|
||||
"object-file-that-doesnt-actually-exist-and-i-just-put-this-here-to-prevent-merge-conflicts-with-this-file": []
|
||||
|
||||
@@ -7690,6 +7690,90 @@
|
||||
[273, "t0", "(pointer uint64)"],
|
||||
[275, "t0", "(pointer gs-reg64)"]
|
||||
],
|
||||
"test-func": [
|
||||
[7, "f1", "float"]
|
||||
],
|
||||
|
||||
"(method 14 drawable-tree-instance-shrub)": [
|
||||
[[12, 151], "gp", "prototype-bucket-shrub"],
|
||||
[15, "a1", "drawable-group"],
|
||||
[39, "v1", "drawable-group"],
|
||||
[61, "s3", "shrubbery"],
|
||||
[85, "v1", "drawable-group"],
|
||||
[107, "s3", "shrubbery"],
|
||||
[151, "gp", "(inline-array prototype-bucket-shrub)"]
|
||||
],
|
||||
|
||||
"(method 10 drawable-tree-instance-shrub)": [
|
||||
[3, "a1", "terrain-context"]
|
||||
],
|
||||
|
||||
"draw-prototype-inline-array-shrub": [
|
||||
[[13, 55], "v1", "prototype-bucket-shrub"],
|
||||
[[15, 30], "a2", "vector4w"],
|
||||
[[42, 51], "a2", "vector4w"],
|
||||
[[87, 93], "a0", "dma-packet"],
|
||||
[[96, 102], "a0", "gs-gif-tag"],
|
||||
[107, "a1", "gs-test"],
|
||||
[107, "a0", "(pointer gs-test)"],
|
||||
[109, "a0", "(pointer gs-reg64)"],
|
||||
[[117, 136], "v1", "matrix3"],
|
||||
[[140, 145], "v1", "dma-packet"],
|
||||
[[238, 247], "a0", "dma-packet"],
|
||||
[[261, 266], "v1", "dma-packet"],
|
||||
[[359, 368], "a0", "dma-packet"],
|
||||
[[382, 387], "v1", "dma-packet"],
|
||||
[[451, 457], "a1", "dma-packet"],
|
||||
[[460, 466], "a1", "dma-packet"],
|
||||
[[524, 530], "a0", "dma-packet"],
|
||||
[55, "v1", "(inline-array prototype-bucket-shrub)"],
|
||||
[156, "v1", "terrain-context"],
|
||||
[212, "gp", "prototype-bucket-shrub"],
|
||||
[333, "gp", "prototype-bucket-shrub"],
|
||||
[[479, 518], "gp", "prototype-bucket-shrub"],
|
||||
[518, "gp", "(inline-array prototype-bucket-shrub)"],
|
||||
[223, "v1", "drawable-group"],
|
||||
[277, "v1", "terrain-context"],
|
||||
[344, "v1", "drawable-group"],
|
||||
[398, "v1", "terrain-context"],
|
||||
[[498, 507], "a1", "prototype-bucket-shrub"],
|
||||
[540, "v1", "terrain-context"]
|
||||
],
|
||||
|
||||
"(method 8 drawable-tree-instance-shrub)": [
|
||||
[54, "v1", "drawable-group"]
|
||||
],
|
||||
|
||||
"draw-drawable-tree-instance-shrub": [
|
||||
[85, "a0", "drawable-group"]
|
||||
],
|
||||
|
||||
"shrub-init-frame": [
|
||||
[[6, 12], "a0", "dma-packet"],
|
||||
[[13, 21], "a0", "gs-gif-tag"],
|
||||
[24, "v1", "(pointer gs-test)"],
|
||||
[26, "v1", "(pointer gs-reg64)"]
|
||||
],
|
||||
|
||||
"shrub-do-init-frame": [
|
||||
[[10, 21], "a0", "dma-packet"],
|
||||
[[24, 29], "a0", "dma-packet"],
|
||||
[33, "v1", "(pointer vif-tag)"],
|
||||
[[35, 41], "v1", "(pointer uint32)"],
|
||||
[42, "v1", "(pointer vif-tag)"],
|
||||
[[43, 51], "v1", "(pointer uint32)"],
|
||||
[52, "v1", "(pointer vif-tag)"],
|
||||
[54, "v1", "(pointer uint32)"]
|
||||
],
|
||||
|
||||
"shrub-upload-view-data": [
|
||||
[[3, 16], "a0", "dma-packet"]
|
||||
],
|
||||
|
||||
"shrub-upload-model": [
|
||||
[[17, 26], "a3", "dma-packet"],
|
||||
[[33, 41], "a0", "dma-packet"],
|
||||
[[47, 55], "a0", "dma-packet"]
|
||||
],
|
||||
"placeholder-do-not-add-below": []
|
||||
}
|
||||
|
||||
@@ -135,6 +135,10 @@ std::unique_ptr<Drawable> make_draw_node_child(TypedRef ref,
|
||||
auto result = std::make_unique<DrawableActor>();
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
} else if (ref.type->get_name() == "instance-shrubbery") {
|
||||
auto result = std::make_unique<shrub_types::InstanceShrubbery>();
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
} else {
|
||||
throw Error("Unknown child of draw node: {}\n", ref.type->get_name());
|
||||
}
|
||||
@@ -149,6 +153,8 @@ int get_child_stride(const std::string& type) {
|
||||
return 64;
|
||||
} else if (type == "drawable-actor") {
|
||||
return 32;
|
||||
} else if (type == "instance-shrubbery") {
|
||||
return 80;
|
||||
} else {
|
||||
throw Error("unknown child for stride: {}", type);
|
||||
}
|
||||
@@ -752,6 +758,13 @@ std::unique_ptr<DrawableInlineArray> make_drawable_inline_array(
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (ref.type->get_name() == "drawable-inline-array-instance-shrub") {
|
||||
auto result = std::make_unique<shrub_types::DrawableInlineArrayInstanceShrub>();
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto result = std::make_unique<DrawableInlineArrayUnknown>();
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
@@ -872,7 +885,6 @@ void PrototypeBucketTie::read_from_file(TypedRef ref,
|
||||
ASSERT(flags == 0 || flags == 2);
|
||||
in_level = read_plain_data_field<u16>(ref, "in-level", dts);
|
||||
utextures = read_plain_data_field<u16>(ref, "utextures", dts);
|
||||
// todo drawables
|
||||
dists.read_from_file(get_field_ref(ref, "dists", dts));
|
||||
rdists.read_from_file(get_field_ref(ref, "rdists", dts));
|
||||
stiffness = read_plain_data_field<float>(ref, "stiffness", dts);
|
||||
@@ -1106,6 +1118,424 @@ std::string DrawableTreeInstanceTie::my_type() const {
|
||||
return "drawable-tree-instance-tie";
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// shrub
|
||||
//////////////////////////
|
||||
|
||||
namespace shrub_types {
|
||||
|
||||
void DrawableTreeInstanceShrub::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
// the usual drawable stuff
|
||||
id = read_plain_data_field<s16>(ref, "id", dts);
|
||||
length = read_plain_data_field<s16>(ref, "length", dts);
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
|
||||
// unfortunately, shrub uses the arrays thing differently.
|
||||
// there's just one top level array, and the nodes are a bit scattered in memory below that.
|
||||
// it doesn't have the 8 child rule
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
if ((data_ref.byte_offset % 4) != 0) {
|
||||
throw Error("misaligned data array");
|
||||
}
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
Ref array_slot_ref = data_ref;
|
||||
array_slot_ref.byte_offset += idx * 4;
|
||||
|
||||
Ref object_ref = deref_label(array_slot_ref);
|
||||
object_ref.byte_offset -= 4;
|
||||
|
||||
arrays.push_back(make_drawable_inline_array(typed_ref_from_basic(object_ref, dts), dts, stats));
|
||||
}
|
||||
// confirm that we have the weird shrub pattern and only found one array.
|
||||
ASSERT(length == 1);
|
||||
|
||||
// now, let's try to discover the remaining arrays (instances).
|
||||
// basically we just look after the top level array in memory.
|
||||
// once we find something else (the time of day palette) we know we're at the end.
|
||||
// the game finds these by traversing the tree, but this is a little easier, and gets us
|
||||
// the familiar arrays that we used in tie/tfrag.
|
||||
|
||||
Ref object_ref = deref_label(data_ref);
|
||||
object_ref.byte_offset -= 4;
|
||||
discovered_arrays.push_back(
|
||||
make_drawable_inline_array(typed_ref_from_basic(object_ref, dts), dts, stats));
|
||||
|
||||
bool done = false;
|
||||
object_ref.byte_offset += 16;
|
||||
while (!done) {
|
||||
auto& word = object_ref.data->words_by_seg.at(object_ref.seg).at(object_ref.byte_offset / 4);
|
||||
if (word.kind() == decompiler::LinkedWord::TYPE_PTR) {
|
||||
if (word.symbol_name() == "drawable-inline-array-node") {
|
||||
discovered_arrays.push_back(
|
||||
make_drawable_inline_array(typed_ref_from_basic(object_ref, dts), dts, stats));
|
||||
} else if (word.symbol_name() == "drawable-inline-array-instance-shrub") {
|
||||
discovered_arrays.push_back(
|
||||
make_drawable_inline_array(typed_ref_from_basic(object_ref, dts), dts, stats));
|
||||
} else if (word.symbol_name() == "time-of-day-palette") {
|
||||
done = true;
|
||||
} else {
|
||||
ASSERT(word.symbol_name() == "draw-node" || word.symbol_name() == "instance-shrubbery");
|
||||
}
|
||||
}
|
||||
object_ref.byte_offset += 16;
|
||||
}
|
||||
|
||||
// this "info" thing holds all the prototypes
|
||||
auto pt = deref_label(get_field_ref(ref, "info", dts));
|
||||
pt.byte_offset -= 4;
|
||||
info.read_from_file(typed_ref_from_basic(pt, dts), dts, stats);
|
||||
|
||||
// time of day palette. we'll want these colors in the FR3 file.
|
||||
auto palette = deref_label(get_field_ref(ref, "colors-added", dts));
|
||||
time_of_day.width = deref_u32(palette, 0);
|
||||
ASSERT(time_of_day.width == 8);
|
||||
time_of_day.height = deref_u32(palette, 1);
|
||||
time_of_day.pad = deref_u32(palette, 2);
|
||||
ASSERT(time_of_day.pad == 0);
|
||||
for (int i = 0; i < int(8 * time_of_day.height); i++) {
|
||||
time_of_day.colors.push_back(deref_u32(palette, 3 + i));
|
||||
}
|
||||
}
|
||||
|
||||
std::string DrawableTreeInstanceShrub::my_type() const {
|
||||
return "drawable-tree-instance-shrub";
|
||||
}
|
||||
|
||||
std::string DrawableTreeInstanceShrub::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
if (!settings.expand_shrub) {
|
||||
return "";
|
||||
}
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
result += fmt::format("{}id: {}\n", is, id);
|
||||
result += fmt::format("{}length: {}\n", is, length);
|
||||
result += fmt::format("{}bsphere: {}", is, bsphere.print_meters());
|
||||
|
||||
if (settings.expand_shrub) {
|
||||
for (size_t i = 0; i < discovered_arrays.size(); i++) {
|
||||
result += fmt::format("{}arrays [{}] ({}):\n", is, i, discovered_arrays[i]->my_type());
|
||||
result += discovered_arrays[i]->print(settings, next_indent);
|
||||
}
|
||||
|
||||
result += fmt::format("{}prototypes:\n", is);
|
||||
result += info.print(settings, next_indent);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void InstanceShrubbery::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* /*stats*/) {
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
bucket_index = read_plain_data_field<u16>(ref, "bucket-index", dts);
|
||||
id = read_plain_data_field<s16>(ref, "id", dts);
|
||||
origin.read_from_file(get_field_ref(ref, "origin", dts));
|
||||
wind_index = read_plain_data_field<u16>(ref, "wind-index", dts);
|
||||
color_indices = read_plain_data_field<u32>(ref, "color-indices", dts);
|
||||
flat_normal.read_from_file(get_field_ref(ref, "flat-normal", dts));
|
||||
}
|
||||
|
||||
std::string InstanceShrubbery::print(const level_tools::PrintSettings& /*settings*/,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
result += fmt::format("{}bsphere: {}", is, bsphere.print_meters());
|
||||
result += fmt::format("{}bucket-index: {}\n", is, bucket_index);
|
||||
result += fmt::format("{}flat-normal: {}", is, flat_normal.print_meters());
|
||||
result += fmt::format("{}color-indices: {}\n", is, color_indices);
|
||||
result += fmt::format("{}wind-index: {}\n", is, wind_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawableInlineArrayInstanceShrub::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) {
|
||||
id = read_plain_data_field<s16>(ref, "id", dts);
|
||||
length = read_plain_data_field<s16>(ref, "length", dts);
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Ref obj_ref = data_ref;
|
||||
obj_ref.byte_offset += 80 * i; // todo not a constant here
|
||||
auto type = get_type_of_basic(obj_ref);
|
||||
if (type != "instance-shrubbery") {
|
||||
throw Error("bad draw node type: {}", type);
|
||||
}
|
||||
instances.emplace_back();
|
||||
instances.back().read_from_file(typed_ref_from_basic(obj_ref, dts), dts, stats);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DrawableInlineArrayInstanceShrub::print(const PrintSettings& settings,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
result += fmt::format("{}id: {}\n", is, id);
|
||||
result += fmt::format("{}length: {}\n", is, length);
|
||||
result += fmt::format("{}bsphere: {}", is, bsphere.print_meters());
|
||||
|
||||
if (settings.expand_shrub) {
|
||||
for (size_t i = 0; i < instances.size(); i++) {
|
||||
result += fmt::format("{}draw-nodes [{}] ({}):\n", is, i, instances[i].my_type());
|
||||
result += instances[i].print(settings, next_indent);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrototypeArrayShrubInfo::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
prototype_inline_array_shrub.read_from_file(
|
||||
get_and_check_ref_to_basic(ref, "prototype-inline-array-shrub",
|
||||
"prototype-inline-array-shrub", dts),
|
||||
dts, stats);
|
||||
wind_vectors = deref_label(get_field_ref(ref, "wind-vectors", dts));
|
||||
}
|
||||
|
||||
std::string PrototypeArrayShrubInfo::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
return prototype_inline_array_shrub.print(settings, indent);
|
||||
}
|
||||
|
||||
void PrototypeInlineArrayShrub::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
length = read_plain_data_field<s16>(ref, "length", dts);
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
Ref thing = data_ref;
|
||||
// note: unlike tie, these are stored in an inline array.
|
||||
thing.byte_offset += 112 * i; // todo - not a constant here
|
||||
auto type = get_type_of_basic(thing);
|
||||
if (type != "prototype-bucket-shrub") {
|
||||
throw Error("bad type in PrototypeInlineArrayShrub data: {}\n", type);
|
||||
}
|
||||
data.emplace_back();
|
||||
data.back().read_from_file(typed_ref_from_basic(thing, dts), dts, stats);
|
||||
}
|
||||
}
|
||||
|
||||
std::string PrototypeGenericShrub::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
result += fmt::format("{}length: {}\n", is, length);
|
||||
|
||||
for (u32 i = 0; i < shrubs.size(); i++) {
|
||||
result += fmt::format("{}data [{}]:\n", is, i);
|
||||
result += shrubs[i].print(settings, next_indent);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrototypeGenericShrub::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
length = read_plain_data_field<s16>(ref, "length", dts);
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Ref thing = data_ref;
|
||||
// note: unlike tie, these are stored in an inline array.
|
||||
thing.byte_offset += 4 * i; // 4 byte pointer
|
||||
thing = deref_label(thing);
|
||||
thing.byte_offset -= 4; // basic offset
|
||||
auto type = get_type_of_basic(thing);
|
||||
if (type != "generic-shrub-fragment") {
|
||||
throw Error("bad type in PrototypeGenericShrub data: {}\n", type);
|
||||
}
|
||||
shrubs.emplace_back();
|
||||
shrubs.back().read_from_file(typed_ref_from_basic(thing, dts), dts, stats);
|
||||
}
|
||||
}
|
||||
|
||||
std::string PrototypeInlineArrayShrub::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
result += fmt::format("{}length: {}\n", is, length);
|
||||
|
||||
for (u32 i = 0; i < data.size(); i++) {
|
||||
result += fmt::format("{}data [{}]:\n", is, i);
|
||||
result += data[i].print(settings, next_indent);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrototypeBucketShrub::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
name = read_string_field(ref, "name", dts, true);
|
||||
flags = read_plain_data_field<u32>(ref, "flags", dts);
|
||||
if (flags) {
|
||||
// lid in misty has flag 2, not sure what it means yet.
|
||||
fmt::print("proto: {} flags: {}\n", name, flags);
|
||||
}
|
||||
ASSERT(flags == 0 || flags == 2);
|
||||
in_level = read_plain_data_field<u16>(ref, "in-level", dts);
|
||||
utextures = read_plain_data_field<u16>(ref, "utextures", dts);
|
||||
dists.read_from_file(get_field_ref(ref, "dists", dts));
|
||||
rdists.read_from_file(get_field_ref(ref, "rdists", dts));
|
||||
stiffness = read_plain_data_field<float>(ref, "stiffness", dts);
|
||||
// 64 to 112 should be zeros
|
||||
for (int i = 0; i < 12; i++) {
|
||||
ASSERT(deref_u32(ref.ref, 16 + i) == 0);
|
||||
}
|
||||
|
||||
auto geom_start = get_field_ref(ref, "geometry", dts);
|
||||
|
||||
// first geometry is generic and we should always have it.
|
||||
auto generic_geom_l = deref_label(geom_start);
|
||||
generic_geom_l.byte_offset -= 4;
|
||||
if (get_type_of_basic(generic_geom_l) != "prototype-generic-shrub") {
|
||||
throw Error("bad generic shrub type: {}", get_type_of_basic(generic_geom_l));
|
||||
}
|
||||
geom_start.byte_offset += 4;
|
||||
|
||||
// second is same data, but in prototype-shrubbery form (for normal shrub renderer)
|
||||
auto normal_geom = deref_label(geom_start);
|
||||
normal_geom.byte_offset -= 4;
|
||||
if (get_type_of_basic(normal_geom) != "prototype-shrubbery") {
|
||||
throw Error("bad normal shrub type: {}", get_type_of_basic(normal_geom));
|
||||
}
|
||||
shrubbery_geom.read_from_file(typed_ref_from_basic(normal_geom, dts), dts, stats);
|
||||
geom_start.byte_offset += 4;
|
||||
|
||||
generic_geom.read_from_file(typed_ref_from_basic(generic_geom_l, dts), dts, stats);
|
||||
|
||||
// todo transparent version
|
||||
// todo billboard version.
|
||||
}
|
||||
|
||||
std::string PrototypeBucketShrub::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
result += fmt::format("{}name: {}\n", is, name);
|
||||
result += fmt::format("{}flags: {}\n", is, flags);
|
||||
|
||||
result += fmt::format("{}generic-geometry [0]:\n", is);
|
||||
result += generic_geom.print(settings, indent + 4);
|
||||
|
||||
result += fmt::format("{}normal-geometry [1]:\n", is);
|
||||
result += shrubbery_geom.print(settings, indent + 4);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrototypeShrubbery::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) {
|
||||
id = read_plain_data_field<s16>(ref, "id", dts);
|
||||
length = read_plain_data_field<s16>(ref, "length", dts);
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
|
||||
auto data_ref = get_field_ref(ref, "data", dts);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Ref obj_ref = data_ref;
|
||||
obj_ref.byte_offset += 32 * i; // todo not a constant here
|
||||
auto type = get_type_of_basic(obj_ref);
|
||||
if (type != "shrubbery") {
|
||||
throw Error("bad draw node type: {}", type);
|
||||
}
|
||||
shrubs.emplace_back();
|
||||
shrubs.back().read_from_file(typed_ref_from_basic(obj_ref, dts), dts, stats);
|
||||
}
|
||||
}
|
||||
|
||||
std::string PrototypeShrubbery::print(const level_tools::PrintSettings& settings,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
result += fmt::format("{}id: {}\n", is, id);
|
||||
result += fmt::format("{}length: {}\n", is, length);
|
||||
result += fmt::format("{}bsphere: {}", is, bsphere.print_meters());
|
||||
|
||||
for (size_t i = 0; i < shrubs.size(); i++) {
|
||||
result += fmt::format("{}draw-nodes [{}] ({}):\n", is, i, shrubs[i].my_type());
|
||||
result += shrubs[i].print(settings, next_indent);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void copy_dma_to_vector(std::vector<u8>* out, Ref data_start, int qwc) {
|
||||
out->resize(qwc * 16);
|
||||
for (int i = 0; i < qwc * 4; i++) {
|
||||
u32 val = deref_u32(data_start, i);
|
||||
memcpy(out->data() + i * 4, &val, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void Shrubbery::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* /*stats*/) {
|
||||
// read the easy ones.
|
||||
obj_qwc = read_plain_data_field<u8>(ref, "obj-qwc", dts);
|
||||
vtx_qwc = read_plain_data_field<u8>(ref, "vtx-qwc", dts);
|
||||
col_qwc = read_plain_data_field<u8>(ref, "col-qwc", dts);
|
||||
stq_qwc = read_plain_data_field<u8>(ref, "stq-qwc", dts);
|
||||
|
||||
auto header_data = deref_label(get_field_ref(ref, "header", dts));
|
||||
// guess that the header is 24 * 4 = 96 bytes here.
|
||||
// not sure what it's used for yet.
|
||||
header.resize(24);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
u32 val = deref_u32(header_data, i);
|
||||
memcpy(header.data() + i, &val, 4);
|
||||
}
|
||||
|
||||
copy_dma_to_vector(&obj, deref_label(get_field_ref(ref, "obj", dts)), obj_qwc);
|
||||
copy_dma_to_vector(&vtx, deref_label(get_field_ref(ref, "vtx", dts)), vtx_qwc);
|
||||
copy_dma_to_vector(&col, deref_label(get_field_ref(ref, "col", dts)), col_qwc);
|
||||
copy_dma_to_vector(&stq, deref_label(get_field_ref(ref, "stq", dts)), stq_qwc);
|
||||
copy_dma_to_vector(&textures, deref_label(get_field_ref(ref, "textures", dts)), header[0] * 10);
|
||||
}
|
||||
|
||||
std::string Shrubbery::print(const level_tools::PrintSettings& /*settings*/, int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
|
||||
return fmt::format("{} qwcs: {} {} {} {}, tex: {}\n", is, obj_qwc, vtx_qwc, col_qwc, stq_qwc,
|
||||
header[0] * 2);
|
||||
}
|
||||
|
||||
std::string GenericShrubFragment::print(const level_tools::PrintSettings& /*settings*/,
|
||||
int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
return fmt::format("{} qwcs: {} {} {} {}: 0x{:x}\n", is, cnt_qwc, vtx_qwc, col_qwc, stq_qwc,
|
||||
vtx_cnt);
|
||||
}
|
||||
|
||||
void GenericShrubFragment::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* /*stats*/) {
|
||||
cnt_qwc = read_plain_data_field<u8>(ref, "cnt-qwc", dts);
|
||||
vtx_qwc = read_plain_data_field<u8>(ref, "vtx-qwc", dts);
|
||||
col_qwc = read_plain_data_field<u8>(ref, "col-qwc", dts);
|
||||
stq_qwc = read_plain_data_field<u8>(ref, "stq-qwc", dts);
|
||||
vtx_cnt = read_plain_data_field<u32>(ref, "vtx-cnt", dts);
|
||||
|
||||
copy_dma_to_vector(&textures, deref_label(get_field_ref(ref, "textures", dts)), cnt_qwc);
|
||||
copy_dma_to_vector(&vtx, deref_label(get_field_ref(ref, "vtx", dts)), vtx_qwc);
|
||||
copy_dma_to_vector(&col, deref_label(get_field_ref(ref, "col", dts)), col_qwc);
|
||||
copy_dma_to_vector(&stq, deref_label(get_field_ref(ref, "stq", dts)), stq_qwc);
|
||||
}
|
||||
|
||||
} // namespace shrub_types
|
||||
|
||||
std::unique_ptr<DrawableTree> make_drawable_tree(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) {
|
||||
@@ -1150,6 +1580,12 @@ std::unique_ptr<DrawableTree> make_drawable_tree(TypedRef ref,
|
||||
tree->read_from_file(ref, dts, stats);
|
||||
return tree;
|
||||
}
|
||||
|
||||
if (ref.type->get_name() == "drawable-tree-instance-shrub") {
|
||||
auto tree = std::make_unique<shrub_types::DrawableTreeInstanceShrub>();
|
||||
tree->read_from_file(ref, dts, stats);
|
||||
return tree;
|
||||
}
|
||||
auto tree = std::make_unique<DrawableTreeUnknown>();
|
||||
tree->read_from_file(ref, dts, stats);
|
||||
return tree;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include "decompiler/util/goal_data_reader.h"
|
||||
|
||||
@@ -13,45 +14,16 @@ class DecompilerTypeSystem;
|
||||
} // namespace decompiler
|
||||
|
||||
namespace level_tools {
|
||||
|
||||
struct Vector {
|
||||
float data[4];
|
||||
|
||||
void read_from_file(Ref ref);
|
||||
|
||||
std::string print(int indent = 0) const;
|
||||
std::string print_meters(int indent = 0) const;
|
||||
};
|
||||
|
||||
struct Matrix4h {
|
||||
u16 data[16];
|
||||
void read_from_file(Ref ref);
|
||||
};
|
||||
|
||||
struct FileInfo {
|
||||
std::string file_type;
|
||||
std::string file_name;
|
||||
u32 major_version;
|
||||
u32 minor_version;
|
||||
|
||||
std::string maya_file_name;
|
||||
std::string tool_debug;
|
||||
std::string mdb_file_name;
|
||||
|
||||
void read_from_file(TypedRef ref, const decompiler::DecompilerTypeSystem& dts);
|
||||
|
||||
std::string print(int indent = 0) const;
|
||||
};
|
||||
|
||||
struct PrintSettings {
|
||||
bool print_tfrag = true;
|
||||
bool expand_draw_node = true;
|
||||
bool expand_drawable_tree_tfrag = true;
|
||||
bool expand_drawable_tree_trans_tfrag = true;
|
||||
bool expand_drawable_tree_tie_proto = true;
|
||||
bool print_tfrag = false;
|
||||
bool expand_draw_node = false;
|
||||
bool expand_drawable_tree_tfrag = false;
|
||||
bool expand_drawable_tree_trans_tfrag = false;
|
||||
bool expand_drawable_tree_tie_proto = false;
|
||||
bool expand_drawable_tree_tie_proto_data = false;
|
||||
bool expand_drawable_tree_instance_tie = false;
|
||||
bool expand_drawable_tree_actor = false;
|
||||
bool expand_shrub = true;
|
||||
};
|
||||
|
||||
struct DrawStats {
|
||||
@@ -66,6 +38,45 @@ struct DrawStats {
|
||||
std::string print() const;
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// Common Types
|
||||
/////////////////////
|
||||
|
||||
// a normal vector of 4 floats.
|
||||
struct Vector {
|
||||
float data[4];
|
||||
|
||||
void read_from_file(Ref ref);
|
||||
|
||||
std::string print(int indent = 0) const;
|
||||
std::string print_meters(int indent = 0) const;
|
||||
};
|
||||
|
||||
// a matrix with 16-bit integers.
|
||||
// typically requires some unpacking step to get meaningful values.
|
||||
struct Matrix4h {
|
||||
u16 data[16];
|
||||
void read_from_file(Ref ref);
|
||||
};
|
||||
|
||||
// A time-of-day color palette.
|
||||
// this is just the raw data, doesn't have any unpacking/meaning.
|
||||
struct TimeOfDayPalette {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 pad;
|
||||
std::vector<u32> colors;
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// Drawable BVH
|
||||
/////////////////////
|
||||
|
||||
// these types are all generic container types/base classes.
|
||||
// note that the unpacker just greedily chases things and doesn't deduplicate, so comparing
|
||||
// pointers for equality won't tell you if two things are the same game object or not.
|
||||
|
||||
// the base class for everything in the BVH tree system.
|
||||
struct Drawable {
|
||||
virtual void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -75,8 +86,9 @@ struct Drawable {
|
||||
virtual ~Drawable() = default;
|
||||
};
|
||||
|
||||
struct DrawableInlineArray : public Drawable {};
|
||||
|
||||
// a node in the BVH tree. It's just used for organizing things within a bsphere.
|
||||
// these nodes are always in inline arrays and have between 0 and 8 children.
|
||||
// the leaves of these nodes are some other type of drawable - the thing you actually want to draw.
|
||||
struct DrawNode : public Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -92,6 +104,53 @@ struct DrawNode : public Drawable {
|
||||
float distance = 0;
|
||||
};
|
||||
|
||||
// an inline array of drawable. There are more specific types for the actual arrays.
|
||||
struct DrawableInlineArray : public Drawable {};
|
||||
|
||||
// an inline array of draw nodes. All draw nodes at a level are stored in a drawable inline array.
|
||||
struct DrawableInlineArrayNode : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<DrawNode> draw_nodes;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
// the generic base class for a "tree". A tree is a BVH with between 1 and 8 DrawNode roots.
|
||||
// there's typically a tree per renderer.
|
||||
struct DrawableTree : public Drawable {};
|
||||
|
||||
// how we represent drawable trees that we don't support yet - this isn't a real type in the game.
|
||||
struct DrawableTreeUnknown : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
std::string type_name;
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayUnknown : public DrawableInlineArray {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
std::string type_name;
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// Actors
|
||||
/////////////////////
|
||||
|
||||
// there's a tree for actors - but we don't do anything with it yet.
|
||||
|
||||
struct EntityActor {};
|
||||
|
||||
struct DrawableActor : public Drawable {
|
||||
@@ -107,6 +166,25 @@ struct DrawableActor : public Drawable {
|
||||
std::string my_type() const override { return "drawable-actor"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeActor : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
|
||||
s16 id;
|
||||
s16 length;
|
||||
// todo time of day stuff
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<std::unique_ptr<DrawableInlineArray>> arrays;
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// TFRAG
|
||||
/////////////////////
|
||||
|
||||
struct TFragmentDebugData {
|
||||
u16 num_tris[4];
|
||||
u16 num_dverts[4];
|
||||
@@ -116,6 +194,7 @@ struct TFragmentDebugData {
|
||||
void read_from_file(Ref ref, const decompiler::DecompilerTypeSystem& dts, DrawStats* stats);
|
||||
};
|
||||
|
||||
// the "fragment" is just a collection of data that fits into the VU memory.
|
||||
struct TFragment : public Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -150,6 +229,67 @@ struct TFragment : public Drawable {
|
||||
// generic // 60 - 64
|
||||
};
|
||||
|
||||
// array of tfragments. This is used as part of the BVH tree
|
||||
struct DrawableInlineArrayTFrag : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<TFragment> tfragments;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
// a top-level tfragment tree.
|
||||
// it has a BVH tree of tfragments as well as a time of day palette.
|
||||
struct DrawableTreeTfrag : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
|
||||
s16 id;
|
||||
s16 length;
|
||||
TimeOfDayPalette time_of_day;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<std::unique_ptr<DrawableInlineArray>> arrays;
|
||||
};
|
||||
|
||||
// various specializations of tfragment.
|
||||
|
||||
struct DrawableTreeTransTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-trans-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeLowresTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-lowres-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeDirtTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-dirt-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeIceTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-ice-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayTransTFrag : public DrawableInlineArrayTFrag {
|
||||
std::string my_type() const override { return "drawable-inline-array-trans-tfrag"; }
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// TIE
|
||||
/////////////////////
|
||||
|
||||
// a tie-fragment is a chunk of geometry that can be sent to the VU.
|
||||
// it's similar to a tfragment, but a bit simpler.
|
||||
// each prototype is made up of fragments.
|
||||
struct TieFragment : public Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -173,6 +313,9 @@ struct TieFragment : public Drawable {
|
||||
// todo, lots more
|
||||
};
|
||||
|
||||
// represents an instance of a prototype.
|
||||
// each instance has its own color data, but the rest of the geometry/texture is shared between
|
||||
// all instances of the same prototype.
|
||||
struct InstanceTie : public Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -181,9 +324,9 @@ struct InstanceTie : public Drawable {
|
||||
std::string my_type() const override { return "instance-tie"; }
|
||||
|
||||
// (bucket-index uint16 :offset 6)
|
||||
u16 bucket_index;
|
||||
u16 bucket_index; // which prototype
|
||||
s16 id;
|
||||
Vector bsphere;
|
||||
Vector bsphere; // where we are located
|
||||
Matrix4h origin;
|
||||
u16 flags;
|
||||
u16 wind_index;
|
||||
@@ -193,101 +336,7 @@ struct InstanceTie : public Drawable {
|
||||
// todo, lots more
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayNode : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<DrawNode> draw_nodes;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayTFrag : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<TFragment> tfragments;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayInstanceTie : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<InstanceTie> instances;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayTransTFrag : public DrawableInlineArrayTFrag {
|
||||
std::string my_type() const override { return "drawable-inline-array-trans-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayUnknown : public DrawableInlineArray {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
std::string type_name;
|
||||
};
|
||||
|
||||
struct DrawableTree : public Drawable {};
|
||||
|
||||
struct TimeOfDayPalette {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 pad;
|
||||
std::vector<u32> colors;
|
||||
};
|
||||
|
||||
struct DrawableTreeTfrag : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
|
||||
s16 id;
|
||||
s16 length;
|
||||
// todo time of day stuff
|
||||
TimeOfDayPalette time_of_day;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<std::unique_ptr<DrawableInlineArray>> arrays;
|
||||
};
|
||||
|
||||
struct DrawableTreeActor : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
|
||||
s16 id;
|
||||
s16 length;
|
||||
// todo time of day stuff
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<std::unique_ptr<DrawableInlineArray>> arrays;
|
||||
};
|
||||
|
||||
// a prototype is basically just a collection of fragments
|
||||
struct PrototypeTie : public DrawableInlineArray {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -301,6 +350,9 @@ struct PrototypeTie : public DrawableInlineArray {
|
||||
std::vector<TieFragment> tie_fragments;
|
||||
};
|
||||
|
||||
// a prototype bucket is a collection of 4 different prototypes (called geometries), one for each
|
||||
// level of detail. All geometries share the same time of day palette.
|
||||
// the bucket also refers to the fact that it collect instances during actual rendering.
|
||||
struct PrototypeBucketTie {
|
||||
std::string name; // 4 - 8
|
||||
u32 flags; // 8 - 12
|
||||
@@ -337,6 +389,8 @@ struct PrototypeBucketTie {
|
||||
std::string print(const PrintSettings& settings, int indent) const;
|
||||
};
|
||||
|
||||
// an array of all the prototypes. The prototypes aren't stored in a BVH (it wouldn't make sense -
|
||||
// they can be located all over the place)- there is just a plain array.
|
||||
struct PrototypeArrayTie {
|
||||
u32 length;
|
||||
u32 allocated_length;
|
||||
@@ -347,6 +401,8 @@ struct PrototypeArrayTie {
|
||||
std::string print(const PrintSettings& settings, int indent) const;
|
||||
};
|
||||
|
||||
// the reason for this type is somewhat unknown, but it just contains the prototype array and
|
||||
// wind vectors. The wind vector data is all 0's and is updated as the game runs.
|
||||
struct ProxyPrototypeArrayTie {
|
||||
void read_from_file(TypedRef ref, const decompiler::DecompilerTypeSystem& dts, DrawStats* stats);
|
||||
std::string print(const PrintSettings& settings, int indent) const;
|
||||
@@ -355,6 +411,22 @@ struct ProxyPrototypeArrayTie {
|
||||
Ref wind_vectors;
|
||||
};
|
||||
|
||||
// array of instances. These are part of the BVH
|
||||
struct DrawableInlineArrayInstanceTie : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
|
||||
std::vector<InstanceTie> instances;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
// TIE tree
|
||||
struct DrawableTreeInstanceTie : public DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
@@ -370,31 +442,211 @@ struct DrawableTreeInstanceTie : public DrawableTree {
|
||||
std::vector<std::unique_ptr<DrawableInlineArray>> arrays;
|
||||
};
|
||||
|
||||
struct DrawableTreeTransTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-trans-tfrag"; }
|
||||
};
|
||||
/////////////////////////////////
|
||||
// SHRUB
|
||||
/////////////////////////////////
|
||||
|
||||
struct DrawableTreeLowresTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-lowres-tfrag"; }
|
||||
};
|
||||
namespace shrub_types {
|
||||
|
||||
struct DrawableTreeDirtTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-dirt-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeIceTfrag : public DrawableTreeTfrag {
|
||||
std::string my_type() const override { return "drawable-tree-ice-tfrag"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeUnknown : public DrawableTree {
|
||||
struct Shrubbery : public level_tools::Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) override;
|
||||
std::string print(const PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
std::string type_name;
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "shrubbery"; }
|
||||
|
||||
// 4 - textures
|
||||
std::vector<u8> textures;
|
||||
|
||||
std::vector<u32> header;
|
||||
u8 obj_qwc; // 12
|
||||
u8 vtx_qwc; // 13
|
||||
u8 col_qwc; // 14
|
||||
u8 stq_qwc; // 15
|
||||
|
||||
std::vector<u8> obj; // 16
|
||||
std::vector<u8> vtx; // 20
|
||||
std::vector<u8> col; // 24
|
||||
std::vector<u8> stq; // 28
|
||||
};
|
||||
|
||||
struct PrototypeShrubbery : public level_tools::DrawableInlineArray {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "prototype-shrubbery"; }
|
||||
s16 id; // 0
|
||||
s16 length; // 4
|
||||
|
||||
level_tools::Vector bsphere; // 16
|
||||
std::vector<Shrubbery> shrubs; // 32
|
||||
};
|
||||
|
||||
struct Billboard {};
|
||||
|
||||
struct GenericShrubFragment : public level_tools::Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "generic-shrub-fragment"; }
|
||||
|
||||
//
|
||||
// (textures (inline-array adgif-shader) :score 999 :offset 4)
|
||||
std::vector<u8> textures;
|
||||
// (vtx-cnt uint32 :score 999 :offset 8)
|
||||
u32 vtx_cnt;
|
||||
// (cnt-qwc uint8 :score 999 :offset 12)
|
||||
u8 cnt_qwc;
|
||||
// (vtx-qwc uint8 :score 999 :offset 13)
|
||||
u8 vtx_qwc;
|
||||
// (col-qwc uint8 :score 999 :offset 14)
|
||||
u8 col_qwc;
|
||||
// (stq-qwc uint8 :score 999 :offset 15)
|
||||
u8 stq_qwc;
|
||||
// (cnt uint32 :score 999 :offset 16)
|
||||
std::vector<u8> cnt;
|
||||
// (vtx uint32 :score 999 :offset 20)
|
||||
std::vector<u8> vtx;
|
||||
// (col uint32 :score 999 :offset 24)
|
||||
std::vector<u8> col;
|
||||
// (stq uint32 :score 999 :offset 28)
|
||||
std::vector<u8> stq;
|
||||
};
|
||||
|
||||
// really a drawable-group, but we'll make it drawable here.
|
||||
struct PrototypeGenericShrub : public level_tools::Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "prototype-generic-shrub"; }
|
||||
s16 length; // 4
|
||||
|
||||
level_tools::Vector bsphere; // 16
|
||||
std::vector<GenericShrubFragment> shrubs; // 32
|
||||
};
|
||||
|
||||
struct PrototypeBucketShrub {
|
||||
std::string name; // 4
|
||||
u32 flags; // 8
|
||||
u16 in_level; // 12
|
||||
u16 utextures; // 14
|
||||
|
||||
// PrototypeShrubbery geometry[4]; // 16
|
||||
PrototypeGenericShrub generic_geom; // 0
|
||||
PrototypeShrubbery shrubbery_geom; // 1
|
||||
// todo transparent geom
|
||||
// todo billboard geom
|
||||
|
||||
level_tools::Vector dists; // 32
|
||||
// - near-plane
|
||||
// - near-stiff
|
||||
// - mid-plane
|
||||
// - far-plane
|
||||
level_tools::Vector rdists; // 48
|
||||
// - rlength-near
|
||||
// - rlength-stiff
|
||||
// - rlength-mid
|
||||
// - stiffness
|
||||
|
||||
float stiffness; // - 60
|
||||
|
||||
// the next/last/count/mod stuff is all 0's.
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats);
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const;
|
||||
};
|
||||
|
||||
struct PrototypeInlineArrayShrub {
|
||||
s16 id; // 4
|
||||
s16 length; // 6
|
||||
level_tools::Vector bsphere; // 16
|
||||
std::vector<PrototypeBucketShrub> data; // 32
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats);
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const;
|
||||
};
|
||||
|
||||
struct PrototypeArrayShrubInfo {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats);
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const;
|
||||
|
||||
PrototypeInlineArrayShrub prototype_inline_array_shrub;
|
||||
Ref wind_vectors;
|
||||
};
|
||||
|
||||
struct InstanceShrubbery : public level_tools::Drawable {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "instance-shrubbery"; }
|
||||
|
||||
s16 id; // 4
|
||||
u16 bucket_index; // 6
|
||||
level_tools::Vector bsphere; // 16
|
||||
level_tools::Matrix4h origin; // 32
|
||||
u16 wind_index; // 62
|
||||
|
||||
// --- instance-shrubbery ---
|
||||
u32 color_indices; // 8 - unlike tie, I think this is just an integer offset
|
||||
level_tools::Vector flat_normal; // 64 (w is flat_hwidth)
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayInstanceShrub : public level_tools::DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
level_tools::Vector bsphere;
|
||||
|
||||
std::vector<InstanceShrubbery> instances;
|
||||
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override { return "drawable-inline-array-instance-shrub"; }
|
||||
};
|
||||
|
||||
struct DrawableTreeInstanceShrub : public level_tools::DrawableTree {
|
||||
void read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
level_tools::DrawStats* stats) override;
|
||||
std::string print(const level_tools::PrintSettings& settings, int indent) const override;
|
||||
std::string my_type() const override;
|
||||
|
||||
s16 id; // 0
|
||||
s16 length; // 4
|
||||
PrototypeArrayShrubInfo info; // 8
|
||||
TimeOfDayPalette time_of_day;
|
||||
level_tools::Vector bsphere; // 16
|
||||
|
||||
std::vector<std::unique_ptr<level_tools::DrawableInlineArray>> arrays;
|
||||
|
||||
// annoyingly, the shrub tree only has the top level in the array....
|
||||
// so we can't use the above "arrays" like we did in tfrag/tie.
|
||||
// luckily, it seems to be possible to figure out the location of the remaining arrays.
|
||||
// so we add this field to hold the arrays we found.
|
||||
// note that the tree format is not quite the same as tfrag/tie - the 8 child max is no longer
|
||||
// true, and the arrays are not truly by depth (the leaves aren't all the same depth)
|
||||
// this means there may be multiple arrays of instances, and we'll need to check all of them.
|
||||
std::vector<std::unique_ptr<level_tools::DrawableInlineArray>> discovered_arrays;
|
||||
};
|
||||
|
||||
} // namespace shrub_types
|
||||
|
||||
////////////////////////////////
|
||||
// Main Level Type (bsp-header)
|
||||
////////////////////////////////
|
||||
|
||||
// all the different trees are stored in a drawable-tree-array.
|
||||
struct DrawableTreeArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
@@ -406,11 +658,28 @@ struct DrawableTreeArray {
|
||||
std::vector<std::unique_ptr<DrawableTree>> trees;
|
||||
};
|
||||
|
||||
// levels may remap textures if they provide one that should be shared
|
||||
struct TextureRemap {
|
||||
u32 original_texid;
|
||||
u32 new_texid;
|
||||
};
|
||||
|
||||
// The "file info"
|
||||
struct FileInfo {
|
||||
std::string file_type;
|
||||
std::string file_name;
|
||||
u32 major_version;
|
||||
u32 minor_version;
|
||||
|
||||
std::string maya_file_name;
|
||||
std::string tool_debug;
|
||||
std::string mdb_file_name;
|
||||
|
||||
void read_from_file(TypedRef ref, const decompiler::DecompilerTypeSystem& dts);
|
||||
|
||||
std::string print(int indent = 0) const;
|
||||
};
|
||||
|
||||
struct BspHeader {
|
||||
// (info file-info :offset 4)
|
||||
FileInfo file_info;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "decompiler/level_extractor/BspHeader.h"
|
||||
#include "decompiler/level_extractor/extract_tfrag.h"
|
||||
#include "decompiler/level_extractor/extract_tie.h"
|
||||
#include "decompiler/level_extractor/extract_shrub.h"
|
||||
#include "common/util/compress.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
@@ -182,6 +183,12 @@ void extract_from_level(ObjectFileDB& db,
|
||||
bsp_header.read_from_file(bsp_file.linked_data, db.dts, &draw_stats);
|
||||
ASSERT((int)bsp_header.drawable_tree_array.trees.size() == bsp_header.drawable_tree_array.length);
|
||||
|
||||
/*
|
||||
level_tools::PrintSettings settings;
|
||||
settings.expand_shrub = true;
|
||||
fmt::print("{}\n", bsp_header.print(settings));
|
||||
*/
|
||||
|
||||
const std::set<std::string> tfrag_trees = {
|
||||
"drawable-tree-tfrag", "drawable-tree-trans-tfrag", "drawable-tree-dirt-tfrag",
|
||||
"drawable-tree-ice-tfrag", "drawable-tree-lowres-tfrag", "drawable-tree-lowres-trans-tfrag"};
|
||||
@@ -207,6 +214,12 @@ void extract_from_level(ObjectFileDB& db,
|
||||
ASSERT(as_tie_tree);
|
||||
extract_tie(as_tie_tree, fmt::format("{}-{}-tie", dgo_name, i++),
|
||||
bsp_header.texture_remap_table, tex_db, tfrag_level, dump_level);
|
||||
} else if (draw_tree->my_type() == "drawable-tree-instance-shrub") {
|
||||
auto as_shrub_tree =
|
||||
dynamic_cast<level_tools::shrub_types::DrawableTreeInstanceShrub*>(draw_tree.get());
|
||||
ASSERT(as_shrub_tree);
|
||||
extract_shrub(as_shrub_tree, fmt::format("{}-{}-shrub", dgo_name, i++),
|
||||
bsp_header.texture_remap_table, tex_db, {}, tfrag_level, dump_level);
|
||||
} else {
|
||||
// fmt::print(" unsupported tree {}\n", draw_tree->my_type());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
#include <array>
|
||||
|
||||
#include "extract_shrub.h"
|
||||
|
||||
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
||||
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
namespace decompiler {
|
||||
using namespace level_tools;
|
||||
|
||||
std::array<math::Vector4f, 4> extract_shrub_matrix(const u16* data) {
|
||||
std::array<math::Vector4f, 4> result;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s32 x = data[12 + i];
|
||||
x <<= 16;
|
||||
x >>= 10;
|
||||
result[3][i] = x;
|
||||
}
|
||||
|
||||
for (int vec = 0; vec < 3; vec++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s32 x = data[vec * 4 + i];
|
||||
x <<= 16;
|
||||
x >>= 16;
|
||||
result[vec][i] = (float)x / 4096.f;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ShrubVertex {
|
||||
math::Vector<float, 3> xyz;
|
||||
math::Vector<float, 2> st;
|
||||
math::Vector<u8, 4> rgba_generic;
|
||||
bool adc = false;
|
||||
};
|
||||
|
||||
struct ShrubDraw {
|
||||
u32 start_vtx_idx = -1;
|
||||
AdGifData adgif;
|
||||
std::vector<ShrubVertex> vertices;
|
||||
};
|
||||
|
||||
struct ShrubFrag {
|
||||
std::vector<ShrubDraw> draws;
|
||||
};
|
||||
|
||||
struct ShrubInstanceInfo {
|
||||
u32 proto_idx;
|
||||
u32 color_idx;
|
||||
std::array<math::Vector4f, 4> mat;
|
||||
math::Vector4f bsphere;
|
||||
};
|
||||
|
||||
struct ShrubProtoInfo {
|
||||
std::vector<ShrubFrag> frags;
|
||||
std::vector<ShrubInstanceInfo> instances;
|
||||
};
|
||||
|
||||
std::string debug_dump_proto_to_obj(const ShrubProtoInfo& proto) {
|
||||
std::vector<math::Vector<float, 3>> verts;
|
||||
std::vector<math::Vector<float, 2>> tcs;
|
||||
std::vector<math::Vector<int, 3>> faces;
|
||||
|
||||
for (auto& frag : proto.frags) {
|
||||
for (auto& strip : frag.draws) {
|
||||
// add verts...
|
||||
ASSERT(strip.vertices.size() >= 3);
|
||||
|
||||
int vert_idx = 0;
|
||||
|
||||
int vtx_idx_queue[3];
|
||||
|
||||
int q_idx = 0;
|
||||
int startup = 0;
|
||||
while (vert_idx < (int)strip.vertices.size()) {
|
||||
verts.push_back(strip.vertices.at(vert_idx).xyz / 65536); // no idea
|
||||
tcs.push_back(math::Vector<float, 2>{strip.vertices.at(vert_idx).st.x(),
|
||||
strip.vertices.at(vert_idx).st.y()});
|
||||
|
||||
vtx_idx_queue[q_idx++] = verts.size();
|
||||
|
||||
// wrap the index
|
||||
if (q_idx == 3) {
|
||||
q_idx = 0;
|
||||
}
|
||||
|
||||
// bump the startup
|
||||
if (startup < 3) {
|
||||
startup++;
|
||||
}
|
||||
|
||||
if (startup >= 3 && strip.vertices.at(vert_idx).adc) {
|
||||
faces.push_back(
|
||||
math::Vector<int, 3>{vtx_idx_queue[0], vtx_idx_queue[1], vtx_idx_queue[2]});
|
||||
}
|
||||
vert_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string result;
|
||||
for (auto& vert : verts) {
|
||||
result += fmt::format("v {} {} {}\n", vert.x(), vert.y(), vert.z());
|
||||
}
|
||||
for (auto& tc : tcs) {
|
||||
result += fmt::format("vt {} {}\n", tc.x(), tc.y());
|
||||
}
|
||||
for (auto& face : faces) {
|
||||
result += fmt::format("f {}/{} {}/{} {}/{}\n", face.x(), face.x(), face.y(), face.y(), face.z(),
|
||||
face.z());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ShrubProtoInfo extract_proto(const shrub_types::PrototypeBucketShrub& proto) {
|
||||
ShrubProtoInfo result;
|
||||
for (int frag_idx = 0; frag_idx < proto.generic_geom.length; frag_idx++) {
|
||||
auto& frag_out = result.frags.emplace_back();
|
||||
auto& frag = proto.generic_geom.shrubs.at(frag_idx);
|
||||
|
||||
std::vector<AdGifData> adgif_data;
|
||||
adgif_data.resize(frag.textures.size() / sizeof(AdGifData));
|
||||
memcpy(adgif_data.data(), frag.textures.data(), frag.textures.size());
|
||||
for (size_t i = 0; i < adgif_data.size(); i++) {
|
||||
auto& draw = frag_out.draws.emplace_back();
|
||||
|
||||
const auto& ag = adgif_data[i];
|
||||
int count = (ag.tex1_addr >> 32) & 0xfff; // drop the eop flag
|
||||
draw.start_vtx_idx = ((ag.tex0_addr >> 32) & 0xffff) / 3;
|
||||
|
||||
if (i > 0) {
|
||||
auto& prev_draw = frag_out.draws[frag_out.draws.size() - 2];
|
||||
ASSERT(prev_draw.start_vtx_idx + prev_draw.vertices.size() + 3 == draw.start_vtx_idx);
|
||||
}
|
||||
|
||||
for (int vert_idx = 0; vert_idx < count; vert_idx++) {
|
||||
auto& vert_out = draw.vertices.emplace_back();
|
||||
s16 vert_data[3];
|
||||
memcpy(vert_data, frag.vtx.data() + sizeof(u16) * 3 * (vert_idx + draw.start_vtx_idx),
|
||||
3 * sizeof(u16));
|
||||
vert_out.xyz = math::Vector3f(vert_data[0], vert_data[1], vert_data[2]);
|
||||
|
||||
u16 st_data[2];
|
||||
memcpy(st_data, frag.stq.data() + sizeof(u16) * 2 * (vert_idx + draw.start_vtx_idx),
|
||||
2 * sizeof(u16));
|
||||
vert_out.st = math::Vector2f(st_data[0], st_data[1]);
|
||||
vert_out.adc = (st_data[0] & 1) == 0; // adc in the low bit of texture coordinate
|
||||
|
||||
memcpy(vert_out.rgba_generic.data(), frag.col.data() + 4 * (vert_idx + draw.start_vtx_idx),
|
||||
4);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(frag.vtx_cnt * 3 * sizeof(u16) <= frag.vtx.size());
|
||||
}
|
||||
|
||||
/*
|
||||
file_util::write_text_file(
|
||||
file_util::get_file_path({fmt::format("debug_out/shrub/{}.obj", proto.name)}),
|
||||
debug_dump_proto_to_obj(result));
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
void extract_instance(const shrub_types::InstanceShrubbery& inst,
|
||||
std::vector<ShrubProtoInfo>& protos) {
|
||||
ShrubInstanceInfo result;
|
||||
result.proto_idx = inst.bucket_index;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
result.bsphere[i] = inst.bsphere.data[i];
|
||||
}
|
||||
|
||||
// from ee asm
|
||||
result.mat = extract_shrub_matrix(inst.origin.data);
|
||||
result.mat[3][0] += result.bsphere[0];
|
||||
result.mat[3][1] += result.bsphere[1];
|
||||
result.mat[3][2] += result.bsphere[2];
|
||||
// result.wind_index = instance.wind_index;
|
||||
|
||||
result.mat[0][3] = 0.f;
|
||||
|
||||
protos.at(result.proto_idx).instances.push_back(result);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Transform a point in a prototype to the actual point location in the game world.
|
||||
*/
|
||||
math::Vector<float, 3> transform_shrub(const std::array<math::Vector4f, 4> mat,
|
||||
const math::Vector3f& pt) {
|
||||
auto temp = mat[0] * pt.x() + mat[1] * pt.y() + mat[2] * pt.z() + mat[3];
|
||||
math::Vector3f result;
|
||||
result.x() = temp.x();
|
||||
result.y() = temp.y();
|
||||
result.z() = temp.z();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dump the entire tie tree to an obj. Used to debug the transform_tie function. If we get this
|
||||
* right, it should fit in with .obj's produced from the tfrag debug.
|
||||
*/
|
||||
std::string dump_full_to_obj(const std::vector<ShrubProtoInfo>& protos) {
|
||||
std::vector<math::Vector<float, 3>> verts;
|
||||
std::vector<math::Vector<int, 3>> faces;
|
||||
|
||||
for (auto& proto : protos) {
|
||||
for (auto& inst : proto.instances) {
|
||||
auto& mat = inst.mat;
|
||||
for (auto& frag : proto.frags) {
|
||||
for (auto& strip : frag.draws) {
|
||||
// add verts...
|
||||
ASSERT(strip.vertices.size() >= 3);
|
||||
|
||||
int vert_idx = 0;
|
||||
|
||||
int vtx_idx_queue[3];
|
||||
|
||||
int q_idx = 0;
|
||||
int startup = 0;
|
||||
while (vert_idx < (int)strip.vertices.size()) {
|
||||
verts.push_back(transform_shrub(mat, strip.vertices.at(vert_idx).xyz) /
|
||||
65536); // no idea
|
||||
|
||||
vtx_idx_queue[q_idx++] = verts.size();
|
||||
|
||||
// wrap the index
|
||||
if (q_idx == 3) {
|
||||
q_idx = 0;
|
||||
}
|
||||
|
||||
// bump the startup
|
||||
if (startup < 3) {
|
||||
startup++;
|
||||
}
|
||||
|
||||
if (startup >= 3 && strip.vertices.at(vert_idx).adc) {
|
||||
faces.push_back(
|
||||
math::Vector<int, 3>{vtx_idx_queue[0], vtx_idx_queue[1], vtx_idx_queue[2]});
|
||||
}
|
||||
vert_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string result;
|
||||
for (auto& vert : verts) {
|
||||
result += fmt::format("v {} {} {}\n", vert.x(), vert.y(), vert.z());
|
||||
}
|
||||
|
||||
for (auto& face : faces) {
|
||||
result += fmt::format("f {}/{} {}/{} {}/{}\n", face.x(), face.x(), face.y(), face.y(), face.z(),
|
||||
face.z());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void extract_shrub(const shrub_types::DrawableTreeInstanceShrub* tree,
|
||||
const std::string& debug_name,
|
||||
const std::vector<level_tools::TextureRemap>& /*map*/,
|
||||
const TextureDB& /*tex_db*/,
|
||||
const std::vector<std::pair<int, int>>& /*expected_missing_textures*/,
|
||||
tfrag3::Level& /*out*/,
|
||||
bool dump_level) {
|
||||
auto& protos = tree->info.prototype_inline_array_shrub;
|
||||
std::vector<ShrubProtoInfo> proto_info;
|
||||
for (auto& proto : protos.data) {
|
||||
proto_info.push_back(extract_proto(proto));
|
||||
}
|
||||
|
||||
for (auto& arr : tree->discovered_arrays) {
|
||||
auto as_shrubs = dynamic_cast<shrub_types::DrawableInlineArrayInstanceShrub*>(arr.get());
|
||||
if (as_shrubs) {
|
||||
for (auto& inst : as_shrubs->instances) {
|
||||
extract_instance(inst, proto_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_level) {
|
||||
auto path = file_util::get_file_path({fmt::format("debug_out/shrub_all/{}.obj", debug_name)});
|
||||
file_util::create_dir_if_needed_for_file(path);
|
||||
file_util::write_text_file(path, dump_full_to_obj(proto_info));
|
||||
}
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "decompiler/level_extractor/BspHeader.h"
|
||||
#include "common/math/Vector.h"
|
||||
#include "common/custom_data/Tfrag3Data.h"
|
||||
#include "decompiler/data/TextureDB.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
/// <summary>
|
||||
/// Extract shrubs from the level
|
||||
/// </summary>
|
||||
/// <param name="tree"></param>
|
||||
/// <param name="debug_name"></param>
|
||||
/// <param name="map"></param>
|
||||
/// <param name="tex_db"></param>
|
||||
/// <param name="expected_missing_textures"></param>
|
||||
/// <param name="out"></param>
|
||||
/// <param name="dump_level"></param>
|
||||
void extract_shrub(const level_tools::shrub_types::DrawableTreeInstanceShrub* tree,
|
||||
const std::string& debug_name,
|
||||
const std::vector<level_tools::TextureRemap>& map,
|
||||
const TextureDB& tex_db,
|
||||
const std::vector<std::pair<int, int>>& expected_missing_textures,
|
||||
tfrag3::Level& out,
|
||||
bool dump_level);
|
||||
|
||||
} // namespace decompiler
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
/*!
|
||||
* Get the index of the first draw node in an array. Works for node or tfrag.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the index of the first draw node in an array. Works for node or tfrag.
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <returns></returns>
|
||||
u16 get_first_idx(const level_tools::DrawableInlineArray* array) {
|
||||
auto as_tie_instances = dynamic_cast<const level_tools::DrawableInlineArrayInstanceTie*>(array);
|
||||
auto as_nodes = dynamic_cast<const level_tools::DrawableInlineArrayNode*>(array);
|
||||
@@ -23,10 +25,14 @@ u16 get_first_idx(const level_tools::DrawableInlineArray* array) {
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Verify node indices follow the patterns we expect. Takes start as the expected first,
|
||||
* writes the end.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Verify node indices follow the patterns we expect. Takes start as the expected first, writes the
|
||||
/// end.
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
/// <returns></returns>
|
||||
bool verify_node_indices_from_array(const level_tools::DrawableInlineArray* array,
|
||||
u16 start,
|
||||
u16* end) {
|
||||
|
||||
+16
-16
@@ -32,7 +32,7 @@ Like with tfrag/tie, we will do the time of day interpolation in C++.
|
||||
|
||||
The shrubs without wind effect will be converted into a single giant mesh. Doing it as a single mesh reduces the number of draw calls, and the entire mesh can be left in GPU memory the whole time.
|
||||
|
||||
The shrubs with wind effect wirgll be drawn as individual instances, as different shrubs need different wind matrices. It's likely going to be similar to `render_tree_wind`.
|
||||
The shrubs with wind effect will be drawn as individual instances, as different shrubs need different wind matrices. It's likely going to be similar to `render_tree_wind`.
|
||||
|
||||
The time-of-day effect will be done like in tfrag/tie. We will create a new time of day texture on each frame, based on the current time, and each vertex will index into a single large texture. This approach is nice because the interpolation/upload can be done in a single large batch.
|
||||
|
||||
@@ -1194,25 +1194,25 @@ L86:
|
||||
vmadday.xyzw acc, vf29, vf12
|
||||
sh t8, 6536(t0)
|
||||
vmaddz.xyzw vf12, vf30, vf12
|
||||
lw t4, 12(a2)
|
||||
lw t4, 12(a2) ;; load the generic geometry?
|
||||
vmulax.xyzw acc, vf28, vf13
|
||||
lw t5, 6532(t0)
|
||||
vmadday.xyzw acc, vf29, vf13
|
||||
lh t6, 2(t4)
|
||||
lh t6, 2(t4) ;; generic frag count.
|
||||
vmaddaz.xyzw acc, vf30, vf13
|
||||
lw a2, 6528(t0)
|
||||
vmaddw.xyzw vf13, vf31, vf0
|
||||
lw t7, 6516(t0)
|
||||
vitof0.xyz vf24, vf24
|
||||
sh t8, 6368(t0)
|
||||
B58:
|
||||
B58: ;; generic loop
|
||||
L87:
|
||||
daddiu t8, a3, -115
|
||||
sll r0, r0, 0
|
||||
blez t8, L90
|
||||
lw t8, 28(t4)
|
||||
lw t8, 28(t4) ;; load the frag
|
||||
|
||||
B59:
|
||||
B59: ;; dma
|
||||
L88:
|
||||
lw t3, 0(a0)
|
||||
sll r0, r0, 0
|
||||
@@ -1272,7 +1272,7 @@ L91:
|
||||
daddiu a3, a3, 12
|
||||
sqc2 vf12, 48(t3)
|
||||
sll r0, r0, 0
|
||||
lw ra, 4(t8)
|
||||
lw ra, 4(t8) ;; ra = vtx-cnt
|
||||
sll r0, r0, 0
|
||||
sqc2 vf13, 64(t3)
|
||||
sll r0, r0, 0
|
||||
@@ -1280,9 +1280,9 @@ L91:
|
||||
sll r0, r0, 0
|
||||
sw ra, 96(t3)
|
||||
sll r0, r0, 0
|
||||
lw ra, 12(t8)
|
||||
lw ra, 12(t8) ;; ra = cnt
|
||||
sll r0, r0, 0
|
||||
lbu gp, 8(t8)
|
||||
lbu gp, 8(t8) ;; gp = cnt-qwc
|
||||
sll r0, r0, 0
|
||||
sw ra, 20(t9)
|
||||
sll r0, r0, 0
|
||||
@@ -1290,25 +1290,25 @@ L91:
|
||||
sll r0, r0, 0
|
||||
sb gp, 30(t9)
|
||||
sll r0, r0, 0
|
||||
lw ra, 24(t8)
|
||||
lw ra, 24(t8) ;; ra = stq
|
||||
sll r0, r0, 0
|
||||
lbu gp, 11(t8)
|
||||
lbu gp, 11(t8) ;; gp = stq-qwc
|
||||
sll r0, r0, 0
|
||||
sw ra, 36(t9)
|
||||
sll r0, r0, 0
|
||||
sb gp, 32(t9)
|
||||
sll r0, r0, 0
|
||||
lw ra, 20(t8)
|
||||
lw ra, 20(t8) ;; ra = col
|
||||
sll r0, r0, 0
|
||||
lbu gp, 10(t8)
|
||||
lbu gp, 10(t8) ;; gp = col-qwc
|
||||
sll r0, r0, 0
|
||||
sw ra, 52(t9)
|
||||
sll r0, r0, 0
|
||||
sb gp, 48(t9)
|
||||
sll r0, r0, 0
|
||||
lw ra, 16(t8)
|
||||
lw ra, 16(t8) ;; ra = vtx
|
||||
sll r0, r0, 0
|
||||
lbu gp, 9(t8)
|
||||
lbu gp, 9(t8) ;; gp = vtx-qwc
|
||||
sll r0, r0, 0
|
||||
sw ra, 68(t9)
|
||||
sll r0, r0, 0
|
||||
@@ -1483,4 +1483,4 @@ L98:
|
||||
sll r0, r0, 0
|
||||
sll r0, r0, 0
|
||||
sll r0, r0, 0
|
||||
```
|
||||
```
|
||||
|
||||
@@ -428,7 +428,7 @@ bool Loader::upload_textures(Timer& timer, LevelData& data, TexturePool& texture
|
||||
return data.textures.size() == data.level->textures.size();
|
||||
}
|
||||
|
||||
void Loader::update_blocking(std::string& status_out, TexturePool& tex_pool) {
|
||||
void Loader::update_blocking(TexturePool& tex_pool) {
|
||||
fmt::print("NOTE: coming out of blackout on next frame, doing all loads now...\n");
|
||||
|
||||
bool missing_levels = true;
|
||||
@@ -457,7 +457,7 @@ void Loader::update_blocking(std::string& status_out, TexturePool& tex_pool) {
|
||||
}
|
||||
|
||||
if (needs_run) {
|
||||
update(status_out, tex_pool);
|
||||
update(tex_pool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ void Loader::update_blocking(std::string& status_out, TexturePool& tex_pool) {
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::update(std::string& status_out, TexturePool& texture_pool) {
|
||||
void Loader::update(TexturePool& texture_pool) {
|
||||
Timer loader_timer;
|
||||
|
||||
// only main thread can touch this.
|
||||
|
||||
@@ -15,8 +15,8 @@ class Loader {
|
||||
static constexpr float SHARED_TEXTURE_LOAD_BUDGET = 3.f;
|
||||
Loader();
|
||||
~Loader();
|
||||
void update(std::string& status_out, TexturePool& tex_pool);
|
||||
void update_blocking(std::string& status_out, TexturePool& tex_pool);
|
||||
void update(TexturePool& tex_pool);
|
||||
void update_blocking(TexturePool& tex_pool);
|
||||
|
||||
struct LevelData {
|
||||
std::unique_ptr<tfrag3::Level> level;
|
||||
|
||||
@@ -291,11 +291,10 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
|
||||
auto prof = m_profiler.root()->make_scoped_child("loader");
|
||||
if (m_last_pmode_alp == 0 && settings.pmode_alp_register != 0 && m_enable_fast_blackout_loads) {
|
||||
// blackout, load everything and don't worry about frame rate
|
||||
m_render_state.loader->update_blocking(m_render_state.load_status_debug,
|
||||
*m_render_state.texture_pool);
|
||||
m_render_state.loader->update_blocking(*m_render_state.texture_pool);
|
||||
|
||||
} else {
|
||||
m_render_state.loader->update(m_render_state.load_status_debug, *m_render_state.texture_pool);
|
||||
m_render_state.loader->update(*m_render_state.texture_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
;; shrubbery
|
||||
;;;;;;;;;;;;;;;;
|
||||
|
||||
#|
|
||||
|
||||
(set! (-> *instance-shrub-work* paused) (paused?))
|
||||
(when (nonzero? (-> *background-work* shrub-tree-count))
|
||||
(if *debug-segment*
|
||||
@@ -217,14 +217,14 @@
|
||||
(let ((s5-0 (-> *background-work* shrub-trees gp-0))
|
||||
(s4-0 (-> *background-work* shrub-levels gp-0))
|
||||
)
|
||||
;; setup colors for shrub
|
||||
(if (nonzero? (-> s5-0 colors-added))
|
||||
(time-of-day-interp-colors
|
||||
(-> *instance-shrub-work* colors)
|
||||
(-> s5-0 colors-added)
|
||||
(-> s4-0 mood)
|
||||
)
|
||||
)
|
||||
;; setup colors for shrub (skipping because I don't think we'll need it here...)
|
||||
; (if (nonzero? (-> s5-0 colors-added))
|
||||
; (time-of-day-interp-colors
|
||||
; (-> *instance-shrub-work* colors)
|
||||
; (-> s5-0 colors-added)
|
||||
; (-> s4-0 mood)
|
||||
; )
|
||||
; )
|
||||
;; and draw!
|
||||
(draw-drawable-tree-instance-shrub s5-0 s4-0)
|
||||
)
|
||||
@@ -237,7 +237,7 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
|#
|
||||
|
||||
|
||||
|
||||
(let ((gp-1 (the-as level #f)))
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; definition for symbol *instance-shrub-work*, type instance-shrub-work
|
||||
(define
|
||||
*instance-shrub-work*
|
||||
(new 'static 'instance-shrub-work
|
||||
@@ -34,27 +35,27 @@
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x10000005 #x0 #x0 #x6c0501a3))
|
||||
)
|
||||
:count-tmpl
|
||||
(new 'static 'inline-array qword 20
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #xa))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x1))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x2))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x3))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x4))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x5))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x6))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x7))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x8))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x9))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #xa))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x1))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x2))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x3))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x4))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x5))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x6))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x7))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x8))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x9))
|
||||
(new 'static 'inline-array vector4w 20
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 10)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 1)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 2)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 3)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 4)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 5)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 6)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 7)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 8)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 9)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 10)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 1)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 2)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 3)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 4)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 5)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 6)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 7)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 8)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 9)
|
||||
)
|
||||
:mscalf-tmpl
|
||||
(new 'static 'dma-packet
|
||||
@@ -477,10 +478,14 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set! (-> *instance-shrub-work* mscalf-tmpl vif0 imm) 103)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set! (-> *instance-shrub-work* mscalf-ret-tmpl vif0 imm) 103)
|
||||
|
||||
;; definition for function upload-generic-shrub
|
||||
;; Used lq/sq
|
||||
(defun upload-generic-shrub ((arg0 dma-buffer) (arg1 generic-shrub-fragment) (arg2 int) (arg3 int))
|
||||
(let* ((v1-0 arg0)
|
||||
(t0-0 (the-as object (-> v1-0 base)))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
(deftype shrub-view-data (structure)
|
||||
((data uint128 3 :offset-assert 0)
|
||||
(texture-giftag qword :inline :offset 0)
|
||||
(texture-giftag gs-gif-tag :inline :offset 0) ;; was qword
|
||||
(consts vector :inline :offset 16)
|
||||
(fog-clamp vector :inline :offset 32)
|
||||
(tex-start-ptr int32 :offset 16)
|
||||
@@ -50,7 +50,8 @@
|
||||
)
|
||||
|
||||
(deftype instance-shrubbery (instance)
|
||||
((flat-normal vector :inline :offset-assert 64)
|
||||
((color-indices uint32 :offset 8) ;; added
|
||||
(flat-normal vector :inline :offset-assert 64)
|
||||
(flat-hwidth float :offset 76)
|
||||
(color uint32 :offset 8)
|
||||
)
|
||||
@@ -70,7 +71,7 @@
|
||||
|
||||
(deftype drawable-tree-instance-shrub (drawable-tree)
|
||||
((info prototype-array-shrub-info :offset 8)
|
||||
(colors-added uint32 :offset 12) ;; added
|
||||
(colors-added time-of-day-palette :offset 12) ;; added
|
||||
)
|
||||
:method-count-assert #x12
|
||||
:size-assert #x24
|
||||
@@ -194,66 +195,70 @@
|
||||
)
|
||||
|
||||
(deftype instance-shrub-work (structure)
|
||||
((dummy qword 3 :inline :offset-assert 0)
|
||||
(chaina qword 8 :inline :offset-assert 48)
|
||||
(chainb qword 8 :inline :offset-assert 176)
|
||||
(colors rgba 1024 :offset-assert 304)
|
||||
(matrix-tmpl qword 20 :inline :offset-assert 4400)
|
||||
(count-tmpl qword 20 :inline :offset-assert 4720)
|
||||
(mscalf-tmpl dma-packet :inline :offset-assert 5040)
|
||||
(mscalf-ret-tmpl dma-packet :inline :offset-assert 5056)
|
||||
(adgif-tmpl dma-gif-packet :inline :offset-assert 5072)
|
||||
(billboard-tmpl dma-gif-packet :inline :offset-assert 5104)
|
||||
(billboard-const vector :inline :offset-assert 5136)
|
||||
(shrub-near-packets shrub-near-packet 6 :inline :offset-assert 5152)
|
||||
(dma-ref dma-packet :inline :offset-assert 6016)
|
||||
(dma-end dma-packet :inline :offset-assert 6032)
|
||||
(wind-const vector :inline :offset-assert 6048)
|
||||
(constants vector :inline :offset-assert 6064)
|
||||
(color-constant vector4w :inline :offset-assert 6080)
|
||||
(hmge-d vector :inline :offset-assert 6096)
|
||||
(hvdf-offset vector :inline :offset-assert 6112)
|
||||
(wind-force vector :inline :offset-assert 6128)
|
||||
(color vector :inline :offset-assert 6144)
|
||||
(bb-color vector :inline :offset-assert 6160)
|
||||
(min-dist vector :inline :offset-assert 6176)
|
||||
(temp-vec vector :inline :offset-assert 6192)
|
||||
(guard-plane plane 4 :inline :offset-assert 6208)
|
||||
(plane plane 4 :inline :offset-assert 6272)
|
||||
(last uint32 4 :offset-assert 6336)
|
||||
(next uint32 4 :offset-assert 6352)
|
||||
(count uint16 4 :offset-assert 6368)
|
||||
(mod-count uint16 4 :offset-assert 6376)
|
||||
(wind-vectors uint32 :offset-assert 6384)
|
||||
(instance-ptr uint32 :offset-assert 6388)
|
||||
(chain-ptr uint32 :offset-assert 6392)
|
||||
(chain-ptr-next uint32 :offset-assert 6396)
|
||||
(stack-ptr uint32 :offset-assert 6400)
|
||||
(bucket-ptr uint32 :offset-assert 6404)
|
||||
(src-ptr uint32 :offset-assert 6408)
|
||||
(to-spr uint32 :offset-assert 6412)
|
||||
(from-spr uint32 :offset-assert 6416)
|
||||
(shrub-count uint32 :offset-assert 6420)
|
||||
(node uint32 6 :offset 6428)
|
||||
(length uint32 6 :offset-assert 6452)
|
||||
(prototypes uint32 :offset-assert 6476)
|
||||
(start-bank uint8 20 :offset 6484)
|
||||
(buffer-index uint32 :offset-assert 6504)
|
||||
(current-spr uint32 :offset-assert 6508)
|
||||
(current-mem uint32 :offset-assert 6512)
|
||||
(current-shrub-near-packet uint32 :offset-assert 6516)
|
||||
(dma-buffer basic :offset 6524)
|
||||
(near-last uint32 :offset-assert 6528)
|
||||
(near-next uint32 :offset-assert 6532)
|
||||
(near-count uint32 :offset-assert 6536)
|
||||
(last-shrubs uint32 :offset-assert 6540)
|
||||
(chains uint32 :offset-assert 6544)
|
||||
(flags uint32 :offset-assert 6548)
|
||||
(paused basic :offset-assert 6552)
|
||||
(node-count uint32 :offset-assert 6556)
|
||||
(inst-count uint32 :offset-assert 6560)
|
||||
(wait-from-spr uint32 :offset-assert 6564)
|
||||
(wait-to-spr uint32 :offset-assert 6568)
|
||||
((dummy qword 3 :inline :offset-assert 0)
|
||||
(chaina qword 8 :inline :offset-assert 48)
|
||||
(chainb qword 8 :inline :offset-assert 176)
|
||||
(colors rgba 1024 :offset-assert 304)
|
||||
(matrix-tmpl qword 20 :inline :offset-assert 4400)
|
||||
(count-tmpl vector4w 20 :inline :offset-assert 4720)
|
||||
(mscalf-tmpl dma-packet :inline :offset-assert 5040)
|
||||
(mscalf-ret-tmpl dma-packet :inline :offset-assert 5056)
|
||||
(adgif-tmpl dma-gif-packet :inline :offset-assert 5072)
|
||||
(billboard-tmpl dma-gif-packet :inline :offset-assert 5104)
|
||||
(billboard-const vector :inline :offset-assert 5136)
|
||||
(shrub-near-packets shrub-near-packet 6 :inline :offset-assert 5152)
|
||||
(dma-ref dma-packet :inline :offset-assert 6016)
|
||||
(dma-end dma-packet :inline :offset-assert 6032)
|
||||
(wind-const vector :inline :offset-assert 6048)
|
||||
(constants vector :inline :offset-assert 6064)
|
||||
(color-constant vector4w :inline :offset-assert 6080)
|
||||
(hmge-d vector :inline :offset-assert 6096)
|
||||
(hvdf-offset vector :inline :offset-assert 6112)
|
||||
(wind-force vector :inline :offset-assert 6128)
|
||||
(color vector :inline :offset-assert 6144)
|
||||
(bb-color vector :inline :offset-assert 6160)
|
||||
(min-dist vector :inline :offset-assert 6176)
|
||||
(temp-vec vector :inline :offset-assert 6192)
|
||||
(guard-plane plane 4 :inline :offset-assert 6208)
|
||||
(plane plane 4 :inline :offset-assert 6272)
|
||||
(last uint32 4 :offset-assert 6336)
|
||||
(next uint32 4 :offset-assert 6352)
|
||||
(count uint16 4 :offset-assert 6368)
|
||||
(mod-count uint16 4 :offset-assert 6376)
|
||||
(wind-vectors uint32 :offset-assert 6384)
|
||||
(instance-ptr uint32 :offset-assert 6388)
|
||||
(chain-ptr uint32 :offset-assert 6392)
|
||||
(chain-ptr-next uint32 :offset-assert 6396)
|
||||
(stack-ptr uint32 :offset-assert 6400)
|
||||
(bucket-ptr uint32 :offset-assert 6404)
|
||||
(src-ptr uint32 :offset-assert 6408)
|
||||
(to-spr uint32 :offset-assert 6412)
|
||||
(from-spr uint32 :offset-assert 6416)
|
||||
(shrub-count uint32 :offset-assert 6420)
|
||||
;;(stack-ptr uint32 :offset-assert 6400) ;; this field appears twice?
|
||||
(node uint32 6 :offset 6428)
|
||||
(length uint32 6 :offset-assert 6452)
|
||||
(prototypes uint32 :offset-assert 6476)
|
||||
;;(bucket-ptr uint32 :offset-assert 6404) appears twice
|
||||
|
||||
(start-bank uint8 20 :offset 6484)
|
||||
(buffer-index uint32 :offset-assert 6504)
|
||||
(current-spr uint32 :offset-assert 6508)
|
||||
(current-mem uint32 :offset-assert 6512)
|
||||
(current-shrub-near-packet uint32 :offset-assert 6516)
|
||||
;;(to-spr uint32 :offset-assert 6412)
|
||||
(dma-buffer basic :offset 6524)
|
||||
(near-last uint32 :offset-assert 6528)
|
||||
(near-next uint32 :offset-assert 6532)
|
||||
(near-count uint32 :offset-assert 6536)
|
||||
(last-shrubs uint32 :offset-assert 6540)
|
||||
(chains uint32 :offset-assert 6544)
|
||||
(flags uint32 :offset-assert 6548)
|
||||
(paused basic :offset-assert 6552)
|
||||
(node-count uint32 :offset-assert 6556)
|
||||
(inst-count uint32 :offset-assert 6560)
|
||||
(wait-from-spr uint32 :offset-assert 6564)
|
||||
(wait-to-spr uint32 :offset-assert 6568)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x19ac
|
||||
|
||||
@@ -5,6 +5,606 @@
|
||||
;; name in dgo: shrubbery
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(defmethod login billboard ((obj billboard))
|
||||
"Set up the billboard adgif shader"
|
||||
(adgif-shader-login (-> obj flat))
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage billboard ((obj billboard) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory used for the billboard."
|
||||
(set! (-> arg0 length) (max 34 (-> arg0 length)))
|
||||
(set! (-> arg0 data 33 name) "billboard")
|
||||
(+! (-> arg0 data 33 count) 1)
|
||||
(let ((v1-6 (asize-of obj)))
|
||||
(+! (-> arg0 data 33 used) v1-6)
|
||||
(+! (-> arg0 data 33 total) (logand -16 (+ v1-6 15)))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defun-recursive mem-usage-shrub-walk draw-node ((arg0 draw-node) (arg1 int) (arg2 memory-usage-block) (arg3 int))
|
||||
"Recursively iterate through the entire shrub tree and compute memory usage for instances."
|
||||
(set! (-> arg2 length) (max 62 (-> arg2 length)))
|
||||
(set! (-> arg2 data 61 name) "draw-node")
|
||||
(+! (-> arg2 data 61 count) arg1)
|
||||
(let ((v1-5 (* arg1 32)))
|
||||
(+! (-> arg2 data 61 used) v1-5)
|
||||
(+! (-> arg2 data 61 total) (logand -16 (+ v1-5 15)))
|
||||
)
|
||||
(let ((s2-0 arg0))
|
||||
(dotimes (s1-0 arg1)
|
||||
(let ((a1-2 (-> s2-0 child-count)))
|
||||
(cond
|
||||
((logtest? (-> s2-0 flags) 1)
|
||||
(mem-usage-shrub-walk (the-as draw-node (-> s2-0 child)) (the-as int a1-2) arg2 arg3)
|
||||
)
|
||||
(else
|
||||
(set! (-> arg2 length) (max 35 (-> arg2 length)))
|
||||
(set! (-> arg2 data 34 name) "instance-shrubbery")
|
||||
(+! (-> arg2 data 34 count) a1-2)
|
||||
(let ((v1-18 (* (the-as uint 80) a1-2)))
|
||||
(+! (-> arg2 data 34 used) v1-18)
|
||||
(+! (-> arg2 data 34 total) (logand -16 (+ v1-18 15)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(&+! s2-0 32)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
)
|
||||
|
||||
(defmethod mem-usage drawable-tree-instance-shrub ((obj drawable-tree-instance-shrub) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute memory usage for an entire shrub tree"
|
||||
(set! (-> arg0 length) (max 1 (-> arg0 length)))
|
||||
(set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
|
||||
(+! (-> arg0 data 0 count) 1)
|
||||
(let ((v1-7 32))
|
||||
(+! (-> arg0 data 0 used) v1-7)
|
||||
(+! (-> arg0 data 0 total) (logand -16 (+ v1-7 15)))
|
||||
)
|
||||
;; time of day colors
|
||||
(when (nonzero? (-> obj colors-added))
|
||||
(set! (-> arg0 length) (max 33 (-> arg0 length)))
|
||||
(set! (-> arg0 data 32 name) "shrubbery-pal")
|
||||
(+! (-> arg0 data 32 count) 1)
|
||||
(let ((v1-19 (asize-of (-> obj colors-added))))
|
||||
(+! (-> arg0 data 32 used) v1-19)
|
||||
(+! (-> arg0 data 32 total) (logand -16 (+ v1-19 15)))
|
||||
)
|
||||
)
|
||||
;; instance tree
|
||||
(mem-usage-shrub-walk
|
||||
(the-as draw-node (&+ (-> obj data 0) 32))
|
||||
(-> (the-as drawable-group (-> obj data 0)) length)
|
||||
arg0
|
||||
arg1
|
||||
)
|
||||
;; prototypes
|
||||
(mem-usage (-> obj info prototype-inline-array-shrub) arg0 (logior arg1 1))
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod login generic-shrub-fragment ((obj generic-shrub-fragment))
|
||||
"Set up shaders in a generic shrub fragment"
|
||||
(let ((s5-0 (/ (-> obj cnt-qwc) (the-as uint 5))))
|
||||
(dotimes (s4-0 (the-as int s5-0))
|
||||
(adgif-shader-login-no-remap (-> obj textures s4-0))
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage generic-shrub-fragment ((obj generic-shrub-fragment) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute memory usage of generic shrub fragment"
|
||||
(set! (-> arg0 length) (max 27 (-> arg0 length)))
|
||||
(set! (-> arg0 data 25 name) "generic-shrub")
|
||||
(+! (-> arg0 data 25 count) 1)
|
||||
;; the actual fragment object
|
||||
(let ((v1-6 (asize-of obj)))
|
||||
(+! (-> arg0 data 25 used) v1-6)
|
||||
(+! (-> arg0 data 25 total) (logand -16 (+ v1-6 15)))
|
||||
)
|
||||
;; the referenced data
|
||||
(set! (-> arg0 data 26 name) "generic-shrub-data")
|
||||
(+! (-> arg0 data 26 count) 1)
|
||||
(let ((v1-17 (* (+ (-> obj cnt-qwc) (-> obj vtx-qwc) (-> obj col-qwc) (-> obj stq-qwc)) 16)))
|
||||
(+! (-> arg0 data 26 used) v1-17)
|
||||
(+! (-> arg0 data 26 total) (logand -16 (+ v1-17 15)))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod inspect prototype-shrubbery ((obj prototype-shrubbery))
|
||||
"Inspect all prototypes in a prototype array."
|
||||
(format #t "[~8x] ~A~%" obj (-> obj type))
|
||||
(format #t "~Tlength: ~D~%" (-> obj length))
|
||||
(format #t "~Tdata[~D]: @ #x~X~%" (-> obj length) (-> obj data))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(format #t "~T [~D] ~A~%" s5-0 (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-shrubbery ((obj prototype-shrubbery) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute memory usage of all prototypes in a prototype array."
|
||||
(set! (-> arg0 length) (max 1 (-> arg0 length)))
|
||||
(set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
|
||||
(+! (-> arg0 data 0 count) 1)
|
||||
(let ((v1-7 32))
|
||||
(+! (-> arg0 data 0 used) v1-7)
|
||||
(+! (-> arg0 data 0 total) (logand -16 (+ v1-7 15)))
|
||||
)
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj data s3-0) arg0 arg1)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod login prototype-shrubbery ((obj prototype-shrubbery))
|
||||
"Login all prototypes in a prototype array"
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod asize-of prototype-shrubbery ((obj prototype-shrubbery))
|
||||
"Compute the allocation size of a prototype shrubbery array (dynamically sized)"
|
||||
(the-as int (+ (-> prototype-shrubbery size) (* (+ (-> obj length) -1) 32)))
|
||||
)
|
||||
|
||||
(defmethod login prototype-generic-shrub ((obj prototype-generic-shrub))
|
||||
"Initialize all fragments in a generic prototype."
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod login shrubbery ((obj shrubbery))
|
||||
"Initialize a shrubbery fragment."
|
||||
(let ((s5-0 (* (-> obj header data 0) 2)))
|
||||
(dotimes (s4-0 (the-as int s5-0))
|
||||
(adgif-shader-login-no-remap (-> obj textures s4-0))
|
||||
)
|
||||
)
|
||||
(shrubbery-login-post-texture obj)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage shrubbery ((obj shrubbery) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory usage of a shrubbery fragment."
|
||||
(set! (-> arg0 length) (max 28 (-> arg0 length)))
|
||||
(set! (-> arg0 data 27 name) "shrubbery")
|
||||
(+! (-> arg0 data 27 count) 1)
|
||||
(let ((v1-6 (asize-of obj)))
|
||||
(+! (-> arg0 data 27 used) v1-6)
|
||||
(+! (-> arg0 data 27 total) (logand -16 (+ v1-6 15)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 30 (-> arg0 length)))
|
||||
(set! (-> arg0 data 29 name) "shrubbery-vertex")
|
||||
(+! (-> arg0 data 29 count) 1)
|
||||
(let ((v1-16 (* (-> obj vtx-qwc) 16)))
|
||||
(+! (-> arg0 data 29 used) v1-16)
|
||||
(+! (-> arg0 data 29 total) (logand -16 (+ v1-16 15)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 31 (-> arg0 length)))
|
||||
(set! (-> arg0 data 30 name) "shrubbery-color")
|
||||
(+! (-> arg0 data 30 count) 1)
|
||||
(let ((v1-26 (* (-> obj col-qwc) 16)))
|
||||
(+! (-> arg0 data 30 used) v1-26)
|
||||
(+! (-> arg0 data 30 total) (logand -16 (+ v1-26 15)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 29 (-> arg0 length)))
|
||||
(set! (-> arg0 data 28 name) "shrubbery-object")
|
||||
(+! (-> arg0 data 28 count) 1)
|
||||
(let ((v1-36 (* (-> obj obj-qwc) 16)))
|
||||
(+! (-> arg0 data 28 used) v1-36)
|
||||
(+! (-> arg0 data 28 total) (logand -16 (+ v1-36 15)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 32 (-> arg0 length)))
|
||||
(set! (-> arg0 data 31 name) "shrubbery-stq")
|
||||
(+! (-> arg0 data 31 count) 1)
|
||||
(let ((v1-46 (* (-> obj stq-qwc) 16)))
|
||||
(+! (-> arg0 data 31 used) v1-46)
|
||||
(+! (-> arg0 data 31 total) (logand -16 (+ v1-46 15)))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod login drawable-tree-instance-shrub ((obj drawable-tree-instance-shrub))
|
||||
"Initialize a shrubbery tree."
|
||||
(if (nonzero? (-> obj info prototype-inline-array-shrub))
|
||||
(login (-> obj info prototype-inline-array-shrub))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(define shrub-vu1-block (new 'static 'vu-function #|:length #x26a :qlength #x135|#))
|
||||
|
||||
(defun shrub-num-tris ((arg0 shrubbery))
|
||||
"Get the number of triangles in a shrubbery fragment."
|
||||
(- (-> arg0 header data 2) (* (-> arg0 header data 1) 2))
|
||||
)
|
||||
|
||||
(defun shrub-make-perspective-matrix ((arg0 matrix))
|
||||
"Compute the matrix used by the shrubbery VU1 program."
|
||||
(let* ((v1-0 arg0)
|
||||
(t0-0 (-> *math-camera* camera-temp))
|
||||
(a1-1 (-> t0-0 vector 0 quad))
|
||||
(a2-0 (-> t0-0 vector 1 quad))
|
||||
(a3-0 (-> t0-0 vector 2 quad))
|
||||
(t0-1 (-> t0-0 vector 3 quad))
|
||||
)
|
||||
(set! (-> v1-0 vector 0 quad) a1-1)
|
||||
(set! (-> v1-0 vector 1 quad) a2-0)
|
||||
(set! (-> v1-0 vector 2 quad) a3-0)
|
||||
(set! (-> v1-0 vector 3 quad) t0-1)
|
||||
)
|
||||
(let ((f0-1 (/ 1.0 (-> *math-camera* pfog0))))
|
||||
(set! (-> arg0 vector 0 w) (* (-> arg0 vector 0 w) f0-1))
|
||||
(set! (-> arg0 vector 1 w) (* (-> arg0 vector 1 w) f0-1))
|
||||
(set! (-> arg0 vector 2 w) (* (-> arg0 vector 2 w) f0-1))
|
||||
(set! (-> arg0 vector 3 w) (* (-> arg0 vector 3 w) f0-1))
|
||||
)
|
||||
(+! (-> arg0 vector 0 x) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off x)))
|
||||
(+! (-> arg0 vector 1 x) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off x)))
|
||||
(+! (-> arg0 vector 2 x) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off x)))
|
||||
(+! (-> arg0 vector 3 x) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off x)))
|
||||
(+! (-> arg0 vector 0 y) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off y)))
|
||||
(+! (-> arg0 vector 1 y) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off y)))
|
||||
(+! (-> arg0 vector 2 y) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off y)))
|
||||
(+! (-> arg0 vector 3 y) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off y)))
|
||||
(+! (-> arg0 vector 0 z) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off z)))
|
||||
(+! (-> arg0 vector 1 z) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off z)))
|
||||
(+! (-> arg0 vector 2 z) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off z)))
|
||||
(+! (-> arg0 vector 3 z) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off z)))
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun shrub-init-view-data ((arg0 shrub-view-data))
|
||||
"Initialize shrubbery constants in place"
|
||||
(set! (-> arg0 texture-giftag tag) (new 'static 'gif-tag64 :nloop #x1 :nreg #x4))
|
||||
(set! (-> arg0 texture-giftag regs) (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id a+d)
|
||||
:regs1 (gif-reg-id a+d)
|
||||
:regs2 (gif-reg-id a+d)
|
||||
:regs3 (gif-reg-id a+d)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 texture-giftag word 3) (the-as uint #x40a00000))
|
||||
(set! (-> arg0 tex-start-ptr) (the-as int 25167696.0))
|
||||
(set! (-> arg0 mtx-buf-ptr) (the-as int 8388608.0))
|
||||
(set! (-> arg0 fog-0) (-> *math-camera* pfog0))
|
||||
(set! (-> arg0 fog-1) (-> *math-camera* pfog1))
|
||||
(set! (-> arg0 fog-min) (-> *math-camera* fog-min))
|
||||
(set! (-> arg0 fog-max) (-> *math-camera* fog-max))
|
||||
#f
|
||||
)
|
||||
|
||||
(defun shrub-upload-view-data ((arg0 dma-buffer))
|
||||
"Generate DMA data to upload shrubbery constants to VU1."
|
||||
(let ((s5-0 3))
|
||||
(let* ((v1-0 arg0)
|
||||
(a0-1 (the-as object (-> v1-0 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-1) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s5-0))
|
||||
(set! (-> (the-as dma-packet a0-1) vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> (the-as dma-packet a0-1) vif1) (new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32) :num s5-0))
|
||||
(set! (-> v1-0 base) (&+ (the-as pointer a0-1) 16))
|
||||
)
|
||||
(shrub-init-view-data (the-as shrub-view-data (-> arg0 base)))
|
||||
(&+! (-> arg0 base) (* s5-0 16))
|
||||
)
|
||||
#f
|
||||
)
|
||||
|
||||
(defun shrub-time ((arg0 int) (arg1 int) (arg2 int) (arg3 int) (arg4 int))
|
||||
(+ (* arg0 8) 29 (* 22 arg2) (* 11 arg1) (* (+ (* arg4 2) 15 (* 5 arg2) (* 13 arg0)) arg3) 53)
|
||||
)
|
||||
|
||||
(defun shrub-do-init-frame ((arg0 dma-buffer))
|
||||
"Generate DMA to initialize the shrubbery renderer on VU1."
|
||||
;; upload VU1 program
|
||||
(dma-buffer-add-vu-function arg0 shrub-vu1-block 1)
|
||||
;; upload constants
|
||||
(shrub-upload-view-data arg0)
|
||||
;; run program initialization function
|
||||
(let* ((v1-0 arg0)
|
||||
(a0-3 (the-as object (-> v1-0 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-3) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-3) vif0) (new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #x0))
|
||||
(set! (-> (the-as dma-packet a0-3) vif1) (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
|
||||
(set! (-> v1-0 base) (&+ (the-as pointer a0-3) 16))
|
||||
)
|
||||
;; initialize VIF for shrubbery chains.
|
||||
(let* ((v1-1 arg0)
|
||||
(a0-5 (the-as object (-> v1-1 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-5) dma) (new 'static 'dma-tag :qwc #x3 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-5) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-5) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> v1-1 base) (&+ (the-as pointer a0-5) 16))
|
||||
)
|
||||
(let ((v1-2 (-> arg0 base)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-2) 0) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 1) (the-as uint #x8080))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 2) (the-as uint #x8080))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 3) (the-as uint #x8080))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 4) (the-as uint 0))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-2) 5) (new 'static 'vif-tag :cmd (vif-cmd stcol) :msk #x1))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 6) (the-as uint 4096))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 7) (the-as uint 4096))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 8) (the-as uint 4096))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 9) (the-as uint 4096))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-2) 10) (new 'static 'vif-tag :cmd (vif-cmd stmask)))
|
||||
(set! (-> (the-as (pointer uint32) v1-2) 11) (the-as uint #xa0a0a0a0))
|
||||
(set! (-> arg0 base) (&+ v1-2 48))
|
||||
)
|
||||
(set! *shrub-state* 2)
|
||||
#f
|
||||
)
|
||||
|
||||
(defun shrub-init-frame ((arg0 dma-buffer) (arg1 gs-test))
|
||||
"Generate DMA to initialize to shrubbery renderer VU1 and GS."
|
||||
|
||||
;; init VU1
|
||||
(shrub-do-init-frame arg0)
|
||||
;; init GS.
|
||||
(let* ((v1-0 arg0)
|
||||
(a0-2 (the-as object (-> v1-0 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-2) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-2) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-2) vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> v1-0 base) (the-as pointer (the-as gs-gif-tag (&+ (the-as pointer a0-2) 16))))
|
||||
)
|
||||
(let* ((v1-1 arg0)
|
||||
(a0-4 (the-as object (-> v1-1 base)))
|
||||
)
|
||||
(set! (-> (the-as gs-gif-tag a0-4) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> (the-as gs-gif-tag a0-4) regs) (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id a+d)
|
||||
:regs1 (gif-reg-id a+d)
|
||||
:regs2 (gif-reg-id a+d)
|
||||
:regs3 (gif-reg-id a+d)
|
||||
:regs4 (gif-reg-id a+d)
|
||||
:regs5 (gif-reg-id a+d)
|
||||
:regs6 (gif-reg-id a+d)
|
||||
:regs7 (gif-reg-id a+d)
|
||||
:regs8 (gif-reg-id a+d)
|
||||
:regs9 (gif-reg-id a+d)
|
||||
:regs10 (gif-reg-id a+d)
|
||||
:regs11 (gif-reg-id a+d)
|
||||
:regs12 (gif-reg-id a+d)
|
||||
:regs13 (gif-reg-id a+d)
|
||||
:regs14 (gif-reg-id a+d)
|
||||
:regs15 (gif-reg-id a+d)
|
||||
)
|
||||
)
|
||||
(set! (-> v1-1 base) (&+ (the-as pointer a0-4) 16))
|
||||
)
|
||||
(let ((v1-2 (-> arg0 base)))
|
||||
(set! (-> (the-as (pointer gs-test) v1-2) 0) arg1)
|
||||
(set! (-> (the-as (pointer gs-reg64) v1-2) 1) (gs-reg64 test-1))
|
||||
(set! (-> arg0 base) (&+ v1-2 16))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun shrub-upload-model ((arg0 shrubbery) (arg1 dma-buffer) (arg2 int))
|
||||
"Generate DMA to upload a shrub model"
|
||||
(let* ((v1-0 arg1)
|
||||
(a3-0 (the-as object (-> v1-0 base)))
|
||||
)
|
||||
;; upload the data
|
||||
(set! (-> (the-as dma-packet a3-0) dma)
|
||||
(new 'static 'dma-tag
|
||||
:id (dma-tag-id ref)
|
||||
:addr (-> arg0 obj)
|
||||
:qwc (+ (-> arg0 obj-qwc) (-> arg0 vtx-qwc) (-> arg0 col-qwc) (-> arg0 stq-qwc))
|
||||
)
|
||||
)
|
||||
(set! (-> (the-as dma-packet a3-0) vif0) (new 'static 'vif-tag :cmd (vif-cmd base) :imm *shrub-state*))
|
||||
(set! (-> (the-as dma-packet a3-0) vif1) (new 'static 'vif-tag :cmd (vif-cmd offset)))
|
||||
(set! (-> v1-0 base) (&+ (the-as pointer a3-0) 16))
|
||||
)
|
||||
;; run the program to init a model
|
||||
(cond
|
||||
((= arg2 1)
|
||||
(let* ((v1-2 arg1)
|
||||
(a0-9 (the-as object (-> v1-2 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-9) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-9) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-9) vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x11))
|
||||
(set! (-> v1-2 base) (&+ (the-as pointer a0-9) 16))
|
||||
)
|
||||
)
|
||||
(else
|
||||
(let* ((v1-3 arg1)
|
||||
(a0-11 (the-as object (-> v1-3 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-11) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-11) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-11) vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x15))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer a0-11) 16))
|
||||
)
|
||||
)
|
||||
)
|
||||
;; some data buffer thing.
|
||||
(set! *shrub-state* (- 164 *shrub-state*))
|
||||
#f
|
||||
)
|
||||
|
||||
;; TODO drawing...
|
||||
|
||||
(defun draw-drawable-tree-instance-shrub ((arg0 drawable-tree-instance-shrub) (arg1 level))
|
||||
;; (local-vars (a0-4 int) (a0-6 int) (a0-11 int) (a0-13 int))
|
||||
(set-vector! (-> *instance-shrub-work* min-dist) 4095996000.0 4095996000.0 4095996000.0 4095996000.0)
|
||||
(set! (-> *instance-shrub-work* near-last) (the-as uint 0))
|
||||
(set! (-> *instance-shrub-work* near-next) (the-as uint 0))
|
||||
(set! (-> *instance-shrub-work* near-count) (the-as uint 0))
|
||||
(set! (-> *instance-shrub-work* wind-vectors) (-> arg0 info wind-vectors))
|
||||
(set! (-> *instance-shrub-work* wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *instance-shrub-work* wait-from-spr) (the-as uint 0))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery shrub-near billboard trans-shrubbery))
|
||||
(let* ((v1-13 (-> arg0 info prototype-inline-array-shrub))
|
||||
(s4-0 (-> v1-13 length))
|
||||
(s3-0 (-> v1-13 data))
|
||||
)
|
||||
(countdown (a1-2 s4-0)
|
||||
(let ((a2-3 (-> v1-13 data a1-2)))
|
||||
(set! (-> a2-3 next-clear) (the-as uint128 0))
|
||||
(set! (-> a2-3 last-clear) (the-as uint128 0))
|
||||
(set! (-> a2-3 count-clear) (the-as uint 0))
|
||||
)
|
||||
0
|
||||
)
|
||||
(let ((v1-19 (-> *display* frames (-> *display* on-screen) frame global-buf)))
|
||||
(when (nonzero? (-> arg0 length))
|
||||
(let ((s5-0 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(reset! (-> *perf-stats* data (perf-stat-bucket inst-shrub)))
|
||||
; (draw-inline-array-instance-shrub
|
||||
; v1-19
|
||||
; (&+ (-> arg0 data 0) 32)
|
||||
; (-> (the-as drawable-group (-> arg0 data 0)) length)
|
||||
; s3-0
|
||||
; )
|
||||
(read! (-> *perf-stats* data (perf-stat-bucket inst-shrub)))
|
||||
(reset! (-> *perf-stats* data (perf-stat-bucket proto-shrub)))
|
||||
; (draw-prototype-inline-array-shrub s4-0 s3-0)
|
||||
(read! (-> *perf-stats* data (perf-stat-bucket proto-shrub)))
|
||||
(let ((v1-28 *dma-mem-usage*))
|
||||
(when (nonzero? v1-28)
|
||||
(set! (-> v1-28 length) (max 28 (-> v1-28 length)))
|
||||
(set! (-> v1-28 data 27 name) "shrubbery")
|
||||
(+! (-> v1-28 data 27 count) 1)
|
||||
(+! (-> v1-28 data 27 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s5-0))
|
||||
)
|
||||
(set! (-> v1-28 data 27 total) (-> v1-28 data 27 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(update-wait-stats
|
||||
(-> *perf-stats* data (perf-stat-bucket inst-shrub))
|
||||
(the-as uint 0)
|
||||
(-> *instance-shrub-work* wait-to-spr)
|
||||
(-> *instance-shrub-work* wait-from-spr)
|
||||
)
|
||||
(set! (-> arg1 closest-object 2) (-> *instance-shrub-work* min-dist x))
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod draw drawable-tree-instance-shrub ((obj drawable-tree-instance-shrub) (arg0 drawable-tree-instance-shrub) (arg1 display-frame))
|
||||
(let* ((v1-1 (-> *background-work* shrub-tree-count))
|
||||
(a1-2 (-> (scratchpad-object terrain-context) bsp lev-index))
|
||||
(a1-5 (-> *level* level a1-2))
|
||||
)
|
||||
(set! (-> *background-work* shrub-trees v1-1) obj)
|
||||
(set! (-> *background-work* shrub-levels v1-1) a1-5)
|
||||
)
|
||||
(+! (-> *background-work* shrub-tree-count) 1)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod unpack-vis drawable-tree-instance-shrub ((obj drawable-tree-instance-shrub) (arg0 (pointer int8)) (arg1 (pointer int8)))
|
||||
arg1
|
||||
)
|
||||
)
|
||||
|
||||
(defmethod collect-stats drawable-tree-instance-shrub ((obj drawable-tree-instance-shrub))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery shrub-near billboard trans-shrubbery))
|
||||
(let* ((v1-3 (-> obj info prototype-inline-array-shrub))
|
||||
(gp-0 (the-as object (-> v1-3 data)))
|
||||
)
|
||||
(countdown (s5-0 (-> v1-3 length))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask shrub-near))
|
||||
(let ((v1-7 (-> (the-as prototype-bucket-shrub gp-0) count 0))
|
||||
(a1-0 (-> (the-as prototype-bucket-shrub gp-0) geometry 0))
|
||||
)
|
||||
(when (nonzero? v1-7)
|
||||
(let ((a0-2 (-> (the-as drawable-group a1-0) length)))
|
||||
(+! (-> *terrain-stats* shrub groups) 1)
|
||||
(+! (-> *terrain-stats* shrub fragments) (* a0-2 (the-as int v1-7)))
|
||||
)
|
||||
(+! (-> *terrain-stats* shrub instances) v1-7)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery))
|
||||
(let ((s4-0 (-> (the-as prototype-bucket-shrub gp-0) count 1))
|
||||
(v1-12 (-> (the-as prototype-bucket-shrub gp-0) geometry 1))
|
||||
)
|
||||
(when (nonzero? s4-0)
|
||||
(let ((s3-0 (&+ v1-12 32))
|
||||
(s2-0 (-> (the-as drawable-group v1-12) length))
|
||||
)
|
||||
(+! (-> *terrain-stats* shrub groups) 1)
|
||||
(+! (-> *terrain-stats* shrub fragments) s2-0)
|
||||
(+! (-> *terrain-stats* shrub instances) s4-0)
|
||||
(while (nonzero? s2-0)
|
||||
(+! s2-0 -1)
|
||||
(let ((a0-13 (* (shrub-num-tris (the-as shrubbery s3-0)) s4-0))
|
||||
(v1-24 (* (-> (the-as shrubbery s3-0) header data 2) s4-0))
|
||||
)
|
||||
(+! (-> *terrain-stats* shrub tris) a0-13)
|
||||
(+! (-> *terrain-stats* shrub dverts) v1-24)
|
||||
)
|
||||
(&+! s3-0 32)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask trans-shrubbery))
|
||||
(let ((s4-1 (-> (the-as prototype-bucket-shrub gp-0) count 2))
|
||||
(v1-30 (-> (the-as prototype-bucket-shrub gp-0) geometry 2))
|
||||
)
|
||||
(when (nonzero? s4-1)
|
||||
(let ((s3-1 (&+ v1-30 32))
|
||||
(s2-1 (-> (the-as drawable-group v1-30) length))
|
||||
)
|
||||
(+! (-> *terrain-stats* trans-shrub groups) 1)
|
||||
(+! (-> *terrain-stats* trans-shrub fragments) s2-1)
|
||||
(+! (-> *terrain-stats* trans-shrub instances) s4-1)
|
||||
(while (nonzero? s2-1)
|
||||
(+! s2-1 -1)
|
||||
(let ((a0-24 (* (shrub-num-tris (the-as shrubbery s3-1)) s4-1))
|
||||
(v1-42 (* (-> (the-as shrubbery s3-1) header data 2) s4-1))
|
||||
)
|
||||
(+! (-> *terrain-stats* trans-shrub tris) a0-24)
|
||||
(+! (-> *terrain-stats* trans-shrub dverts) v1-42)
|
||||
)
|
||||
(&+! s3-1 32)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask billboard))
|
||||
(let ((v1-48 (-> (the-as prototype-bucket-shrub gp-0) count 3)))
|
||||
(when (nonzero? v1-48)
|
||||
(+! (-> *terrain-stats* billboard groups) 1)
|
||||
(+! (-> *terrain-stats* billboard instances) v1-48)
|
||||
(+! (-> *terrain-stats* billboard tris) (* v1-48 2))
|
||||
(+! (-> *terrain-stats* billboard dverts) (* v1-48 4))
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! gp-0 (-> (the-as (inline-array prototype-bucket-shrub) gp-0) 1))
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
;; a geom, based on distance from the camera (or other settings) and will add itself to the list
|
||||
;; for that geom.
|
||||
(deftype prototype-bucket (basic)
|
||||
((name basic :offset-assert 4)
|
||||
((name string :offset-assert 4)
|
||||
(flags uint32 :offset-assert 8)
|
||||
(in-level uint16 :offset-assert 12)
|
||||
(utextures uint16 :offset-assert 14)
|
||||
@@ -33,6 +33,10 @@
|
||||
(rlength-mid float :offset 56)
|
||||
(stiffness float :offset 60)
|
||||
(next-clear uint128 :offset 64)
|
||||
(next-clear-1 int32 :offset 64)
|
||||
(next-clear-2 int32 :offset 68)
|
||||
(next-clear-3 int32 :offset 72)
|
||||
(next-clear-4 int32 :offset 76)
|
||||
(count-clear uint64 :offset 80)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@@ -47,7 +51,8 @@
|
||||
;; specialization for shrub. We keep the end of the linked list too.
|
||||
(deftype prototype-bucket-shrub (prototype-bucket)
|
||||
((mod-count uint16 4 :offset-assert 88)
|
||||
(last uint32 4 :offset-assert 96)
|
||||
(last dma-packet 4 :offset-assert 96)
|
||||
(count-clear-qword uint128 :offset 80)
|
||||
(last-clear uint128 :offset 96)
|
||||
)
|
||||
:method-count-assert 9
|
||||
|
||||
+3
-9
@@ -635,13 +635,7 @@
|
||||
(let ((s3-0 (-> (the-as drawable-tree-instance-shrub v1-7) info prototype-inline-array-shrub)))
|
||||
(dotimes (s2-0 (-> s3-0 length))
|
||||
(let ((a1-4
|
||||
(new
|
||||
'global
|
||||
'debug-menu-item-flag
|
||||
(the-as string (-> s3-0 data s2-0 name))
|
||||
(-> s3-0 data s2-0 name)
|
||||
dm-instance-pick-func
|
||||
)
|
||||
(new 'global 'debug-menu-item-flag (-> s3-0 data s2-0 name) (-> s3-0 data s2-0 name) dm-instance-pick-func)
|
||||
)
|
||||
)
|
||||
(debug-menu-append-item *instance-shrub-menu* a1-4)
|
||||
@@ -656,7 +650,7 @@
|
||||
(new
|
||||
'debug
|
||||
'debug-menu-item-flag
|
||||
(the-as string (-> s3-1 array-data s2-1 name))
|
||||
(-> s3-1 array-data s2-1 name)
|
||||
(-> s3-1 array-data s2-1 name)
|
||||
dm-instance-pick-func
|
||||
)
|
||||
@@ -668,7 +662,7 @@
|
||||
(new
|
||||
'debug
|
||||
'debug-menu-item-flag
|
||||
(the-as string (-> s3-1 array-data s2-1 name))
|
||||
(-> s3-1 array-data s2-1 name)
|
||||
(-> s3-1 array-data s2-1 name)
|
||||
dm-enable-instance-func
|
||||
)
|
||||
|
||||
+5
-5
@@ -257,7 +257,7 @@
|
||||
((drawable-tree-instance-shrub)
|
||||
(let ((s2-0 (-> (the-as drawable-tree-instance-shrub v1-7) info prototype-inline-array-shrub)))
|
||||
(dotimes (s1-0 (-> s2-0 length))
|
||||
(if (string= arg0 (the-as string (-> s2-0 data s1-0 name)))
|
||||
(if (string= arg0 (-> s2-0 data s1-0 name))
|
||||
(return (-> s2-0 data s1-0))
|
||||
)
|
||||
)
|
||||
@@ -266,7 +266,7 @@
|
||||
((drawable-tree-instance-tie)
|
||||
(let ((s2-1 (-> (the-as drawable-tree-instance-tie v1-7) prototypes prototype-array-tie)))
|
||||
(dotimes (s1-1 (-> s2-1 length))
|
||||
(if (string= arg0 (the-as string (-> s2-1 array-data s1-1 name)))
|
||||
(if (string= arg0 (-> s2-1 array-data s1-1 name))
|
||||
(return (-> s2-1 array-data s1-1))
|
||||
)
|
||||
)
|
||||
@@ -353,7 +353,7 @@
|
||||
;; Used lq/sq
|
||||
(defun-debug draw-instance-info ((arg0 string))
|
||||
(local-vars
|
||||
(sv-16 int)
|
||||
(sv-16 uint)
|
||||
(sv-32 uint)
|
||||
(sv-48 uint)
|
||||
(sv-64 int)
|
||||
@@ -448,14 +448,14 @@
|
||||
s0-0
|
||||
sv-16
|
||||
sv-32
|
||||
(/ (* 2.0 (the float sv-16)) (the float (- sv-32 (the-as uint sv-16))))
|
||||
(/ (* 2.0 (the float sv-16)) (the float (- sv-32 sv-16)))
|
||||
sv-48
|
||||
)
|
||||
(+! s3-1 sv-16)
|
||||
(+! s4-2 sv-32)
|
||||
(set! f30-0
|
||||
(+ 29.0
|
||||
(* 5.5 (the float (- sv-32 (the-as uint sv-16))))
|
||||
(* 5.5 (the float (- sv-32 sv-16)))
|
||||
(* 22.0 (the float sv-48))
|
||||
(* 8.0 (the float sv-32))
|
||||
(* 53.0 (the float (/ (+ s2-1 9) (the-as uint 10))))
|
||||
|
||||
+5
-1
@@ -120,7 +120,11 @@
|
||||
(s4-0 (-> *background-work* shrub-levels gp-0))
|
||||
)
|
||||
(if (nonzero? (-> s5-0 colors-added))
|
||||
(time-of-day-interp-colors (-> *instance-shrub-work* colors) (-> s5-0 colors-added) (-> s4-0 mood))
|
||||
(time-of-day-interp-colors
|
||||
(-> *instance-shrub-work* colors)
|
||||
(the-as uint (-> s5-0 colors-added))
|
||||
(-> s4-0 mood)
|
||||
)
|
||||
)
|
||||
(draw-drawable-tree-instance-shrub s5-0 s4-0)
|
||||
)
|
||||
|
||||
+21
-21
@@ -29,27 +29,27 @@
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x10000005 #x0 #x0 #x6c0501a3))
|
||||
)
|
||||
:count-tmpl
|
||||
(new 'static 'inline-array qword 20
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #xa))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x1))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x2))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x3))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x4))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x5))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x6))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x7))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x8))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #x9))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010142 #xa))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x1))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x2))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x3))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x4))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x5))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x6))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x7))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x8))
|
||||
(new 'static 'qword :data (new 'static 'array uint32 4 #x20000000 #x0 #x60010175 #x9))
|
||||
(new 'static 'inline-array vector4w 20
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 10)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 1)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 2)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 3)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 4)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 5)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 6)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 7)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 8)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 9)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010142 :w 10)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 1)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 2)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 3)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 4)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 5)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 6)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 7)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 8)
|
||||
(new 'static 'vector4w :x #x20000000 :z #x60010175 :w 9)
|
||||
)
|
||||
:mscalf-tmpl
|
||||
(new 'static 'dma-packet
|
||||
|
||||
+28
-27
@@ -21,18 +21,18 @@
|
||||
|
||||
;; definition of type shrub-view-data
|
||||
(deftype shrub-view-data (structure)
|
||||
((data uint128 3 :offset-assert 0)
|
||||
(texture-giftag qword :inline :offset 0)
|
||||
(consts vector :inline :offset 16)
|
||||
(fog-clamp vector :inline :offset 32)
|
||||
(tex-start-ptr int32 :offset 16)
|
||||
(gifbufsum float :offset 16)
|
||||
(mtx-buf-ptr int32 :offset 20)
|
||||
(exp23 float :offset 20)
|
||||
(fog-0 float :offset 24)
|
||||
(fog-1 float :offset 28)
|
||||
(fog-min float :offset 32)
|
||||
(fog-max float :offset 36)
|
||||
((data uint128 3 :offset-assert 0)
|
||||
(texture-giftag gs-gif-tag :inline :offset 0)
|
||||
(consts vector :inline :offset 16)
|
||||
(fog-clamp vector :inline :offset 32)
|
||||
(tex-start-ptr int32 :offset 16)
|
||||
(gifbufsum float :offset 16)
|
||||
(mtx-buf-ptr int32 :offset 20)
|
||||
(exp23 float :offset 20)
|
||||
(fog-0 float :offset 24)
|
||||
(fog-1 float :offset 28)
|
||||
(fog-min float :offset 32)
|
||||
(fog-max float :offset 36)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x30
|
||||
@@ -44,16 +44,16 @@
|
||||
(format #t "[~8x] ~A~%" obj 'shrub-view-data)
|
||||
(format #t "~Tdata[3] @ #x~X~%" (-> obj data))
|
||||
(format #t "~Ttexture-giftag: #<qword @ #x~X>~%" (-> obj data))
|
||||
(format #t "~Tconsts: #<vector @ #x~X>~%" (-> obj consts))
|
||||
(format #t "~Tfog-clamp: #<vector @ #x~X>~%" (-> obj fog-clamp))
|
||||
(format #t "~Ttex-start-ptr: ~D~%" (-> obj consts x))
|
||||
(format #t "~Tgifbufsum: ~f~%" (-> obj consts x))
|
||||
(format #t "~Tmtx-buf-ptr: ~D~%" (-> obj consts y))
|
||||
(format #t "~Texp23: ~f~%" (-> obj consts y))
|
||||
(format #t "~Tfog-0: ~f~%" (-> obj consts z))
|
||||
(format #t "~Tfog-1: ~f~%" (-> obj consts w))
|
||||
(format #t "~Tfog-min: ~f~%" (-> obj fog-clamp x))
|
||||
(format #t "~Tfog-max: ~f~%" (-> obj fog-clamp y))
|
||||
(format #t "~Tconsts: #<vector @ #x~X>~%" (&-> obj tex-start-ptr))
|
||||
(format #t "~Tfog-clamp: #<vector @ #x~X>~%" (&-> obj fog-min))
|
||||
(format #t "~Ttex-start-ptr: ~D~%" (-> obj tex-start-ptr))
|
||||
(format #t "~Tgifbufsum: ~f~%" (-> obj gifbufsum))
|
||||
(format #t "~Tmtx-buf-ptr: ~D~%" (-> obj mtx-buf-ptr))
|
||||
(format #t "~Texp23: ~f~%" (-> obj exp23))
|
||||
(format #t "~Tfog-0: ~f~%" (-> obj fog-0))
|
||||
(format #t "~Tfog-1: ~f~%" (-> obj fog-1))
|
||||
(format #t "~Tfog-min: ~f~%" (-> obj fog-min))
|
||||
(format #t "~Tfog-max: ~f~%" (-> obj fog-max))
|
||||
obj
|
||||
)
|
||||
|
||||
@@ -95,9 +95,10 @@
|
||||
|
||||
;; definition of type instance-shrubbery
|
||||
(deftype instance-shrubbery (instance)
|
||||
((flat-normal vector :inline :offset-assert 64)
|
||||
(flat-hwidth float :offset 76)
|
||||
(color uint32 :offset 8)
|
||||
((color-indices uint32 :offset 8)
|
||||
(flat-normal vector :inline :offset-assert 64)
|
||||
(flat-hwidth float :offset 76)
|
||||
(color uint32 :offset 8)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x50
|
||||
@@ -131,7 +132,7 @@
|
||||
;; definition of type drawable-tree-instance-shrub
|
||||
(deftype drawable-tree-instance-shrub (drawable-tree)
|
||||
((info prototype-array-shrub-info :offset 8)
|
||||
(colors-added uint32 :offset 12)
|
||||
(colors-added time-of-day-palette :offset 12)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x24
|
||||
@@ -292,7 +293,7 @@
|
||||
(chainb qword 8 :inline :offset-assert 176)
|
||||
(colors rgba 1024 :offset-assert 304)
|
||||
(matrix-tmpl qword 20 :inline :offset-assert 4400)
|
||||
(count-tmpl qword 20 :inline :offset-assert 4720)
|
||||
(count-tmpl vector4w 20 :inline :offset-assert 4720)
|
||||
(mscalf-tmpl dma-packet :inline :offset-assert 5040)
|
||||
(mscalf-ret-tmpl dma-packet :inline :offset-assert 5056)
|
||||
(adgif-tmpl dma-gif-packet :inline :offset-assert 5072)
|
||||
|
||||
+9
-4
@@ -3,7 +3,7 @@
|
||||
|
||||
;; definition of type prototype-bucket
|
||||
(deftype prototype-bucket (basic)
|
||||
((name basic :offset-assert 4)
|
||||
((name string :offset-assert 4)
|
||||
(flags uint32 :offset-assert 8)
|
||||
(in-level uint16 :offset-assert 12)
|
||||
(utextures uint16 :offset-assert 14)
|
||||
@@ -21,6 +21,10 @@
|
||||
(rlength-mid float :offset 56)
|
||||
(stiffness float :offset 60)
|
||||
(next-clear uint128 :offset 64)
|
||||
(next-clear-1 int32 :offset 64)
|
||||
(next-clear-2 int32 :offset 68)
|
||||
(next-clear-3 int32 :offset 72)
|
||||
(next-clear-4 int32 :offset 76)
|
||||
(count-clear uint64 :offset 80)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@@ -56,9 +60,10 @@
|
||||
|
||||
;; definition of type prototype-bucket-shrub
|
||||
(deftype prototype-bucket-shrub (prototype-bucket)
|
||||
((mod-count uint16 4 :offset-assert 88)
|
||||
(last uint32 4 :offset-assert 96)
|
||||
(last-clear uint128 :offset 96)
|
||||
((mod-count uint16 4 :offset-assert 88)
|
||||
(last dma-packet 4 :offset-assert 96)
|
||||
(count-clear-qword uint128 :offset 80)
|
||||
(last-clear uint128 :offset 96)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x70
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@
|
||||
(set! (-> arg0 length) (max 81 (-> arg0 length)))
|
||||
(set! (-> arg0 data 80 name) "string")
|
||||
(+! (-> arg0 data 80 count) 1)
|
||||
(let ((v1-13 ((method-of-type string asize-of) (the-as string (-> obj name)))))
|
||||
(let ((v1-13 (asize-of (-> obj name))))
|
||||
(+! (-> arg0 data 80 used) v1-13)
|
||||
(+! (-> arg0 data 80 total) (logand -16 (+ v1-13 15)))
|
||||
)
|
||||
@@ -127,7 +127,7 @@
|
||||
(set! (-> arg0 length) (max 81 (-> arg0 length)))
|
||||
(set! (-> arg0 data 80 name) "string")
|
||||
(+! (-> arg0 data 80 count) 1)
|
||||
(let ((v1-22 ((method-of-type string asize-of) (the-as string (-> obj name)))))
|
||||
(let ((v1-22 (asize-of (-> obj name))))
|
||||
(+! (-> arg0 data 80 used) v1-22)
|
||||
(+! (-> arg0 data 80 total) (logand -16 (+ v1-22 15)))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user