mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
[decomp] sky/time of day (#883)
* time of day * goal code seems to work * stars at wrong spot * stars and sun work * debugging clouds * fix texture correction * sky works * cleanup, add profiler * clean up * final clean up * offline tests * missing include
This commit is contained in:
parent
d7eeddf2fc
commit
b2052016e2
|
@ -136,6 +136,13 @@ class Vector {
|
|||
return *this;
|
||||
}
|
||||
|
||||
Vector<T, Size>& operator/=(const T& val) {
|
||||
for (int i = 0; i < Size; i++) {
|
||||
m_data[i] /= val;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<T, Size> cross(const Vector<T, Size>& other) const {
|
||||
static_assert(Size == 3, "Size for cross");
|
||||
Vector<T, Size> result = {y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(),
|
||||
|
|
|
@ -83,4 +83,14 @@ T align4(T in) {
|
|||
template <typename T>
|
||||
T align64(T in) {
|
||||
return (in + 63) & (~T(63));
|
||||
}
|
||||
|
||||
inline u32 count_leading_zeros_u32(u32 in) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_clz(in);
|
||||
#else
|
||||
unsigned long result;
|
||||
_BitScanReverse(&result, in);
|
||||
return result;
|
||||
#endif
|
||||
}
|
25
common/util/colors.h
Normal file
25
common/util/colors.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace colors {
|
||||
// some reasonable colors that are different from each other
|
||||
constexpr int COLOR_COUNT = 131;
|
||||
u32 common_colors[COLOR_COUNT] = {
|
||||
0xF0F8FE, 0xFAEBD7, 0x00FFFF, 0x70DB93, 0xF0FFFF, 0xF5F5DC, 0x000000, 0x0000FF, 0x9F5F9F,
|
||||
0xB5A642, 0xD9D919, 0x8C7853, 0xA52A2A, 0x5F9EA0, 0xD2691E, 0xB87333, 0xFF7F50, 0xDC143C,
|
||||
0x00FFFF, 0x00008B, 0x5C4033, 0x008B8B, 0xB8860B, 0xA9A9A9, 0x006400, 0xBDB76B, 0x8B008B,
|
||||
0x4F4F2F, 0xFF8C00, 0x9932CD, 0x871F78, 0xE9967A, 0x6B238E, 0x2F4F4F, 0x97694F, 0x7093DB,
|
||||
0x9400D3, 0x855E42, 0x545454, 0x856363, 0xD19275, 0xB22222, 0x238E23, 0xCD7F32, 0xDBDB70,
|
||||
0xC0C0C0, 0x00FF00, 0x527F76, 0x93DB70, 0xFF69B4, 0x215E21, 0xCD5C5C, 0x4B0082, 0xFFFFF0,
|
||||
0x9F9F5F, 0xE6E6FA, 0xC0D9D9, 0xF08080, 0xE0FFFF, 0xA8A8A8, 0x90EE90, 0xFFB6C1, 0x8F8FBD,
|
||||
0xE9C2A6, 0x00FF00, 0x32CD32, 0xFF00FF, 0xE47833, 0x8E236B, 0x32CD99, 0x3232CD, 0x6B8E23,
|
||||
0xEAEAAE, 0x9370DB, 0x426F42, 0x7F00FF, 0x7FFF00, 0x70DBDB, 0xDB7093, 0xA68064, 0x2F2F4F,
|
||||
0xF5FFFA, 0xFFE4E1, 0x23238E, 0x4D4DFF, 0xFF6EC7, 0x00009C, 0xEBC79E, 0xCFB53B, 0x808000,
|
||||
0xFF7F00, 0xFF2400, 0xDB70DB, 0xEEE8AA, 0x8FBC8F, 0xAFEEEE, 0xBC8F8F, 0xEAADEA, 0xB0E0E6,
|
||||
0x800080, 0xD9D9F3, 0xFF0000, 0x5959AB, 0x4169E1, 0x8B4513, 0x6F4242, 0xF4A460, 0x8C1717,
|
||||
0x238E68, 0x8E6B23, 0xE6E8FA, 0x3299CC, 0x007FFF, 0xFFFAFA, 0xFF1CAE, 0x00FF7F, 0x236B8E,
|
||||
0x38B0DE, 0xDB9370, 0x008080, 0xD8BFD8, 0xFF6347, 0xADEAEA, 0x5C4033, 0x5C4033, 0x422F4F,
|
||||
0xCC3299, 0xD8D8BF, 0xFFFFFF, 0xFFFF00, 0x99CC32,
|
||||
};
|
||||
} // namespace colors
|
|
@ -2307,6 +2307,19 @@ void StoreInSymbolElement::push_to_stack(const Env& env, FormPool& pool, FormSta
|
|||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value, m_my_idx);
|
||||
val->update_children_from_stack(env, pool, stack, true);
|
||||
|
||||
if (m_cast_for_set) {
|
||||
// we'd need to cast for set. Let's see if we can simplify it instead:
|
||||
auto simplified = try_cast_simplify(val, *m_cast_for_set, pool, env, false);
|
||||
if (simplified) {
|
||||
if (m_cast_for_define && *m_cast_for_define == *m_cast_for_set) {
|
||||
// if we'd need exactly the same cast for a define, we can drop it too
|
||||
m_cast_for_define = {};
|
||||
}
|
||||
m_cast_for_set = {};
|
||||
val = simplified;
|
||||
}
|
||||
}
|
||||
|
||||
auto elt = pool.alloc_element<SetFormFormElement>(sym, val, m_cast_for_set, m_cast_for_define);
|
||||
elt->mark_popped();
|
||||
stack.push_form_element(elt, true);
|
||||
|
|
|
@ -632,6 +632,12 @@ Mips2C_Line handle_generic_op2(const Instruction& i0,
|
|||
instr_str};
|
||||
}
|
||||
|
||||
Mips2C_Line handle_plain_op(const Instruction& /*i0*/,
|
||||
const std::string& instr_str,
|
||||
const std::string& op_name) {
|
||||
return {fmt::format("c->{}();", op_name), instr_str};
|
||||
}
|
||||
|
||||
Mips2C_Line handle_or(const Instruction& i0, const std::string& instr_str) {
|
||||
if (is_gpr_3(i0, InstructionKind::OR, {}, rs7(), rr0())) {
|
||||
// set reg_dest to #f : or reg_dest, s7, r0
|
||||
|
@ -648,7 +654,7 @@ Mips2C_Line handle_or(const Instruction& i0, const std::string& instr_str) {
|
|||
instr_str};
|
||||
} else {
|
||||
// actually do a logical OR of two registers: or a0, a1, a2
|
||||
return handle_unknown(instr_str);
|
||||
return handle_generic_op3(i0, instr_str, "_or");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,6 +710,8 @@ Mips2C_Line handle_non_likely_branch_bc(const Instruction& i0, const std::string
|
|||
return {fmt::format("bc = ((s64){}) <= 0;", reg64_or_zero(i0.get_src(0))), instr_str};
|
||||
case InstructionKind::BC1F:
|
||||
return {fmt::format("bc = !cop1_bc;"), instr_str};
|
||||
case InstructionKind::BC1T:
|
||||
return {fmt::format("bc = cop1_bc;"), instr_str};
|
||||
default:
|
||||
return handle_unknown(instr_str);
|
||||
}
|
||||
|
@ -849,9 +857,13 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
|||
case InstructionKind::MULT3:
|
||||
case InstructionKind::PMINW:
|
||||
case InstructionKind::PMAXW:
|
||||
case InstructionKind::SUBU:
|
||||
case InstructionKind::DSRAV:
|
||||
return handle_generic_op3(i0, instr_str, {});
|
||||
case InstructionKind::MULS:
|
||||
return handle_generic_op3(i0, instr_str, "muls");
|
||||
case InstructionKind::DIVS:
|
||||
return handle_generic_op3(i0, instr_str, "divs");
|
||||
case InstructionKind::ADDS:
|
||||
return handle_generic_op3(i0, instr_str, "adds");
|
||||
case InstructionKind::SUBS:
|
||||
|
@ -893,6 +905,8 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
|||
return handle_generic_op2(i0, instr_str, "mfc1");
|
||||
case InstructionKind::MTC1:
|
||||
return handle_generic_op2(i0, instr_str, "mtc1");
|
||||
case InstructionKind::NEGS:
|
||||
return handle_generic_op2(i0, instr_str, "negs");
|
||||
case InstructionKind::CVTWS:
|
||||
return handle_generic_op2(i0, instr_str, "cvtws");
|
||||
case InstructionKind::CVTSW:
|
||||
|
@ -901,11 +915,15 @@ Mips2C_Line handle_normal_instr(Mips2C_Output& output,
|
|||
return handle_generic_op2(i0, instr_str, "pexew");
|
||||
case InstructionKind::SQRTS:
|
||||
return handle_generic_op2(i0, instr_str, "sqrts");
|
||||
case InstructionKind::PLZCW:
|
||||
return handle_generic_op2(i0, instr_str, "plzcw");
|
||||
case InstructionKind::LUI:
|
||||
return handle_lui(i0, instr_str);
|
||||
case InstructionKind::CLTS:
|
||||
output.needs_cop1_bc = true;
|
||||
return handle_clts(i0, instr_str);
|
||||
case InstructionKind::VWAITQ:
|
||||
return handle_plain_op(i0, instr_str, "vwaitq");
|
||||
default:
|
||||
unknown_count++;
|
||||
return handle_unknown(instr_str);
|
||||
|
|
|
@ -518,8 +518,10 @@
|
|||
|
||||
(generic-foreground 30) ;; ?
|
||||
(alpha-tex0 31)
|
||||
(sky-tex0 32)
|
||||
|
||||
(alpha-tex1 38)
|
||||
(sky-tex1 39)
|
||||
|
||||
(bucket-45 45)
|
||||
(bucket-46 46)
|
||||
|
@ -3545,6 +3547,8 @@
|
|||
(deftype dma-gif-packet (structure)
|
||||
((dma-vif dma-packet :inline :offset-assert 0)
|
||||
(gif uint64 2 :offset-assert 16) ;; guess
|
||||
(gif0 uint64 :offset 16)
|
||||
(gif1 uint64 :offset 24)
|
||||
(quad uint128 2 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
|
@ -4338,7 +4342,7 @@
|
|||
|
||||
;; - Symbols
|
||||
|
||||
(define-extern *fog-color* int)
|
||||
(define-extern *fog-color* rgba)
|
||||
(define-extern *default-regs-buffer* dma-buffer)
|
||||
|
||||
|
||||
|
@ -5050,7 +5054,7 @@
|
|||
(display? symbol :offset-assert 376)
|
||||
(meta-inside? symbol :offset-assert 380)
|
||||
(mood mood-context :offset-assert 384)
|
||||
(mood-func function :offset-assert 388)
|
||||
(mood-func (function mood-context float int none) :offset-assert 388)
|
||||
(vis-bits pointer :offset-assert 392)
|
||||
(all-visible? symbol :offset-assert 396)
|
||||
(force-all-visible? symbol :offset-assert 400)
|
||||
|
@ -7334,9 +7338,9 @@
|
|||
)
|
||||
|
||||
(deftype sky-tng-data (basic)
|
||||
((giftag-base qword :inline :offset-assert 16)
|
||||
(giftag-roof qword :inline :offset-assert 32)
|
||||
(giftag-ocean qword :inline :offset-assert 48)
|
||||
((giftag-base gs-gif-tag :inline :offset-assert 16);; changed
|
||||
(giftag-roof gs-gif-tag :inline :offset-assert 32)
|
||||
(giftag-ocean gs-gif-tag :inline :offset-assert 48)
|
||||
(fog vector :inline :offset-assert 64)
|
||||
(sky uint32 8 :offset-assert 80)
|
||||
(time float :offset-assert 112)
|
||||
|
@ -7354,8 +7358,8 @@
|
|||
((adgif-tmpl dma-gif-packet :inline :offset-assert 0)
|
||||
(draw-tmpl dma-gif-packet :inline :offset-assert 32)
|
||||
(blend-tmpl dma-gif-packet :inline :offset-assert 64)
|
||||
(sky-data uint128 5 :offset-assert 96)
|
||||
(cloud-data uint128 5 :offset-assert 176)
|
||||
(sky-data qword 5 :inline :offset-assert 96)
|
||||
(cloud-data qword 5 :inline :offset-assert 176)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x100
|
||||
|
@ -7502,7 +7506,7 @@
|
|||
:flag-assert #xb00000110
|
||||
(:methods
|
||||
(reset! (_type_) symbol 9)
|
||||
(TODO-RENAME-10 (_type_ int float float vector) object 10) ; returns float or error string
|
||||
(set-fade! (_type_ int float float vector) object 10) ; returns float or error string
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -7549,7 +7553,7 @@
|
|||
((active-count uint32 :offset-assert 4)
|
||||
(interp float :offset-assert 8)
|
||||
(current-interp float :offset-assert 12)
|
||||
(moods uint64 2 :offset-assert 16)
|
||||
(moods mood-context 2 :offset-assert 16)
|
||||
(current-fog mood-fog :inline :offset-assert 32)
|
||||
(current-sun mood-sun :inline :offset-assert 80)
|
||||
(current-prt-color vector :inline :offset-assert 112)
|
||||
|
@ -7559,7 +7563,7 @@
|
|||
(title-light-group light-group :inline :offset-assert 1888)
|
||||
(time float :offset-assert 2080)
|
||||
(target-interp float :offset-assert 2084)
|
||||
(erase-color uint32 :offset-assert 2088)
|
||||
(erase-color rgba :offset-assert 2088)
|
||||
(num-stars float :offset-assert 2092)
|
||||
(light-masks-0 uint8 2 :offset-assert 2096)
|
||||
(light-masks-1 uint8 2 :offset-assert 2098)
|
||||
|
@ -17536,24 +17540,25 @@
|
|||
|
||||
;; - Functions
|
||||
|
||||
(define-extern make-sky-textures function)
|
||||
(define-extern init-time-of-day (function none))
|
||||
(define-extern make-sky-textures (function time-of-day-context int none))
|
||||
(define-extern init-time-of-day (function none :behavior time-of-day-proc))
|
||||
(define-extern update-sky-tng-data (function float none))
|
||||
(define-extern time-of-day-update (function none))
|
||||
(define-extern start-time-of-day (function int))
|
||||
(define-extern time-of-day-setup (function symbol none))
|
||||
(define-extern time-of-day-update (function none :behavior time-of-day-proc))
|
||||
(define-extern start-time-of-day (function none))
|
||||
(define-extern time-of-day-setup (function symbol symbol))
|
||||
(define-extern set-time-of-day (function float none))
|
||||
(define-extern init-time-of-day-context (function time-of-day-context float))
|
||||
(define-extern update-time-of-day (function time-of-day-context none))
|
||||
|
||||
;; - Symbols
|
||||
|
||||
(define-extern time-of-day-tick state)
|
||||
(define-extern time-of-day-tick (state time-of-day-proc))
|
||||
(define-extern time-of-day-effect (function none)) ;; only 'nothing' is stored here, looks like dead code
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
;;(define-extern sky-base-polygons object) ;; unknown type
|
||||
(define-extern sky-base-polygons (inline-array sky-vertex))
|
||||
|
||||
|
||||
;; ----------------------
|
||||
|
@ -17580,37 +17585,37 @@
|
|||
|
||||
;; - Types
|
||||
|
||||
; (deftype sky-frame-data (structure)
|
||||
; ((data UNKNOWN 18 :offset-assert 0)
|
||||
; (world-homo-matrix matrix :inline :offset-assert 0)
|
||||
; (hmge-scale vector :inline :offset-assert 64)
|
||||
; (hvdf-offset vector :inline :offset-assert 80)
|
||||
; (consts vector :inline :offset-assert 96)
|
||||
; (pfog0 float :offset-assert 96)
|
||||
; (radius float :offset-assert 100)
|
||||
; (nokick float :offset-assert 108)
|
||||
; (strip-giftag qword :inline :offset-assert 112)
|
||||
; (col-adgif qword :inline :offset-assert 128)
|
||||
; (save UNKNOWN 5 :offset-assert 144)
|
||||
; (sun-fan-giftag qword :inline :offset-assert 224)
|
||||
; (sun-strip-giftag qword :inline :offset-assert 240)
|
||||
; (sun-alpha qword :inline :offset-assert 256)
|
||||
; (sun-alpha-giftag qword :inline :offset-assert 272)
|
||||
; )
|
||||
; :method-count-assert 9
|
||||
; :size-assert #x120
|
||||
; :flag-assert #x900000120
|
||||
; )
|
||||
(deftype sky-frame-data (structure)
|
||||
((data uint128 18 :offset-assert 0)
|
||||
(world-homo-matrix matrix :inline :offset 0)
|
||||
(hmge-scale vector :inline :offset 64)
|
||||
(hvdf-offset vector :inline :offset 80)
|
||||
(consts vector :inline :offset 96)
|
||||
(pfog0 float :offset 96)
|
||||
(radius float :offset 100)
|
||||
(nokick float :offset 108)
|
||||
(strip-giftag qword :inline :offset 112)
|
||||
(col-adgif qword :inline :offset 128)
|
||||
(save uint128 5 :offset 144)
|
||||
(sun-fan-giftag qword :inline :offset 224)
|
||||
(sun-strip-giftag qword :inline :offset 240)
|
||||
(sun-alpha qword :inline :offset 256)
|
||||
(sun-alpha-giftag qword :inline :offset 272)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x120
|
||||
:flag-assert #x900000120
|
||||
)
|
||||
|
||||
;; - Functions
|
||||
|
||||
(define-extern sky-add-frame-data function)
|
||||
(define-extern sky-make-sun-data (function sky-parms int float none))
|
||||
(define-extern sky-make-moon-data (function sky-parms float none))
|
||||
(define-extern sky-make-light function)
|
||||
(define-extern sky-make-light (function sky-parms light int rgba none))
|
||||
(define-extern sky-init-upload-data function)
|
||||
(define-extern sky-upload function)
|
||||
(define-extern sky-draw function)
|
||||
(define-extern sky-draw (function sky-parms none))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
|
@ -17625,29 +17630,29 @@
|
|||
|
||||
;; - Functions
|
||||
|
||||
(define-extern copy-sky-texture function)
|
||||
(define-extern copy-cloud-texture function)
|
||||
(define-extern init-sky-regs function)
|
||||
(define-extern render-sky-tri function)
|
||||
(define-extern close-sky-buffer function)
|
||||
(define-extern set-tex-offset function)
|
||||
(define-extern render-sky-quad function)
|
||||
(define-extern sky-tng-setup-cloud-layer function)
|
||||
(define-extern copy-sky-texture (function dma-buffer adgif-shader float none))
|
||||
(define-extern copy-cloud-texture (function dma-buffer adgif-shader float none))
|
||||
(define-extern init-sky-regs (function none))
|
||||
(define-extern render-sky-tri (function (inline-array sky-vertex) dma-buffer none))
|
||||
(define-extern close-sky-buffer (function dma-buffer none))
|
||||
(define-extern set-tex-offset (function int int none))
|
||||
(define-extern render-sky-quad (function int dma-buffer none))
|
||||
(define-extern sky-tng-setup-cloud-layer (function float float vector (inline-array sky-vertex) none))
|
||||
(define-extern draw-large-polygon function)
|
||||
(define-extern init-sky-tng-data function)
|
||||
(define-extern init-sky-tng-data (function sky-tng-data none))
|
||||
(define-extern clip-polygon-against-positive-hyperplane function)
|
||||
(define-extern clip-polygon-against-negative-hyperplane function)
|
||||
(define-extern sky-duplicate-polys function)
|
||||
(define-extern sky-tng-setup-clouds function)
|
||||
(define-extern sky-tng-setup-clouds (function none))
|
||||
(define-extern render-sky-tng (function time-of-day-context none))
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
;;(define-extern *sky-work* object) ;; unknown type
|
||||
(define-extern *sky-work* sky-work) ;; unknown type
|
||||
(define-extern *sky-tng-data* sky-tng-data) ;; unknown type
|
||||
;;(define-extern sky-roof-polygons object) ;; unknown type
|
||||
;;(define-extern sky-cloud-polygons object) ;; unknown type
|
||||
;;(define-extern sky-cloud-polygon-indices object) ;; unknown type
|
||||
(define-extern sky-roof-polygons (inline-array sky-vertex)) ;; unknown type
|
||||
(define-extern sky-cloud-polygons (inline-array sky-vertex)) ;; unknown type
|
||||
(define-extern sky-cloud-polygon-indices (pointer uint8)) ;; unknown type
|
||||
|
||||
|
||||
;; ----------------------
|
||||
|
|
|
@ -671,8 +671,8 @@
|
|||
],
|
||||
|
||||
"time-of-day": [
|
||||
[10, "(function none)"],
|
||||
[12, "(function sparticle-system sparticle-cpuinfo int none)"]
|
||||
[10, "(function none :behavior time-of-day-proc)"],
|
||||
[12, "(function sparticle-system sparticle-cpuinfo none)"]
|
||||
],
|
||||
|
||||
"basebutton": [
|
||||
|
|
|
@ -547,7 +547,15 @@
|
|||
"particle-adgif",
|
||||
"sp-launch-particles-var",
|
||||
"sp-process-block-2d",
|
||||
"sp-process-block-3d"
|
||||
"sp-process-block-3d",
|
||||
"draw-large-polygon",
|
||||
"clip-polygon-against-positive-hyperplane",
|
||||
"clip-polygon-against-negative-hyperplane",
|
||||
"render-sky-quad",
|
||||
"render-sky-tri",
|
||||
"init-sky-regs",
|
||||
"set-tex-offset",
|
||||
"adgif-shader<-texture-with-update!"
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -799,6 +799,21 @@
|
|||
["L733", "uint64", true]
|
||||
],
|
||||
|
||||
"sky": [
|
||||
["L13", "vu-function"]
|
||||
],
|
||||
|
||||
"sky-tng": [
|
||||
["L82", "sky-work"],
|
||||
// 576 bytes, 32 bytes each
|
||||
["L81", "(inline-array sky-vertex)", 12],
|
||||
["L80", "(inline-array sky-vertex)", 12],
|
||||
["L79", "(inline-array sky-vertex)", 72],
|
||||
["L78", "(pointer uint8)", 48],
|
||||
["L77", "vector"],
|
||||
["L76", "vector"]
|
||||
],
|
||||
|
||||
"effect-control": [
|
||||
["L300", "float", true],
|
||||
["L301", "float", true],
|
||||
|
|
|
@ -1201,7 +1201,8 @@
|
|||
],
|
||||
|
||||
"update-time-of-day": [
|
||||
[16, "(array float)"] // TODO - broken!
|
||||
[16, "(array float)"], // TODO - broken!
|
||||
[48, "vector"]
|
||||
],
|
||||
|
||||
"check-drop-level-rain": [
|
||||
|
@ -2783,5 +2784,17 @@
|
|||
[32, "vector"]
|
||||
],
|
||||
|
||||
"init-sky-regs": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"set-tex-offset": [
|
||||
[16, "vector"]
|
||||
],
|
||||
|
||||
"sky-tng-setup-cloud-layer": [
|
||||
[16,["inline-array", "sky-vertex", 12]]
|
||||
],
|
||||
|
||||
"placeholder-do-not-add-below!": []
|
||||
}
|
||||
|
|
|
@ -2634,23 +2634,6 @@
|
|||
[[15, 250], "s5", "symbol"]
|
||||
],
|
||||
|
||||
"time-of-day-update": [
|
||||
[[0, 999], "s6", "time-of-day-proc"]
|
||||
],
|
||||
|
||||
"(anon-function 10 time-of-day)": [
|
||||
[[0, 999], "s6", "time-of-day-proc"]
|
||||
],
|
||||
|
||||
"init-time-of-day": [
|
||||
[[0, 999], "s6", "time-of-day-proc"],
|
||||
[[51, 54], "t9", "(function object object object)"]
|
||||
],
|
||||
|
||||
"start-time-of-day": [
|
||||
[[20, 23], "t9", "(function process function object)"]
|
||||
],
|
||||
|
||||
"cam-master-effect": [
|
||||
[[0, 999], "s6", "camera-master"]
|
||||
],
|
||||
|
@ -3934,6 +3917,82 @@
|
|||
[2, "v1", "(pointer process-drawable)"]
|
||||
],
|
||||
|
||||
"update-time-of-day": [
|
||||
[46, "v0", "(array float)"]
|
||||
],
|
||||
|
||||
"sky-make-light": [
|
||||
[[10, 23], "a0", "sky-sun-data"]
|
||||
],
|
||||
|
||||
"make-sky-textures": [
|
||||
[[90, 94], "a0", "dma-packet"],
|
||||
[[100, 103], "a0", "gs-gif-tag"],
|
||||
[108, "a0", "(pointer gs-alpha)"],
|
||||
[110, "a0", "(pointer gs-reg64)"],
|
||||
[[121, 124], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"copy-cloud-texture": [
|
||||
[[2, 48], "s5", "(pointer uint128)"],
|
||||
[[28, 32], "s4", "adgif-shader"]
|
||||
],
|
||||
|
||||
"copy-sky-texture": [
|
||||
[[2, 48], "s5", "(pointer uint128)"],
|
||||
[[28, 32], "s4", "adgif-shader"]
|
||||
],
|
||||
|
||||
"render-sky-tng": [
|
||||
[[244, 262], "s2", "(inline-array sky-vertex)"],
|
||||
[[34, 38], "a0", "dma-packet"],
|
||||
[[44, 47], "a0", "gs-gif-tag"],
|
||||
[52, "a0", "(pointer gs-zbuf)"],
|
||||
[54, "a0", "(pointer gs-reg64)"],
|
||||
[56, "a0", "(pointer gs-test)"],
|
||||
[58, "a0", "(pointer gs-reg64)"],
|
||||
[60, "a0", "(pointer gs-alpha)"],
|
||||
[62, "a0", "(pointer gs-reg64)"],
|
||||
[[74, 78], "a0", "dma-packet"],
|
||||
[[84, 87], "a0", "gs-gif-tag"],
|
||||
|
||||
[107, "s2", "(pointer gs-tex0)"],
|
||||
[109, "s2", "(pointer gs-reg64)"],
|
||||
[111, "s2", "(pointer gs-tex1)"],
|
||||
[113, "s2", "(pointer gs-reg64)"],
|
||||
[115, "s2", "(pointer gs-clamp)"],
|
||||
[117, "s2", "(pointer gs-reg64)"],
|
||||
[118, "s2", "(pointer uint64)"],
|
||||
[120, "s2", "(pointer gs-reg64)"],
|
||||
[[159, 166], "s3", "dma-packet"],
|
||||
[[171, 175], "a0", "dma-packet"],
|
||||
[[181, 184], "a0", "gs-gif-tag"],
|
||||
|
||||
[189, "s2", "(pointer gs-alpha)"],
|
||||
[191, "s2", "(pointer gs-reg64)"],
|
||||
[209, "s2", "(pointer gs-tex0)"],
|
||||
[211, "s2", "(pointer gs-reg64)"],
|
||||
[213, "s2", "(pointer gs-tex1)"],
|
||||
[215, "s2", "(pointer gs-reg64)"],
|
||||
[216, "s2", "(pointer gs-clamp)"],
|
||||
[218, "s2", "(pointer gs-reg64)"],
|
||||
[219, "s2", "(pointer int64)"],
|
||||
[221, "s2", "(pointer gs-reg64)"],
|
||||
[[303, 310], "s3", "dma-packet"],
|
||||
[[312, 316], "v1", "dma-packet"]
|
||||
],
|
||||
|
||||
"render-sky-tri": [
|
||||
[5, "a0", "int"],
|
||||
[[6, 50], "a0", "(inline-array sky-vertex)"],
|
||||
[[25, 48], "a3", "(inline-array sky-vertex)"]
|
||||
],
|
||||
|
||||
"render-sky-quad": [
|
||||
[[9, 32], "a0", "(inline-array sky-vertex)"],
|
||||
[[33, 62], "a3", "(inline-array sky-vertex)"]
|
||||
],
|
||||
|
||||
"(method 10 effect-control)": [
|
||||
[88, "v1", "collide-shape-moving"],
|
||||
[143, "s3", "(pointer sparticle-launch-group)"],
|
||||
|
|
|
@ -273,6 +273,7 @@ goos::Object decompile_value_array(const TypeSpec& elt_type,
|
|||
}
|
||||
elt_bytes.push_back(word.get_byte(j % 4));
|
||||
}
|
||||
assert(elt_type != TypeSpec("uint128"));
|
||||
array_def.push_back(decompile_value(elt_type, elt_bytes, ts));
|
||||
}
|
||||
|
||||
|
@ -865,6 +866,10 @@ goos::Object bitfield_defs_print(const TypeSpec& type,
|
|||
} else if (def.is_signed) {
|
||||
result.push_back(
|
||||
pretty_print::to_symbol(fmt::format(":{} {}", def.field_name, (s64)def.value)));
|
||||
} else if (def.nested_field) {
|
||||
result.push_back(pretty_print::to_symbol(fmt::format(
|
||||
":{} {}", def.field_name,
|
||||
bitfield_defs_print(def.nested_field->field_type, def.nested_field->fields).print())));
|
||||
} else {
|
||||
result.push_back(
|
||||
pretty_print::to_symbol(fmt::format(":{} #x{:x}", def.field_name, def.value)));
|
||||
|
@ -1087,6 +1092,7 @@ goos::Object decompile_boxed_array(const DecompilerLabel& label,
|
|||
}
|
||||
elt_bytes.push_back(word.get_byte(j % 4));
|
||||
}
|
||||
assert(content_type != TypeSpec("uint128"));
|
||||
result.push_back(decompile_value(content_type, elt_bytes, ts));
|
||||
}
|
||||
return pretty_print::build_list(result);
|
||||
|
|
|
@ -61,9 +61,11 @@ set(RUNTIME_SOURCE
|
|||
kernel/ksound.cpp
|
||||
mips2c/mips2c_table.cpp
|
||||
mips2c/functions/draw_string.cpp
|
||||
mips2c/functions/sky_tng.cpp
|
||||
mips2c/functions/sparticle.cpp
|
||||
mips2c/functions/sparticle_launcher.cpp
|
||||
mips2c/functions/test_func.cpp
|
||||
mips2c/functions/texture.cpp
|
||||
overlord/dma.cpp
|
||||
overlord/fake_iso.cpp
|
||||
overlord/iso.cpp
|
||||
|
@ -88,7 +90,9 @@ set(RUNTIME_SOURCE
|
|||
graphics/opengl_renderer/debug_gui.cpp
|
||||
graphics/opengl_renderer/DirectRenderer.cpp
|
||||
graphics/opengl_renderer/OpenGLRenderer.cpp
|
||||
graphics/opengl_renderer/Profiler.cpp
|
||||
graphics/opengl_renderer/Shader.cpp
|
||||
graphics/opengl_renderer/SkyRenderer.cpp
|
||||
graphics/opengl_renderer/SpriteRenderer.cpp
|
||||
graphics/opengl_renderer/TextureUploadHandler.cpp
|
||||
graphics/texture/TextureConverter.cpp
|
||||
|
|
|
@ -81,6 +81,10 @@ std::string GifTag::print() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string register_address_name(u32 reg) {
|
||||
return register_address_name(GsRegisterAddress(reg));
|
||||
}
|
||||
|
||||
std::string register_address_name(GsRegisterAddress reg) {
|
||||
switch (reg) {
|
||||
case GsRegisterAddress::PRIM:
|
||||
|
|
|
@ -59,10 +59,6 @@ struct GifTag {
|
|||
u64 data[2];
|
||||
};
|
||||
|
||||
struct AdGif {
|
||||
GifTag giftag[5];
|
||||
};
|
||||
|
||||
std::string reg_descriptor_name(GifTag::RegisterDescriptor reg);
|
||||
|
||||
enum class GsRegisterAddress : u8 {
|
||||
|
@ -125,6 +121,7 @@ enum class GsRegisterAddress : u8 {
|
|||
enum class TextureFormat { PSMZ32, PSMZ24, PSMZ16, PSMZ16S };
|
||||
|
||||
std::string register_address_name(GsRegisterAddress reg);
|
||||
std::string register_address_name(u32 reg);
|
||||
|
||||
struct GsZbuf {
|
||||
GsZbuf(u64 val) : data(val) {}
|
||||
|
@ -332,4 +329,18 @@ struct GsTexa {
|
|||
std::string print() const;
|
||||
|
||||
u64 data = 0;
|
||||
};
|
||||
|
||||
// not including the giftag
|
||||
struct AdGifData {
|
||||
u64 tex0_data;
|
||||
u64 tex0_addr;
|
||||
u64 tex1_data;
|
||||
u64 tex1_addr;
|
||||
u64 mip_data;
|
||||
u64 mip_addr;
|
||||
u64 clamp_data;
|
||||
u64 clamp_addr;
|
||||
u64 alpha_data;
|
||||
u64 alpha_addr;
|
||||
};
|
45
game/graphics/opengl_renderer/AdgifHandler.h
Normal file
45
game/graphics/opengl_renderer/AdgifHandler.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/graphics/dma/gs.h"
|
||||
|
||||
class AdgifHelper {
|
||||
public:
|
||||
// takes the 5QW of adgif data
|
||||
explicit AdgifHelper(const u8* data) {
|
||||
memcpy(&m_data, data, 16 * 5);
|
||||
m_tex0 = GsTex0(m_data.tex0_data);
|
||||
m_tex1 = GsTex1(m_data.tex1_data);
|
||||
m_alpha = GsAlpha(m_data.alpha_data);
|
||||
}
|
||||
|
||||
bool is_normal_adgif() const {
|
||||
return (u8)m_data.tex0_addr == (u32)GsRegisterAddress::TEX0_1 &&
|
||||
(u8)m_data.tex1_addr == (u32)GsRegisterAddress::TEX1_1 &&
|
||||
(u8)m_data.mip_addr == (u32)GsRegisterAddress::MIPTBP1_1 &&
|
||||
(u8)m_data.clamp_addr == (u32)GsRegisterAddress::CLAMP_1 &&
|
||||
(u8)m_data.alpha_addr == (u32)GsRegisterAddress::ALPHA_1;
|
||||
}
|
||||
|
||||
std::string print() const {
|
||||
std::string result;
|
||||
result +=
|
||||
fmt::format("[0] {}\n {}\n", register_address_name(m_data.tex0_addr), m_tex0.print());
|
||||
result +=
|
||||
fmt::format("[1] {}\n {}\n", register_address_name(m_data.tex1_addr), m_tex1.print());
|
||||
result += fmt::format("[2] {}\n", register_address_name(m_data.mip_addr));
|
||||
result += fmt::format("[3] {}\n", register_address_name(m_data.clamp_addr));
|
||||
result +=
|
||||
fmt::format("[4] {}\n {}\n", register_address_name(m_data.alpha_addr), m_alpha.print());
|
||||
return result;
|
||||
}
|
||||
|
||||
const GsAlpha& alpha() const { return m_alpha; }
|
||||
|
||||
const GsTex0& tex0() const { return m_tex0; }
|
||||
|
||||
private:
|
||||
AdGifData m_data;
|
||||
GsTex0 m_tex0;
|
||||
GsTex1 m_tex1;
|
||||
GsAlpha m_alpha;
|
||||
};
|
|
@ -9,7 +9,9 @@ std::string BucketRenderer::name_and_id() const {
|
|||
EmptyBucketRenderer::EmptyBucketRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id) {}
|
||||
|
||||
void EmptyBucketRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void EmptyBucketRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& /*prof*/) {
|
||||
// an empty bucket should have 4 things:
|
||||
// a NEXT in the bucket buffer
|
||||
// a CALL that calls the default register buffer chain
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "game/graphics/dma/dma_chain_read.h"
|
||||
#include "game/graphics/opengl_renderer/Shader.h"
|
||||
#include "game/graphics/texture/TexturePool.h"
|
||||
#include "game/graphics/opengl_renderer/Profiler.h"
|
||||
|
||||
/*!
|
||||
* Matches the bucket-id enum in GOAL
|
||||
|
@ -12,9 +13,11 @@
|
|||
enum class BucketId {
|
||||
BUCKET0 = 0,
|
||||
BUCKET1 = 1,
|
||||
SKY_DRAW = 3,
|
||||
TFRAG_TEX_LEVEL0 = 5,
|
||||
SHRUB_TEX_LEVEL0 = 19,
|
||||
ALPHA_TEX_LEVEL0 = 31,
|
||||
SKY_LEVEL0 = 32,
|
||||
PRIS_TEX_LEVEL0 = 48,
|
||||
WATER_TEX_LEVEL0 = 57,
|
||||
// ...
|
||||
|
@ -49,7 +52,9 @@ struct SharedRenderState {
|
|||
class BucketRenderer {
|
||||
public:
|
||||
BucketRenderer(const std::string& name, BucketId my_id) : m_name(name), m_my_id(my_id) {}
|
||||
virtual void render(DmaFollower& dma, SharedRenderState* render_state) = 0;
|
||||
virtual void render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) = 0;
|
||||
std::string name_and_id() const;
|
||||
virtual ~BucketRenderer() = default;
|
||||
bool& enabled() { return m_enabled; }
|
||||
|
@ -69,7 +74,7 @@ class BucketRenderer {
|
|||
class EmptyBucketRenderer : public BucketRenderer {
|
||||
public:
|
||||
EmptyBucketRenderer(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state) override;
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
bool empty() const override { return true; }
|
||||
void draw_debug_window() override {}
|
||||
};
|
|
@ -21,7 +21,7 @@ DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batc
|
|||
glBufferData(GL_ARRAY_BUFFER, m_ogl.color_buffer_bytes, nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.st_buffer);
|
||||
m_ogl.st_buffer_bytes = batch_size * 3 * 2 * sizeof(float);
|
||||
m_ogl.st_buffer_bytes = batch_size * 3 * 3 * sizeof(float);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_ogl.st_buffer_bytes, nullptr, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ DirectRenderer::~DirectRenderer() {
|
|||
/*!
|
||||
* Render from a DMA bucket.
|
||||
*/
|
||||
void DirectRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void DirectRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// if we're rendering from a bucket, we should start off we a totally reset state:
|
||||
reset_state();
|
||||
setup_common_state(render_state);
|
||||
|
@ -45,7 +47,7 @@ void DirectRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
|||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
auto data = dma.read_and_advance();
|
||||
if (data.size_bytes && m_enabled) {
|
||||
render_vif(data.vif0(), data.vif1(), data.data, data.size_bytes, render_state);
|
||||
render_vif(data.vif0(), data.vif1(), data.data, data.size_bytes, render_state, prof);
|
||||
}
|
||||
|
||||
if (dma.current_tag_offset() == render_state->default_regs_buffer) {
|
||||
|
@ -57,7 +59,7 @@ void DirectRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
|||
}
|
||||
|
||||
if (m_enabled) {
|
||||
flush_pending(render_state);
|
||||
flush_pending(render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +93,7 @@ float u32_to_sc(u32 in) {
|
|||
return (flt - 0.5) * 16.0;
|
||||
}
|
||||
|
||||
void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
||||
void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (m_prim_buffer.vert_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -117,12 +119,6 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
m_texture_state.needs_gl_update = false;
|
||||
}
|
||||
|
||||
if (m_debug_state.wireframe) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
} else {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
if (m_debug_state.disable_texture) {
|
||||
// a bit of a hack, this forces the non-textured shader always.
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
|
@ -131,6 +127,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
if (m_debug_state.red) {
|
||||
render_state->shaders[ShaderId::DEBUG_RED].activate();
|
||||
glDisable(GL_BLEND);
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
m_blend_state_needs_gl_update = true;
|
||||
}
|
||||
|
||||
// hacks
|
||||
|
@ -151,8 +149,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
m_prim_buffer.rgba_u8.data());
|
||||
if (m_prim_gl_state.texture_enable) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.st_buffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, m_prim_buffer.sts.size() * sizeof(math::Vector<float, 2>),
|
||||
m_prim_buffer.sts.data());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, m_prim_buffer.stqs.size() * sizeof(math::Vector<float, 3>),
|
||||
m_prim_buffer.stqs.data());
|
||||
}
|
||||
|
||||
// setup attributes:
|
||||
|
@ -179,7 +177,7 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.st_buffer);
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, // location 0 in the shader
|
||||
2, // 3 floats per vert
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored,
|
||||
0, // tightly packed
|
||||
|
@ -190,8 +188,14 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
|
||||
int draw_count = 0;
|
||||
if (m_mode == Mode::SPRITE_CPU) {
|
||||
assert(m_texture_state.tcc);
|
||||
assert(m_prim_gl_state.texture_enable);
|
||||
if (!m_prim_gl_state.texture_enable) {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
} else {
|
||||
assert(m_texture_state.tcc);
|
||||
assert(m_prim_gl_state.texture_enable);
|
||||
render_state->shaders[ShaderId::SPRITE_CPU].activate();
|
||||
}
|
||||
|
||||
if (m_sprite_mode.do_first_draw) {
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
draw_count++;
|
||||
|
@ -201,6 +205,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
glDepthMask(GL_FALSE);
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
glDepthMask(GL_TRUE);
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
m_blend_state_needs_gl_update = true;
|
||||
draw_count++;
|
||||
}
|
||||
} else {
|
||||
|
@ -208,8 +214,20 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state) {
|
|||
draw_count++;
|
||||
}
|
||||
|
||||
if (m_debug_state.wireframe) {
|
||||
render_state->shaders[ShaderId::DEBUG_RED].activate();
|
||||
glDisable(GL_BLEND);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
draw_count++;
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
m_triangles += draw_count * (m_prim_buffer.vert_count / 3);
|
||||
int n_tris = draw_count * (m_prim_buffer.vert_count / 3);
|
||||
prof.add_tri(n_tris);
|
||||
prof.add_draw_call(draw_count);
|
||||
m_triangles += n_tris;
|
||||
m_draw_calls += draw_count;
|
||||
m_prim_buffer.vert_count = 0;
|
||||
}
|
||||
|
@ -221,6 +239,8 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
|||
if (m_texture_state.tcc) {
|
||||
if (m_mode == Mode::SPRITE_CPU) {
|
||||
render_state->shaders[ShaderId::SPRITE_CPU].activate();
|
||||
} else if (m_mode == Mode::SKY) {
|
||||
assert(false);
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].activate();
|
||||
}
|
||||
|
@ -229,7 +249,11 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
|||
}
|
||||
update_gl_texture(render_state);
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
if (m_mode == Mode::SKY) {
|
||||
render_state->shaders[ShaderId::SKY].activate();
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
}
|
||||
}
|
||||
if (state.fogging_enable) {
|
||||
assert(false);
|
||||
|
@ -255,8 +279,16 @@ void DirectRenderer::update_gl_texture(SharedRenderState* render_state) {
|
|||
} else {
|
||||
tex = render_state->texture_pool->lookup(m_texture_state.texture_base_ptr);
|
||||
}
|
||||
|
||||
if (!tex) {
|
||||
// TODO Add back
|
||||
fmt::print("Failed to find texture at {}, using random\n", m_texture_state.texture_base_ptr);
|
||||
tex = render_state->texture_pool->get_random_texture();
|
||||
if (tex) {
|
||||
// fmt::print("Successful texture lookup! {} {}\n", tex->page_name, tex->name);
|
||||
}
|
||||
}
|
||||
assert(tex);
|
||||
// fmt::print("Successful texture lookup! {} {}\n", tex->page_name, tex->name);
|
||||
|
||||
// first: do we need to load the texture?
|
||||
if (!tex->on_gpu) {
|
||||
|
@ -266,8 +298,14 @@ void DirectRenderer::update_gl_texture(SharedRenderState* render_state) {
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->gpu_texture);
|
||||
// Note: CLAMP and CLAMP_TO_EDGE are different...
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
if (m_clamp_state.clamp) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glUniform1i(
|
||||
|
@ -327,7 +365,7 @@ void DirectRenderer::update_gl_test() {
|
|||
}
|
||||
|
||||
if (state.alpha_test_enable) {
|
||||
assert(false);
|
||||
assert(state.alpha_test == GsTest::AlphaTest::ALWAYS);
|
||||
}
|
||||
|
||||
if (state.depth_writes) {
|
||||
|
@ -371,7 +409,8 @@ void DirectRenderer::render_vif(u32 vif0,
|
|||
u32 vif1,
|
||||
const u8* data,
|
||||
u32 size,
|
||||
SharedRenderState* render_state) {
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// here we process VIF data. Basically we just go forward, looking for DIRECTs.
|
||||
// We skip stuff like flush and nops.
|
||||
|
||||
|
@ -395,7 +434,7 @@ void DirectRenderer::render_vif(u32 vif0,
|
|||
assert(get_direct_qwc_or_nop(VifCode(vif)) == 0);
|
||||
} else {
|
||||
// aligned! do a gif transfer!
|
||||
render_gif(data + offset_into_data, gif_qwc * 16, render_state);
|
||||
render_gif(data + offset_into_data, gif_qwc * 16, render_state, prof);
|
||||
offset_into_data += gif_qwc * 16;
|
||||
}
|
||||
} else {
|
||||
|
@ -411,7 +450,10 @@ void DirectRenderer::render_vif(u32 vif0,
|
|||
/*!
|
||||
* Render GIF data.
|
||||
*/
|
||||
void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* render_state) {
|
||||
void DirectRenderer::render_gif(const u8* data,
|
||||
u32 size,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
assert(size >= 16);
|
||||
bool eop = false;
|
||||
|
||||
|
@ -433,13 +475,13 @@ void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* ren
|
|||
auto format = tag.flg();
|
||||
if (format == GifTag::Format::PACKED) {
|
||||
if (tag.pre()) {
|
||||
handle_prim(tag.prim(), render_state);
|
||||
handle_prim(tag.prim(), render_state, prof);
|
||||
}
|
||||
for (u32 loop = 0; loop < tag.nloop(); loop++) {
|
||||
for (u32 reg = 0; reg < nreg; reg++) {
|
||||
switch (reg_desc[reg]) {
|
||||
case GifTag::RegisterDescriptor::AD:
|
||||
handle_ad(data + offset, render_state);
|
||||
handle_ad(data + offset, render_state, prof);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::ST:
|
||||
handle_st_packed(data + offset);
|
||||
|
@ -448,13 +490,13 @@ void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* ren
|
|||
handle_rgbaq_packed(data + offset);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::XYZF2:
|
||||
handle_xyzf2_packed(data + offset, render_state);
|
||||
handle_xyzf2_packed(data + offset, render_state, prof);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::PRIM:
|
||||
handle_prim_packed(data + offset, render_state);
|
||||
handle_prim_packed(data + offset, render_state, prof);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::TEX0_1:
|
||||
handle_tex0_1_packed(data + offset, render_state);
|
||||
handle_tex0_1_packed(data + offset, render_state, prof);
|
||||
break;
|
||||
default:
|
||||
fmt::print("Register {} is not supported in packed mode yet\n",
|
||||
|
@ -473,13 +515,13 @@ void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* ren
|
|||
// reg_descriptor_name(reg_desc[reg]));
|
||||
switch (reg_desc[reg]) {
|
||||
case GifTag::RegisterDescriptor::PRIM:
|
||||
handle_prim(register_data, render_state);
|
||||
handle_prim(register_data, render_state, prof);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::RGBAQ:
|
||||
handle_rgbaq(register_data);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::XYZF2:
|
||||
handle_xyzf2(register_data, render_state);
|
||||
handle_xyzf2(register_data, render_state, prof);
|
||||
break;
|
||||
default:
|
||||
fmt::print("Register {} is not supported in reglist mode yet\n",
|
||||
|
@ -501,7 +543,9 @@ void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* ren
|
|||
// fmt::print("{}\n", GifTag(data).print());
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_ad(const u8* data, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_ad(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u64 value;
|
||||
GsRegisterAddress addr;
|
||||
memcpy(&value, data, sizeof(u64));
|
||||
|
@ -509,22 +553,22 @@ void DirectRenderer::handle_ad(const u8* data, SharedRenderState* render_state)
|
|||
|
||||
switch (addr) {
|
||||
case GsRegisterAddress::ZBUF_1:
|
||||
handle_zbuf1(value, render_state);
|
||||
handle_zbuf1(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::TEST_1:
|
||||
handle_test1(value, render_state);
|
||||
handle_test1(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::ALPHA_1:
|
||||
handle_alpha1(value, render_state);
|
||||
handle_alpha1(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::PABE:
|
||||
handle_pabe(value);
|
||||
break;
|
||||
case GsRegisterAddress::CLAMP_1:
|
||||
handle_clamp1(value);
|
||||
handle_clamp1(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::PRIM:
|
||||
handle_prim(value, render_state);
|
||||
handle_prim(value, render_state, prof);
|
||||
break;
|
||||
|
||||
case GsRegisterAddress::TEX1_1:
|
||||
|
@ -543,11 +587,13 @@ void DirectRenderer::handle_ad(const u8* data, SharedRenderState* render_state)
|
|||
// TODO
|
||||
break;
|
||||
case GsRegisterAddress::TEX0_1:
|
||||
handle_tex0_1(value, render_state);
|
||||
handle_tex0_1(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::MIPTBP1_1:
|
||||
// TODO this has the address of different mip levels.
|
||||
break;
|
||||
case GsRegisterAddress::TEXFLUSH:
|
||||
break;
|
||||
default:
|
||||
fmt::print("Address {} is not supported\n", register_address_name(addr));
|
||||
assert(false);
|
||||
|
@ -565,22 +611,25 @@ void DirectRenderer::handle_tex1_1(u64 val) {
|
|||
if (!(reg.mmin() == 1 || reg.mmin() == 4)) { // with mipmap off, both of these are linear
|
||||
// lg::error("unsupported mmin");
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_tex0_1_packed(const u8* data, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_tex0_1_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u64 val;
|
||||
memcpy(&val, data, sizeof(u64));
|
||||
handle_tex0_1(val, render_state);
|
||||
handle_tex0_1(val, render_state, prof);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_tex0_1(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_tex0_1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsTex0 reg(val);
|
||||
|
||||
// update tbp
|
||||
if (m_texture_state.current_register != reg) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to tex0\n");
|
||||
flush_pending(render_state, prof);
|
||||
m_texture_state.texture_base_ptr = reg.tbp0();
|
||||
m_texture_state.using_mt4hh = reg.psm() == GsTex0::PSM::PSMT4HH;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
|
@ -628,7 +677,9 @@ void DirectRenderer::handle_rgbaq_packed(const u8* data) {
|
|||
m_prim_building.rgba_reg[3] = data[12];
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyzf2_packed(const u8* data, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_xyzf2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u32 x, y;
|
||||
memcpy(&x, data, 4);
|
||||
memcpy(&y, data + 4, 4);
|
||||
|
@ -641,42 +692,52 @@ void DirectRenderer::handle_xyzf2_packed(const u8* data, SharedRenderState* rend
|
|||
bool adc = upper & (1ull << 47);
|
||||
assert(!adc);
|
||||
// assert(!f);
|
||||
handle_xyzf2_common(x, y, z, f, render_state);
|
||||
handle_xyzf2_common(x, y, z, f, render_state, prof);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_zbuf1(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_zbuf1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// note: we can basically ignore this. There's a single z buffer that's always configured the same
|
||||
// way - 24-bit, at offset 448.
|
||||
GsZbuf x(val);
|
||||
assert(x.psm() == TextureFormat::PSMZ24);
|
||||
assert(x.zbp() == 448);
|
||||
|
||||
bool write = !x.zmsk();
|
||||
bool write = x.zmsk();
|
||||
// assert(write);
|
||||
|
||||
if (write != m_test_state.depth_writes) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to depth write\n");
|
||||
flush_pending(render_state, prof);
|
||||
m_test_state_needs_gl_update = true;
|
||||
m_test_state.depth_writes = !write;
|
||||
m_test_state.depth_writes = write;
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_test1(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_test1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsTest reg(val);
|
||||
assert(!reg.alpha_test_enable());
|
||||
if (reg.alpha_test_enable()) {
|
||||
assert(reg.alpha_test() == GsTest::AlphaTest::ALWAYS);
|
||||
}
|
||||
assert(!reg.date());
|
||||
assert(!(val & 1));
|
||||
if (m_test_state.current_register != reg) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to test\n");
|
||||
flush_pending(render_state, prof);
|
||||
m_test_state.from_register(reg);
|
||||
m_test_state_needs_gl_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_alpha1(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_alpha1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsAlpha reg(val);
|
||||
if (m_blend_state.current_register != reg) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to alpha1\n");
|
||||
flush_pending(render_state, prof);
|
||||
m_blend_state.from_register(reg);
|
||||
m_blend_state_needs_gl_update = true;
|
||||
}
|
||||
|
@ -686,17 +747,33 @@ void DirectRenderer::handle_pabe(u64 val) {
|
|||
assert(val == 0); // not really sure how to handle this yet.
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_clamp1(u64 val) {
|
||||
assert(val == 0b101); // clamp s and t.
|
||||
void DirectRenderer::handle_clamp1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
assert(val == 0b101 || val == 0);
|
||||
if (m_clamp_state.current_register != val) {
|
||||
flush_pending(render_state, prof);
|
||||
m_clamp_state.current_register = val;
|
||||
if (val == 0b101) {
|
||||
m_clamp_state.clamp = true;
|
||||
} else {
|
||||
m_clamp_state.clamp = false;
|
||||
}
|
||||
m_texture_state.needs_gl_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_prim_packed(const u8* data, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_prim_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u64 val;
|
||||
memcpy(&val, data, sizeof(u64));
|
||||
handle_prim(val, render_state);
|
||||
handle_prim(val, render_state, prof);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_prim(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_prim(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (m_prim_building.tri_strip_startup) {
|
||||
m_prim_building.tri_strip_startup = 0;
|
||||
m_prim_building.building_idx = 0;
|
||||
|
@ -709,7 +786,8 @@ void DirectRenderer::handle_prim(u64 val, SharedRenderState* render_state) {
|
|||
|
||||
GsPrim prim(val);
|
||||
if (m_prim_gl_state.current_register != prim || m_blend_state.alpha_blend_enable != prim.abe()) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to prim\n");
|
||||
flush_pending(render_state, prof);
|
||||
m_prim_gl_state.from_register(prim);
|
||||
m_blend_state.alpha_blend_enable = prim.abe();
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
|
@ -728,15 +806,17 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
u32 y,
|
||||
u32 z,
|
||||
u8 f,
|
||||
SharedRenderState* render_state) {
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
assert(z < (1 << 24));
|
||||
(void)f; // TODO: do something with this.
|
||||
if (m_prim_buffer.is_full()) {
|
||||
flush_pending(render_state);
|
||||
// fmt::print("flush due to fill {} {}\n", m_prim_buffer.vert_count, m_prim_buffer.max_verts);
|
||||
flush_pending(render_state, prof);
|
||||
}
|
||||
|
||||
// assert(f == 0);
|
||||
m_prim_building.building_st.at(m_prim_building.building_idx) = m_prim_building.st_reg;
|
||||
m_prim_building.building_stq.at(m_prim_building.building_idx) = math::Vector<float, 3>(
|
||||
m_prim_building.st_reg.x(), m_prim_building.st_reg.y(), m_prim_building.Q);
|
||||
m_prim_building.building_rgba.at(m_prim_building.building_idx) = m_prim_building.rgba_reg;
|
||||
m_prim_building.building_vert.at(m_prim_building.building_idx) = {x << 16, y << 16, z << 8};
|
||||
m_prim_building.building_idx++;
|
||||
|
@ -780,7 +860,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
if (m_prim_building.tri_strip_startup >= 3) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_st[i]);
|
||||
m_prim_building.building_stq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,7 +871,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
m_prim_building.building_idx = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_st[i]);
|
||||
m_prim_building.building_stq[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -807,10 +887,11 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_st[i]);
|
||||
m_prim_building.building_stq[i]);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case GsPrim::Kind::LINE: {
|
||||
if (m_prim_building.building_idx == 2) {
|
||||
math::Vector<double, 3> pt0 = m_prim_building.building_vert[0].cast<double>();
|
||||
|
@ -845,13 +926,15 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyzf2(u64 val, SharedRenderState* render_state) {
|
||||
void DirectRenderer::handle_xyzf2(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u32 x = val & 0xffff;
|
||||
u32 y = (val >> 16) & 0xffff;
|
||||
u32 z = (val >> 32) & 0xffffff;
|
||||
u32 f = (val >> 56) & 0xff;
|
||||
|
||||
handle_xyzf2_common(x, y, z, f, render_state);
|
||||
handle_xyzf2_common(x, y, z, f, render_state, prof);
|
||||
}
|
||||
|
||||
void DirectRenderer::reset_state() {
|
||||
|
@ -915,15 +998,15 @@ void DirectRenderer::PrimGlState::from_register(GsPrim reg) {
|
|||
DirectRenderer::PrimitiveBuffer::PrimitiveBuffer(int max_triangles) {
|
||||
rgba_u8.resize(max_triangles * 3);
|
||||
verts.resize(max_triangles * 3);
|
||||
sts.resize(max_triangles * 3);
|
||||
stqs.resize(max_triangles * 3);
|
||||
max_verts = max_triangles * 3;
|
||||
}
|
||||
|
||||
void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
|
||||
const math::Vector<u32, 3>& vert,
|
||||
const math::Vector<float, 2>& st) {
|
||||
const math::Vector<float, 3>& st) {
|
||||
rgba_u8[vert_count] = rgba;
|
||||
verts[vert_count] = vert;
|
||||
sts[vert_count] = st;
|
||||
stqs[vert_count] = st;
|
||||
vert_count++;
|
||||
}
|
||||
|
|
|
@ -20,24 +20,33 @@ class DirectRenderer : public BucketRenderer {
|
|||
public:
|
||||
// specializations of direct renderer to handle certain outputs.
|
||||
enum class Mode {
|
||||
NORMAL, // use for general debug drawing, font.
|
||||
SPRITE_CPU // use for sprites (does the appropriate alpha test)
|
||||
NORMAL, // use for general debug drawing, font.
|
||||
SPRITE_CPU, // use for sprites (does the appropriate alpha test tricks)
|
||||
SKY // disables texture perspective correction
|
||||
};
|
||||
DirectRenderer(const std::string& name, BucketId my_id, int batch_size, Mode mode);
|
||||
~DirectRenderer();
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state) override;
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
|
||||
/*!
|
||||
* Render directly from _VIF_ data.
|
||||
* You can optionally provide two vif tags that come in front of data.
|
||||
* These can be set to 0 if you don't have these.
|
||||
*/
|
||||
void render_vif(u32 vif0, u32 vif1, const u8* data, u32 size, SharedRenderState* render_state);
|
||||
void render_vif(u32 vif0,
|
||||
u32 vif1,
|
||||
const u8* data,
|
||||
u32 size,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
/*!
|
||||
* Render directly from _GIF_ data.
|
||||
*/
|
||||
void render_gif(const u8* data, u32 size, SharedRenderState* render_state);
|
||||
void render_gif(const u8* data,
|
||||
u32 size,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void reset_state();
|
||||
|
||||
|
@ -49,30 +58,41 @@ class DirectRenderer : public BucketRenderer {
|
|||
/*!
|
||||
* If you don't use the render interface, call this at the very end.
|
||||
*/
|
||||
void flush_pending(SharedRenderState* render_state);
|
||||
void flush_pending(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
void draw_debug_window() override;
|
||||
|
||||
private:
|
||||
void handle_ad(const u8* data, SharedRenderState* render_state);
|
||||
void handle_zbuf1(u64 val, SharedRenderState* render_state);
|
||||
void handle_test1(u64 val, SharedRenderState* render_state);
|
||||
void handle_alpha1(u64 val, SharedRenderState* render_state);
|
||||
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_test1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_alpha1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_pabe(u64 val);
|
||||
void handle_clamp1(u64 val);
|
||||
void handle_prim(u64 val, SharedRenderState* render_state);
|
||||
void handle_prim_packed(const u8* data, SharedRenderState* render_state);
|
||||
void handle_clamp1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_prim(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_prim_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_rgbaq(u64 val);
|
||||
void handle_xyzf2(u64 val, SharedRenderState* render_state);
|
||||
void handle_xyzf2(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_st_packed(const u8* data);
|
||||
void handle_rgbaq_packed(const u8* data);
|
||||
void handle_xyzf2_packed(const u8* data, SharedRenderState* render_state);
|
||||
void handle_tex0_1_packed(const u8* data, SharedRenderState* render_state);
|
||||
void handle_tex0_1(u64 val, SharedRenderState* render_state);
|
||||
void handle_xyzf2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_tex0_1_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_tex0_1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_tex1_1(u64 val);
|
||||
void handle_texa(u64 val);
|
||||
|
||||
void handle_xyzf2_common(u32 x, u32 y, u32 z, u8 f, SharedRenderState* render_state);
|
||||
void handle_xyzf2_common(u32 x,
|
||||
u32 y,
|
||||
u32 z,
|
||||
u8 f,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
void update_gl_prim(SharedRenderState* render_state);
|
||||
void update_gl_blend();
|
||||
|
@ -110,6 +130,12 @@ class DirectRenderer : public BucketRenderer {
|
|||
|
||||
} m_blend_state;
|
||||
|
||||
struct ClampState {
|
||||
void from_register(u64 value);
|
||||
u64 current_register = 0b101;
|
||||
bool clamp = true;
|
||||
} m_clamp_state;
|
||||
|
||||
// state set through the prim register that requires changing GL stuff.
|
||||
struct PrimGlState {
|
||||
void from_register(GsPrim reg);
|
||||
|
@ -141,11 +167,11 @@ class DirectRenderer : public BucketRenderer {
|
|||
|
||||
std::array<math::Vector<u8, 4>, 3> building_rgba;
|
||||
std::array<math::Vector<u32, 3>, 3> building_vert;
|
||||
std::array<math::Vector<float, 2>, 3> building_st;
|
||||
std::array<math::Vector<float, 3>, 3> building_stq;
|
||||
int building_idx = 0;
|
||||
int tri_strip_startup = 0;
|
||||
|
||||
float Q = 0;
|
||||
float Q = 1.0;
|
||||
|
||||
} m_prim_building;
|
||||
|
||||
|
@ -153,7 +179,7 @@ class DirectRenderer : public BucketRenderer {
|
|||
PrimitiveBuffer(int max_triangles);
|
||||
std::vector<math::Vector<u8, 4>> rgba_u8;
|
||||
std::vector<math::Vector<u32, 3>> verts;
|
||||
std::vector<math::Vector<float, 2>> sts;
|
||||
std::vector<math::Vector<float, 3>> stqs;
|
||||
int vert_count = 0;
|
||||
int max_verts = 0;
|
||||
|
||||
|
@ -161,7 +187,7 @@ class DirectRenderer : public BucketRenderer {
|
|||
bool is_full() { return max_verts < (vert_count + 18); }
|
||||
void push(const math::Vector<u8, 4>& rgba,
|
||||
const math::Vector<u32, 3>& vert,
|
||||
const math::Vector<float, 2>& st);
|
||||
const math::Vector<float, 3>& stq);
|
||||
} m_prim_buffer;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "game/graphics/opengl_renderer/SpriteRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/TextureUploadHandler.h"
|
||||
#include "third-party/imgui/imgui.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "game/graphics/opengl_renderer/SkyRenderer.h"
|
||||
|
||||
// for the vif callback
|
||||
#include "game/kernel/kmachine.h"
|
||||
|
@ -21,7 +23,8 @@ void GLAPIENTRY opengl_error_callback(GLenum source,
|
|||
const GLchar* message,
|
||||
const void* /*userParam*/) {
|
||||
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) {
|
||||
lg::debug("OpenGL notification 0x{:X} S{:X} T{:X}: {}", id, source, type, message);
|
||||
// On some drivers this prints on every single texture upload, which is too much spam
|
||||
// lg::debug("OpenGL notification 0x{:X} S{:X} T{:X}: {}", id, source, type, message);
|
||||
} else if (severity == GL_DEBUG_SEVERITY_LOW) {
|
||||
lg::info("OpenGL message 0x{:X} S{:X} T{:X}: {}", id, source, type, message);
|
||||
} else if (severity == GL_DEBUG_SEVERITY_MEDIUM) {
|
||||
|
@ -56,7 +59,9 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool)
|
|||
*/
|
||||
void OpenGLRenderer::init_bucket_renderers() {
|
||||
init_bucket_renderer<EmptyBucketRenderer>("bucket0", BucketId::BUCKET0);
|
||||
init_bucket_renderer<SkyRenderer>("sky", BucketId::SKY_DRAW);
|
||||
init_bucket_renderer<TextureUploadHandler>("tfrag-tex-0", BucketId::TFRAG_TEX_LEVEL0);
|
||||
init_bucket_renderer<SkyTextureHandler>("sky-tex-0", BucketId::SKY_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("shrub-tex-0", BucketId::SHRUB_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("alpha-tex-0", BucketId::ALPHA_TEX_LEVEL0);
|
||||
init_bucket_renderer<TextureUploadHandler>("pris-tex-0", BucketId::PRIS_TEX_LEVEL0);
|
||||
|
@ -79,27 +84,46 @@ void OpenGLRenderer::init_bucket_renderers() {
|
|||
/*!
|
||||
* Main render function. This is called from the gfx loop with the chain passed from the game.
|
||||
*/
|
||||
void OpenGLRenderer::render(DmaFollower dma,
|
||||
int window_width_px,
|
||||
int window_height_px,
|
||||
bool draw_debug_window,
|
||||
bool dump_playback) {
|
||||
m_render_state.dump_playback = dump_playback;
|
||||
m_render_state.ee_main_memory = dump_playback ? nullptr : g_ee_main_mem;
|
||||
void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
|
||||
m_profiler.clear();
|
||||
m_render_state.dump_playback = settings.playing_from_dump;
|
||||
m_render_state.ee_main_memory = settings.playing_from_dump ? nullptr : g_ee_main_mem;
|
||||
m_render_state.offset_of_s7 = offset_of_s7();
|
||||
setup_frame(window_width_px, window_height_px);
|
||||
m_render_state.texture_pool->remove_garbage_textures();
|
||||
|
||||
{
|
||||
auto prof = m_profiler.root()->make_scoped_child("frame-setup");
|
||||
setup_frame(settings.window_width_px, settings.window_height_px);
|
||||
}
|
||||
{
|
||||
auto prof = m_profiler.root()->make_scoped_child("texture-gc");
|
||||
m_render_state.texture_pool->remove_garbage_textures();
|
||||
}
|
||||
|
||||
// draw_test_triangle();
|
||||
// render the buckets!
|
||||
dispatch_buckets(dma);
|
||||
{
|
||||
auto prof = m_profiler.root()->make_scoped_child("buckets");
|
||||
dispatch_buckets(dma, prof);
|
||||
}
|
||||
|
||||
if (draw_debug_window) {
|
||||
if (settings.draw_render_debug_window) {
|
||||
auto prof = m_profiler.root()->make_scoped_child("render-window");
|
||||
draw_renderer_selection_window();
|
||||
// add a profile bar for the imgui stuff
|
||||
if (!m_render_state.dump_playback) {
|
||||
vif_interrupt_callback();
|
||||
}
|
||||
}
|
||||
|
||||
m_profiler.finish();
|
||||
if (settings.draw_profiler_window) {
|
||||
m_profiler.draw();
|
||||
}
|
||||
|
||||
if (settings.save_screenshot) {
|
||||
finish_screenshot(settings.screenshot_path, settings.window_width_px,
|
||||
settings.window_height_px);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::serialize(Serializer& ser) {
|
||||
|
@ -109,6 +133,9 @@ void OpenGLRenderer::serialize(Serializer& ser) {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draw the per-renderer debug window
|
||||
*/
|
||||
void OpenGLRenderer::draw_renderer_selection_window() {
|
||||
ImGui::Begin("Renderer Debug");
|
||||
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
|
||||
|
@ -145,7 +172,7 @@ void OpenGLRenderer::setup_frame(int window_width_px, int window_height_px) {
|
|||
/*!
|
||||
* This function finds buckets and dispatches them to the appropriate part.
|
||||
*/
|
||||
void OpenGLRenderer::dispatch_buckets(DmaFollower dma) {
|
||||
void OpenGLRenderer::dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof) {
|
||||
// The first thing the DMA chain should be a call to a common default-registers chain.
|
||||
// this chain resets the state of the GS. After this is buckets
|
||||
|
||||
|
@ -176,7 +203,8 @@ void OpenGLRenderer::dispatch_buckets(DmaFollower dma) {
|
|||
// loop over the buckets!
|
||||
for (int bucket_id = 0; bucket_id < (int)BucketId::MAX_BUCKETS; bucket_id++) {
|
||||
auto& renderer = m_bucket_renderers[bucket_id];
|
||||
renderer->render(dma, &m_render_state);
|
||||
auto bucket_prof = prof.make_scoped_child(renderer->name_and_id());
|
||||
renderer->render(dma, &m_render_state, bucket_prof);
|
||||
// should have ended at the start of the next chain
|
||||
assert(dma.current_tag_offset() == m_render_state.next_bucket);
|
||||
m_render_state.next_bucket += 16;
|
||||
|
@ -246,3 +274,25 @@ void OpenGLRenderer::draw_test_triangle() {
|
|||
glDeleteBuffers(1, &vertex_buffer);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Take a screenshot!
|
||||
*/
|
||||
void OpenGLRenderer::finish_screenshot(const std::string& output_name, int width, int height) {
|
||||
std::vector<u32> buffer(width * height);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
|
||||
// flip upside down in place
|
||||
for (int h = 0; h < height / 2; h++) {
|
||||
for (int w = 0; w < width; w++) {
|
||||
std::swap(buffer[h * width + w], buffer[(height - h) * width + w]);
|
||||
}
|
||||
}
|
||||
|
||||
// set alpha. For some reason, image viewers do weird stuff with alpha.
|
||||
for (auto& x : buffer) {
|
||||
x |= 0xff000000;
|
||||
}
|
||||
file_util::write_rgba_png(output_name, buffer.data(), width, height);
|
||||
}
|
|
@ -6,30 +6,41 @@
|
|||
#include "game/graphics/dma/dma_chain_read.h"
|
||||
#include "game/graphics/opengl_renderer/Shader.h"
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/Profiler.h"
|
||||
|
||||
struct RenderOptions {
|
||||
int window_height_px = 0;
|
||||
int window_width_px = 0;
|
||||
bool draw_render_debug_window = false;
|
||||
bool draw_profiler_window = false;
|
||||
bool playing_from_dump = false;
|
||||
|
||||
bool save_screenshot = false;
|
||||
std::string screenshot_path;
|
||||
};
|
||||
|
||||
class OpenGLRenderer {
|
||||
public:
|
||||
OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool);
|
||||
void render(DmaFollower dma,
|
||||
int window_width_px,
|
||||
int window_height_px,
|
||||
bool draw_debug_window,
|
||||
bool dump_playback);
|
||||
void render(DmaFollower dma, const RenderOptions& settings);
|
||||
void serialize(Serializer& ser);
|
||||
|
||||
private:
|
||||
void setup_frame(int window_width_px, int window_height_px);
|
||||
void draw_test_triangle();
|
||||
void dispatch_buckets(DmaFollower dma);
|
||||
void dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof);
|
||||
void init_bucket_renderers();
|
||||
void draw_renderer_selection_window();
|
||||
|
||||
void finish_screenshot(const std::string& output_name, int px, int py);
|
||||
|
||||
template <typename T, class... Args>
|
||||
void init_bucket_renderer(const std::string& name, BucketId id, Args&&... args) {
|
||||
m_bucket_renderers.at((int)id) = std::make_unique<T>(name, id, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
SharedRenderState m_render_state;
|
||||
Profiler m_profiler;
|
||||
|
||||
std::array<std::unique_ptr<BucketRenderer>, (int)BucketId::MAX_BUCKETS> m_bucket_renderers;
|
||||
};
|
||||
|
|
145
game/graphics/opengl_renderer/Profiler.cpp
Normal file
145
game/graphics/opengl_renderer/Profiler.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "Profiler.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/colors.h"
|
||||
#include "third-party/imgui/imgui.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
ProfilerNode::ProfilerNode(const std::string& name) : m_name(name) {}
|
||||
|
||||
ProfilerNode* ProfilerNode::make_child(const std::string& name) {
|
||||
m_children.emplace_back(name);
|
||||
return &m_children.back();
|
||||
}
|
||||
|
||||
void ProfilerNode::finish() {
|
||||
if (m_finished) {
|
||||
lg::error("finish() called twice on {}\n", m_name);
|
||||
} else {
|
||||
m_stats.duration = m_timer.getSeconds();
|
||||
float total_child_time = 0;
|
||||
for (const auto& child : m_children) {
|
||||
if (!child.finished()) {
|
||||
lg::error("finish() not called on {}\n", child.name());
|
||||
}
|
||||
total_child_time += child.m_stats.duration;
|
||||
m_stats.add_draw_stats(child.m_stats);
|
||||
}
|
||||
|
||||
if (!m_children.empty()) {
|
||||
float unknown_time = m_stats.duration - total_child_time;
|
||||
if (unknown_time > 0.0001 || unknown_time > (m_stats.duration * 0.05)) {
|
||||
ProfilerNode unk("unknown");
|
||||
unk.m_stats.duration = unknown_time;
|
||||
m_children.push_back(unk);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_finished = true;
|
||||
}
|
||||
|
||||
void ProfilerNode::sort(ProfilerSort mode) {
|
||||
if (mode == ProfilerSort::NONE) {
|
||||
return;
|
||||
}
|
||||
std::sort(m_children.begin(), m_children.end(),
|
||||
[=](const ProfilerNode& a, const ProfilerNode& b) {
|
||||
switch (mode) {
|
||||
case ProfilerSort::DRAW_CALLS:
|
||||
return a.m_stats.draw_calls > b.m_stats.draw_calls;
|
||||
case ProfilerSort::TIME:
|
||||
return a.m_stats.duration > b.m_stats.duration;
|
||||
case ProfilerSort::TRIANGLES:
|
||||
return a.m_stats.triangles > b.m_stats.triangles;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
});
|
||||
for (auto& child : m_children) {
|
||||
child.sort(mode);
|
||||
}
|
||||
}
|
||||
|
||||
ScopedProfilerNode ProfilerNode::make_scoped_child(const std::string& name) {
|
||||
return ScopedProfilerNode(make_child(name));
|
||||
}
|
||||
|
||||
Profiler::Profiler() : m_root("root") {}
|
||||
|
||||
void Profiler::clear() {
|
||||
m_root = ProfilerNode("root");
|
||||
}
|
||||
|
||||
void Profiler::finish() {
|
||||
m_root.finish();
|
||||
}
|
||||
|
||||
void Profiler::draw() {
|
||||
ImGui::Begin("Profiler");
|
||||
const char* listbox_entries[] = {"None", "Time", "Draw Calls", "Tris"};
|
||||
ImGui::Combo("Sort", &m_mode_selector, listbox_entries, 4);
|
||||
m_root.sort((ProfilerSort)m_mode_selector);
|
||||
ImGui::SameLine();
|
||||
bool all = ImGui::Button("Expand All");
|
||||
ImGui::Dummy(ImVec2(0.0f, 80.0f));
|
||||
draw_node(m_root, all, 0, 0.f);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
u32 name_to_color(const std::string& name) {
|
||||
u64 val = std::hash<std::string>{}(name);
|
||||
return colors::common_colors[val % colors::COLOR_COUNT] | 0xff000000;
|
||||
}
|
||||
|
||||
void Profiler::draw_node(ProfilerNode& node, bool expand, int depth, float start_time) {
|
||||
u32 color = 0xFFFFFFFF;
|
||||
|
||||
constexpr int origin_x = 40;
|
||||
constexpr int origin_y = 60;
|
||||
constexpr int row_height = 15;
|
||||
constexpr int px_per_ms = 200;
|
||||
|
||||
if (node.m_stats.duration > 0.00001) {
|
||||
color = name_to_color(node.m_name);
|
||||
}
|
||||
bool color_orange = false;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
auto str =
|
||||
fmt::format("{:20s} {:.2f}ms {:6d} tri {:4d} draw", node.m_name, node.m_stats.duration * 1000,
|
||||
node.m_stats.triangles, node.m_stats.draw_calls);
|
||||
if (node.m_children.empty()) {
|
||||
ImGui::Text(" %s", str.c_str());
|
||||
color_orange = ImGui::IsItemHovered();
|
||||
} else {
|
||||
if (expand) {
|
||||
ImGui::SetNextTreeNodeOpen(true);
|
||||
}
|
||||
if (ImGui::TreeNode(node.m_name.c_str(), "%s", str.c_str())) {
|
||||
color_orange = ImGui::IsItemHovered();
|
||||
float child_start = start_time;
|
||||
for (auto& child : node.m_children) {
|
||||
draw_node(child, expand, depth + 1, child_start);
|
||||
child_start += child.m_stats.duration;
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
if (node.m_stats.duration > 0.00001 || color_orange) {
|
||||
if (color_orange) {
|
||||
color = 0xff00a5ff;
|
||||
}
|
||||
auto dl = ImGui::GetWindowDrawList();
|
||||
auto window_pos = ImGui::GetWindowPos();
|
||||
float x0 = window_pos.x + origin_x + px_per_ms * 1000 * start_time;
|
||||
float x1 = x0 + px_per_ms * 1000 * node.m_stats.duration;
|
||||
float y0 = window_pos.y + origin_y + depth * row_height;
|
||||
float y1 = y0 + row_height;
|
||||
|
||||
dl->AddRectFilled(ImVec2(x0, y0), ImVec2(x1, y1), color);
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
83
game/graphics/opengl_renderer/Profiler.h
Normal file
83
game/graphics/opengl_renderer/Profiler.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/util/Timer.h"
|
||||
|
||||
enum class ProfilerSort { NONE = 0, TIME = 1, DRAW_CALLS = 2, TRIANGLES = 3 };
|
||||
|
||||
struct ProfilerStats {
|
||||
float duration = 0; // seconds
|
||||
u32 draw_calls = 0;
|
||||
u32 triangles = 0;
|
||||
|
||||
void add_draw_stats(const ProfilerStats& other) {
|
||||
draw_calls += other.draw_calls;
|
||||
triangles += other.triangles;
|
||||
}
|
||||
};
|
||||
|
||||
class ScopedProfilerNode;
|
||||
|
||||
class ProfilerNode {
|
||||
public:
|
||||
ProfilerNode(const std::string& name);
|
||||
ProfilerNode* make_child(const std::string& name);
|
||||
ScopedProfilerNode make_scoped_child(const std::string& name);
|
||||
void sort(ProfilerSort mode);
|
||||
void finish();
|
||||
|
||||
bool finished() const { return m_finished; }
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
void add_draw_call(int count = 1) { m_stats.draw_calls += count; }
|
||||
void add_tri(int count = 1) { m_stats.triangles += count; }
|
||||
|
||||
private:
|
||||
friend class Profiler;
|
||||
std::string m_name;
|
||||
ProfilerStats m_stats;
|
||||
std::vector<ProfilerNode> m_children;
|
||||
Timer m_timer;
|
||||
bool m_finished = false;
|
||||
};
|
||||
|
||||
class ScopedProfilerNode {
|
||||
public:
|
||||
ScopedProfilerNode(ProfilerNode* node) : m_node(node) {}
|
||||
ScopedProfilerNode(const ScopedProfilerNode& other) = delete;
|
||||
ScopedProfilerNode& operator=(const ScopedProfilerNode& other) = delete;
|
||||
ProfilerNode* make_child(const std::string& name) { return m_node->make_child(name); }
|
||||
ScopedProfilerNode make_scoped_child(const std::string& name) {
|
||||
return m_node->make_scoped_child(name);
|
||||
}
|
||||
~ScopedProfilerNode() { m_node->finish(); }
|
||||
|
||||
void add_draw_call(int count = 1) { m_node->add_draw_call(count); }
|
||||
void add_tri(int count = 1) { m_node->add_tri(count); }
|
||||
|
||||
private:
|
||||
ProfilerNode* m_node;
|
||||
};
|
||||
|
||||
class Profiler {
|
||||
public:
|
||||
Profiler();
|
||||
void clear();
|
||||
void draw();
|
||||
void finish();
|
||||
ProfilerNode* root() { return &m_root; }
|
||||
|
||||
private:
|
||||
void draw_node(ProfilerNode& node, bool expand, int depth, float start_time);
|
||||
|
||||
struct BarEntry {
|
||||
float duration;
|
||||
float rgba[4];
|
||||
};
|
||||
|
||||
int m_mode_selector = 0;
|
||||
ProfilerNode m_root;
|
||||
};
|
|
@ -71,4 +71,6 @@ ShaderLibrary::ShaderLibrary() {
|
|||
at(ShaderId::DEBUG_RED) = {"debug_red"};
|
||||
at(ShaderId::SPRITE_CPU) = {"sprite_cpu"};
|
||||
at(ShaderId::SPRITE_CPU_AFAIL) = {"sprite_cpu_afail"};
|
||||
at(ShaderId::SKY) = {"sky"};
|
||||
at(ShaderId::SKY_BLEND) = {"sky_blend"};
|
||||
}
|
|
@ -29,6 +29,8 @@ enum class ShaderId {
|
|||
DEBUG_RED = 4,
|
||||
SPRITE_CPU = 5,
|
||||
SPRITE_CPU_AFAIL = 6,
|
||||
SKY,
|
||||
SKY_BLEND,
|
||||
MAX_SHADERS
|
||||
};
|
||||
|
||||
|
|
370
game/graphics/opengl_renderer/SkyRenderer.cpp
Normal file
370
game/graphics/opengl_renderer/SkyRenderer.cpp
Normal file
|
@ -0,0 +1,370 @@
|
|||
#include "SkyRenderer.h"
|
||||
#include "third-party/imgui/imgui.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
#include "game/graphics/opengl_renderer/AdgifHandler.h"
|
||||
#include "common/log/log.h"
|
||||
|
||||
// The sky texture system blends together sky textures from different levels and times of day
|
||||
// to create the final sky texture.
|
||||
|
||||
// The sequence is:
|
||||
// set-display-gs-state 8qw
|
||||
// copy-sky-textures (between 0 and 8, usually 2.)
|
||||
// copy-cloud-texture
|
||||
// set alpha state
|
||||
// reset display gs state
|
||||
// and this happens twice: one for each level. Note that the first call to either of the copy
|
||||
// functions will use "draw" mode instead of "blend"
|
||||
// The results are stored in special sky textures.
|
||||
|
||||
// size of the sky texture is 64x96, but it's actually a 64x64 (clouds) and a 32x32 (sky)
|
||||
|
||||
SkyTextureHandler::SkyTextureHandler(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id) {
|
||||
// generate textures for sky blending
|
||||
glGenFramebuffers(2, m_framebuffers);
|
||||
glGenTextures(2, m_textures);
|
||||
|
||||
GLint old_framebuffer;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer);
|
||||
|
||||
// setup the framebuffers
|
||||
for (int i = 0; i < 2; i++) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[i]);
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures[i]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_sizes[i], m_sizes[i], 0, GL_RGBA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textures[i], 0);
|
||||
GLenum draw_buffers[1] = {GL_COLOR_ATTACHMENT0};
|
||||
glDrawBuffers(1, draw_buffers);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
lg::error("SkyTextureHandler setup failed.");
|
||||
}
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glGenBuffers(1, &m_gl_vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_gl_vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 6, nullptr, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, old_framebuffer);
|
||||
|
||||
// we only draw squares
|
||||
m_vertex_data[0].x = 0;
|
||||
m_vertex_data[0].y = 0;
|
||||
|
||||
m_vertex_data[1].x = 1;
|
||||
m_vertex_data[1].y = 0;
|
||||
|
||||
m_vertex_data[2].x = 0;
|
||||
m_vertex_data[2].y = 1;
|
||||
|
||||
m_vertex_data[3].x = 1;
|
||||
m_vertex_data[3].y = 0;
|
||||
|
||||
m_vertex_data[4].x = 0;
|
||||
m_vertex_data[4].y = 1;
|
||||
|
||||
m_vertex_data[5].x = 1;
|
||||
m_vertex_data[5].y = 1;
|
||||
}
|
||||
|
||||
SkyTextureHandler::~SkyTextureHandler() {
|
||||
glDeleteFramebuffers(2, m_framebuffers);
|
||||
glDeleteBuffers(1, &m_gl_vertex_buffer);
|
||||
glDeleteTextures(2, m_textures);
|
||||
}
|
||||
|
||||
void SkyTextureHandler::handle_sky_copies(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (!m_enabled) {
|
||||
while (dma.current_tag().qwc == 6) {
|
||||
dma.read_and_advance();
|
||||
dma.read_and_advance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLint old_viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, old_viewport);
|
||||
|
||||
GLint old_framebuffer;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer);
|
||||
|
||||
while (dma.current_tag().qwc == 6) {
|
||||
// assuming that the vif and gif-tag is correct
|
||||
auto setup_data = dma.read_and_advance();
|
||||
if (render_state->dump_playback) {
|
||||
// continue;
|
||||
}
|
||||
|
||||
// first is an adgif
|
||||
AdgifHelper adgif(setup_data.data + 16);
|
||||
assert(adgif.is_normal_adgif());
|
||||
assert(adgif.alpha().data == 0x8000000068); // Cs + Cd
|
||||
|
||||
// next is the actual draw
|
||||
auto draw_data = dma.read_and_advance();
|
||||
assert(draw_data.size_bytes == 6 * 16);
|
||||
|
||||
GifTag draw_or_blend_tag(draw_data.data);
|
||||
|
||||
// the first draw overwrites the previous frame's draw by disabling alpha blend (ABE = 0)
|
||||
bool is_first_draw = !GsPrim(draw_or_blend_tag.prim()).abe();
|
||||
|
||||
// here's we're relying on the format of the drawing to get the alpha/offset.
|
||||
u32 coord;
|
||||
u32 intensity;
|
||||
memcpy(&coord, draw_data.data + (5 * 16), 4);
|
||||
memcpy(&intensity, draw_data.data + 16, 4);
|
||||
|
||||
// we didn't parse the render-to-texture setup earlier, so we need a way to tell sky from
|
||||
// clouds. we can look at the drawing coordinates to tell - the sky is smaller than the clouds.
|
||||
int buffer_idx = 0;
|
||||
if (coord == 0x200) {
|
||||
// sky
|
||||
buffer_idx = 0;
|
||||
} else if (coord == 0x400) {
|
||||
buffer_idx = 1;
|
||||
} else {
|
||||
assert(false); // bad data
|
||||
}
|
||||
|
||||
// look up the source texture
|
||||
auto tex = render_state->texture_pool->lookup(adgif.tex0().tbp0());
|
||||
assert(tex);
|
||||
|
||||
if (!tex->on_gpu) {
|
||||
render_state->texture_pool->upload_to_gpu(tex);
|
||||
}
|
||||
|
||||
// setup for rendering!
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[buffer_idx]);
|
||||
glViewport(0, 0, m_sizes[buffer_idx], m_sizes[buffer_idx]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textures[buffer_idx], 0);
|
||||
render_state->shaders[ShaderId::SKY_BLEND].activate();
|
||||
|
||||
// if the first is set, it disables alpha. we can just clear here, so it's easier to find
|
||||
// in renderdoc.
|
||||
if (is_first_draw) {
|
||||
float clear[4] = {0, 0, 0, 0};
|
||||
glClearBufferfv(GL_COLOR, 0, clear);
|
||||
}
|
||||
|
||||
// intensities should be 0-128 (maybe higher is okay, but I don't see how this could be
|
||||
// generated with the GOAL code.)
|
||||
assert(intensity <= 128);
|
||||
|
||||
// todo - could do this on the GPU, but probably not worth it for <20 triangles...
|
||||
float intensity_float = intensity / 128.f;
|
||||
for (auto& vert : m_vertex_data) {
|
||||
vert.intensity = intensity_float;
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// will add.
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
|
||||
// setup draw data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_gl_vertex_buffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * 6, m_vertex_data);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
0, // tightly packed
|
||||
0
|
||||
|
||||
);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->gpu_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::SKY_BLEND].id(), "T0"), 0);
|
||||
|
||||
// Draw a sqaure
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
// 1 draw, 2 triangles
|
||||
prof.add_draw_call(1);
|
||||
prof.add_tri(2);
|
||||
|
||||
if (buffer_idx == 0) {
|
||||
if (is_first_draw) {
|
||||
m_stats.sky_draws++;
|
||||
} else {
|
||||
m_stats.sky_blends++;
|
||||
}
|
||||
} else {
|
||||
if (is_first_draw) {
|
||||
m_stats.cloud_draws++;
|
||||
} else {
|
||||
m_stats.cloud_blends++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// put in pool.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// todo - these are hardcoded and rely on the vram layout.
|
||||
u32 tbp = i == 0 ? 8064 : 8096;
|
||||
|
||||
// lookup existing, or create a new entry
|
||||
TextureRecord* tex = render_state->texture_pool->lookup(tbp);
|
||||
if (!tex) {
|
||||
auto tsp = std::make_shared<TextureRecord>();
|
||||
render_state->texture_pool->set_texture(tbp, tsp);
|
||||
tex = tsp.get();
|
||||
}
|
||||
|
||||
// update it
|
||||
tex->gpu_texture = m_textures[i];
|
||||
tex->on_gpu = true;
|
||||
tex->only_on_gpu = true;
|
||||
tex->do_gc = false;
|
||||
tex->w = m_sizes[i];
|
||||
tex->h = m_sizes[i];
|
||||
tex->name = fmt::format("PC-SKY-{}", i);
|
||||
}
|
||||
|
||||
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer);
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
}
|
||||
|
||||
void SkyTextureHandler::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
m_stats = {};
|
||||
// First thing should be a NEXT with two nops. this is a jump from buckets to sprite data
|
||||
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) {
|
||||
// sky 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;
|
||||
}
|
||||
|
||||
// first is the set-display-gs-state
|
||||
auto set_display = dma.read_and_advance();
|
||||
assert(set_display.size_bytes == 8 * 16);
|
||||
|
||||
handle_sky_copies(dma, render_state, prof);
|
||||
|
||||
auto reset_alpha = dma.read_and_advance();
|
||||
assert(reset_alpha.size_bytes == 16 * 2);
|
||||
|
||||
auto reset_gs = dma.read_and_advance();
|
||||
assert(reset_gs.size_bytes == 16 * 8);
|
||||
|
||||
auto empty = dma.read_and_advance();
|
||||
assert(empty.size_bytes == 0);
|
||||
assert(empty.vif0() == 0);
|
||||
assert(empty.vif1() == 0);
|
||||
|
||||
assert(dma.current_tag().kind == DmaTag::Kind::CALL);
|
||||
dma.read_and_advance();
|
||||
dma.read_and_advance(); // cnt
|
||||
assert(dma.current_tag().kind == DmaTag::Kind::RET);
|
||||
dma.read_and_advance(); // ret
|
||||
dma.read_and_advance(); // ret
|
||||
assert(dma.current_tag_offset() == render_state->next_bucket);
|
||||
}
|
||||
|
||||
void SkyTextureHandler::draw_debug_window() {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Draw/Blend ( sky ): %d/%d", m_stats.sky_draws, m_stats.sky_blends);
|
||||
ImGui::Text("Draw/Blend (cloud): %d/%d", m_stats.cloud_draws, m_stats.cloud_blends);
|
||||
}
|
||||
|
||||
SkyRenderer::SkyRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id),
|
||||
m_direct_renderer("sky-direct", my_id, 100, DirectRenderer::Mode::NORMAL) {}
|
||||
|
||||
void SkyRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
m_direct_renderer.reset_state();
|
||||
m_frame_stats = {};
|
||||
// First thing should be a NEXT with two nops. this is a jump from buckets to sprite data
|
||||
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) {
|
||||
// sky 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 setup_packet = dma.read_and_advance();
|
||||
assert(setup_packet.size_bytes == 16 * 4);
|
||||
m_direct_renderer.render_gif(setup_packet.data, setup_packet.size_bytes, render_state, prof);
|
||||
|
||||
auto draw_setup_packet = dma.read_and_advance();
|
||||
assert(draw_setup_packet.size_bytes == 16 * 5);
|
||||
m_direct_renderer.render_gif(draw_setup_packet.data, draw_setup_packet.size_bytes, render_state,
|
||||
prof);
|
||||
// tex0: tbw = 1, th = 5, hw = 5, sky-base-block
|
||||
// mmag/mmin = 1
|
||||
// clamp
|
||||
// drawing.
|
||||
int dma_idx = 0;
|
||||
while (dma.current_tag().kind == DmaTag::Kind::CNT) {
|
||||
m_frame_stats.gif_packets++;
|
||||
auto data = dma.read_and_advance();
|
||||
assert(data.vifcode0().kind == VifCode::Kind::NOP);
|
||||
assert(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
assert(data.vifcode1().immediate == data.size_bytes / 16);
|
||||
if (m_enabled) {
|
||||
m_direct_renderer.render_gif(data.data, data.size_bytes, render_state, prof);
|
||||
}
|
||||
dma_idx++;
|
||||
}
|
||||
|
||||
m_direct_renderer.flush_pending(render_state, prof);
|
||||
|
||||
auto empty = dma.read_and_advance();
|
||||
assert(empty.size_bytes == 0);
|
||||
assert(empty.vif0() == 0);
|
||||
assert(empty.vif1() == 0);
|
||||
|
||||
assert(dma.current_tag().kind == DmaTag::Kind::CALL);
|
||||
dma.read_and_advance();
|
||||
dma.read_and_advance(); // cnt
|
||||
assert(dma.current_tag().kind == DmaTag::Kind::RET);
|
||||
dma.read_and_advance(); // ret
|
||||
dma.read_and_advance(); // ret
|
||||
assert(dma.current_tag_offset() == render_state->next_bucket);
|
||||
}
|
||||
|
||||
void SkyRenderer::draw_debug_window() {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("GIF packets: %d", m_frame_stats.gif_packets);
|
||||
|
||||
if (ImGui::TreeNode("direct")) {
|
||||
m_direct_renderer.draw_debug_window();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
57
game/graphics/opengl_renderer/SkyRenderer.h
Normal file
57
game/graphics/opengl_renderer/SkyRenderer.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
|
||||
#pragma once
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
|
||||
/*!
|
||||
* Handles texture blending for the sky.
|
||||
* Will insert the result texture into the texture pool.
|
||||
*/
|
||||
class SkyTextureHandler : public BucketRenderer {
|
||||
public:
|
||||
SkyTextureHandler(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
~SkyTextureHandler();
|
||||
|
||||
private:
|
||||
void handle_sky_copies(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
GLuint m_framebuffers[2]; // sky, clouds
|
||||
GLuint m_textures[2]; // sky, clouds
|
||||
int m_sizes[2] = {32, 64};
|
||||
GLuint m_gl_vertex_buffer;
|
||||
|
||||
struct Vertex {
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float intensity = 0;
|
||||
};
|
||||
|
||||
struct FrameStats {
|
||||
int sky_draws = 0;
|
||||
int cloud_draws = 0;
|
||||
int sky_blends = 0;
|
||||
int cloud_blends = 0;
|
||||
} m_stats;
|
||||
|
||||
Vertex m_vertex_data[6];
|
||||
};
|
||||
|
||||
/*!
|
||||
* Handles sky drawing.
|
||||
*/
|
||||
class SkyRenderer : public BucketRenderer {
|
||||
public:
|
||||
SkyRenderer(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
|
||||
private:
|
||||
DirectRenderer m_direct_renderer;
|
||||
|
||||
struct FrameStats {
|
||||
int gif_packets = 0;
|
||||
} m_frame_stats;
|
||||
};
|
|
@ -147,15 +147,17 @@ SpriteRenderer::SpriteRenderer(const std::string& name, BucketId my_id)
|
|||
* Run the sprite distorter. Currently nothing uses sprite-distorter so this just skips through
|
||||
* the table upload stuff that runs every frame, even if there are no sprites.
|
||||
*/
|
||||
void SpriteRenderer::render_distorter(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void SpriteRenderer::render_distorter(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// Next thing should be the sprite-distorter setup
|
||||
m_direct_renderer.reset_state();
|
||||
while (dma.current_tag().qwc != 7) {
|
||||
auto direct_data = dma.read_and_advance();
|
||||
m_direct_renderer.render_vif(direct_data.vif0(), direct_data.vif1(), direct_data.data,
|
||||
direct_data.size_bytes, render_state);
|
||||
direct_data.size_bytes, render_state, prof);
|
||||
}
|
||||
m_direct_renderer.flush_pending(render_state);
|
||||
m_direct_renderer.flush_pending(render_state, prof);
|
||||
auto sprite_distorter_direct_setup = dma.read_and_advance();
|
||||
assert(sprite_distorter_direct_setup.vifcode0().kind == VifCode::Kind::NOP);
|
||||
assert(sprite_distorter_direct_setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
|
@ -233,9 +235,41 @@ void SpriteRenderer::render_3d(DmaFollower& dma) {
|
|||
// TODO
|
||||
}
|
||||
|
||||
void SpriteRenderer::render_2d_group0(DmaFollower& dma) {
|
||||
void SpriteRenderer::render_2d_group0(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
(void)dma;
|
||||
// TODO
|
||||
while (looks_like_2d_chunk_start(dma)) {
|
||||
m_debug_stats.blocks_2d_grp0++;
|
||||
// 4 packets per chunk
|
||||
|
||||
// first is the header
|
||||
u32 sprite_count = process_sprite_chunk_header(dma);
|
||||
m_debug_stats.count_2d_grp0 += sprite_count;
|
||||
|
||||
// second is the vector data
|
||||
u32 expected_vec_size = sizeof(SpriteVecData2d) * sprite_count;
|
||||
auto vec_data = dma.read_and_advance();
|
||||
assert(expected_vec_size <= sizeof(m_vec_data_2d));
|
||||
unpack_to_no_stcycl(&m_vec_data_2d, vec_data, VifCode::Kind::UNPACK_V4_32, expected_vec_size,
|
||||
SpriteDataMem::Vector, false, true);
|
||||
|
||||
// third is the adgif data
|
||||
u32 expected_adgif_size = sizeof(AdGifData) * sprite_count;
|
||||
auto adgif_data = dma.read_and_advance();
|
||||
assert(expected_adgif_size <= sizeof(m_adgif));
|
||||
unpack_to_no_stcycl(&m_adgif, adgif_data, VifCode::Kind::UNPACK_V4_32, expected_adgif_size,
|
||||
SpriteDataMem::Adgif, false, true);
|
||||
|
||||
// fourth is the actual run!!!!!
|
||||
auto run = dma.read_and_advance();
|
||||
assert(run.vifcode0().kind == VifCode::Kind::NOP);
|
||||
assert(run.vifcode1().kind == VifCode::Kind::MSCAL);
|
||||
assert(run.vifcode1().immediate == SpriteProgMem::Sprites2dGrp0);
|
||||
if (m_enabled) {
|
||||
do_2d_group0_block_cpu(sprite_count, render_state, prof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteRenderer::render_fake_shadow(DmaFollower& dma) {
|
||||
|
@ -249,7 +283,9 @@ void SpriteRenderer::render_fake_shadow(DmaFollower& dma) {
|
|||
/*!
|
||||
* Handle DMA data for group1 2d's (HUD)
|
||||
*/
|
||||
void SpriteRenderer::render_2d_group1(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void SpriteRenderer::render_2d_group1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// one time matrix data upload
|
||||
auto mat_upload = dma.read_and_advance();
|
||||
bool mat_ok = verify_unpack_with_stcycl(mat_upload, VifCode::Kind::UNPACK_V4_32, 4, 4, 80,
|
||||
|
@ -275,7 +311,7 @@ void SpriteRenderer::render_2d_group1(DmaFollower& dma, SharedRenderState* rende
|
|||
SpriteDataMem::Vector, false, true);
|
||||
|
||||
// third is the adgif data
|
||||
u32 expected_adgif_size = sizeof(AdGif) * sprite_count;
|
||||
u32 expected_adgif_size = sizeof(AdGifData) * sprite_count;
|
||||
auto adgif_data = dma.read_and_advance();
|
||||
assert(expected_adgif_size <= sizeof(m_adgif));
|
||||
unpack_to_no_stcycl(&m_adgif, adgif_data, VifCode::Kind::UNPACK_V4_32, expected_adgif_size,
|
||||
|
@ -287,12 +323,14 @@ void SpriteRenderer::render_2d_group1(DmaFollower& dma, SharedRenderState* rende
|
|||
assert(run.vifcode1().kind == VifCode::Kind::MSCAL);
|
||||
assert(run.vifcode1().immediate == SpriteProgMem::Sprites2dHud);
|
||||
if (m_enabled) {
|
||||
do_2d_group1_block_cpu(sprite_count, render_state);
|
||||
do_2d_group1_block_cpu(sprite_count, render_state, prof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void SpriteRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
m_debug_stats = {};
|
||||
// First thing should be a NEXT with two nops. this is a jump from buckets to sprite data
|
||||
auto data0 = dma.read_and_advance();
|
||||
|
@ -310,7 +348,10 @@ void SpriteRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
|||
}
|
||||
|
||||
// First is the distorter
|
||||
render_distorter(dma, render_state);
|
||||
{
|
||||
auto child = prof.make_scoped_child("distorter");
|
||||
render_distorter(dma, render_state, child);
|
||||
}
|
||||
|
||||
// next, sprite frame setup.
|
||||
handle_sprite_frame_setup(dma);
|
||||
|
@ -319,15 +360,21 @@ void SpriteRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
|||
render_3d(dma);
|
||||
|
||||
// 2d draw
|
||||
render_2d_group0(dma);
|
||||
m_sprite_renderer.reset_state();
|
||||
{
|
||||
auto child = prof.make_scoped_child("2d-group0");
|
||||
render_2d_group0(dma, render_state, child);
|
||||
}
|
||||
|
||||
// shadow draw
|
||||
render_fake_shadow(dma);
|
||||
|
||||
// 2d draw (HUD)
|
||||
m_sprite_renderer.reset_state();
|
||||
render_2d_group1(dma, render_state);
|
||||
m_sprite_renderer.flush_pending(render_state);
|
||||
{
|
||||
auto child = prof.make_scoped_child("2d-group1");
|
||||
render_2d_group1(dma, render_state, child);
|
||||
m_sprite_renderer.flush_pending(render_state, child);
|
||||
}
|
||||
|
||||
// TODO finish this up.
|
||||
// fmt::print("next bucket is 0x{}\n", render_state->next_bucket);
|
||||
|
@ -345,6 +392,8 @@ void SpriteRenderer::render(DmaFollower& dma, SharedRenderState* render_state) {
|
|||
|
||||
void SpriteRenderer::draw_debug_window() {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("2D Group 0 (World) blocks: %d sprites: %d", m_debug_stats.blocks_2d_grp0,
|
||||
m_debug_stats.count_2d_grp0);
|
||||
ImGui::Text("2D Group 1 (HUD) blocks: %d sprites: %d", m_debug_stats.blocks_2d_grp1,
|
||||
m_debug_stats.count_2d_grp1);
|
||||
ImGui::Checkbox("Extra Debug", &m_extra_debug);
|
||||
|
@ -398,9 +447,11 @@ void imgui_vec(const Vector4f& vec, const char* name = nullptr, int indent = 0)
|
|||
* - do this math on the GPU
|
||||
* - special case the primitive buffer stuff
|
||||
*/
|
||||
void SpriteRenderer::do_2d_group1_block_cpu(u32 count, SharedRenderState* render_state) {
|
||||
void SpriteRenderer::do_2d_group1_block_cpu(u32 count,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::Begin("Sprite Extra Debug");
|
||||
ImGui::Begin("Sprite Extra Debug 2d_1");
|
||||
}
|
||||
|
||||
// set up double buffering
|
||||
|
@ -448,6 +499,9 @@ void SpriteRenderer::do_2d_group1_block_cpu(u32 count, SharedRenderState* render
|
|||
|
||||
// lqi.xyzw vf01, vi02 | nop
|
||||
Vector4f pos_vf01 = m_vec_data_2d[sprite_idx].xyz_sx;
|
||||
if (m_extra_debug) {
|
||||
imgui_vec(pos_vf01, "POS", 2);
|
||||
}
|
||||
// lqi.xyzw vf05, vi02 | nop
|
||||
Vector4f flags_vf05 = m_vec_data_2d[sprite_idx].flag_rot_sy;
|
||||
// lqi.xyzw vf11, vi02 | nop
|
||||
|
@ -733,7 +787,7 @@ void SpriteRenderer::do_2d_group1_block_cpu(u32 count, SharedRenderState* render
|
|||
// SIXTEEN is xy3int
|
||||
packet.xy3 = xy3_vf22_int;
|
||||
|
||||
m_sprite_renderer.render_gif((const u8*)&packet, sizeof(packet), render_state);
|
||||
m_sprite_renderer.render_gif((const u8*)&packet, sizeof(packet), render_state, prof);
|
||||
if (m_extra_debug) {
|
||||
imgui_vec(vf12_rotated, "vf12", 2);
|
||||
imgui_vec(vf13_rotated_trans, "vf13", 2);
|
||||
|
@ -766,4 +820,368 @@ void SpriteRenderer::do_2d_group1_block_cpu(u32 count, SharedRenderState* render
|
|||
if (m_extra_debug) {
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteRenderer::do_2d_group0_block_cpu(u32 count,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::Begin("Sprite Extra Debug 2d_0");
|
||||
}
|
||||
|
||||
Matrix4f camera_matrix = m_3d_matrix_data.camera; // vf25, vf26, vf27, vf28
|
||||
for (u32 sprite_idx = 0; sprite_idx < count; sprite_idx++) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::Text("Sprite: %d", sprite_idx);
|
||||
}
|
||||
SpriteHud2DPacket packet;
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
// ilw.y vi08, 1(vi02) | nop vi08 = matrix
|
||||
u32 offset_selector = m_vec_data_2d[sprite_idx].matrix();
|
||||
assert(offset_selector == 0 || offset_selector == 1);
|
||||
// moved this out of the loop.
|
||||
// lq.xyzw vf25, 900(vi00) | nop vf25 = cam_mat
|
||||
// lq.xyzw vf26, 901(vi00) | nop
|
||||
// lq.xyzw vf27, 902(vi00) | nop
|
||||
// lq.xyzw vf28, 903(vi00) | nop
|
||||
// lq.xyzw vf30, 904(vi00) | nop vf30 = hvdf_offset
|
||||
// vf30
|
||||
Vector4f hvdf_offset = m_3d_matrix_data.hvdf_offset;
|
||||
|
||||
// lqi.xyzw vf01, vi02 | nop
|
||||
Vector4f pos_vf01 = m_vec_data_2d[sprite_idx].xyz_sx;
|
||||
if (m_extra_debug) {
|
||||
imgui_vec(pos_vf01, "POS", 2);
|
||||
}
|
||||
// lqi.xyzw vf05, vi02 | nop
|
||||
Vector4f flags_vf05 = m_vec_data_2d[sprite_idx].flag_rot_sy;
|
||||
// lqi.xyzw vf11, vi02 | nop
|
||||
Vector4f color_vf11 = m_vec_data_2d[sprite_idx].rgba;
|
||||
|
||||
// multiplications from the right column
|
||||
Vector4f transformed_pos_vf02 = matrix_transform(camera_matrix, pos_vf01);
|
||||
|
||||
Vector4f scales_vf01 = pos_vf01; // now used for something else.
|
||||
// lq.xyzw vf12, 1020(vi00) | mulaw.xyzw ACC, vf28, vf00
|
||||
// vf12 is fog consts
|
||||
Vector4f fog_consts_vf12(m_frame_data.fog_min, m_frame_data.fog_max, m_frame_data.max_scale,
|
||||
m_frame_data.bonus);
|
||||
// ilw.y vi08, 1(vi02) | maddax.xyzw ACC, vf25, vf01
|
||||
// load offset selector for the next round.
|
||||
// nop | madday.xyzw ACC, vf26, vf01
|
||||
// nop | maddz.xyzw vf02, vf27, vf01
|
||||
|
||||
// move.w vf05, vf00 | addw.z vf01, vf00, vf05
|
||||
// scales_vf01.z = sy
|
||||
scales_vf01.z() = flags_vf05.w(); // start building the scale vector
|
||||
flags_vf05.w() = 1.f; // what are we building in flags right now??
|
||||
|
||||
// nop | nop
|
||||
// div Q, vf31.x, vf02.w | muly.z vf05, vf05, vf31
|
||||
float Q = m_frame_data.pfog0 / transformed_pos_vf02.w();
|
||||
flags_vf05.z() *= m_frame_data.deg_to_rad;
|
||||
// nop | mul.xyzw vf03, vf02, vf29
|
||||
Vector4f scaled_pos_vf03 = transformed_pos_vf02.elementwise_multiply(m_frame_data.hmge_scale);
|
||||
// nop | nop
|
||||
// nop | nop
|
||||
// nop | mulz.z vf04, vf05, vf05 (ts)
|
||||
// fmt::print("rot is {} degrees\n", flags_vf05.z() * 360.0 / (2.0 * M_PI));
|
||||
|
||||
// the load is for rotation stuff,
|
||||
// lq.xyzw vf14, 1001(vi00) | clipw.xyz vf03, vf03 (used for fcand)
|
||||
// iaddi vi06, vi00, 0x1 | adda.xyzw ACC, vf11, vf11 (used for fmand)
|
||||
|
||||
// upcoming fcand with 0x3f, that checks all of them.
|
||||
bool fcand_result = clip_xyz_plus_minus(scaled_pos_vf03);
|
||||
bool fmand_result = color_vf11.w() == 0; // (really w+w, but I don't think it matters?)
|
||||
|
||||
// L8:
|
||||
// xgkick double buffer setup
|
||||
// ior vi05, vi15, vi00 | mul.zw vf01, vf01, Q
|
||||
scales_vf01.z() *= Q; // sy
|
||||
scales_vf01.w() *= Q; // sx
|
||||
|
||||
// lq.xyzw vf06, 998(vi00) | mulz.xyzw vf15, vf05, vf04 (ts)
|
||||
auto adgif_vf06 = m_frame_data.adgif_giftag;
|
||||
|
||||
// lq.xyzw vf14, 1002(vi00) ts| mula.xyzw ACC, vf05, vf14 (ts)
|
||||
|
||||
// fmand vi01, vi06 | mul.xyz vf02, vf02, Q
|
||||
transformed_pos_vf02.x() *= Q;
|
||||
transformed_pos_vf02.y() *= Q;
|
||||
transformed_pos_vf02.z() *= Q;
|
||||
|
||||
// if (m_extra_debug) {
|
||||
// imgui_vec(transformed_pos_vf02, "scaled xf");
|
||||
// }
|
||||
|
||||
// ibne vi00, vi01, L10 | addz.x vf01, vf00, vf01
|
||||
scales_vf01.x() = scales_vf01.z(); // = sy
|
||||
if (fmand_result) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::TextColored(ImVec4(0.8, 0.2, 0.2, 1.0), "fmand (1) reject");
|
||||
ImGui::Separator();
|
||||
}
|
||||
continue; // reject!
|
||||
}
|
||||
|
||||
// lqi.xyzw vf07, vi03 | mulz.xyzw vf16, vf15, vf04 (ts)
|
||||
// vf07 is first use adgif
|
||||
|
||||
// lq.xyzw vf14, 1003(vi00) | madda.xyzw ACC, vf15, vf14 (ts both)
|
||||
|
||||
// lqi.xyzw vf08, vi03 | add.xyzw vf10, vf02, vf30
|
||||
// vf08 is second user adgif
|
||||
Vector4f offset_pos_vf10 = transformed_pos_vf02 + hvdf_offset;
|
||||
// if (m_extra_debug) {
|
||||
// ImGui::Text("sel %d", offset_selector);
|
||||
// //ImGui::Text("hvdf off z: %f tf/w z: %f", hvdf_offset.z(), transformed_pos_vf02.z());
|
||||
// imgui_vec(hvdf_offset, "hvdf");
|
||||
// imgui_vec(transformed_pos_vf02, "tf'd");
|
||||
// }
|
||||
|
||||
// lqi.xyzw vf09, vi03 | mulw.x vf01, vf01, vf01
|
||||
// vf09 is third user adgif
|
||||
scales_vf01.x() *= scales_vf01.w(); // x = sx * sy
|
||||
|
||||
// sqi.xyzw vf06, vi05 | mulz.xyzw vf15, vf16, vf04 (ts)
|
||||
// FIRST ADGIF IS adgif_vf06
|
||||
packet.adgif_giftag = adgif_vf06;
|
||||
|
||||
// lq.xyzw vf14, 1004(vi00) | madda.xyzw ACC, vf16, vf14 (ts both)
|
||||
|
||||
// sqi.xyzw vf07, vi05 | maxx.w vf10, vf10, vf12
|
||||
// SECOND ADGIF is first user
|
||||
// just do all 5 now.
|
||||
packet.user_adgif = m_adgif[sprite_idx];
|
||||
|
||||
offset_pos_vf10.w() = std::max(offset_pos_vf10.w(), m_frame_data.fog_max);
|
||||
|
||||
// sqi.xyzw vf08, vi05 | maxz.zw vf01, vf01, vf31
|
||||
// THIRD ADGIF is second user
|
||||
scales_vf01.z() = std::max(scales_vf01.z(), m_frame_data.min_scale);
|
||||
scales_vf01.w() = std::max(scales_vf01.w(), m_frame_data.min_scale);
|
||||
|
||||
// sqi.xyzw vf09, vi05 | mulz.xyzw vf16, vf15, vf04 (ts)
|
||||
// FOURTH ADGIF is third user
|
||||
|
||||
// lq.xyzw vf14, 1005(vi00) | madda.xyzw ACC, vf15, vf14 (ts both)
|
||||
|
||||
// lqi.xyzw vf06, vi03 | mulw.x vf01, vf01, vf31
|
||||
// vf06 is fourth user adgif
|
||||
scales_vf01.x() *= m_frame_data.inv_area; // x = sx * sy * inv_area (area ratio)
|
||||
|
||||
// lqi.xyzw vf07, vi03 | miniy.w vf10, vf10, vf12
|
||||
// vf07 is fifth user adgif
|
||||
offset_pos_vf10.w() = std::min(offset_pos_vf10.w(), m_frame_data.fog_min);
|
||||
|
||||
// lq.xyzw vf08, 999(vi00) | miniz.zw vf01, vf01, vf12
|
||||
// vf08 is 2d giftag 1 (NOTE THIS IS DIFFERENT FROM 2d 1)!!!!!
|
||||
scales_vf01.z() = std::min(scales_vf01.z(), fog_consts_vf12.z());
|
||||
scales_vf01.w() = std::min(scales_vf01.w(), fog_consts_vf12.z());
|
||||
bool use_first_giftag = offset_selector == 0;
|
||||
|
||||
// ilw.x vi07, -2(vi02) | madd.xyzw vf05, vf16, vf14
|
||||
auto flag_vi07 = m_vec_data_2d[sprite_idx].flag();
|
||||
Vector4f vf05_sincos(0, 0, std::sin(flags_vf05.z()), std::cos(flags_vf05.z()));
|
||||
|
||||
// lqi.xyzw vf23, vi02 | miniw.x vf01, vf01, vf00
|
||||
// pipeline
|
||||
scales_vf01.x() = std::min(scales_vf01.x(), 1.f);
|
||||
|
||||
// nop | suby.w vf02, vf10, vf12 (unique)
|
||||
transformed_pos_vf02.w() = offset_pos_vf10.w() - fog_consts_vf12.y();
|
||||
|
||||
// lqi.xyzw vf24, vi02 | mulx.w vf11, vf11, vf01
|
||||
// pipeline
|
||||
color_vf11.w() *= scales_vf01.x(); // is this right? doesn't this stall??
|
||||
|
||||
// fcand vi01, 0x3f | mulaw.xyzw ACC, vf28, vf00
|
||||
// already computed pipeline
|
||||
|
||||
// lq.xyzw vf17, 1006(vi00) | maddax.xyzw ACC, vf25, vf23 (pipeline)
|
||||
Vector4f basis_x_vf17 = m_frame_data.basis_x;
|
||||
|
||||
// fmand vi09, vi06 | nop
|
||||
// ibne vi00, vi09, L6 | nop
|
||||
if (transformed_pos_vf02.w() != 0) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::TextColored(ImVec4(0.8, 0.2, 0.2, 1.0), "fmand (2) trick");
|
||||
}
|
||||
use_first_giftag = false;
|
||||
}
|
||||
|
||||
// lq.xyzw vf18, 1007(vi00) | madday.xyzw ACC, vf26, vf23 (pipeline)
|
||||
Vector4f basis_y_vf18 = m_frame_data.basis_y;
|
||||
|
||||
assert(flag_vi07 == 0);
|
||||
Vector4f* xy_array = m_frame_data.xy_array + flag_vi07;
|
||||
// lq.xyzw vf19, 980(vi07) | ftoi0.xyzw vf11, vf11
|
||||
Vector4f xy0_vf19 = xy_array[0];
|
||||
math::Vector<s32, 4> color_integer_vf11 = color_vf11.cast<s32>();
|
||||
|
||||
// lq.xyzw vf20, 981(vi07) | maddz.xyzw vf02, vf27, vf23 (pipeline)
|
||||
Vector4f xy1_vf20 = xy_array[1];
|
||||
|
||||
// lq.xyzw vf21, 982(vi07) | mulaw.xyzw ACC, vf17, vf05
|
||||
Vector4f xy2_vf21 = xy_array[2];
|
||||
Vector4f acc = basis_x_vf17 * vf05_sincos.w();
|
||||
|
||||
// lq.xyzw vf22, 983(vi07) | msubz.xyzw vf12, vf18, vf05
|
||||
Vector4f xy3_vf22 = xy_array[3];
|
||||
Vector4f vf12_rotated = acc - (basis_y_vf18 * vf05_sincos.z());
|
||||
// sq.xyzw vf11, 3(vi05) | mulaz.xyzw ACC, vf17, vf05
|
||||
// EIGHTH is color integer
|
||||
packet.color = color_integer_vf11;
|
||||
|
||||
acc = basis_x_vf17 * vf05_sincos.z();
|
||||
|
||||
// lqi.xyzw vf11, vi02 | maddw.xyzw vf13, vf18, vf05
|
||||
// (pipeline)
|
||||
Vector4f vf13_rotated_trans = acc + basis_y_vf18 * vf05_sincos.w();
|
||||
|
||||
// move.w vf24, vf00 | addw.z vf23, vf00, vf24 (pipeline both)
|
||||
|
||||
// div Q, vf31.x, vf02.w | mulw.xyzw vf12, vf12, vf01
|
||||
// (pipeline)
|
||||
vf12_rotated *= scales_vf01.w();
|
||||
|
||||
// ibne vi00, vi01, L9 | muly.z vf24, vf24, vf31 (pipeline)
|
||||
if (fcand_result) {
|
||||
if (m_extra_debug) {
|
||||
ImGui::TextColored(ImVec4(0.8, 0.2, 0.2, 1.0), "fcand reject");
|
||||
ImGui::Separator();
|
||||
}
|
||||
continue; // reject (could move earlier)
|
||||
}
|
||||
|
||||
// ilw.y vi08, 1(vi02) | mulz.xyzw vf13, vf13, vf01
|
||||
// (pipeline)
|
||||
vf13_rotated_trans *= scales_vf01.z();
|
||||
|
||||
// LEFT OFF HERE!
|
||||
|
||||
// sqi.xyzw vf06, vi05 | mul.xyzw vf03, vf02, vf29
|
||||
// FIFTH is fourth user
|
||||
|
||||
// sqi.xyzw vf07, vi05 | mulaw.xyzw ACC, vf10, vf00
|
||||
// SIXTH is fifth user
|
||||
acc = offset_pos_vf10;
|
||||
|
||||
// sqi.xyzw vf08, vi05 | maddax.xyzw ACC, vf12, vf19
|
||||
// SEVENTH is giftag2
|
||||
packet.sprite_giftag =
|
||||
use_first_giftag ? m_frame_data.sprite_2d_giftag : m_frame_data.sprite_2d_giftag2;
|
||||
acc += vf12_rotated * xy0_vf19.x();
|
||||
|
||||
// lq.xyzw vf06, 988(vi00) | maddy.xyzw vf19, vf13, vf19
|
||||
Vector4f st0_vf06 = m_frame_data.st_array[0];
|
||||
xy0_vf19 = acc + vf13_rotated_trans * xy0_vf19.y();
|
||||
|
||||
// lq.xyzw vf07, 989(vi00) | mulaw.xyzw ACC, vf10, vf00
|
||||
Vector4f st1_vf07 = m_frame_data.st_array[1];
|
||||
acc = offset_pos_vf10;
|
||||
|
||||
// lq.xyzw vf08, 990(vi00) | maddax.xyzw ACC, vf12, vf20
|
||||
Vector4f st2_vf08 = m_frame_data.st_array[2];
|
||||
acc += vf12_rotated * xy1_vf20.x();
|
||||
|
||||
// lq.xyzw vf09, 991(vi00) | maddy.xyzw vf20, vf13, vf20
|
||||
Vector4f st3_vf09 = m_frame_data.st_array[3];
|
||||
xy1_vf20 = acc + vf13_rotated_trans * xy1_vf20.y();
|
||||
|
||||
// sq.xyzw vf06, 1(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
// NINTH is st0
|
||||
packet.st0 = st0_vf06;
|
||||
acc = offset_pos_vf10;
|
||||
|
||||
// sq.xyzw vf07, 3(vi05) | maddax.xyzw ACC, vf12, vf21
|
||||
// ELEVEN is st1
|
||||
packet.st1 = st1_vf07;
|
||||
acc += vf12_rotated * xy2_vf21.x();
|
||||
|
||||
// sq.xyzw vf08, 5(vi05) | maddy.xyzw vf21, vf13, vf21
|
||||
// THIRTEEN is st2
|
||||
packet.st2 = st2_vf08;
|
||||
xy2_vf21 = acc + vf13_rotated_trans * xy2_vf21.y();
|
||||
|
||||
// sq.xyzw vf09, 7(vi05) | mulaw.xyzw ACC, vf10, vf00
|
||||
// FIFTEEN is st3
|
||||
packet.st3 = st3_vf09;
|
||||
acc = offset_pos_vf10;
|
||||
|
||||
// nop | maddax.xyzw ACC, vf12, vf22
|
||||
acc += vf12_rotated * xy3_vf22.x();
|
||||
|
||||
// nop | maddy.xyzw vf22, vf13, vf22
|
||||
xy3_vf22 = acc + vf13_rotated_trans * xy3_vf22.y();
|
||||
|
||||
// lq.xyzw vf12, 1020(vi00) | ftoi4.xyzw vf19, vf19
|
||||
// (pipeline)
|
||||
auto xy0_vf19_int = (xy0_vf19 * 16.f).cast<s32>();
|
||||
|
||||
// lq.xyzw vf14, 1001(vi00) | ftoi4.xyzw vf20, vf20
|
||||
// (pipeline)
|
||||
auto xy1_vf20_int = (xy1_vf20 * 16.f).cast<s32>();
|
||||
|
||||
// move.xyzw vf05, vf24 | ftoi4.xyzw vf21, vf21
|
||||
// (pipeline)
|
||||
auto xy2_vf21_int = (xy2_vf21 * 16.f).cast<s32>();
|
||||
|
||||
// move.xyzw vf01, vf23 | ftoi4.xyzw vf22, vf22
|
||||
// (pipeline)
|
||||
auto xy3_vf22_int = (xy3_vf22 * 16.f).cast<s32>();
|
||||
|
||||
if (m_extra_debug) {
|
||||
u32 zi = xy3_vf22_int.z() >> 4;
|
||||
ImGui::Text("z (int): 0x%08x %s", zi, zi >= (1 << 24) ? "bad" : "");
|
||||
ImGui::Text("z (flt): %f", (double)(((u32)zi) << 8) / UINT32_MAX);
|
||||
}
|
||||
|
||||
// sq.xyzw vf19, 2(vi05) | mulz.z vf04, vf24, vf24 (pipeline)
|
||||
// TENTH is xy0int
|
||||
packet.xy0 = xy0_vf19_int;
|
||||
// sq.xyzw vf20, 4(vi05) | clipw.xyz vf03, vf03 (pipeline)
|
||||
// TWELVE is xy1int
|
||||
packet.xy1 = xy1_vf20_int;
|
||||
// sq.xyzw vf21, 6(vi05) | nop
|
||||
// FOURTEEN is xy2int
|
||||
packet.xy2 = xy2_vf21_int;
|
||||
// sq.xyzw vf22, 8(vi05) | nop
|
||||
// SIXTEEN is xy3int
|
||||
packet.xy3 = xy3_vf22_int;
|
||||
|
||||
m_sprite_renderer.render_gif((const u8*)&packet, sizeof(packet), render_state, prof);
|
||||
if (m_extra_debug) {
|
||||
imgui_vec(vf12_rotated, "vf12", 2);
|
||||
imgui_vec(vf13_rotated_trans, "vf13", 2);
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
// 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
|
||||
// nop | nop
|
||||
}
|
||||
|
||||
if (m_extra_debug) {
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ struct SpriteFrameData {
|
|||
Vector4f basis_x;
|
||||
Vector4f basis_y;
|
||||
GifTag sprite_3d_giftag;
|
||||
AdGif screen_shader;
|
||||
AdGifData screen_shader;
|
||||
GifTag clipped_giftag;
|
||||
Vector4f inv_hmge_scale;
|
||||
Vector4f stq_offset;
|
||||
|
@ -117,7 +117,7 @@ enum SpriteDataMem {
|
|||
*/
|
||||
struct SpriteHud2DPacket {
|
||||
GifTag adgif_giftag; // starts the adgif shader. 0
|
||||
AdGif user_adgif; // the adgif shader 16
|
||||
AdGifData user_adgif; // the adgif shader 16
|
||||
GifTag sprite_giftag; // 96
|
||||
math::Vector<s32, 4> color;
|
||||
Vector4f st0;
|
||||
|
@ -146,18 +146,25 @@ static_assert(sizeof(SpriteFrameData) == 0x290, "SpriteFrameData size");
|
|||
class SpriteRenderer : public BucketRenderer {
|
||||
public:
|
||||
SpriteRenderer(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state) override;
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
static constexpr int SPRITES_PER_CHUNK = 48;
|
||||
|
||||
private:
|
||||
void render_distorter(DmaFollower& dma, SharedRenderState* render_state);
|
||||
void render_distorter(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_sprite_frame_setup(DmaFollower& dma);
|
||||
void render_3d(DmaFollower& dma);
|
||||
void render_2d_group0(DmaFollower& dma);
|
||||
void render_2d_group0(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void render_fake_shadow(DmaFollower& dma);
|
||||
void render_2d_group1(DmaFollower& dma, SharedRenderState* render_state);
|
||||
void do_2d_group1_block_cpu(u32 count, SharedRenderState* render_state);
|
||||
void render_2d_group1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void do_2d_group1_block_cpu(u32 count, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void do_2d_group0_block_cpu(u32 count, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
u8 m_sprite_distorter_setup[7 * 16]; // direct data
|
||||
u8 m_sprite_direct_setup[3 * 16];
|
||||
|
@ -166,9 +173,11 @@ class SpriteRenderer : public BucketRenderer {
|
|||
SpriteHudMatrixData m_hud_matrix_data;
|
||||
|
||||
SpriteVecData2d m_vec_data_2d[SPRITES_PER_CHUNK];
|
||||
AdGif m_adgif[SPRITES_PER_CHUNK];
|
||||
AdGifData m_adgif[SPRITES_PER_CHUNK];
|
||||
|
||||
struct DebugStats {
|
||||
int blocks_2d_grp0 = 0;
|
||||
int count_2d_grp0 = 0;
|
||||
int blocks_2d_grp1 = 0;
|
||||
int count_2d_grp1 = 0;
|
||||
} m_debug_stats;
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
TextureUploadHandler::TextureUploadHandler(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id) {}
|
||||
|
||||
void TextureUploadHandler::render(DmaFollower& dma, SharedRenderState* render_state) {
|
||||
void TextureUploadHandler::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& /*prof*/) {
|
||||
m_stats = {};
|
||||
|
||||
// this is the data we get from the PC Port modification.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
class TextureUploadHandler : public BucketRenderer {
|
||||
public:
|
||||
TextureUploadHandler(const std::string& name, BucketId my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state) override;
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
void serialize(Serializer& ser) override;
|
||||
|
||||
|
|
|
@ -84,10 +84,14 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
|
|||
if (ImGui::BeginMenu("Windows")) {
|
||||
ImGui::MenuItem("Frame Time Plot", nullptr, &m_draw_frame_time);
|
||||
ImGui::MenuItem("Render Debug", nullptr, &m_draw_debug);
|
||||
ImGui::MenuItem("Profiler", nullptr, &m_draw_profiler);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Gfx Dump")) {
|
||||
ImGui::MenuItem("Screenshot Next Frame!", nullptr, &m_want_screenshot);
|
||||
ImGui::InputText("File", m_screenshot_save_name, 30);
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Dump Next Frame!", nullptr, &m_want_save);
|
||||
bool old_replay = m_want_replay;
|
||||
ImGui::MenuItem("Load Saved Dump", nullptr, &m_want_replay);
|
||||
|
@ -96,7 +100,7 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
|
|||
}
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::InputText("Filename", m_dump_save_name, 12);
|
||||
ImGui::InputText("Dump", m_dump_save_name, 12);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,19 +39,32 @@ class OpenGlDebugGui {
|
|||
void finish_frame();
|
||||
void draw(const DmaStats& dma_stats);
|
||||
bool should_draw_render_debug() const { return m_draw_debug; }
|
||||
bool should_draw_profiler() const { return m_draw_profiler; }
|
||||
bool& want_save() { return m_want_save; }
|
||||
bool& want_dump_replay() { return m_want_replay; }
|
||||
bool& want_dump_load() { return m_want_dump_load; }
|
||||
const char* dump_name() const { return m_dump_save_name; }
|
||||
const char* screenshot_name() const { return m_screenshot_save_name; }
|
||||
|
||||
bool should_advance_frame() { return m_frame_timer.should_advance_frame(); }
|
||||
|
||||
bool get_screenshot_flag() {
|
||||
if (m_want_screenshot) {
|
||||
m_want_screenshot = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
FrameTimeRecorder m_frame_timer;
|
||||
bool m_draw_frame_time = false;
|
||||
bool m_draw_profiler = false;
|
||||
bool m_draw_debug = false;
|
||||
bool m_want_save = false;
|
||||
bool m_want_replay = false;
|
||||
bool m_want_dump_load = false;
|
||||
bool m_want_screenshot = false;
|
||||
char m_dump_save_name[256] = "dump.bin";
|
||||
char m_screenshot_save_name[256] = "screenshot.png";
|
||||
};
|
|
@ -7,6 +7,7 @@ in vec2 tex_coord;
|
|||
uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord);
|
||||
//vec4 T0 = texture(tex_T0, tex_coord);
|
||||
vec4 T0 = textureProj(tex_T0, vec3(tex_coord, 1.0));
|
||||
color = fragment_color * T0 * 2.0;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec2 tex_coord_in;
|
||||
layout (location = 2) in vec3 tex_coord_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec2 tex_coord;
|
||||
|
@ -10,5 +10,5 @@ out vec2 tex_coord;
|
|||
void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32, position_in.z, 1.0);
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
|
||||
tex_coord = tex_coord_in;
|
||||
tex_coord = tex_coord_in.xy;
|
||||
}
|
|
@ -3,11 +3,13 @@
|
|||
out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
in vec2 tex_coord;
|
||||
in vec3 tex_coord;
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord);
|
||||
vec4 T0 = texture(tex_T0, tex_coord.xy / tex_coord.z);
|
||||
//vec4 T0 = textureProj(tex_T0, vec3(tex_coord.xy, 1.0));
|
||||
T0.w = 1.0;
|
||||
color = fragment_color * T0 * 2.0;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec2 tex_coord_in;
|
||||
layout (location = 2) in vec3 tex_coord_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec2 tex_coord;
|
||||
out vec3 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32, position_in.z, 1.0);
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16. , -(position_in.y - 0.5) * 32, position_in.z, 1.0);
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.a * 2);
|
||||
tex_coord = tex_coord_in;
|
||||
}
|
13
game/graphics/opengl_renderer/shaders/sky.frag
Normal file
13
game/graphics/opengl_renderer/shaders/sky.frag
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 330 core
|
||||
|
||||
out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
in vec3 tex_coord;
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord.xy / tex_coord.z);
|
||||
T0.w = 1.0;
|
||||
color = fragment_color * T0 * 2.0;
|
||||
}
|
14
game/graphics/opengl_renderer/shaders/sky.vert
Normal file
14
game/graphics/opengl_renderer/shaders/sky.vert
Normal file
|
@ -0,0 +1,14 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec3 tex_coord_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
noperspective out vec3 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16. , -(position_in.y - 0.5) * 32, position_in.z, 1.0);
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.a * 2);
|
||||
tex_coord = tex_coord_in;
|
||||
}
|
11
game/graphics/opengl_renderer/shaders/sky_blend.frag
Normal file
11
game/graphics/opengl_renderer/shaders/sky_blend.frag
Normal file
|
@ -0,0 +1,11 @@
|
|||
#version 330 core
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
in vec3 tex_coord;
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord.xy);
|
||||
color = vec4(((T0 )) * tex_coord.z);
|
||||
}
|
10
game/graphics/opengl_renderer/shaders/sky_blend.vert
Normal file
10
game/graphics/opengl_renderer/shaders/sky_blend.vert
Normal file
|
@ -0,0 +1,10 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
|
||||
out vec3 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position_in.x*2 -1, position_in.y*2-1, 0.0, 1.0);
|
||||
tex_coord = position_in;
|
||||
}
|
|
@ -190,6 +190,13 @@ static void gl_kill_display(GfxDisplay* display) {
|
|||
glfwDestroyWindow(display->window_glfw);
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string make_output_file_name(const std::string& file_name) {
|
||||
file_util::create_dir_if_needed(file_util::get_file_path({"gfx_dumps"}));
|
||||
return file_util::get_file_path({"gfx_dumps", file_name});
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void make_gfx_dump() {
|
||||
Timer ser_timer;
|
||||
Serializer ser;
|
||||
|
@ -203,10 +210,8 @@ void make_gfx_dump() {
|
|||
ser_timer.getMs(), ((double)result.second) / (1 << 20),
|
||||
((double)compressed.size() / (1 << 20)), compression_timer.getMs());
|
||||
|
||||
file_util::create_dir_if_needed(file_util::get_file_path({"gfx_dumps"}));
|
||||
file_util::write_binary_file(
|
||||
file_util::get_file_path({"gfx_dumps", g_gfx_data->debug_gui.dump_name()}), compressed.data(),
|
||||
compressed.size());
|
||||
file_util::write_binary_file(make_output_file_name(g_gfx_data->debug_gui.dump_name()),
|
||||
compressed.data(), compressed.size());
|
||||
}
|
||||
|
||||
void render_game_frame(int width, int height) {
|
||||
|
@ -234,9 +239,17 @@ void render_game_frame(int width, int height) {
|
|||
|
||||
auto& chain = g_gfx_data->dma_copier.get_last_result();
|
||||
g_gfx_data->frame_idx_of_input_data = g_gfx_data->frame_idx;
|
||||
g_gfx_data->ogl_renderer.render(DmaFollower(chain.data.data(), chain.start_offset), width,
|
||||
height, g_gfx_data->debug_gui.should_draw_render_debug(),
|
||||
false);
|
||||
RenderOptions options;
|
||||
options.window_height_px = height;
|
||||
options.window_width_px = width;
|
||||
options.draw_render_debug_window = g_gfx_data->debug_gui.should_draw_render_debug();
|
||||
options.draw_profiler_window = g_gfx_data->debug_gui.should_draw_profiler();
|
||||
options.playing_from_dump = false;
|
||||
options.save_screenshot = g_gfx_data->debug_gui.get_screenshot_flag();
|
||||
if (options.save_screenshot) {
|
||||
options.screenshot_path = make_output_file_name(g_gfx_data->debug_gui.screenshot_name());
|
||||
}
|
||||
g_gfx_data->ogl_renderer.render(DmaFollower(chain.data.data(), chain.start_offset), options);
|
||||
}
|
||||
|
||||
// before vsync, mark the chain as rendered.
|
||||
|
@ -252,8 +265,8 @@ void render_game_frame(int width, int height) {
|
|||
void render_dump_frame(int width, int height) {
|
||||
Timer deser_timer;
|
||||
if (g_gfx_data->debug_gui.want_dump_load()) {
|
||||
auto data = file_util::read_binary_file(
|
||||
file_util::get_file_path({"gfx_dumps", g_gfx_data->debug_gui.dump_name()}));
|
||||
auto data =
|
||||
file_util::read_binary_file(make_output_file_name(g_gfx_data->debug_gui.dump_name()));
|
||||
auto decompressed = compression::decompress_zstd(data.data(), data.size());
|
||||
g_gfx_data->loaded_dump = Serializer(decompressed.data(), decompressed.size());
|
||||
}
|
||||
|
@ -268,8 +281,19 @@ void render_dump_frame(int width, int height) {
|
|||
g_gfx_data->debug_gui.want_dump_load() = false;
|
||||
|
||||
auto& chain = g_gfx_data->dma_copier.get_last_result();
|
||||
g_gfx_data->ogl_renderer.render(DmaFollower(chain.data.data(), chain.start_offset), width, height,
|
||||
g_gfx_data->debug_gui.should_draw_render_debug(), true);
|
||||
|
||||
RenderOptions options;
|
||||
options.window_height_px = height;
|
||||
options.window_width_px = width;
|
||||
options.draw_render_debug_window = g_gfx_data->debug_gui.should_draw_render_debug();
|
||||
options.draw_profiler_window = g_gfx_data->debug_gui.should_draw_profiler();
|
||||
options.playing_from_dump = true;
|
||||
options.save_screenshot = g_gfx_data->debug_gui.get_screenshot_flag();
|
||||
if (options.save_screenshot) {
|
||||
options.screenshot_path = make_output_file_name(g_gfx_data->debug_gui.screenshot_name());
|
||||
}
|
||||
|
||||
g_gfx_data->ogl_renderer.render(DmaFollower(chain.data.data(), chain.start_offset), options);
|
||||
}
|
||||
|
||||
static void gl_render_display(GfxDisplay* display) {
|
||||
|
@ -314,8 +338,9 @@ static void gl_render_display(GfxDisplay* display) {
|
|||
|
||||
// exit if display window was closed
|
||||
if (glfwWindowShouldClose(window)) {
|
||||
// Display::KillDisplay(window);
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->sync_mutex);
|
||||
MasterExit = 2;
|
||||
g_gfx_data->sync_cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,7 +355,7 @@ u32 gl_vsync() {
|
|||
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->sync_mutex);
|
||||
auto init_frame = g_gfx_data->frame_idx_of_input_data;
|
||||
g_gfx_data->sync_cv.wait(lock, [=] { return g_gfx_data->frame_idx > init_frame; });
|
||||
g_gfx_data->sync_cv.wait(lock, [=] { return MasterExit || g_gfx_data->frame_idx > init_frame; });
|
||||
|
||||
return g_gfx_data->frame_idx & 1;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,16 @@ std::string GoalTexturePage::print() const {
|
|||
}
|
||||
|
||||
void TextureRecord::serialize(Serializer& ser) {
|
||||
if (only_on_gpu) {
|
||||
assert(on_gpu);
|
||||
if (ser.is_saving()) {
|
||||
// we should download the texture and save it.
|
||||
data.resize(w * h * 4);
|
||||
glBindTexture(GL_TEXTURE_2D, gpu_texture);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, data.data());
|
||||
}
|
||||
}
|
||||
|
||||
ser.from_str(&page_name);
|
||||
ser.from_str(&name);
|
||||
ser.from_ptr(&mip_level);
|
||||
|
@ -46,6 +56,7 @@ void TextureRecord::serialize(Serializer& ser) {
|
|||
ser.from_ptr(&data_segment);
|
||||
ser.from_ptr(&on_gpu);
|
||||
ser.from_ptr(&do_gc);
|
||||
ser.from_ptr(&only_on_gpu);
|
||||
ser.from_ptr(&gpu_texture);
|
||||
ser.from_ptr(&dest);
|
||||
ser.from_pod_vector(&data);
|
||||
|
@ -53,6 +64,10 @@ void TextureRecord::serialize(Serializer& ser) {
|
|||
ser.from_ptr(&max_a_zero);
|
||||
ser.from_ptr(&min_a_nonzero);
|
||||
ser.from_ptr(&max_a_nonzero);
|
||||
|
||||
if (ser.is_loading()) {
|
||||
gpu_texture = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureData::serialize(Serializer& ser) {
|
||||
|
@ -67,6 +82,7 @@ void TextureData::serialize(Serializer& ser) {
|
|||
if (mt4hh_texture) {
|
||||
ser.save<u8>(1); // has it.
|
||||
mt4hh_texture->serialize(ser);
|
||||
|
||||
} else {
|
||||
ser.save<u8>(0);
|
||||
}
|
||||
|
@ -75,9 +91,7 @@ void TextureData::serialize(Serializer& ser) {
|
|||
if (has_normal) {
|
||||
normal_texture = std::make_shared<TextureRecord>();
|
||||
normal_texture->serialize(ser);
|
||||
// after deserializing, nothing is on the GPU
|
||||
normal_texture->on_gpu = false;
|
||||
// there will be a duplicate copy of this texture in the bucket, we want this one to be gc'd
|
||||
normal_texture->do_gc = true;
|
||||
} else {
|
||||
normal_texture.reset();
|
||||
|
@ -284,6 +298,7 @@ void TexturePool::set_texture(u32 location, std::shared_ptr<TextureRecord> recor
|
|||
if (m_textures.at(location).normal_texture) {
|
||||
if (record->do_gc && m_textures.at(location).normal_texture != record) {
|
||||
m_garbage_textures.push_back(std::move(m_textures[location].normal_texture));
|
||||
fmt::print("replace add to garbage list {}\n", m_garbage_textures.back()->name);
|
||||
}
|
||||
}
|
||||
m_textures[location].normal_texture = std::move(record);
|
||||
|
@ -356,8 +371,8 @@ void TexturePool::draw_debug_for_tex(const std::string& name, TextureRecord& tex
|
|||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3, 0.8, 0.3, 1.0));
|
||||
}
|
||||
if (ImGui::TreeNode(name.c_str())) {
|
||||
ImGui::Text("P: %s sz: %d x %d mip %d GPU? %d psm %d cpsm %d", tex.page_name.c_str(), tex.w,
|
||||
tex.h, tex.mip_level, tex.on_gpu, tex.psm, tex.cpsm);
|
||||
ImGui::Text("P: %s sz: %d x %d mip %d GPU? %d psm %d cpsm %d dest %d", tex.page_name.c_str(),
|
||||
tex.w, tex.h, tex.mip_level, tex.on_gpu, tex.psm, tex.cpsm, tex.dest);
|
||||
if (tex.on_gpu) {
|
||||
ImGui::Image((void*)tex.gpu_texture, ImVec2(tex.w, tex.h));
|
||||
} else {
|
||||
|
@ -401,6 +416,7 @@ void TexturePool::remove_garbage_textures() {
|
|||
for (auto& t : m_garbage_textures) {
|
||||
if (t->on_gpu) {
|
||||
m_most_recent_gc_count_gpu++;
|
||||
fmt::print("GC {}\n", t->name);
|
||||
t->unload_from_gpu();
|
||||
}
|
||||
}
|
||||
|
@ -409,5 +425,16 @@ void TexturePool::remove_garbage_textures() {
|
|||
|
||||
void TexturePool::discard(std::shared_ptr<TextureRecord> tex) {
|
||||
assert(!tex->do_gc);
|
||||
fmt::print("discard {}\n", tex->name);
|
||||
m_garbage_textures.push_back(tex);
|
||||
}
|
||||
|
||||
TextureRecord* TexturePool::get_random_texture() {
|
||||
u32 idx = 8;
|
||||
for (u32 i = 0; i < m_textures.size(); i++) {
|
||||
if (m_textures.at((i + idx) % m_textures.size()).normal_texture) {
|
||||
return m_textures.at((i + idx) % m_textures.size()).normal_texture.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -16,7 +16,8 @@ struct TextureRecord {
|
|||
u16 w, h;
|
||||
u8 data_segment;
|
||||
bool on_gpu = false;
|
||||
bool do_gc = true;
|
||||
bool do_gc = true; // if set, will be unloaded from GPU when another is upload on top
|
||||
bool only_on_gpu = false;
|
||||
std::vector<u8> data;
|
||||
u64 gpu_texture = 0;
|
||||
u32 dest = -1;
|
||||
|
@ -124,6 +125,8 @@ class TexturePool {
|
|||
}
|
||||
}
|
||||
|
||||
TextureRecord* get_random_texture();
|
||||
|
||||
void upload_to_gpu(TextureRecord* rec);
|
||||
|
||||
void relocate(u32 destination, u32 source, u32 format);
|
||||
|
|
|
@ -364,7 +364,8 @@ void load_and_link_dgo_from_c(const char* name, Ptr<kheapinfo> heap, u32 linkFla
|
|||
|
||||
char objName[64];
|
||||
strcpy(objName, (dgoObj + 4).cast<char>().c()); // name from dgo object header
|
||||
lg::debug("[link and exec] {} {} {}", objName, lastObjectLoaded, objSize);
|
||||
lg::debug("[link and exec] {:18s} {} {:6d} heap-use {:8d} {:8d}", objName, lastObjectLoaded,
|
||||
objSize, kheapused(kglobalheap), kheapused(kdebugheap));
|
||||
link_and_exec(obj, objName, objSize, heap, linkFlag); // link now!
|
||||
|
||||
// inform IOP we are done
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "common/goal_constants.h"
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "game/mips2c/mips2c_table.h"
|
||||
|
||||
//! Controls link mode when EnableMethodSet = 0, MasterDebug = 1, DiskBoot = 0. Will enable a
|
||||
//! warning message if EnableMethodSet = 1
|
||||
|
@ -1712,6 +1713,8 @@ s32 test_function(s32 arg0, s32 arg1, s32 arg2, s32 arg3) {
|
|||
*/
|
||||
s32 InitHeapAndSymbol() {
|
||||
Timer heap_init_timer;
|
||||
// reset all mips2c functions
|
||||
Mips2C::gLinkedFunctionTable = {};
|
||||
// allocate memory for the symbol table
|
||||
auto symbol_table = kmalloc(kglobalheap, 0x20000, KMALLOC_MEMSET, "symbol-table").cast<u32>();
|
||||
|
||||
|
|
1112
game/mips2c/functions/sky_tng.cpp
Normal file
1112
game/mips2c/functions/sky_tng.cpp
Normal file
File diff suppressed because it is too large
Load diff
163
game/mips2c/functions/texture.cpp
Normal file
163
game/mips2c/functions/texture.cpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
//--------------------------MIPS2C---------------------
|
||||
// clang-format off
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/kscheme.h"
|
||||
namespace Mips2C {
|
||||
namespace adgif_shader_texture_with_update {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->ld(a2, 16, a0); // ld a2, 16(a0)
|
||||
c->addiu(v1, r0, 256); // addiu v1, r0, 256
|
||||
c->andi(a2, a2, 513); // andi a2, a2, 513
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->cvtsw(f0, f0); // cvt.s.w f0, f0
|
||||
c->lbu(v1, 4, a1); // lbu v1, 4(a1)
|
||||
c->lwc1(f1, 44, a1); // lwc1 f1, 44(a1)
|
||||
c->daddiu(v1, v1, -1); // daddiu v1, v1, -1
|
||||
c->divs(f0, f0, f1); // div.s f0, f0, f1
|
||||
c->dsll(v1, v1, 2); // dsll v1, v1, 2
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->lbu(v1, 7, a1); // lbu v1, 7(a1)
|
||||
c->dsll(v1, v1, 19); // dsll v1, v1, 19
|
||||
c->lbu(a3, 5, a1); // lbu a3, 5(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll(a3, a3, 5); // dsll a3, a3, 5
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->ld(t1, 0, a0); // ld t1, 0(a0)
|
||||
c->dsll(t1, t1, 27); // dsll t1, t1, 27
|
||||
c->lbu(v1, 6, a1); // lbu v1, 6(a1)
|
||||
c->dsra32(t1, t1, 30); // dsra32 t1, t1, 30
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->dsll32(t1, t1, 3); // dsll32 t1, t1, 3
|
||||
c->lhu(a3, 10, a1); // lhu a3, 10(a1)
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lbu(v1, 26, a1); // lbu v1, 26(a1)
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->dsll(v1, v1, 14); // dsll v1, v1, 14
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lhu(v1, 0, a1); // lhu v1, 0(a1)
|
||||
c->plzcw(v1, v1); // plzcw v1, v1
|
||||
c->addiu(t0, r0, 30); // addiu t0, r0, 30
|
||||
c->subu(v1, t0, v1); // subu v1, t0, v1
|
||||
c->lhu(a3, 2, a1); // lhu a3, 2(a1)
|
||||
c->dsll(v1, v1, 26); // dsll v1, v1, 26
|
||||
c->plzcw(a3, a3); // plzcw a3, a3
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->subu(a3, t0, a3); // subu a3, t0, a3
|
||||
c->dsll(a3, a3, 30); // dsll a3, a3, 30
|
||||
c->addiu(v1, r0, 1); // addiu v1, r0, 1
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->dsll32(v1, v1, 2); // dsll32 v1, v1, 2
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lhu(v1, 24, a1); // lhu v1, 24(a1)
|
||||
c->dsll32(v1, v1, 5); // dsll32 v1, v1, 5
|
||||
c->lhu(a3, 8, a1); // lhu a3, 8(a1)
|
||||
c->dsll32(a3, a3, 19); // dsll32 a3, a3, 19
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->addiu(v1, r0, 1); // addiu v1, r0, 1
|
||||
c->dsll32(v1, v1, 29); // dsll32 v1, v1, 29
|
||||
c->cvtws(f0, f0); // cvt.w.s f0, f0
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
c->sd(t1, 0, a0); // sd t1, 0(a0)
|
||||
c->plzcw(a3, v1); // plzcw a3, v1
|
||||
c->subu(a3, t0, a3); // subu a3, t0, a3
|
||||
c->lbu(t0, 7, a1); // lbu t0, 7(a1)
|
||||
c->daddiu(t0, t0, -1); // daddiu t0, t0, -1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t0) == 0; // beq t0, r0, L22
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
c->daddiu(t0, a3, -4); // daddiu t0, a3, -4
|
||||
c->dsll(a3, a3, 4); // dsll a3, a3, 4
|
||||
c->dsrav(t0, v1, t0); // dsrav t0, v1, t0
|
||||
c->daddiu(a3, a3, -175); // daddiu a3, a3, -175
|
||||
c->andi(t0, t0, 15); // andi t0, t0, 15
|
||||
// nop // sll r0, r0, 0
|
||||
//beq r0, r0, L23 // beq r0, r0, L23
|
||||
c->daddu(a3, a3, t0); // daddu a3, a3, t0
|
||||
goto block_3; // branch always
|
||||
|
||||
|
||||
block_2:
|
||||
c->daddiu(t0, a3, -5); // daddiu t0, a3, -5
|
||||
c->dsll(a3, a3, 5); // dsll a3, a3, 5
|
||||
c->dsrav(t0, v1, t0); // dsrav t0, v1, t0
|
||||
c->daddiu(a3, a3, -350); // daddiu a3, a3, -350
|
||||
c->andi(t0, t0, 31); // andi t0, t0, 31
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddu(a3, a3, t0); // daddu a3, a3, t0
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_3:
|
||||
c->andi(a3, a3, 4095); // andi a3, a3, 4095
|
||||
c->lhu(t1, 12, a1); // lhu t1, 12(a1)
|
||||
c->dsll32(a3, a3, 0); // dsll32 a3, a3, 0
|
||||
c->lbu(v1, 27, a1); // lbu v1, 27(a1)
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->dsll(v1, v1, 14); // dsll v1, v1, 14
|
||||
c->sd(a2, 16, a0); // sd a2, 16(a0)
|
||||
c->or_(a2, t1, v1); // or a2, t1, v1
|
||||
c->lhu(v1, 14, a1); // lhu v1, 14(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(a3, 28, a1); // lbu a3, 28(a1)
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 2); // dsll32 a3, a3, 2
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 16, a1); // lhu v1, 16(a1)
|
||||
c->lbu(a3, 29, a1); // lbu a3, 29(a1)
|
||||
c->dsll32(v1, v1, 8); // dsll32 v1, v1, 8
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 22); // dsll32 a3, a3, 22
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lbu(t0, 4, a1); // lbu t0, 4(a1)
|
||||
c->daddiu(t0, t0, -5); // daddiu t0, t0, -5
|
||||
c->sd(a2, 32, a0); // sd a2, 32(a0)
|
||||
bc = ((s64)c->sgpr64(t0)) < 0; // bltz t0, L24
|
||||
c->lbu(a3, 30, a1); // lbu a3, 30(a1)
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
c->lhu(a2, 18, a1); // lhu a2, 18(a1)
|
||||
c->dsll(a3, a3, 14); // dsll a3, a3, 14
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 20, a1); // lhu v1, 20(a1)
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->lbu(a3, 31, a1); // lbu a3, 31(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 2); // dsll32 a3, a3, 2
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 22, a1); // lhu v1, 22(a1)
|
||||
c->dsll32(v1, v1, 8); // dsll32 v1, v1, 8
|
||||
c->lbu(a3, 32, a1); // lbu a3, 32(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 22); // dsll32 a3, a3, 22
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->addiu(v1, r0, 54); // addiu v1, r0, 54
|
||||
c->sd(a2, 64, a0); // sd a2, 64(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(v1, 72, a0); // sw v1, 72(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_5:
|
||||
c->mov64(v0, a0); // or v0, a0, r0
|
||||
//jr ra // jr ra
|
||||
c->daddu(sp, sp, r0); // daddu sp, sp, r0
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
gLinkedFunctionTable.reg("adgif-shader<-texture-with-update!", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace adgif_shader<_texture_with_update
|
||||
} // namespace Mips2C
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#include "common/common_types.h"
|
||||
#include "game/mips2c/mips2c_table.h"
|
||||
#include "common/util/assert.h"
|
||||
#include "common/util/BitUtils.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
|
||||
// This file contains utility functions for code generated by the mips2c pass.
|
||||
|
@ -162,6 +163,12 @@ struct ExecutionContext {
|
|||
|
||||
float Q;
|
||||
|
||||
void copy_vfs_from_other(const ExecutionContext* other) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
vfs[i] = other->vfs[i];
|
||||
}
|
||||
}
|
||||
|
||||
u128 vf_src(int idx) {
|
||||
if (idx == 0) {
|
||||
u128 result;
|
||||
|
@ -495,6 +502,9 @@ struct ExecutionContext {
|
|||
}
|
||||
|
||||
void dsra(int dst, int src, int sa) { gprs[dst].ds64[0] = gpr_src(src).ds64[0] >> sa; }
|
||||
void dsrav(int dst, int src, int sa) {
|
||||
gprs[dst].ds64[0] = gpr_src(src).ds64[0] >> gpr_src(sa).du32[0];
|
||||
}
|
||||
void dsra32(int dst, int src, int sa) { gprs[dst].ds64[0] = gpr_src(src).ds64[0] >> (32 + sa); }
|
||||
void sra(int dst, int src, int sa) { gprs[dst].ds64[0] = gpr_src(src).ds32[0] >> sa; }
|
||||
void dsll(int dst, int src0, int sa) { gprs[dst].du64[0] = gpr_src(src0).du64[0] << sa; }
|
||||
|
@ -518,7 +528,11 @@ struct ExecutionContext {
|
|||
}
|
||||
|
||||
void dsubu(int dst, int src0, int src1) { gprs[dst].du64[0] = sgpr64(src0) - sgpr64(src1); }
|
||||
void subu(int dst, int src0, int src1) {
|
||||
gprs[dst].ds64[0] = gpr_src(src0).ds32[0] - gpr_src(src1).ds32[0];
|
||||
}
|
||||
void xor_(int dst, int src0, int src1) { gprs[dst].du64[0] = sgpr64(src0) ^ sgpr64(src1); }
|
||||
void or_(int dst, int src0, int src1) { gprs[dst].du64[0] = sgpr64(src0) | sgpr64(src1); }
|
||||
|
||||
void movz(int dst, int src0, int src1) {
|
||||
if (sgpr64(src1) == 0) {
|
||||
|
@ -578,6 +592,21 @@ struct ExecutionContext {
|
|||
gprs[dst].du16[7] = s0.du16[3];
|
||||
}
|
||||
|
||||
u32 lzocw(s32 in) {
|
||||
if (in < 0) {
|
||||
in = ~in;
|
||||
}
|
||||
if (in == 0) {
|
||||
return 32;
|
||||
}
|
||||
return count_leading_zeros_u32(in);
|
||||
}
|
||||
|
||||
void plzcw(int dst, int src) {
|
||||
gprs[dst].du32[0] = lzocw(gpr_src(src).ds32[0]) - 1;
|
||||
gprs[dst].du32[1] = lzocw(gpr_src(src).ds32[1]) - 1;
|
||||
}
|
||||
|
||||
void por(int dst, int src0, int src1) {
|
||||
auto s0 = gpr_src(src0);
|
||||
auto s1 = gpr_src(src1);
|
||||
|
@ -646,6 +675,16 @@ struct ExecutionContext {
|
|||
void muls(int dst, int src0, int src1) { fprs[dst] = fprs[src0] * fprs[src1]; }
|
||||
void adds(int dst, int src0, int src1) { fprs[dst] = fprs[src0] + fprs[src1]; }
|
||||
void subs(int dst, int src0, int src1) { fprs[dst] = fprs[src0] - fprs[src1]; }
|
||||
void divs(int dst, int src0, int src1) {
|
||||
assert(fprs[src1] != 0);
|
||||
fprs[dst] = fprs[src0] / fprs[src1];
|
||||
}
|
||||
void negs(int dst, int src) {
|
||||
u32 v;
|
||||
memcpy(&v, &fprs[src], 4);
|
||||
v ^= 0x80000000;
|
||||
memcpy(&fprs[dst], &v, 4);
|
||||
}
|
||||
|
||||
void cvtws(int dst, int src) {
|
||||
// float to int
|
||||
|
@ -659,6 +698,13 @@ struct ExecutionContext {
|
|||
memcpy(&value, &fprs[src], 4);
|
||||
fprs[dst] = value;
|
||||
}
|
||||
|
||||
void vwaitq() {}
|
||||
|
||||
std::string print_vf_float(int vf) {
|
||||
auto src = vf_src(vf);
|
||||
return fmt::format("{} {} {} {}", src.f[0], src.f[1], src.f[2], src.f[3]);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Mips2C
|
|
@ -36,20 +36,60 @@ namespace sp_process_block_2d {
|
|||
extern void link();
|
||||
}
|
||||
|
||||
namespace draw_large_polygon {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace init_sky_regs {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace clip_polygon_against_positive_hyperplane {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace render_sky_quad {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace render_sky_tri {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace set_tex_offset {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace set_sky_vf27 {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace set_sky_vf23_value {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
namespace adgif_shader_texture_with_update {
|
||||
extern void link();
|
||||
}
|
||||
|
||||
LinkedFunctionTable gLinkedFunctionTable;
|
||||
Rng gRng;
|
||||
std::unordered_map<std::string, std::vector<void (*)()>> gMips2CLinkCallbacks = {
|
||||
{"font", {draw_string::link}},
|
||||
{"sparticle-launcher",
|
||||
{sp_init_fields::link, particle_adgif::link, sp_launch_particles_var::link}},
|
||||
{"sparticle", {sp_process_block_3d::link, sp_process_block_2d::link}}};
|
||||
{"sparticle", {sp_process_block_3d::link, sp_process_block_2d::link}},
|
||||
{"texture", {adgif_shader_texture_with_update::link}},
|
||||
{"sky-tng",
|
||||
{draw_large_polygon::link, init_sky_regs::link, clip_polygon_against_positive_hyperplane::link,
|
||||
render_sky_quad::link, render_sky_tri::link, set_tex_offset::link, set_sky_vf27::link,
|
||||
set_sky_vf23_value::link}}};
|
||||
|
||||
void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 stack_size) {
|
||||
const auto& it = m_executes.insert({name, {exec, Ptr<u8>()}});
|
||||
if (!it.second) {
|
||||
lg::error("MIPS2C Function {} is registered multiple times, ignoring later registrations.",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
// this is short stub that will jump to the appropriate function.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
;; Forward declarations for stuff we haven't written yet:
|
||||
(define-extern external-cam-reset! (function none))
|
||||
(define-extern time-of-day-setup (function symbol none))
|
||||
(define-extern time-of-day-setup (function symbol symbol))
|
||||
(define-extern *compact-actors* symbol)
|
||||
(define-extern find-instance-by-name (function string instance))
|
||||
(define-extern *edit-instance* string)
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
(deftype dma-gif-packet (structure)
|
||||
((dma-vif dma-packet :inline :offset-assert 0)
|
||||
(gif uint64 2 :offset-assert 16) ;; guess
|
||||
;; these two were added to make it easier.
|
||||
(gif0 uint64 :offset 16)
|
||||
(gif1 uint64 :offset 24)
|
||||
|
||||
(quad uint128 2 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
|
|
|
@ -234,8 +234,10 @@
|
|||
|
||||
(generic-foreground 30) ;; ?
|
||||
(alpha-tex0 31)
|
||||
(sky-tex0 32)
|
||||
|
||||
(alpha-tex1 38)
|
||||
(sky-tex1 39)
|
||||
|
||||
(bucket-45 45)
|
||||
(bucket-46 46)
|
||||
|
|
|
@ -127,9 +127,21 @@
|
|||
)
|
||||
)
|
||||
|
||||
;; texture common
|
||||
;; sky
|
||||
;; todo - disabled sky
|
||||
(when (logtest? *vu1-enable-user* 8)
|
||||
(cond
|
||||
((and (-> *time-of-day-context* sky) *sky-drawn*)
|
||||
(render-sky-tng *time-of-day-context*)
|
||||
)
|
||||
(else
|
||||
;; todo
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; tod update
|
||||
(update-time-of-day *time-of-day-context*)
|
||||
;; closest
|
||||
;; ocean
|
||||
;; merc
|
||||
|
|
|
@ -789,7 +789,7 @@
|
|||
|
||||
;; some nice blue. probably the same as the fog color for geyser/sandover/etc.
|
||||
;; "default" fog color when resetting registers
|
||||
(define *fog-color* #xc88029)
|
||||
(define *fog-color* (the-as rgba (new 'static 'rgba :r #x29 :g #x80 :b #xc8)))
|
||||
|
||||
;; set up a DMA buffer. This will hold a message to set the GS state to normal.
|
||||
;; these regs are NOT the ones mapped in the EE memory, but other internal GS registers.
|
||||
|
|
|
@ -126,9 +126,9 @@
|
|||
)
|
||||
|
||||
(deftype sky-tng-data (basic)
|
||||
((giftag-base qword :inline :offset-assert 16)
|
||||
(giftag-roof qword :inline :offset-assert 32)
|
||||
(giftag-ocean qword :inline :offset-assert 48)
|
||||
((giftag-base gs-gif-tag :inline :offset-assert 16);; changed
|
||||
(giftag-roof gs-gif-tag :inline :offset-assert 32)
|
||||
(giftag-ocean gs-gif-tag :inline :offset-assert 48)
|
||||
(fog vector :inline :offset-assert 64)
|
||||
(sky uint32 8 :offset-assert 80)
|
||||
(time float :offset-assert 112)
|
||||
|
@ -146,8 +146,8 @@
|
|||
((adgif-tmpl dma-gif-packet :inline :offset-assert 0)
|
||||
(draw-tmpl dma-gif-packet :inline :offset-assert 32)
|
||||
(blend-tmpl dma-gif-packet :inline :offset-assert 64)
|
||||
(sky-data uint128 5 :offset-assert 96)
|
||||
(cloud-data uint128 5 :offset-assert 176)
|
||||
(sky-data qword 5 :inline :offset-assert 96)
|
||||
(cloud-data qword 5 :inline :offset-assert 176)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x100
|
||||
|
@ -166,3 +166,9 @@
|
|||
|
||||
(define *sky-drawn* #f)
|
||||
(define *cloud-drawn* #f)
|
||||
|
||||
|
||||
(declare-type time-of-day-context basic)
|
||||
(define-extern update-sky-tng-data (function float none))
|
||||
(define-extern make-sky-textures (function time-of-day-context int none))
|
||||
(define-extern sky-base-polygons (inline-array sky-vertex))
|
File diff suppressed because it is too large
Load diff
|
@ -5,3 +5,138 @@
|
|||
;; name in dgo: sky
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(defun sky-make-sun-data ((arg0 sky-parms) (arg1 int) (arg2 float))
|
||||
"Make sun data for the arg1th sun at arg2 time"
|
||||
(let* ((s4-0 (-> arg0 orbit arg1))
|
||||
(s3-0 (-> arg0 upload-data sun arg1))
|
||||
(f0-1 (- arg2 (-> s4-0 high-noon)))
|
||||
(f30-0 (* 2730.6667 f0-1))
|
||||
(f28-0 (* (sin f30-0) (-> s4-0 dist)))
|
||||
(f30-1 (cos f30-0))
|
||||
)
|
||||
(let* ((f24-0 (* f30-1 (-> s4-0 dist)))
|
||||
(f26-0 (* f24-0 (cos-rad (-> s4-0 tilt))))
|
||||
(f24-1 (* f24-0 (sin-rad (-> s4-0 tilt))))
|
||||
(f22-0 (sin-rad (-> s4-0 rise)))
|
||||
(f0-10 (cos-rad (-> s4-0 rise)))
|
||||
)
|
||||
(set! (-> s3-0 pos z) (- (+ (* f28-0 f0-10) (* f24-1 f22-0))))
|
||||
(set! (-> s3-0 pos y) f26-0)
|
||||
(set! (-> s3-0 pos x) (- (* f24-1 f0-10) (* f28-0 f22-0)))
|
||||
)
|
||||
(let ((f0-14 (if (< f30-1 0.0)
|
||||
0.0
|
||||
f30-1
|
||||
)
|
||||
)
|
||||
)
|
||||
(set!
|
||||
(-> arg0 upload-data sun arg1 r-aurora)
|
||||
(+ (* (-> s4-0 min-halo) (- 1.0 f0-14)) (* (-> s4-0 max-halo) f0-14))
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun sky-make-moon-data ((arg0 sky-parms) (arg1 float))
|
||||
"Make moon data for moon at arg1 time"
|
||||
(let* ((s5-0 (-> arg0 orbit 2))
|
||||
(gp-0 (-> arg0 upload-data moon))
|
||||
(f0-1 (- arg1 (-> s5-0 high-noon)))
|
||||
(f28-0 (* 2730.6667 f0-1))
|
||||
(f30-0 (* (sin f28-0) (-> s5-0 dist)))
|
||||
(f26-0 (* (cos f28-0) (-> s5-0 dist)))
|
||||
(f28-1 (* f26-0 (cos-rad (-> s5-0 tilt))))
|
||||
(f26-1 (* f26-0 (sin-rad (-> s5-0 tilt))))
|
||||
(f24-0 (sin-rad (-> s5-0 rise)))
|
||||
(f0-10 (cos-rad (-> s5-0 rise)))
|
||||
)
|
||||
(set! (-> gp-0 pos z) (- (+ (* f30-0 f0-10) (* f26-1 f24-0))))
|
||||
(set! (-> gp-0 pos y) f28-1)
|
||||
(set! (-> gp-0 pos x) (- (* f26-1 f0-10) (* f30-0 f24-0)))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Old Sky Renderer
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defun sky-make-light ((arg0 sky-parms) (arg1 light) (arg2 int) (arg3 rgba))
|
||||
(let* ((v1-2 (-> arg0 orbit arg2))
|
||||
(a0-1 (if (= arg2 2)
|
||||
(-> arg0 upload-data moon)
|
||||
(-> arg0 upload-data sun arg2)
|
||||
)
|
||||
)
|
||||
(f0-0 0.003921569)
|
||||
(f1-1 (/ 1.0 (-> v1-2 dist)))
|
||||
(v1-3 arg1)
|
||||
)
|
||||
(set! (-> v1-3 direction x) (* (-> (the-as sky-sun-data a0-1) pos x) f1-1))
|
||||
(set! (-> v1-3 direction y) (* (-> (the-as sky-sun-data a0-1) pos y) f1-1))
|
||||
(set! (-> v1-3 direction z) (* (-> (the-as sky-sun-data a0-1) pos z) f1-1))
|
||||
(set! (-> v1-3 color x) (* (the float (-> arg3 r)) f0-0))
|
||||
(set! (-> v1-3 color y) (* (the float (-> arg3 g)) f0-0))
|
||||
(set! (-> v1-3 color z) (* (the float (-> arg3 b)) f0-0))
|
||||
(set! (-> v1-3 color w) 1.0)
|
||||
(set! (-> v1-3 levels x) 1.0)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
(deftype sky-frame-data (structure)
|
||||
((data uint128 18 :offset-assert 0)
|
||||
(world-homo-matrix matrix :inline :offset 0)
|
||||
(hmge-scale vector :inline :offset 64)
|
||||
(hvdf-offset vector :inline :offset 80)
|
||||
(consts vector :inline :offset 96)
|
||||
(pfog0 float :offset 96)
|
||||
(radius float :offset 100)
|
||||
(nokick float :offset 108)
|
||||
(strip-giftag qword :inline :offset 112)
|
||||
(col-adgif qword :inline :offset 128)
|
||||
(save uint128 5 :offset 144)
|
||||
(sun-fan-giftag qword :inline :offset 224)
|
||||
(sun-strip-giftag qword :inline :offset 240)
|
||||
(sun-alpha qword :inline :offset 256)
|
||||
(sun-alpha-giftag qword :inline :offset 272)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x120
|
||||
:flag-assert #x900000120
|
||||
)
|
||||
|
||||
;; skipping old sky stuff (for now)
|
||||
(define sky-vu1-block (new 'static 'vu-function))
|
||||
|
||||
;; TODO sky-init-upload-data
|
||||
;; sky-add-frame-data
|
||||
;; sky-upload
|
||||
;; sky-draw
|
||||
|
||||
|
||||
;; set the suns
|
||||
(sky-set-sun-radii *sky-parms* 0 60.0 200.0 300.0)
|
||||
(sky-set-sun-radii *sky-parms* 1 15.0 20.0 300.0)
|
||||
|
||||
|
||||
(sky-set-sun-colors *sky-parms* 1
|
||||
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x80)
|
||||
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x80)
|
||||
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x20)
|
||||
(new 'static 'rgba :r #xc2 :g #xfe :b #x78)
|
||||
)
|
||||
|
||||
|
||||
(sky-set-orbit *sky-parms* 0 12.5 -15.0 0.0 9950.0 300.0 300.0)
|
||||
(sky-set-orbit *sky-parms* 1 4.0 0.0 60.0 9950.0 120.0 120.0)
|
||||
(sky-set-orbit *sky-parms* 2 0.0 0.0 -10.0 9950.0 0.0 0.0)
|
|
@ -645,17 +645,22 @@
|
|||
)
|
||||
)
|
||||
|
||||
; (dotimes (i num-sprites)
|
||||
; (let ((spidx (+ i start-sprite-idx)))
|
||||
; (when (or (= spidx (-> sprites num-sprites 0)) (= spidx (+ 1 (-> sprites num-sprites 0))))
|
||||
; (let ((data (the sprite-vec-data-2d (&+ (-> sprites vec-data) (* 48 (+ i start-sprite-idx))))))
|
||||
; (format #t "spidx: ~d~%")
|
||||
; (inspect data)
|
||||
; (inspect (-> data r-g-b-a))
|
||||
; )
|
||||
; )
|
||||
; )
|
||||
; )
|
||||
#|
|
||||
;(when (= mscal-addr 3)
|
||||
(dotimes (i num-sprites)
|
||||
(let ((spidx (+ i start-sprite-idx)))
|
||||
;(when (or (= spidx (-> sprites num-sprites 0)) (= spidx (+ 1 (-> sprites num-sprites 0))))
|
||||
(let ((data (the sprite-vec-data-2d (&+ (-> sprites vec-data) (* 48 (+ i start-sprite-idx))))))
|
||||
(let ((vec (-> data x-y-z-sx)))
|
||||
(format 0 "sp: ~d ~f ~f ~f~%" (+ i start-sprite-idx) (-> vec x) (-> vec y) (-> vec z))
|
||||
)
|
||||
)
|
||||
; )
|
||||
)
|
||||
)
|
||||
; )
|
||||
|#
|
||||
|
||||
|
||||
;; third packet is adgif data (5 qw/sprite)
|
||||
(let ((qwc-pkt3 (* 5 num-sprites)))
|
||||
|
|
|
@ -2435,6 +2435,7 @@
|
|||
)
|
||||
|
||||
;; TODO adgif-shader<-texture-with-update!
|
||||
(def-mips2c adgif-shader<-texture-with-update! (function adgif-shader texture adgif-shader))
|
||||
|
||||
(defun adgif-shader-login ((shader adgif-shader))
|
||||
"If not logged in already, link us and update from texture."
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
:flag-assert #xb00000110
|
||||
(:methods
|
||||
(reset! (_type_) symbol 9)
|
||||
(TODO-RENAME-10 (_type_ int float float vector) object 10) ; returns float or error string
|
||||
(set-fade! (_type_ int float float vector) object 10) ; returns float or error string
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
|||
((active-count uint32 :offset-assert 4)
|
||||
(interp float :offset-assert 8)
|
||||
(current-interp float :offset-assert 12)
|
||||
(moods uint64 2 :offset-assert 16)
|
||||
(moods mood-context 2 :offset-assert 16)
|
||||
(current-fog mood-fog :inline :offset-assert 32)
|
||||
(current-sun mood-sun :inline :offset-assert 80)
|
||||
(current-prt-color vector :inline :offset-assert 112)
|
||||
|
@ -84,7 +84,7 @@
|
|||
(title-light-group light-group :inline :offset-assert 1888)
|
||||
(time float :offset-assert 2080)
|
||||
(target-interp float :offset-assert 2084)
|
||||
(erase-color uint32 :offset-assert 2088)
|
||||
(erase-color rgba :offset-assert 2088)
|
||||
(num-stars float :offset-assert 2092)
|
||||
(light-masks-0 uint8 2 :offset-assert 2096)
|
||||
(light-masks-1 uint8 2 :offset-assert 2098)
|
||||
|
|
|
@ -5,4 +5,671 @@
|
|||
;; name in dgo: time-of-day
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(define *time-of-day-proc* (the (pointer time-of-day-proc) #f))
|
||||
(defmethod asize-of time-of-day-palette ((obj time-of-day-palette))
|
||||
"Compute the size in memory of a time-of-day-palette"
|
||||
(the-as int (+ (-> obj type size) (* (* (-> obj height) (-> obj width)) 4)))
|
||||
)
|
||||
|
||||
;; The time-of-day-effect function is a callback used before doing a time-of-day-update.
|
||||
;; I think it's unused?
|
||||
(define-extern time-of-day-effect (function none))
|
||||
;; if undefined, set to nothing so we can still call it.
|
||||
(if (zero? time-of-day-effect)
|
||||
(set! time-of-day-effect nothing)
|
||||
)
|
||||
|
||||
(defbehavior time-of-day-update time-of-day-proc ()
|
||||
"Update the particles and sky tng renderer for time-of-day effects"
|
||||
(time-of-day-effect)
|
||||
|
||||
;; spawn or kill stars, if needed.
|
||||
(cond
|
||||
;; should have stars in the sky
|
||||
((and (or (>= (-> self hour) 19) (>= 5 (-> self hour))) ;; night time
|
||||
(and (< 45.0 (-> *time-of-day-context* num-stars)) (-> *time-of-day-context* sky)) ;; sky + stars desired
|
||||
)
|
||||
|
||||
;; see if we need more
|
||||
(when (and *dproc* (< (-> self star-count) (the int (-> *time-of-day-context* num-stars))))
|
||||
(spawn (-> self stars) (math-camera-pos))
|
||||
(+! (-> self star-count) 1)
|
||||
)
|
||||
)
|
||||
|
||||
;; have stars, but don't want them
|
||||
((> (-> self star-count) 0)
|
||||
;; kill all stars.
|
||||
(forall-particles-with-key
|
||||
(-> self stars)
|
||||
(lambda ((arg0 sparticle-system) (arg1 sparticle-cpuinfo))
|
||||
(if (< (the-as uint #x493e0) (-> arg1 next-time))
|
||||
(set! (-> arg1 next-time) (the-as uint 5))
|
||||
(sparticle-kill-it arg0 arg1)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
#t
|
||||
#t
|
||||
)
|
||||
(set! (-> self star-count) 0)
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
;; spawn or kill sun, if needed
|
||||
(cond
|
||||
((and (>= (-> self time-of-day) 6.25)
|
||||
(< (-> self time-of-day) 18.75)
|
||||
(!= (-> *time-of-day-context* sun-fade) 0.0)
|
||||
)
|
||||
(when (and *dproc* (zero? (-> self sun-count)))
|
||||
(spawn (-> self sun) (math-camera-pos))
|
||||
(+! (-> self sun-count) 1)
|
||||
)
|
||||
)
|
||||
((> (-> self sun-count) 0)
|
||||
(kill-and-free-particles (-> self sun))
|
||||
(set! (-> self sun-count) 0)
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
;; spawn or kill green sun, if needed
|
||||
(cond
|
||||
((and (or (>= (-> self time-of-day) 21.75) (>= 10.25 (-> self time-of-day)))
|
||||
(!= (-> *time-of-day-context* sun-fade) 0.0)
|
||||
)
|
||||
(when (and *dproc* (zero? (-> self green-sun-count)))
|
||||
(spawn (-> self green-sun) (math-camera-pos))
|
||||
(+! (-> self green-sun-count) 1)
|
||||
)
|
||||
)
|
||||
((> (-> self green-sun-count) 0)
|
||||
(kill-and-free-particles (-> self green-sun))
|
||||
(set! (-> self green-sun-count) 0)
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
;; update the sky renderer.
|
||||
(update-sky-tng-data (-> self time-of-day))
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
;; State for just ticking time forward.
|
||||
(defstate time-of-day-tick (time-of-day-proc)
|
||||
:code
|
||||
(behavior ()
|
||||
(while #t
|
||||
;; tick!
|
||||
(+! (-> self frame) (the int (* (-> self time-ratio) (-> *display* time-adjust-ratio))))
|
||||
|
||||
;; now update time...
|
||||
(when (>= (-> self frame) 300)
|
||||
;; 300 ticks/second
|
||||
(while (>= (-> self frame) 300)
|
||||
(+! (-> self frame) -300)
|
||||
(+! (-> self second) 1)
|
||||
)
|
||||
;; 60 sec/minute
|
||||
(when (>= (-> self second) 60)
|
||||
(while (>= (-> self second) 60)
|
||||
(+! (-> self second) -60)
|
||||
(+! (-> self minute) 1)
|
||||
)
|
||||
;; 60 min/hour
|
||||
(when (>= (-> self minute) 60)
|
||||
(while (>= (-> self minute) 60)
|
||||
(+! (-> self minute) -60)
|
||||
(+! (-> self hour) 1)
|
||||
)
|
||||
;; 24 hour/day
|
||||
(when (>= (-> self hour) 24)
|
||||
(while (>= (-> self hour) 24)
|
||||
(+! (-> self hour) -24)
|
||||
(+! (-> self day) 1)
|
||||
)
|
||||
;; 7 day/week
|
||||
(when (>= (-> self day) 7)
|
||||
(while (>= (-> self day) 7)
|
||||
(+! (-> self day) -7)
|
||||
(+! (-> self week) 1)
|
||||
)
|
||||
;; 4 week/month
|
||||
(when (>= (-> self week) 4)
|
||||
(while (>= (-> self week) 4)
|
||||
(+! (-> self week) -4)
|
||||
(+! (-> self month) 1)
|
||||
)
|
||||
;; 12 month/year
|
||||
(when (>= (-> self month) 12)
|
||||
(while (>= (-> self month) 12)
|
||||
(+! (-> self month) -12)
|
||||
(+! (-> self year) 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; set the time of day float. This is in hours (0-24)
|
||||
(format *stdcon* "~0kstars: ~d time ~d:~2d~%" (-> self star-count) (-> self hour) (-> self minute))
|
||||
(let* ((f0-4 (the float (-> self frame)))
|
||||
(f0-6 (+ (* 0.0033333334 f0-4) (the float (-> self second))))
|
||||
(f0-8 (+ (* 0.016666668 f0-6) (the float (-> self minute))))
|
||||
(f0-10 (+ (* 0.016666668 f0-8) (the float (-> self hour))))
|
||||
)
|
||||
(set! (-> self time-of-day) f0-10)
|
||||
(set! (-> *time-of-day-context* time) f0-10)
|
||||
)
|
||||
(suspend)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
:post time-of-day-update
|
||||
)
|
||||
|
||||
(defbehavior init-time-of-day time-of-day-proc ()
|
||||
"Initialize the time-of-day process"
|
||||
(stack-size-set! (-> self main-thread) 128)
|
||||
(set! (-> self year) 0)
|
||||
(set! (-> self month) 0)
|
||||
(set! (-> self week) 0)
|
||||
(set! (-> self day) 0)
|
||||
(set! (-> self hour) 0)
|
||||
(set! (-> self minute) 0)
|
||||
(set! (-> self second) 0)
|
||||
(set! (-> self frame) 0)
|
||||
(set! (-> self time-of-day) 0.0)
|
||||
(if *time-of-day-fast*
|
||||
(set! (-> self time-ratio) 18000.0)
|
||||
(set! (-> self time-ratio) 300.0)
|
||||
)
|
||||
(set! (-> self star-count) 0)
|
||||
(set! (-> self stars) (create-launch-control (-> *part-group-id-table* 34) self))
|
||||
(set! (-> self sun) (create-launch-control (-> *part-group-id-table* 35) self))
|
||||
(set! (-> self green-sun) (create-launch-control (-> *part-group-id-table* 36) self))
|
||||
(go time-of-day-tick)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun start-time-of-day ()
|
||||
"Start up the time of day process. Kill any existing ones"
|
||||
(kill-by-name 'time-of-day-proc *active-pool*)
|
||||
(let ((gp-0 (get-process *default-dead-pool* time-of-day-proc #x4000)))
|
||||
(set! *time-of-day-proc*
|
||||
(the-as (pointer time-of-day-proc)
|
||||
(when gp-0
|
||||
(let ((t9-2 (method-of-type time-of-day-proc activate)))
|
||||
(t9-2 (the-as time-of-day-proc gp-0) *default-pool* 'time-of-day-proc (the-as pointer #x70004000))
|
||||
)
|
||||
(run-now-in-process gp-0 init-time-of-day)
|
||||
(-> gp-0 ppointer )
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun time-of-day-setup ((arg0 symbol))
|
||||
"This function is weird. Returns if time of day will tick forward or not.
|
||||
If you set arg0 it will toggle on/off time of day.
|
||||
Otherwise, calling the function has no side effects."
|
||||
(when arg0
|
||||
(cond
|
||||
((= (-> *time-of-day-proc* 0 time-ratio) 0.0)
|
||||
(if *time-of-day-fast*
|
||||
(set! (-> *time-of-day-proc* 0 time-ratio) 18000.0)
|
||||
(set! (-> *time-of-day-proc* 0 time-ratio) 300.0)
|
||||
)
|
||||
(set! *time-of-day-mode* 8)
|
||||
)
|
||||
(else
|
||||
(set! (-> *time-of-day-proc* 0 time-ratio) 0.0)
|
||||
(set! *time-of-day-mode* 4)
|
||||
(set! (-> *time-of-day-proc* 0 hour) 12)
|
||||
(set! (-> *time-of-day-proc* 0 minute) 0)
|
||||
0
|
||||
)
|
||||
)
|
||||
)
|
||||
(if (= (-> *time-of-day-proc* 0 time-ratio) 0.0)
|
||||
#f
|
||||
#t
|
||||
)
|
||||
)
|
||||
|
||||
(defun set-time-of-day ((arg0 float))
|
||||
"Manually set the time of day."
|
||||
(let ((v1-0 *time-of-day-proc*))
|
||||
(set! (-> v1-0 0 hour) (the int arg0))
|
||||
(let ((a0-1 (* 60.0 (- arg0 (the float (the int arg0))))))
|
||||
(set! (-> v1-0 0 minute) (the int a0-1))
|
||||
(set! (-> v1-0 0 second) (the int (* 60.0 (- a0-1 (the float (the int a0-1))))))
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; TODO time-of-day-interp-colors
|
||||
;; TODO time-of-day-interp-colors-scratch
|
||||
|
||||
|
||||
(defun init-time-of-day-context ((arg0 time-of-day-context))
|
||||
"Set up the title-light-group."
|
||||
(set-vector! (-> arg0 title-light-group dir0 color) 0.82 0.82 0.82 1.0)
|
||||
(set-vector! (-> arg0 title-light-group dir1 color) 2.0 2.0 2.0 1.0)
|
||||
(set-vector! (-> arg0 title-light-group ambi color) 0.5 0.5 0.5 1.0)
|
||||
(set! (-> arg0 title-light-group dir0 levels x) 1.0)
|
||||
(set! (-> arg0 title-light-group dir1 levels x) 1.0)
|
||||
(let ((f0-14 1.0))
|
||||
(set! (-> arg0 title-light-group ambi levels x) f0-14)
|
||||
f0-14
|
||||
)
|
||||
)
|
||||
|
||||
(defun update-time-of-day ((arg0 time-of-day-context))
|
||||
"Update the time of day context"
|
||||
|
||||
;; set defaults
|
||||
(set! (-> arg0 sky) #f)
|
||||
(set! (-> arg0 target-interp) 0.0)
|
||||
;; TODO re-enable
|
||||
#|
|
||||
(when *target*
|
||||
(set! (-> *target* draw light-index) (the-as uint 0))
|
||||
(when (-> *target* sidekick)
|
||||
(set! (-> *target* sidekick 0 draw light-index) (the-as uint 0))
|
||||
0
|
||||
)
|
||||
)
|
||||
|#
|
||||
|
||||
;; see if either level gives us a sky.
|
||||
(dotimes (v1-12 (-> *level* length))
|
||||
(let ((a0-4 (-> *level* level v1-12)))
|
||||
(when (= (-> a0-4 status) 'active)
|
||||
(if (-> a0-4 info sky)
|
||||
(set! (-> arg0 sky) #t)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; level distances
|
||||
(let ((s4-0 (new 'stack-no-clear 'array 'float 2))) ;; was a boxed array, but the GOAL implementation seems buggy.
|
||||
(set! (-> s4-0 0) 0.0)
|
||||
(set! (-> s4-0 1) 0.0)
|
||||
0.0
|
||||
|
||||
(let ((s5-0 0)
|
||||
(f30-0 (-> arg0 current-interp))
|
||||
)
|
||||
(set! *lightning-frame-done* #f)
|
||||
(set! *lightning-realtime-done* #f)
|
||||
|
||||
;; loop over levels and figure out which to use.
|
||||
(dotimes (s3-0 2)
|
||||
(let ((s2-0 (-> *level* level s3-0)))
|
||||
(cond
|
||||
((!= (-> s2-0 status) 'inactive)
|
||||
;; level is good, use its mood
|
||||
(set! (-> s4-0 s3-0) (-> s2-0 level-distance))
|
||||
(set! (-> arg0 moods s3-0) (-> s2-0 mood))
|
||||
;; run its mood callback
|
||||
((-> s2-0 mood-func) (-> s2-0 mood) (-> arg0 time) s3-0)
|
||||
;; sky count
|
||||
(if (and (= (-> s2-0 status) 'active) (-> s2-0 info sky))
|
||||
(+! s5-0 1)
|
||||
)
|
||||
)
|
||||
(else
|
||||
;; level is no good. Use the default mood in its place.
|
||||
(set! (-> s4-0 s3-0) 4095996000.0)
|
||||
(set! (-> arg0 moods s3-0) *default-mood*)
|
||||
(update-mood-default *default-mood* (-> arg0 time) 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; now pick desired interpolation weights
|
||||
(let* ((f0-6 (-> s4-0 0))
|
||||
(f1-0 (-> s4-0 1))
|
||||
(f28-0 (cond
|
||||
((= f1-0 4095996000.0)
|
||||
;; second level is no good, just use first
|
||||
0.0
|
||||
)
|
||||
((= f0-6 4095996000.0)
|
||||
;; first level is no good, just use second.
|
||||
1.0
|
||||
)
|
||||
((= f0-6 f1-0)
|
||||
;; not sure why this is special cased...
|
||||
0.5
|
||||
)
|
||||
;; this is a hack to pick the mood of village2 when we're closer to sunken, as long as
|
||||
;; the camera is above 0.
|
||||
((and (< 0.0 (-> *math-camera* trans y))
|
||||
(= (-> *level* level0 name) 'village2)
|
||||
(= (-> *level* level1 name) 'sunken)
|
||||
)
|
||||
0.0 ;; picks 0 = village2
|
||||
)
|
||||
((and (< 0.0 (-> *math-camera* trans y))
|
||||
(= (-> *level* level0 name) 'sunken)
|
||||
(= (-> *level* level1 name) 'village2)
|
||||
)
|
||||
1.0 ;; picks 1 = village 2
|
||||
)
|
||||
(else
|
||||
;; interplate between them.
|
||||
(/ f0-6 (+ f0-6 f1-0))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; normally we will slowly ramp the interpolation weights.
|
||||
;; but if we've just teleported, immediately snap to the new value.
|
||||
(if *teleport*
|
||||
(set! f30-0 f28-0)
|
||||
)
|
||||
|
||||
;; ramp interpolation weights.
|
||||
(when (not (or (paused?) (= f28-0 f30-0)))
|
||||
(let ((f0-7 (- f30-0 f28-0)))
|
||||
(set! f30-0 (cond
|
||||
((= (-> *setting-control* current video-mode) 'pal)
|
||||
(cond
|
||||
((< (fabs f0-7) 0.00396)
|
||||
;; close enough
|
||||
f28-0
|
||||
)
|
||||
((< f0-7 0.0)
|
||||
;; ramp up
|
||||
(+ 0.00396 f30-0)
|
||||
)
|
||||
(else
|
||||
;; ramp down
|
||||
(+ -0.00396 f30-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
((< (fabs f0-7) 0.0033)
|
||||
;; close enough
|
||||
f28-0
|
||||
)
|
||||
((< f0-7 0.0)
|
||||
;; ramp up
|
||||
(+ 0.0033 f30-0)
|
||||
)
|
||||
(else
|
||||
;; ramp down.
|
||||
(+ -0.0033 f30-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; number of active skys
|
||||
(set! (-> arg0 active-count) (the-as uint s5-0))
|
||||
;; interpolation value between the two level moods.
|
||||
(set! (-> arg0 interp) f28-0)
|
||||
)
|
||||
|
||||
;; Do the interpolation
|
||||
(set! (-> arg0 current-interp) f30-0)
|
||||
(set! *sky-drawn* #f)
|
||||
(set! *cloud-drawn* #f)
|
||||
(let ((s5-1 (-> arg0 current-fog)))
|
||||
(cond
|
||||
((= f30-0 0.0)
|
||||
;; special case: only use level 0
|
||||
(let ((v1-67 (-> arg0 moods 0 current-fog)))
|
||||
(set! (-> s5-1 fog-color quad) (-> v1-67 fog-color quad))
|
||||
(set! (-> s5-1 fog-dists quad) (-> v1-67 fog-dists quad))
|
||||
(set! (-> s5-1 erase-color quad) (-> v1-67 erase-color quad))
|
||||
)
|
||||
(set! (-> arg0 current-prt-color quad) (-> arg0 moods 0 current-prt-color quad))
|
||||
(set! (-> arg0 current-sun sun-color quad) (-> arg0 moods 0 current-sun sun-color quad))
|
||||
(set! (-> arg0 current-sun env-color quad) (-> arg0 moods 0 current-sun env-color quad))
|
||||
(set! (-> arg0 current-shadow quad) (-> arg0 moods 0 current-shadow quad))
|
||||
(set! (-> arg0 current-shadow-color quad) (-> arg0 moods 0 current-shadow-color quad))
|
||||
(dotimes (s4-1 8)
|
||||
(quad-copy! (the-as pointer (-> arg0 light-group s4-1)) (the-as pointer (-> arg0 moods 0 light-group s4-1)) 12)
|
||||
)
|
||||
(set! (-> arg0 num-stars) (-> arg0 moods 0 num-stars))
|
||||
(set! (-> arg0 sun-fade) (-> *level* level0 info sun-fade))
|
||||
)
|
||||
((= f30-0 1.0)
|
||||
;; special case: use only level 1
|
||||
(let ((v1-88 (-> arg0 moods 1 current-fog)))
|
||||
(set! (-> s5-1 fog-color quad) (-> v1-88 fog-color quad))
|
||||
(set! (-> s5-1 fog-dists quad) (-> v1-88 fog-dists quad))
|
||||
(set! (-> s5-1 erase-color quad) (-> v1-88 erase-color quad))
|
||||
)
|
||||
(set! (-> arg0 current-prt-color quad) (-> arg0 moods 1 current-prt-color quad))
|
||||
(set! (-> arg0 current-sun sun-color quad) (-> arg0 moods 1 current-sun sun-color quad))
|
||||
(set! (-> arg0 current-sun env-color quad) (-> arg0 moods 1 current-sun env-color quad))
|
||||
(set! (-> arg0 current-shadow quad) (-> arg0 moods 1 current-shadow quad))
|
||||
(set! (-> arg0 current-shadow-color quad) (-> arg0 moods 1 current-shadow-color quad))
|
||||
(dotimes (s4-2 8)
|
||||
(quad-copy! (the-as pointer (-> arg0 light-group s4-2)) (the-as pointer (-> arg0 moods 1 light-group s4-2)) 12)
|
||||
)
|
||||
(set! (-> arg0 num-stars) (-> arg0 moods 1 num-stars))
|
||||
(set! (-> arg0 sun-fade) (-> *level* level1 info sun-fade))
|
||||
)
|
||||
(else
|
||||
;; interpolate!
|
||||
;; note: the array access here seems to be different from everywhere else and I suspect there was some
|
||||
;; weird pointer math in the original code.
|
||||
(let ((s4-3 (-> arg0 moods 0 current-fog))
|
||||
(s3-1 (-> arg0 moods 1 current-fog))
|
||||
)
|
||||
(vector4-lerp! (-> s5-1 fog-color) (-> s4-3 fog-color) (-> s3-1 fog-color) f30-0)
|
||||
(vector4-lerp! (-> s5-1 fog-dists) (-> s4-3 fog-dists) (-> s3-1 fog-dists) f30-0)
|
||||
(vector4-lerp! (-> s5-1 erase-color) (-> s4-3 erase-color) (-> s3-1 erase-color) f30-0)
|
||||
)
|
||||
(vector4-lerp! (-> arg0 current-prt-color) (-> arg0 moods 0 current-prt-color) (-> arg0 moods 1 current-prt-color) f30-0)
|
||||
(vector4-lerp!
|
||||
(the-as vector (-> arg0 current-sun))
|
||||
(the-as vector (-> arg0 moods 0 current-sun))
|
||||
(the-as vector (-> arg0 moods 1 current-sun))
|
||||
f30-0
|
||||
)
|
||||
(vector4-lerp! (-> arg0 current-sun env-color) (-> arg0 moods 0 current-sun env-color) (-> arg0 moods 1 current-sun env-color) f30-0)
|
||||
(vector4-lerp! (-> arg0 current-shadow) (-> arg0 moods 0 current-shadow) (-> arg0 moods 1 current-shadow) f30-0)
|
||||
(vector4-lerp! (-> arg0 current-shadow-color) (-> arg0 moods 0 current-shadow-color) (-> arg0 moods 1 current-shadow-color) f30-0)
|
||||
(dotimes (s4-4 8)
|
||||
(dotimes (s3-2 3)
|
||||
(let ((s2-1 (+ (+ (* 48 s3-2) 156 (* 192 s4-4)) (the-as int arg0))))
|
||||
(let ((s1-0 (+ (+ (* 48 s3-2) 156 (* 192 s4-4)) (the-as int (-> arg0 moods 0))) )
|
||||
(s0-0 (+ (+ (* 48 s3-2) 156 (* 192 s4-4)) (the-as int (-> arg0 moods 1))) )
|
||||
)
|
||||
(vector4-lerp! (the-as vector (+ s2-1 0)) (the-as vector (+ s1-0 0)) (the-as vector (+ s0-0 0)) f30-0)
|
||||
(vector4-lerp! (the-as vector (+ s2-1 16)) (the-as vector (+ s1-0 16)) (the-as vector (+ s0-0 16)) f30-0)
|
||||
(vector4-lerp! (the-as vector (+ s2-1 32)) (the-as vector (+ s1-0 32)) (the-as vector (+ s0-0 32)) f30-0)
|
||||
)
|
||||
(vector-normalize! (the-as vector (+ s2-1 0)) 1.0)
|
||||
)
|
||||
)
|
||||
(let ((s3-3 (+ (the-as uint (-> arg0 light-group 0 ambi)) (* 192 s4-4)))
|
||||
(s2-2 (+ (the-as uint (-> arg0 moods 0 light-group 0 ambi)) (* 192 s4-4)))
|
||||
(s1-1 (+ (the-as uint (-> arg0 moods 1 light-group 0 ambi)) (* 192 s4-4)))
|
||||
)
|
||||
(vector4-lerp! (the-as vector (+ s3-3 0)) (the-as vector (+ s2-2 0)) (the-as vector (+ s1-1 0)) f30-0)
|
||||
(vector4-lerp! (the-as vector (+ s3-3 16)) (the-as vector (+ s2-2 16)) (the-as vector (+ s1-1 16)) f30-0)
|
||||
(vector4-lerp! (the-as vector (+ s3-3 32)) (the-as vector (+ s2-2 32)) (the-as vector (+ s1-1 32)) f30-0)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 num-stars) (+ (-> arg0 moods 0 num-stars) (* (- (-> arg0 moods 1 num-stars) (-> arg0 moods 0 num-stars)) f30-0)))
|
||||
(let ((f0-20 (-> *level* level0 info sun-fade)))
|
||||
(set! (-> arg0 sun-fade) (+ f0-20 (* f30-0 (- (-> *level* level1 info sun-fade) f0-20))))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; setup sky stuff
|
||||
(dotimes (s4-5 2)
|
||||
(make-sky-textures arg0 s4-5)
|
||||
)
|
||||
(set! (-> sky-base-polygons 0 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 1 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 2 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 3 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 4 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 5 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 6 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 7 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 8 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 9 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 10 col quad) (-> s5-1 erase-color quad))
|
||||
(set! (-> sky-base-polygons 11 col quad) (-> s5-1 erase-color quad))
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> arg0 current-sun env-color x) (* 0.5019608 (-> arg0 current-sun env-color x)))
|
||||
(set! (-> arg0 current-sun env-color y) (* 0.5019608 (-> arg0 current-sun env-color y)))
|
||||
(set! (-> arg0 current-sun env-color z) (* 0.5019608 (-> arg0 current-sun env-color z)))
|
||||
(set! (-> arg0 current-sun env-color w) (* 0.5019608 (-> arg0 current-sun env-color w)))
|
||||
|
||||
(let ((v1-179 (-> arg0 current-fog)))
|
||||
(set! *fog-color*
|
||||
(new 'static 'rgba
|
||||
:r (the int (-> v1-179 fog-color x))
|
||||
:g (the int (-> v1-179 fog-color y))
|
||||
:b (the int (-> v1-179 fog-color z))
|
||||
)
|
||||
)
|
||||
)
|
||||
(let ((v1-184 (-> arg0 current-fog erase-color)))
|
||||
(set! (-> arg0 erase-color)
|
||||
(new 'static 'rgba
|
||||
:a #x80
|
||||
:b (the int (-> v1-184 z))
|
||||
:g (the int (-> v1-184 y))
|
||||
:r (the int (-> v1-184 x))
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! (-> *math-camera* fog-start) (-> arg0 current-fog fog-dists x))
|
||||
(set! (-> *math-camera* fog-end) (-> arg0 current-fog fog-dists y))
|
||||
(set! (-> *math-camera* fog-max) (-> arg0 current-fog fog-dists z))
|
||||
(set! (-> *math-camera* fog-min) (-> arg0 current-fog fog-dists w))
|
||||
|
||||
;; interp target lights.
|
||||
(let* ((v1-195 0 #|(-> *target* draw light-index)|#) ;; TODO
|
||||
(f30-1 (-> arg0 target-interp))
|
||||
(s4-6 (-> arg0 light-group))
|
||||
(s5-2 (-> arg0 light-group v1-195))
|
||||
)
|
||||
|
||||
|
||||
(when (nonzero? v1-195)
|
||||
(cond
|
||||
((= f30-1 1.0)
|
||||
)
|
||||
((= f30-1 0.0)
|
||||
(quad-copy! (the-as pointer (-> arg0 light-group v1-195)) (the-as pointer (-> arg0 light-group)) 12)
|
||||
)
|
||||
(else
|
||||
(dotimes (s3-4 4)
|
||||
(vector4-lerp!
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s4-6 0)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0)) (* 48 s3-4)))
|
||||
f30-1
|
||||
)
|
||||
(vector4-lerp!
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0 color)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s4-6 0 dir0 color)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0 color)) (* 48 s3-4)))
|
||||
f30-1
|
||||
)
|
||||
(vector4-lerp!
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0 levels)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s4-6 0 dir0 levels)) (* 48 s3-4)))
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0 levels)) (* 48 s3-4)))
|
||||
f30-1
|
||||
)
|
||||
(vector-normalize!
|
||||
(the-as vector (+ (the-as uint (-> s5-2 dir0)) (* 48 s3-4)))
|
||||
1.0
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; some shadow thing.
|
||||
(let ((a2-30 (new 'stack-no-clear 'vector)))
|
||||
(set! (-> a2-30 x) (- (-> s5-2 dir0 direction x)))
|
||||
(set! (-> a2-30 y) (- (-> s5-2 dir0 direction y)))
|
||||
(set! (-> a2-30 z) (- (-> s5-2 dir0 direction z)))
|
||||
(when (< (-> s5-2 dir0 direction y) 0.9063)
|
||||
(let* ((f0-56 0.4226)
|
||||
(f1-17 (-> a2-30 x))
|
||||
(f1-19 (* f1-17 f1-17))
|
||||
(f2-7 (-> a2-30 z))
|
||||
(f0-57 (/ f0-56 (sqrtf (+ f1-19 (* f2-7 f2-7)))))
|
||||
)
|
||||
(set! (-> a2-30 x) (* (-> a2-30 x) f0-57))
|
||||
(set! (-> a2-30 y) -0.9063)
|
||||
(set! (-> a2-30 z) (* (-> a2-30 z) f0-57))
|
||||
)
|
||||
)
|
||||
(vector4-lerp! (-> arg0 current-shadow) (-> arg0 current-shadow) a2-30 f30-1)
|
||||
)
|
||||
(vector-normalize! (-> arg0 current-shadow) 1.0)
|
||||
)
|
||||
)
|
||||
|
||||
(reset! *palette-fade-controls*)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod set-fade! palette-fade-controls ((obj palette-fade-controls) (arg0 int) (arg1 float) (arg2 float) (arg3 vector))
|
||||
(cond
|
||||
((and (>= arg0 0) (< arg0 8))
|
||||
(let ((v1-3 (-> obj control arg0)))
|
||||
(when (< arg2 (-> v1-3 actor-dist))
|
||||
(if arg3
|
||||
(set! (-> v1-3 trans quad) (-> arg3 quad))
|
||||
)
|
||||
(set! (-> v1-3 fade) (fmax 0.0 (fmin 1.993 arg1)))
|
||||
(let ((f0-3 arg2))
|
||||
(set! (-> v1-3 actor-dist) f0-3)
|
||||
f0-3
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(format 0 "ERROR: Bogus palette-fade-control index!~%")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defmethod reset! palette-fade-controls ((obj palette-fade-controls))
|
||||
(countdown (v1-0 8)
|
||||
(let ((a1-2 (-> obj control v1-0)))
|
||||
(set! (-> a1-2 fade) 0.0)
|
||||
(set! (-> a1-2 actor-dist) 4096000000.0)
|
||||
)
|
||||
)
|
||||
#f
|
||||
)
|
||||
|
||||
|
||||
;; start the time of day process!!
|
||||
(start-time-of-day)
|
|
@ -130,7 +130,7 @@
|
|||
(display? symbol :offset-assert 376)
|
||||
(meta-inside? symbol :offset-assert 380)
|
||||
(mood mood-context :offset-assert 384)
|
||||
(mood-func function :offset-assert 388)
|
||||
(mood-func (function mood-context float int none) :offset-assert 388)
|
||||
(vis-bits pointer :offset-assert 392)
|
||||
(all-visible? symbol :offset-assert 396)
|
||||
(force-all-visible? symbol :offset-assert 400)
|
||||
|
|
|
@ -274,7 +274,7 @@
|
|||
(set! (-> s5-1 load-name) level-name)
|
||||
)
|
||||
(set! (-> s5-1 mood) (the mood-context (-> s5-1 info mood value)))
|
||||
(set! (-> s5-1 mood-func) (the function (-> s5-1 info mood-func value)))
|
||||
(set! (-> s5-1 mood-func) (the (function mood-context float int none) (-> s5-1 info mood-func value)))
|
||||
(set! (-> s5-1 display?) #f)
|
||||
(set! (-> s5-1 force-all-visible?) #f)
|
||||
(set! (-> s5-1 force-inside?) #f)
|
||||
|
@ -493,8 +493,7 @@
|
|||
(when (nonzero? (-> bsp adgifs))
|
||||
(let ((adgifs (-> bsp adgifs)))
|
||||
(dotimes (i (-> adgifs length))
|
||||
;; TODO
|
||||
;;(adgif-shader-login-no-remap (-> adgifs data i)) TODO texture.gc
|
||||
(adgif-shader-login-no-remap (-> adgifs data i))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -495,12 +495,12 @@
|
|||
(defmacro set-vector! (v xv yv zv wv)
|
||||
"Set all fields in a vector"
|
||||
(with-gensyms (vec)
|
||||
`(let ((vec ,v))
|
||||
(set! (-> vec x) ,xv)
|
||||
(set! (-> vec y) ,yv)
|
||||
(set! (-> vec z) ,zv)
|
||||
(set! (-> vec w) ,wv)
|
||||
vec
|
||||
`(let ((,vec ,v))
|
||||
(set! (-> ,vec x) ,xv)
|
||||
(set! (-> ,vec y) ,yv)
|
||||
(set! (-> ,vec z) ,zv)
|
||||
(set! (-> ,vec w) ,wv)
|
||||
,vec
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -251,7 +251,6 @@
|
|||
(s3-0 (new 'stack-no-clear 'vector))
|
||||
)
|
||||
|
||||
(format #t "adjust launch~%")
|
||||
;; use the field-init-spec to create a totally new launchinfo.
|
||||
(sp-init-fields!
|
||||
(-> s5-0 launchrot)
|
||||
|
@ -288,6 +287,7 @@
|
|||
(+! (-> arg0 launchrot z) (-> s3-0 z))
|
||||
)
|
||||
|
||||
|
||||
;; if desired, apply addition y rotation.
|
||||
(when (!= (-> s5-0 rotate-y) 0.0)
|
||||
(let ((s3-1 (new 'stack-no-clear 'matrix)))
|
||||
|
@ -689,7 +689,6 @@
|
|||
(defun sp-relaunch-particle-2d ((arg0 object) (arg1 sparticle-launcher) (arg2 sparticle-cpuinfo) (arg3 sprite-vec-data-3d))
|
||||
"relaunch a 2d particle"
|
||||
(sp-relaunch-setup-fields arg0 arg1 arg2 arg3)
|
||||
(format #t "here we are... ~A~%" (logtest? (-> arg2 flags) (sp-cpuinfo-flag aux-list)))
|
||||
(when (logtest? (-> arg2 flags) (sp-cpuinfo-flag aux-list))
|
||||
(set! (-> arg2 func) add-to-sprite-aux-list)
|
||||
(set! (-> arg3 r-g-b-a w) 0.0)
|
||||
|
|
|
@ -301,7 +301,6 @@
|
|||
(when (= a3-0 t0-0)
|
||||
;; wrap
|
||||
(set! a3-0 0)
|
||||
(format #t "wrapped!!~%")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1534,6 +1534,12 @@
|
|||
|
||||
;; definition for function target-joint-pos
|
||||
(defun target-joint-pos ()
|
||||
;; added hack
|
||||
(when (and *target* (zero? (-> *target* draw)))
|
||||
;; just return 0, we have the fake target
|
||||
(return (new 'static 'vector))
|
||||
)
|
||||
|
||||
(let ((v1-0 *target*))
|
||||
(if v1-0
|
||||
(vector<-cspace!
|
||||
|
|
|
@ -34,7 +34,11 @@
|
|||
(matrix-transpose! (-> *math-camera* camera-rot) (-> *math-camera* inv-camera-rot))
|
||||
|
||||
;; fake some value here
|
||||
(set! (-> *math-camera* fov-correction-factor) 1.0)
|
||||
;;(set! (-> *math-camera* fov-correction-factor) 1000.0)
|
||||
(set! (-> *math-camera* fov) (degrees 64.0))
|
||||
(let ((f0-28 (fmin 11650.845 (-> *math-camera* fov))))
|
||||
(set! (-> *math-camera* fov-correction-factor) (* 0.00008583069 f0-28))
|
||||
)
|
||||
|
||||
;; do the math
|
||||
(set! (-> *math-camera* trans quad) (-> location quad))
|
||||
|
@ -185,10 +189,10 @@
|
|||
(set! (-> trans rot x) (+ -54.13336 (-> trans rot x)))
|
||||
)
|
||||
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons left))
|
||||
(set! (-> trans rot y) (+ 546.13336 (-> trans rot y)))
|
||||
(set! (-> trans rot y) (+ 150.13336 (-> trans rot y)))
|
||||
)
|
||||
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons right))
|
||||
(set! (-> trans rot y) (+ -546.13336 (-> trans rot y)))
|
||||
(set! (-> trans rot y) (+ -150.13336 (-> trans rot y)))
|
||||
)
|
||||
|
||||
(set! (-> trans scale x) 1.)
|
||||
|
|
|
@ -592,3 +592,12 @@
|
|||
"Create a pointer to an object on the scratchpad."
|
||||
`(the-as (pointer ,type) (&+ *fake-scratchpad-data* ,offset))
|
||||
)
|
||||
|
||||
|
||||
(defmacro def-mips2c (name type)
|
||||
"Define a mips2c object."
|
||||
`(begin
|
||||
(define-extern ,name ,type)
|
||||
(set! ,name (the-as ,type (__pc-get-mips2c ,(symbol->string name))))
|
||||
)
|
||||
)
|
|
@ -211,7 +211,7 @@
|
|||
(set! (-> s3-0 intensity) arg1)
|
||||
)
|
||||
)
|
||||
(TODO-RENAME-10 *palette-fade-controls* (+ arg0 1) arg1 0.0 (-> s3-0 trans))
|
||||
(set-fade! *palette-fade-controls* (+ arg0 1) arg1 0.0 (-> s3-0 trans))
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@
|
|||
)
|
||||
)
|
||||
)
|
||||
(TODO-RENAME-10
|
||||
(set-fade!
|
||||
*palette-fade-controls*
|
||||
3
|
||||
(-> self deadly-fade)
|
||||
|
|
|
@ -275,6 +275,9 @@ StackVarAddrVal* FunctionEnv::allocate_aligned_stack_variable(const TypeSpec& ts
|
|||
int size_bytes,
|
||||
int align_bytes) {
|
||||
require_aligned_stack();
|
||||
if (align_bytes > 16) {
|
||||
fmt::print("\n\n\nBad stack align: {} bytes for {}\n\n\n\n", align_bytes, ts.print());
|
||||
}
|
||||
assert(align_bytes <= 16);
|
||||
int align_slots = (align_bytes + emitter::GPR_SIZE - 1) / emitter::GPR_SIZE;
|
||||
while (m_stack_var_slots_used % align_slots) {
|
||||
|
|
|
@ -1103,7 +1103,7 @@ Val* Compiler::compile_stack_new(const goos::Object& form,
|
|||
assert(stride == info.stride);
|
||||
|
||||
int size_in_bytes = info.stride * constant_count;
|
||||
auto addr = fe->allocate_aligned_stack_variable(ts, size_in_bytes, stride);
|
||||
auto addr = fe->allocate_aligned_stack_variable(ts, size_in_bytes, 16);
|
||||
return addr;
|
||||
} else {
|
||||
auto ti = m_ts.lookup_type(type_of_object);
|
||||
|
|
|
@ -564,6 +564,9 @@ bool Debugger::get_symbol_value(const std::string& sym_name, u32* output) {
|
|||
* Starts the debugger watch thread which watches the target process to see if it stops.
|
||||
*/
|
||||
void Debugger::start_watcher() {
|
||||
if (m_watcher_running) {
|
||||
stop_watcher();
|
||||
}
|
||||
assert(!m_watcher_running);
|
||||
m_watcher_running = true;
|
||||
m_watcher_should_stop = false;
|
||||
|
@ -609,6 +612,7 @@ void Debugger::watcher() {
|
|||
break;
|
||||
case xdbg::SignalInfo::DISAPPEARED:
|
||||
printf("Target has disappeared. Maybe it quit or was killed.\n");
|
||||
handle_disappearance();
|
||||
break;
|
||||
default:
|
||||
printf("[Debugger] unhandled signal in watcher: %d\n", int(signal_info.kind));
|
||||
|
@ -629,6 +633,14 @@ void Debugger::watcher() {
|
|||
}
|
||||
}
|
||||
|
||||
void Debugger::handle_disappearance() {
|
||||
m_watcher_should_stop = true;
|
||||
xdbg::close_memory(m_debug_context.tid, &m_memory_handle);
|
||||
xdbg::detach_and_resume(m_debug_context.tid);
|
||||
m_context_valid = false;
|
||||
m_attached = false;
|
||||
}
|
||||
|
||||
Debugger::SignalInfo Debugger::pop_signal() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_watcher_mutex);
|
||||
|
|
|
@ -165,6 +165,7 @@ class Debugger {
|
|||
void stop_watcher();
|
||||
void watcher();
|
||||
void update_continue_info();
|
||||
void handle_disappearance();
|
||||
|
||||
struct Breakpoint {
|
||||
u32 goal_addr = 0; // address to break at
|
||||
|
|
|
@ -980,7 +980,7 @@
|
|||
(define *thunder-id2* (new-sound-id))
|
||||
|
||||
;; definition for symbol *thunder-id*, type sound-id
|
||||
(define *thunder-id* (the-as sound-id 0))
|
||||
(define *thunder-id* (new 'static 'sound-id))
|
||||
|
||||
;; definition for symbol *thunder-count*, type int
|
||||
(define *thunder-count* 0)
|
||||
|
@ -4014,7 +4014,3 @@
|
|||
(update-mood-itimes arg0)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
(deftype dma-gif-packet (structure)
|
||||
((dma-vif dma-packet :inline :offset-assert 0)
|
||||
(gif uint64 2 :offset-assert 16)
|
||||
(gif0 uint64 :offset 16)
|
||||
(gif1 uint64 :offset 24)
|
||||
(quad uint128 2 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
|
|
|
@ -790,8 +790,8 @@
|
|||
(the-as gif-tag (format #t "~Tregs15: ~4d~%" (-> obj regs15)))
|
||||
)
|
||||
|
||||
;; definition for symbol *fog-color*, type int
|
||||
(define *fog-color* #xc88029)
|
||||
;; definition for symbol *fog-color*, type rgba
|
||||
(define *fog-color* (new 'static 'rgba :r #x29 :g #x80 :b #xc8))
|
||||
|
||||
;; definition for symbol *default-regs-buffer*, type dma-buffer
|
||||
(define *default-regs-buffer* (new 'global 'dma-buffer 1024))
|
||||
|
|
|
@ -226,16 +226,16 @@
|
|||
|
||||
;; definition of type sky-tng-data
|
||||
(deftype sky-tng-data (basic)
|
||||
((giftag-base qword :inline :offset-assert 16)
|
||||
(giftag-roof qword :inline :offset-assert 32)
|
||||
(giftag-ocean qword :inline :offset-assert 48)
|
||||
(fog vector :inline :offset-assert 64)
|
||||
(sky uint32 8 :offset-assert 80)
|
||||
(time float :offset-assert 112)
|
||||
(off-s-0 uint16 :offset-assert 116)
|
||||
(off-t-0 uint16 :offset-assert 118)
|
||||
(off-s-1 uint16 :offset-assert 120)
|
||||
(off-t-1 uint16 :offset-assert 122)
|
||||
((giftag-base gs-gif-tag :inline :offset-assert 16)
|
||||
(giftag-roof gs-gif-tag :inline :offset-assert 32)
|
||||
(giftag-ocean gs-gif-tag :inline :offset-assert 48)
|
||||
(fog vector :inline :offset-assert 64)
|
||||
(sky uint32 8 :offset-assert 80)
|
||||
(time float :offset-assert 112)
|
||||
(off-s-0 uint16 :offset-assert 116)
|
||||
(off-t-0 uint16 :offset-assert 118)
|
||||
(off-s-1 uint16 :offset-assert 120)
|
||||
(off-t-1 uint16 :offset-assert 122)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x7c
|
||||
|
@ -260,11 +260,11 @@
|
|||
|
||||
;; definition of type sky-work
|
||||
(deftype sky-work (structure)
|
||||
((adgif-tmpl dma-gif-packet :inline :offset-assert 0)
|
||||
(draw-tmpl dma-gif-packet :inline :offset-assert 32)
|
||||
(blend-tmpl dma-gif-packet :inline :offset-assert 64)
|
||||
(sky-data uint128 5 :offset-assert 96)
|
||||
(cloud-data uint128 5 :offset-assert 176)
|
||||
((adgif-tmpl dma-gif-packet :inline :offset-assert 0)
|
||||
(draw-tmpl dma-gif-packet :inline :offset-assert 32)
|
||||
(blend-tmpl dma-gif-packet :inline :offset-assert 64)
|
||||
(sky-data qword 5 :inline :offset-assert 96)
|
||||
(cloud-data qword 5 :inline :offset-assert 176)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x100
|
||||
|
|
138
test/decompiler/reference/engine/gfx/texture_REF.gc
vendored
138
test/decompiler/reference/engine/gfx/texture_REF.gc
vendored
|
@ -3154,143 +3154,7 @@
|
|||
)
|
||||
|
||||
;; definition for function adgif-shader<-texture-with-update!
|
||||
;; WARN: Unsupported inline assembly instruction kind - [plzcw v1, v1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [subu v1, t0, v1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [plzcw a3, a3]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [subu a3, t0, a3]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [plzcw a3, v1]
|
||||
;; WARN: Unsupported inline assembly instruction kind - [subu a3, t0, a3]
|
||||
(defun adgif-shader<-texture-with-update! ((arg0 adgif-shader) (arg1 texture))
|
||||
(local-vars
|
||||
(v1-11 uint128)
|
||||
(v1-12 int)
|
||||
(a3-4 uint128)
|
||||
(a3-5 int)
|
||||
(a3-9 uint128)
|
||||
(a3-10 int)
|
||||
(a3-13 int)
|
||||
(a3-22 uint)
|
||||
)
|
||||
(let* ((a2-0 (-> arg0 tex1))
|
||||
(v1-0 256)
|
||||
(a2-1 (incomplete-bitfield-access a2-0))
|
||||
(f0-1 (the float v1-0))
|
||||
(v1-1 (-> arg1 num-mips))
|
||||
(f1-0 (-> arg1 uv-dist))
|
||||
(v1-2 (+ v1-1 -1))
|
||||
(f0-2 (/ f0-1 f1-0))
|
||||
(a2-2 (logior a2-1 (* v1-2 4)))
|
||||
(v1-5 (shl (-> arg1 mip-shift) 19))
|
||||
(a3-0 (-> arg1 tex1-control))
|
||||
(a2-4 (logior (logior a2-2 v1-5) (* a3-0 32)))
|
||||
)
|
||||
(let* ((t1-1 (incomplete-bitfield-access (-> arg0 tex0)))
|
||||
(v1-6 (-> arg1 psm))
|
||||
(t1-2 (sar t1-1 62))
|
||||
(v1-7 (shl (the-as int v1-6) 20))
|
||||
(t1-3 (shl t1-2 35))
|
||||
(a3-2 (-> arg1 dest 0))
|
||||
(t1-4 (logior t1-3 v1-7))
|
||||
(v1-8 (-> arg1 width 0))
|
||||
(t1-6 (logior (logior t1-4 a3-2) (shl v1-8 14)))
|
||||
)
|
||||
(let ((v1-10 (the-as uint128 (-> arg1 wu))))
|
||||
(.plzcw v1-11 (the-as uint v1-10))
|
||||
)
|
||||
(let ((t0-0 30))
|
||||
(.subu v1-12 t0-0 (the-as int v1-11))
|
||||
(let ((a3-3 (the-as uint128 (-> arg1 hu)))
|
||||
(v1-13 (shl v1-12 26))
|
||||
)
|
||||
(.plzcw a3-4 (the-as uint a3-3))
|
||||
(let ((t1-7 (logior t1-6 v1-13)))
|
||||
(.subu a3-5 t0-0 (the-as int a3-4))
|
||||
(let* ((a3-6 (shl a3-5 30))
|
||||
(v1-14 1)
|
||||
(t1-9 (logior (logior t1-7 a3-6) (shl v1-14 34)))
|
||||
(v1-17 (shl (-> arg1 clutdest) 37))
|
||||
(a3-8 (shl (-> arg1 clutpsm) 51))
|
||||
(t1-11 (logior (logior t1-9 v1-17) a3-8))
|
||||
(v1-19 (shl 1 61))
|
||||
(f0-3 (the int f0-2))
|
||||
(t1-12 (logior t1-11 v1-19))
|
||||
(v1-20 (the-as uint128 f0-3))
|
||||
)
|
||||
(set! (-> arg0 tex0) (the-as gs-tex0 t1-12))
|
||||
(.plzcw a3-9 (the-as int v1-20))
|
||||
(.subu a3-10 t0-0 (the-as int a3-9))
|
||||
(let ((t0-2 (+ (-> arg1 mip-shift) -1)))
|
||||
(nop!)
|
||||
(b! (zero? t0-2) cfg-2 :delay (nop!))
|
||||
)
|
||||
(let* ((t0-3 (+ a3-10 -4))
|
||||
(a3-11 (* a3-10 16))
|
||||
(t0-4 (sar (the-as int v1-20) t0-3))
|
||||
(a3-12 (+ a3-11 -175))
|
||||
(t0-5 (logand t0-4 15))
|
||||
)
|
||||
(nop!)
|
||||
(b! #t cfg-3 :delay (set! a3-13 (+ a3-12 t0-5)))
|
||||
)
|
||||
(label cfg-2)
|
||||
(let* ((t0-6 (+ a3-10 -5))
|
||||
(a3-14 (* a3-10 32))
|
||||
(t0-7 (sar (the-as int v1-20) t0-6))
|
||||
(a3-15 (+ a3-14 -350))
|
||||
(t0-8 (logand t0-7 31))
|
||||
)
|
||||
(nop!)
|
||||
(set! a3-13 (+ a3-15 t0-8))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(nop!)
|
||||
(label cfg-3)
|
||||
(let* ((a3-16 (logand a3-13 4095))
|
||||
(t1-13 (-> arg1 dest 1))
|
||||
(a3-17 (shl a3-16 32))
|
||||
(v1-21 (-> arg1 width 1))
|
||||
(a2-5 (logior a2-4 a3-17))
|
||||
(v1-22 (shl v1-21 14))
|
||||
)
|
||||
(set! (-> arg0 tex1) a2-5)
|
||||
(let ((a2-6 (logior t1-13 v1-22))
|
||||
(v1-23 (-> arg1 dest 2))
|
||||
)
|
||||
(nop!)
|
||||
(let* ((a3-18 (-> arg1 width 2))
|
||||
(a2-8 (logior (logior a2-6 (shl v1-23 20)) (shl a3-18 34)))
|
||||
(v1-25 (-> arg1 dest 3))
|
||||
(a3-20 (-> arg1 width 3))
|
||||
(a2-10 (logior (logior a2-8 (shl v1-25 40)) (shl a3-20 54)))
|
||||
(t0-10 (+ (-> arg1 num-mips) -5))
|
||||
)
|
||||
(set! (-> arg0 miptbp1) (the-as gs-miptbp a2-10))
|
||||
(b! (< (the-as int t0-10) 0) cfg-5 :delay (set! a3-22 (-> arg1 width 4)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(let* ((a2-12 (logior (-> arg1 dest 4) (shl a3-22 14)))
|
||||
(v1-28 (shl (-> arg1 dest 5) 20))
|
||||
(a3-24 (-> arg1 width 5))
|
||||
(a2-14 (logior (logior a2-12 v1-28) (shl a3-24 34)))
|
||||
(v1-30 (shl (-> arg1 dest 6) 40))
|
||||
(a3-26 (-> arg1 width 6))
|
||||
(a2-16 (logior (logior a2-14 v1-30) (shl a3-26 54)))
|
||||
(v1-31 54)
|
||||
)
|
||||
(set! (-> arg0 alpha) (the-as gs-miptbp a2-16))
|
||||
(nop!)
|
||||
(set! (-> arg0 quad 4 vector4w z) v1-31)
|
||||
)
|
||||
(nop!)
|
||||
(label cfg-5)
|
||||
arg0
|
||||
)
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
;; definition for function adgif-shader-login
|
||||
(defun adgif-shader-login ((shader adgif-shader))
|
||||
|
|
|
@ -304,7 +304,7 @@
|
|||
(define GSH_ENABLE #f)
|
||||
|
||||
;; definition for symbol GSH_BUCKET, type bucket-id
|
||||
(define GSH_BUCKET (the-as bucket-id 3))
|
||||
(define GSH_BUCKET (bucket-id bucket-3))
|
||||
|
||||
;; definition for symbol GSH_WHICH_STAT, type int
|
||||
(define GSH_WHICH_STAT 1)
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
:flag-assert #xb00000110
|
||||
(:methods
|
||||
(reset! (_type_) symbol 9)
|
||||
(TODO-RENAME-10 (_type_ int float float vector) object 10)
|
||||
(set-fade! (_type_ int float float vector) object 10)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -123,27 +123,27 @@
|
|||
|
||||
;; definition of type time-of-day-context
|
||||
(deftype time-of-day-context (basic)
|
||||
((active-count uint32 :offset-assert 4)
|
||||
(interp float :offset-assert 8)
|
||||
(current-interp float :offset-assert 12)
|
||||
(moods uint64 2 :offset-assert 16)
|
||||
(current-fog mood-fog :inline :offset-assert 32)
|
||||
(current-sun mood-sun :inline :offset-assert 80)
|
||||
(current-prt-color vector :inline :offset-assert 112)
|
||||
(current-shadow vector :inline :offset-assert 128)
|
||||
(current-shadow-color vector :inline :offset-assert 144)
|
||||
(light-group light-group 9 :inline :offset-assert 160)
|
||||
(title-light-group light-group :inline :offset-assert 1888)
|
||||
(time float :offset-assert 2080)
|
||||
(target-interp float :offset-assert 2084)
|
||||
(erase-color uint32 :offset-assert 2088)
|
||||
(num-stars float :offset-assert 2092)
|
||||
(light-masks-0 uint8 2 :offset-assert 2096)
|
||||
(light-masks-1 uint8 2 :offset-assert 2098)
|
||||
(light-interp uint32 2 :offset-assert 2100)
|
||||
(sky symbol :offset-assert 2108)
|
||||
(sun-fade float :offset-assert 2112)
|
||||
(title-updated symbol :offset-assert 2116)
|
||||
((active-count uint32 :offset-assert 4)
|
||||
(interp float :offset-assert 8)
|
||||
(current-interp float :offset-assert 12)
|
||||
(moods mood-context 2 :offset-assert 16)
|
||||
(current-fog mood-fog :inline :offset-assert 32)
|
||||
(current-sun mood-sun :inline :offset-assert 80)
|
||||
(current-prt-color vector :inline :offset-assert 112)
|
||||
(current-shadow vector :inline :offset-assert 128)
|
||||
(current-shadow-color vector :inline :offset-assert 144)
|
||||
(light-group light-group 9 :inline :offset-assert 160)
|
||||
(title-light-group light-group :inline :offset-assert 1888)
|
||||
(time float :offset-assert 2080)
|
||||
(target-interp float :offset-assert 2084)
|
||||
(erase-color rgba :offset-assert 2088)
|
||||
(num-stars float :offset-assert 2092)
|
||||
(light-masks-0 uint8 2 :offset-assert 2096)
|
||||
(light-masks-1 uint8 2 :offset-assert 2098)
|
||||
(light-interp uint32 2 :offset-assert 2100)
|
||||
(sky symbol :offset-assert 2108)
|
||||
(sun-fade float :offset-assert 2112)
|
||||
(title-updated symbol :offset-assert 2116)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x848
|
||||
|
|
|
@ -139,47 +139,47 @@
|
|||
|
||||
;; definition of type level
|
||||
(deftype level (basic)
|
||||
((name symbol :offset-assert 4)
|
||||
(load-name symbol :offset-assert 8)
|
||||
(nickname symbol :offset-assert 12)
|
||||
(index int32 :offset-assert 16)
|
||||
(status symbol :offset-assert 20)
|
||||
(other level :offset-assert 24)
|
||||
(heap kheap :inline :offset-assert 32)
|
||||
(bsp bsp-header :offset-assert 48)
|
||||
(art-group load-dir-art-group :offset-assert 52)
|
||||
(info level-load-info :offset-assert 56)
|
||||
(texture-page texture-page 9 :offset-assert 60)
|
||||
(loaded-texture-page texture-page 16 :offset-assert 96)
|
||||
(loaded-texture-page-count int32 :offset-assert 160)
|
||||
(foreground-sink-group dma-foreground-sink-group 3 :inline :offset-assert 176)
|
||||
(foreground-draw-engine engine 3 :offset-assert 272)
|
||||
(entity entity-links-array :offset-assert 284)
|
||||
(ambient entity-ambient-data-array :offset-assert 288)
|
||||
(closest-object float 9 :offset-assert 292)
|
||||
(upload-size int32 9 :offset-assert 328)
|
||||
(level-distance meters :offset-assert 364)
|
||||
(inside-sphere? symbol :offset-assert 368)
|
||||
(inside-boxes? symbol :offset-assert 372)
|
||||
(display? symbol :offset-assert 376)
|
||||
(meta-inside? symbol :offset-assert 380)
|
||||
(mood mood-context :offset-assert 384)
|
||||
(mood-func function :offset-assert 388)
|
||||
(vis-bits pointer :offset-assert 392)
|
||||
(all-visible? symbol :offset-assert 396)
|
||||
(force-all-visible? symbol :offset-assert 400)
|
||||
(linking basic :offset-assert 404)
|
||||
(vis-info level-vis-info 8 :offset-assert 408)
|
||||
(vis-self-index int32 :offset-assert 440)
|
||||
(vis-adj-index int32 :offset-assert 444)
|
||||
(vis-buffer uint8 2048 :offset-assert 448)
|
||||
(mem-usage-block memory-usage-block :offset-assert 2496)
|
||||
(mem-usage int32 :offset-assert 2500)
|
||||
(code-memory-start pointer :offset-assert 2504)
|
||||
(code-memory-end pointer :offset-assert 2508)
|
||||
(texture-mask uint32 9 :offset-assert 2512)
|
||||
(force-inside? symbol :offset-assert 2548)
|
||||
(pad uint8 56 :offset-assert 2552)
|
||||
((name symbol :offset-assert 4)
|
||||
(load-name symbol :offset-assert 8)
|
||||
(nickname symbol :offset-assert 12)
|
||||
(index int32 :offset-assert 16)
|
||||
(status symbol :offset-assert 20)
|
||||
(other level :offset-assert 24)
|
||||
(heap kheap :inline :offset-assert 32)
|
||||
(bsp bsp-header :offset-assert 48)
|
||||
(art-group load-dir-art-group :offset-assert 52)
|
||||
(info level-load-info :offset-assert 56)
|
||||
(texture-page texture-page 9 :offset-assert 60)
|
||||
(loaded-texture-page texture-page 16 :offset-assert 96)
|
||||
(loaded-texture-page-count int32 :offset-assert 160)
|
||||
(foreground-sink-group dma-foreground-sink-group 3 :inline :offset-assert 176)
|
||||
(foreground-draw-engine engine 3 :offset-assert 272)
|
||||
(entity entity-links-array :offset-assert 284)
|
||||
(ambient entity-ambient-data-array :offset-assert 288)
|
||||
(closest-object float 9 :offset-assert 292)
|
||||
(upload-size int32 9 :offset-assert 328)
|
||||
(level-distance meters :offset-assert 364)
|
||||
(inside-sphere? symbol :offset-assert 368)
|
||||
(inside-boxes? symbol :offset-assert 372)
|
||||
(display? symbol :offset-assert 376)
|
||||
(meta-inside? symbol :offset-assert 380)
|
||||
(mood mood-context :offset-assert 384)
|
||||
(mood-func (function mood-context float int none) :offset-assert 388)
|
||||
(vis-bits pointer :offset-assert 392)
|
||||
(all-visible? symbol :offset-assert 396)
|
||||
(force-all-visible? symbol :offset-assert 400)
|
||||
(linking basic :offset-assert 404)
|
||||
(vis-info level-vis-info 8 :offset-assert 408)
|
||||
(vis-self-index int32 :offset-assert 440)
|
||||
(vis-adj-index int32 :offset-assert 444)
|
||||
(vis-buffer uint8 2048 :offset-assert 448)
|
||||
(mem-usage-block memory-usage-block :offset-assert 2496)
|
||||
(mem-usage int32 :offset-assert 2500)
|
||||
(code-memory-start pointer :offset-assert 2504)
|
||||
(code-memory-end pointer :offset-assert 2508)
|
||||
(texture-mask uint32 9 :offset-assert 2512)
|
||||
(force-inside? symbol :offset-assert 2548)
|
||||
(pad uint8 56 :offset-assert 2552)
|
||||
)
|
||||
:method-count-assert 29
|
||||
:size-assert #xa30
|
||||
|
|
|
@ -239,7 +239,7 @@
|
|||
(set! (-> s3-0 intensity) arg1)
|
||||
)
|
||||
)
|
||||
(TODO-RENAME-10 *palette-fade-controls* (+ arg0 1) arg1 0.0 (-> s3-0 trans))
|
||||
(set-fade! *palette-fade-controls* (+ arg0 1) arg1 0.0 (-> s3-0 trans))
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -281,7 +281,3 @@
|
|||
f30-0
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@
|
|||
)
|
||||
)
|
||||
)
|
||||
(TODO-RENAME-10
|
||||
(set-fade!
|
||||
*palette-fade-controls*
|
||||
3
|
||||
(-> self deadly-fade)
|
||||
|
|
|
@ -63,6 +63,8 @@ const std::unordered_set<std::string> g_functions_expected_to_reject = {
|
|||
// display
|
||||
"vblank-handler", // asm
|
||||
"vif1-handler", "vif1-handler-debug",
|
||||
// texture
|
||||
"adgif-shader<-texture-with-update!", // mips2c
|
||||
// sparticle
|
||||
"sp-launch-particles-var", "particle-adgif", "sp-init-fields!", "memcpy", "sp-process-block-2d",
|
||||
"sp-process-block-3d",
|
||||
|
|
Loading…
Reference in a new issue