mirror of
https://github.com/open-goal/jak-project
synced 2026-07-08 14:36:52 -04:00
[graphics] TIE extractor (#1026)
* temp * temp * wip * more progress on the instance asm * first half of tie extraction, up to dma lists * more tie extraction * first part figured out maybe * bp1 loop seems to work, bp2 loop does not * bp1 and bp2 appear working. sadly ip is needed * ip1 outline, not working ip2 * just kidding, ip2 seems to work * extraction seems to work * basic rendering working * tie fixes * performance optimization of tie renderer * hook up tie to engine * fix more bugs * cleanup and perf improvements * fix tests * ref tests * mm256i for gcc * CLANG * windows * more compile fixes * fix fast time of day * small fixes * fix after merge * clang
This commit is contained in:
@@ -53,5 +53,3 @@ if(UNIX)
|
||||
elseif(WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2")
|
||||
endif()
|
||||
|
||||
install(TARGETS common)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace tfrag3 {
|
||||
|
||||
void Draw::serialize(Serializer& ser) {
|
||||
void StripDraw::serialize(Serializer& ser) {
|
||||
ser.from_ptr(&mode);
|
||||
ser.from_ptr(&tree_tex_id);
|
||||
ser.from_pod_vector(&vertex_index_stream);
|
||||
@@ -11,7 +11,7 @@ void Draw::serialize(Serializer& ser) {
|
||||
ser.from_ptr(&num_triangles);
|
||||
}
|
||||
|
||||
void Tree::serialize(Serializer& ser) {
|
||||
void TfragTree::serialize(Serializer& ser) {
|
||||
ser.from_ptr(&kind);
|
||||
|
||||
if (ser.is_saving()) {
|
||||
@@ -24,14 +24,32 @@ void Tree::serialize(Serializer& ser) {
|
||||
}
|
||||
|
||||
ser.from_pod_vector(&vertices);
|
||||
ser.from_pod_vector(&color_indices_per_vertex);
|
||||
ser.from_pod_vector(&vis_nodes);
|
||||
ser.from_pod_vector(&colors);
|
||||
bvh.serialize(ser);
|
||||
}
|
||||
|
||||
void TieTree::serialize(Serializer& ser) {
|
||||
if (ser.is_saving()) {
|
||||
ser.save<size_t>(static_draws.size());
|
||||
} else {
|
||||
static_draws.resize(ser.load<size_t>());
|
||||
}
|
||||
for (auto& draw : static_draws) {
|
||||
draw.serialize(ser);
|
||||
}
|
||||
|
||||
ser.from_pod_vector(&vertices);
|
||||
ser.from_pod_vector(&colors);
|
||||
bvh.serialize(ser);
|
||||
}
|
||||
|
||||
void BVH::serialize(Serializer& ser) {
|
||||
ser.from_ptr(&first_leaf_node);
|
||||
ser.from_ptr(&last_leaf_node);
|
||||
ser.from_ptr(&first_root);
|
||||
ser.from_ptr(&num_roots);
|
||||
ser.from_ptr(&only_children);
|
||||
ser.from_pod_vector(&vis_nodes);
|
||||
}
|
||||
|
||||
void Texture::serialize(Serializer& ser) {
|
||||
@@ -62,11 +80,20 @@ void Level::serialize(Serializer& ser) {
|
||||
}
|
||||
|
||||
if (ser.is_saving()) {
|
||||
ser.save<size_t>(trees.size());
|
||||
ser.save<size_t>(tfrag_trees.size());
|
||||
} else {
|
||||
trees.resize(ser.load<size_t>());
|
||||
tfrag_trees.resize(ser.load<size_t>());
|
||||
}
|
||||
for (auto& tree : trees) {
|
||||
for (auto& tree : tfrag_trees) {
|
||||
tree.serialize(ser);
|
||||
}
|
||||
|
||||
if (ser.is_saving()) {
|
||||
ser.save<size_t>(tie_trees.size());
|
||||
} else {
|
||||
tie_trees.resize(ser.load<size_t>());
|
||||
}
|
||||
for (auto& tree : tie_trees) {
|
||||
tree.serialize(ser);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace tfrag3 {
|
||||
|
||||
constexpr int TFRAG3_VERSION = 6;
|
||||
constexpr int TFRAG3_VERSION = 7;
|
||||
|
||||
// These vertices should be uploaded to the GPU at load time and don't change
|
||||
struct PreloadedVertex {
|
||||
@@ -18,71 +18,110 @@ struct PreloadedVertex {
|
||||
float x, y, z;
|
||||
// texture coordinates
|
||||
float s, t, q;
|
||||
// currently unused, color table indices.
|
||||
// color table index
|
||||
u16 color_index;
|
||||
u16 pad[3];
|
||||
};
|
||||
static_assert(sizeof(PreloadedVertex) == 32, "PreloadedVertex size");
|
||||
|
||||
// Settings for an OpenGL draw
|
||||
struct Draw {
|
||||
// Settings for drawing a group of triangle strips.
|
||||
// This refers to a group of PreloadedVertices that are already uploaded.
|
||||
// All triangles here are drawn in the same "mode" (blending, texture, etc)
|
||||
// The vertex index list is chunked by visibility group.
|
||||
// You can just memcpy the entire list to draw everything, or iterate through visgroups and
|
||||
// check visibility.
|
||||
struct StripDraw {
|
||||
DrawMode mode; // the OpenGL draw settings.
|
||||
u32 tree_tex_id = 0; // the texture that should be bound for the draw
|
||||
|
||||
// the list of vertices in the draw.
|
||||
// the list of vertices in the draw. This includes the restart code of UINT32_MAX that OpenGL
|
||||
// will use to start a new strip.
|
||||
std::vector<u32> vertex_index_stream;
|
||||
|
||||
// to do culling, the above vertex stream is grouped.
|
||||
// by following the visgroups and checking the visibility of the tfrag_idx, you can leave out
|
||||
// invisible vertices.
|
||||
// by following the visgroups and checking the visibility, you can leave out invisible vertices.
|
||||
struct VisGroup {
|
||||
u32 num = 0;
|
||||
u32 tfrag_idx = 0;
|
||||
u32 num = 0; // number of vertex indices in this group
|
||||
u32 vis_idx = 0; // the visibility group they belong to
|
||||
};
|
||||
std::vector<VisGroup> vis_groups;
|
||||
u32 num_triangles = 0;
|
||||
|
||||
// for debug counting.
|
||||
u32 num_triangles = 0;
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
// node in the BVH.
|
||||
struct VisNode {
|
||||
math::Vector<float, 4> bsphere; // the bounding sphere, in meters (4096 = 1 game meter). w = rad
|
||||
u16 child_id = 0xffff; // the ID of our first child.
|
||||
u8 num_kids = 0xff; // number of children. The children are consecutive in memory
|
||||
u8 flags = 0; // flags. If 1, we have a DrawVisNode child, otherwise a Tfrag.
|
||||
u8 flags = 0; // flags. If 1, we have a DrawVisNode child, otherwise a leaf.
|
||||
};
|
||||
|
||||
enum class TFragmentTreeKind { NORMAL, TRANS, DIRT, ICE, LOWRES, LOWRES_TRANS, INVALID };
|
||||
|
||||
constexpr const char* tfrag_tree_names[] = {"normal", "trans", "dirt", "ice",
|
||||
"lowres", "lowres-trans", "invalid"};
|
||||
|
||||
struct TimeOfDayColor {
|
||||
math::Vector<u8, 4> rgba[8];
|
||||
};
|
||||
|
||||
struct Tree {
|
||||
TFragmentTreeKind kind;
|
||||
std::vector<Draw> draws;
|
||||
std::vector<u16> color_indices_per_vertex;
|
||||
std::vector<VisNode> vis_nodes;
|
||||
std::vector<PreloadedVertex> vertices;
|
||||
std::vector<TimeOfDayColor> colors;
|
||||
// The leaf nodes don't actually exist in the vector of VisNodes, but instead they are ID's used
|
||||
// by the actual geometry. Currently we do not include the bspheres of these, but this might be
|
||||
// worth it if we have a more performant culling algorithm.
|
||||
struct BVH {
|
||||
std::vector<VisNode> vis_nodes; // bvh for frustum culling
|
||||
// additional information about the BVH
|
||||
u16 first_leaf_node = 0;
|
||||
u16 last_leaf_node = 0;
|
||||
u16 first_root = 0;
|
||||
u16 num_roots = 0;
|
||||
bool only_children = false;
|
||||
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
// A time-of-day color. Each stores 8 colors. At a given "time of day", they are interpolated
|
||||
// to find a single color which goes into a color palette.
|
||||
struct TimeOfDayColor {
|
||||
math::Vector<u8, 4> rgba[8];
|
||||
|
||||
bool operator==(const TimeOfDayColor& other) const {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
if (rgba[i] != other.rgba[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// A single texture. Stored as RGBA8888.
|
||||
struct Texture {
|
||||
u16 w, h;
|
||||
u32 combo_id = 0;
|
||||
std::vector<u32> data;
|
||||
std::string debug_name;
|
||||
std::string debug_tpage_name;
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
// Tfrag trees have several kinds:
|
||||
enum class TFragmentTreeKind { NORMAL, TRANS, DIRT, ICE, LOWRES, LOWRES_TRANS, INVALID };
|
||||
|
||||
constexpr const char* tfrag_tree_names[] = {"normal", "trans", "dirt", "ice",
|
||||
"lowres", "lowres-trans", "invalid"};
|
||||
|
||||
// A tfrag model
|
||||
struct TfragTree {
|
||||
TFragmentTreeKind kind; // our tfrag kind
|
||||
std::vector<StripDraw> draws; // the actual topology and settings
|
||||
std::vector<PreloadedVertex> vertices; // mesh vertices
|
||||
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
|
||||
BVH bvh; // the bvh for frustum culling
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
// A tie model
|
||||
struct TieTree {
|
||||
BVH bvh;
|
||||
std::vector<StripDraw> static_draws; // the actual topology and settings
|
||||
std::vector<PreloadedVertex> vertices; // mesh vertices
|
||||
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
|
||||
|
||||
// TODO wind stuff
|
||||
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
@@ -91,7 +130,8 @@ struct Level {
|
||||
u16 version = TFRAG3_VERSION;
|
||||
std::string level_name;
|
||||
std::vector<Texture> textures;
|
||||
std::vector<Tree> trees;
|
||||
std::vector<TfragTree> tfrag_trees;
|
||||
std::vector<TieTree> tie_trees;
|
||||
u16 version2 = TFRAG3_VERSION;
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
+17
-4
@@ -349,7 +349,13 @@ struct AdGifData {
|
||||
// it can also represent "invalid".
|
||||
class DrawMode {
|
||||
public:
|
||||
enum class AlphaBlend { DISABLED = 0, SRC_DST_SRC_DST = 1, SRC_0_SRC_DST = 2, SRC_0_FIX_DST = 3 };
|
||||
enum class AlphaBlend {
|
||||
DISABLED = 0,
|
||||
SRC_DST_SRC_DST = 1,
|
||||
SRC_0_SRC_DST = 2,
|
||||
SRC_0_FIX_DST = 3, // fix = 128
|
||||
SRC_DST_FIX_DST = 4 // fix = 64
|
||||
};
|
||||
|
||||
enum class AlphaTest {
|
||||
NEVER = 0,
|
||||
@@ -364,8 +370,8 @@ class DrawMode {
|
||||
GsTest::ZTest get_depth_test() const { return (GsTest::ZTest)((m_val >> 1) & 0b11); }
|
||||
void set_depth_test(GsTest::ZTest dt) { m_val = (m_val & ~(0b110)) | ((u32)(dt) << 1); }
|
||||
|
||||
AlphaBlend get_alpha_blend() const { return (AlphaBlend)((m_val >> 3) & 0b11); }
|
||||
void set_alpha_blend(AlphaBlend ab) { m_val = (m_val & ~(0b11000)) | ((u32)(ab) << 3); }
|
||||
AlphaBlend get_alpha_blend() const { return (AlphaBlend)((m_val >> 24) & 0b111); }
|
||||
void set_alpha_blend(AlphaBlend ab) { m_val = (m_val & ~(0b111 << 24)) | ((u32)(ab) << 24); }
|
||||
|
||||
u8 get_aref() const { return m_val >> 8; }
|
||||
void set_aref(u8 val) { m_val = (m_val & ~(0xff00)) | (val << 8); }
|
||||
@@ -457,6 +463,10 @@ class DrawMode {
|
||||
void enable_t_clamp() { m_val = m_val | (1 << 23); }
|
||||
void disable_t_clamp() { m_val = m_val & (~(1 << 23)); }
|
||||
|
||||
bool get_decal() const { return !(m_val & (1 << 28)); }
|
||||
void enable_decal() { m_val = m_val & (~(1 << 28)); }
|
||||
void disable_decal() { m_val = m_val | (1 << 28); }
|
||||
|
||||
u32& as_int() { return m_val; }
|
||||
|
||||
bool operator==(const DrawMode& other) const { return m_val == other.m_val; }
|
||||
@@ -467,7 +477,8 @@ class DrawMode {
|
||||
private:
|
||||
// 0 - depth write enable
|
||||
// 1, 2 - test: never, always, gequal, greater
|
||||
// 3, 4 - alpha: disable, [src,dst,src,dst], [src,0,src,dst], XX
|
||||
// 3, 4 - free
|
||||
|
||||
// 5 - clamp enable
|
||||
// 6 - filt enable
|
||||
// 7 - tcc enable
|
||||
@@ -478,5 +489,7 @@ class DrawMode {
|
||||
// 20 - abe
|
||||
// 21, 22 - afail
|
||||
// 23 t clamp
|
||||
// 24 - 27 alpha blend
|
||||
// 28 !decal
|
||||
u32 m_val = UINT32_MAX;
|
||||
};
|
||||
|
||||
+13
-2
@@ -68,6 +68,17 @@ class Vector {
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool operator==(const Vector<T, Size>& other) const {
|
||||
for (int i = 0; i < Size; i++) {
|
||||
if (m_data[i] != other.m_data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Vector<T, Size>& other) const { return !((*this) == other); }
|
||||
|
||||
const T length() const { return std::sqrt(squared_length()); }
|
||||
|
||||
Vector<T, Size> operator+(const Vector<T, Size>& other) const {
|
||||
@@ -213,8 +224,8 @@ struct Matrix {
|
||||
return result;
|
||||
}
|
||||
|
||||
const T& operator()(int r, int c) const { return m_data[c + r * Cols]; }
|
||||
T& operator()(int r, int c) { return m_data[r + c * Rows]; }
|
||||
// const T& operator()(int r, int c) const { return m_data[c + r * Cols]; }
|
||||
// T& operator()(int r, int c) { return m_data[r + c * Rows]; }
|
||||
|
||||
Vector<T, Rows> col(int c) const {
|
||||
Vector<T, Rows> result;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
template <typename T>
|
||||
class Filtered {
|
||||
public:
|
||||
Filtered(const T& alpha = 0.9) : m_val(T(0)), m_alpha(alpha) {}
|
||||
Filtered(const T& v, const T& alpha) : m_val(v), m_alpha(alpha) {}
|
||||
const T& add(const T& v) {
|
||||
m_val = (m_val * m_alpha) + (v * (T(1) - m_alpha));
|
||||
return m_val;
|
||||
}
|
||||
const T& get() const { return m_val; }
|
||||
|
||||
private:
|
||||
T m_val;
|
||||
T m_alpha;
|
||||
};
|
||||
@@ -44,6 +44,14 @@ constexpr const T& min(const T& a, const T& b) {
|
||||
template <typename T, std::size_t inline_elt_count = max(std::size_t(1), 128 / sizeof(T))>
|
||||
class SmallVector {
|
||||
private:
|
||||
template <typename U>
|
||||
constexpr U* launder(U* in) const {
|
||||
#if __cpp_lib_launder >= 201606
|
||||
return std::launder(in);
|
||||
#else
|
||||
return in;
|
||||
#endif
|
||||
}
|
||||
// how much to increase the storage amount when we run out.
|
||||
static constexpr double GROW_AMOUNT = 1.5;
|
||||
|
||||
@@ -53,10 +61,8 @@ class SmallVector {
|
||||
typename std::aligned_storage<sizeof(T), alignof(T)>::type m_inline[inline_elt_count];
|
||||
|
||||
// get a T* at the beginning of our inline storage.
|
||||
constexpr const T* inline_begin() const {
|
||||
return std::launder(reinterpret_cast<const T*>(m_inline));
|
||||
}
|
||||
constexpr T* inline_begin() { return std::launder(reinterpret_cast<T*>(m_inline)); }
|
||||
constexpr const T* inline_begin() const { return launder(reinterpret_cast<const T*>(m_inline)); }
|
||||
constexpr T* inline_begin() { return launder(reinterpret_cast<T*>(m_inline)); }
|
||||
|
||||
// regardless of our storage mode, these hold the beginning and end of the storage.
|
||||
// by default, they are initialized to the inline storage.
|
||||
@@ -73,14 +79,14 @@ class SmallVector {
|
||||
* The objects in storage are uninitialized.
|
||||
*/
|
||||
void allocate_and_set_heap_storage(std::size_t elt_count) {
|
||||
m_storage_begin = std::launder(reinterpret_cast<T*>(new uint8_t[elt_count * sizeof(T)]));
|
||||
m_storage_begin = launder(reinterpret_cast<T*>(new uint8_t[elt_count * sizeof(T)]));
|
||||
m_storage_end = m_storage_begin + elt_count;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free heap storage, without calling destructors of objects.
|
||||
*/
|
||||
void free_heap_storage(T* ptr) { delete[] std::launder(reinterpret_cast<uint8_t*>(ptr)); }
|
||||
void free_heap_storage(T* ptr) { delete[] launder(reinterpret_cast<uint8_t*>(ptr)); }
|
||||
|
||||
/*!
|
||||
* Set the current storage to the inline memory.
|
||||
|
||||
@@ -57,6 +57,7 @@ add_library(
|
||||
|
||||
level_extractor/extract_level.cpp
|
||||
level_extractor/extract_tfrag.cpp
|
||||
level_extractor/extract_tie.cpp
|
||||
level_extractor/BspHeader.cpp
|
||||
|
||||
ObjectFile/LinkedObjectFile.cpp
|
||||
@@ -97,5 +98,3 @@ target_link_libraries(decompiler
|
||||
common
|
||||
lzokay
|
||||
fmt)
|
||||
|
||||
install(TARGETS decompiler)
|
||||
|
||||
@@ -484,6 +484,8 @@
|
||||
(tfrag-tex0 5)
|
||||
(tfrag-0 6)
|
||||
(tfrag-near-0 7)
|
||||
(tie-near-0 8)
|
||||
(tie-0 9)
|
||||
;; merc0 10
|
||||
;; generic0 11
|
||||
(bucket-10 10)
|
||||
@@ -492,6 +494,8 @@
|
||||
(tfrag-tex1 12)
|
||||
(tfrag-1 13)
|
||||
(tfrag-near-1 14)
|
||||
(tie-near-1 15)
|
||||
(tie-1 16)
|
||||
;; merc1 17
|
||||
;; generic1 18
|
||||
(bucket-17 17)
|
||||
@@ -6763,7 +6767,7 @@
|
||||
(quad uint128 :offset 0)
|
||||
(data uint64 :offset 0)
|
||||
(cmds uint64 :offset 8)
|
||||
(cmd uint8 :offset 8)
|
||||
(cmd gs-reg :offset 8)
|
||||
(x uint32 :offset 0)
|
||||
(y uint32 :offset 4)
|
||||
(z uint32 :offset 8)
|
||||
@@ -9526,6 +9530,7 @@
|
||||
)
|
||||
|
||||
(declare-type drawable-inline-array-collide-fragment drawable-inline-array)
|
||||
(declare-type prototype-tie drawable)
|
||||
(deftype prototype-bucket-tie (prototype-bucket)
|
||||
((generic-count uint16 4 :offset-assert 88)
|
||||
(generic-next uint32 4 :offset-assert 96)
|
||||
@@ -9541,6 +9546,7 @@
|
||||
(color-index-qwc uint32 :dynamic :offset-assert 148)
|
||||
(generic-next-clear uint128 :offset 96)
|
||||
(generic-count-clear uint128 :offset 80)
|
||||
(geometry-override prototype-tie 4 :offset 16 :score 1)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x94
|
||||
@@ -9554,7 +9560,7 @@
|
||||
:size-assert #x10
|
||||
:flag-assert #xa00000010
|
||||
(:methods
|
||||
(TODO-RENAME-9 (_type_) none 9)
|
||||
(login (_type_) none 9)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -12751,7 +12757,7 @@
|
||||
;; - Types
|
||||
|
||||
(deftype tie-fragment (drawable)
|
||||
((gif-ref uint32 :offset 4)
|
||||
((gif-ref (inline-array adgif-shader) :offset 4)
|
||||
(point-ref uint32 :offset 8)
|
||||
(color-index uint16 :offset 12)
|
||||
(base-colors uint8 :offset 14)
|
||||
@@ -12763,9 +12769,9 @@
|
||||
(num-dverts uint16 :offset-assert 42)
|
||||
(dp-ref uint32 :offset-assert 44)
|
||||
(dp-qwc uint32 :offset-assert 48)
|
||||
(generic-ref uint32 :offset-assert 52)
|
||||
(generic-ref uint32 :offset-assert 52) ;; L891 ish, just a pointer to data.
|
||||
(generic-count uint32 :offset-assert 56)
|
||||
(debug-lines basic :offset-assert 60)
|
||||
(debug-lines (array vector-array) :offset-assert 60)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x40
|
||||
@@ -12905,6 +12911,7 @@
|
||||
:flag-assert #x900000134
|
||||
)
|
||||
|
||||
;; stored at spr + 16 (I think)
|
||||
(deftype prototype-tie-dma (structure)
|
||||
((colora rgba 256 :offset-assert 0)
|
||||
(colorb rgba 256 :offset-assert 1024)
|
||||
@@ -16689,7 +16696,7 @@
|
||||
(define-extern draw-drawable-tree-trans-tfrag (function drawable-tree-trans-tfrag none))
|
||||
(define-extern draw-drawable-tree-dirt-tfrag (function drawable-tree-dirt-tfrag none))
|
||||
(define-extern draw-drawable-tree-ice-tfrag (function drawable-tree-ice-tfrag none))
|
||||
(define-extern tie-near-make-perspective-matrix (function matrix none))
|
||||
(define-extern tie-near-make-perspective-matrix (function matrix matrix))
|
||||
(define-extern draw-drawable-tree-instance-tie (function drawable-tree-instance-tie level none))
|
||||
(define-extern init-background (function none))
|
||||
(define-extern finish-background (function none))
|
||||
@@ -16829,35 +16836,35 @@
|
||||
|
||||
;; - Types
|
||||
|
||||
; (deftype tie-consts (structure)
|
||||
; ((data UNKNOWN 24 :offset-assert 0)
|
||||
; (vector UNKNOWN 6 :offset-assert 0)
|
||||
; (quads UNKNOWN 6 :offset-assert 0)
|
||||
; (adgif qword :inline :offset-assert 0)
|
||||
; (strgif qword :inline :offset-assert 16)
|
||||
; (extra qword :inline :offset-assert 32)
|
||||
; (gifbufs qword :inline :offset-assert 48)
|
||||
; (clrbufs qword :inline :offset-assert 64)
|
||||
; (misc qword :inline :offset-assert 80)
|
||||
; (atestgif qword :inline :offset-assert 96)
|
||||
; (atest UNKNOWN 2 :offset-assert 112)
|
||||
; (atest-tra ad-cmd :inline :offset-assert 112)
|
||||
; (atest-def ad-cmd :inline :offset-assert 128)
|
||||
; )
|
||||
; :method-count-assert 9
|
||||
; :size-assert #x90
|
||||
; :flag-assert #x900000090
|
||||
; )
|
||||
(deftype tie-consts (structure)
|
||||
((data uint32 24 :offset-assert 0)
|
||||
(vector vector 6 :inline :offset 0)
|
||||
(quads uint128 6 :offset 0)
|
||||
(adgif gs-gif-tag :inline :offset 0) ;; was qword
|
||||
(strgif gs-gif-tag :inline :offset 16) ;; was qword
|
||||
(extra vector :inline :offset 32) ;; was qword
|
||||
(gifbufs vector :inline :offset 48) ;; was qword
|
||||
(clrbufs qword :inline :offset 64)
|
||||
(misc qword :inline :offset 80)
|
||||
(atestgif gs-gif-tag :inline :offset 96)
|
||||
(atest ad-cmd 2 :inline :offset 112)
|
||||
(atest-tra ad-cmd :inline :offset 112)
|
||||
(atest-def ad-cmd :inline :offset 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x90
|
||||
:flag-assert #x900000090
|
||||
)
|
||||
|
||||
;; - Functions
|
||||
|
||||
(define-extern tie-init-consts function)
|
||||
(define-extern tie-float-reg function)
|
||||
(define-extern tie-int-reg function)
|
||||
(define-extern tie-init-engine function)
|
||||
(define-extern tie-end-buffer function)
|
||||
(define-extern tie-ints function)
|
||||
(define-extern tie-floats function)
|
||||
(define-extern tie-init-consts (function tie-consts int none))
|
||||
(define-extern tie-float-reg (function int string))
|
||||
(define-extern tie-int-reg (function int string))
|
||||
(define-extern tie-init-engine (function dma-buffer gs-test int none)) ;; probably first int is gs-test
|
||||
(define-extern tie-end-buffer (function dma-buffer none))
|
||||
(define-extern tie-ints (function none))
|
||||
(define-extern tie-floats (function none))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
@@ -16872,32 +16879,32 @@
|
||||
|
||||
;; - Types
|
||||
|
||||
; (deftype tie-near-consts (structure)
|
||||
; ((extra qword :inline :offset-assert 0)
|
||||
; (gifbufs qword :inline :offset-assert 16)
|
||||
; (clrbufs qword :inline :offset-assert 32)
|
||||
; (adgif qword :inline :offset-assert 48)
|
||||
; (strgif qword :inline :offset-assert 64)
|
||||
; (fangif qword :inline :offset-assert 80)
|
||||
; (hvdfoffs vector :inline :offset-assert 96)
|
||||
; (invhscale vector :inline :offset-assert 112)
|
||||
; (guard vector :inline :offset-assert 128)
|
||||
; (atest UNKNOWN 2 :offset-assert 144)
|
||||
; (atest-tra ad-cmd :inline :offset-assert 144)
|
||||
; (atest-def ad-cmd :inline :offset-assert 160)
|
||||
; )
|
||||
; :method-count-assert 9
|
||||
; :size-assert #xb0
|
||||
; :flag-assert #x9000000b0
|
||||
; )
|
||||
(deftype tie-near-consts (structure)
|
||||
((extra qword :inline :offset-assert 0)
|
||||
(gifbufs qword :inline :offset-assert 16)
|
||||
(clrbufs qword :inline :offset-assert 32)
|
||||
(adgif gs-gif-tag :inline :offset-assert 48) ;; was qword
|
||||
(strgif gs-gif-tag :inline :offset-assert 64) ;; was qword
|
||||
(fangif gs-gif-tag :inline :offset-assert 80) ;; was qword
|
||||
(hvdfoffs vector :inline :offset-assert 96)
|
||||
(invhscale vector :inline :offset-assert 112)
|
||||
(guard vector :inline :offset-assert 128)
|
||||
(atest ad-cmd 2 :inline :offset-assert 144)
|
||||
(atest-tra ad-cmd :inline :offset 144)
|
||||
(atest-def ad-cmd :inline :offset 160)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xb0
|
||||
:flag-assert #x9000000b0
|
||||
)
|
||||
|
||||
;; - Functions
|
||||
|
||||
(define-extern tie-near-init-consts function)
|
||||
(define-extern tie-near-init-engine function)
|
||||
(define-extern tie-near-end-buffer function)
|
||||
(define-extern tie-near-int-reg function)
|
||||
(define-extern tie-near-float-reg function)
|
||||
(define-extern tie-near-init-consts (function tie-near-consts int none))
|
||||
(define-extern tie-near-init-engine (function dma-buffer gs-test int none))
|
||||
(define-extern tie-near-end-buffer (function dma-buffer none))
|
||||
(define-extern tie-near-int-reg (function int string))
|
||||
(define-extern tie-near-float-reg (function int string))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
@@ -16935,19 +16942,19 @@
|
||||
;; - Functions
|
||||
|
||||
(define-extern tie-init-buffers (function dma-buffer none))
|
||||
(define-extern tie-debug-between function)
|
||||
(define-extern tie-debug-one function)
|
||||
(define-extern walk-tie-generic-prototypes function)
|
||||
(define-extern draw-inline-array-instance-tie function)
|
||||
(define-extern draw-inline-array-prototype-tie-generic-asm function)
|
||||
(define-extern draw-inline-array-prototype-tie-asm function)
|
||||
(define-extern draw-inline-array-prototype-tie-near-asm function)
|
||||
(define-extern tie-test-cam-restore function)
|
||||
(define-extern tie-debug-between (function uint uint uint))
|
||||
(define-extern tie-debug-one (function uint uint uint))
|
||||
(define-extern walk-tie-generic-prototypes (function none))
|
||||
(define-extern draw-inline-array-instance-tie (function pointer drawable int dma-buffer none))
|
||||
(define-extern draw-inline-array-prototype-tie-generic-asm (function dma-buffer int prototype-array-tie none))
|
||||
(define-extern draw-inline-array-prototype-tie-asm (function dma-buffer int prototype-array-tie none))
|
||||
(define-extern draw-inline-array-prototype-tie-near-asm (function dma-buffer int prototype-array-tie none))
|
||||
(define-extern tie-test-cam-restore (function none))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
;;(define-extern *tie* object) ;; unknown type
|
||||
;;(define-extern *pke-hack* object) ;; unknown type
|
||||
(define-extern *tie* tie-instance-debug)
|
||||
(define-extern *pke-hack* vector)
|
||||
|
||||
|
||||
;; ----------------------
|
||||
|
||||
@@ -478,9 +478,9 @@
|
||||
"draw-drawable-tree-trans-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-dirt-tfrag": [6, 8, 13, 15],
|
||||
"draw-drawable-tree-ice-tfrag": [6, 8, 13, 15],
|
||||
|
||||
"birth-pickup-at-point": [0],
|
||||
"draw-drawable-tree-instance-tie": [10, 12, 18, 20, 26, 28, 37, 39],
|
||||
|
||||
"birth-pickup-at-point": [0],
|
||||
"draw-bones": [0, 1, 2, 8, 81],
|
||||
"draw-bones-hud": [7, 8]
|
||||
},
|
||||
|
||||
@@ -1973,6 +1973,13 @@
|
||||
["L162", "vu-function"]
|
||||
],
|
||||
|
||||
"tie": [
|
||||
["L43", "vu-function"]
|
||||
],
|
||||
|
||||
"tie-near": [
|
||||
["L91", "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": []
|
||||
}
|
||||
|
||||
@@ -5941,5 +5941,11 @@
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"tie-test-cam-restore": [
|
||||
[16, "vector"],
|
||||
[32, "matrix"],
|
||||
[96, "event-message-block"]
|
||||
],
|
||||
|
||||
"placeholder-do-not-add-below!": []
|
||||
}
|
||||
|
||||
@@ -7205,5 +7205,82 @@
|
||||
[137, "v1", "float"]
|
||||
],
|
||||
|
||||
"tie-init-engine": [
|
||||
[[14, 18], "a0", "dma-packet"],
|
||||
[[24, 28], "a0", "gs-gif-tag"],
|
||||
[31, "a0", "(pointer gs-test)"],
|
||||
[33, "a0", "(pointer gs-reg64)"],
|
||||
[[43, 51], "a0", "dma-packet"],
|
||||
[[64, 69], "a0", "dma-packet"],
|
||||
[[74, 78], "a0", "dma-packet"],
|
||||
[[82, 89], "v1", "(inline-array vector4w)"],
|
||||
[[89, 97], "v1", "(pointer vif-tag)"]
|
||||
],
|
||||
|
||||
"tie-end-buffer": [
|
||||
[[6, 10], "a1", "dma-packet"],
|
||||
[[16, 19], "a1", "gs-gif-tag"],
|
||||
[24, "a1", "(pointer gs-test)"],
|
||||
[26, "a1", "(pointer gs-reg64)"],
|
||||
[[32, 36], "a1", "dma-packet"],
|
||||
[[41, 52], "a0", "(pointer vif-tag)"]
|
||||
],
|
||||
|
||||
"tie-ints": [
|
||||
[[3, 30], "gp", "(pointer uint32)"]
|
||||
],
|
||||
|
||||
"tie-floats": [
|
||||
[[3, 73], "gp", "(pointer uint32)"]
|
||||
],
|
||||
|
||||
"tie-init-buffers": [
|
||||
[[29, 32], "v1", "dma-packet"],
|
||||
[[59, 62], "a0", "dma-packet"],
|
||||
[65, "a0", "(pointer uint32)"],
|
||||
[[96, 99], "v1", "dma-packet"],
|
||||
[[126, 129], "a0", "dma-packet"],
|
||||
[132, "a0", "(pointer uint32)"],
|
||||
[[163, 166], "v1", "dma-packet"],
|
||||
[[193, 196], "a0", "dma-packet"],
|
||||
[199, "a0", "(pointer uint32)"],
|
||||
[[230, 233], "v1", "dma-packet"],
|
||||
[[260, 263], "a0", "dma-packet"],
|
||||
[266, "a0", "(pointer uint32)"]
|
||||
],
|
||||
|
||||
"draw-drawable-tree-instance-tie": [
|
||||
[[23, 36], "v1", "drawable-inline-array-node"],
|
||||
[25, "a0", "drawable-inline-array-node"],
|
||||
[61, "v1", "drawable-inline-array-instance-tie"],
|
||||
[74, "v1", "drawable-inline-array-node"],
|
||||
[84, "v1", "int"],
|
||||
[86, "a0", "int"],
|
||||
[66, "a1", "terrain-context"],
|
||||
[[363, 366], "v1", "dma-packet"],
|
||||
[[484, 487], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"(method 10 drawable-tree-instance-tie)": [
|
||||
[3, "a1", "terrain-context"]
|
||||
],
|
||||
|
||||
"(method 14 drawable-tree-instance-tie)": [
|
||||
[[47, 62], "t1", "tie-fragment"],
|
||||
[[102, 117], "t1", "tie-fragment"],
|
||||
[[150, 165], "a1", "tie-fragment"]
|
||||
],
|
||||
|
||||
"(method 11 drawable-inline-array-instance-tie)": [
|
||||
[[1, 6], "v1", "instance-tie"]
|
||||
],
|
||||
|
||||
"(method 12 drawable-inline-array-instance-tie)": [
|
||||
[[1, 6], "v1", "instance-tie"]
|
||||
],
|
||||
|
||||
"(method 13 drawable-inline-array-instance-tie)": [
|
||||
[[1, 6], "v1", "instance-tie"]
|
||||
],
|
||||
"placeholder-do-not-add-below": []
|
||||
}
|
||||
|
||||
@@ -31,6 +31,19 @@ void Vector::read_from_file(Ref ref) {
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix4h::read_from_file(Ref ref) {
|
||||
if ((ref.byte_offset % 16) != 0) {
|
||||
throw Error("misaligned Matrix4h");
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
const auto& word = ref.data->words_by_seg.at(ref.seg).at((ref.byte_offset / 4) + i);
|
||||
if (word.kind() != decompiler::LinkedWord::PLAIN_DATA) {
|
||||
throw Error("Matrix4h didn't get plain data.");
|
||||
}
|
||||
memcpy(&data[i * 2], &word.data, 4);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Vector::print(int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
@@ -426,6 +439,32 @@ void TieFragment::read_from_file(TypedRef ref,
|
||||
bsphere.read_from_file(get_field_ref(ref, "bsphere", dts));
|
||||
num_tris = read_plain_data_field<u16>(ref, "num-tris", dts);
|
||||
num_dverts = read_plain_data_field<u16>(ref, "num-dverts", dts);
|
||||
tex_count = read_plain_data_field<u16>(ref, "tex-count", dts);
|
||||
gif_count = read_plain_data_field<u16>(ref, "gif-count", dts);
|
||||
vertex_count = read_plain_data_field<u16>(ref, "vertex-count", dts);
|
||||
|
||||
auto gif_data_ref = deref_label(get_field_ref(ref, "gif-ref", dts));
|
||||
|
||||
assert((tex_count % 5) == 0);
|
||||
u32 total_gif_qw = tex_count + gif_count;
|
||||
gif_data.resize(16 * total_gif_qw);
|
||||
for (u32 i = 0; i < total_gif_qw * 4; i++) {
|
||||
auto& word =
|
||||
gif_data_ref.data->words_by_seg.at(gif_data_ref.seg).at((gif_data_ref.byte_offset / 4) + i);
|
||||
assert(word.kind() == decompiler::LinkedWord::PLAIN_DATA);
|
||||
memcpy(gif_data.data() + (i * 4), &word.data, 4);
|
||||
}
|
||||
|
||||
auto points_data_ref = deref_label(get_field_ref(ref, "point-ref", dts));
|
||||
point_ref.resize(16 * vertex_count);
|
||||
debug_label_name = inspect_ref(get_field_ref(ref, "point-ref", dts));
|
||||
for (u32 i = 0; i < vertex_count * 4; i++) {
|
||||
auto& word = points_data_ref.data->words_by_seg.at(points_data_ref.seg)
|
||||
.at((points_data_ref.byte_offset / 4) + i);
|
||||
assert(word.kind() == decompiler::LinkedWord::PLAIN_DATA);
|
||||
memcpy(point_ref.data() + (i * 4), &word.data, 4);
|
||||
}
|
||||
|
||||
stats->total_tie_prototype_tris += num_tris;
|
||||
}
|
||||
|
||||
@@ -457,6 +496,12 @@ void InstanceTie::read_from_file(TypedRef ref,
|
||||
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);
|
||||
flags = read_plain_data_field<u16>(ref, "flags", dts);
|
||||
// assert(flags == 0); // TODO
|
||||
origin.read_from_file(get_field_ref(ref, "origin", dts));
|
||||
wind_index = read_plain_data_field<u16>(ref, "wind-index", dts);
|
||||
color_indices = deref_label(get_field_ref(ref, "color-indices", dts));
|
||||
stats->total_tie_instances++;
|
||||
}
|
||||
|
||||
@@ -596,9 +641,9 @@ std::string DrawableInlineArrayTFrag::my_type() const {
|
||||
return "drawable-inline-array-tfrag";
|
||||
}
|
||||
|
||||
void DrawableInlineArrayTie::read_from_file(TypedRef ref,
|
||||
const decompiler::DecompilerTypeSystem& dts,
|
||||
DrawStats* stats) {
|
||||
void DrawableInlineArrayInstanceTie::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));
|
||||
@@ -616,7 +661,7 @@ void DrawableInlineArrayTie::read_from_file(TypedRef ref,
|
||||
}
|
||||
}
|
||||
|
||||
std::string DrawableInlineArrayTie::print(const PrintSettings& settings, int indent) const {
|
||||
std::string DrawableInlineArrayInstanceTie::print(const PrintSettings& settings, int indent) const {
|
||||
std::string is(indent, ' ');
|
||||
std::string result;
|
||||
int next_indent = indent + 4;
|
||||
@@ -634,7 +679,7 @@ std::string DrawableInlineArrayTie::print(const PrintSettings& settings, int ind
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string DrawableInlineArrayTie::my_type() const {
|
||||
std::string DrawableInlineArrayInstanceTie::my_type() const {
|
||||
return "drawable-inline-array-instance-tie";
|
||||
}
|
||||
|
||||
@@ -703,7 +748,7 @@ std::unique_ptr<DrawableInlineArray> make_drawable_inline_array(
|
||||
}
|
||||
|
||||
if (ref.type->get_name() == "drawable-inline-array-instance-tie") {
|
||||
auto result = std::make_unique<DrawableInlineArrayTie>();
|
||||
auto result = std::make_unique<DrawableInlineArrayInstanceTie>();
|
||||
result->read_from_file(ref, dts, stats);
|
||||
return result;
|
||||
}
|
||||
@@ -824,11 +869,13 @@ void PrototypeBucketTie::read_from_file(TypedRef ref,
|
||||
DrawStats* stats) {
|
||||
name = read_string_field(ref, "name", dts, true);
|
||||
flags = read_plain_data_field<u32>(ref, "flags", dts);
|
||||
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);
|
||||
|
||||
auto next_slot = get_field_ref(ref, "next", dts);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -882,6 +929,37 @@ void PrototypeBucketTie::read_from_file(TypedRef ref,
|
||||
for (auto x : generic_next) {
|
||||
assert(x == 0);
|
||||
}
|
||||
|
||||
// get the color count data
|
||||
{
|
||||
u32 num_color_qwcs = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
u32 start = index_start[i];
|
||||
u32 end = start + frag_count[i];
|
||||
// fmt::print("i = {}: {} -> {}\n", i, start, end);
|
||||
assert(num_color_qwcs <= end);
|
||||
num_color_qwcs = std::max(end, num_color_qwcs);
|
||||
}
|
||||
|
||||
auto data_array = get_field_ref(ref, "color-index-qwc", dts);
|
||||
for (u32 i = 0; i < num_color_qwcs; i++) {
|
||||
int byte_offset = data_array.byte_offset + i;
|
||||
auto word = data_array.data->words_by_seg.at(data_array.seg).at(byte_offset / 4);
|
||||
color_index_qwc.push_back(word.get_byte(byte_offset % 4));
|
||||
}
|
||||
}
|
||||
|
||||
// get the colors
|
||||
auto palette = deref_label(get_field_ref(ref, "tie-colors", 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 PrototypeBucketTie::print(const PrintSettings& settings, int indent) const {
|
||||
|
||||
@@ -23,6 +23,11 @@ struct Vector {
|
||||
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;
|
||||
@@ -156,6 +161,15 @@ struct TieFragment : public Drawable {
|
||||
u16 num_tris;
|
||||
u16 num_dverts;
|
||||
|
||||
u16 tex_count;
|
||||
u16 gif_count;
|
||||
u16 vertex_count; // qwc of vertex data.
|
||||
|
||||
std::vector<u8> gif_data;
|
||||
std::vector<u8> point_ref;
|
||||
|
||||
std::string debug_label_name;
|
||||
|
||||
// todo, lots more
|
||||
};
|
||||
|
||||
@@ -168,7 +182,13 @@ struct InstanceTie : public Drawable {
|
||||
|
||||
// (bucket-index uint16 :offset 6)
|
||||
u16 bucket_index;
|
||||
s16 id;
|
||||
Vector bsphere;
|
||||
Matrix4h origin;
|
||||
u16 flags;
|
||||
u16 wind_index;
|
||||
|
||||
Ref color_indices; // can't read this in the first pass because we don't know how long.
|
||||
|
||||
// todo, lots more
|
||||
};
|
||||
@@ -201,7 +221,7 @@ struct DrawableInlineArrayTFrag : public DrawableInlineArray {
|
||||
std::string my_type() const override;
|
||||
};
|
||||
|
||||
struct DrawableInlineArrayTie : public DrawableInlineArray {
|
||||
struct DrawableInlineArrayInstanceTie : public DrawableInlineArray {
|
||||
s16 id;
|
||||
s16 length;
|
||||
Vector bsphere;
|
||||
@@ -295,13 +315,19 @@ struct PrototypeBucketTie {
|
||||
|
||||
u16 generic_count[4];
|
||||
u32 generic_next[4];
|
||||
u8 frag_count[4];
|
||||
u8 frag_count[4] = {0};
|
||||
u8 index_start[4];
|
||||
u16 base_qw[4];
|
||||
|
||||
float envmap_rfade;
|
||||
float envmap_fade_far;
|
||||
|
||||
float stiffness;
|
||||
|
||||
std::vector<u8> color_index_qwc;
|
||||
|
||||
TimeOfDayPalette time_of_day;
|
||||
|
||||
// todo envmap shader
|
||||
// todo collide-frag
|
||||
// todo tie-colors
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "extract_level.h"
|
||||
#include "decompiler/level_extractor/BspHeader.h"
|
||||
#include "decompiler/level_extractor/extract_tfrag.h"
|
||||
#include "decompiler/level_extractor/extract_tie.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
namespace decompiler {
|
||||
@@ -91,10 +92,14 @@ void extract_from_level(ObjectFileDB& db,
|
||||
}
|
||||
extract_tfrag(as_tfrag_tree, fmt::format("{}-{}", dgo_name, i++),
|
||||
bsp_header.texture_remap_table, tex_db, expected_missing_textures, tfrag_level);
|
||||
} else if (draw_tree->my_type() == "drawable-tree-instance-tie") {
|
||||
fmt::print(" extracting TIE\n");
|
||||
auto as_tie_tree = dynamic_cast<level_tools::DrawableTreeInstanceTie*>(draw_tree.get());
|
||||
assert(as_tie_tree);
|
||||
extract_tie(as_tie_tree, fmt::format("{}-{}-tie", dgo_name, i++),
|
||||
bsp_header.texture_remap_table, tex_db, tfrag_level);
|
||||
} else {
|
||||
fmt::print(" unsupported tree {}\n", draw_tree->my_type());
|
||||
tfrag_level.trees.emplace_back();
|
||||
tfrag_level.trees.back().kind = tfrag3::TFragmentTreeKind::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1976,7 +1976,7 @@ std::map<u32, std::vector<GroupedDraw>> make_draw_groups(std::vector<TFragDraw>&
|
||||
}
|
||||
|
||||
void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
|
||||
tfrag3::Tree& tree_out,
|
||||
tfrag3::TfragTree& tree_out,
|
||||
std::vector<tfrag3::Texture>& texture_pool,
|
||||
const TextureDB& tdb,
|
||||
const std::vector<std::pair<int, int>>& expected_missing_textures) {
|
||||
@@ -2030,13 +2030,13 @@ void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
|
||||
|
||||
// now, add draws
|
||||
for (auto& draw : draw_list) {
|
||||
tfrag3::Draw tdraw;
|
||||
tfrag3::StripDraw tdraw;
|
||||
tdraw.mode = draw.mode;
|
||||
tdraw.tree_tex_id = tfrag3_tex_id;
|
||||
|
||||
for (auto& strip : draw.strips) {
|
||||
tfrag3::Draw::VisGroup vgroup;
|
||||
vgroup.tfrag_idx = strip.tfrag_id; // associate with the tfrag for culling
|
||||
tfrag3::StripDraw::VisGroup vgroup;
|
||||
vgroup.vis_idx = strip.tfrag_id; // associate with the tfrag for culling
|
||||
vgroup.num = strip.verts.size() + 1; // one for the primitive restart!
|
||||
|
||||
tdraw.num_triangles += strip.verts.size() - 2;
|
||||
@@ -2049,7 +2049,7 @@ void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
|
||||
vtx.s = vert.stq.x();
|
||||
vtx.t = vert.stq.y();
|
||||
vtx.q = vert.stq.z();
|
||||
vtx.color_index = vert.rgba;
|
||||
vtx.color_index = vert.rgba / 4;
|
||||
// assert((vert.rgba >> 2) < 1024); spider cave has 2048?
|
||||
assert((vert.rgba & 3) == 0);
|
||||
|
||||
@@ -2071,7 +2071,7 @@ void emulate_tfrags(const std::vector<level_tools::TFragment>& frags,
|
||||
const std::string& debug_name,
|
||||
const std::vector<level_tools::TextureRemap>& map,
|
||||
tfrag3::Level& level_out,
|
||||
tfrag3::Tree& tree_out,
|
||||
tfrag3::TfragTree& tree_out,
|
||||
const TextureDB& tdb,
|
||||
const std::vector<std::pair<int, int>>& expected_missing_textures) {
|
||||
TFragExtractStats stats;
|
||||
@@ -2099,7 +2099,7 @@ void emulate_tfrags(const std::vector<level_tools::TFragment>& frags,
|
||||
file_util::get_file_path({"debug_out", fmt::format("tfrag-{}.obj", debug_name)}), debug_out);
|
||||
}
|
||||
|
||||
void extract_time_of_day(const level_tools::DrawableTreeTfrag* tree, tfrag3::Tree& out) {
|
||||
void extract_time_of_day(const level_tools::DrawableTreeTfrag* tree, tfrag3::TfragTree& out) {
|
||||
out.colors.resize(tree->time_of_day.height);
|
||||
for (int i = 0; i < (int)tree->time_of_day.height; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
@@ -2116,7 +2116,7 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree,
|
||||
const TextureDB& tex_db,
|
||||
const std::vector<std::pair<int, int>>& expected_missing_textures,
|
||||
tfrag3::Level& out) {
|
||||
tfrag3::Tree this_tree;
|
||||
tfrag3::TfragTree this_tree;
|
||||
if (tree->my_type() == "drawable-tree-tfrag") {
|
||||
this_tree.kind = tfrag3::TFragmentTreeKind::NORMAL;
|
||||
} else if (tree->my_type() == "drawable-tree-dirt-tfrag") {
|
||||
@@ -2151,17 +2151,17 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree,
|
||||
fmt::print(" tree has {} arrays and {} tfragments\n", tree->length, as_tfrag_array->length);
|
||||
|
||||
auto vis_nodes = extract_vis_data(tree, as_tfrag_array->tfragments.front().id);
|
||||
this_tree.first_leaf_node = vis_nodes.first_child_node;
|
||||
this_tree.last_leaf_node = vis_nodes.last_child_node;
|
||||
this_tree.num_roots = vis_nodes.num_roots;
|
||||
this_tree.only_children = vis_nodes.only_children;
|
||||
this_tree.first_root = vis_nodes.first_root;
|
||||
this_tree.vis_nodes = std::move(vis_nodes.vis_nodes);
|
||||
this_tree.bvh.first_leaf_node = vis_nodes.first_child_node;
|
||||
this_tree.bvh.last_leaf_node = vis_nodes.last_child_node;
|
||||
this_tree.bvh.num_roots = vis_nodes.num_roots;
|
||||
this_tree.bvh.only_children = vis_nodes.only_children;
|
||||
this_tree.bvh.first_root = vis_nodes.first_root;
|
||||
this_tree.bvh.vis_nodes = std::move(vis_nodes.vis_nodes);
|
||||
|
||||
std::unordered_map<int, int> tfrag_parents;
|
||||
// for (auto& node : this_tree.vis_nodes) {
|
||||
for (size_t node_idx = 0; node_idx < this_tree.vis_nodes.size(); node_idx++) {
|
||||
const auto& node = this_tree.vis_nodes[node_idx];
|
||||
for (size_t node_idx = 0; node_idx < this_tree.bvh.vis_nodes.size(); node_idx++) {
|
||||
const auto& node = this_tree.bvh.vis_nodes[node_idx];
|
||||
if (node.flags == 0) {
|
||||
for (int i = 0; i < node.num_kids; i++) {
|
||||
tfrag_parents[node.child_id + i] = node_idx;
|
||||
@@ -2176,14 +2176,14 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree,
|
||||
|
||||
for (auto& draw : this_tree.draws) {
|
||||
for (auto& str : draw.vis_groups) {
|
||||
auto it = tfrag_parents.find(str.tfrag_idx);
|
||||
auto it = tfrag_parents.find(str.vis_idx);
|
||||
if (it == tfrag_parents.end()) {
|
||||
str.tfrag_idx = UINT32_MAX;
|
||||
str.vis_idx = UINT32_MAX;
|
||||
} else {
|
||||
str.tfrag_idx = it->second;
|
||||
str.vis_idx = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.trees.push_back(this_tree);
|
||||
out.tfrag_trees.push_back(this_tree);
|
||||
}
|
||||
} // namespace decompiler
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "extract_tie.h"
|
||||
#include "decompiler/level_extractor/BspHeader.h"
|
||||
#include "decompiler/data/TextureDB.h"
|
||||
#include "common/custom_data/Tfrag3Data.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
void extract_tie(const level_tools::DrawableTreeInstanceTie* tree,
|
||||
const std::string& debug_name,
|
||||
const std::vector<level_tools::TextureRemap>& tex_map,
|
||||
const TextureDB& tex_db,
|
||||
tfrag3::Level& out);
|
||||
}
|
||||
@@ -57,6 +57,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
file_util::create_dir_if_needed(out_folder);
|
||||
file_util::create_dir_if_needed(file_util::get_file_path({"debug_out"}));
|
||||
|
||||
fmt::print("[Mem] After config read: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
# Porting Tfrag
|
||||
Tfrag is the renderer for non-instanced background geometry. It's typically used for the floor and unique walls/level geometry. It has a level of detail system, and time of day lighting, optionaly transparancy and that's it. No other features.
|
||||
|
||||
The approach I took was to go slowly and understand the rendering code. I made two different "test" renderers that were slow but did things exactly the same way as in the PS2 version. After this, I made a custom PC version called tfrag3. The key difference with tfrag3 is that there is an offline preprocessing step that reads the level data and outputs data in a good format for PC.
|
||||
|
||||
Trying to understand the rendering code is annoying, but I think it was worth it in the end.
|
||||
- you can often leave out huge chunks of code. I never touched `tfrag-near` or most of the `tfrag` VU program.
|
||||
- you can eventually figure out how move more to the GPU. For example, all clipping/scissoring and transformation is done on the GPU. This is faster (GPUs are good) and easier (OpenGL does it automatically if you set it up right, you don't have to do the math).
|
||||
- you can rearrange things for better performance. Keeping the number of OpenGL draw calls down is probably the best thing we can do for performance.
|
||||
|
||||
But in order to understand the renderer, I had to start with a slow "emulation-like" port.
|
||||
|
||||
This document is divided into three parts:
|
||||
1. PS2 rendering (in Jak).
|
||||
2. Jak's `drawable` system
|
||||
3. Tfrag-specific details
|
||||
|
||||
# Basics of PS2 Rendering
|
||||
The main idea of the Jak rendering system is that there are always two frames in progress at a time. One frame is being "rendered" meaning triangles are being transformed and rasterized and the VRAM is being written to. The other frame is being "calculated", meaning the game is building the list of instructions to draw the frame. The "calculation" happens from GOAL code, mostly on the EE, and builds a single giant "DMA chain". At the end of a frame, the engine takes the full DMA chain that was built, and sends it to the rendering hardware. The rendering process is all "automatic" - once it gets the list of data it will run for an entire frame and do all of the drawing.
|
||||
|
||||
The EE user manual sections for DMAC, VPU (VU), and GIF are worth reading before trying to understand new rendering code.
|
||||
|
||||
Because the calculation and rendering happen simultaneously, the calculation cannot use the same hardware and memory as the rendering. The following resources are used only by rendering:
|
||||
- VU1
|
||||
- VIF1
|
||||
- GIF
|
||||
- GS
|
||||
|
||||
The following resources are used only by calculation:
|
||||
- VU0-macro mode (`vf` register on EE and `vadd` like instructions)
|
||||
- VU0-micro mode
|
||||
- VIF0
|
||||
- The scratchpad
|
||||
|
||||
The following resources are shared:
|
||||
- DMA controller. It can handle multiple transfers to different places at the same time, and there are no shared destinations, so there's no issue here. Rendering uses only to VIF1. Calculation uses to VIF0, to scratchpad, and from scratchpad.
|
||||
- The "global" DMA buffer. The calculation process fills this buffer and the rendering reads from it. There are two copies of this buffer and the engine will swap them automatically at the end of the frame. So one copy is always being filled while the other is being read and the graphics code mostly doesn't worry about this.
|
||||
- DMA data inside of level data. The DMA list may include chunks of data that's part of the level data. In practice there's not much to be aware of here - the rendering process just reads this data.
|
||||
|
||||
## DMA
|
||||
The whole rendering system is driven by DMA. The DMA controller can copy data from main memory to different peripherals. If the destination is "busy", it will wait. So it doesn't just blindly dump data into things as fast as it can - it only sends data if the destination is ready to accept it. The DMA controller is controlled by "DMA tags". These contain a command like "transfer X bytes of data from address Y, then move on to the DMA tag at address Z". This allows the game to build up really complicated linked-lists of data to send.
|
||||
|
||||
The DMA list built for rendering is divided into buckets. See `dma-h.gc` for the bucket names. Individual renderers add data to buckets, and then the buckets are linked together in the order they are listed in that enum. Code like `tfrag` won't start DMA to VIF1 or deal with linking buckets - that is handled by the game engine.
|
||||
|
||||
However, code like `tfrag` may just set up its own transfers to/from SPR and VIF0 - these are free-to-use during the "calculation" step.
|
||||
|
||||
## The VIF
|
||||
The VIF is "vector unit interface". There's one for VU0 and VU1 and they are (as far as I know) identical. The rendering DMA list is sent directly to VIF1. There are also "tags" that control the VIF. The general types of tags are:
|
||||
- "take the following N bytes of data and copy it to VU data memory" (possibly with some fancy "unpacking" operation to move stuff around)
|
||||
- "take the following N bytes of data and copy it to VU program memory" - to upload a new VU program
|
||||
- "run a VU program starting at this address in VU program memory"
|
||||
- "send this data **direct**ly to the GIF" This is called a "direct" transfer. It's typically used to set things up on the GS that will be constant for one specific renderer.
|
||||
|
||||
I haven't seen VIF0 really used much. The pattern for VIF1 is usually:
|
||||
1. upload program
|
||||
2. upload some constants
|
||||
3. upload some model data
|
||||
4. run program
|
||||
5. repeat steps 3 and 4 many times
|
||||
|
||||
## VU programs
|
||||
The VU programs are usually responsible for transforming vertices with the camera matrix, clipping, lighting calculations, etc. The output of a VU program is GIF packets containing the actual drawing information (transformed vertices, drawing settings, etc).
|
||||
|
||||
The usual pattern is that the VU program will build up a GIF packet, then use the `XGKICK` instruction with the address of the start of the packet. This will start transferring the packet directly to the GIF. The transfer happens in the background. The transfer will only be completed once all triangles are drawn - there's no buffer on the GIF/GS. A single packet can be pretty big and have many triangles.
|
||||
|
||||
For the tfrag1/tfrag2 renderers, I ported up to this part. Then, I sent the `xgkick` data to the `DirectRenderer` which can handle this format of data. It is not super fast, but it's nice for debugging. Being able to inspect this was helpful to understand how it works.
|
||||
|
||||
## VU buffer hell
|
||||
Typically the VU programs have 4 buffers. There is a buffer for input and output data, and both are double buffered. This allows you to be uploading new data with DMA, transforming vertices, and sending data to the GIF all at the same time.
|
||||
|
||||
All 4 buffers are in use at the same time.
|
||||
1. Untransformed Data being uploaded from the DMA list to VU data. This happens automatically by DMA.
|
||||
2. Untransformed Data being transformed by the VU1 program.
|
||||
3. A GIF packet being built from the output of the transformation. This is written by the VU1 program.
|
||||
4. A GIF packet currently being `XGKICK`ed.
|
||||
|
||||
Once 1 is full and 2 is totally used, these buffers are swapped. The same thing happens for 3 and 4.
|
||||
In some renderers, these swaps are always done at the same time. For example `sprite`. This tends to use the built-in `xitop` instructions for managing double buffering.
|
||||
|
||||
In other renderers, the buffer swaps can happen at different times. This leads to awful code where you have 4 different versions of the same renderer for all possible combinations of which buffers are input/output. Storing the address of the input/output buffer in a variable can lead to extra instructions inside the transformation loops, which will significantly slow down.
|
||||
|
||||
## GIF
|
||||
The GIF can receive commands like:
|
||||
- "set the alpha blending mode to X"
|
||||
- "use texture located at VRAM address Y"
|
||||
- "draw a triangle"
|
||||
|
||||
It can't do any transformation or lighting calculations.
|
||||
|
||||
|
||||
# Jak `drawable` system
|
||||
There is a `drawable` system that's used to store things that can be "drawn". It uses a tree structure. So you can do something like
|
||||
```
|
||||
(draw some-level)
|
||||
```
|
||||
and it will recursively go through the entire level's tree of drawables and draw everything. Note that there are a lot of tricks/hacks so not every `drawable` supports `draw` and some code may defer some `draw`s until later.
|
||||
|
||||
The lowest-level drawable for tfrag is `tfragment`. It makes sense to split up the level into "fragments" because the entire level is way too big to fit in the VU memory. Most of the time, you can't see every triangle in the level, so it makes sense to skip uploading the fragments that you know can't be seen.
|
||||
There are thousands of these fragments. They tend to be ~ a few kB and each contains a chunk of data to upload to the VUs. Note that `draw` is not called directly on `tfragment`, despite the fact that they are `drawable`s (more details later). The `tfragment` is just a reference to some DMA data.
|
||||
|
||||
## Drawables for Tfrag
|
||||
|
||||
The top-level drawable type for an entire level is `bsp-header`. This is the type of the `-vis` file of the level's DGO, and has all the graphics data (not including textures). It is also a `drawable`.
|
||||
|
||||
Within `bsp-header` is a `drawable-tree-array`. As the name implies, this contains an array of `drawable-tree`. Usually there are 5-10 of these in a level. There will be a `drawable-tree` for each renderer. Or possibly a few per renderer, if that renderer supports different modes. For example there's one for tfrag, one for transparent tfrag, one for tie, etc.
|
||||
|
||||
You can just check the type of the `drawable-tree` to see if it's for tfrag/tie etc. The tfrag types are:
|
||||
- `drawable-tree-tfrag` (parent of the rest)
|
||||
- `drawable-tree-trans-tfrag`
|
||||
- `drawable-tree-dirt-tfrag`
|
||||
- `drawable-tree-ice-tfrag`
|
||||
- `drawable-tree-lowres-tfrag`
|
||||
- `drawable-tree-lowres-trans-tfrag`
|
||||
|
||||
Each "tree" contains a bunch of `tfragment`s and a time of day color palette. But they are stored in a really weird way. There is a bounding volume hierarchy of `tfragment`s. This is just a tree-like structure where each node stores a sphere, and all the node's children fit inside of that sphere. The nodes at each depth are stored in an array. The layout of this tree is designed to let them use some crazy assembly SIMD 8-at-a-time traversal of the tree, with minimal pointer-chasing and good memory access patterns.
|
||||
|
||||
Each tree has an array of `drawable-inline-array`s, storing all the nodes at a given depth. The last `drawable-inline-array` is actually a `drawable-inline-array-frag`, which is a wrapper around an inline array of `tfragment`s.
|
||||
|
||||
The other arrays are used to store tree nodes to organize these `tfragment`s. Each node in the tree contains a `bsphere`. All tfrags below the node fit into this sphere.
|
||||
|
||||
The second to last array (if it exists) is a `drawable-inline-array-node`. This contains an inline array of `draw-node`. Each `draw-node` is the parent of between 1 and 8 `tfragment`s. They store a reference to the first child `tfragment` and a child count, and the children are just the ones that come after the first `tfragment` in memory.
|
||||
|
||||
The third to last array (if it exists) is also a `drawable-inline-array-node`, containing an inline array of `draw-node`. Each `draw-node` is the parent of between 1 and 8 `draw-node`s from the array mentioned above. They store a reference to the first child `draw-node` and a child count, and the children are stored consecutively.
|
||||
|
||||
This pattern continues until you get a `drawable-inline-array-node` with 8 or fewer nodes at the top.
|
||||
|
||||
All the `draw-node` and `tfragment`s have ID numbers. These are used for the occlusion culling system. The visibility numbering is shared with all the other `drawable-tree`s in the `bsp-header`. The indices are given out consecutively, starting from the roots. Between depths, they are aligned to 32 elements, so there are some unused ids. These IDs are the index of the bit in the visibility string.
|
||||
|
||||
With that out of the way, we can now go through the tfrag renderer
|
||||
|
||||
# Tfrag
|
||||
|
||||
The rough process for rendering is:
|
||||
- "login" the data
|
||||
- do "drawing" as part of the `drawable` system (on EE)
|
||||
- do the real "draw"
|
||||
- do culling
|
||||
- compute time of day colors (or other precomputation)
|
||||
- generate DMA lists
|
||||
- unpack data to VU memory
|
||||
- transform vertices
|
||||
- clip
|
||||
- build gs packets
|
||||
- XGKICK
|
||||
|
||||
I expect that most other renderers will be pretty similar.
|
||||
|
||||
## Login
|
||||
The tfrag data needs to be initialized before it can be used. You only have to do this once. This is called `login`, and it's a method of all `drawable`s. The level loader will call the `login` method of many things as part of the level load. For `tfrag`, all I had to do was decompile the `login` methods, and it worked and I could completely ignore this until tfrag3.
|
||||
|
||||
It's possible to just call `login` on an entire level, but this probably takes too long, so the level loader will cleverly split it up over multiple frames.
|
||||
|
||||
It is from:
|
||||
- `level-update`
|
||||
- `load-continue`
|
||||
- `level-update-after-load`
|
||||
- various calls to `login`.
|
||||
|
||||
|
||||
In the end, the only thing the `login` does for tfrag is:
|
||||
```
|
||||
(adgif-shader-login-no-remap (-> obj shader i))
|
||||
```
|
||||
for all the "shaders" in all the tfrags. A "shader" is an `adgif-shader`, which is just some settings for the GS that tells it drawing modes, like which texture to use, blending modes, etc. The `tfrag` VU1 code will send these to the GIF as needed when drawing. A `tfragment` can have multiple shaders. There is a different shader per texture.
|
||||
|
||||
The actual "shader" object is just 5x quadwords that contain "adress + data" format data. The address tells the GIF which parameter to change and the "data" has the value of the parameter. Some of them are not set properly in the level data, and the `adgif-shader-login-no-remap` function updates them. For tfrag, the 5 addresses are always the same:
|
||||
|
||||
- `TEST_1`: this sets the alpha and z test settings. This is set properly in the level data and `login` doesn't touch it.
|
||||
- `TEX0_1`: this has some texture parameters. This is 0 in the level data and is modified by `login`.
|
||||
- `TEX1_1`: this has more texture parameters. In the level data this is has `0x120` as the value and the address is set to the texture ID of the texture. During `login`, the texture ID is looked up in the texture pool and `TEX0_1`/`TEX1_1` are set to point to the right VRAM address and have the right settings to use the texture.
|
||||
- `MIPTBP1_1`: is mipmap settings. I ignore these because we do our own mipmapping.
|
||||
- `CLAMP_1`: this has texture clamp settings. This is set properly in the level data.
|
||||
- `ALPHA_1`: this has alpha blend settings. This is set properly in the level data.
|
||||
|
||||
|
||||
## Calling the `draw` method
|
||||
The `tfragment` at least pretends to use the `drawable` system, and the drawing is initiated by calling `draw` on the `drawable-tree-tfrag`. Getting this to actually be called took some digging - it uses some functions in later files that we haven't completed yet.
|
||||
|
||||
When the level is loaded, the `bsp-header` is added to the `*background-draw-engine*` by the level loader. The path to calling draw is:
|
||||
- In `main.gc`, there is a `display-loop`. This has a while loop that runs once per frame and runs many systems.
|
||||
- The `display-loop` calls `*draw-hook*`
|
||||
- The `*draw-hook*` variable is set to `main-draw-hook`
|
||||
- The `main-draw-hook` calls `real-main-draw-hook`
|
||||
- The `real-main-draw-hook` calls `(execute-connections *background-draw-engine*`
|
||||
- This "engine" calls the `add-bsp-drawable` function on the `bsp-header` for each loaded level.
|
||||
- The `draw` method of `bsp-header` sets up some stuff on the scratchpad and some `vf` registers.
|
||||
- The `draw` method of `bsp-header` calls `draw` on the `drawable-tree-array` (defined in parent class `drawable-group`)
|
||||
- The `draw` method of `drawable-group` checks if the level is visible, and if so calls `draw` on each tree.
|
||||
- The `draw` method of `drawable-tree-tfrag` simply adds the tree to a list of trees in `*background-work*`.
|
||||
|
||||
|
||||
## Real "drawing"
|
||||
Later on, in the `real-main-draw-hook`, there is a call to `finish-background`.
|
||||
|
||||
There's some stuff at the top of this function that's only used for the separate shrubbery renderer. It sets up some VU0 programs. I noticed that the stuff before tfrag drawing would overwrite this VU0 stuff so I ignored it for now.
|
||||
|
||||
The first thing that happens before any tfrag drawing is setting the `vf` registers to store the `math-camera` values. In OpenGOAL, the `vf` registers aren't saved between functions, so I had to manually use the `with-vf` macro with the `:rw 'write` flag to save these:
|
||||
```lisp
|
||||
(let ((v1-48 *math-camera*))
|
||||
(with-vf (vf16 vf17 vf18 vf19 vf20 vf21 vf22 vf23 vf24 vf25 vf26 vf27 vf28 vf29 vf30 vf31)
|
||||
:rw 'write
|
||||
(.lvf vf16 (&-> v1-48 plane 0 quad))
|
||||
(.lvf vf17 (&-> v1-48 plane 1 quad))
|
||||
;; ...
|
||||
```
|
||||
these will later be used in part of the drawing function. The `:rw 'write` flag will save these to a structure where we can read them later.
|
||||
|
||||
Then, for each tree:
|
||||
```
|
||||
(upload-vis-bits s1-0 gp-1 a2-4)
|
||||
```
|
||||
this uploads the visibility data to the scratchpad. The visibility data is stored at the end of the 16 kB scratchpad. The drawable with ID of `n` can look at the `n`-th bit of this data to determine if it is visible. The visibility IDs are per level, and the drawing order of the `tfrag` will alternate between levels, so they upload this for each tree to draw. It seems like you could skip this after the first upload if you detect that you're drawing multiple trees in the same level. They do it for TIE and not TFRAG and don't know why. The visibility data is based on the position of the camera. Currently this doesn't work so I modified it to upload all 1's.
|
||||
|
||||
The modification to the code to use the scratchpad in OpenGOAL is:
|
||||
```
|
||||
;;(spad-vis (the-as (pointer uint128) (+ #x38b0 #x70000000)))
|
||||
(spad-vis (scratchpad-ptr uint128 :offset VISIBLE_LIST_SCRATCHPAD))
|
||||
```
|
||||
The `0x38b0` offset is just something we've noticed over time as being the location of the visible list, so there's a constant I made for it. (TODO: I think it's also `terrain-context work background vis-list`)
|
||||
|
||||
The hack for visibility is:
|
||||
```lisp
|
||||
;; TODO this is a hack.
|
||||
(quad-copy! (-> arg0 vis-bits) (-> arg2 all-visible-list) (/ (+ (-> arg2 visible-list-length) 15) 16))
|
||||
```
|
||||
which actually modifies the level to say that everything is visbile. The `all-visible-list` is just a list which has `1` for every drawable that actually exists (I think, need to configm). There are some skipped ID's.
|
||||
|
||||
|
||||
The next part of drawing is:
|
||||
```
|
||||
(when (not (or (zero? s0-0) (= s4-1 s0-0)))
|
||||
(flush-cache 0)
|
||||
(time-of-day-interp-colors-scratch (scratchpad-ptr rgba :offset 6160) s0-0 (-> s1-0 mood))
|
||||
;; remember the previous colors
|
||||
(set! s4-1 s0-0)
|
||||
```
|
||||
where `s0-0` is the `time-of-day-pal` for the tfrag tree. It will skip interpolation if it is the same color palette that was just interpolated.
|
||||
|
||||
The `time-of-day-interp-colors-scratch` function uploads the colors from `s0-0` to the scratchpad at offset `6160`. It computes the correct colors for the time-of-day/lighting settings in the the level `s1-0`'s mood. This function is pretty complicated, so I used MIPS2C.
|
||||
|
||||
### Time of Day Interp Colors Scratch
|
||||
The very first attempts for TFRAG just skipped this function because it wasn't needed to debug the basic drawing functions. I manually set the lighting to `0.5` for all colors and `1.0` for alpha. I suspected that this stored the colors in the scratchpad. I assumed it would be fine if these garbage for a first test.
|
||||
|
||||
I noticed that this function does a few tricky things. It uses the scratchpad and it uses DMA. I know it uses DMA because I saw:
|
||||
```cpp
|
||||
c->lui(t0, 4096); // lui t0, 4096
|
||||
// some stuff in between...
|
||||
c->ori(a1, t0, 54272); // ori a1, t0, 54272 = (0x1000D400) SPR TO
|
||||
```
|
||||
and this `0x1000D4000` is the address of the DMA control register for transferring to the scratchpad. The scratchpad here is just used as a faster memory. And eventually the draw code will read the result from the scratchpad.
|
||||
|
||||
They really like this pattern of doing work on the scratchpad while DMA is running in the background, copying things to/from the scratchpad. In this case, they upload the palette to the scratchpad in chunks. As those uploads are running, they do math on the previous upload to blend together the colors for the chosen time of day. To get optimal performance, they often count how many times they finish before the DMA is ready. When this happens, they increment a "wait" variable.
|
||||
|
||||
I modified scratchpad access like this:
|
||||
```cpp
|
||||
c->lui(v1, 28672); // lui v1, 28672 0x7000
|
||||
// stuff in between skipped...
|
||||
//c->ori(v1, v1, 2064); // ori v1, v1, 2064 SPAD mods
|
||||
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 2064, c);
|
||||
```
|
||||
the original code would set the address to an offset of 2064 in the scratchpad.
|
||||
|
||||
The first thing they do is wait for any in-progress DMA transfers to finish:
|
||||
```cpp
|
||||
block_1:
|
||||
c->lw(t5, 0, a1); // lw t5, 0(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t5, t5, 256); // andi t5, t5, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t5) != 0; // bne t5, r0, L62
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
```
|
||||
which is reading and checking the DMA register in a loop. We can just get rid of this - we make all DMA instant.
|
||||
|
||||
|
||||
I also modified the code that starts the transfer to just do a memcpy from the fake scratchpad. See the EE manual for details on what these registers mean. The `a1` register points to the control register for SPR TO DMA.
|
||||
```cpp
|
||||
{
|
||||
// c->sw(t4, 16, a1); // sw t4, 16(a1)
|
||||
u32 madr = c->sgpr64(t4);
|
||||
c->daddiu(t3, t3, -32); // daddiu t3, t3, -32
|
||||
// c->sw(v1, 128, a1); // sw v1, 128(a1)
|
||||
u32 sadr = c->sgpr64(v1);
|
||||
c->addiu(t5, r0, 64); // addiu t5, r0, 64
|
||||
//c->sw(t5, 32, a1); // sw t5, 32(a1)
|
||||
u32 qwc = c->sgpr64(t5);
|
||||
c->addiu(t5, r0, 256); // addiu t5, r0, 256
|
||||
// c->sw(t5, 0, a1); // sw t5, 0(a1)
|
||||
spad_to_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
c->daddiu(t4, t4, 1024); // daddiu t4, t4, 1024
|
||||
}
|
||||
```
|
||||
This data is double buffered. One buffer is being filled from DMA while another is being processed. To swap buffers, they often use `xor` to toggle a bit. But this trick only works if our buffer has the same alignment as theirs up to the bit being toggled (otherwise their first `xor` might toggle a 0 to a 1, advancing the address, where ours does the opposite).
|
||||
```
|
||||
c->xori(v1, v1, 1024); // xori v1, v1, 1024
|
||||
```
|
||||
|
||||
The actual processing is an annoying pipelined loop. The palette stores groups of 8 colors. The time of day system computes 8 weights, passed to this function. Each of the 8 colors is multiplied by the weight and added. This process is repeated for each group. There are usually 1024 or 2048 groups. The tfragments are lit by indexing into these groups. One important detail is that the r/g/b/a values are saturated so they don't overflow.
|
||||
|
||||
This part works using the MIPS2C function in the first tfrag renderers. In the third one, it was annoying to get this data to the C++ renderer, so I just recomputed it in C++. This also lets us manually override the time of day values for fun. The code is much simpler:
|
||||
```cpp
|
||||
void Tfrag3::interp_time_of_day_slow(const float weights[8],
|
||||
const std::vector<tfrag3::TimeOfDayColor>& in,
|
||||
math::Vector<u8, 4>* out) {
|
||||
for (size_t color = 0; color < in.size(); color++) {
|
||||
math::Vector4f result = math::Vector4f::zero();
|
||||
for (int component = 0; component < 8; component++) {
|
||||
result += in[color].rgba[component].cast<float>() * weights[component];
|
||||
}
|
||||
result[0] = std::min(result[0], 255.f);
|
||||
result[1] = std::min(result[1], 255.f);
|
||||
result[2] = std::min(result[2], 255.f);
|
||||
result[3] = std::min(result[3], 128.f); // note: different for alpha!
|
||||
out[color] = result.cast<u8>();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### The Call to Draw
|
||||
There was another scratchpad use to patch up here. They often treat the scratchpad as a `terrain-context`. There are quite a few overlays here so sometimes you have to do some manual searching to figure it out.
|
||||
```lisp
|
||||
(set! (-> (scratchpad-object terrain-context) bsp lev-index) (-> s1-0 index))
|
||||
|
||||
(set! (-> *tfrag-work* min-dist z) 4095996000.0)
|
||||
;; draw!
|
||||
(draw-drawable-tree-tfrag s2-0 s1-0)
|
||||
)
|
||||
;; remember closest.
|
||||
(set! (-> *level* level (-> (scratchpad-object terrain-context) bsp lev-index) closest-object 0)
|
||||
(-> *tfrag-work* min-dist z)
|
||||
)
|
||||
)
|
||||
```
|
||||
the remembering closest is used for figuring out which mip levels of texture need uploading.
|
||||
|
||||
|
||||
### Draw node culling
|
||||
This is a part that I left out. I still haven't done it. But I suspect it looks at the position of the camera (stored in `vf` regs from earlier) and modifies the visibility data. I think it uses a "sphere in view frustum" check and traverses the tree of `draw-node`s. I think it only culls the `draw-node`s and not actually the `tfragment`s, and it modifies the visibility data in place. It only culls the range of nodes that correspond to the tree we're drawing.
|
||||
|
||||
Later, on tfrag3, I did the culling in C++. (More on this later - it's done in a tricky way so that you can efficiently build a list of only the visible things to send to the GPU).
|
||||
|
||||
|
||||
### DMA List Generation
|
||||
The objective of the draw function is to generate a DMA list. This gets added to the entire DMA list for the frame and gets sent to the VIF. The DMA data is a list of instructions like:
|
||||
- upload this data to the VU memory
|
||||
- run this VU program
|
||||
- change various settings related to the VU data upload.
|
||||
|
||||
The pattern used by tfrag is:
|
||||
- Call `tfrag-init-buffer` once. This is unoptimized code that just sets things up.
|
||||
- Call `draw-inline-array-tfrag`. This adds DMA per tfragment. It is super optimized.
|
||||
- Call `tfrag-end-buffer`. This is unoptimized code that ends the DMA list for tfrag
|
||||
@@ -0,0 +1,112 @@
|
||||
xtop vi02 | nop
|
||||
nop | nop
|
||||
ilwr.x vi04, vi02 | nop
|
||||
iaddi vi02, vi02, 0x1 | nop
|
||||
iaddiu vi03, vi02, 0x90 | nop
|
||||
L1:
|
||||
ilw.y vi08, 1(vi02) | nop
|
||||
lq.xyzw vf25, 900(vi00) | nop
|
||||
lq.xyzw vf26, 901(vi00) | nop
|
||||
lq.xyzw vf27, 902(vi00) | nop
|
||||
lq.xyzw vf28, 903(vi00) | nop
|
||||
lq.xyzw vf30, 904(vi00) | nop
|
||||
lqi.xyzw vf01, vi02 | nop
|
||||
lqi.xyzw vf05, vi02 | nop
|
||||
lqi.xyzw vf11, vi02 | nop
|
||||
lq.xyzw vf12, 1020(vi00) | mulaw.xyzw ACC, vf28, vf00
|
||||
nop | maddax.xyzw ACC, vf25, vf01
|
||||
nop | madday.xyzw ACC, vf26, vf01
|
||||
nop | maddz.xyzw vf02, vf27, vf01
|
||||
move.w vf05, vf00 | addw.z vf01, vf00, vf05
|
||||
nop | nop
|
||||
div Q, vf31.x, vf02.w | muly.z vf05, vf05, vf31
|
||||
nop | mul.xyzw vf03, vf02, vf29
|
||||
nop | nop
|
||||
nop | nop
|
||||
nop | mulz.z vf04, vf05, vf05
|
||||
lq.xyzw vf14, 1001(vi00) | clipw.xyz vf03, vf03
|
||||
iaddi vi06, vi00, 0x1 | adda.xyzw ACC, vf11, vf11
|
||||
L2:
|
||||
ior vi05, vi15, vi00 | mul.zw vf01, vf01, Q
|
||||
lq.xyzw vf06, 998(vi00) | mulz.xyzw vf15, vf05, vf04
|
||||
lq.xyzw vf14, 1002(vi00) | mula.xyzw ACC, vf05, vf14
|
||||
fmand vi01, vi06 | mul.xyz vf02, vf02, Q
|
||||
ibne vi00, vi01, L5 | addz.x vf01, vf00, vf01
|
||||
lqi.xyzw vf07, vi03 | mulz.xyzw vf16, vf15, vf04
|
||||
lq.xyzw vf14, 1003(vi00) | madda.xyzw ACC, vf15, vf14
|
||||
lqi.xyzw vf08, vi03 | add.xyzw vf10, vf02, vf30
|
||||
lqi.xyzw vf09, vi03 | mulw.x vf01, vf01, vf01
|
||||
sqi.xyzw vf06, vi05 | mulz.xyzw vf15, vf16, vf04
|
||||
lq.xyzw vf14, 1004(vi00) | madda.xyzw ACC, vf16, vf14
|
||||
sqi.xyzw vf07, vi05 | maxx.w vf10, vf10, vf12
|
||||
sqi.xyzw vf08, vi05 | maxz.zw vf01, vf01, vf31
|
||||
sqi.xyzw vf09, vi05 | mulz.xyzw vf16, vf15, vf04
|
||||
lq.xyzw vf14, 1005(vi00) | madda.xyzw ACC, vf15, vf14
|
||||
lqi.xyzw vf06, vi03 | mulw.x vf01, vf01, vf31
|
||||
lqi.xyzw vf07, vi03 | miniy.w vf10, vf10, vf12
|
||||
lq.xyzw vf08, 999(vi08) | miniz.zw vf01, vf01, vf12
|
||||
ilw.x vi07, -2(vi02) | madd.xyzw vf05, vf16, vf14
|
||||
lqi.xyzw vf23, vi02 | miniw.x vf01, vf01, vf00
|
||||
nop | suby.w vf02, vf10, vf12
|
||||
lqi.xyzw vf24, vi02 | mulx.w vf11, vf11, vf01
|
||||
fcand vi01, 0x3f | mulaw.xyzw ACC, vf28, vf00
|
||||
lq.xyzw vf17, 1006(vi00) | maddax.xyzw ACC, vf25, vf23
|
||||
fmand vi09, vi06 | nop
|
||||
ibne vi00, vi09, L6 | nop
|
||||
lq.xyzw vf18, 1007(vi00) | madday.xyzw ACC, vf26, vf23
|
||||
L3:
|
||||
lq.xyzw vf19, 980(vi07) | ftoi0.xyzw vf11, vf11
|
||||
lq.xyzw vf20, 981(vi07) | maddz.xyzw vf02, vf27, vf23
|
||||
lq.xyzw vf21, 982(vi07) | mulaw.xyzw ACC, vf17, vf05
|
||||
lq.xyzw vf22, 983(vi07) | msubz.xyzw vf12, vf18, vf05
|
||||
sq.xyzw vf11, 3(vi05) | mulaz.xyzw ACC, vf17, vf05
|
||||
lqi.xyzw vf11, vi02 | maddw.xyzw vf13, vf18, vf05
|
||||
move.w vf24, vf00 | addw.z vf23, vf00, vf24
|
||||
div Q, vf31.x, vf02.w | mulw.xyzw vf12, vf12, vf01
|
||||
ibne vi00, vi01, L4 | muly.z vf24, vf24, vf31
|
||||
ilw.y vi08, -2(vi02) | mulz.xyzw vf13, vf13, vf01
|
||||
sqi.xyzw vf06, vi05 | mul.xyzw vf03, vf02, vf29
|
||||
sqi.xyzw vf07, vi05 | mulaw.xyzw ACC, vf10, vf00
|
||||
sqi.xyzw vf08, vi05 | maddax.xyzw ACC, vf12, vf19
|
||||
lq.xyzw vf06, 988(vi00) | maddy.xyzw vf19, vf13, vf19
|
||||
lq.xyzw vf07, 989(vi00) | mulaw.xyzw ACC, vf10, vf00
|
||||
lq.xyzw vf08, 990(vi00) | maddax.xyzw ACC, vf12, vf20
|
||||
lq.xyzw vf09, 991(vi00) | maddy.xyzw vf20, vf13, vf20
|
||||
sq.xyzw vf06, 1(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
sq.xyzw vf07, 3(vi05) | maddax.xyzw ACC, vf12, vf21
|
||||
sq.xyzw vf08, 5(vi05) | maddy.xyzw vf21, vf13, vf21
|
||||
sq.xyzw vf09, 7(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
nop | maddax.xyzw ACC, vf12, vf22
|
||||
nop | maddy.xyzw vf22, vf13, vf22
|
||||
lq.xyzw vf12, 1020(vi00) | ftoi4.xyzw vf19, vf19
|
||||
lq.xyzw vf14, 1001(vi00) | ftoi4.xyzw vf20, vf20
|
||||
move.xyzw vf05, vf24 | ftoi4.xyzw vf21, vf21
|
||||
move.xyzw vf01, vf23 | ftoi4.xyzw vf22, vf22
|
||||
sq.xyzw vf19, 2(vi05) | mulz.z vf04, vf24, vf24
|
||||
sq.xyzw vf20, 4(vi05) | clipw.xyz vf03, vf03
|
||||
sq.xyzw vf21, 6(vi05) | nop
|
||||
sq.xyzw vf22, 8(vi05) | nop
|
||||
xgkick vi15 | nop
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddiu vi01, vi00, 0x672 | nop
|
||||
ibne vi00, vi04, L2 | nop
|
||||
isub vi15, vi01, vi15 | adda.xyzw ACC, vf11, vf11
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
L4:
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddi vi02, vi02, -0x3 | nop
|
||||
ibne vi00, vi04, L1 | nop
|
||||
nop | nop
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
L5:
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddi vi03, vi03, 0x4 | nop
|
||||
ibne vi00, vi04, L1 | nop
|
||||
nop | nop
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
L6:
|
||||
b L3 | nop
|
||||
lq.xyzw vf08, 1000(vi00) | nop
|
||||
@@ -0,0 +1,105 @@
|
||||
xtop vi02 | nop
|
||||
nop | nop
|
||||
ilwr.x vi04, vi02 | nop
|
||||
iaddi vi02, vi02, 0x1 | nop
|
||||
iaddiu vi03, vi02, 0x90 | nop
|
||||
L7:
|
||||
ilw.y vi08, 1(vi02) | nop
|
||||
lq.xyzw vf25, 900(vi00) | nop
|
||||
lq.xyzw vf26, 901(vi00) | nop
|
||||
lq.xyzw vf27, 902(vi00) | nop
|
||||
lq.xyzw vf28, 903(vi00) | nop
|
||||
lq.xyzw vf30, 904(vi08) | nop
|
||||
lqi.xyzw vf01, vi02 | nop
|
||||
lqi.xyzw vf05, vi02 | nop
|
||||
lqi.xyzw vf11, vi02 | nop
|
||||
lq.xyzw vf12, 1020(vi00) | mulaw.xyzw ACC, vf28, vf00
|
||||
ilw.y vi08, 1(vi02) | maddax.xyzw ACC, vf25, vf01
|
||||
nop | madday.xyzw ACC, vf26, vf01
|
||||
nop | maddz.xyzw vf02, vf27, vf01
|
||||
move.w vf05, vf00 | addw.z vf01, vf00, vf05
|
||||
nop | nop
|
||||
div Q, vf31.x, vf02.w | muly.z vf05, vf05, vf31
|
||||
nop | mul.xyzw vf03, vf02, vf29
|
||||
nop | nop
|
||||
nop | nop
|
||||
nop | mulz.z vf04, vf05, vf05
|
||||
lq.xyzw vf14, 1001(vi00) | clipw.xyz vf03, vf03
|
||||
iaddi vi06, vi00, 0x1 | adda.xyzw ACC, vf11, vf11
|
||||
L8:
|
||||
ior vi05, vi15, vi00 | mul.zw vf01, vf01, Q
|
||||
lq.xyzw vf06, 998(vi00) | mulz.xyzw vf15, vf05, vf04
|
||||
lq.xyzw vf14, 1002(vi00) | mula.xyzw ACC, vf05, vf14
|
||||
fmand vi01, vi06 | mul.xyz vf02, vf02, Q
|
||||
ibne vi00, vi01, L10 | addz.x vf01, vf00, vf01
|
||||
lqi.xyzw vf07, vi03 | mulz.xyzw vf16, vf15, vf04
|
||||
lq.xyzw vf14, 1003(vi00) | madda.xyzw ACC, vf15, vf14
|
||||
lqi.xyzw vf08, vi03 | add.xyzw vf10, vf02, vf30
|
||||
lqi.xyzw vf09, vi03 | mulw.x vf01, vf01, vf01
|
||||
sqi.xyzw vf06, vi05 | mulz.xyzw vf15, vf16, vf04
|
||||
lq.xyzw vf14, 1004(vi00) | madda.xyzw ACC, vf16, vf14
|
||||
sqi.xyzw vf07, vi05 | maxx.w vf10, vf10, vf12
|
||||
sqi.xyzw vf08, vi05 | maxz.zw vf01, vf01, vf31
|
||||
sqi.xyzw vf09, vi05 | mulz.xyzw vf16, vf15, vf04
|
||||
lq.xyzw vf14, 1005(vi00) | madda.xyzw ACC, vf15, vf14
|
||||
lqi.xyzw vf06, vi03 | mulw.x vf01, vf01, vf31
|
||||
lqi.xyzw vf07, vi03 | miniy.w vf10, vf10, vf12
|
||||
lq.xyzw vf08, 1000(vi00) | nop
|
||||
ilw.x vi07, -2(vi02) | madd.xyzw vf05, vf16, vf14
|
||||
lq.xyzw vf30, 904(vi08) | nop
|
||||
lqi.xyzw vf23, vi02 | miniw.x vf01, vf01, vf00
|
||||
lqi.xyzw vf24, vi02 | mulx.w vf11, vf11, vf01
|
||||
fcand vi01, 0x3f | mulaw.xyzw ACC, vf28, vf00
|
||||
lq.xyzw vf17, 1006(vi00) | maddax.xyzw ACC, vf25, vf23
|
||||
lq.xyzw vf18, 1007(vi00) | madday.xyzw ACC, vf26, vf23
|
||||
lq.xyzw vf19, 980(vi07) | ftoi0.xyzw vf11, vf11
|
||||
lq.xyzw vf20, 981(vi07) | maddz.xyzw vf02, vf27, vf23
|
||||
lq.xyzw vf21, 982(vi07) | mulaw.xyzw ACC, vf17, vf05
|
||||
lq.xyzw vf22, 983(vi07) | msubz.xyzw vf12, vf18, vf05
|
||||
sq.xyzw vf11, 3(vi05) | mulaz.xyzw ACC, vf17, vf05
|
||||
lqi.xyzw vf11, vi02 | maddw.xyzw vf13, vf18, vf05
|
||||
move.w vf24, vf00 | addw.z vf23, vf00, vf24
|
||||
div Q, vf31.x, vf02.w | mulw.xyzw vf12, vf12, vf01
|
||||
ibne vi00, vi01, L9 | muly.z vf24, vf24, vf31
|
||||
ilw.y vi08, 1(vi02) | mulz.xyzw vf13, vf13, vf01
|
||||
sqi.xyzw vf06, vi05 | mul.xyzw vf03, vf02, vf29
|
||||
sqi.xyzw vf07, vi05 | mulaw.xyzw ACC, vf10, vf00
|
||||
sqi.xyzw vf08, vi05 | maddax.xyzw ACC, vf12, vf19
|
||||
lq.xyzw vf06, 988(vi00) | maddy.xyzw vf19, vf13, vf19
|
||||
lq.xyzw vf07, 989(vi00) | mulaw.xyzw ACC, vf10, vf00
|
||||
lq.xyzw vf08, 990(vi00) | maddax.xyzw ACC, vf12, vf20
|
||||
lq.xyzw vf09, 991(vi00) | maddy.xyzw vf20, vf13, vf20
|
||||
sq.xyzw vf06, 1(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
sq.xyzw vf07, 3(vi05) | maddax.xyzw ACC, vf12, vf21
|
||||
sq.xyzw vf08, 5(vi05) | maddy.xyzw vf21, vf13, vf21
|
||||
sq.xyzw vf09, 7(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
nop | maddax.xyzw ACC, vf12, vf22
|
||||
nop | maddy.xyzw vf22, vf13, vf22
|
||||
lq.xyzw vf12, 1020(vi00) | ftoi4.xyzw vf19, vf19
|
||||
lq.xyzw vf14, 1001(vi00) | ftoi4.xyzw vf20, vf20
|
||||
move.xyzw vf05, vf24 | ftoi4.xyzw vf21, vf21
|
||||
move.xyzw vf01, vf23 | ftoi4.xyzw vf22, vf22
|
||||
sq.xyzw vf19, 2(vi05) | mulz.z vf04, vf24, vf24
|
||||
sq.xyzw vf20, 4(vi05) | clipw.xyz vf03, vf03
|
||||
sq.xyzw vf21, 6(vi05) | nop
|
||||
sq.xyzw vf22, 8(vi05) | nop
|
||||
xgkick vi15 | nop
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddiu vi01, vi00, 0x672 | nop
|
||||
ibne vi00, vi04, L8 | nop
|
||||
isub vi15, vi01, vi15 | adda.xyzw ACC, vf11, vf11
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
L9:
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddi vi02, vi02, -0x3 | nop
|
||||
ibne vi00, vi04, L7 | nop
|
||||
nop | nop
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
L10:
|
||||
iaddi vi04, vi04, -0x1 | nop
|
||||
iaddi vi03, vi03, 0x4 | nop
|
||||
ibne vi00, vi04, L7 | nop
|
||||
nop | nop
|
||||
nop | nop :e
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
TIE Format Document
|
||||
--------------------
|
||||
|
||||
|
||||
TIE Instances
|
||||
----------------
|
||||
|
||||
The instances are arranged into a BVH like with tfrag.
|
||||
The visibility bit strings work exactly the same way too.
|
||||
|
||||
The "origin" matrix stores 16-bits per entry.
|
||||
The final row is set with (x << 16) >> 10 and vitof0
|
||||
The other rows are set with (x << 16) >> 16 and vitof12
|
||||
row0's w is set to 0 manually.
|
||||
|
||||
|
||||
There are 64 winds. The wind index of an instance is (wind-index + wind-time) & 0b111111. The wind time is stored in *wind-work*.
|
||||
This indexes into the wind-vectors in the proxy-prototype-array-tie of the drawable-tree-instance-tie.
|
||||
(and also the wind-vectors of *wind-work*, but this isn't known yet)
|
||||
|
||||
|
||||
The flags mean:
|
||||
0b01 : Do not generate instance DMA, in all conditions. Likely rare because it's checked pretty late.
|
||||
0b10 : Use the GENERIC renderer.
|
||||
|
||||
DMA in work:
|
||||
work.upload-color-0.addr = output_ptr
|
||||
work.generic-color-0.addr = output_ptr
|
||||
|
||||
|
||||
calculation of clipped w:
|
||||
multiply bsphere by camera matrix
|
||||
add hvdf_offset.w to w
|
||||
clamp to within (hmge-d.x hmdge-d.y)
|
||||
|
||||
calculation of total camera matrix:
|
||||
vf10+ is origin, vf20+ is the SHRUB MATRIX!!!
|
||||
|
||||
vmulax.xyzw acc, vf20, vf10
|
||||
vmadday.xyzw acc, vf21, vf10
|
||||
vmaddz.xyzw vf10, vf22, vf10
|
||||
vmulax.xyzw acc, vf20, vf11
|
||||
vmadday.xyzw acc, vf21, vf11
|
||||
vmaddz.xyzw vf11, vf22, vf11
|
||||
vmulax.xyzw acc, vf20, vf12
|
||||
vmadday.xyzw acc, vf21, vf12
|
||||
vmaddz.xyzw vf12, vf22, vf12
|
||||
vmulax.xyzw acc, vf20, vf13
|
||||
vmadday.xyzw acc, vf21, vf13
|
||||
vmaddaz.xyzw acc, vf22, vf13
|
||||
vmaddw.xyzw vf13, vf23, vf0
|
||||
|
||||
Out data (6 qw = 96 bytes):
|
||||
0-64 : matrix.
|
||||
64 : morph constants
|
||||
80 : [flags & 2, clipping/dists, 0, clipped_w]
|
||||
|
||||
Next are 3x "color" tags.
|
||||
The final one will link to the "next" instance in the proto bucket
|
||||
For the final instance in the bucket, it will be a ret.
|
||||
|
||||
96: color0
|
||||
|
||||
+3
-2
@@ -19,7 +19,7 @@ if(UNIX)
|
||||
-Woverloaded-virtual \
|
||||
-Wredundant-decls \
|
||||
-Wshadow \
|
||||
-Wsign-promo")
|
||||
-Wsign-promo -O3 -march=haswell")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "/EHsc")
|
||||
endif(UNIX)
|
||||
@@ -99,8 +99,10 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/tfrag/BufferedRenderer.cpp
|
||||
graphics/opengl_renderer/tfrag/program6_cpu.cpp
|
||||
graphics/opengl_renderer/tfrag/Tfrag3.cpp
|
||||
graphics/opengl_renderer/tfrag/tfrag_common.cpp
|
||||
graphics/opengl_renderer/tfrag/tfrag_unpack.cpp
|
||||
graphics/opengl_renderer/tfrag/TFragment.cpp
|
||||
graphics/opengl_renderer/tfrag/Tie3.cpp
|
||||
graphics/texture/TextureConverter.cpp
|
||||
graphics/texture/TexturePool.cpp
|
||||
graphics/pipelines/opengl.cpp
|
||||
@@ -121,4 +123,3 @@ endif()
|
||||
add_executable(gk main.cpp)
|
||||
target_link_libraries(gk runtime)
|
||||
|
||||
install(TARGETS gk)
|
||||
|
||||
@@ -17,8 +17,10 @@ enum class BucketId {
|
||||
SKY_DRAW = 3,
|
||||
TFRAG_TEX_LEVEL0 = 5,
|
||||
TFRAG_LEVEL0 = 6,
|
||||
TIE_LEVEL0 = 9,
|
||||
TFRAG_TEX_LEVEL1 = 12,
|
||||
TFRAG_LEVEL1 = 13,
|
||||
TIE_LEVEL1 = 16,
|
||||
SHRUB_TEX_LEVEL0 = 19,
|
||||
SHRUB_TEX_LEVEL1 = 25,
|
||||
ALPHA_TEX_LEVEL0 = 31,
|
||||
|
||||
@@ -26,7 +26,8 @@ tfrag3::Level* Loader::get_tfrag3_level(const std::string& level_name) {
|
||||
Serializer ser(data.data(), data.size());
|
||||
result.serialize(ser);
|
||||
double import_time = import_timer.getSeconds();
|
||||
fmt::print("Load from file: {:.3f}s, import {:.3f}s\n", disk_load_time, import_time);
|
||||
fmt::print("------------> Load from file: {:.3f}s, import {:.3f}s\n", disk_load_time,
|
||||
import_time);
|
||||
return &result;
|
||||
} else {
|
||||
return &existing->second;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "game/graphics/opengl_renderer/SkyRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/TFragment.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/Tie3.h"
|
||||
|
||||
// for the vif callback
|
||||
#include "game/kernel/kmachine.h"
|
||||
@@ -73,8 +74,10 @@ void OpenGLRenderer::init_bucket_renderers() {
|
||||
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-0", BucketId::TFRAG_TEX_LEVEL0);
|
||||
init_bucket_renderer<TFragment>("tfrag-0", BucketId::TFRAG_LEVEL0, normal_tfrags, false);
|
||||
init_bucket_renderer<Tie3>("tie-0", BucketId::TIE_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-1", BucketId::TFRAG_TEX_LEVEL1);
|
||||
init_bucket_renderer<TFragment>("tfrag-1", BucketId::TFRAG_LEVEL1, normal_tfrags, false);
|
||||
init_bucket_renderer<Tie3>("tie-1", BucketId::TIE_LEVEL1);
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-0", BucketId::SHRUB_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-1", BucketId::SHRUB_TEX_LEVEL1);
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-0", BucketId::ALPHA_TEX_LEVEL0);
|
||||
|
||||
@@ -14,7 +14,7 @@ void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord.xy / tex_coord.z);
|
||||
color = fragment_color * T0 * 2.0;
|
||||
|
||||
if (color.a <= alpha_min) {
|
||||
if (color.a < alpha_min) {
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@ void TFragment::render(DmaFollower& dma,
|
||||
}
|
||||
|
||||
assert(!level_name.empty());
|
||||
m_tfrag3.setup_for_level(level_name, render_state);
|
||||
Tfrag3::RenderSettings settings;
|
||||
m_tfrag3.setup_for_level(m_tree_kinds, level_name, render_state);
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
|
||||
settings.fog_x = m_tfrag_data.fog.x();
|
||||
memcpy(settings.math_camera.data(), &m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16],
|
||||
@@ -178,10 +178,22 @@ void TFragment::render(DmaFollower& dma,
|
||||
}
|
||||
|
||||
if (m_hack_test_many_levels) {
|
||||
std::vector<tfrag3::TFragmentTreeKind> all_kinds = {
|
||||
tfrag3::TFragmentTreeKind::NORMAL, tfrag3::TFragmentTreeKind::TRANS,
|
||||
tfrag3::TFragmentTreeKind::DIRT, tfrag3::TFragmentTreeKind::ICE,
|
||||
tfrag3::TFragmentTreeKind::LOWRES, tfrag3::TFragmentTreeKind::LOWRES_TRANS};
|
||||
for (int i = 0; i < HackManyLevels::NUM_LEVELS; i++) {
|
||||
if (m_many_level_render.level_enables[i]) {
|
||||
m_many_level_render.level_renderers[i].setup_for_level(level_names[i], render_state);
|
||||
Tfrag3::RenderSettings settings;
|
||||
if (!m_many_level_render.tfrag_level_renderers[i]) {
|
||||
m_many_level_render.tfrag_level_renderers[i] = std::make_unique<Tfrag3>();
|
||||
}
|
||||
if (!m_many_level_render.tie_level_renderers[i]) {
|
||||
m_many_level_render.tie_level_renderers[i] = std::make_unique<Tie3>("tie", m_my_id);
|
||||
}
|
||||
m_many_level_render.tfrag_level_renderers[i]->setup_for_level(all_kinds, level_names[i],
|
||||
render_state);
|
||||
m_many_level_render.tie_level_renderers[i]->setup_for_level(level_names[i], render_state);
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
|
||||
settings.fog_x = m_tfrag_data.fog.x();
|
||||
memcpy(settings.math_camera.data(),
|
||||
@@ -193,12 +205,15 @@ void TFragment::render(DmaFollower& dma,
|
||||
|
||||
auto t3prof = prof.make_scoped_child(level_names[i]);
|
||||
|
||||
m_many_level_render.level_renderers[i].debug_render_all_trees_nolores(settings,
|
||||
render_state, t3prof);
|
||||
m_many_level_render.tfrag_level_renderers[i]->debug_render_all_trees_nolores(
|
||||
settings, render_state, t3prof);
|
||||
m_many_level_render.tie_level_renderers[i]->render_all_trees(settings, render_state,
|
||||
t3prof);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TFragment::draw_debug_window() {
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Extra Debug", &m_extra_debug);
|
||||
@@ -307,8 +322,8 @@ void TFragment::handle_initialization(DmaFollower& dma,
|
||||
m_globals.vf04_ambient = m_tfrag_data.ambient; // TODO get rid?
|
||||
|
||||
auto pc_port_data = dma.read_and_advance();
|
||||
assert(pc_port_data.size_bytes == sizeof(PcPortData));
|
||||
memcpy(&m_pc_port_data, pc_port_data.data, sizeof(PcPortData));
|
||||
assert(pc_port_data.size_bytes == sizeof(TfragPcPortData));
|
||||
memcpy(&m_pc_port_data, pc_port_data.data, sizeof(TfragPcPortData));
|
||||
m_pc_port_data.level_name[11] = '\0';
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
@@ -212,12 +212,7 @@ class TFragment : public BucketRenderer {
|
||||
TFragData m_tfrag_data;
|
||||
TFragKickZone m_kick_data;
|
||||
|
||||
struct PcPortData {
|
||||
Vector4f planes[4];
|
||||
math::Vector<s32, 4> itimes[4];
|
||||
char level_name[12];
|
||||
u32 tree_idx;
|
||||
} m_pc_port_data;
|
||||
TfragPcPortData m_pc_port_data;
|
||||
|
||||
// buffers
|
||||
TFragBufferedData m_buffered_data[2];
|
||||
@@ -301,7 +296,8 @@ class TFragment : public BucketRenderer {
|
||||
|
||||
struct HackManyLevels {
|
||||
static constexpr int NUM_LEVELS = 23;
|
||||
Tfrag3 level_renderers[NUM_LEVELS];
|
||||
std::unique_ptr<Tfrag3> tfrag_level_renderers[NUM_LEVELS];
|
||||
std::unique_ptr<Tie3> tie_level_renderers[NUM_LEVELS];
|
||||
bool level_enables[NUM_LEVELS] = {0};
|
||||
} m_many_level_render;
|
||||
};
|
||||
|
||||
@@ -34,43 +34,49 @@ Tfrag3::~Tfrag3() {
|
||||
glDeleteVertexArrays(1, &m_debug_vao);
|
||||
}
|
||||
|
||||
void Tfrag3::setup_for_level(const std::string& level, SharedRenderState* render_state) {
|
||||
void Tfrag3::setup_for_level(const std::vector<tfrag3::TFragmentTreeKind>& tree_kinds,
|
||||
const std::string& level,
|
||||
SharedRenderState* render_state) {
|
||||
// make sure we have the level data.
|
||||
auto lev_data = render_state->loader.get_tfrag3_level(level);
|
||||
if (m_level_name != level) {
|
||||
Timer tfrag3_setup_timer;
|
||||
fmt::print("new level for tfrag3: {} -> {}\n", m_level_name, level);
|
||||
fmt::print("discarding old stuff\n");
|
||||
discard_tree_cache();
|
||||
fmt::print("level has {} trees\n", lev_data->trees.size());
|
||||
m_cached_trees.resize(lev_data->trees.size());
|
||||
fmt::print("level has {} trees\n", lev_data->tfrag_trees.size());
|
||||
m_cached_trees.clear();
|
||||
|
||||
size_t idx_buffer_len = 0;
|
||||
size_t time_of_day_count = 0;
|
||||
size_t vis_temp_len = 0;
|
||||
size_t max_draw = 0;
|
||||
|
||||
for (size_t tree_idx = 0; tree_idx < lev_data->trees.size(); tree_idx++) {
|
||||
const auto& tree = lev_data->trees[tree_idx];
|
||||
m_cached_trees[tree_idx].kind = tree.kind;
|
||||
if (tree.kind != tfrag3::TFragmentTreeKind::INVALID) {
|
||||
for (size_t tree_idx = 0; tree_idx < lev_data->tfrag_trees.size(); tree_idx++) {
|
||||
const auto& tree = lev_data->tfrag_trees[tree_idx];
|
||||
m_cached_trees.emplace_back();
|
||||
auto& tree_cache = m_cached_trees.back();
|
||||
|
||||
tree_cache.kind = tree.kind;
|
||||
if (std::find(tree_kinds.begin(), tree_kinds.end(), tree.kind) != tree_kinds.end()) {
|
||||
max_draw = std::max(tree.draws.size(), max_draw);
|
||||
for (auto& draw : tree.draws) {
|
||||
idx_buffer_len = std::max(idx_buffer_len, draw.vertex_index_stream.size());
|
||||
idx_buffer_len += draw.vertex_index_stream.size();
|
||||
}
|
||||
time_of_day_count = std::max(tree.colors.size(), time_of_day_count);
|
||||
u32 verts = tree.vertices.size();
|
||||
fmt::print(" tree {} has {} verts ({} kB) and {} draws\n", tree_idx, verts,
|
||||
verts * sizeof(tfrag3::PreloadedVertex) / 1024.f, tree.draws.size());
|
||||
glGenVertexArrays(1, &m_cached_trees[tree_idx].vao);
|
||||
glBindVertexArray(m_cached_trees[tree_idx].vao);
|
||||
glGenBuffers(1, &m_cached_trees[tree_idx].vertex_buffer);
|
||||
m_cached_trees[tree_idx].vert_count = verts;
|
||||
m_cached_trees[tree_idx].draws = &tree.draws; // todo - should we just copy this?
|
||||
m_cached_trees[tree_idx].colors = &tree.colors;
|
||||
m_cached_trees[tree_idx].vis = &tree.vis_nodes;
|
||||
// don't bother with vis if we only have children.
|
||||
m_cached_trees[tree_idx].num_vis_tree_roots = tree.only_children ? 0 : tree.num_roots;
|
||||
m_cached_trees[tree_idx].vis_tree_root = tree.first_root;
|
||||
m_cached_trees[tree_idx].vis_temp.resize(tree.vis_nodes.size());
|
||||
m_cached_trees[tree_idx].culled_indices.resize(idx_buffer_len);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_cached_trees[tree_idx].vertex_buffer);
|
||||
glGenVertexArrays(1, &tree_cache.vao);
|
||||
glBindVertexArray(tree_cache.vao);
|
||||
glGenBuffers(1, &tree_cache.vertex_buffer);
|
||||
tree_cache.vert_count = verts;
|
||||
tree_cache.draws = &tree.draws; // todo - should we just copy this?
|
||||
tree_cache.colors = &tree.colors;
|
||||
tree_cache.vis = &tree.bvh;
|
||||
tree_cache.tod_cache = swizzle_time_of_day(tree.colors);
|
||||
vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tree_cache.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, verts * sizeof(tfrag3::PreloadedVertex), nullptr,
|
||||
GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
@@ -107,6 +113,11 @@ void Tfrag3::setup_for_level(const std::string& level, SharedRenderState* render
|
||||
}
|
||||
}
|
||||
|
||||
fmt::print("TFRAG temporary vis output size: {}\n", vis_temp_len);
|
||||
m_cache.vis_temp.resize(vis_temp_len);
|
||||
fmt::print("TFRAG max draws/tree: {}\n", max_draw);
|
||||
m_cache.draw_idx_temp.resize(max_draw);
|
||||
|
||||
fmt::print("level has {} textures\n", lev_data->textures.size());
|
||||
for (auto& tex : lev_data->textures) {
|
||||
GLuint gl_tex;
|
||||
@@ -127,6 +138,7 @@ void Tfrag3::setup_for_level(const std::string& level, SharedRenderState* render
|
||||
}
|
||||
|
||||
fmt::print("level max index stream: {}\n", idx_buffer_len);
|
||||
m_cache.index_list.resize(idx_buffer_len);
|
||||
m_has_index_buffer = true;
|
||||
glGenBuffers(1, &m_index_buffer);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
@@ -149,155 +161,30 @@ void Tfrag3::setup_for_level(const std::string& level, SharedRenderState* render
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
m_level_name = level;
|
||||
fmt::print("TFRAG3 setup: {:.3f}\n", tfrag3_setup_timer.getSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
void Tfrag3::first_draw_setup(const RenderSettings& settings, SharedRenderState* render_state) {
|
||||
render_state->shaders[ShaderId::TFRAG3].activate();
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "tex_T0"), 0);
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "tex_T1"), 1);
|
||||
glUniformMatrix4fv(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "camera"),
|
||||
1, GL_FALSE, settings.math_camera.data());
|
||||
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "hvdf_offset"),
|
||||
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
|
||||
settings.hvdf_offset[3]);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
}
|
||||
|
||||
Tfrag3::DoubleDraw Tfrag3::setup_shader(const RenderSettings& /*settings*/,
|
||||
SharedRenderState* render_state,
|
||||
DrawMode mode) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
if (mode.get_zt_enable()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
switch (mode.get_depth_test()) {
|
||||
case GsTest::ZTest::NEVER:
|
||||
glDepthFunc(GL_NEVER);
|
||||
break;
|
||||
case GsTest::ZTest::ALWAYS:
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
break;
|
||||
case GsTest::ZTest::GEQUAL:
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
break;
|
||||
case GsTest::ZTest::GREATER:
|
||||
glDepthFunc(GL_GREATER);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (mode.get_ab_enable() && mode.get_alpha_blend() != DrawMode::AlphaBlend::DISABLED) {
|
||||
glEnable(GL_BLEND);
|
||||
switch (mode.get_alpha_blend()) {
|
||||
case DrawMode::AlphaBlend::SRC_DST_SRC_DST:
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case DrawMode::AlphaBlend::SRC_0_SRC_DST:
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
break;
|
||||
case DrawMode::AlphaBlend::SRC_0_FIX_DST:
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (mode.get_clamp_s_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (mode.get_clamp_t_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (mode.get_filt_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
// for some reason, they set atest NEVER + FB_ONLY to disable depth writes
|
||||
bool alpha_hack_to_disable_z_write = false;
|
||||
DoubleDraw double_draw;
|
||||
|
||||
float alpha_min = 0.;
|
||||
if (mode.get_at_enable()) {
|
||||
switch (mode.get_alpha_test()) {
|
||||
case DrawMode::AlphaTest::ALWAYS:
|
||||
break;
|
||||
case DrawMode::AlphaTest::GEQUAL:
|
||||
alpha_min = mode.get_aref() / 127.f;
|
||||
switch (mode.get_alpha_fail()) {
|
||||
case GsTest::AlphaFail::KEEP:
|
||||
// ok, no need for double draw
|
||||
break;
|
||||
case GsTest::AlphaFail::FB_ONLY:
|
||||
// darn, we need to draw twice
|
||||
double_draw.kind = DoubleDrawKind::AFAIL_NO_DEPTH_WRITE;
|
||||
double_draw.aref = alpha_min;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case DrawMode::AlphaTest::NEVER:
|
||||
if (mode.get_alpha_fail() == GsTest::AlphaFail::FB_ONLY) {
|
||||
alpha_hack_to_disable_z_write = true;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode.get_depth_write_enable()) {
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_min"),
|
||||
alpha_min);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
|
||||
10.f);
|
||||
|
||||
return double_draw;
|
||||
}
|
||||
|
||||
void Tfrag3::render_tree(const RenderSettings& settings,
|
||||
void Tfrag3::render_tree(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
bool use_vis) {
|
||||
ScopedProfilerNode& prof) {
|
||||
auto& tree = m_cached_trees.at(settings.tree_idx);
|
||||
assert(tree.kind != tfrag3::TFragmentTreeKind::INVALID);
|
||||
|
||||
if (m_color_result.size() < tree.colors->size()) {
|
||||
m_color_result.resize(tree.colors->size());
|
||||
}
|
||||
interp_time_of_day_slow(settings.time_of_day_weights, *tree.colors, m_color_result.data());
|
||||
if (m_use_fast_time_of_day) {
|
||||
interp_time_of_day_fast(settings.time_of_day_weights, tree.tod_cache, m_color_result.data());
|
||||
} else {
|
||||
interp_time_of_day_slow(settings.time_of_day_weights, *tree.colors, m_color_result.data());
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_1D, m_time_of_day_texture);
|
||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, tree.colors->size(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
m_color_result.data());
|
||||
|
||||
first_draw_setup(settings, render_state);
|
||||
first_tfrag_draw_setup(settings, render_state);
|
||||
|
||||
glBindVertexArray(tree.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tree.vertex_buffer);
|
||||
@@ -306,41 +193,33 @@ void Tfrag3::render_tree(const RenderSettings& settings,
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
|
||||
for (const auto& draw : *tree.draws) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures.at(draw.tree_tex_id));
|
||||
auto double_draw = setup_shader(settings, render_state, draw.mode);
|
||||
tree.tris_this_frame += draw.num_triangles;
|
||||
tree.draws_this_frame++;
|
||||
int draw_size = draw.vertex_index_stream.size();
|
||||
if (use_vis) {
|
||||
int vtx_idx = 0;
|
||||
int out_idx = 0;
|
||||
for (auto& grp : draw.vis_groups) {
|
||||
if (grp.tfrag_idx == 0xffffffff || tree.vis_temp.at(grp.tfrag_idx)) {
|
||||
memcpy(&tree.culled_indices[out_idx], &draw.vertex_index_stream[vtx_idx],
|
||||
grp.num * sizeof(u32));
|
||||
out_idx += grp.num;
|
||||
}
|
||||
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, m_cache.vis_temp.data());
|
||||
|
||||
vtx_idx += grp.num;
|
||||
}
|
||||
int idx_buffer_ptr = make_index_list_from_vis_string(
|
||||
m_cache.draw_idx_temp.data(), m_cache.index_list.data(), *tree.draws, m_cache.vis_temp);
|
||||
|
||||
draw_size = out_idx;
|
||||
if (draw_size == 0) {
|
||||
continue;
|
||||
}
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_ptr * sizeof(u32),
|
||||
m_cache.index_list.data());
|
||||
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(draw.num_triangles * (float)out_idx / draw.vertex_index_stream.size());
|
||||
for (size_t draw_idx = 0; draw_idx < tree.draws->size(); draw_idx++) {
|
||||
const auto& draw = tree.draws->operator[](draw_idx);
|
||||
const auto& indices = m_cache.draw_idx_temp[draw_idx];
|
||||
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, out_idx * sizeof(u32),
|
||||
tree.culled_indices.data());
|
||||
} else {
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, draw.vertex_index_stream.size() * sizeof(u32),
|
||||
draw.vertex_index_stream.data());
|
||||
if (indices.second <= indices.first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures.at(draw.tree_tex_id));
|
||||
auto double_draw = setup_tfrag_shader(settings, render_state, draw.mode);
|
||||
tree.tris_this_frame += draw.num_triangles;
|
||||
tree.draws_this_frame++;
|
||||
int draw_size = indices.second - indices.first;
|
||||
void* offset = (void*)(indices.first * sizeof(u32));
|
||||
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(draw.num_triangles * (float)draw_size / draw.vertex_index_stream.size());
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
|
||||
switch (double_draw.kind) {
|
||||
case DoubleDrawKind::NONE:
|
||||
@@ -353,7 +232,7 @@ void Tfrag3::render_tree(const RenderSettings& settings,
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
|
||||
double_draw.aref);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)0);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@@ -362,63 +241,28 @@ void Tfrag3::render_tree(const RenderSettings& settings,
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
bool sphere_in_view_ref(const math::Vector4f& sphere, const math::Vector4f* planes) {
|
||||
/*
|
||||
*(let ((v1-0 *math-camera*))
|
||||
(.lvf vf6 (&-> arg0 quad))
|
||||
(.lvf vf1 (&-> v1-0 plane 0 quad))
|
||||
(.lvf vf2 (&-> v1-0 plane 1 quad))
|
||||
(.lvf vf3 (&-> v1-0 plane 2 quad))
|
||||
(.lvf vf4 (&-> v1-0 plane 3 quad))
|
||||
)
|
||||
(.mul.x.vf acc vf1 vf6)
|
||||
(.add.mul.y.vf acc vf2 vf6 acc)
|
||||
(.add.mul.z.vf acc vf3 vf6 acc)
|
||||
(.sub.mul.w.vf vf5 vf4 vf0 acc)
|
||||
(.add.w.vf vf5 vf5 vf6)
|
||||
(.mov v1-1 vf5)
|
||||
(.pcgtw v1-2 r0-0 v1-1)
|
||||
(.ppach v1-3 r0-0 v1-2)
|
||||
(zero? (the-as int v1-3))
|
||||
*/
|
||||
|
||||
math::Vector4f acc =
|
||||
planes[0] * sphere.x() + planes[1] * sphere.y() + planes[2] * sphere.z() - planes[3];
|
||||
|
||||
return acc.x() > -sphere.w() && acc.y() > -sphere.w() && acc.z() > -sphere.w() &&
|
||||
acc.w() > -sphere.w();
|
||||
}
|
||||
|
||||
void cull_ref_all(const math::Vector4f* planes,
|
||||
const std::vector<tfrag3::VisNode>& nodes,
|
||||
u8* out) {
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
out[i] = sphere_in_view_ref(nodes[i].bsphere, planes);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Render all trees with settings for the given tree.
|
||||
* This is intended to be used only for debugging when we can't easily get commands for all trees
|
||||
* working.
|
||||
*/
|
||||
void Tfrag3::render_all_trees(const RenderSettings& settings,
|
||||
void Tfrag3::render_all_trees(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
RenderSettings settings_copy = settings;
|
||||
TfragRenderSettings settings_copy = settings;
|
||||
for (size_t i = 0; i < m_cached_trees.size(); i++) {
|
||||
if (m_cached_trees[i].kind != tfrag3::TFragmentTreeKind::INVALID) {
|
||||
settings_copy.tree_idx = i;
|
||||
render_tree(settings_copy, render_state, prof, false);
|
||||
render_tree(settings_copy, render_state, prof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tfrag3::render_matching_trees(const std::vector<tfrag3::TFragmentTreeKind>& trees,
|
||||
const RenderSettings& settings,
|
||||
const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
RenderSettings settings_copy = settings;
|
||||
TfragRenderSettings settings_copy = settings;
|
||||
for (size_t i = 0; i < m_cached_trees.size(); i++) {
|
||||
m_cached_trees[i].reset_stats();
|
||||
if (!m_cached_trees[i].allowed) {
|
||||
@@ -428,8 +272,7 @@ void Tfrag3::render_matching_trees(const std::vector<tfrag3::TFragmentTreeKind>&
|
||||
m_cached_trees[i].forced) {
|
||||
m_cached_trees[i].rendered_this_frame = true;
|
||||
settings_copy.tree_idx = i;
|
||||
cull_ref_all(settings.planes, *m_cached_trees[i].vis, m_cached_trees[i].vis_temp.data());
|
||||
render_tree(settings_copy, render_state, prof, true);
|
||||
render_tree(settings_copy, render_state, prof);
|
||||
if (m_cached_trees[i].cull_debug) {
|
||||
render_tree_cull_debug(settings_copy, render_state, prof);
|
||||
}
|
||||
@@ -437,16 +280,16 @@ void Tfrag3::render_matching_trees(const std::vector<tfrag3::TFragmentTreeKind>&
|
||||
}
|
||||
}
|
||||
|
||||
void Tfrag3::debug_render_all_trees_nolores(const RenderSettings& settings,
|
||||
void Tfrag3::debug_render_all_trees_nolores(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
RenderSettings settings_copy = settings;
|
||||
TfragRenderSettings settings_copy = settings;
|
||||
for (size_t i = 0; i < m_cached_trees.size(); i++) {
|
||||
if (m_cached_trees[i].kind != tfrag3::TFragmentTreeKind::INVALID &&
|
||||
m_cached_trees[i].kind != tfrag3::TFragmentTreeKind::LOWRES_TRANS &&
|
||||
m_cached_trees[i].kind != tfrag3::TFragmentTreeKind::LOWRES) {
|
||||
settings_copy.tree_idx = i;
|
||||
render_tree(settings_copy, render_state, prof, false);
|
||||
render_tree(settings_copy, render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,16 +320,7 @@ void Tfrag3::draw_debug_window() {
|
||||
ImGui::PopID();
|
||||
if (tree.rendered_this_frame) {
|
||||
ImGui::Text(" tris: %d draws: %d", tree.tris_this_frame, tree.draws_this_frame);
|
||||
int vis = 0;
|
||||
for (auto x : tree.vis_temp) {
|
||||
if (x) {
|
||||
vis++;
|
||||
}
|
||||
}
|
||||
ImGui::Text(" cull: %d vis out of %d", vis, (int)tree.vis_temp.size());
|
||||
}
|
||||
ImGui::Text("root: %d, roots: %d, nodes %d", tree.vis_tree_root, tree.num_vis_tree_roots,
|
||||
(int)tree.vis->size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,25 +353,6 @@ void Tfrag3::discard_tree_cache() {
|
||||
m_cached_trees.clear();
|
||||
}
|
||||
|
||||
void Tfrag3::interp_time_of_day_slow(const float weights[8],
|
||||
const std::vector<tfrag3::TimeOfDayColor>& in,
|
||||
math::Vector<u8, 4>* out) {
|
||||
// Timer interp_timer;
|
||||
for (size_t color = 0; color < in.size(); color++) {
|
||||
math::Vector4f result = math::Vector4f::zero();
|
||||
for (int component = 0; component < 8; component++) {
|
||||
result += in[color].rgba[component].cast<float>() * weights[component];
|
||||
}
|
||||
result[0] = std::min(result[0], 255.f);
|
||||
result[1] = std::min(result[1], 255.f);
|
||||
result[2] = std::min(result[2], 255.f);
|
||||
result[3] = std::min(result[3], 128.f); // note: different for alpha!
|
||||
out[color] = result.cast<u8>();
|
||||
}
|
||||
// about 70 us, not bad.
|
||||
// fmt::print("interp {} colors {:.2f} ms\n", in.size(), interp_timer.getMs());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
float frac(float in) {
|
||||
@@ -617,15 +432,15 @@ void debug_vis_draw(int first_root,
|
||||
|
||||
} // namespace
|
||||
|
||||
void Tfrag3::render_tree_cull_debug(const RenderSettings& settings,
|
||||
void Tfrag3::render_tree_cull_debug(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// generate debug verts:
|
||||
m_debug_vert_data.clear();
|
||||
auto& tree = m_cached_trees.at(settings.tree_idx);
|
||||
|
||||
debug_vis_draw(tree.vis_tree_root, tree.vis_tree_root, tree.num_vis_tree_roots, 1, *tree.vis,
|
||||
m_debug_vert_data);
|
||||
debug_vis_draw(tree.vis->first_root, tree.vis->first_root, tree.vis->num_roots, 1,
|
||||
tree.vis->vis_nodes, m_debug_vert_data);
|
||||
|
||||
render_state->shaders[ShaderId::TFRAG3_NO_TEX].activate();
|
||||
glUniformMatrix4fv(
|
||||
|
||||
@@ -4,48 +4,37 @@
|
||||
#include "common/math/Vector.h"
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/tfrag_common.h"
|
||||
#include "game/graphics/opengl_renderer/tfrag/Tie3.h"
|
||||
|
||||
class Tfrag3 {
|
||||
public:
|
||||
struct RenderSettings {
|
||||
math::Matrix4f math_camera;
|
||||
math::Vector4f hvdf_offset;
|
||||
float fog_x;
|
||||
const u8* rgba_data;
|
||||
int tree_idx;
|
||||
float time_of_day_weights[8] = {0};
|
||||
math::Vector4f planes[4];
|
||||
bool do_culling = false;
|
||||
bool debug_culling = false;
|
||||
// todo culling planes
|
||||
// todo occlusion culling string.
|
||||
};
|
||||
|
||||
Tfrag3();
|
||||
~Tfrag3();
|
||||
|
||||
void debug_render_all_trees_nolores(const RenderSettings& settings,
|
||||
void debug_render_all_trees_nolores(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void render_all_trees(const RenderSettings& settings,
|
||||
void render_all_trees(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void render_matching_trees(const std::vector<tfrag3::TFragmentTreeKind>& trees,
|
||||
const RenderSettings& settings,
|
||||
const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void render_tree(const RenderSettings& settings,
|
||||
void render_tree(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
bool use_vis);
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void setup_for_level(const std::string& level, SharedRenderState* render_state);
|
||||
void setup_for_level(const std::vector<tfrag3::TFragmentTreeKind>& tree_kinds,
|
||||
const std::string& level,
|
||||
SharedRenderState* render_state);
|
||||
void discard_tree_cache();
|
||||
|
||||
void render_tree_cull_debug(const RenderSettings& settings,
|
||||
void render_tree_cull_debug(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
@@ -56,34 +45,15 @@ class Tfrag3 {
|
||||
};
|
||||
|
||||
private:
|
||||
void first_draw_setup(const RenderSettings& settings, SharedRenderState* render_state);
|
||||
enum class DoubleDrawKind { NONE, AFAIL_NO_DEPTH_WRITE };
|
||||
struct DoubleDraw {
|
||||
DoubleDrawKind kind = DoubleDrawKind::NONE;
|
||||
float aref = 0.;
|
||||
};
|
||||
|
||||
DoubleDraw setup_shader(const RenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
DrawMode mode);
|
||||
void interp_time_of_day_slow(const float weights[8],
|
||||
const std::vector<tfrag3::TimeOfDayColor>& in,
|
||||
math::Vector<u8, 4>* out);
|
||||
|
||||
struct TreeCache {
|
||||
tfrag3::TFragmentTreeKind kind;
|
||||
GLuint vertex_buffer = -1;
|
||||
GLuint vao;
|
||||
u32 vert_count = 0;
|
||||
const std::vector<tfrag3::Draw>* draws = nullptr;
|
||||
const std::vector<tfrag3::StripDraw>* draws = nullptr;
|
||||
const std::vector<tfrag3::TimeOfDayColor>* colors = nullptr;
|
||||
const std::vector<tfrag3::VisNode>* vis = nullptr;
|
||||
|
||||
std::vector<u8> vis_temp;
|
||||
std::vector<u32> culled_indices;
|
||||
int num_vis_tree_roots = 0;
|
||||
int vis_tree_root = 0;
|
||||
int first_vis_leaf = 0;
|
||||
const tfrag3::BVH* vis = nullptr;
|
||||
SwizzledTimeOfDay tod_cache;
|
||||
|
||||
void reset_stats() {
|
||||
rendered_this_frame = false;
|
||||
@@ -98,6 +68,12 @@ class Tfrag3 {
|
||||
bool cull_debug = false;
|
||||
};
|
||||
|
||||
struct Cache {
|
||||
std::vector<u8> vis_temp;
|
||||
std::vector<std::pair<int, int>> draw_idx_temp;
|
||||
std::vector<u32> index_list;
|
||||
} m_cache;
|
||||
|
||||
std::string m_level_name;
|
||||
|
||||
std::vector<GLuint> m_textures;
|
||||
@@ -115,8 +91,10 @@ class Tfrag3 {
|
||||
|
||||
// in theory could be up to 4096, I think, but we don't see that many...
|
||||
// should be easy to increase (will require a shader change too for indexing)
|
||||
static constexpr int TIME_OF_DAY_COLOR_COUNT = 2048;
|
||||
static constexpr int TIME_OF_DAY_COLOR_COUNT = 8192;
|
||||
|
||||
static constexpr int DEBUG_TRI_COUNT = 4096;
|
||||
std::vector<DebugVertex> m_debug_vert_data;
|
||||
|
||||
bool m_use_fast_time_of_day = true;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
#include "Tie3.h"
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
Tie3::Tie3(const std::string& name, BucketId my_id) : BucketRenderer(name, my_id) {}
|
||||
|
||||
Tie3::~Tie3() {
|
||||
discard_tree_cache();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set up all OpenGL and temporary buffers for a given level name.
|
||||
* The level name should be the 3 character short name.
|
||||
*/
|
||||
void Tie3::setup_for_level(const std::string& level, SharedRenderState* render_state) {
|
||||
// make sure we have the level data.
|
||||
// TODO: right now this will wait to load from disk and unpack it.
|
||||
auto lev_data = render_state->loader.get_tfrag3_level(level);
|
||||
|
||||
if (m_level_name != level) {
|
||||
Timer tie_setup_timer;
|
||||
// We changed level!
|
||||
fmt::print("TIE3 level change! {} -> {}\n", m_level_name, level);
|
||||
fmt::print(" Removing old level...\n");
|
||||
discard_tree_cache();
|
||||
fmt::print(" New level has {} tie trees\n", lev_data->tie_trees.size());
|
||||
m_trees.resize(lev_data->tie_trees.size());
|
||||
|
||||
size_t idx_buffer_len = 0;
|
||||
size_t time_of_day_count = 0;
|
||||
size_t vis_temp_len = 0;
|
||||
size_t max_draw = 0;
|
||||
size_t max_idx_per_draw = 0;
|
||||
|
||||
// set up each tree
|
||||
for (size_t tree_idx = 0; tree_idx < lev_data->tie_trees.size(); tree_idx++) {
|
||||
const auto& tree = lev_data->tie_trees[tree_idx];
|
||||
max_draw = std::max(tree.static_draws.size(), max_draw);
|
||||
for (auto& draw : tree.static_draws) {
|
||||
idx_buffer_len += draw.vertex_index_stream.size();
|
||||
max_idx_per_draw = std::max(max_idx_per_draw, draw.vertex_index_stream.size());
|
||||
}
|
||||
time_of_day_count = std::max(tree.colors.size(), time_of_day_count);
|
||||
u32 verts = tree.vertices.size();
|
||||
fmt::print(" tree {} has {} verts ({} kB) and {} draws\n", tree_idx, verts,
|
||||
verts * sizeof(tfrag3::PreloadedVertex) / 1024.f, tree.static_draws.size());
|
||||
glGenVertexArrays(1, &m_trees[tree_idx].vao);
|
||||
glBindVertexArray(m_trees[tree_idx].vao);
|
||||
glGenBuffers(1, &m_trees[tree_idx].vertex_buffer);
|
||||
m_trees[tree_idx].vert_count = verts;
|
||||
m_trees[tree_idx].draws = &tree.static_draws; // todo - should we just copy this?
|
||||
m_trees[tree_idx].colors = &tree.colors;
|
||||
m_trees[tree_idx].vis = &tree.bvh;
|
||||
vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size());
|
||||
m_trees[tree_idx].tod_cache = swizzle_time_of_day(tree.colors);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_trees[tree_idx].vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, verts * sizeof(tfrag3::PreloadedVertex), nullptr,
|
||||
GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, verts * sizeof(tfrag3::PreloadedVertex),
|
||||
tree.vertices.data());
|
||||
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 values per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized
|
||||
sizeof(tfrag3::PreloadedVertex), // stride
|
||||
(void*)offsetof(tfrag3::PreloadedVertex, x) // offset (0)
|
||||
);
|
||||
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
3, // 3 values per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized
|
||||
sizeof(tfrag3::PreloadedVertex), // stride
|
||||
(void*)offsetof(tfrag3::PreloadedVertex, s) // offset (0)
|
||||
);
|
||||
|
||||
glVertexAttribPointer(2, // location 2 in the shader
|
||||
1, // 1 values per vert
|
||||
GL_UNSIGNED_SHORT, // u16
|
||||
GL_FALSE, // don't normalize
|
||||
sizeof(tfrag3::PreloadedVertex), // stride
|
||||
(void*)offsetof(tfrag3::PreloadedVertex, color_index) // offset (0)
|
||||
);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
fmt::print("TIE temporary vis output size: {}\n", vis_temp_len);
|
||||
m_cache.vis_temp.resize(vis_temp_len);
|
||||
fmt::print("TIE max draws/tree: {}\n", max_draw);
|
||||
m_cache.draw_idx_temp.resize(max_draw);
|
||||
fmt::print("TIE draw with the most verts: {}\n", max_idx_per_draw);
|
||||
|
||||
// todo share textures
|
||||
fmt::print("level has {} textures\n", lev_data->textures.size());
|
||||
for (auto& tex : lev_data->textures) {
|
||||
GLuint gl_tex;
|
||||
glGenTextures(1, &gl_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, gl_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.w, tex.h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
tex.data.data());
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, gl_tex);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
float aniso = 0.0f;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &aniso);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, aniso);
|
||||
m_textures.push_back(gl_tex);
|
||||
}
|
||||
|
||||
fmt::print("level TIE index stream: {}\n", idx_buffer_len);
|
||||
m_cache.index_list.resize(idx_buffer_len);
|
||||
m_has_index_buffer = true;
|
||||
glGenBuffers(1, &m_index_buffer);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_len * sizeof(u32), nullptr, GL_STREAM_DRAW);
|
||||
|
||||
fmt::print("level max time of day: {}\n", time_of_day_count);
|
||||
assert(time_of_day_count <= TIME_OF_DAY_COLOR_COUNT);
|
||||
// regardless of how many we use some fixed max
|
||||
// we won't actually interp or upload to gpu the unused ones, but we need a fixed maximum so
|
||||
// indexing works properly.
|
||||
m_color_result.resize(TIME_OF_DAY_COLOR_COUNT);
|
||||
glGenTextures(1, &m_time_of_day_texture);
|
||||
m_has_time_of_day_texture = true;
|
||||
glBindTexture(GL_TEXTURE_1D, m_time_of_day_texture);
|
||||
// just fill with zeros. this lets use use the faster texsubimage later
|
||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, TIME_OF_DAY_COLOR_COUNT, 0, GL_RGBA,
|
||||
GL_UNSIGNED_INT_8_8_8_8, m_color_result.data());
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
m_level_name = level;
|
||||
fmt::print("TIE setup: {:.3f}\n", tie_setup_timer.getSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
void Tie3::discard_tree_cache() {
|
||||
for (auto tex : m_textures) {
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glDeleteTextures(1, &tex);
|
||||
}
|
||||
m_textures.clear();
|
||||
|
||||
for (auto& tree : m_trees) {
|
||||
glDeleteBuffers(1, &tree.vertex_buffer);
|
||||
glDeleteVertexArrays(1, &tree.vao);
|
||||
}
|
||||
|
||||
if (m_has_index_buffer) {
|
||||
glDeleteBuffers(1, &m_index_buffer);
|
||||
m_has_index_buffer = false;
|
||||
}
|
||||
|
||||
if (m_has_time_of_day_texture) {
|
||||
glBindTexture(GL_TEXTURE_1D, m_time_of_day_texture);
|
||||
glDeleteTextures(1, &m_time_of_day_texture);
|
||||
m_has_time_of_day_texture = false;
|
||||
}
|
||||
|
||||
m_trees.clear();
|
||||
}
|
||||
|
||||
void Tie3::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (!m_enabled) {
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_override_level && m_pending_user_level) {
|
||||
setup_for_level(*m_pending_user_level, render_state);
|
||||
m_pending_user_level = {};
|
||||
}
|
||||
|
||||
auto data0 = dma.read_and_advance();
|
||||
assert(data0.vif1() == 0);
|
||||
assert(data0.vif0() == 0);
|
||||
assert(data0.size_bytes == 0);
|
||||
|
||||
if (dma.current_tag().kind == DmaTag::Kind::CALL) {
|
||||
// renderer didn't run, let's just get out of here.
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
assert(dma.current_tag_offset() == render_state->next_bucket);
|
||||
return;
|
||||
}
|
||||
|
||||
auto gs_test = dma.read_and_advance();
|
||||
assert(gs_test.size_bytes == 32);
|
||||
|
||||
auto tie_consts = dma.read_and_advance();
|
||||
assert(tie_consts.size_bytes == 9 * 16);
|
||||
|
||||
auto mscalf = dma.read_and_advance();
|
||||
assert(mscalf.size_bytes == 0);
|
||||
|
||||
auto row = dma.read_and_advance();
|
||||
assert(row.size_bytes == 32);
|
||||
|
||||
auto next = dma.read_and_advance();
|
||||
assert(next.size_bytes == 0);
|
||||
|
||||
auto pc_port_data = dma.read_and_advance();
|
||||
assert(pc_port_data.size_bytes == sizeof(TfragPcPortData));
|
||||
memcpy(&m_pc_port_data, pc_port_data.data, sizeof(TfragPcPortData));
|
||||
m_pc_port_data.level_name[11] = '\0';
|
||||
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_pc_port_data.hvdf_off;
|
||||
settings.fog_x = m_pc_port_data.fogx;
|
||||
|
||||
memcpy(settings.math_camera.data(), m_pc_port_data.camera[0].data(), 64);
|
||||
settings.tree_idx = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
settings.planes[i] = m_pc_port_data.planes[i];
|
||||
}
|
||||
|
||||
if (false) {
|
||||
// for (int i = 0; i < 8; i++) {
|
||||
// settings.time_of_day_weights[i] = m_time_of_days[i];
|
||||
// }
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
settings.time_of_day_weights[i] =
|
||||
2 * (0xff & m_pc_port_data.itimes[i / 2].data()[2 * (i % 2)]) / 127.f;
|
||||
}
|
||||
}
|
||||
if (!m_override_level) {
|
||||
setup_for_level(m_pc_port_data.level_name, render_state);
|
||||
}
|
||||
render_all_trees(settings, render_state, prof);
|
||||
// todo render all...
|
||||
}
|
||||
|
||||
void Tie3::render_all_trees(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
Timer all_tree_timer;
|
||||
if (m_override_level && m_pending_user_level) {
|
||||
setup_for_level(*m_pending_user_level, render_state);
|
||||
m_pending_user_level = {};
|
||||
}
|
||||
for (u32 i = 0; i < m_trees.size(); i++) {
|
||||
render_tree(i, settings, render_state, prof);
|
||||
}
|
||||
m_all_tree_time.add(all_tree_timer.getSeconds());
|
||||
}
|
||||
|
||||
void Tie3::render_tree(int idx,
|
||||
const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
Timer tree_timer;
|
||||
auto& tree = m_trees.at(idx);
|
||||
tree.perf.draws = 0;
|
||||
tree.perf.verts = 0;
|
||||
tree.perf.full_draws = 0;
|
||||
|
||||
if (m_color_result.size() < tree.colors->size()) {
|
||||
m_color_result.resize(tree.colors->size());
|
||||
}
|
||||
|
||||
Timer interp_timer;
|
||||
if (m_use_fast_time_of_day) {
|
||||
interp_time_of_day_fast(settings.time_of_day_weights, tree.tod_cache, m_color_result.data());
|
||||
} else {
|
||||
interp_time_of_day_slow(settings.time_of_day_weights, *tree.colors, m_color_result.data());
|
||||
}
|
||||
tree.perf.tod_time.add(interp_timer.getSeconds());
|
||||
|
||||
Timer setup_timer;
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_1D, m_time_of_day_texture);
|
||||
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, tree.colors->size(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
m_color_result.data());
|
||||
|
||||
first_tfrag_draw_setup(settings, render_state);
|
||||
|
||||
glBindVertexArray(tree.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tree.vertex_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
tree.perf.tod_time.add(setup_timer.getSeconds());
|
||||
|
||||
int last_texture = -1;
|
||||
|
||||
Timer cull_timer;
|
||||
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, m_cache.vis_temp.data());
|
||||
tree.perf.cull_time.add(cull_timer.getSeconds());
|
||||
|
||||
Timer index_timer;
|
||||
int idx_buffer_ptr = make_index_list_from_vis_string(
|
||||
m_cache.draw_idx_temp.data(), m_cache.index_list.data(), *tree.draws, m_cache.vis_temp);
|
||||
tree.perf.index_time.add(index_timer.getSeconds());
|
||||
tree.perf.index_upload = sizeof(u32) * idx_buffer_ptr;
|
||||
|
||||
Timer draw_timer;
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_ptr * sizeof(u32),
|
||||
m_cache.index_list.data());
|
||||
|
||||
for (size_t draw_idx = 0; draw_idx < tree.draws->size(); draw_idx++) {
|
||||
const auto& draw = tree.draws->operator[](draw_idx);
|
||||
const auto& indices = m_cache.draw_idx_temp[draw_idx];
|
||||
|
||||
if (indices.second <= indices.first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)draw.tree_tex_id != last_texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures.at(draw.tree_tex_id));
|
||||
last_texture = draw.tree_tex_id;
|
||||
}
|
||||
|
||||
auto double_draw = setup_tfrag_shader(settings, render_state, draw.mode);
|
||||
int draw_size = indices.second - indices.first;
|
||||
void* offset = (void*)(indices.first * sizeof(u32));
|
||||
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(draw.num_triangles * (float)draw_size / draw.vertex_index_stream.size());
|
||||
|
||||
bool is_full = draw_size == (int)draw.vertex_index_stream.size();
|
||||
|
||||
tree.perf.draws++;
|
||||
if (is_full) {
|
||||
tree.perf.full_draws++;
|
||||
}
|
||||
tree.perf.verts += draw_size;
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
|
||||
switch (double_draw.kind) {
|
||||
case DoubleDrawKind::NONE:
|
||||
break;
|
||||
case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE:
|
||||
tree.perf.draws++;
|
||||
tree.perf.verts += draw_size;
|
||||
if (is_full) {
|
||||
tree.perf.full_draws++;
|
||||
}
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(draw_size);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_min"),
|
||||
-10.f);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
|
||||
double_draw.aref);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (m_debug_wireframe) {
|
||||
render_state->shaders[ShaderId::TFRAG3_NO_TEX].activate();
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "camera"), 1,
|
||||
GL_FALSE, settings.math_camera.data());
|
||||
glUniform4f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "hvdf_offset"),
|
||||
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
|
||||
settings.hvdf_offset[3]);
|
||||
glUniform1f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
glDisable(GL_BLEND);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(draw_size);
|
||||
render_state->shaders[ShaderId::TFRAG3].activate();
|
||||
}
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
tree.perf.draw_time.add(draw_timer.getSeconds());
|
||||
tree.perf.tree_time.add(tree_timer.getSeconds());
|
||||
}
|
||||
|
||||
void Tie3::draw_debug_window() {
|
||||
ImGui::InputText("Custom Level", m_user_level, sizeof(m_user_level));
|
||||
if (ImGui::Button("Go!")) {
|
||||
m_pending_user_level = m_user_level;
|
||||
}
|
||||
ImGui::Checkbox("Override level", &m_override_level);
|
||||
ImGui::Checkbox("Fast ToD", &m_use_fast_time_of_day);
|
||||
ImGui::Checkbox("Wireframe", &m_debug_wireframe);
|
||||
ImGui::Separator();
|
||||
for (u32 i = 0; i < m_trees.size(); i++) {
|
||||
auto& perf = m_trees[i].perf;
|
||||
ImGui::Text("Tree: %d", i);
|
||||
ImGui::Text("index data bytes: %d", perf.index_upload);
|
||||
ImGui::Text("time of days: %d", (int)m_trees[i].colors->size());
|
||||
ImGui::Text("draw: %d, full: %d, verts: %d", perf.draws, perf.full_draws, perf.verts);
|
||||
ImGui::Text("total: %.2f", perf.tree_time.get());
|
||||
ImGui::Text("cull: %.2f index: %.2f tod: %.2f setup: %.2f draw: %.2f",
|
||||
perf.cull_time.get() * 1000.f, perf.index_time.get() * 1000.f,
|
||||
perf.tod_time.get() * 1000.f, perf.setup_time.get() * 1000.f,
|
||||
perf.draw_time.get() * 1000.f);
|
||||
ImGui::Separator();
|
||||
}
|
||||
ImGui::Text("All trees: %.2f", 1000.f * m_all_tree_time.get());
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "game/graphics/opengl_renderer/tfrag/tfrag_common.h"
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
#include "common/util/FilteredValue.h"
|
||||
|
||||
class Tie3 : public BucketRenderer {
|
||||
public:
|
||||
Tie3(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
~Tie3();
|
||||
|
||||
void render_all_trees(const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void render_tree(int idx,
|
||||
const TfragRenderSettings& settings,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void setup_for_level(const std::string& str, SharedRenderState* render_state);
|
||||
|
||||
private:
|
||||
void discard_tree_cache();
|
||||
struct Tree {
|
||||
GLuint vertex_buffer;
|
||||
GLuint vao;
|
||||
u32 vert_count;
|
||||
const std::vector<tfrag3::StripDraw>* draws = nullptr;
|
||||
const std::vector<tfrag3::TimeOfDayColor>* colors = nullptr;
|
||||
const tfrag3::BVH* vis = nullptr;
|
||||
SwizzledTimeOfDay tod_cache;
|
||||
|
||||
struct {
|
||||
u32 index_upload = 0;
|
||||
u32 verts = 0;
|
||||
u32 draws = 0;
|
||||
u32 full_draws = 0; // ones that have all visible
|
||||
Filtered<float> cull_time;
|
||||
Filtered<float> index_time;
|
||||
Filtered<float> tod_time;
|
||||
Filtered<float> setup_time;
|
||||
Filtered<float> draw_time;
|
||||
Filtered<float> tree_time;
|
||||
} perf;
|
||||
};
|
||||
|
||||
std::vector<Tree> m_trees;
|
||||
std::string m_level_name;
|
||||
std::vector<GLuint> m_textures; // todo, can we share with tfrag in some cases?
|
||||
|
||||
struct Cache {
|
||||
std::vector<u8> vis_temp;
|
||||
std::vector<std::pair<int, int>> draw_idx_temp;
|
||||
std::vector<u32> index_list;
|
||||
} m_cache;
|
||||
|
||||
GLuint m_time_of_day_texture = -1;
|
||||
bool m_has_time_of_day_texture = false;
|
||||
|
||||
std::vector<math::Vector<u8, 4>> m_color_result;
|
||||
|
||||
bool m_has_index_buffer = false;
|
||||
GLuint m_index_buffer = -1;
|
||||
|
||||
static constexpr int TIME_OF_DAY_COLOR_COUNT = 8192;
|
||||
|
||||
char m_user_level[255] = "vi1";
|
||||
std::optional<std::string> m_pending_user_level = std::nullopt;
|
||||
bool m_override_level = false;
|
||||
bool m_use_fast_time_of_day = true;
|
||||
bool m_debug_wireframe = false;
|
||||
Filtered<float> m_all_tree_time;
|
||||
|
||||
TfragPcPortData m_pc_port_data;
|
||||
};
|
||||
@@ -0,0 +1,349 @@
|
||||
|
||||
|
||||
#include "tfrag_common.h"
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
DoubleDraw setup_tfrag_shader(const TfragRenderSettings& /*settings*/,
|
||||
SharedRenderState* render_state,
|
||||
DrawMode mode) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
if (mode.get_zt_enable()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
switch (mode.get_depth_test()) {
|
||||
case GsTest::ZTest::NEVER:
|
||||
glDepthFunc(GL_NEVER);
|
||||
break;
|
||||
case GsTest::ZTest::ALWAYS:
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
break;
|
||||
case GsTest::ZTest::GEQUAL:
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
break;
|
||||
case GsTest::ZTest::GREATER:
|
||||
glDepthFunc(GL_GREATER);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (mode.get_ab_enable() && mode.get_alpha_blend() != DrawMode::AlphaBlend::DISABLED) {
|
||||
glEnable(GL_BLEND);
|
||||
switch (mode.get_alpha_blend()) {
|
||||
case DrawMode::AlphaBlend::SRC_DST_SRC_DST:
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case DrawMode::AlphaBlend::SRC_0_SRC_DST:
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
break;
|
||||
case DrawMode::AlphaBlend::SRC_0_FIX_DST:
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
break;
|
||||
case DrawMode::AlphaBlend::SRC_DST_FIX_DST:
|
||||
// Cv = (Cs - Cd) * FIX + Cd
|
||||
// Cs * FIX * 0.5
|
||||
// Cd * FIX * 0.5
|
||||
glBlendFunc(GL_CONSTANT_COLOR, GL_CONSTANT_COLOR);
|
||||
glBlendColor(0.5, 0.5, 0.5, 0.5);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (mode.get_clamp_s_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (mode.get_clamp_t_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (mode.get_filt_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
// for some reason, they set atest NEVER + FB_ONLY to disable depth writes
|
||||
bool alpha_hack_to_disable_z_write = false;
|
||||
DoubleDraw double_draw;
|
||||
|
||||
float alpha_min = 0.;
|
||||
if (mode.get_at_enable()) {
|
||||
switch (mode.get_alpha_test()) {
|
||||
case DrawMode::AlphaTest::ALWAYS:
|
||||
break;
|
||||
case DrawMode::AlphaTest::GEQUAL:
|
||||
alpha_min = mode.get_aref() / 127.f;
|
||||
switch (mode.get_alpha_fail()) {
|
||||
case GsTest::AlphaFail::KEEP:
|
||||
// ok, no need for double draw
|
||||
break;
|
||||
case GsTest::AlphaFail::FB_ONLY:
|
||||
// darn, we need to draw twice
|
||||
double_draw.kind = DoubleDrawKind::AFAIL_NO_DEPTH_WRITE;
|
||||
double_draw.aref = alpha_min;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case DrawMode::AlphaTest::NEVER:
|
||||
if (mode.get_alpha_fail() == GsTest::AlphaFail::FB_ONLY) {
|
||||
alpha_hack_to_disable_z_write = true;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode.get_depth_write_enable()) {
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_min"),
|
||||
alpha_min);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
|
||||
10.f);
|
||||
|
||||
return double_draw;
|
||||
}
|
||||
|
||||
void first_tfrag_draw_setup(const TfragRenderSettings& settings, SharedRenderState* render_state) {
|
||||
render_state->shaders[ShaderId::TFRAG3].activate();
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "tex_T0"), 0);
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "tex_T1"), 1);
|
||||
glUniformMatrix4fv(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "camera"),
|
||||
1, GL_FALSE, settings.math_camera.data());
|
||||
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "hvdf_offset"),
|
||||
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
|
||||
settings.hvdf_offset[3]);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
}
|
||||
|
||||
void interp_time_of_day_slow(const float weights[8],
|
||||
const std::vector<tfrag3::TimeOfDayColor>& in,
|
||||
math::Vector<u8, 4>* out) {
|
||||
// Timer interp_timer;
|
||||
for (size_t color = 0; color < in.size(); color++) {
|
||||
math::Vector4f result = math::Vector4f::zero();
|
||||
for (int component = 0; component < 8; component++) {
|
||||
result += in[color].rgba[component].cast<float>() * weights[component];
|
||||
}
|
||||
result[0] = std::min(result[0], 255.f);
|
||||
result[1] = std::min(result[1], 255.f);
|
||||
result[2] = std::min(result[2], 255.f);
|
||||
result[3] = std::min(result[3], 128.f); // note: different for alpha!
|
||||
out[color] = result.cast<u8>();
|
||||
}
|
||||
}
|
||||
|
||||
// we want to absolutely minimize the number of time we have to "cross lanes" in AVX (meaning X
|
||||
// component of one vector interacts with Y component of another). We can make this a lot better by
|
||||
// taking groups of 4 time of day colors (each containing 8x RGBAs) and rearranging them with this
|
||||
// pattern. We want to compute:
|
||||
// [rgba][0][0] * weights[0] + [rgba][0][1] * weights[1] + [rgba][0][2]... + rgba[0][7] * weights[7]
|
||||
// RGBA is already a vector of 4 components, but with AVX we have vectors with 32 bytes which fit
|
||||
// 16 colors in them.
|
||||
|
||||
// This makes each vector have:
|
||||
// colors0 = [rgba][0][0], [rgba][1][0], [rgba][2][0], [rgba][3][0]
|
||||
// colors1 = [rgba][0][1], [rgba][1][1], [rgba][2][1], [rgba][3][1]
|
||||
// ...
|
||||
// so we can basically add up the columns (multiplying by weights in between)
|
||||
// and we'll end up with [final0, final1, final2, final3, final4]
|
||||
|
||||
// the swizzle function below rearranges to get this pattern.
|
||||
// it's not the most efficient way to do it, but it just runs during loading and not on every frame.
|
||||
|
||||
SwizzledTimeOfDay swizzle_time_of_day(const std::vector<tfrag3::TimeOfDayColor>& in) {
|
||||
SwizzledTimeOfDay out;
|
||||
out.data.resize(in.size() * 8 * 4);
|
||||
|
||||
// we're rearranging per 4 colors (groups of 32 * 4 = 128)
|
||||
// color (lots of these)
|
||||
// component (8 of these)
|
||||
// channel (4 of these, rgba)
|
||||
|
||||
for (u32 color_quad = 0; color_quad < in.size() / 4; color_quad++) {
|
||||
u8* quad_out = out.data.data() + color_quad * 128;
|
||||
for (u32 component = 0; component < 8; component++) {
|
||||
for (u32 color = 0; color < 4; color++) {
|
||||
for (u32 channel = 0; channel < 4; channel++) {
|
||||
*quad_out = in.at(color_quad * 4 + color).rgba[component][channel];
|
||||
quad_out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.color_count = in.size();
|
||||
return out;
|
||||
}
|
||||
|
||||
// This does the same thing as interp_time_of_day_slow, but is faster.
|
||||
// Due to using integers instead of floats, it may be a tiny bit different.
|
||||
// TODO: it might be possible to reorder the loop into two blocks of loads and avoid spilling xmms.
|
||||
// It's ~8x faster than the slow version.
|
||||
void interp_time_of_day_fast(const float weights[8],
|
||||
const SwizzledTimeOfDay& in,
|
||||
math::Vector<u8, 4>* out) {
|
||||
// even though the colors are 8 bits, we'll use 16 bits so we can saturate correctly
|
||||
|
||||
// weight multipliers
|
||||
__m256i weights0 = _mm256_set1_epi16(weights[0] * 128.f);
|
||||
__m256i weights1 = _mm256_set1_epi16(weights[1] * 128.f);
|
||||
__m256i weights2 = _mm256_set1_epi16(weights[2] * 128.f);
|
||||
__m256i weights3 = _mm256_set1_epi16(weights[3] * 128.f);
|
||||
__m256i weights4 = _mm256_set1_epi16(weights[4] * 128.f);
|
||||
__m256i weights5 = _mm256_set1_epi16(weights[5] * 128.f);
|
||||
__m256i weights6 = _mm256_set1_epi16(weights[6] * 128.f);
|
||||
__m256i weights7 = _mm256_set1_epi16(weights[7] * 128.f);
|
||||
|
||||
// saturation: note that alpha is saturated to 128 but the rest are 255.
|
||||
// TODO: maybe we should saturate to 255 for everybody (can do this using a single packus) and
|
||||
// change the shader to deal with this.
|
||||
__m256i sat = _mm256_set_epi16(128, 255, 255, 255, 128, 255, 255, 255, 128, 255, 255, 255, 128,
|
||||
255, 255, 255);
|
||||
|
||||
for (u32 color_quad = 0; color_quad < in.color_count / 4; color_quad++) {
|
||||
// first, load colors. We put 16 bytes / register and don't touch the upper half because we will
|
||||
// convert u8s to u16s.
|
||||
const u8* base = in.data.data() + color_quad * 128;
|
||||
__m128i color0_p = _mm_loadu_si128((const __m128i*)(base + 0));
|
||||
__m128i color1_p = _mm_loadu_si128((const __m128i*)(base + 16));
|
||||
__m128i color2_p = _mm_loadu_si128((const __m128i*)(base + 32));
|
||||
__m128i color3_p = _mm_loadu_si128((const __m128i*)(base + 48));
|
||||
__m128i color4_p = _mm_loadu_si128((const __m128i*)(base + 64));
|
||||
__m128i color5_p = _mm_loadu_si128((const __m128i*)(base + 80));
|
||||
__m128i color6_p = _mm_loadu_si128((const __m128i*)(base + 96));
|
||||
__m128i color7_p = _mm_loadu_si128((const __m128i*)(base + 112));
|
||||
|
||||
// unpack to 16-bits. each has 16x 16 bit colors.
|
||||
__m256i color0 = _mm256_cvtepu8_epi16(color0_p);
|
||||
__m256i color1 = _mm256_cvtepu8_epi16(color1_p);
|
||||
__m256i color2 = _mm256_cvtepu8_epi16(color2_p);
|
||||
__m256i color3 = _mm256_cvtepu8_epi16(color3_p);
|
||||
__m256i color4 = _mm256_cvtepu8_epi16(color4_p);
|
||||
__m256i color5 = _mm256_cvtepu8_epi16(color5_p);
|
||||
__m256i color6 = _mm256_cvtepu8_epi16(color6_p);
|
||||
__m256i color7 = _mm256_cvtepu8_epi16(color7_p);
|
||||
|
||||
// multiply by weights
|
||||
color0 = _mm256_mullo_epi16(color0, weights0);
|
||||
color1 = _mm256_mullo_epi16(color1, weights1);
|
||||
color2 = _mm256_mullo_epi16(color2, weights2);
|
||||
color3 = _mm256_mullo_epi16(color3, weights3);
|
||||
color4 = _mm256_mullo_epi16(color4, weights4);
|
||||
color5 = _mm256_mullo_epi16(color5, weights5);
|
||||
color6 = _mm256_mullo_epi16(color6, weights6);
|
||||
color7 = _mm256_mullo_epi16(color7, weights7);
|
||||
|
||||
// add. This order minimizes dependencies.
|
||||
color0 = _mm256_add_epi16(color0, color1);
|
||||
color2 = _mm256_add_epi16(color2, color3);
|
||||
color4 = _mm256_add_epi16(color4, color5);
|
||||
color6 = _mm256_add_epi16(color6, color7);
|
||||
|
||||
color0 = _mm256_add_epi16(color0, color2);
|
||||
color4 = _mm256_add_epi16(color4, color6);
|
||||
|
||||
color0 = _mm256_add_epi16(color0, color4);
|
||||
|
||||
// divide, because we multiplied our weights by 2^7.
|
||||
color0 = _mm256_srli_epi16(color0, 7);
|
||||
|
||||
// saturate
|
||||
color0 = _mm256_min_epu16(sat, color0);
|
||||
|
||||
// back to u8s.
|
||||
auto hi = _mm256_extracti128_si256(color0, 1);
|
||||
auto result = _mm_packus_epi16(_mm256_castsi256_si128(color0), hi);
|
||||
|
||||
// store result
|
||||
_mm_storeu_si128((__m128i*)(&out[color_quad * 4]), result);
|
||||
}
|
||||
}
|
||||
|
||||
bool sphere_in_view_ref(const math::Vector4f& sphere, const math::Vector4f* planes) {
|
||||
math::Vector4f acc =
|
||||
planes[0] * sphere.x() + planes[1] * sphere.y() + planes[2] * sphere.z() - planes[3];
|
||||
|
||||
return acc.x() > -sphere.w() && acc.y() > -sphere.w() && acc.z() > -sphere.w() &&
|
||||
acc.w() > -sphere.w();
|
||||
}
|
||||
|
||||
// this isn't super efficient, but we spend so little time here it's not worth it to go faster.
|
||||
void cull_check_all_slow(const math::Vector4f* planes,
|
||||
const std::vector<tfrag3::VisNode>& nodes,
|
||||
u8* out) {
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
out[i] = sphere_in_view_ref(nodes[i].bsphere, planes);
|
||||
}
|
||||
}
|
||||
|
||||
u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
|
||||
u32* idx_out,
|
||||
const std::vector<tfrag3::StripDraw>& draws,
|
||||
const std::vector<u8>& vis_data) {
|
||||
int idx_buffer_ptr = 0;
|
||||
for (size_t i = 0; i < draws.size(); i++) {
|
||||
const auto& draw = draws[i];
|
||||
int vtx_idx = 0;
|
||||
std::pair<int, int> ds;
|
||||
ds.first = idx_buffer_ptr;
|
||||
bool building_run = false;
|
||||
int run_start_out = 0;
|
||||
int run_start_in = 0;
|
||||
for (auto& grp : draw.vis_groups) {
|
||||
bool vis = grp.vis_idx == 0xffffffff || vis_data[grp.vis_idx];
|
||||
if (building_run) {
|
||||
if (vis) {
|
||||
idx_buffer_ptr += grp.num;
|
||||
} else {
|
||||
building_run = false;
|
||||
idx_buffer_ptr += grp.num;
|
||||
memcpy(&idx_out[run_start_out], &draw.vertex_index_stream[run_start_in],
|
||||
(idx_buffer_ptr - run_start_out) * sizeof(u32));
|
||||
}
|
||||
} else {
|
||||
if (vis) {
|
||||
building_run = true;
|
||||
run_start_out = idx_buffer_ptr;
|
||||
run_start_in = vtx_idx;
|
||||
idx_buffer_ptr += grp.num;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
vtx_idx += grp.num;
|
||||
}
|
||||
if (building_run) {
|
||||
memcpy(&idx_out[run_start_out], &draw.vertex_index_stream[run_start_in],
|
||||
(idx_buffer_ptr - run_start_out) * sizeof(u32));
|
||||
}
|
||||
|
||||
ds.second = idx_buffer_ptr;
|
||||
group_out[i] = ds;
|
||||
}
|
||||
return idx_buffer_ptr;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/math/Vector.h"
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
|
||||
struct TfragRenderSettings {
|
||||
math::Matrix4f math_camera;
|
||||
math::Vector4f hvdf_offset;
|
||||
float fog_x;
|
||||
int tree_idx;
|
||||
float time_of_day_weights[8] = {0};
|
||||
math::Vector4f planes[4];
|
||||
bool do_culling = false;
|
||||
bool debug_culling = false;
|
||||
// todo occlusion culling string.
|
||||
};
|
||||
|
||||
enum class DoubleDrawKind { NONE, AFAIL_NO_DEPTH_WRITE };
|
||||
|
||||
struct DoubleDraw {
|
||||
DoubleDrawKind kind = DoubleDrawKind::NONE;
|
||||
float aref = 0.;
|
||||
};
|
||||
|
||||
DoubleDraw setup_tfrag_shader(const TfragRenderSettings& /*settings*/,
|
||||
SharedRenderState* render_state,
|
||||
DrawMode mode);
|
||||
void first_tfrag_draw_setup(const TfragRenderSettings& settings, SharedRenderState* render_state);
|
||||
void interp_time_of_day_slow(const float weights[8],
|
||||
const std::vector<tfrag3::TimeOfDayColor>& in,
|
||||
math::Vector<u8, 4>* out);
|
||||
|
||||
struct SwizzledTimeOfDay {
|
||||
std::vector<u8> data;
|
||||
u32 color_count = 0;
|
||||
};
|
||||
|
||||
SwizzledTimeOfDay swizzle_time_of_day(const std::vector<tfrag3::TimeOfDayColor>& in);
|
||||
|
||||
void interp_time_of_day_fast(const float weights[8],
|
||||
const SwizzledTimeOfDay& in,
|
||||
math::Vector<u8, 4>* out);
|
||||
|
||||
void cull_check_all_slow(const math::Vector4f* planes,
|
||||
const std::vector<tfrag3::VisNode>& nodes,
|
||||
u8* out);
|
||||
|
||||
struct TfragPcPortData {
|
||||
math::Vector4f planes[4];
|
||||
math::Vector<s32, 4> itimes[4];
|
||||
math::Vector4f camera[4];
|
||||
math::Vector4f hvdf_off;
|
||||
float fogx;
|
||||
float unused[3];
|
||||
char level_name[12];
|
||||
u32 tree_idx;
|
||||
};
|
||||
|
||||
u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
|
||||
u32* idx_out,
|
||||
const std::vector<tfrag3::StripDraw>& draws,
|
||||
const std::vector<u8>& vis_data);
|
||||
+1
-1
@@ -260,7 +260,7 @@ void dmac_runner(SystemThreadInterface& iface) {
|
||||
// }
|
||||
// }
|
||||
// avoid running the DMAC on full blast (this does not sync to its clockrate)
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(50000));
|
||||
}
|
||||
|
||||
VM::unsubscribe_component();
|
||||
|
||||
@@ -90,7 +90,7 @@ void IOP::kill_from_ee() {
|
||||
|
||||
void IOP::signal_run_iop() {
|
||||
std::unique_lock<std::mutex> lk(iters_mutex);
|
||||
iop_iters_des += 100; // todo, tune this
|
||||
iop_iters_des++; // todo, tune this
|
||||
if (iop_iters_des - iop_iters_act > 500) {
|
||||
iop_iters_des = iop_iters_act + 500;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
;; the x/y ratio are frustum slopes
|
||||
(set! (-> math-cam x-ratio) (tan (* 0.5 (-> math-cam fov))))
|
||||
;;(format #t "aspect is ~A~%" aspect)
|
||||
(if (= aspect 'aspect4x3)
|
||||
(set! (-> math-cam y-ratio) (* 0.75 (-> math-cam x-ratio)))
|
||||
(set! (-> math-cam y-ratio) (* 0.5625 (-> math-cam x-ratio)))
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
;; Used internally for computing memory info
|
||||
(define *temp-mem-usage* (the-as memory-usage-block #f))
|
||||
|
||||
;; TODO: flags.
|
||||
;; bit 0 : count as a prototype definition.
|
||||
;; bit 1 : count as an instance of a prototype.
|
||||
;; bit 2 : count tie colors 1 (geom 1)
|
||||
;; bit 3 : count tie colors 2 (geom 2)
|
||||
;; bit 4 : ?? (geom 3)
|
||||
|
||||
|
||||
;; Memory usage stats are organized by the type of object.
|
||||
;; This enum allows you to go from type to the index in the memory-usage-block's data array.
|
||||
|
||||
@@ -220,6 +220,8 @@
|
||||
(tfrag-tex0 5)
|
||||
(tfrag-0 6)
|
||||
(tfrag-near-0 7)
|
||||
(tie-near-0 8)
|
||||
(tie-0 9)
|
||||
;; merc0 10
|
||||
;; generic0 11
|
||||
(bucket-10 10)
|
||||
@@ -228,6 +230,8 @@
|
||||
(tfrag-tex1 12)
|
||||
(tfrag-1 13)
|
||||
(tfrag-near-1 14)
|
||||
(tie-near-1 15)
|
||||
(tie-1 16)
|
||||
;; merc1 17
|
||||
;; generic1 18
|
||||
(bucket-17 17)
|
||||
|
||||
@@ -411,7 +411,7 @@
|
||||
|
||||
|
||||
;;;;;;;;;; TIE (TFRAG Instance Engine)
|
||||
#|
|
||||
|
||||
;; common setup
|
||||
(set! (-> *instance-tie-work* paused) (paused?))
|
||||
(when (nonzero? (-> *background-work* tie-tree-count))
|
||||
@@ -436,8 +436,8 @@
|
||||
(set! gp-1 s4-2)
|
||||
)
|
||||
)
|
||||
(set! (-> (the-as terrain-context #x70000000) bsp lev-index) (-> s4-2 index))
|
||||
(set! (-> (the-as terrain-context #x70000000) bsp mood) (-> s4-2 mood))
|
||||
(set! (-> (scratchpad-object terrain-context) bsp lev-index) (-> s4-2 index))
|
||||
(set! (-> (scratchpad-object terrain-context) bsp mood) (-> s4-2 mood))
|
||||
(draw-drawable-tree-instance-tie (-> *background-work* tie-trees s5-3) s4-2)
|
||||
)
|
||||
;; todo, type here probably wrong.
|
||||
@@ -452,7 +452,7 @@
|
||||
(new 'static 'rgba :r #x80 :g #x20 :b #x60 :a #x80)
|
||||
)
|
||||
)
|
||||
|
||||
#|
|
||||
;; TIE Generic
|
||||
(dotimes (gp-2 (-> *background-work* tie-tree-count))
|
||||
(when (nonzero? (-> *background-work* tie-generic gp-2))
|
||||
@@ -478,9 +478,9 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
|#
|
||||
)
|
||||
|
||||
|#
|
||||
)
|
||||
0
|
||||
(none)
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
(quad uint128 :offset 0)
|
||||
(data uint64 :offset 0)
|
||||
(cmds uint64 :offset 8)
|
||||
(cmd uint8 :offset 8)
|
||||
(cmd gs-reg :offset 8)
|
||||
(x uint32 :offset 0)
|
||||
(y uint32 :offset 4)
|
||||
(z uint32 :offset 8)
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
(defun add-pc-tfrag3-data ((dma-buf dma-buffer) (lev level))
|
||||
"Add PC-port specific tfrag data"
|
||||
(let ((packet (the-as dma-packet (-> dma-buf base))))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 9))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 15))
|
||||
(set! (-> packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
|
||||
(set! (-> dma-buf base) (the pointer (&+ packet 16)))
|
||||
@@ -338,9 +338,17 @@
|
||||
(set! (-> data-ptr 5) (-> lev mood itimes 1 quad))
|
||||
(set! (-> data-ptr 6) (-> lev mood itimes 2 quad))
|
||||
(set! (-> data-ptr 7) (-> lev mood itimes 3 quad))
|
||||
(charp<-string (the (pointer uint8) (&-> data-ptr 8)) (symbol->string (-> lev nickname)))
|
||||
(set! (-> data-ptr 8) (-> *math-camera* camera-temp vector 0 quad))
|
||||
(set! (-> data-ptr 9) (-> *math-camera* camera-temp vector 1 quad))
|
||||
(set! (-> data-ptr 10) (-> *math-camera* camera-temp vector 2 quad))
|
||||
(set! (-> data-ptr 11) (-> *math-camera* camera-temp vector 3 quad))
|
||||
(set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
|
||||
(let ((vec (-> (the (inline-array vector) data-ptr) 13)))
|
||||
(set! (-> vec x) (-> *math-camera* pfog0))
|
||||
)
|
||||
(charp<-string (the (pointer uint8) (&-> data-ptr 14)) (symbol->string (-> lev nickname)))
|
||||
)
|
||||
(&+! (-> dma-buf base) (* 16 9))
|
||||
(&+! (-> dma-buf base) (* 16 15))
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
)
|
||||
|
||||
(declare-type drawable-inline-array-collide-fragment drawable-inline-array)
|
||||
(declare-type prototype-tie drawable)
|
||||
(deftype prototype-bucket-tie (prototype-bucket)
|
||||
((generic-count uint16 4 :offset-assert 88)
|
||||
(generic-next uint32 4 :offset-assert 96)
|
||||
@@ -88,6 +89,7 @@
|
||||
(color-index-qwc uint32 :dynamic :offset-assert 148)
|
||||
(generic-next-clear uint128 :offset 96)
|
||||
(generic-count-clear uint128 :offset 80)
|
||||
(geometry-override prototype-tie 4 :offset 16 :score 1)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x94
|
||||
@@ -101,7 +103,7 @@
|
||||
:size-assert #x10
|
||||
:flag-assert #xa00000010
|
||||
(:methods
|
||||
(TODO-RENAME-9 (_type_) none 9)
|
||||
(login (_type_) none 9)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -5,3 +5,134 @@
|
||||
;; name in dgo: prototype
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; shared code for the tie and shrub prototypes
|
||||
|
||||
(defmethod login prototype-array-tie ((obj prototype-array-tie))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(let ((s4-0 (-> obj array-data s5-0)))
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-1 (-> s4-0 geometry s3-0)))
|
||||
(if (nonzero? a0-1)
|
||||
(login a0-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((s4-1 (-> s4-0 envmap-shader)))
|
||||
(when (nonzero? s4-1)
|
||||
(adgif-shader-login-no-remap s4-1)
|
||||
(set! (-> s4-1 tex1) (new 'static 'gs-tex1 :mmag #x1 :mmin #x1))
|
||||
(set! (-> s4-1 clamp) (new 'static 'gs-clamp :wms (gs-tex-wrap-mode clamp) :wmt (gs-tex-wrap-mode clamp)))
|
||||
(set! (-> s4-1 alpha) (new 'static 'gs-miptbp :tbp1 #x58))
|
||||
(set! (-> s4-1 prims 1) (gs-reg64 tex0-1))
|
||||
(set! (-> s4-1 prims 3) (gs-reg64 tex1-1))
|
||||
(set! (-> s4-1 prims 5) (gs-reg64 miptbp1-1))
|
||||
(set! (-> s4-1 clamp-reg) (gs-reg64 clamp-1))
|
||||
(set! (-> s4-1 prims 9) (gs-reg64 alpha-1))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod login prototype-inline-array-shrub ((obj prototype-inline-array-shrub))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(let ((s4-0 (-> obj data s5-0)))
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-1 (-> s4-0 geometry s3-0)))
|
||||
(if (nonzero? a0-1)
|
||||
(login a0-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-array-tie ((obj prototype-array-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(set! (-> arg0 length) (max 1 (-> arg0 length)))
|
||||
(set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
|
||||
(+! (-> arg0 data 0 count) 1)
|
||||
(let ((v1-8 (asize-of obj)))
|
||||
(+! (-> arg0 data 0 used) v1-8)
|
||||
(+! (-> arg0 data 0 total) (logand -16 (+ v1-8 15)))
|
||||
)
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj array-data s3-0) arg0 arg1)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-bucket-tie ((obj prototype-bucket-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-1 (-> obj geometry s3-0)))
|
||||
(if (nonzero? a0-1)
|
||||
(mem-usage a0-1 arg0 (logior arg1 1))
|
||||
)
|
||||
)
|
||||
)
|
||||
(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)))))
|
||||
(+! (-> arg0 data 80 used) v1-13)
|
||||
(+! (-> arg0 data 80 total) (logand -16 (+ v1-13 15)))
|
||||
)
|
||||
(when (nonzero? (-> obj tie-colors))
|
||||
(set! (-> arg0 length) (max 17 (-> arg0 length)))
|
||||
(set! (-> arg0 data 16 name) "tie-pal")
|
||||
(+! (-> arg0 data 16 count) 1)
|
||||
(let ((v1-25 (asize-of (-> obj tie-colors))))
|
||||
(+! (-> arg0 data 16 used) v1-25)
|
||||
(+! (-> arg0 data 16 total) (logand -16 (+ v1-25 15)))
|
||||
)
|
||||
)
|
||||
(if (nonzero? (-> obj collide-frag))
|
||||
(mem-usage (-> obj collide-frag) arg0 (logior arg1 1))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-inline-array-shrub ((obj prototype-inline-array-shrub) (arg0 memory-usage-block) (arg1 int))
|
||||
(set! (-> arg0 length) (max 1 (-> arg0 length)))
|
||||
(set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
|
||||
(+! (-> arg0 data 0 count) 1)
|
||||
(let ((v1-8 (asize-of obj)))
|
||||
(+! (-> arg0 data 0 used) v1-8)
|
||||
(+! (-> arg0 data 0 total) (logand -16 (+ v1-8 15)))
|
||||
)
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj data s3-0) arg0 arg1)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-bucket-shrub ((obj prototype-bucket-shrub) (arg0 memory-usage-block) (arg1 int))
|
||||
(set! (-> arg0 length) (max 25 (-> arg0 length)))
|
||||
(set! (-> arg0 data 24 name) "prototype-bucket-shrub")
|
||||
(+! (-> arg0 data 24 count) 1)
|
||||
(let ((v1-5 112))
|
||||
(+! (-> arg0 data 24 used) v1-5)
|
||||
(+! (-> arg0 data 24 total) (logand -16 (+ v1-5 15)))
|
||||
)
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-5 (-> obj geometry s3-0)))
|
||||
(if (nonzero? a0-5)
|
||||
(mem-usage a0-5 arg0 (logior arg1 1))
|
||||
)
|
||||
)
|
||||
)
|
||||
(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)))))
|
||||
(+! (-> arg0 data 80 used) v1-22)
|
||||
(+! (-> arg0 data 80 total) (logand -16 (+ v1-22 15)))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,29 +7,34 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; The TIE FRAGMENT is a record for a chunk of TIE DMA data.
|
||||
;; The actual data isn't stored in the tie-fragment - this just has some meta-data and a pointer
|
||||
;; to the actual data.
|
||||
;; Unlike with tfrag, tie-fragments aren't part of the draw-node tree - instead they are associated with a prototype.
|
||||
(deftype tie-fragment (drawable)
|
||||
((gif-ref uint32 :offset 4)
|
||||
(point-ref uint32 :offset 8)
|
||||
(color-index uint16 :offset 12)
|
||||
(base-colors uint8 :offset 14)
|
||||
(tex-count uint16 :offset-assert 32)
|
||||
(gif-count uint16 :offset-assert 34)
|
||||
(vertex-count uint16 :offset-assert 36)
|
||||
(color-count uint16 :offset-assert 38)
|
||||
(num-tris uint16 :offset-assert 40)
|
||||
(num-dverts uint16 :offset-assert 42)
|
||||
(dp-ref uint32 :offset-assert 44)
|
||||
(dp-qwc uint32 :offset-assert 48)
|
||||
(generic-ref uint32 :offset-assert 52)
|
||||
(generic-count uint32 :offset-assert 56)
|
||||
(debug-lines basic :offset-assert 60)
|
||||
((gif-ref (inline-array adgif-shader) :offset 4) ;; starts with adgif shaders, may have more after.
|
||||
(point-ref uint32 :offset 8)
|
||||
(color-index uint16 :offset 12)
|
||||
(base-colors uint8 :offset 14)
|
||||
(tex-count uint16 :offset-assert 32) ;; number of qw's of adgif-shaders in gif-ref (5 qw/shader)
|
||||
(gif-count uint16 :offset-assert 34)
|
||||
(vertex-count uint16 :offset-assert 36) ;; number of qw's of vertex data
|
||||
(color-count uint16 :offset-assert 38)
|
||||
(num-tris uint16 :offset-assert 40)
|
||||
(num-dverts uint16 :offset-assert 42)
|
||||
(dp-ref uint32 :offset-assert 44)
|
||||
(dp-qwc uint32 :offset-assert 48) ;; number of "draw points", in qw's.
|
||||
(generic-ref uint32 :offset-assert 52) ;; L891 ish, just a pointer to data.
|
||||
(generic-count uint32 :offset-assert 56) ;; number of qw's of generic data.
|
||||
(debug-lines (array vector-array) :offset-assert 60)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x40
|
||||
:flag-assert #x1200000040
|
||||
)
|
||||
|
||||
|
||||
;; This is a specialization of the shared instance type for a TIE.
|
||||
;; It is the child node type in the draw-node BVH tree.
|
||||
(deftype instance-tie (instance)
|
||||
((color-indices uint32 :offset 8)
|
||||
(bucket-ptr prototype-bucket-tie :offset 12)
|
||||
@@ -41,9 +46,10 @@
|
||||
:flag-assert #x1200000040
|
||||
)
|
||||
|
||||
|
||||
;; Wrapper class for lists of consecutive instances.
|
||||
;; This is equivalent to drawable-inline-array-tfrag of tfrag.
|
||||
(deftype drawable-inline-array-instance-tie (drawable-inline-array)
|
||||
((data instance-tie 1 :inline :offset-assert 32)
|
||||
((data instance-tie 1 :inline :offset-assert 32) ;; dynamic sized
|
||||
(pad uint32 :offset-assert 96)
|
||||
)
|
||||
:method-count-assert 18
|
||||
@@ -51,6 +57,9 @@
|
||||
:flag-assert #x1200000064
|
||||
)
|
||||
|
||||
;; Top-level drawable tree for TIE instances.
|
||||
;; this is also a drawable-group, so it has a data array containing drawables.
|
||||
;; based on the login methods it seems like the data field has all the drawables.
|
||||
(deftype drawable-tree-instance-tie (drawable-tree)
|
||||
((prototypes proxy-prototype-array-tie :offset 8)
|
||||
)
|
||||
@@ -59,26 +68,30 @@
|
||||
:flag-assert #x1200000024
|
||||
)
|
||||
|
||||
;; Wrapper class for lists of consecutive prototypes.
|
||||
;; It's not known if these are proper draw-node BVH trees.
|
||||
;; you could imagine it being for things with only one instance (like generic stuff?)
|
||||
(deftype prototype-tie (drawable-inline-array)
|
||||
((data tie-fragment 1 :inline :offset-assert 32)
|
||||
(pad uint32)
|
||||
((data tie-fragment 1 :inline :offset-assert 32)
|
||||
(pad uint32 :offset-assert 96)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x64
|
||||
:flag-assert #x1200000064
|
||||
)
|
||||
|
||||
;; The actual matrix type we will upload to VU1 per instance.
|
||||
(deftype tie-matrix (structure)
|
||||
((mat matrix :inline :offset-assert 0)
|
||||
(morph qword :inline :offset-assert 64)
|
||||
(fog qword :inline :offset-assert 80)
|
||||
((mat matrix :inline :offset-assert 0) ;; the transformation matrix
|
||||
(morph qword :inline :offset-assert 64) ;; ? LOD stuff?
|
||||
(fog qword :inline :offset-assert 80) ;; ? why 4 values?
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x60
|
||||
:flag-assert #x900000060
|
||||
)
|
||||
|
||||
|
||||
;; Temps used in the instance drawing asm functions
|
||||
(deftype instance-tie-work (structure)
|
||||
((wind-const vector :inline :offset-assert 0)
|
||||
(hmge-d vector :inline :offset-assert 16)
|
||||
@@ -120,7 +133,7 @@
|
||||
:flag-assert #x9000001c0
|
||||
)
|
||||
|
||||
|
||||
;; DMA storage for instance dma generation (mapped to scratchpad)
|
||||
(deftype instance-tie-dma (structure)
|
||||
((banka instance-tie 32 :inline :offset-assert 0)
|
||||
(bankb instance-tie 32 :inline :offset-assert 2048)
|
||||
@@ -133,7 +146,7 @@
|
||||
:flag-assert #x900003000
|
||||
)
|
||||
|
||||
|
||||
;; temps used in the prototype drawing
|
||||
(deftype prototype-tie-work (structure)
|
||||
((upload-palette-0 dma-packet :inline :offset-assert 0)
|
||||
(upload-palette-1 dma-packet :inline :offset-assert 16)
|
||||
@@ -166,7 +179,7 @@
|
||||
:flag-assert #x900000134
|
||||
)
|
||||
|
||||
|
||||
;; DMA storage for prototype dma generation (mapped to scratchpad)
|
||||
(deftype prototype-tie-dma (structure)
|
||||
((colora rgba 256 :offset-assert 0)
|
||||
(colorb rgba 256 :offset-assert 1024)
|
||||
@@ -187,5 +200,5 @@
|
||||
|
||||
(define *instance-tie-work-copy* (the-as instance-tie-work #f))
|
||||
(define-extern *instance-tie-work* instance-tie-work)
|
||||
(define-extern tie-near-make-perspective-matrix (function matrix none))
|
||||
(define-extern draw-drawable-tree-instance-tie (function drawable-tree-instance-tie level none))
|
||||
(define-extern tie-near-make-perspective-matrix (function matrix matrix))
|
||||
(define-extern draw-drawable-tree-instance-tie (function drawable-tree-instance-tie level none))
|
||||
|
||||
@@ -5,6 +5,732 @@
|
||||
;; name in dgo: tie-methods
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(defun tie-init-buffers ((dma-buf dma-buffer))
|
||||
;; TODO stub.
|
||||
(defun tie-init-buffers ((arg0 dma-buffer))
|
||||
"Initialize the TIE buckets.
|
||||
Note: the buffer passed in here is _not_ used.
|
||||
this function should be called _after_ all TIE drawing is done.
|
||||
It will skip setup if there is nothing drawn."
|
||||
|
||||
;; the TIE buckets are only used by TIE - so we can safely splice things at the beginning/end without
|
||||
;; messing things up.
|
||||
(let ((gp-0 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-0))))
|
||||
;; only if we have something in the bucket.
|
||||
(when (!= gp-0 (-> gp-0 last))
|
||||
(let* ((s5-0 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-1 (-> s5-0 base))
|
||||
)
|
||||
;; add initialization data
|
||||
(tie-init-engine
|
||||
s5-0
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
0
|
||||
)
|
||||
;; patch to the start
|
||||
(let ((v1-8 (the-as object (-> s5-0 base))))
|
||||
(set! (-> (the-as dma-packet v1-8) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-0 next)))
|
||||
(set! (-> (the-as dma-packet v1-8) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-8) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-0 base) (&+ (the-as pointer v1-8) 16))
|
||||
)
|
||||
(set! (-> gp-0 next) (the-as uint s4-1))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(let ((gp-1 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-0))))
|
||||
;; only if we have something in teh bucket
|
||||
(when (!= gp-1 (-> gp-1 last))
|
||||
(let* ((s4-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-1 (-> s4-2 base))
|
||||
)
|
||||
;; add the end data at the end.
|
||||
(tie-end-buffer s4-2)
|
||||
(let ((v1-19 (-> s4-2 base)))
|
||||
(let ((a0-17 (the-as object (-> s4-2 base))))
|
||||
(set! (-> (the-as dma-packet a0-17) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-17) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-17) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-2 base) (&+ (the-as pointer a0-17) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-1 last)) 1) (the-as uint s5-1))
|
||||
(set! (-> gp-1 last) (the-as (pointer dma-tag) v1-19))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; same as above, but for level 1's tie.
|
||||
(let ((gp-2 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-1))))
|
||||
(when (!= gp-2 (-> gp-2 last))
|
||||
(let* ((s5-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-4 (-> s5-2 base))
|
||||
)
|
||||
(tie-init-engine
|
||||
s5-2
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
0
|
||||
)
|
||||
(let ((v1-28 (the-as object (-> s5-2 base))))
|
||||
(set! (-> (the-as dma-packet v1-28) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-2 next)))
|
||||
(set! (-> (the-as dma-packet v1-28) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-28) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-2 base) (&+ (the-as pointer v1-28) 16))
|
||||
)
|
||||
(set! (-> gp-2 next) (the-as uint s4-4))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-3 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-1))))
|
||||
(when (!= gp-3 (-> gp-3 last))
|
||||
(let* ((s4-5 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-3 (-> s4-5 base))
|
||||
)
|
||||
(tie-end-buffer s4-5)
|
||||
(let ((v1-39 (-> s4-5 base)))
|
||||
(let ((a0-36 (the-as object (-> s4-5 base))))
|
||||
(set! (-> (the-as dma-packet a0-36) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-36) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-36) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-5 base) (&+ (the-as pointer a0-36) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-3 last)) 1) (the-as uint s5-3))
|
||||
(set! (-> gp-3 last) (the-as (pointer dma-tag) v1-39))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
#|
|
||||
;; level 0's tie near
|
||||
(let ((gp-4 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-near-0))))
|
||||
(when (!= gp-4 (-> gp-4 last))
|
||||
(let* ((s5-4 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-7 (-> s5-4 base))
|
||||
)
|
||||
(tie-near-init-engine
|
||||
s5-4
|
||||
(new 'static 'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)
|
||||
)
|
||||
0
|
||||
)
|
||||
(let ((v1-48 (the-as object (-> s5-4 base))))
|
||||
(set! (-> (the-as dma-packet v1-48) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-4 next)))
|
||||
(set! (-> (the-as dma-packet v1-48) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-48) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-4 base) (&+ (the-as pointer v1-48) 16))
|
||||
)
|
||||
(set! (-> gp-4 next) (the-as uint s4-7))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-5 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-near-0))))
|
||||
(when (!= gp-5 (-> gp-5 last))
|
||||
(let* ((s4-8 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-5 (-> s4-8 base))
|
||||
)
|
||||
(tie-near-end-buffer s4-8)
|
||||
(let ((v1-59 (-> s4-8 base)))
|
||||
(let ((a0-55 (the-as object (-> s4-8 base))))
|
||||
(set! (-> (the-as dma-packet a0-55) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-55) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-55) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-8 base) (&+ (the-as pointer a0-55) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-5 last)) 1) (the-as uint s5-5))
|
||||
(set! (-> gp-5 last) (the-as (pointer dma-tag) v1-59))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; level 1's tie near
|
||||
(let ((gp-6 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-near-1))))
|
||||
(when (!= gp-6 (-> gp-6 last))
|
||||
(let* ((s5-6 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-10 (-> s5-6 base))
|
||||
)
|
||||
(tie-near-init-engine
|
||||
s5-6
|
||||
(new 'static 'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)
|
||||
)
|
||||
0
|
||||
)
|
||||
(let ((v1-68 (the-as object (-> s5-6 base))))
|
||||
(set! (-> (the-as dma-packet v1-68) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-6 next)))
|
||||
(set! (-> (the-as dma-packet v1-68) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-68) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-6 base) (&+ (the-as pointer v1-68) 16))
|
||||
)
|
||||
(set! (-> gp-6 next) (the-as uint s4-10))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-7 (-> *display* frames (-> *display* on-screen) frame bucket-group (bucket-id tie-near-1))))
|
||||
(when (!= gp-7 (-> gp-7 last))
|
||||
(let* ((s4-11 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-7 (-> s4-11 base))
|
||||
)
|
||||
(tie-near-end-buffer s4-11)
|
||||
(let ((v1-79 (-> s4-11 base)))
|
||||
(let ((a0-74 (the-as object (-> s4-11 base))))
|
||||
(set! (-> (the-as dma-packet a0-74) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-74) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-74) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-11 base) (&+ (the-as pointer a0-74) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-7 last)) 1) (the-as uint s5-7))
|
||||
(set! (-> gp-7 last) (the-as (pointer dma-tag) v1-79))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|#
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;
|
||||
;; TIE debug
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; most of this doesn't really do anything.
|
||||
|
||||
;; a ranges of instances to debug
|
||||
(deftype tie-instance-debug (structure)
|
||||
((max-instance uint32 :offset-assert 0)
|
||||
(min-instance uint32 :offset-assert 4)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x8
|
||||
:flag-assert #x900000008
|
||||
)
|
||||
|
||||
;; unused
|
||||
(define *tie* (new 'global 'tie-instance-debug))
|
||||
|
||||
(defun tie-debug-between ((arg0 uint) (arg1 uint))
|
||||
(set! (-> *instance-tie-work* test-id) arg1)
|
||||
(set! (-> *instance-tie-work* test-id2) arg0)
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun tie-debug-one ((arg0 uint) (arg1 uint))
|
||||
(set! (-> *instance-tie-work* test-id) (+ arg1 -1 arg0))
|
||||
(set! (-> *instance-tie-work* test-id2) arg0)
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun walk-tie-generic-prototypes ()
|
||||
(none)
|
||||
)
|
||||
|
||||
;; unused
|
||||
(define *pke-hack* (new 'global 'vector))
|
||||
|
||||
;; draw-inline-array-instance-tie
|
||||
;; draw-inline-array-prototype-tie-generic-asm
|
||||
;; draw-inline-array-prototype-tie-asm
|
||||
;; draw-inline-array-prototype-tie-near-asm
|
||||
|
||||
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
(if (nonzero? (-> obj prototypes prototype-array-tie))
|
||||
(login (-> obj prototypes prototype-array-tie))
|
||||
)
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defun draw-drawable-tree-instance-tie ((arg0 drawable-tree-instance-tie) (arg1 level))
|
||||
"Actually draw TIE instances.
|
||||
Will draw TIE, TIE-NEAR, and GENERIC"
|
||||
|
||||
;; todo kill
|
||||
(local-vars
|
||||
(r0-0 none)
|
||||
(a0-31 int)
|
||||
(a0-33 int)
|
||||
(a0-46 int)
|
||||
(a0-48 int)
|
||||
(a0-62 int)
|
||||
(a0-64 int)
|
||||
(a0-82 int)
|
||||
(a0-84 int)
|
||||
(sv-16 int)
|
||||
)
|
||||
|
||||
;; only if one of our renderers is enabled.
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near tie generic))
|
||||
;; setup work (TODO, what uses TIE wind?)
|
||||
(set! (-> *instance-tie-work* first-generic-prototype) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work* wind-vectors) (-> arg0 prototypes wind-vectors))
|
||||
|
||||
;;
|
||||
(let ((s4-0 (+ (-> arg0 length) -1))) ;; number of arrays of draw-nodes (depth of the BVH tree, not counting instance leaves)
|
||||
|
||||
;; perform draw node culling. TODO
|
||||
#|
|
||||
(when (nonzero? s4-0)
|
||||
(dotimes (s3-0 s4-0)
|
||||
(let* ((v1-10 (-> arg0 data s3-0))
|
||||
(a0-5 (-> arg0 data (+ s3-0 1)))
|
||||
(a1-2 (/ (-> (the-as drawable-inline-array-node v1-10) data 0 id) 8))
|
||||
(a0-7 (/ (-> (the-as drawable-inline-array-node a0-5) data 0 id) 8))
|
||||
(a1-4 (+ a1-2 #x38b0 #x70000000))
|
||||
(a0-9 (+ a0-7 #x38b0 #x70000000))
|
||||
)
|
||||
(draw-node-cull
|
||||
(the-as pointer a0-9)
|
||||
(the-as pointer a1-4)
|
||||
(-> (the-as drawable-inline-array-node v1-10) data)
|
||||
(-> (the-as drawable-inline-array-node v1-10) length)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|#
|
||||
|
||||
(let* ((v1-16 (-> arg0 data s4-0)) ;; leaves
|
||||
(s4-1 (-> arg0 prototypes prototype-array-tie)) ;; prototypes
|
||||
(s5-1 (-> s4-1 length)) ;; number of prototypes
|
||||
)
|
||||
|
||||
(dotimes (a0-11 s5-1) ;; loop over prototypes, zero stuff??
|
||||
(let ((a1-7 (-> s4-1 array-data a0-11)))
|
||||
(set! (-> a1-7 next-clear) (the-as uint128 0))
|
||||
(set! (-> a1-7 generic-count-clear) (the-as uint128 0))
|
||||
(set! (-> a1-7 generic-next-clear) (the-as uint128 0))
|
||||
)
|
||||
0
|
||||
)
|
||||
|
||||
(let* ((s1-0 (-> (the-as drawable-inline-array-instance-tie v1-16) data)) ;; the inline array of instances
|
||||
(s0-0 (&-> (scratchpad-object terrain-context) work background vis-list (/ (-> s1-0 0 id) 8))) ;; vis for first.
|
||||
(s3-1 (-> *display* frames (-> *display* on-screen) frame global-buf)) ;; dma buf to write to
|
||||
)
|
||||
(set! sv-16 (-> (the-as drawable-inline-array-node v1-16) length)) ;; number of instances
|
||||
|
||||
;; if we actually have things to draw
|
||||
(when (nonzero? sv-16)
|
||||
|
||||
;; this is some buffer for the generic renderer
|
||||
(let* ((v1-21 (logand (the-as int *gsf-buffer*) 8191))
|
||||
(v1-23 (logand (the-as int (&- (logand (the-as int (&-> (-> s4-1 data) -512)) 8191) (the-as uint v1-21))) 8191))
|
||||
)
|
||||
;; not sure why, but we'll use some gsf-buffer space to store an instance-tie-work
|
||||
;; all the external stuff will dump into *instance-tie-work*, and we'll make a copy that's used
|
||||
;; in the actual DMA generation code.
|
||||
(set! *instance-tie-work-copy* (the-as instance-tie-work (+ (the-as int *gsf-buffer*) v1-23)))
|
||||
)
|
||||
|
||||
|
||||
;;; TIE instance Drawing
|
||||
;; we do the instances first so the prototypes that aren't drawn can be skipped.
|
||||
(let ((s2-0 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
;; actually copy the work
|
||||
(quad-copy! (the-as pointer *instance-tie-work-copy*) (the-as pointer *instance-tie-work*) 28)
|
||||
;; clear perf counting stuff
|
||||
(set! (-> *instance-tie-work-copy* wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work-copy* wait-from-spr) (the-as uint 0))
|
||||
(reset! (-> *perf-stats* data 9))
|
||||
|
||||
;; DRAW!
|
||||
;;(draw-inline-array-instance-tie s0-0 s1-0 sv-16 s3-1)
|
||||
;; finish perf stats
|
||||
(read! (-> *perf-stats* data 9))
|
||||
(update-wait-stats (-> *perf-stats* data 9) (the-as uint 0)
|
||||
(-> *instance-tie-work-copy* wait-to-spr)
|
||||
(-> *instance-tie-work-copy* wait-from-spr))
|
||||
|
||||
;; copy out things from instance tie work
|
||||
(let ((v1-42 (-> *instance-tie-work-copy* min-dist quad)))
|
||||
(set! (-> *instance-tie-work* min-dist quad) v1-42)
|
||||
)
|
||||
(set! (-> *instance-tie-work* flags) (-> *instance-tie-work-copy* flags))
|
||||
|
||||
;; update memory usage
|
||||
(let ((a0-38 *dma-mem-usage*))
|
||||
(when (nonzero? a0-38)
|
||||
(set! (-> a0-38 length) (max 10 (-> a0-38 length)))
|
||||
(set! (-> a0-38 data 9 name) "tie-fragment")
|
||||
(+! (-> a0-38 data 9 count) 1)
|
||||
(+! (-> a0-38 data 9 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s2-0))
|
||||
)
|
||||
(set! (-> a0-38 data 9 total) (-> a0-38 data 9 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Generic TIE prototype drawing
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
(when (logtest? (-> *instance-tie-work* flags) 2)
|
||||
(let ((s2-1 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(set! (-> *prototype-tie-work* generic-wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* generic-wait-from-spr) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work* first-generic-prototype) (the-as uint (-> s3-1 base)))
|
||||
|
||||
(reset! (-> *perf-stats* data 10))
|
||||
;;(draw-inline-array-prototype-tie-generic-asm s3-1 s5-1 s4-1)
|
||||
(read! (-> *perf-stats* data 10))
|
||||
(update-wait-stats (-> *perf-stats* data 10) (the-as uint 0)
|
||||
(-> *prototype-tie-work* generic-wait-to-spr)
|
||||
(-> *prototype-tie-work* generic-wait-from-spr)
|
||||
)
|
||||
;; Note: we don't add to a bucket. This lives in some buffer somewhere and generic will take care of actually adding it.
|
||||
(let ((a0-51 *dma-mem-usage*))
|
||||
(when (nonzero? a0-51)
|
||||
(set! (-> a0-51 length) (max 18 (-> a0-51 length)))
|
||||
(set! (-> a0-51 data 17 name) "tie-generic")
|
||||
(+! (-> a0-51 data 17 count) 1)
|
||||
(+! (-> a0-51 data 17 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s2-1))
|
||||
)
|
||||
(set! (-> a0-51 data 17 total) (-> a0-51 data 17 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Normal TIE prototype drawing
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let ((s3-2 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let* ((s1-1 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s2-2 (-> s1-1 base))
|
||||
)
|
||||
(set! (-> *prototype-tie-work* wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* wait-from-spr) (the-as uint 0))
|
||||
(reset! (-> *perf-stats* data 11))
|
||||
;;(draw-inline-array-prototype-tie-asm s1-1 s5-1 s4-1)
|
||||
(add-pc-tfrag3-data s1-1 (-> *level* data (-> (scratchpad-object terrain-context) bsp lev-index)))
|
||||
(read! (-> *perf-stats* data 11))
|
||||
(update-wait-stats (-> *perf-stats* data 11) (the-as uint 0)
|
||||
(-> *prototype-tie-work* wait-to-spr)
|
||||
(-> *prototype-tie-work* wait-from-spr)
|
||||
)
|
||||
|
||||
;; this actually generates real drawing DMA, so add it to the appropriate bucket.
|
||||
(let ((a3-11 (-> s1-1 base)))
|
||||
(let ((v1-94 (the-as object (-> s1-1 base))))
|
||||
(set! (-> (the-as dma-packet v1-94) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet v1-94) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-94) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s1-1 base) (&+ (the-as pointer v1-94) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
(the-as bucket-id (if (zero? (-> arg1 index))
|
||||
(bucket-id tie-0)
|
||||
(bucket-id tie-1)
|
||||
)
|
||||
)
|
||||
s2-2
|
||||
(the-as (pointer dma-tag) a3-11)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((v1-100 *dma-mem-usage*))
|
||||
(when (nonzero? v1-100)
|
||||
(set! (-> v1-100 length) (max 10 (-> v1-100 length)))
|
||||
(set! (-> v1-100 data 9 name) "tie-fragment")
|
||||
(+! (-> v1-100 data 9 count) 1)
|
||||
(+! (-> v1-100 data 9 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s3-2))
|
||||
)
|
||||
(set! (-> v1-100 data 9 total) (-> v1-100 data 9 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
#|
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(let ((s3-3 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(let* ((s1-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s2-3 (-> s1-2 base))
|
||||
)
|
||||
(set! (-> *prototype-tie-work* near-wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* near-wait-from-spr) (the-as uint 0))
|
||||
(reset! (-> *perf-stats* data 12))
|
||||
;;(draw-inline-array-prototype-tie-near-asm s1-2 s5-1 s4-1)
|
||||
(read! (-> *perf-stats* data 12))
|
||||
(update-wait-stats (-> *perf-stats* data 12) (the-as uint 0)
|
||||
(-> *prototype-tie-work* near-wait-to-spr)
|
||||
(-> *prototype-tie-work* near-wait-from-spr)
|
||||
)
|
||||
(let ((a3-16 (-> s1-2 base)))
|
||||
(let ((v1-123 (the-as object (-> s1-2 base))))
|
||||
(set! (-> (the-as dma-packet v1-123) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet v1-123) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-123) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s1-2 base) (&+ (the-as pointer v1-123) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
(the-as bucket-id (if (zero? (-> arg1 index))
|
||||
(bucket-id tie-near-0)
|
||||
(bucket-id tie-near-1)
|
||||
)
|
||||
)
|
||||
s2-3
|
||||
(the-as (pointer dma-tag) a3-16)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((a0-92 *dma-mem-usage*))
|
||||
(when (nonzero? a0-92)
|
||||
(set! (-> a0-92 length) (max 16 (-> a0-92 length)))
|
||||
(set! (-> a0-92 data 15 name) "tie-near")
|
||||
(+! (-> a0-92 data 15 count) 1)
|
||||
(+! (-> a0-92 data 15 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s3-3))
|
||||
)
|
||||
(set! (-> a0-92 data 15 total) (-> a0-92 data 15 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)|#
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
)
|
||||
(set! (-> arg1 closest-object 5) (-> *instance-tie-work* min-dist x))
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod draw drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 drawable-tree-instance-tie) (arg1 display-frame))
|
||||
"Add the tree to the background work list."
|
||||
(let* ((v1-1 (-> *background-work* tie-tree-count))
|
||||
(a1-2 (-> (scratchpad-object terrain-context) bsp lev-index))
|
||||
(a1-5 (-> *level* level a1-2))
|
||||
)
|
||||
(set! (-> *background-work* tie-trees v1-1) obj)
|
||||
(set! (-> *background-work* tie-levels v1-1) a1-5)
|
||||
)
|
||||
(+! (-> *background-work* tie-tree-count) 1)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod collect-stats drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
"Collect statistics on TIE drawing."
|
||||
|
||||
;; only if tie/generic ran
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near tie generic))
|
||||
;; unused?
|
||||
(-> obj data (+ (-> obj length) -1))
|
||||
|
||||
;; loop over all prototypes.
|
||||
;; the drawing process will write to the prototypes to say how many of each it draws
|
||||
(let ((v1-8 (-> obj prototypes prototype-array-tie)))
|
||||
(dotimes (a0-1 (-> v1-8 length))
|
||||
;; grap the prototype
|
||||
(let ((a1-2 (-> v1-8 array-data a0-1)))
|
||||
|
||||
;; GENERIC
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
;; there are 4 arrays of fragments per prototype. Looks like we check them all for generic.
|
||||
(let ((a2-3 0)
|
||||
(a3-0 3)
|
||||
)
|
||||
(while (>= a3-0 a2-3)
|
||||
(let ((t0-2 (-> a1-2 generic-count a2-3)) ;; number of times this geom was drawn with generic
|
||||
(t2-0 (-> a1-2 geometry-override a2-3)) ;; the geom that was drawn
|
||||
)
|
||||
(when (nonzero? t0-2) ;; were we drawn?
|
||||
(let ((t1-3 (the-as object (-> t2-0 data))) ;; tie fragment array
|
||||
(t2-1 (-> t2-0 length)) ;; number of tie fragments
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-generic groups) 1) ;; number of geometries drawn (unique)
|
||||
(+! (-> *terrain-stats* tie-generic fragments) t2-1) ;; number of frags drawn (unique)
|
||||
(+! (-> *terrain-stats* tie-generic instances) t0-2) ;; number of instances drawn (not unique)
|
||||
|
||||
;; now, collect stats per fragment
|
||||
(dotimes (t3-9 t2-1)
|
||||
(let ((t5-0 (* (-> (the-as tie-fragment t1-3) num-tris) t0-2)) ;; multiply by number of instances
|
||||
(t4-5 (* (-> (the-as tie-fragment t1-3) num-dverts) t0-2))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-generic tris) t5-0)
|
||||
(+! (-> *terrain-stats* tie-generic dverts) t4-5)
|
||||
)
|
||||
(set! t1-3 (&+ (the-as tie-fragment t1-3) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! a2-3 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; normal tie
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let ((a2-9 1) ;; looks like we never draw geom 0's with normal tie?
|
||||
(a3-1 3)
|
||||
)
|
||||
(while (>= a3-1 a2-9)
|
||||
(let ((t0-6 (-> a1-2 count a2-9))
|
||||
(t2-2 (-> a1-2 geometry-override a2-9))
|
||||
)
|
||||
(when (nonzero? t0-6)
|
||||
(let ((t1-8 (the-as object (-> t2-2 data)))
|
||||
(t2-3 (-> t2-2 length))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie groups) 1)
|
||||
(+! (-> *terrain-stats* tie fragments) t2-3)
|
||||
(+! (-> *terrain-stats* tie instances) t0-6)
|
||||
(dotimes (t3-19 t2-3)
|
||||
(let ((t5-5 (* (-> (the-as tie-fragment t1-8) num-tris) t0-6))
|
||||
(t4-12 (* (-> (the-as tie-fragment t1-8) num-dverts) t0-6))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie tris) t5-5)
|
||||
(+! (-> *terrain-stats* tie dverts) t4-12)
|
||||
)
|
||||
(set! t1-8 (&+ (the-as tie-fragment t1-8) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! a2-9 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; near tie
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(let ((a2-14 (-> a1-2 count 0)) ;; always geom 0.
|
||||
(a3-2 (-> a1-2 geometry-override 0))
|
||||
)
|
||||
(when (nonzero? a2-14)
|
||||
(let ((a1-3 (the-as object (-> a3-2 data)))
|
||||
(a3-3 (-> a3-2 length))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-near groups) 1)
|
||||
(+! (-> *terrain-stats* tie-near fragments) a3-3)
|
||||
(+! (-> *terrain-stats* tie-near instances) a2-14)
|
||||
(dotimes (t0-19 a3-3)
|
||||
(let ((t2-4 (* (-> (the-as tie-fragment a1-3) num-tris) a2-14))
|
||||
(t1-15 (* (-> (the-as tie-fragment a1-3) num-dverts) a2-14))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-near tris) t2-4)
|
||||
(+! (-> *terrain-stats* tie-near dverts) t1-15)
|
||||
)
|
||||
(set! a1-3 (&+ (the-as tie-fragment a1-3) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
(defmethod debug-draw drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 drawable) (arg1 display-frame))
|
||||
(-> obj data (+ (-> obj length) -1))
|
||||
(let* ((s5-0 (-> obj prototypes prototype-array-tie))
|
||||
(s4-0 (-> s5-0 length))
|
||||
)
|
||||
(dotimes (s3-0 s4-0)
|
||||
(let ((a1-1 (-> s5-0 array-data s3-0 geometry 0)))
|
||||
(debug-draw a1-1 a1-1 arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;
|
||||
;; TIE collision
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; note: the first three methods appear twice in the original code.
|
||||
|
||||
(defmethod collide-with-box drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-with-box (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod collide-y-probe drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-y-probe (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod collide-ray drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-ray (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
(defmethod collide-with-box drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-with-box (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod collide-y-probe drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-y-probe (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod collide-ray drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-ray (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun tie-test-cam-restore ()
|
||||
(let ((a0-0 (new-stack-vector0))
|
||||
(a1-0 (new-stack-matrix0))
|
||||
)
|
||||
(set! (-> a0-0 x) 1246582.6)
|
||||
(set! (-> a0-0 y) 57026.02)
|
||||
(set! (-> a0-0 z) -490734.78)
|
||||
(set! (-> a0-0 w) 1.0)
|
||||
(set! (-> a1-0 vector 0 x) -0.9873)
|
||||
(set! (-> a1-0 vector 0 y) 0.0)
|
||||
(set! (-> a1-0 vector 0 z) -0.1587)
|
||||
(set! (-> a1-0 vector 0 w) 0.0)
|
||||
(set! (-> a1-0 vector 1 x) 0.0014)
|
||||
(set! (-> a1-0 vector 1 y) 0.9999)
|
||||
(set! (-> a1-0 vector 1 z) -0.0092)
|
||||
(set! (-> a1-0 vector 1 w) 0.0)
|
||||
(set! (-> a1-0 vector 2 x) 0.1587)
|
||||
(set! (-> a1-0 vector 2 y) -0.0093)
|
||||
(set! (-> a1-0 vector 2 z) -0.9872)
|
||||
(set! (-> a1-0 vector 2 w) 0.0)
|
||||
(set! (-> a1-0 vector 3 x) 0.0)
|
||||
(set! (-> a1-0 vector 3 y) 0.0)
|
||||
(set! (-> a1-0 vector 3 z) 0.0)
|
||||
(set! (-> a1-0 vector 3 w) 1.0)
|
||||
(debug-set-camera-pos-rot! a0-0 a1-0)
|
||||
)
|
||||
(send-event *camera* 'set-fov 11650.845)
|
||||
(none)
|
||||
)
|
||||
@@ -5,3 +5,268 @@
|
||||
;; name in dgo: tie-near
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; The "near" version of TIE.
|
||||
;; This correctly handles scissoring triangles.
|
||||
;; Like tfrag near, we plan to not port this because it's complicated, and instead let opengl do
|
||||
;; the hard work for us.
|
||||
|
||||
;; This isn't super well documented or even complete, see tie.gc.
|
||||
|
||||
;; uploaded to VU1 once per frame.
|
||||
(deftype tie-near-consts (structure)
|
||||
((extra qword :inline :offset-assert 0)
|
||||
(gifbufs qword :inline :offset-assert 16)
|
||||
(clrbufs qword :inline :offset-assert 32)
|
||||
(adgif gs-gif-tag :inline :offset-assert 48)
|
||||
(strgif gs-gif-tag :inline :offset-assert 64)
|
||||
(fangif gs-gif-tag :inline :offset-assert 80)
|
||||
(hvdfoffs vector :inline :offset-assert 96)
|
||||
(invhscale vector :inline :offset-assert 112)
|
||||
(guard vector :inline :offset-assert 128)
|
||||
(atest ad-cmd 2 :inline :offset-assert 144)
|
||||
(atest-tra ad-cmd :inline :offset 144)
|
||||
(atest-def ad-cmd :inline :offset 160)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xb0
|
||||
:flag-assert #x9000000b0
|
||||
)
|
||||
|
||||
;; the actual program.
|
||||
(define tie-near-vu1-block (new 'static 'vu-function :length #x6f8 :qlength #x37c))
|
||||
|
||||
(defun tie-near-init-consts ((arg0 tie-near-consts) (arg1 int))
|
||||
"Initialize tie near constant data."
|
||||
(set! (-> arg0 adgif tag) (new 'static 'gif-tag64 :nloop #x5 :nreg #x1))
|
||||
(set! (-> arg0 adgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(set! (-> arg0 atest-tra cmds) (the-as uint 71))
|
||||
(set! (-> arg0 atest-tra data) (the-as uint #x5026b))
|
||||
(set! (-> arg0 atest-def cmds) (the-as uint 71))
|
||||
(set! (-> arg0 atest-def data) (the-as uint #x5000e))
|
||||
(cond
|
||||
((zero? *subdivide-draw-mode*)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 3)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1)
|
||||
:nreg #x3
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 1)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type line-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 2)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 strgif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
(set! (-> arg0 fangif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 fangif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
(let ((f1-0 8388894.0)
|
||||
(f2-0 8389078.0)
|
||||
(f0-0 8389262.0)
|
||||
)
|
||||
(set! (-> arg0 gifbufs vector4w x) (the-as int f0-0))
|
||||
(set! (-> arg0 gifbufs vector4w y) (the-as int f2-0))
|
||||
(set! (-> arg0 gifbufs vector4w z) (the-as int f0-0))
|
||||
(set! (-> arg0 gifbufs vector4w w) (the-as int f2-0))
|
||||
(set! (-> arg0 extra vector4w x) (the-as int (+ f1-0 f2-0 f0-0)))
|
||||
(set! (-> arg0 extra vector4w y) (the-as int 0.0))
|
||||
(set! (-> arg0 extra vector4w z) (the-as int (+ f1-0 f2-0 f0-0)))
|
||||
)
|
||||
(set! (-> arg0 clrbufs vector4w x) 198)
|
||||
(set! (-> arg0 clrbufs vector4w y) 242)
|
||||
(set! (-> arg0 clrbufs vector4w z) 198)
|
||||
(set! (-> arg0 clrbufs vector4w w) 242)
|
||||
(let ((v1-41 *math-camera*))
|
||||
(set! (-> arg0 invhscale quad) (-> v1-41 inv-hmge-scale quad))
|
||||
(set! (-> arg0 hvdfoffs quad) (-> v1-41 hvdf-off quad))
|
||||
(set! (-> arg0 guard quad) (-> v1-41 guard quad))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; SKIPPED tie-near-init-engine
|
||||
;; SKIPPED tie-near-end-buffer
|
||||
|
||||
(defun tie-near-make-perspective-matrix ((arg0 matrix))
|
||||
(column-scale-matrix! arg0 (-> *math-camera* hmge-scale) (-> *math-camera* camera-temp))
|
||||
)
|
||||
|
||||
(defun tie-near-int-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"itemp"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"delta"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"dest-0"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"dest-1"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"dest-2"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"dest-3"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"delta-ptr"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"prev"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"itemp2"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun tie-near-float-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"vtx-0"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"vtx-1"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"vtx-2"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"vtx-3"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"hvtx-0"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"hvtx-1"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"hvtx-2"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"hvtx-3"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"tex-0"
|
||||
)
|
||||
((= v1-0 10)
|
||||
"tex-1"
|
||||
)
|
||||
((= v1-0 11)
|
||||
"tex-2"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"tex-3"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"deltas"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"invh"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"hvdfcl"
|
||||
)
|
||||
((= v1-0 16)
|
||||
"hvdfnc"
|
||||
)
|
||||
((= v1-0 17)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 18)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 21)
|
||||
"gifbuf"
|
||||
)
|
||||
((= v1-0 22)
|
||||
"clrbuf"
|
||||
)
|
||||
((= v1-0 23)
|
||||
"extra"
|
||||
)
|
||||
((= v1-0 24)
|
||||
"inds"
|
||||
)
|
||||
((= v1-0 25)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 26)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 27)
|
||||
"morph"
|
||||
)
|
||||
((= v1-0 28)
|
||||
"xyzofs"
|
||||
)
|
||||
((= v1-0 29)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 30)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 31)
|
||||
"--"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
+109
-186
@@ -6,199 +6,122 @@
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; definition for symbol *instance-tie-work*, type instance-tie-work
|
||||
(define
|
||||
*instance-tie-work*
|
||||
(new 'static 'instance-tie-work
|
||||
:wind-const
|
||||
(new 'static 'vector :x 0.5 :y 100.0 :z 0.0166 :w -1.0)
|
||||
:constant
|
||||
(new 'static 'vector :x 4096.0 :y 128.0)
|
||||
:far-morph (new 'static 'vector :x 1.0 :w 256.0)
|
||||
:upload-color-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :qwc #x6 :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x80c6 :num #x6 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-color-1
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #xc0cc :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-color-2
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id next))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
)
|
||||
:upload-color-ret
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ret))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
)
|
||||
:generic-color-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :qwc #x6 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x3)
|
||||
)
|
||||
:generic-color-1
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-color-end
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id end)))
|
||||
:refl-fade-fac -0.000625
|
||||
:refl-fade-end 409600.0
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *instance-tie-work* upload-color-2 vif1)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
;; helpful constants for the instance drawing EE asm.
|
||||
(define *instance-tie-work*
|
||||
(new 'static 'instance-tie-work
|
||||
:wind-const (new 'static 'vector :x 0.5 :y 100.0 :z 0.0166 :w -1.0)
|
||||
:constant (new 'static 'vector :x 4096.0 :y 128.0)
|
||||
:far-morph (new 'static 'vector :x 1.0 :w 256.0)
|
||||
:upload-color-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x6 :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x80c6 :num #x6 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-color-1 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1 (new 'static 'vif-tag :imm #xc0cc :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-color-2 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id next))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
)
|
||||
:upload-color-ret (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ret))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
)
|
||||
:generic-color-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x6 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x3)
|
||||
)
|
||||
:generic-color-1 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-color-end (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id end)))
|
||||
:refl-fade-fac -0.000625
|
||||
:refl-fade-end 409600.0
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *instance-tie-work* upload-color-ret vif1)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
(set! (-> *instance-tie-work* upload-color-2 vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1))
|
||||
(set! (-> *instance-tie-work* upload-color-ret vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1))
|
||||
|
||||
;; definition for symbol *prototype-tie-work*, type prototype-tie-work
|
||||
(define
|
||||
*prototype-tie-work*
|
||||
(new 'static 'prototype-tie-work
|
||||
:upload-palette-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id cnt))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1)
|
||||
)
|
||||
:upload-palette-1
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :qwc #x20 :id (dma-tag-id cnt))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :imm #x1 :cmd (vif-cmd stmod))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x4346 :num #x80 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-model-1
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x4000 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-2
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x32 :cmd (vif-cmd unpack-v4-16))
|
||||
)
|
||||
:upload-model-3
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id call)))
|
||||
:upload-model-near-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-model-near-1
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x4000 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-near-2
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x1e :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-near-3
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1
|
||||
(new 'static 'vif-tag :imm #x32 :cmd (vif-cmd unpack-v4-16))
|
||||
)
|
||||
:upload-model-near-4
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id call)))
|
||||
:generic-envmap-shader
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :qwc #x5 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x1)
|
||||
)
|
||||
:generic-palette
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :qwc #x20 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x1)
|
||||
)
|
||||
:generic-model-0
|
||||
(new 'static 'dma-packet
|
||||
:dma
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x2)
|
||||
)
|
||||
:generic-model-1
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-model-2
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-model-next
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
:clamp #x8000ff00ff00ff
|
||||
)
|
||||
)
|
||||
;; helpful constants for the prototype drawing EE asm
|
||||
(define *prototype-tie-work*
|
||||
(new 'static 'prototype-tie-work
|
||||
:upload-palette-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1)
|
||||
)
|
||||
:upload-palette-1 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x20 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x1 :cmd (vif-cmd stmod))
|
||||
:vif1 (new 'static 'vif-tag :imm #x4346 :num #x80 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1 (new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-model-1 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x4000 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-2 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x32 :cmd (vif-cmd unpack-v4-16))
|
||||
)
|
||||
:upload-model-3 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id call)))
|
||||
:upload-model-near-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :cmd (vif-cmd stmod))
|
||||
:vif1 (new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:upload-model-near-1 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x4000 :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-near-2 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x1e :cmd (vif-cmd unpack-v4-8))
|
||||
)
|
||||
:upload-model-near-3 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif1 (new 'static 'vif-tag :imm #x32 :cmd (vif-cmd unpack-v4-16))
|
||||
)
|
||||
:upload-model-near-4 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id call)))
|
||||
:generic-envmap-shader (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x5 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x1)
|
||||
)
|
||||
:generic-palette (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x20 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x1)
|
||||
)
|
||||
:generic-model-0 (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x2)
|
||||
)
|
||||
:generic-model-1 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-model-2 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id ref)))
|
||||
:generic-model-next (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
:clamp #x8000ff00ff00ff
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *prototype-tie-work* upload-model-1 vif0)
|
||||
(new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
(set! (-> *prototype-tie-work* upload-model-1 vif0)
|
||||
(new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *prototype-tie-work* upload-model-3 vif0)
|
||||
(new 'static 'vif-tag :imm #x6 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
(set! (-> *prototype-tie-work* upload-model-3 vif0)
|
||||
(new 'static 'vif-tag :imm #x6 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *prototype-tie-work* upload-model-near-1 vif0)
|
||||
(new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
(set! (-> *prototype-tie-work* upload-model-near-1 vif0)
|
||||
(new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *prototype-tie-work* upload-model-near-4 vif0)
|
||||
(new 'static 'vif-tag :imm #x6 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
(set! (-> *prototype-tie-work* upload-model-near-4 vif0)
|
||||
(new 'static 'vif-tag :imm #x6 :cmd (vif-cmd mscal) :msk #x1)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,811 @@
|
||||
;; name in dgo: tie
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
|
||||
;; TIE
|
||||
;; tesselating fragment instance engine
|
||||
|
||||
;; The TIE renderer is one of three main background renderers.
|
||||
;; TIE has the following features:
|
||||
;; - instanced rendering (you can draw the same thing multiple times!)
|
||||
;; - time of day lighting (believed to be slightly different in implementation than tfrag)
|
||||
|
||||
|
||||
;; Background elements that use the GENERIC render will store their data in tie-fragments.
|
||||
;; The exact procedure for GENERIC through TIE is unknown.
|
||||
;; The functions are generic-tie-execute and generic-tie-convert
|
||||
|
||||
;;;;;;;;;;;;;;;;;
|
||||
;; Basic Methods
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; something is going wrong mem-usage (believed fixed)
|
||||
|
||||
(defmethod login tie-fragment ((obj tie-fragment))
|
||||
"Initialize the shaders for a tie-fragment"
|
||||
|
||||
;; the gif data is just adgif shaders, each are 5 qw's
|
||||
(let ((s5-0 (-> obj gif-ref))
|
||||
(s4-0 (/ (-> obj tex-count) (the-as uint 5)))
|
||||
)
|
||||
(dotimes (s3-0 (the-as int s4-0))
|
||||
;; will modify the adgif-shaders in place to have the appropriate tbp.
|
||||
(adgif-shader-login-no-remap (-> s5-0 s3-0))
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod inspect drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie))
|
||||
"Inspect an array of instances"
|
||||
(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 asize-of drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie))
|
||||
"Compute the size in memory of an array of instances."
|
||||
(the-as int (+ (-> drawable-inline-array-instance-tie size)
|
||||
(* (+ (-> obj length) -1) 64) ;; 64 bytes / instance, minus the 1 in the type.
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
#|
|
||||
;; for some reason, this showed up twice.
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
obj
|
||||
)
|
||||
|#
|
||||
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
"Login method for the tie instance tree."
|
||||
;; just log in all of the drawables.
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
(the-as drawable-tree-instance-tie #f)
|
||||
)
|
||||
|
||||
(defmethod inspect prototype-tie ((obj prototype-tie))
|
||||
"Inspect the inline-array of tie"
|
||||
(format #t "[~8x] ~A~%" obj (-> obj type))
|
||||
(format #t "~Tlength: ~D~%" (-> obj length))
|
||||
(format #t "~Tdata[~D]: @ #x~X~%" (-> obj length) (-> obj data))
|
||||
;; print each fragment
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(format #t "~T [~D] ~A~%" s5-0 (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod login prototype-tie ((obj prototype-tie))
|
||||
"Login each tie-fragment."
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute memory usage for a drawable tree of TIE instances"
|
||||
(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)))
|
||||
)
|
||||
|
||||
;; do our drawables
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj data s3-0) arg0 arg1)
|
||||
)
|
||||
|
||||
;; do our prototypes, but with a flag set!
|
||||
(mem-usage (-> obj prototypes prototype-array-tie) arg0 (logior arg1 1))
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage tie-fragment ((obj tie-fragment) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory usage of a TIE prototype."
|
||||
(when (logtest? arg1 2)
|
||||
;; count for an instance of this prototype.
|
||||
(let ((v1-3 (* (-> obj color-count) 4))
|
||||
;; pick one of the instance color categories.
|
||||
(a0-2 (cond
|
||||
((logtest? arg1 4)
|
||||
20
|
||||
)
|
||||
((logtest? arg1 8)
|
||||
21
|
||||
)
|
||||
(else
|
||||
22
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! (-> arg0 data a0-2 count) 1)
|
||||
(+! (-> arg0 data a0-2 used) v1-3)
|
||||
(+! (-> arg0 data a0-2 total) (logand -4 (+ v1-3 3)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 23 (-> arg0 length)))
|
||||
(set! obj obj)
|
||||
(goto cfg-13)
|
||||
)
|
||||
|
||||
;; not an instance, count the memory of the prototype.
|
||||
(set! (-> arg0 length) (max 18 (-> arg0 length)))
|
||||
(set! (-> arg0 data 9 name) "tie-fragment")
|
||||
(set! (-> arg0 data 10 name) "tie-gif")
|
||||
(set! (-> arg0 data 11 name) "tie-points")
|
||||
(set! (-> arg0 data 12 name) "tie-colors")
|
||||
(set! (-> arg0 data 14 name) "tie-debug")
|
||||
(set! (-> arg0 data 13 name) "tie-draw-points")
|
||||
(set! (-> arg0 data 17 name) "tie-generic")
|
||||
(+! (-> arg0 data 9 count) 1)
|
||||
(let ((v1-21 (asize-of obj)))
|
||||
(+! (-> arg0 data 9 used) v1-21)
|
||||
(+! (-> arg0 data 9 total) (logand -16 (+ v1-21 15)))
|
||||
)
|
||||
(let ((v1-26 (* (-> obj gif-count) 16)))
|
||||
(+! (-> arg0 data 10 count) (-> obj tex-count))
|
||||
(+! (-> arg0 data 10 used) v1-26)
|
||||
(+! (-> arg0 data 10 total) (logand -16 (+ v1-26 15)))
|
||||
)
|
||||
(let ((v1-31 (* (-> obj vertex-count) 16)))
|
||||
(+! (-> arg0 data 11 count) (-> obj vertex-count))
|
||||
(+! (-> arg0 data 11 used) v1-31)
|
||||
(+! (-> arg0 data 11 total) (logand -16 (+ v1-31 15)))
|
||||
)
|
||||
(let ((v1-36 (* (-> obj dp-qwc) 16)))
|
||||
(+! (-> arg0 data 13 count) (* (-> obj dp-qwc) 16))
|
||||
(+! (-> arg0 data 13 used) v1-36)
|
||||
(+! (-> arg0 data 13 total) (logand -16 (+ v1-36 15)))
|
||||
)
|
||||
(let ((v1-41 (* (-> obj generic-count) 16)))
|
||||
(+! (-> arg0 data 17 count) 1)
|
||||
(+! (-> arg0 data 17 used) v1-41)
|
||||
(+! (-> arg0 data 17 total) (logand -16 (+ v1-41 15)))
|
||||
)
|
||||
(when (nonzero? (-> obj debug-lines))
|
||||
(dotimes (s4-0 (-> obj debug-lines length))
|
||||
(+!
|
||||
(-> arg0 data 14 count)
|
||||
(-> (the-as (pointer int32) (-> obj debug-lines s4-0)) 0)
|
||||
)
|
||||
(let ((v1-52 (asize-of (the-as basic (-> obj debug-lines s4-0)))))
|
||||
(+! (-> arg0 data 12 used) v1-52)
|
||||
(+! (-> arg0 data 12 total) (logand -16 (+ v1-52 15)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(label cfg-13)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage instance-tie ((obj instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory usage of TIE instance."
|
||||
(set! (-> arg0 length) (max 19 (-> arg0 length)))
|
||||
(set! (-> arg0 data 18 name) "instance-tie")
|
||||
(+! (-> arg0 data 18 count) 1)
|
||||
(let ((v1-6 (asize-of obj)))
|
||||
(+! (-> arg0 data 18 used) v1-6)
|
||||
(+! (-> arg0 data 18 total) (logand -16 (+ v1-6 15)))
|
||||
)
|
||||
(when (nonzero? (-> obj error))
|
||||
(set! (-> arg0 length) (max 24 (-> arg0 length)))
|
||||
(set! (-> arg0 data 23 name) "instance-tie-colors*")
|
||||
(set! (-> arg0 data 19 name) "instance-tie-colors0")
|
||||
(set! (-> arg0 data 20 name) "instance-tie-colors1")
|
||||
(set! (-> arg0 data 21 name) "instance-tie-colors2")
|
||||
(set! (-> arg0 data 22 name) "instance-tie-colors3")
|
||||
(+! (-> arg0 data 23 count) 1)
|
||||
(let ((s3-0 (-> obj bucket-ptr)))
|
||||
;; unused
|
||||
(+ (-> arg0 data 19 used) (-> arg0 data 20 used) (-> arg0 data 21 used) (-> arg0 data 22 used))
|
||||
|
||||
;; loop over all 4 possible geometries
|
||||
(dotimes (s2-0 4)
|
||||
(let ((a0-10 (-> s3-0 geometry-override s2-0)))
|
||||
(when (nonzero? a0-10) ;; only if we actually have it.
|
||||
(mem-usage a0-10 arg0
|
||||
(logior (logior (cond ;; based on which geom we are, pick the right color bucket.
|
||||
((= s2-0 1) 4)
|
||||
((= s2-0 2) 8)
|
||||
((= s2-0 3) 16)
|
||||
(else 0)
|
||||
)
|
||||
2 ;; set so we count it as an instance of a prototype.
|
||||
)
|
||||
arg1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory usage of an entire array of instances"
|
||||
(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)))
|
||||
)
|
||||
;; just call mem-usage on every element.
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj data s3-0) arg0 arg1)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod mem-usage prototype-tie ((obj prototype-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
"Compute the memory usage of an entire array of prototypes."
|
||||
(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)))
|
||||
)
|
||||
;; just call mem-usage on each.
|
||||
(dotimes (s3-0 (-> obj length))
|
||||
(mem-usage (-> obj data s3-0) arg0 arg1)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
(defmethod asize-of prototype-tie ((obj prototype-tie))
|
||||
"Compute the size in memory of a prototype array"
|
||||
;; 64 bytes/fragment, minus 1 in the type.
|
||||
(the-as int (+ (-> prototype-tie size) (* (+ (-> obj length) -1) 64)))
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TIE Renderer
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; these constants are uploaded to the VU once per frame.
|
||||
(deftype tie-consts (structure)
|
||||
((data uint32 24 :offset-assert 0)
|
||||
(vector vector 6 :inline :offset 0)
|
||||
(quads uint128 6 :offset 0)
|
||||
(adgif gs-gif-tag :inline :offset 0) ;; was qword
|
||||
(strgif gs-gif-tag :inline :offset 16) ;; was qword
|
||||
(extra vector :inline :offset 32) ;; was qword
|
||||
(gifbufs vector :inline :offset 48) ;; was qword
|
||||
(clrbufs qword :inline :offset 64)
|
||||
(misc qword :inline :offset 80)
|
||||
(atestgif gs-gif-tag :inline :offset 96)
|
||||
(atest ad-cmd 2 :inline :offset 112)
|
||||
(atest-tra ad-cmd :inline :offset 112)
|
||||
(atest-def ad-cmd :inline :offset 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x90
|
||||
:flag-assert #x900000090
|
||||
)
|
||||
;; definition for symbol tie-vu1-block, type vu-function
|
||||
(define tie-vu1-block (new 'static 'vu-function :length 0 :qlength 0)) ;; was 0x3e1, 0x1f1
|
||||
|
||||
;; definition for function tie-init-consts
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-init-consts ((arg0 tie-consts) (arg1 int))
|
||||
"Initialize TIE constants. arg1 enables alpha blending"
|
||||
|
||||
;; set the adgif shader tag (just 5x a+d's)
|
||||
(set! (-> arg0 adgif tag) (new 'static 'gif-tag64 :nloop #x5 :nreg #x1))
|
||||
(set! (-> arg0 adgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
|
||||
;; based on the menu drawing mode, create the template tag for geometry.
|
||||
(cond
|
||||
((zero? *subdivide-draw-mode*) ;; normal textured
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 3) ;; "hack". same as normal.
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 1) ;; outline (wireframe). just switch to line-strip
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type line-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 2) ;; gouraud - turn off tme.
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; the main drawing tag: st, rgbaq, xyzf per vertex (same in all draws modes)
|
||||
(set! (-> arg0 strgif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
|
||||
;; some magic constants
|
||||
(let ((f1-0 8388894.0)
|
||||
(f2-0 8389078.0)
|
||||
(f0-0 8389262.0)
|
||||
)
|
||||
(set! (-> arg0 gifbufs x) f0-0)
|
||||
(set! (-> arg0 gifbufs y) f2-0)
|
||||
(set! (-> arg0 gifbufs z) f0-0)
|
||||
(set! (-> arg0 gifbufs w) f2-0)
|
||||
(set! (-> arg0 extra x) (+ f1-0 f2-0 f0-0))
|
||||
(set! (-> arg0 extra y) 0.0)
|
||||
(set! (-> arg0 extra z) (+ f1-0 f2-0 f0-0))
|
||||
)
|
||||
(set! (-> arg0 clrbufs vector4w x) 198)
|
||||
(set! (-> arg0 clrbufs vector4w y) 242)
|
||||
(set! (-> arg0 clrbufs vector4w z) 198)
|
||||
(set! (-> arg0 clrbufs vector4w w) 242)
|
||||
|
||||
;; looks like tie can toggle on and off alpha testing during the draw
|
||||
;; tra = transparent, def = default?
|
||||
(set! (-> arg0 atestgif tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> arg0 atestgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(set! (-> arg0 atest-tra cmd) (gs-reg test-1))
|
||||
(set! (-> arg0 atest-tra data)
|
||||
(the uint
|
||||
(new 'static 'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 atest-def cmd) (gs-reg test-1))
|
||||
(set! (-> arg0 atest-def data)
|
||||
(the uint (new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal)))
|
||||
)
|
||||
|
||||
;; more magic constants
|
||||
(set! (-> arg0 misc vector4w x) 0)
|
||||
(set! (-> arg0 misc vector4w y) -1)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun tie-init-engine ((arg0 dma-buffer) (arg1 gs-test) (arg2 int))
|
||||
"Set up tie initialization DMA in the given buffer. arg2 picks abe."
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
;; add the tie code
|
||||
(dma-buffer-add-vu-function arg0 tie-vu1-block 1)
|
||||
|
||||
;; set up the given gs-test register
|
||||
(let* ((v1-3 arg0)
|
||||
(a0-2 (the-as object (-> v1-3 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-3 base) (&+ (the-as pointer a0-2) 16))
|
||||
)
|
||||
(let* ((v1-4 arg0)
|
||||
(a0-4 (the-as object (-> v1-4 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-4 base) (the-as pointer (&+ (the-as gs-gif-tag a0-4) 16)))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a0-6 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-test) a0-6) 0) arg1)
|
||||
(set! (-> (the-as (pointer gs-reg64) a0-6) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ a0-6 16))
|
||||
)
|
||||
|
||||
;; set up the tie constants
|
||||
(let ((s4-1 9))
|
||||
(let* ((v1-6 arg0)
|
||||
(a0-8 (the-as object (-> v1-6 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-8) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s4-1))
|
||||
(set! (-> (the-as dma-packet a0-8) vif0) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as dma-packet a0-8) vif1)
|
||||
(new 'static 'vif-tag :imm #x3c6 :cmd (vif-cmd unpack-v4-32) :num s4-1)
|
||||
)
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer a0-8) 16))
|
||||
)
|
||||
(tie-init-consts (the-as tie-consts (-> arg0 base)) arg2)
|
||||
(&+! (-> arg0 base) (* s4-1 16))
|
||||
)
|
||||
|
||||
;; initialize the microprogram
|
||||
(let* ((v1-9 arg0)
|
||||
(a0-12 (the-as object (-> v1-9 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-12) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-12) vif0) (new 'static 'vif-tag :imm #x8 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> (the-as dma-packet a0-12) vif1) (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(set! (-> v1-9 base) (&+ (the-as pointer a0-12) 16))
|
||||
)
|
||||
|
||||
;; initialize the VIF's ROW register
|
||||
(let* ((v1-10 arg0)
|
||||
(a0-14 (the-as object (-> v1-10 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-14) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-14) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-14) vif1) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> v1-10 base) (&+ (the-as pointer a0-14) 16))
|
||||
)
|
||||
(let ((v1-11 (the-as object (-> arg0 base))))
|
||||
;; row contants
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 x) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 y) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 z) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 w) #x4b000000)
|
||||
;; setup VIF unpack and double buffering modes.
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 4) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 5) (new 'static 'vif-tag :imm #x2c :cmd (vif-cmd offset)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 6) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 7) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> arg0 base) (&+ (the-as pointer v1-11) 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun tie-end-buffer ((arg0 dma-buffer))
|
||||
"Add to dma buffer after drawing. This resets things to the usual state."
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let* ((v1-3 arg0)
|
||||
(a1-0 (the-as object (-> v1-3 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a1-0) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a1-0) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a1-0) vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer a1-0) 16))
|
||||
)
|
||||
;; restore the test register
|
||||
(let* ((v1-4 arg0)
|
||||
(a1-2 (the-as object (-> v1-4 base)))
|
||||
)
|
||||
(set! (-> (the-as gs-gif-tag a1-2) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> (the-as gs-gif-tag a1-2) 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-4 base) (&+ (the-as pointer a1-2) 16))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a1-4 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-test) a1-4) 0)
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-reg64) a1-4) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ a1-4 16))
|
||||
)
|
||||
|
||||
;; restore the stmask register
|
||||
(let* ((v1-6 arg0)
|
||||
(a1-6 (the-as object (-> v1-6 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a1-6) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a1-6) vif0) (new 'static 'vif-tag :cmd (vif-cmd stmask)))
|
||||
(set! (-> (the-as dma-packet a1-6) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer a1-6) 16))
|
||||
)
|
||||
|
||||
;; this calls a TIE program that... does nothing?
|
||||
(let* ((v1-7 arg0)
|
||||
(a0-1 (-> v1-7 base))
|
||||
)
|
||||
;; run the nothing program
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 0) (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
;; reset VIF stuff we changed
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 1) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 2) (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 3) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
;; actually row constants = 0
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 4) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 5) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 6) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 7) (new 'static 'vif-tag))
|
||||
(set! (-> v1-7 base) (&+ a0-1 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;
|
||||
;; debug print
|
||||
;;;;;;;;;;;;;;;;
|
||||
|
||||
(defun-debug tie-int-reg ((arg0 int))
|
||||
"Convert a VU1 int register ID to the name given to it in the TIE VU1 program"
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"itemp"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"point-ptr"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"clr-ptr"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"target-bp1-ptr"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"skip-bp2"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"target-bp2-ptr"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"target-ip1-ptr"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"target-ip2-ptr"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"ind/ind0"
|
||||
)
|
||||
((= v1-0 10)
|
||||
" ind1"
|
||||
)
|
||||
((= v1-0 11)
|
||||
" ind2"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"dest-ptr"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"dest2-ptr"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"skip-ips"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"kick-addr"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun-debug tie-float-reg ((arg0 int))
|
||||
"Convert a VU1 float register ID to the name given to it in the TIE VU1 program"
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"t-mtx0"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"t-mtx1"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"t-mtx2"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"t-mtx3"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"vtx-0"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"vtx-1"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"vtx-2"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"vtx-3"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"pos-0/2"
|
||||
)
|
||||
((= v1-0 10)
|
||||
"pos-1/3"
|
||||
)
|
||||
((= v1-0 11)
|
||||
"clr-0"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"clr-1"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"clr-2"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"clr-3"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"tex-0"
|
||||
)
|
||||
((= v1-0 16)
|
||||
"tex-1"
|
||||
)
|
||||
((= v1-0 17)
|
||||
"tex-2"
|
||||
)
|
||||
((= v1-0 18)
|
||||
"tex-3"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"res-0/2"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"res-1/3"
|
||||
)
|
||||
((= v1-0 21)
|
||||
"gifbuf"
|
||||
)
|
||||
((= v1-0 22)
|
||||
"clrbuf"
|
||||
)
|
||||
((= v1-0 23)
|
||||
"extra"
|
||||
)
|
||||
((= v1-0 24)
|
||||
"inds"
|
||||
)
|
||||
((= v1-0 25)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 26)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 27)
|
||||
"morph"
|
||||
)
|
||||
((= v1-0 28)
|
||||
"xyzofs"
|
||||
)
|
||||
((= v1-0 29)
|
||||
"clr1"
|
||||
)
|
||||
((= v1-0 30)
|
||||
"clr2"
|
||||
)
|
||||
((= v1-0 31)
|
||||
"--"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; NOTE: these dump programs rely on a not-present function that stashes the register values
|
||||
;; at the top of the VU memory.
|
||||
|
||||
(defun-debug tie-ints ()
|
||||
"Dump the VU1 integer registers to stdout."
|
||||
(local-vars (sv-16 uint))
|
||||
(let ((gp-0 (the-as (pointer uint32) (+ #x3fa0 #x1100c000))))
|
||||
(dotimes (s5-0 16)
|
||||
(if (< s5-0 10)
|
||||
(format 0 " ")
|
||||
)
|
||||
(let ((s4-0 format)
|
||||
(s3-0 0)
|
||||
(s2-0 "vi~d: ~6d #x~4,'0X ~s~%")
|
||||
(s1-0 s5-0)
|
||||
(s0-0 (-> gp-0 (* s5-0 4)))
|
||||
)
|
||||
(set! sv-16 (-> gp-0 (* s5-0 4)))
|
||||
(let ((t1-0 (tie-int-reg s5-0)))
|
||||
(s4-0 s3-0 s2-0 s1-0 s0-0 sv-16 t1-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun-debug tie-floats ()
|
||||
"Dump the VU1 float registers to stdout."
|
||||
(local-vars (sv-16 uint) (sv-32 uint))
|
||||
(let ((gp-0 (the-as (pointer uint32) (+ #x3da0 #x1100c000))))
|
||||
(dotimes (s5-0 32)
|
||||
(if (< s5-0 10)
|
||||
(format 0 " ")
|
||||
)
|
||||
(format
|
||||
0
|
||||
"vf~d: #x~8,'0X #x~8,'0X #x~8,'0X #x~8,'0X "
|
||||
s5-0
|
||||
(-> gp-0 (* s5-0 4))
|
||||
(-> gp-0 (+ (* s5-0 4) 1))
|
||||
(-> gp-0 (+ (* s5-0 4) 2))
|
||||
(-> gp-0 (+ (* s5-0 4) 3))
|
||||
)
|
||||
(let ((s4-0 format)
|
||||
(s3-0 0)
|
||||
(s2-0 "~F ~F ~F ~F ~s~%")
|
||||
(s1-0 (-> gp-0 (* s5-0 4)))
|
||||
(s0-0 (-> gp-0 (+ (* s5-0 4) 1)))
|
||||
)
|
||||
(set! sv-16 (-> gp-0 (+ (* s5-0 4) 2)))
|
||||
(set! sv-32 (-> gp-0 (+ (* s5-0 4) 3)))
|
||||
(let ((t2-1 (tie-float-reg s5-0)))
|
||||
(s4-0 s3-0 s2-0 s1-0 s0-0 sv-16 sv-32 t2-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -76,10 +76,12 @@
|
||||
)
|
||||
|
||||
(defun tpage-name (id)
|
||||
"Get the name of the tpage obj file with the given id"
|
||||
(fmt #f "tpage-{}.go" id)
|
||||
)
|
||||
|
||||
(defmacro copy-texture (tpage-id)
|
||||
"Copy a texture from the game, using the given tpage ID"
|
||||
(let* ((folder (get-environment-variable "OPENGOAL_DECOMP_DIR" :default ""))
|
||||
(path (string-append "decompiler_out/" folder "raw_obj/" (tpage-name tpage-id))))
|
||||
`(defstep :in ,path
|
||||
@@ -105,6 +107,18 @@
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro copy-strs (&rest strs)
|
||||
`(begin ,@(apply (lambda (x) `(copy-str ,x)) strs)))
|
||||
|
||||
(defmacro copy-str (name)
|
||||
(let* ((folder (get-environment-variable "OPENGOAL_DECOMP_DIR" :default ""))
|
||||
(path (string-append "iso_data/" folder "/STR/" name ".STR")))
|
||||
`(defstep :in ,path
|
||||
:tool 'copy
|
||||
:out '(,(string-append "out/iso/" name ".STR")))))
|
||||
|
||||
|
||||
|
||||
(defmacro group (name &rest stuff)
|
||||
`(defstep :in ""
|
||||
:tool 'group
|
||||
@@ -166,6 +180,13 @@
|
||||
|
||||
(copy-textures 463 2 880 256 1278 1032 62 1532)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Streaming anim (common)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(copy-strs "FUCV3"
|
||||
"FUCV4")
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Art (Common)
|
||||
@@ -220,6 +241,8 @@
|
||||
"out/iso/BEA.DGO"
|
||||
"out/iso/CIT.DGO"
|
||||
"out/iso/SUN.DGO"
|
||||
"out/iso/FUCV3.STR"
|
||||
"out/iso/FUCV4.STR"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -59,4 +59,3 @@ endif ()
|
||||
add_executable(goalc main.cpp)
|
||||
target_link_libraries(goalc common Zydis compiler)
|
||||
|
||||
install(TARGETS goalc)
|
||||
|
||||
+1
-5
@@ -776,7 +776,7 @@
|
||||
(when (and
|
||||
(< 0.0 (-> self fact-info-target eco-level))
|
||||
(zero? (logand (-> self state-flags) 512))
|
||||
(zero? (logand (-> self draw status) 6))
|
||||
(zero? (logand (-> self draw status) (draw-status drwf01 drwf02)))
|
||||
(not (movie?))
|
||||
(rand-vu-percent?
|
||||
(lerp-scale
|
||||
@@ -968,7 +968,3 @@
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@
|
||||
(quad uint128 :offset 0)
|
||||
(data uint64 :offset 0)
|
||||
(cmds uint64 :offset 8)
|
||||
(cmd uint8 :offset 8)
|
||||
(cmd gs-reg :offset 8)
|
||||
(x uint32 :offset 0)
|
||||
(y uint32 :offset 4)
|
||||
(z uint32 :offset 8)
|
||||
|
||||
+3
-2
@@ -149,6 +149,7 @@
|
||||
(color-index-qwc uint32 :dynamic :offset-assert 148)
|
||||
(generic-next-clear uint128 :offset 96)
|
||||
(generic-count-clear uint128 :offset 80)
|
||||
(geometry-override prototype-tie 4 :offset 16)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x94
|
||||
@@ -163,7 +164,7 @@
|
||||
(format #t "~Tflags: ~D~%" (-> obj flags))
|
||||
(format #t "~Tin-level: ~D~%" (-> obj in-level))
|
||||
(format #t "~Tutextures: ~D~%" (-> obj utextures))
|
||||
(format #t "~Tgeometry[4] @ #x~X~%" (-> obj geometry))
|
||||
(format #t "~Tgeometry[4] @ #x~X~%" (-> obj geometry-override))
|
||||
(format #t "~Tdists: #<vector @ #x~X>~%" (-> obj dists))
|
||||
(format #t "~Trdists: #<vector @ #x~X>~%" (-> obj rdists))
|
||||
(format #t "~Tnext[4] @ #x~X~%" (-> obj next))
|
||||
@@ -203,7 +204,7 @@
|
||||
:size-assert #x10
|
||||
:flag-assert #xa00000010
|
||||
(:methods
|
||||
(TODO-RENAME-9 (_type_) none 9)
|
||||
(login (_type_) none 9)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
+3
-3
@@ -3,11 +3,11 @@
|
||||
|
||||
;; definition for method 9 of type prototype-array-tie
|
||||
;; INFO: Return type mismatch prototype-array-tie vs none.
|
||||
(defmethod TODO-RENAME-9 prototype-array-tie ((obj prototype-array-tie))
|
||||
(defmethod login prototype-array-tie ((obj prototype-array-tie))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(let ((s4-0 (-> obj array-data s5-0)))
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-1 (-> s4-0 geometry s3-0)))
|
||||
(let ((a0-1 (-> s4-0 geometry-override s3-0)))
|
||||
(if (nonzero? a0-1)
|
||||
(login a0-1)
|
||||
)
|
||||
@@ -65,7 +65,7 @@
|
||||
;; definition for method 8 of type prototype-bucket-tie
|
||||
(defmethod mem-usage prototype-bucket-tie ((obj prototype-bucket-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(dotimes (s3-0 4)
|
||||
(let ((a0-1 (-> obj geometry s3-0)))
|
||||
(let ((a0-1 (-> obj geometry-override s3-0)))
|
||||
(if (nonzero? a0-1)
|
||||
(mem-usage a0-1 arg0 (logior arg1 1))
|
||||
)
|
||||
|
||||
+15
-15
@@ -3,21 +3,21 @@
|
||||
|
||||
;; definition of type tie-fragment
|
||||
(deftype tie-fragment (drawable)
|
||||
((gif-ref uint32 :offset 4)
|
||||
(point-ref uint32 :offset 8)
|
||||
(color-index uint16 :offset 12)
|
||||
(base-colors uint8 :offset 14)
|
||||
(tex-count uint16 :offset-assert 32)
|
||||
(gif-count uint16 :offset-assert 34)
|
||||
(vertex-count uint16 :offset-assert 36)
|
||||
(color-count uint16 :offset-assert 38)
|
||||
(num-tris uint16 :offset-assert 40)
|
||||
(num-dverts uint16 :offset-assert 42)
|
||||
(dp-ref uint32 :offset-assert 44)
|
||||
(dp-qwc uint32 :offset-assert 48)
|
||||
(generic-ref uint32 :offset-assert 52)
|
||||
(generic-count uint32 :offset-assert 56)
|
||||
(debug-lines basic :offset-assert 60)
|
||||
((gif-ref (inline-array adgif-shader) :offset 4)
|
||||
(point-ref uint32 :offset 8)
|
||||
(color-index uint16 :offset 12)
|
||||
(base-colors uint8 :offset 14)
|
||||
(tex-count uint16 :offset-assert 32)
|
||||
(gif-count uint16 :offset-assert 34)
|
||||
(vertex-count uint16 :offset-assert 36)
|
||||
(color-count uint16 :offset-assert 38)
|
||||
(num-tris uint16 :offset-assert 40)
|
||||
(num-dverts uint16 :offset-assert 42)
|
||||
(dp-ref uint32 :offset-assert 44)
|
||||
(dp-qwc uint32 :offset-assert 48)
|
||||
(generic-ref uint32 :offset-assert 52)
|
||||
(generic-count uint32 :offset-assert 56)
|
||||
(debug-lines (array vector-array) :offset-assert 60)
|
||||
)
|
||||
:method-count-assert 18
|
||||
:size-assert #x40
|
||||
|
||||
+897
@@ -0,0 +1,897 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; definition for function tie-init-buffers
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-init-buffers ((arg0 dma-buffer))
|
||||
(let ((gp-0 (-> *display* frames (-> *display* on-screen) frame bucket-group 9)))
|
||||
(when (!= gp-0 (-> gp-0 last))
|
||||
(let* ((s5-0 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-1 (-> s5-0 base))
|
||||
)
|
||||
(tie-init-engine
|
||||
s5-0
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
0
|
||||
)
|
||||
(let ((v1-8 (the-as object (-> s5-0 base))))
|
||||
(set! (-> (the-as dma-packet v1-8) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-0 next)))
|
||||
(set! (-> (the-as dma-packet v1-8) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-8) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-0 base) (&+ (the-as pointer v1-8) 16))
|
||||
)
|
||||
(set! (-> gp-0 next) (the-as uint s4-1))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-1 (-> *display* frames (-> *display* on-screen) frame bucket-group 9)))
|
||||
(when (!= gp-1 (-> gp-1 last))
|
||||
(let* ((s4-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-1 (-> s4-2 base))
|
||||
)
|
||||
(tie-end-buffer s4-2)
|
||||
(let ((v1-19 (-> s4-2 base)))
|
||||
(let ((a0-17 (the-as object (-> s4-2 base))))
|
||||
(set! (-> (the-as dma-packet a0-17) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-17) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-17) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-2 base) (&+ (the-as pointer a0-17) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-1 last)) 1) (the-as uint s5-1))
|
||||
(set! (-> gp-1 last) (the-as (pointer dma-tag) v1-19))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-2 (-> *display* frames (-> *display* on-screen) frame bucket-group 16)))
|
||||
(when (!= gp-2 (-> gp-2 last))
|
||||
(let* ((s5-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-4 (-> s5-2 base))
|
||||
)
|
||||
(tie-init-engine
|
||||
s5-2
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
0
|
||||
)
|
||||
(let ((v1-28 (the-as object (-> s5-2 base))))
|
||||
(set! (-> (the-as dma-packet v1-28) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-2 next)))
|
||||
(set! (-> (the-as dma-packet v1-28) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-28) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-2 base) (&+ (the-as pointer v1-28) 16))
|
||||
)
|
||||
(set! (-> gp-2 next) (the-as uint s4-4))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-3 (-> *display* frames (-> *display* on-screen) frame bucket-group 16)))
|
||||
(when (!= gp-3 (-> gp-3 last))
|
||||
(let* ((s4-5 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-3 (-> s4-5 base))
|
||||
)
|
||||
(tie-end-buffer s4-5)
|
||||
(let ((v1-39 (-> s4-5 base)))
|
||||
(let ((a0-36 (the-as object (-> s4-5 base))))
|
||||
(set! (-> (the-as dma-packet a0-36) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-36) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-36) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-5 base) (&+ (the-as pointer a0-36) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-3 last)) 1) (the-as uint s5-3))
|
||||
(set! (-> gp-3 last) (the-as (pointer dma-tag) v1-39))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-4 (-> *display* frames (-> *display* on-screen) frame bucket-group 8)))
|
||||
(when (!= gp-4 (-> gp-4 last))
|
||||
(let* ((s5-4 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-7 (-> s5-4 base))
|
||||
)
|
||||
(tie-near-init-engine
|
||||
s5-4
|
||||
(new 'static 'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)
|
||||
)
|
||||
0
|
||||
)
|
||||
(let ((v1-48 (the-as object (-> s5-4 base))))
|
||||
(set! (-> (the-as dma-packet v1-48) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-4 next)))
|
||||
(set! (-> (the-as dma-packet v1-48) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-48) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-4 base) (&+ (the-as pointer v1-48) 16))
|
||||
)
|
||||
(set! (-> gp-4 next) (the-as uint s4-7))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-5 (-> *display* frames (-> *display* on-screen) frame bucket-group 8)))
|
||||
(when (!= gp-5 (-> gp-5 last))
|
||||
(let* ((s4-8 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-5 (-> s4-8 base))
|
||||
)
|
||||
(tie-near-end-buffer s4-8)
|
||||
(let ((v1-59 (-> s4-8 base)))
|
||||
(let ((a0-55 (the-as object (-> s4-8 base))))
|
||||
(set! (-> (the-as dma-packet a0-55) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-55) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-55) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-8 base) (&+ (the-as pointer a0-55) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-5 last)) 1) (the-as uint s5-5))
|
||||
(set! (-> gp-5 last) (the-as (pointer dma-tag) v1-59))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-6 (-> *display* frames (-> *display* on-screen) frame bucket-group 15)))
|
||||
(when (!= gp-6 (-> gp-6 last))
|
||||
(let* ((s5-6 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s4-10 (-> s5-6 base))
|
||||
)
|
||||
(tie-near-init-engine
|
||||
s5-6
|
||||
(new 'static 'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)
|
||||
)
|
||||
0
|
||||
)
|
||||
(let ((v1-68 (the-as object (-> s5-6 base))))
|
||||
(set! (-> (the-as dma-packet v1-68) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> gp-6 next)))
|
||||
(set! (-> (the-as dma-packet v1-68) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-68) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s5-6 base) (&+ (the-as pointer v1-68) 16))
|
||||
)
|
||||
(set! (-> gp-6 next) (the-as uint s4-10))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((gp-7 (-> *display* frames (-> *display* on-screen) frame bucket-group 15)))
|
||||
(when (!= gp-7 (-> gp-7 last))
|
||||
(let* ((s4-11 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s5-7 (-> s4-11 base))
|
||||
)
|
||||
(tie-near-end-buffer s4-11)
|
||||
(let ((v1-79 (-> s4-11 base)))
|
||||
(let ((a0-74 (the-as object (-> s4-11 base))))
|
||||
(set! (-> (the-as dma-packet a0-74) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet a0-74) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-74) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s4-11 base) (&+ (the-as pointer a0-74) 16))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint32) (-> gp-7 last)) 1) (the-as uint s5-7))
|
||||
(set! (-> gp-7 last) (the-as (pointer dma-tag) v1-79))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition of type tie-instance-debug
|
||||
(deftype tie-instance-debug (structure)
|
||||
((max-instance uint32 :offset-assert 0)
|
||||
(min-instance uint32 :offset-assert 4)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x8
|
||||
:flag-assert #x900000008
|
||||
)
|
||||
|
||||
;; definition for method 3 of type tie-instance-debug
|
||||
(defmethod inspect tie-instance-debug ((obj tie-instance-debug))
|
||||
(format #t "[~8x] ~A~%" obj 'tie-instance-debug)
|
||||
(format #t "~Tmax-instance: ~D~%" (-> obj max-instance))
|
||||
(format #t "~Tmin-instance: ~D~%" (-> obj min-instance))
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for symbol *tie*, type tie-instance-debug
|
||||
(define *tie* (new 'global 'tie-instance-debug))
|
||||
|
||||
;; definition for function tie-debug-between
|
||||
(defun tie-debug-between ((arg0 uint) (arg1 uint))
|
||||
(set! (-> *instance-tie-work* test-id) arg1)
|
||||
(set! (-> *instance-tie-work* test-id2) arg0)
|
||||
arg0
|
||||
)
|
||||
|
||||
;; definition for function tie-debug-one
|
||||
(defun tie-debug-one ((arg0 uint) (arg1 uint))
|
||||
(set! (-> *instance-tie-work* test-id) (+ arg1 -1 arg0))
|
||||
(set! (-> *instance-tie-work* test-id2) arg0)
|
||||
arg0
|
||||
)
|
||||
|
||||
;; definition for function walk-tie-generic-prototypes
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
(defun walk-tie-generic-prototypes ()
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for symbol *pke-hack*, type vector
|
||||
(define *pke-hack* (new 'global 'vector))
|
||||
|
||||
;; definition for function draw-inline-array-instance-tie
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
;; definition for function draw-inline-array-prototype-tie-generic-asm
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
;; definition for function draw-inline-array-prototype-tie-asm
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
;; definition for function draw-inline-array-prototype-tie-near-asm
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
;; definition for method 9 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
(if (nonzero? (-> obj prototypes prototype-array-tie))
|
||||
(login (-> obj prototypes prototype-array-tie))
|
||||
)
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for function draw-drawable-tree-instance-tie
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr0, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr1, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, a0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr0, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr1, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, a0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr0, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr1, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, a0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr0, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtpc pcr1, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, a0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mtc0 Perf, r0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.l]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [sync.p]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr0]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [mfpc a0, pcr1]
|
||||
;; Used lq/sq
|
||||
(defun draw-drawable-tree-instance-tie ((arg0 drawable-tree-instance-tie) (arg1 level))
|
||||
(local-vars
|
||||
(r0-0 none)
|
||||
(a0-31 int)
|
||||
(a0-33 int)
|
||||
(a0-46 int)
|
||||
(a0-48 int)
|
||||
(a0-62 int)
|
||||
(a0-64 int)
|
||||
(a0-82 int)
|
||||
(a0-84 int)
|
||||
(sv-16 int)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near tie generic))
|
||||
(set! (-> *instance-tie-work* first-generic-prototype) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work* wind-vectors) (-> arg0 prototypes wind-vectors))
|
||||
(let ((s4-0 (+ (-> arg0 length) -1)))
|
||||
(when (nonzero? s4-0)
|
||||
(dotimes (s3-0 s4-0)
|
||||
(let* ((v1-10 (-> arg0 data s3-0))
|
||||
(a0-5 (-> arg0 data (+ s3-0 1)))
|
||||
(a1-2 (/ (-> (the-as drawable-inline-array-node v1-10) data 0 id) 8))
|
||||
(a0-7 (/ (-> (the-as drawable-inline-array-node a0-5) data 0 id) 8))
|
||||
(a1-4 (+ a1-2 #x38b0 #x70000000))
|
||||
(a0-9 (+ a0-7 #x38b0 #x70000000))
|
||||
)
|
||||
(draw-node-cull
|
||||
(the-as pointer a0-9)
|
||||
(the-as pointer a1-4)
|
||||
(-> (the-as drawable-inline-array-node v1-10) data)
|
||||
(-> (the-as drawable-inline-array-node v1-10) length)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let* ((v1-16 (-> arg0 data s4-0))
|
||||
(s4-1 (-> arg0 prototypes prototype-array-tie))
|
||||
(s5-1 (-> s4-1 length))
|
||||
)
|
||||
(dotimes (a0-11 s5-1)
|
||||
(let ((a1-7 (-> s4-1 array-data a0-11)))
|
||||
(set! (-> a1-7 next-clear) (the-as uint128 0))
|
||||
(set! (-> a1-7 generic-count-clear) (the-as uint128 0))
|
||||
(set! (-> a1-7 generic-next-clear) (the-as uint128 0))
|
||||
)
|
||||
0
|
||||
)
|
||||
(let* ((s1-0 (-> (the-as drawable-inline-array-instance-tie v1-16) data))
|
||||
(s0-0 (&-> (the-as terrain-context #x70000000) work background vis-list (/ (-> s1-0 0 id) 8)))
|
||||
(s3-1 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
)
|
||||
(set! sv-16 (-> (the-as drawable-inline-array-node v1-16) length))
|
||||
(when (nonzero? sv-16)
|
||||
(let* ((v1-21 (logand (the-as int *gsf-buffer*) 8191))
|
||||
(v1-23
|
||||
(logand (the-as int (&- (logand (the-as int (&-> (-> s4-1 data) -512)) 8191) (the-as uint v1-21))) 8191)
|
||||
)
|
||||
)
|
||||
(set! *instance-tie-work-copy* (the-as instance-tie-work (+ (the-as int *gsf-buffer*) v1-23)))
|
||||
)
|
||||
(let ((s2-0 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(quad-copy! (the-as pointer *instance-tie-work-copy*) (the-as pointer *instance-tie-work*) 28)
|
||||
(set! (-> *instance-tie-work-copy* wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work-copy* wait-from-spr) (the-as uint 0))
|
||||
(let* ((v1-32 (-> *perf-stats* data 9))
|
||||
(a0-28 (-> v1-32 ctrl))
|
||||
)
|
||||
(+! (-> v1-32 count) 1)
|
||||
(b! (zero? a0-28) cfg-12 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtpc pcr0 r0-0)
|
||||
(.mtpc pcr1 r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtc0 Perf a0-28)
|
||||
)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(label cfg-12)
|
||||
0
|
||||
(let ((t9-2 draw-inline-array-instance-tie)
|
||||
(a3-1 s3-1)
|
||||
)
|
||||
(t9-2 s0-0 (the-as drawable s1-0) sv-16 a3-1)
|
||||
)
|
||||
(let ((v1-35 (-> *perf-stats* data 9)))
|
||||
(b! (zero? (-> v1-35 ctrl)) cfg-14 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mfpc a0-31 pcr0)
|
||||
(+! (-> v1-35 accum0) a0-31)
|
||||
(.mfpc a0-33 pcr1)
|
||||
(+! (-> v1-35 accum1) a0-33)
|
||||
)
|
||||
(label cfg-14)
|
||||
0
|
||||
(update-wait-stats
|
||||
(-> *perf-stats* data 9)
|
||||
(the-as uint 0)
|
||||
(-> *instance-tie-work-copy* wait-to-spr)
|
||||
(-> *instance-tie-work-copy* wait-from-spr)
|
||||
)
|
||||
(let ((v1-42 (-> *instance-tie-work-copy* min-dist quad)))
|
||||
(set! (-> *instance-tie-work* min-dist quad) v1-42)
|
||||
)
|
||||
(set! (-> *instance-tie-work* flags) (-> *instance-tie-work-copy* flags))
|
||||
(let ((a0-38 *dma-mem-usage*))
|
||||
(when (nonzero? a0-38)
|
||||
(set! (-> a0-38 length) (max 10 (-> a0-38 length)))
|
||||
(set! (-> a0-38 data 9 name) "tie-fragment")
|
||||
(+! (-> a0-38 data 9 count) 1)
|
||||
(+!
|
||||
(-> a0-38 data 9 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s2-0))
|
||||
)
|
||||
(set! (-> a0-38 data 9 total) (-> a0-38 data 9 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
(when (logtest? (-> *instance-tie-work* flags) 2)
|
||||
(let ((s2-1 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(set! (-> *prototype-tie-work* generic-wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* generic-wait-from-spr) (the-as uint 0))
|
||||
(set! (-> *instance-tie-work* first-generic-prototype) (the-as uint (-> s3-1 base)))
|
||||
(let* ((v1-60 (-> *perf-stats* data 10))
|
||||
(a0-43 (-> v1-60 ctrl))
|
||||
)
|
||||
(+! (-> v1-60 count) 1)
|
||||
(b! (zero? a0-43) cfg-20 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtpc pcr0 r0-0)
|
||||
(.mtpc pcr1 r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtc0 Perf a0-43)
|
||||
)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(label cfg-20)
|
||||
0
|
||||
(draw-inline-array-prototype-tie-generic-asm s3-1 s5-1 s4-1)
|
||||
(let ((v1-63 (-> *perf-stats* data 10)))
|
||||
(b! (zero? (-> v1-63 ctrl)) cfg-22 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mfpc a0-46 pcr0)
|
||||
(+! (-> v1-63 accum0) a0-46)
|
||||
(.mfpc a0-48 pcr1)
|
||||
(+! (-> v1-63 accum1) a0-48)
|
||||
)
|
||||
(label cfg-22)
|
||||
0
|
||||
(update-wait-stats
|
||||
(-> *perf-stats* data 10)
|
||||
(the-as uint 0)
|
||||
(-> *prototype-tie-work* generic-wait-to-spr)
|
||||
(-> *prototype-tie-work* generic-wait-from-spr)
|
||||
)
|
||||
(let ((a0-51 *dma-mem-usage*))
|
||||
(when (nonzero? a0-51)
|
||||
(set! (-> a0-51 length) (max 18 (-> a0-51 length)))
|
||||
(set! (-> a0-51 data 17 name) "tie-generic")
|
||||
(+! (-> a0-51 data 17 count) 1)
|
||||
(+!
|
||||
(-> a0-51 data 17 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s2-1))
|
||||
)
|
||||
(set! (-> a0-51 data 17 total) (-> a0-51 data 17 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let ((s3-2 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let* ((s1-1 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s2-2 (-> s1-1 base))
|
||||
)
|
||||
(set! (-> *prototype-tie-work* wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* wait-from-spr) (the-as uint 0))
|
||||
(let* ((v1-85 (-> *perf-stats* data 11))
|
||||
(a0-59 (-> v1-85 ctrl))
|
||||
)
|
||||
(+! (-> v1-85 count) 1)
|
||||
(b! (zero? a0-59) cfg-28 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtpc pcr0 r0-0)
|
||||
(.mtpc pcr1 r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtc0 Perf a0-59)
|
||||
)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(label cfg-28)
|
||||
0
|
||||
(draw-inline-array-prototype-tie-asm s1-1 s5-1 s4-1)
|
||||
(let ((v1-88 (-> *perf-stats* data 11)))
|
||||
(b! (zero? (-> v1-88 ctrl)) cfg-30 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mfpc a0-62 pcr0)
|
||||
(+! (-> v1-88 accum0) a0-62)
|
||||
(.mfpc a0-64 pcr1)
|
||||
(+! (-> v1-88 accum1) a0-64)
|
||||
)
|
||||
(label cfg-30)
|
||||
0
|
||||
(update-wait-stats
|
||||
(-> *perf-stats* data 11)
|
||||
(the-as uint 0)
|
||||
(-> *prototype-tie-work* wait-to-spr)
|
||||
(-> *prototype-tie-work* wait-from-spr)
|
||||
)
|
||||
(let ((a3-11 (-> s1-1 base)))
|
||||
(let ((v1-94 (the-as object (-> s1-1 base))))
|
||||
(set! (-> (the-as dma-packet v1-94) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet v1-94) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-94) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s1-1 base) (&+ (the-as pointer v1-94) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
(the-as bucket-id (if (zero? (-> arg1 index))
|
||||
9
|
||||
16
|
||||
)
|
||||
)
|
||||
s2-2
|
||||
(the-as (pointer dma-tag) a3-11)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((v1-100 *dma-mem-usage*))
|
||||
(when (nonzero? v1-100)
|
||||
(set! (-> v1-100 length) (max 10 (-> v1-100 length)))
|
||||
(set! (-> v1-100 data 9 name) "tie-fragment")
|
||||
(+! (-> v1-100 data 9 count) 1)
|
||||
(+!
|
||||
(-> v1-100 data 9 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s3-2))
|
||||
)
|
||||
(set! (-> v1-100 data 9 total) (-> v1-100 data 9 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(let ((s3-3 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
|
||||
(let* ((s1-2 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(s2-3 (-> s1-2 base))
|
||||
)
|
||||
(set! (-> *prototype-tie-work* near-wait-to-spr) (the-as uint 0))
|
||||
(set! (-> *prototype-tie-work* near-wait-from-spr) (the-as uint 0))
|
||||
(let* ((v1-114 (-> *perf-stats* data 12))
|
||||
(a0-79 (-> v1-114 ctrl))
|
||||
)
|
||||
(+! (-> v1-114 count) 1)
|
||||
(b! (zero? a0-79) cfg-39 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtpc pcr0 r0-0)
|
||||
(.mtpc pcr1 r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mtc0 Perf a0-79)
|
||||
)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(label cfg-39)
|
||||
0
|
||||
(draw-inline-array-prototype-tie-near-asm s1-2 s5-1 s4-1)
|
||||
(let ((v1-117 (-> *perf-stats* data 12)))
|
||||
(b! (zero? (-> v1-117 ctrl)) cfg-41 :delay (nop!))
|
||||
(.mtc0 Perf r0-0)
|
||||
(.sync.l)
|
||||
(.sync.p)
|
||||
(.mfpc a0-82 pcr0)
|
||||
(+! (-> v1-117 accum0) a0-82)
|
||||
(.mfpc a0-84 pcr1)
|
||||
(+! (-> v1-117 accum1) a0-84)
|
||||
)
|
||||
(label cfg-41)
|
||||
0
|
||||
(update-wait-stats
|
||||
(-> *perf-stats* data 12)
|
||||
(the-as uint 0)
|
||||
(-> *prototype-tie-work* near-wait-to-spr)
|
||||
(-> *prototype-tie-work* near-wait-from-spr)
|
||||
)
|
||||
(let ((a3-16 (-> s1-2 base)))
|
||||
(let ((v1-123 (the-as object (-> s1-2 base))))
|
||||
(set! (-> (the-as dma-packet v1-123) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> (the-as dma-packet v1-123) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet v1-123) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s1-2 base) (&+ (the-as pointer v1-123) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
(the-as bucket-id (if (zero? (-> arg1 index))
|
||||
8
|
||||
15
|
||||
)
|
||||
)
|
||||
s2-3
|
||||
(the-as (pointer dma-tag) a3-16)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((a0-92 *dma-mem-usage*))
|
||||
(when (nonzero? a0-92)
|
||||
(set! (-> a0-92 length) (max 16 (-> a0-92 length)))
|
||||
(set! (-> a0-92 data 15 name) "tie-near")
|
||||
(+! (-> a0-92 data 15 count) 1)
|
||||
(+!
|
||||
(-> a0-92 data 15 used)
|
||||
(&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s3-3))
|
||||
)
|
||||
(set! (-> a0-92 data 15 total) (-> a0-92 data 15 used))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
)
|
||||
(set! (-> arg1 closest-object 5) (-> *instance-tie-work* min-dist x))
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 10 of type drawable-tree-instance-tie
|
||||
;; INFO: Return type mismatch drawable-tree-instance-tie vs none.
|
||||
(defmethod draw drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 drawable-tree-instance-tie) (arg1 display-frame))
|
||||
(let* ((v1-1 (-> *background-work* tie-tree-count))
|
||||
(a1-2 (-> (the-as terrain-context #x70000000) bsp lev-index))
|
||||
(a1-5 (-> *level* level a1-2))
|
||||
)
|
||||
(set! (-> *background-work* tie-trees v1-1) obj)
|
||||
(set! (-> *background-work* tie-levels v1-1) a1-5)
|
||||
)
|
||||
(+! (-> *background-work* tie-tree-count) 1)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 14 of type drawable-tree-instance-tie
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
(defmethod collect-stats drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near tie generic))
|
||||
(-> obj data (+ (-> obj length) -1))
|
||||
(let ((v1-8 (-> obj prototypes prototype-array-tie)))
|
||||
(dotimes (a0-1 (-> v1-8 length))
|
||||
(let ((a1-2 (-> v1-8 array-data a0-1)))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask generic))
|
||||
(let ((a2-3 0)
|
||||
(a3-0 3)
|
||||
)
|
||||
(while (>= a3-0 a2-3)
|
||||
(let ((t0-2 (-> a1-2 generic-count a2-3))
|
||||
(t2-0 (-> a1-2 geometry-override a2-3))
|
||||
)
|
||||
(when (nonzero? t0-2)
|
||||
(let ((t1-3 (the-as object (-> t2-0 data)))
|
||||
(t2-1 (-> t2-0 length))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-generic groups) 1)
|
||||
(+! (-> *terrain-stats* tie-generic fragments) t2-1)
|
||||
(+! (-> *terrain-stats* tie-generic instances) t0-2)
|
||||
(dotimes (t3-9 t2-1)
|
||||
(let ((t5-0 (* (-> (the-as tie-fragment t1-3) num-tris) t0-2))
|
||||
(t4-5 (* (-> (the-as tie-fragment t1-3) num-dverts) t0-2))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-generic tris) t5-0)
|
||||
(+! (-> *terrain-stats* tie-generic dverts) t4-5)
|
||||
)
|
||||
(set! t1-3 (&+ (the-as tie-fragment t1-3) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! a2-3 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let ((a2-9 1)
|
||||
(a3-1 3)
|
||||
)
|
||||
(while (>= a3-1 a2-9)
|
||||
(let ((t0-6 (-> a1-2 count a2-9))
|
||||
(t2-2 (-> a1-2 geometry-override a2-9))
|
||||
)
|
||||
(when (nonzero? t0-6)
|
||||
(let ((t1-8 (the-as object (-> t2-2 data)))
|
||||
(t2-3 (-> t2-2 length))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie groups) 1)
|
||||
(+! (-> *terrain-stats* tie fragments) t2-3)
|
||||
(+! (-> *terrain-stats* tie instances) t0-6)
|
||||
(dotimes (t3-19 t2-3)
|
||||
(let ((t5-5 (* (-> (the-as tie-fragment t1-8) num-tris) t0-6))
|
||||
(t4-12 (* (-> (the-as tie-fragment t1-8) num-dverts) t0-6))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie tris) t5-5)
|
||||
(+! (-> *terrain-stats* tie dverts) t4-12)
|
||||
)
|
||||
(set! t1-8 (&+ (the-as tie-fragment t1-8) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! a2-9 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(let ((a2-14 (-> a1-2 count 0))
|
||||
(a3-2 (-> a1-2 geometry-override 0))
|
||||
)
|
||||
(when (nonzero? a2-14)
|
||||
(let ((a1-3 (the-as object (-> a3-2 data)))
|
||||
(a3-3 (-> a3-2 length))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-near groups) 1)
|
||||
(+! (-> *terrain-stats* tie-near fragments) a3-3)
|
||||
(+! (-> *terrain-stats* tie-near instances) a2-14)
|
||||
(dotimes (t0-19 a3-3)
|
||||
(let ((t2-4 (* (-> (the-as tie-fragment a1-3) num-tris) a2-14))
|
||||
(t1-15 (* (-> (the-as tie-fragment a1-3) num-dverts) a2-14))
|
||||
)
|
||||
(+! (-> *terrain-stats* tie-near tris) t2-4)
|
||||
(+! (-> *terrain-stats* tie-near dverts) t1-15)
|
||||
)
|
||||
(set! a1-3 (&+ (the-as tie-fragment a1-3) 64))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 15 of type drawable-tree-instance-tie
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
(defmethod debug-draw drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 drawable) (arg1 display-frame))
|
||||
(-> obj data (+ (-> obj length) -1))
|
||||
(let* ((s5-0 (-> obj prototypes prototype-array-tie))
|
||||
(s4-0 (-> s5-0 length))
|
||||
)
|
||||
(dotimes (s3-0 s4-0)
|
||||
(let ((a1-1 (-> s5-0 array-data s3-0 geometry-override 0)))
|
||||
(debug-draw a1-1 a1-1 arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 11 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-with-box drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-with-box (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 12 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-y-probe drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-y-probe (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 13 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-ray drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-ray (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 11 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-with-box drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-with-box (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 12 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-y-probe drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-y-probe (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 13 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-ray drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-ray (-> obj data 0) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 11 of type drawable-inline-array-instance-tie
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-with-box drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-with-box (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 12 of type drawable-inline-array-instance-tie
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-y-probe drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-y-probe (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 13 of type drawable-inline-array-instance-tie
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defmethod collide-ray drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 int) (arg1 collide-list))
|
||||
(collide-ray (the-as instance-tie (-> obj data)) (-> obj length) arg1)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition (debug) for function tie-test-cam-restore
|
||||
;; INFO: Return type mismatch object vs none.
|
||||
;; Used lq/sq
|
||||
(defun-debug tie-test-cam-restore ()
|
||||
(let ((a0-0 (new-stack-vector0))
|
||||
(a1-0 (new-stack-matrix0))
|
||||
)
|
||||
(set! (-> a0-0 x) 1246582.6)
|
||||
(set! (-> a0-0 y) 57026.02)
|
||||
(set! (-> a0-0 z) -490734.78)
|
||||
(set! (-> a0-0 w) 1.0)
|
||||
(set! (-> a1-0 vector 0 x) -0.9873)
|
||||
(set! (-> a1-0 vector 0 y) 0.0)
|
||||
(set! (-> a1-0 vector 0 z) -0.1587)
|
||||
(set! (-> a1-0 vector 0 w) 0.0)
|
||||
(set! (-> a1-0 vector 1 x) 0.0014)
|
||||
(set! (-> a1-0 vector 1 y) 0.9999)
|
||||
(set! (-> a1-0 vector 1 z) -0.0092)
|
||||
(set! (-> a1-0 vector 1 w) 0.0)
|
||||
(set! (-> a1-0 vector 2 x) 0.1587)
|
||||
(set! (-> a1-0 vector 2 y) -0.0093)
|
||||
(set! (-> a1-0 vector 2 z) -0.9872)
|
||||
(set! (-> a1-0 vector 2 w) 0.0)
|
||||
(set! (-> a1-0 vector 3 x) 0.0)
|
||||
(set! (-> a1-0 vector 3 y) 0.0)
|
||||
(set! (-> a1-0 vector 3 z) 0.0)
|
||||
(set! (-> a1-0 vector 3 w) 1.0)
|
||||
(debug-set-camera-pos-rot! a0-0 a1-0)
|
||||
)
|
||||
(send-event *camera* 'set-fov 11650.845)
|
||||
(none)
|
||||
)
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; definition of type tie-near-consts
|
||||
(deftype tie-near-consts (structure)
|
||||
((extra qword :inline :offset-assert 0)
|
||||
(gifbufs qword :inline :offset-assert 16)
|
||||
(clrbufs qword :inline :offset-assert 32)
|
||||
(adgif gs-gif-tag :inline :offset-assert 48)
|
||||
(strgif gs-gif-tag :inline :offset-assert 64)
|
||||
(fangif gs-gif-tag :inline :offset-assert 80)
|
||||
(hvdfoffs vector :inline :offset-assert 96)
|
||||
(invhscale vector :inline :offset-assert 112)
|
||||
(guard vector :inline :offset-assert 128)
|
||||
(atest ad-cmd 2 :inline :offset-assert 144)
|
||||
(atest-tra ad-cmd :inline :offset 144)
|
||||
(atest-def ad-cmd :inline :offset 160)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xb0
|
||||
:flag-assert #x9000000b0
|
||||
)
|
||||
|
||||
;; definition for method 3 of type tie-near-consts
|
||||
(defmethod inspect tie-near-consts ((obj tie-near-consts))
|
||||
(format #t "[~8x] ~A~%" obj 'tie-near-consts)
|
||||
(format #t "~Textra: #<qword @ #x~X>~%" (-> obj extra))
|
||||
(format #t "~Tgifbufs: #<qword @ #x~X>~%" (-> obj gifbufs))
|
||||
(format #t "~Tclrbufs: #<qword @ #x~X>~%" (-> obj clrbufs))
|
||||
(format #t "~Tadgif: #<qword @ #x~X>~%" (-> obj adgif))
|
||||
(format #t "~Tstrgif: #<qword @ #x~X>~%" (-> obj strgif))
|
||||
(format #t "~Tfangif: #<qword @ #x~X>~%" (-> obj fangif))
|
||||
(format #t "~Thvdfoffs: #<vector @ #x~X>~%" (-> obj hvdfoffs))
|
||||
(format #t "~Tinvhscale: #<vector @ #x~X>~%" (-> obj invhscale))
|
||||
(format #t "~Tguard: #<vector @ #x~X>~%" (-> obj guard))
|
||||
(format #t "~Tatest[2] @ #x~X~%" (-> obj atest))
|
||||
(format #t "~Tatest-tra: #<ad-cmd @ #x~X>~%" (-> obj atest))
|
||||
(format #t "~Tatest-def: #<ad-cmd @ #x~X>~%" (-> obj atest-def))
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for symbol tie-near-vu1-block, type vu-function
|
||||
(define tie-near-vu1-block (new 'static 'vu-function :length #x6f8 :qlength #x37c))
|
||||
|
||||
;; definition for function tie-near-init-consts
|
||||
;; INFO: Return type mismatch vector vs none.
|
||||
;; Used lq/sq
|
||||
(defun tie-near-init-consts ((arg0 tie-near-consts) (arg1 int))
|
||||
(set! (-> arg0 adgif tag) (new 'static 'gif-tag64 :nloop #x5 :nreg #x1))
|
||||
(set! (-> arg0 adgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(set! (-> arg0 atest-tra cmds) (the-as uint 71))
|
||||
(set! (-> arg0 atest-tra data) (the-as uint #x5026b))
|
||||
(set! (-> arg0 atest-def cmds) (the-as uint 71))
|
||||
(set! (-> arg0 atest-def data) (the-as uint #x5000e))
|
||||
(cond
|
||||
((zero? *subdivide-draw-mode*)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 3)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1)
|
||||
:nreg #x3
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 1)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type line-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 2)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 strgif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
(set! (-> arg0 fangif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 fangif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
(let ((f1-0 8388894.0)
|
||||
(f2-0 8389078.0)
|
||||
(f0-0 8389262.0)
|
||||
)
|
||||
(set! (-> arg0 gifbufs vector4w x) (the-as int f0-0))
|
||||
(set! (-> arg0 gifbufs vector4w y) (the-as int f2-0))
|
||||
(set! (-> arg0 gifbufs vector4w z) (the-as int f0-0))
|
||||
(set! (-> arg0 gifbufs vector4w w) (the-as int f2-0))
|
||||
(set! (-> arg0 extra vector4w x) (the-as int (+ f1-0 f2-0 f0-0)))
|
||||
(set! (-> arg0 extra vector4w y) (the-as int 0.0))
|
||||
(set! (-> arg0 extra vector4w z) (the-as int (+ f1-0 f2-0 f0-0)))
|
||||
)
|
||||
(set! (-> arg0 clrbufs vector4w x) 198)
|
||||
(set! (-> arg0 clrbufs vector4w y) 242)
|
||||
(set! (-> arg0 clrbufs vector4w z) 198)
|
||||
(set! (-> arg0 clrbufs vector4w w) 242)
|
||||
(let ((v1-41 *math-camera*))
|
||||
(set! (-> arg0 invhscale quad) (-> v1-41 inv-hmge-scale quad))
|
||||
(set! (-> arg0 hvdfoffs quad) (-> v1-41 hvdf-off quad))
|
||||
(set! (-> arg0 guard quad) (-> v1-41 guard quad))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function tie-near-init-engine
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-near-init-engine ((arg0 dma-buffer) (arg1 gs-test) (arg2 int))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(dma-buffer-add-vu-function arg0 tie-near-vu1-block 1)
|
||||
(let ((s4-0 11))
|
||||
(let* ((v1-2 arg0)
|
||||
(a0-2 (-> v1-2 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a0-2)) (logior #x10000000 (shr (shl s4-0 48) 48)))
|
||||
(let ((a1-4 #x5000000))
|
||||
(s.w! (+ a0-2 8) a1-4)
|
||||
)
|
||||
(let ((a1-6 (logior #x6c0003c6 (shr (shl s4-0 56) 40))))
|
||||
(s.w! (+ a0-2 12) a1-6)
|
||||
)
|
||||
(set! (-> v1-2 base) (&+ a0-2 16))
|
||||
)
|
||||
(tie-near-init-consts (the-as tie-near-consts (-> arg0 base)) arg2)
|
||||
(&+! (-> arg0 base) (* s4-0 16))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a0-6 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a0-6)) #x10000000)
|
||||
(let ((a1-9 #x15000008))
|
||||
(s.w! (+ a0-6 8) a1-9)
|
||||
)
|
||||
(let ((a1-10 #x13000000))
|
||||
(s.w! (+ a0-6 12) a1-10)
|
||||
)
|
||||
(set! (-> v1-5 base) (&+ a0-6 16))
|
||||
)
|
||||
(let* ((v1-6 arg0)
|
||||
(a0-8 (-> v1-6 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a0-8)) #x10000002)
|
||||
(s.w! (+ a0-8 8) 0)
|
||||
(let ((a1-12 #x30000000))
|
||||
(s.w! (+ a0-8 12) a1-12)
|
||||
)
|
||||
(set! (-> v1-6 base) (&+ a0-8 16))
|
||||
)
|
||||
(let ((v1-7 (-> arg0 base)))
|
||||
(set! (-> (the-as (pointer int32) v1-7)) #x4b000000)
|
||||
(let ((a0-11 #x4b000000))
|
||||
(s.w! (+ v1-7 4) a0-11)
|
||||
)
|
||||
(let ((a0-12 #x4b000000))
|
||||
(s.w! (+ v1-7 8) a0-12)
|
||||
)
|
||||
(let ((a0-13 #x4b000000))
|
||||
(s.w! (+ v1-7 12) a0-13)
|
||||
)
|
||||
(let ((a0-14 #x3000000))
|
||||
(s.w! (+ v1-7 16) a0-14)
|
||||
)
|
||||
(let ((a0-15 #x200002c))
|
||||
(s.w! (+ v1-7 20) a0-15)
|
||||
)
|
||||
(let ((a0-16 #x5000000))
|
||||
(s.w! (+ v1-7 24) a0-16)
|
||||
)
|
||||
(let ((a0-17 #x1000404))
|
||||
(s.w! (+ v1-7 28) a0-17)
|
||||
)
|
||||
(set! (-> arg0 base) (&+ v1-7 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function tie-near-end-buffer
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-near-end-buffer ((arg0 dma-buffer))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie-near))
|
||||
(let* ((v1-2 arg0)
|
||||
(a1-0 (-> v1-2 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a1-0)) #x10000002)
|
||||
(s.w! (+ a1-0 8) 0)
|
||||
(let ((a2-1 #x50000002))
|
||||
(s.w! (+ a1-0 12) a2-1)
|
||||
)
|
||||
(set! (-> v1-2 base) (&+ a1-0 16))
|
||||
)
|
||||
(let* ((v1-3 arg0)
|
||||
(a1-2 (-> v1-3 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer uint64) a1-2)) (make-u128 0 (the-as uint #x1000000000008001)))
|
||||
(let ((a2-4 (the-as uint #xeeeeeeeeeeeeeeee)))
|
||||
(s.d! (+ a1-2 8) a2-4)
|
||||
)
|
||||
(set! (-> v1-3 base) (&+ a1-2 16))
|
||||
)
|
||||
(let* ((v1-4 arg0)
|
||||
(a1-4 (-> v1-4 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a1-4)) #x5026b)
|
||||
(let ((a2-6 71))
|
||||
(s.d! (+ a1-4 8) a2-6)
|
||||
)
|
||||
(set! (-> v1-4 base) (&+ a1-4 16))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a1-6 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int64) a1-6)) #x10000002)
|
||||
(let ((a2-8 #x20000000))
|
||||
(s.w! (+ a1-6 8) a2-8)
|
||||
)
|
||||
(s.w! (+ a1-6 12) 0)
|
||||
(set! (-> v1-5 base) (&+ a1-6 16))
|
||||
)
|
||||
(let* ((v1-6 arg0)
|
||||
(a0-1 (-> v1-6 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer int32) a0-1)) #x15000004)
|
||||
(let ((a1-9 #x5000000))
|
||||
(s.w! (+ a0-1 4) a1-9)
|
||||
)
|
||||
(let ((a1-10 #x13000000))
|
||||
(s.w! (+ a0-1 8) a1-10)
|
||||
)
|
||||
(let ((a1-11 #x30000000))
|
||||
(s.w! (+ a0-1 12) a1-11)
|
||||
)
|
||||
(s.w! (+ a0-1 16) 0)
|
||||
(s.w! (+ a0-1 20) 0)
|
||||
(s.w! (+ a0-1 24) 0)
|
||||
(s.w! (+ a0-1 28) 0)
|
||||
(set! (-> v1-6 base) (&+ a0-1 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function tie-near-make-perspective-matrix
|
||||
(defun tie-near-make-perspective-matrix ((arg0 matrix))
|
||||
(column-scale-matrix! arg0 (-> *math-camera* hmge-scale) (-> *math-camera* camera-temp))
|
||||
)
|
||||
|
||||
;; definition for function tie-near-int-reg
|
||||
(defun tie-near-int-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"itemp"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"delta"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"dest-0"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"dest-1"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"dest-2"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"dest-3"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"delta-ptr"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"prev"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"itemp2"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function tie-near-float-reg
|
||||
(defun tie-near-float-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"vtx-0"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"vtx-1"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"vtx-2"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"vtx-3"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"hvtx-0"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"hvtx-1"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"hvtx-2"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"hvtx-3"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"tex-0"
|
||||
)
|
||||
((= v1-0 10)
|
||||
"tex-1"
|
||||
)
|
||||
((= v1-0 11)
|
||||
"tex-2"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"tex-3"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"deltas"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"invh"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"hvdfcl"
|
||||
)
|
||||
((= v1-0 16)
|
||||
"hvdfnc"
|
||||
)
|
||||
((= v1-0 17)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 18)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 21)
|
||||
"gifbuf"
|
||||
)
|
||||
((= v1-0 22)
|
||||
"clrbuf"
|
||||
)
|
||||
((= v1-0 23)
|
||||
"extra"
|
||||
)
|
||||
((= v1-0 24)
|
||||
"inds"
|
||||
)
|
||||
((= v1-0 25)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 26)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 27)
|
||||
"morph"
|
||||
)
|
||||
((= v1-0 28)
|
||||
"xyzofs"
|
||||
)
|
||||
((= v1-0 29)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 30)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 31)
|
||||
"--"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
+754
@@ -0,0 +1,754 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; definition for method 9 of type tie-fragment
|
||||
(defmethod login tie-fragment ((obj tie-fragment))
|
||||
(let ((s5-0 (-> obj gif-ref))
|
||||
(s4-0 (/ (-> obj tex-count) (the-as uint 5)))
|
||||
)
|
||||
(dotimes (s3-0 (the-as int s4-0))
|
||||
(adgif-shader-login-no-remap (-> s5-0 s3-0))
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 3 of type drawable-inline-array-instance-tie
|
||||
(defmethod inspect drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie))
|
||||
(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
|
||||
)
|
||||
|
||||
;; definition for method 5 of type drawable-inline-array-instance-tie
|
||||
;; INFO: Return type mismatch uint vs int.
|
||||
(defmethod asize-of drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie))
|
||||
(the-as int (+ (-> drawable-inline-array-instance-tie size) (* (+ (-> obj length) -1) 64)))
|
||||
)
|
||||
|
||||
;; definition for method 9 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 9 of type drawable-tree-instance-tie
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; INFO: Return type mismatch symbol vs drawable-tree-instance-tie.
|
||||
(defmethod login drawable-tree-instance-tie ((obj drawable-tree-instance-tie))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
(the-as drawable-tree-instance-tie #f)
|
||||
)
|
||||
|
||||
;; definition for method 3 of type prototype-tie
|
||||
(defmethod inspect prototype-tie ((obj prototype-tie))
|
||||
(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
|
||||
)
|
||||
|
||||
;; definition for method 9 of type prototype-tie
|
||||
(defmethod login prototype-tie ((obj prototype-tie))
|
||||
(dotimes (s5-0 (-> obj length))
|
||||
(login (-> obj data s5-0))
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 8 of type drawable-tree-instance-tie
|
||||
(defmethod mem-usage drawable-tree-instance-tie ((obj drawable-tree-instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(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)
|
||||
)
|
||||
(mem-usage (-> obj prototypes prototype-array-tie) arg0 (logior arg1 1))
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 8 of type tie-fragment
|
||||
(defmethod mem-usage tie-fragment ((obj tie-fragment) (arg0 memory-usage-block) (arg1 int))
|
||||
(when (logtest? arg1 2)
|
||||
(let ((v1-3 (* (-> obj color-count) 4))
|
||||
(a0-2 (cond
|
||||
((logtest? arg1 4)
|
||||
20
|
||||
)
|
||||
((logtest? arg1 8)
|
||||
21
|
||||
)
|
||||
(else
|
||||
22
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+! (-> arg0 data a0-2 count) 1)
|
||||
(+! (-> arg0 data a0-2 used) v1-3)
|
||||
(+! (-> arg0 data a0-2 total) (logand -4 (+ v1-3 3)))
|
||||
)
|
||||
(set! (-> arg0 length) (max 23 (-> arg0 length)))
|
||||
(set! obj obj)
|
||||
(goto cfg-13)
|
||||
)
|
||||
(set! (-> arg0 length) (max 18 (-> arg0 length)))
|
||||
(set! (-> arg0 data 9 name) "tie-fragment")
|
||||
(set! (-> arg0 data 10 name) "tie-gif")
|
||||
(set! (-> arg0 data 11 name) "tie-points")
|
||||
(set! (-> arg0 data 12 name) "tie-colors")
|
||||
(set! (-> arg0 data 14 name) "tie-debug")
|
||||
(set! (-> arg0 data 13 name) "tie-draw-points")
|
||||
(set! (-> arg0 data 17 name) "tie-generic")
|
||||
(+! (-> arg0 data 9 count) 1)
|
||||
(let ((v1-21 (asize-of obj)))
|
||||
(+! (-> arg0 data 9 used) v1-21)
|
||||
(+! (-> arg0 data 9 total) (logand -16 (+ v1-21 15)))
|
||||
)
|
||||
(let ((v1-26 (* (-> obj gif-count) 16)))
|
||||
(+! (-> arg0 data 10 count) (-> obj tex-count))
|
||||
(+! (-> arg0 data 10 used) v1-26)
|
||||
(+! (-> arg0 data 10 total) (logand -16 (+ v1-26 15)))
|
||||
)
|
||||
(let ((v1-31 (* (-> obj vertex-count) 16)))
|
||||
(+! (-> arg0 data 11 count) (-> obj vertex-count))
|
||||
(+! (-> arg0 data 11 used) v1-31)
|
||||
(+! (-> arg0 data 11 total) (logand -16 (+ v1-31 15)))
|
||||
)
|
||||
(let ((v1-36 (* (-> obj dp-qwc) 16)))
|
||||
(+! (-> arg0 data 13 count) (* (-> obj dp-qwc) 16))
|
||||
(+! (-> arg0 data 13 used) v1-36)
|
||||
(+! (-> arg0 data 13 total) (logand -16 (+ v1-36 15)))
|
||||
)
|
||||
(let ((v1-41 (* (-> obj generic-count) 16)))
|
||||
(+! (-> arg0 data 17 count) 1)
|
||||
(+! (-> arg0 data 17 used) v1-41)
|
||||
(+! (-> arg0 data 17 total) (logand -16 (+ v1-41 15)))
|
||||
)
|
||||
(when (nonzero? (-> obj debug-lines))
|
||||
(dotimes (s4-0 (-> obj debug-lines length))
|
||||
(+! (-> arg0 data 14 count) (-> (the-as (pointer int32) (-> obj debug-lines s4-0)) 0))
|
||||
(let ((v1-52 (asize-of (the-as basic (-> obj debug-lines s4-0)))))
|
||||
(+! (-> arg0 data 12 used) v1-52)
|
||||
(+! (-> arg0 data 12 total) (logand -16 (+ v1-52 15)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(label cfg-13)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 8 of type instance-tie
|
||||
(defmethod mem-usage instance-tie ((obj instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(set! (-> arg0 length) (max 19 (-> arg0 length)))
|
||||
(set! (-> arg0 data 18 name) "instance-tie")
|
||||
(+! (-> arg0 data 18 count) 1)
|
||||
(let ((v1-6 (asize-of obj)))
|
||||
(+! (-> arg0 data 18 used) v1-6)
|
||||
(+! (-> arg0 data 18 total) (logand -16 (+ v1-6 15)))
|
||||
)
|
||||
(when (nonzero? (-> obj error))
|
||||
(set! (-> arg0 length) (max 24 (-> arg0 length)))
|
||||
(set! (-> arg0 data 23 name) "instance-tie-colors*")
|
||||
(set! (-> arg0 data 19 name) "instance-tie-colors0")
|
||||
(set! (-> arg0 data 20 name) "instance-tie-colors1")
|
||||
(set! (-> arg0 data 21 name) "instance-tie-colors2")
|
||||
(set! (-> arg0 data 22 name) "instance-tie-colors3")
|
||||
(+! (-> arg0 data 23 count) 1)
|
||||
(let ((s3-0 (-> obj bucket-ptr)))
|
||||
(+ (-> arg0 data 19 used) (-> arg0 data 20 used) (-> arg0 data 21 used) (-> arg0 data 22 used))
|
||||
(dotimes (s2-0 4)
|
||||
(let ((a0-10 (-> s3-0 geometry-override s2-0)))
|
||||
(when (nonzero? a0-10)
|
||||
(let ((t9-1 (method-of-object a0-10 mem-usage))
|
||||
(a1-2 arg0)
|
||||
(v1-29 s2-0)
|
||||
)
|
||||
(t9-1 a0-10 a1-2 (logior
|
||||
(logior
|
||||
(cond
|
||||
((= v1-29 1)
|
||||
4
|
||||
)
|
||||
((= v1-29 2)
|
||||
8
|
||||
)
|
||||
((= v1-29 3)
|
||||
16
|
||||
)
|
||||
(else
|
||||
0
|
||||
)
|
||||
)
|
||||
2
|
||||
)
|
||||
arg1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for method 8 of type drawable-inline-array-instance-tie
|
||||
(defmethod mem-usage drawable-inline-array-instance-tie ((obj drawable-inline-array-instance-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(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
|
||||
)
|
||||
|
||||
;; definition for method 8 of type prototype-tie
|
||||
(defmethod mem-usage prototype-tie ((obj prototype-tie) (arg0 memory-usage-block) (arg1 int))
|
||||
(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
|
||||
)
|
||||
|
||||
;; definition for method 5 of type prototype-tie
|
||||
;; INFO: Return type mismatch uint vs int.
|
||||
(defmethod asize-of prototype-tie ((obj prototype-tie))
|
||||
(the-as int (+ (-> prototype-tie size) (* (+ (-> obj length) -1) 64)))
|
||||
)
|
||||
|
||||
;; definition of type tie-consts
|
||||
(deftype tie-consts (structure)
|
||||
((data uint32 24 :offset-assert 0)
|
||||
(vector vector 6 :inline :offset 0)
|
||||
(quads uint128 6 :offset 0)
|
||||
(adgif gs-gif-tag :inline :offset 0)
|
||||
(strgif gs-gif-tag :inline :offset 16)
|
||||
(extra vector :inline :offset 32)
|
||||
(gifbufs vector :inline :offset 48)
|
||||
(clrbufs qword :inline :offset 64)
|
||||
(misc qword :inline :offset 80)
|
||||
(atestgif gs-gif-tag :inline :offset 96)
|
||||
(atest ad-cmd 2 :inline :offset 112)
|
||||
(atest-tra ad-cmd :inline :offset 112)
|
||||
(atest-def ad-cmd :inline :offset 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x90
|
||||
:flag-assert #x900000090
|
||||
)
|
||||
|
||||
;; definition for method 3 of type tie-consts
|
||||
(defmethod inspect tie-consts ((obj tie-consts))
|
||||
(format #t "[~8x] ~A~%" obj 'tie-consts)
|
||||
(format #t "~Tdata[24] @ #x~X~%" (-> obj data))
|
||||
(format #t "~Tvector[6] @ #x~X~%" (-> obj data))
|
||||
(format #t "~Tquads[6] @ #x~X~%" (-> obj data))
|
||||
(format #t "~Tadgif: #<qword @ #x~X>~%" (-> obj data))
|
||||
(format #t "~Tstrgif: #<qword @ #x~X>~%" (-> obj strgif))
|
||||
(format #t "~Textra: #<qword @ #x~X>~%" (-> obj extra))
|
||||
(format #t "~Tgifbufs: #<qword @ #x~X>~%" (-> obj gifbufs))
|
||||
(format #t "~Tclrbufs: #<qword @ #x~X>~%" (-> obj clrbufs))
|
||||
(format #t "~Tmisc: #<qword @ #x~X>~%" (-> obj misc))
|
||||
(format #t "~Tatestgif: #<qword @ #x~X>~%" (-> obj atestgif))
|
||||
(format #t "~Tatest[2] @ #x~X~%" (-> obj atest))
|
||||
(format #t "~Tatest-tra: #<ad-cmd @ #x~X>~%" (-> obj atest))
|
||||
(format #t "~Tatest-def: #<ad-cmd @ #x~X>~%" (-> obj atest-def))
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for symbol tie-vu1-block, type vu-function
|
||||
(define tie-vu1-block (new 'static 'vu-function :length #x3e1 :qlength #x1f1))
|
||||
|
||||
;; definition for function tie-init-consts
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-init-consts ((arg0 tie-consts) (arg1 int))
|
||||
(set! (-> arg0 adgif tag) (new 'static 'gif-tag64 :nloop #x5 :nreg #x1))
|
||||
(set! (-> arg0 adgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(cond
|
||||
((zero? *subdivide-draw-mode*)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 3)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 1)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type line-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
((= *subdivide-draw-mode* 2)
|
||||
(set! (-> arg0 strgif tag)
|
||||
(new 'static 'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :fge #x1 :abe arg1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 strgif regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
(let ((f1-0 8388894.0)
|
||||
(f2-0 8389078.0)
|
||||
(f0-0 8389262.0)
|
||||
)
|
||||
(set! (-> arg0 gifbufs x) f0-0)
|
||||
(set! (-> arg0 gifbufs y) f2-0)
|
||||
(set! (-> arg0 gifbufs z) f0-0)
|
||||
(set! (-> arg0 gifbufs w) f2-0)
|
||||
(set! (-> arg0 extra x) (+ f1-0 f2-0 f0-0))
|
||||
(set! (-> arg0 extra y) 0.0)
|
||||
(set! (-> arg0 extra z) (+ f1-0 f2-0 f0-0))
|
||||
)
|
||||
(set! (-> arg0 clrbufs vector4w x) 198)
|
||||
(set! (-> arg0 clrbufs vector4w y) 242)
|
||||
(set! (-> arg0 clrbufs vector4w z) 198)
|
||||
(set! (-> arg0 clrbufs vector4w w) 242)
|
||||
(set! (-> arg0 atestgif tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> arg0 atestgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(set! (-> arg0 atest-tra cmd) (gs-reg test-1))
|
||||
(set! (-> arg0 atest-tra data) (the-as uint #x5026b))
|
||||
(set! (-> arg0 atest-def cmd) (gs-reg test-1))
|
||||
(set! (-> arg0 atest-def data) (the-as uint #x5000e))
|
||||
(set! (-> arg0 misc vector4w x) 0)
|
||||
(set! (-> arg0 misc vector4w y) -1)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function tie-init-engine
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-init-engine ((arg0 dma-buffer) (arg1 gs-test) (arg2 int))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(dma-buffer-add-vu-function arg0 tie-vu1-block 1)
|
||||
(let* ((v1-3 arg0)
|
||||
(a0-2 (the-as object (-> v1-3 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-3 base) (&+ (the-as pointer a0-2) 16))
|
||||
)
|
||||
(let* ((v1-4 arg0)
|
||||
(a0-4 (the-as object (-> v1-4 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-4 base) (the-as pointer (&+ (the-as gs-gif-tag a0-4) 16)))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a0-6 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-test) a0-6) 0) arg1)
|
||||
(set! (-> (the-as (pointer gs-reg64) a0-6) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ a0-6 16))
|
||||
)
|
||||
(let ((s4-1 9))
|
||||
(let* ((v1-6 arg0)
|
||||
(a0-8 (the-as object (-> v1-6 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-8) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s4-1))
|
||||
(set! (-> (the-as dma-packet a0-8) vif0) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as dma-packet a0-8) vif1)
|
||||
(new 'static 'vif-tag :imm #x3c6 :cmd (vif-cmd unpack-v4-32) :num s4-1)
|
||||
)
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer a0-8) 16))
|
||||
)
|
||||
(tie-init-consts (the-as tie-consts (-> arg0 base)) arg2)
|
||||
(&+! (-> arg0 base) (* s4-1 16))
|
||||
)
|
||||
(let* ((v1-9 arg0)
|
||||
(a0-12 (the-as object (-> v1-9 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-12) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-12) vif0) (new 'static 'vif-tag :imm #x8 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> (the-as dma-packet a0-12) vif1) (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(set! (-> v1-9 base) (&+ (the-as pointer a0-12) 16))
|
||||
)
|
||||
(let* ((v1-10 arg0)
|
||||
(a0-14 (the-as object (-> v1-10 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a0-14) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a0-14) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a0-14) vif1) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> v1-10 base) (&+ (the-as pointer a0-14) 16))
|
||||
)
|
||||
(let ((v1-11 (the-as object (-> arg0 base))))
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 x) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 y) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 z) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) v1-11) 0 w) #x4b000000)
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 4) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 5) (new 'static 'vif-tag :imm #x2c :cmd (vif-cmd offset)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 6) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as (pointer vif-tag) v1-11) 7) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> arg0 base) (&+ (the-as pointer v1-11) 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function tie-end-buffer
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun tie-end-buffer ((arg0 dma-buffer))
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
(let* ((v1-3 arg0)
|
||||
(a1-0 (the-as object (-> v1-3 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a1-0) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a1-0) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet a1-0) vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer a1-0) 16))
|
||||
)
|
||||
(let* ((v1-4 arg0)
|
||||
(a1-2 (the-as object (-> v1-4 base)))
|
||||
)
|
||||
(set! (-> (the-as gs-gif-tag a1-2) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> (the-as gs-gif-tag a1-2) 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-4 base) (&+ (the-as pointer a1-2) 16))
|
||||
)
|
||||
(let* ((v1-5 arg0)
|
||||
(a1-4 (-> v1-5 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-test) a1-4) 0)
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
)
|
||||
(set! (-> (the-as (pointer gs-reg64) a1-4) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ a1-4 16))
|
||||
)
|
||||
(let* ((v1-6 arg0)
|
||||
(a1-6 (the-as object (-> v1-6 base)))
|
||||
)
|
||||
(set! (-> (the-as dma-packet a1-6) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet a1-6) vif0) (new 'static 'vif-tag :cmd (vif-cmd stmask)))
|
||||
(set! (-> (the-as dma-packet a1-6) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer a1-6) 16))
|
||||
)
|
||||
(let* ((v1-7 arg0)
|
||||
(a0-1 (-> v1-7 base))
|
||||
)
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 0) (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 1) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 2) (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 3) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 4) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 5) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 6) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) a0-1) 7) (new 'static 'vif-tag))
|
||||
(set! (-> v1-7 base) (&+ a0-1 32))
|
||||
)
|
||||
0
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition (debug) for function tie-int-reg
|
||||
(defun-debug tie-int-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"itemp"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"point-ptr"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"clr-ptr"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"target-bp1-ptr"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"skip-bp2"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"target-bp2-ptr"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"target-ip1-ptr"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"target-ip2-ptr"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"ind/ind0"
|
||||
)
|
||||
((= v1-0 10)
|
||||
" ind1"
|
||||
)
|
||||
((= v1-0 11)
|
||||
" ind2"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"dest-ptr"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"dest2-ptr"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"skip-ips"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"kick-addr"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition (debug) for function tie-float-reg
|
||||
(defun-debug tie-float-reg ((arg0 int))
|
||||
(let ((v1-0 arg0))
|
||||
(cond
|
||||
((zero? v1-0)
|
||||
"zero"
|
||||
)
|
||||
((= v1-0 1)
|
||||
"t-mtx0"
|
||||
)
|
||||
((= v1-0 2)
|
||||
"t-mtx1"
|
||||
)
|
||||
((= v1-0 3)
|
||||
"t-mtx2"
|
||||
)
|
||||
((= v1-0 4)
|
||||
"t-mtx3"
|
||||
)
|
||||
((= v1-0 5)
|
||||
"vtx-0"
|
||||
)
|
||||
((= v1-0 6)
|
||||
"vtx-1"
|
||||
)
|
||||
((= v1-0 7)
|
||||
"vtx-2"
|
||||
)
|
||||
((= v1-0 8)
|
||||
"vtx-3"
|
||||
)
|
||||
((= v1-0 9)
|
||||
"pos-0/2"
|
||||
)
|
||||
((= v1-0 10)
|
||||
"pos-1/3"
|
||||
)
|
||||
((= v1-0 11)
|
||||
"clr-0"
|
||||
)
|
||||
((= v1-0 12)
|
||||
"clr-1"
|
||||
)
|
||||
((= v1-0 13)
|
||||
"clr-2"
|
||||
)
|
||||
((= v1-0 14)
|
||||
"clr-3"
|
||||
)
|
||||
((= v1-0 15)
|
||||
"tex-0"
|
||||
)
|
||||
((= v1-0 16)
|
||||
"tex-1"
|
||||
)
|
||||
((= v1-0 17)
|
||||
"tex-2"
|
||||
)
|
||||
((= v1-0 18)
|
||||
"tex-3"
|
||||
)
|
||||
((= v1-0 19)
|
||||
"res-0/2"
|
||||
)
|
||||
((= v1-0 20)
|
||||
"res-1/3"
|
||||
)
|
||||
((= v1-0 21)
|
||||
"gifbuf"
|
||||
)
|
||||
((= v1-0 22)
|
||||
"clrbuf"
|
||||
)
|
||||
((= v1-0 23)
|
||||
"extra"
|
||||
)
|
||||
((= v1-0 24)
|
||||
"inds"
|
||||
)
|
||||
((= v1-0 25)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 26)
|
||||
"--"
|
||||
)
|
||||
((= v1-0 27)
|
||||
"morph"
|
||||
)
|
||||
((= v1-0 28)
|
||||
"xyzofs"
|
||||
)
|
||||
((= v1-0 29)
|
||||
"clr1"
|
||||
)
|
||||
((= v1-0 30)
|
||||
"clr2"
|
||||
)
|
||||
((= v1-0 31)
|
||||
"--"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition (debug) for function tie-ints
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
;; Used lq/sq
|
||||
(defun-debug tie-ints ()
|
||||
(local-vars (sv-16 uint))
|
||||
(let ((gp-0 (the-as (pointer uint32) (+ #x3fa0 #x1100c000))))
|
||||
(dotimes (s5-0 16)
|
||||
(if (< s5-0 10)
|
||||
(format 0 " ")
|
||||
)
|
||||
(let ((s4-0 format)
|
||||
(s3-0 0)
|
||||
(s2-0 "vi~d: ~6d #x~4,'0X ~s~%")
|
||||
(s1-0 s5-0)
|
||||
(s0-0 (-> gp-0 (* s5-0 4)))
|
||||
)
|
||||
(set! sv-16 (-> gp-0 (* s5-0 4)))
|
||||
(let ((t1-0 (tie-int-reg s5-0)))
|
||||
(s4-0 s3-0 s2-0 s1-0 s0-0 sv-16 t1-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition (debug) for function tie-floats
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
;; Used lq/sq
|
||||
(defun-debug tie-floats ()
|
||||
(local-vars (sv-16 uint) (sv-32 uint))
|
||||
(let ((gp-0 (the-as (pointer uint32) (+ #x3da0 #x1100c000))))
|
||||
(dotimes (s5-0 32)
|
||||
(if (< s5-0 10)
|
||||
(format 0 " ")
|
||||
)
|
||||
(format
|
||||
0
|
||||
"vf~d: #x~8,'0X #x~8,'0X #x~8,'0X #x~8,'0X "
|
||||
s5-0
|
||||
(-> gp-0 (* s5-0 4))
|
||||
(-> gp-0 (+ (* s5-0 4) 1))
|
||||
(-> gp-0 (+ (* s5-0 4) 2))
|
||||
(-> gp-0 (+ (* s5-0 4) 3))
|
||||
)
|
||||
(let ((s4-0 format)
|
||||
(s3-0 0)
|
||||
(s2-0 "~F ~F ~F ~F ~s~%")
|
||||
(s1-0 (-> gp-0 (* s5-0 4)))
|
||||
(s0-0 (-> gp-0 (+ (* s5-0 4) 1)))
|
||||
)
|
||||
(set! sv-16 (-> gp-0 (+ (* s5-0 4) 2)))
|
||||
(set! sv-32 (-> gp-0 (+ (* s5-0 4) 3)))
|
||||
(let ((t2-1 (tie-float-reg s5-0)))
|
||||
(s4-0 s3-0 s2-0 s1-0 s0-0 sv-16 sv-32 t2-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -577,7 +577,7 @@
|
||||
(set! sv-16 (-> s1-2 array-data (the-as uint current-login-pos)))
|
||||
(set! sv-32 0)
|
||||
(while (< sv-32 4)
|
||||
(let ((a0-28 (-> sv-16 geometry sv-32)))
|
||||
(let ((a0-28 (-> sv-16 geometry-override sv-32)))
|
||||
(if (nonzero? a0-28)
|
||||
(login a0-28)
|
||||
)
|
||||
|
||||
@@ -186,7 +186,18 @@
|
||||
"command-get-process", // handle casts
|
||||
|
||||
// sage-finalboss
|
||||
"(method 7 sage-finalboss)" // inline-array stuff
|
||||
"(method 7 sage-finalboss)", // inline-array stuff
|
||||
|
||||
// appears twice
|
||||
"(method 9 drawable-tree-instance-tie)",
|
||||
"(method 11 drawable-tree-instance-tie)",
|
||||
"(method 12 drawable-tree-instance-tie)",
|
||||
"(method 13 drawable-tree-instance-tie)",
|
||||
|
||||
// not in use in PC port
|
||||
"tie-near-init-engine",
|
||||
"tie-near-end-buffer"
|
||||
|
||||
],
|
||||
|
||||
"skip_compile_states": {
|
||||
|
||||
@@ -12,4 +12,3 @@ add_executable(memory_dump_tool
|
||||
MemoryDumpTool/main.cpp)
|
||||
target_link_libraries(memory_dump_tool common decomp elzip)
|
||||
|
||||
install(TARGETS dgo_unpacker dgo_packer)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "third-party/11zip/include/elzip/elzip.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
Reference in New Issue
Block a user