[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:
water111
2022-03-28 18:14:25 -04:00
committed by GitHub
parent 4ea8c01e02
commit b2ed9313bd
30 changed files with 2179 additions and 384 deletions
+1
View File
@@ -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
+18
View File
@@ -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;
}
}
}
+3 -1
View File
@@ -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 - [{}]",
+52 -29
View File
@@ -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": []
}
+437 -1
View File
@@ -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;
+422 -153
View File
@@ -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
+13 -7
View File
@@ -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
View File
@@ -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
```
```
+3 -3
View File
@@ -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.
+2 -2
View File
@@ -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);
}
}
+10 -10
View File
@@ -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)))
+26 -21
View File
@@ -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)))
+68 -63
View File
@@ -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
+601 -1
View File
@@ -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)
)
+7 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)))
)