mirror of
https://github.com/open-goal/jak-project
synced 2026-09-09 20:21:28 -04:00
up to generic-effect
This commit is contained in:
@@ -2964,6 +2964,51 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
||||
// SetVarElement
|
||||
///////////////////
|
||||
|
||||
namespace {
|
||||
bool try_rewrite_string_format_load(SetVarElement& set,
|
||||
const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack) {
|
||||
// string-format expands to
|
||||
// (begin (format (clear *temp-string*) args...) *temp-string*)
|
||||
//
|
||||
// Recognize the reload only when the matching format call is the immediately preceding active
|
||||
// expression. Keeping the resulting value at the reload's position is important: normal stack
|
||||
// popping can then inline it only where doing so preserves argument evaluation order, or leave a
|
||||
// temporary when an intervening argument was evaluated after the format call.
|
||||
if (!set.src()->to_form(env).is_symbol("*temp-string*")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* previous = stack.active_back();
|
||||
if (!previous || previous->destination || !previous->elt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* format_call = dynamic_cast<GenericElement*>(previous->elt);
|
||||
if (!format_call || !format_call->op().is_func() ||
|
||||
!format_call->op().func()->to_form(env).is_symbol("format") || format_call->elts().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* clear_call = format_call->elts().front()->try_as_element<GenericElement>();
|
||||
if (!clear_call || !clear_call->op().is_func() ||
|
||||
!clear_call->op().func()->to_form(env).is_symbol("clear") || clear_call->elts().size() != 1 ||
|
||||
!clear_call->elts().front()->to_form(env).is_symbol("*temp-string*")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Form*> format_args(format_call->elts().begin() + 1, format_call->elts().end());
|
||||
auto string_format = pool.form<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("string-format")),
|
||||
format_args);
|
||||
|
||||
stack.pop_active_back();
|
||||
stack.push_value_to_reg(set.dst(), string_format, true, set.src_type(), set.info());
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
for (auto x : m_src->elts()) {
|
||||
@@ -2977,6 +3022,10 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
||||
return;
|
||||
}
|
||||
|
||||
if (try_rewrite_string_format_load(*this, env, pool, stack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we are a reg-reg move that consumes the original, push it without popping from stack.
|
||||
// it is the Stack's responsibility to untangle these later on.
|
||||
if (m_src->is_single_element()) {
|
||||
|
||||
@@ -929,7 +929,7 @@ FormElement* rewrite_set_vector(LetElement* in, const Env& env, FormPool& pool)
|
||||
FormElement* rewrite_set_vector_sequence(const std::array<FormElement*, 4>& elts,
|
||||
const Env& env,
|
||||
FormPool& pool) {
|
||||
std::optional<RegisterAccess> vector_access;
|
||||
std::optional<RegisterAccess> root_access;
|
||||
Form* vector_form = nullptr;
|
||||
std::vector<Form*> sources;
|
||||
|
||||
@@ -940,26 +940,37 @@ FormElement* rewrite_set_vector_sequence(const std::array<FormElement*, 4>& elts
|
||||
}
|
||||
|
||||
auto* deref = set->dst()->try_as_element<DerefElement>();
|
||||
Matcher dst_matcher = Matcher::deref(Matcher::any_reg(0), false,
|
||||
{DerefTokenMatcher::string(std::string(1, "xyzw"[i]))});
|
||||
auto mr = match(dst_matcher, set->dst());
|
||||
if (!deref || !mr.matched) {
|
||||
if (!deref || deref->is_addr_of() || deref->tokens().empty() ||
|
||||
!deref->tokens().back().is_field_name(std::string(1, "xyzw"[i]))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto this_access = *mr.maps.regs.at(0);
|
||||
if (vector_access &&
|
||||
env.get_program_var_id(*vector_access) != env.get_program_var_id(this_access)) {
|
||||
const auto root_atom = form_as_atom(deref->base());
|
||||
if (!root_atom || !root_atom->is_var()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto this_root = root_atom->var();
|
||||
if (root_access && env.get_program_var_id(*root_access) != env.get_program_var_id(this_root)) {
|
||||
return nullptr;
|
||||
}
|
||||
root_access = this_root;
|
||||
|
||||
auto target_tokens = deref->tokens();
|
||||
target_tokens.pop_back();
|
||||
Form* this_vector_form = deref->base();
|
||||
if (!target_tokens.empty()) {
|
||||
this_vector_form = pool.form<DerefElement>(deref->base(), false, std::move(target_tokens));
|
||||
}
|
||||
if (vector_form && vector_form->to_form(env) != this_vector_form->to_form(env)) {
|
||||
return nullptr;
|
||||
}
|
||||
vector_access = this_access;
|
||||
if (!vector_form) {
|
||||
vector_form = deref->base();
|
||||
vector_form = this_vector_form;
|
||||
}
|
||||
sources.push_back(set->src());
|
||||
}
|
||||
|
||||
ASSERT(vector_access);
|
||||
ASSERT(root_access);
|
||||
std::vector<Form*> args = {vector_form};
|
||||
args.insert(args.end(), sources.begin(), sources.end());
|
||||
auto op = GenericOperator::make_function(
|
||||
|
||||
@@ -20518,7 +20518,7 @@ framebuffer on alpha failure."
|
||||
;; - Types
|
||||
|
||||
(deftype ripple-request (structure)
|
||||
((waveform ripple-wave :offset-assert 0)
|
||||
((waveform ripple-wave-set :offset-assert 0)
|
||||
(effect merc-effect :offset-assert 4)
|
||||
)
|
||||
:pack-me
|
||||
@@ -20564,7 +20564,7 @@ bytes. Fragment geometry, query, and control streams advance according to their
|
||||
(define-extern ripple-make-request
|
||||
"Queue an effect to receive a waveform during this frame. Ignore duplicate effects and requests
|
||||
beyond the sixteen-entry buffer."
|
||||
(function ripple-wave merc-effect none))
|
||||
(function ripple-wave-set merc-effect none))
|
||||
(define-extern ripple-execute
|
||||
"Build each requested waveform table once, apply it to every queued effect that shares that
|
||||
waveform, and clear the request list."
|
||||
|
||||
@@ -326,6 +326,15 @@
|
||||
"rewrite":
|
||||
"(dma-buffer-add-gif-tag $buf $tag $regs)"
|
||||
},
|
||||
{
|
||||
// &-> produces the address of the selected value. Immediately dereferencing element zero
|
||||
// cancels that address operation and can be expressed as an ordinary value access.
|
||||
"name": "deref-zero-of-addressed-field",
|
||||
"match":
|
||||
"(-> (&-> $base $*tokens) 0)",
|
||||
"rewrite":
|
||||
"(-> $base $*tokens)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-two-uint128",
|
||||
"match":
|
||||
@@ -333,6 +342,33 @@
|
||||
"rewrite":
|
||||
"(dma-buffer-add-uint128 $buf $value0 $value1)"
|
||||
},
|
||||
{
|
||||
// The cursor binding can retain an inferred storage view while the casts on both stores
|
||||
// establish the actual flat uint128 layout.
|
||||
"name": "dma-buffer-add-two-uint128-cast-stores",
|
||||
"match":
|
||||
"(let* (($alias $buf) ($data (the-as $storage-type (-> $alias base)))) (set! (-> (the-as (pointer uint128) $data) 0) $value0) (set! (-> (the-as (pointer uint128) $data) 1) $value1) (set! (-> $alias base) (&+ (the-as pointer $data) 32)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-uint128 $buf $value0 $value1)"
|
||||
},
|
||||
{
|
||||
// Four qwords may be reconstructed through an aggregate containing two pairs instead of as
|
||||
// a flat uint128 pointer. The field sequence and 64-byte advance identify the same append.
|
||||
"name": "dma-buffer-add-four-uint128-pairs",
|
||||
"match":
|
||||
"(let* (($alias $buf) ($data (the-as (inline-array vector4w-2) (-> $alias base)))) (set! (-> $data 0 quad 0) $value0) (set! (-> $data 0 quad 1) $value1) (set! (-> $data 1 quad 0) $value2) (set! (-> $data 1 quad 1) $value3) (set! (-> $alias base) (&+ (the-as pointer $data) 64)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-uint128 $buf $value0 $value1 $value2 $value3)"
|
||||
},
|
||||
{
|
||||
// A storage view may remain on the cursor binding, but explicit uint128 casts on all six
|
||||
// indexed stores make their flat contiguous layout independent of that inferred view.
|
||||
"name": "dma-buffer-add-six-uint128-cast-stores",
|
||||
"match":
|
||||
"(let* (($alias $buf) ($data (the-as $storage-type (-> $alias base)))) (set! (-> (the-as (pointer uint128) $data) 0) $value0) (set! (-> (the-as (pointer uint128) $data) 1) $value1) (set! (-> (the-as (pointer uint128) $data) 2) $value2) (set! (-> (the-as (pointer uint128) $data) 3) $value3) (set! (-> (the-as (pointer uint128) $data) 4) $value4) (set! (-> (the-as (pointer uint128) $data) 5) $value5) (set! (-> $alias base) (&+ (the-as pointer $data) 96)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-uint128 $buf $value0 $value1 $value2 $value3 $value4 $value5)"
|
||||
},
|
||||
{
|
||||
// Four sequential eight-byte stores are the common expansion of dma-buffer-add-uint64.
|
||||
// Their individual pointer types reflect the value types; the 32-byte advance fixes the width.
|
||||
@@ -350,6 +386,24 @@
|
||||
"rewrite":
|
||||
"(with-cnt-vif-block ($buf) $*body)"
|
||||
},
|
||||
{
|
||||
// Variant emitted when the saved tag is inferred as a uint64 pointer. The pointer-form
|
||||
// subtraction and direct uint64 stores are equivalent to the typed dma-tag expansion.
|
||||
"name": "with-cnt-vif-block-uint64-tag",
|
||||
"match":
|
||||
"(let (($start (the-as (pointer uint64) (-> $buf base)))) (dma-buffer-add-cnt-vif2 $buf 0 (new 'static 'vif-tag) (new 'static 'vif-tag :cmd (vif-cmd direct) :msk #x1)) $*body (let (($qwc (/ (the-as int (+ (&- (the-as pointer -16) (the-as uint $start)) (the-as int (-> $buf base)))) 16))) (cond ((nonzero? $qwc) (logior! (-> $start 0) (shr (shl $qwc 48) 48)) (logior! (-> $start 1) (shl (shr (shl $qwc 48) 48) 32))) (else (set! (-> $buf base) $start)))))",
|
||||
"rewrite":
|
||||
"(with-cnt-vif-block ($buf) $*body)"
|
||||
},
|
||||
{
|
||||
// gif-prim sets exactly IIP and ABE in addition to the primitive kind. Keep the complete
|
||||
// constructor in the match so primitives with any other flag combination remain explicit.
|
||||
"name": "gif-prim",
|
||||
"match":
|
||||
"(new 'static 'gs-prim :prim (gs-prim-type $prim-type) :iip #x1 :abe #x1)",
|
||||
"rewrite":
|
||||
"(gif-prim $prim-type)"
|
||||
},
|
||||
{
|
||||
// Let insertion may merge the saved tag pointer into a caller's surrounding let*.
|
||||
"name": "with-cnt-vif-block-merged-bindings",
|
||||
|
||||
@@ -652,7 +652,7 @@
|
||||
"add-debug-flat-triangle": [
|
||||
[[55, 61], "a3", "dma-packet"],
|
||||
[[64, 70], "a3", "gs-gif-tag"],
|
||||
[[93, 112], "a3", "(inline-array vector4w-3)"],
|
||||
[[93, 112], "a3", "(pointer uint128)"],
|
||||
[[53, 133], "a0", "(pointer uint64)"],
|
||||
[115, "a1", "pointer"],
|
||||
[[135, 140], "a0", "dma-packet"]
|
||||
@@ -660,12 +660,13 @@
|
||||
"add-debug-line2d": [
|
||||
[[58, 64], "a2", "dma-packet"],
|
||||
[[67, 73], "a2", "gs-gif-tag"],
|
||||
[[76, 81], "a2", "(inline-array vector4w)"],
|
||||
[[84, 89], "a2", "(inline-array vector4w)"],
|
||||
[[76, 81], "a2", "(pointer uint128)"],
|
||||
[[84, 89], "a2", "(pointer uint128)"],
|
||||
[[56, 110], "a0", "(pointer uint64)"],
|
||||
[92, "a1", "pointer"],
|
||||
[[112, 117], "v1", "dma-packet"]
|
||||
],
|
||||
"add-debug-light": [[82, "s1", "rgba"]],
|
||||
"debug-percent-bar": [[[32, 43], "v1", "dma-packet"]],
|
||||
"debug-pad-display": [[[70, 75], "v1", "dma-packet"]],
|
||||
"internal-draw-debug-text-3d": [[[54, 59], "v1", "dma-packet"]],
|
||||
|
||||
@@ -22160,7 +22160,10 @@
|
||||
"label"
|
||||
],
|
||||
"vars": {
|
||||
"s1-0": "packed-color",
|
||||
"s1-0": [
|
||||
"packed-color",
|
||||
"rgba"
|
||||
],
|
||||
"s2-1": "position",
|
||||
"t0-2": "text"
|
||||
}
|
||||
|
||||
@@ -169,7 +169,6 @@ set(RUNTIME_SOURCE
|
||||
mips2c/jak1_functions/merc_blend_shape.cpp
|
||||
mips2c/jak1_functions/ocean_vu0.cpp
|
||||
mips2c/jak1_functions/ocean.cpp
|
||||
mips2c/jak1_functions/ripple.cpp
|
||||
mips2c/jak1_functions/shadow.cpp
|
||||
mips2c/jak1_functions/sky_tng.cpp
|
||||
mips2c/jak1_functions/sparticle_launcher.cpp
|
||||
|
||||
@@ -122,894 +122,6 @@ void vcallms48(ExecutionContext* c) {
|
||||
|
||||
}
|
||||
|
||||
namespace generic_envmap_dproc {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
// nop // sll r0, r0, 0
|
||||
get_fake_spad_addr(at, cache.fake_scratchpad_data, 0, c);// lui at, 28672
|
||||
c->lui(v1, 16256); // lui v1, 16256
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->lwu(a1, 60, at); // lwu a1, 60(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(v1, 12048, at); // lw v1, 12048(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a2, 4, a1); // lw a2, 4(a1)
|
||||
c->mov64(a0, a2); // or a0, a2, r0
|
||||
c->lhu(a1, 20, a1); // lhu a1, 20(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f4, 24, a2); // lwc1 f4, 24(a2)
|
||||
c->daddiu(a1, a1, -4); // daddiu a1, a1, -4
|
||||
c->lwc1(f3, 56, a2); // lwc1 f3, 56(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f2, 88, a2); // lwc1 f2, 88(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f1, 120, a2); // lwc1 f1, 120(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t2, 16, a2); // lq t2, 16(a2)
|
||||
c->subs(f4, f4, f0); // sub.s f4, f4, f0
|
||||
c->lq(t3, 48, a2); // lq t3, 48(a2)
|
||||
c->divs(f4, f0, f4); // div.s f4, f0, f4
|
||||
c->lq(t4, 80, a2); // lq t4, 80(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t5, 112, a2); // lq t5, 112(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lqc2(vf31, 12016, at); // lqc2 vf31, 12016(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t6, 0, a2); // lq t6, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(a3, 32, a2); // lq a3, 32(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t0, 64, a2); // lq t0, 64(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t1, 96, a2); // lq t1, 96(a2)
|
||||
c->muls(f4, f4, f0); // mul.s f4, f4, f0
|
||||
c->mov128_vf_gpr(vf21, t2); // qmtc2.i vf21, t2
|
||||
c->subs(f3, f3, f0); // sub.s f3, f3, f0
|
||||
c->mov128_vf_gpr(vf22, t3); // qmtc2.ni vf22, t3
|
||||
c->divs(f3, f0, f3); // div.s f3, f0, f3
|
||||
c->mov128_vf_gpr(vf23, t4); // qmtc2.ni vf23, t4
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf24, t5); // qmtc2.ni vf24, t5
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf9, t6); // qmtc2.ni vf9, t6
|
||||
c->subs(f2, f2, f0); // sub.s f2, f2, f0
|
||||
c->mfc1(t2, f4); // mfc1 t2, f4
|
||||
c->subs(f1, f1, f0); // sub.s f1, f1, f0
|
||||
c->mov128_vf_gpr(vf10, a3); // qmtc2.ni vf10, a3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf11, t0); // qmtc2.ni vf11, t0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf12, t1); // qmtc2.ni vf12, t1
|
||||
c->muls(f3, f3, f0); // mul.s f3, f3, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f2, f0, f2); // div.s f2, f0, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(a3, f3); // mfc1 a3, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f2, f2, f0); // mul.s f2, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f1, f0, f1); // div.s f1, f0, f1
|
||||
// nop // sll r0, r0, 0
|
||||
c->pextlw(a3, a3, t2); // pextlw a3, a3, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t0, f2); // mfc1 t0, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a2, a2, 128); // daddiu a2, a2, 128
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t1, f1); // mfc1 t1, f1
|
||||
c->pextlw(t0, t1, t0); // pextlw t0, t1, t0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(a3, t0, a3); // pcpyld a3, t0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf27, a3); // qmtc2.ni vf27, a3
|
||||
// nop // sll r0, r0, 0
|
||||
// Unknown instr: vcallms 48
|
||||
vcallms48(c);
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f4, 24, a2); // lwc1 f4, 24(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f3, 56, a2); // lwc1 f3, 56(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f2, 88, a2); // lwc1 f2, 88(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f1, 120, a2); // lwc1 f1, 120(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(a3, 16, a2); // lq a3, 16(a2)
|
||||
c->subs(f4, f4, f0); // sub.s f4, f4, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f3, f3, f0); // sub.s f3, f3, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f2, f2, f0); // sub.s f2, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f1, f1, f0); // sub.s f1, f1, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f4, f0, f4); // div.s f4, f0, f4
|
||||
c->lq(t0, 48, a2); // lq t0, 48(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t1, 80, a2); // lq t1, 80(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t2, 112, a2); // lq t2, 112(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t3, 0, a2); // lq t3, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t4, 32, a2); // lq t4, 32(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t5, 64, a2); // lq t5, 64(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t6, 96, a2); // lq t6, 96(a2)
|
||||
c->muls(f4, f4, f0); // mul.s f4, f4, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f3, f0, f3); // div.s f3, f0, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t7, f4); // mfc1 t7, f4
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a2, a2, 128); // daddiu a2, a2, 128
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f3, f3, f0); // mul.s f3, f3, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f2, f0, f2); // div.s f2, f0, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f3); // mfc1 t8, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f2, f2, f0); // mul.s f2, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f1, f0, f1); // div.s f1, f0, f1
|
||||
// nop // sll r0, r0, 0
|
||||
c->pextlw(t7, t8, t7); // pextlw t7, t8, t7
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f2); // mfc1 t8, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t9, f1); // mfc1 t9, f1
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf21, a3); // qmtc2.ni vf21, a3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf9, t3); // qmtc2.ni vf9, t3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf10, t4); // qmtc2.ni vf10, t4
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf11, t5); // qmtc2.ni vf11, t5
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf12, t6); // qmtc2.ni vf12, t6
|
||||
c->pextlw(a3, t9, t8); // pextlw a3, t9, t8
|
||||
// nop // sll r0, r0, 0
|
||||
c->pcpyld(a3, a3, t7); // pcpyld a3, a3, t7
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf22, t0); // qmtc2.ni vf22, t0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf23, t1); // qmtc2.ni vf23, t1
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf24, t2); // qmtc2.ni vf24, t2
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf27, a3); // qmtc2.ni vf27, a3
|
||||
// nop // sll r0, r0, 0
|
||||
// Unknown instr: vcallms 48
|
||||
vcallms48(c);
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f1, 24, a2); // lwc1 f1, 24(a2)
|
||||
c->subs(f1, f1, f0); // sub.s f1, f1, f0
|
||||
c->lwc1(f2, 56, a2); // lwc1 f2, 56(a2)
|
||||
c->divs(f3, f0, f1); // div.s f3, f0, f1
|
||||
c->lwc1(f5, 88, a2); // lwc1 f5, 88(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f1, 120, a2); // lwc1 f1, 120(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(a3, 16, a2); // lq a3, 16(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f4, f2, f0); // sub.s f4, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f2, f5, f0); // sub.s f2, f5, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->subs(f1, f1, f0); // sub.s f1, f1, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f3, f3, f0); // mul.s f3, f3, f0
|
||||
c->lq(t0, 48, a2); // lq t0, 48(a2)
|
||||
c->divs(f4, f0, f4); // div.s f4, f0, f4
|
||||
c->lq(t1, 80, a2); // lq t1, 80(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t2, 112, a2); // lq t2, 112(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t3, 0, a2); // lq t3, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t4, 32, a2); // lq t4, 32(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t5, 64, a2); // lq t5, 64(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t6, 96, a2); // lq t6, 96(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t7, f3); // mfc1 t7, f3
|
||||
c->muls(f3, f4, f0); // mul.s f3, f4, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f2, f0, f2); // div.s f2, f0, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a2, a2, 128); // daddiu a2, a2, 128
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f3); // mfc1 t8, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f2, f2, f0); // mul.s f2, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f1, f0, f1); // div.s f1, f0, f1
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t9, f2); // mfc1 t9, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->pextlw(t7, t8, t7); // pextlw t7, t8, t7
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f1); // mfc1 t8, f1
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->pextlw(t8, t8, t9); // pextlw t8, t8, t9
|
||||
// nop // sll r0, r0, 0
|
||||
c->pcpyld(t7, t8, t7); // pcpyld t7, t8, t7
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf21, a3); // qmtc2.ni vf21, a3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf22, t0); // qmtc2.ni vf22, t0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf23, t1); // qmtc2.ni vf23, t1
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf24, t2); // qmtc2.ni vf24, t2
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf9, t3); // qmtc2.ni vf9, t3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf10, t4); // qmtc2.ni vf10, t4
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf11, t5); // qmtc2.ni vf11, t5
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf12, t6); // qmtc2.ni vf12, t6
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf27, t7); // qmtc2.ni vf27, t7
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t1, vf17); // qmfc2.ni t1, vf17
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t2, vf18); // qmfc2.ni t2, vf18
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t0, vf19); // qmfc2.ni t0, vf19
|
||||
bc = ((s64)c->sgpr64(a1)) <= 0; // blez a1, L47
|
||||
c->mov128_gpr_vf(a3, vf20); // qmfc2.ni a3, vf20
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
|
||||
block_1:
|
||||
c->ppach(t1, r0, t1); // ppach t1, r0, t1
|
||||
// Unknown instr: vcallms 48
|
||||
vcallms48(c);
|
||||
c->ppach(t2, r0, t2); // ppach t2, r0, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->ppach(t0, r0, t0); // ppach t0, r0, t0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->ppach(a3, r0, a3); // ppach a3, r0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t1, 16, a0); // sw t1, 16(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t2, 48, a0); // sw t2, 48(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t0, 80, a0); // sw t0, 80(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(a3, 112, a0); // sw a3, 112(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f4, 24, a2); // lwc1 f4, 24(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f3, 56, a2); // lwc1 f3, 56(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f2, 88, a2); // lwc1 f2, 88(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lwc1(f1, 120, a2); // lwc1 f1, 120(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(a3, 16, a2); // lq a3, 16(a2)
|
||||
c->subs(f4, f4, f0); // sub.s f4, f4, f0
|
||||
c->sw(v1, 20, a0); // sw v1, 20(a0)
|
||||
c->subs(f3, f3, f0); // sub.s f3, f3, f0
|
||||
c->sw(v1, 52, a0); // sw v1, 52(a0)
|
||||
c->subs(f2, f2, f0); // sub.s f2, f2, f0
|
||||
c->sw(v1, 84, a0); // sw v1, 84(a0)
|
||||
c->subs(f1, f1, f0); // sub.s f1, f1, f0
|
||||
c->sw(v1, 116, a0); // sw v1, 116(a0)
|
||||
c->divs(f4, f0, f4); // div.s f4, f0, f4
|
||||
c->lq(t3, 48, a2); // lq t3, 48(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t4, 80, a2); // lq t4, 80(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t5, 112, a2); // lq t5, 112(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t6, 0, a2); // lq t6, 0(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t2, 32, a2); // lq t2, 32(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t0, 64, a2); // lq t0, 64(a2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t1, 96, a2); // lq t1, 96(a2)
|
||||
c->daddiu(a1, a1, -4); // daddiu a1, a1, -4
|
||||
c->daddiu(a0, a0, 128); // daddiu a0, a0, 128
|
||||
c->muls(f4, f4, f0); // mul.s f4, f4, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f3, f0, f3); // div.s f3, f0, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t7, f4); // mfc1 t7, f4
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a2, a2, 128); // daddiu a2, a2, 128
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f3, f3, f0); // mul.s f3, f3, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f2, f0, f2); // div.s f2, f0, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f3); // mfc1 t8, f3
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->muls(f2, f2, f0); // mul.s f2, f2, f0
|
||||
// nop // sll r0, r0, 0
|
||||
c->divs(f1, f0, f1); // div.s f1, f0, f1
|
||||
// nop // sll r0, r0, 0
|
||||
c->pextlw(t7, t8, t7); // pextlw t7, t8, t7
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t8, f2); // mfc1 t8, f2
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mfc1(t9, f1); // mfc1 t9, f1
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf21, a3); // qmtc2.ni vf21, a3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf22, t3); // qmtc2.ni vf22, t3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf23, t4); // qmtc2.ni vf23, t4
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf24, t5); // qmtc2.ni vf24, t5
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf9, t6); // qmtc2.ni vf9, t6
|
||||
c->pextlw(a3, t9, t8); // pextlw a3, t9, t8
|
||||
c->mov128_vf_gpr(vf10, t2); // qmtc2.ni vf10, t2
|
||||
c->pcpyld(a3, a3, t7); // pcpyld a3, a3, t7
|
||||
c->mov128_vf_gpr(vf11, t0); // qmtc2.ni vf11, t0
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf12, t1); // qmtc2.ni vf12, t1
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_vf_gpr(vf27, a3); // qmtc2.ni vf27, a3
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t1, vf17); // qmfc2.ni t1, vf17
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t2, vf18); // qmfc2.ni t2, vf18
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(t0, vf19); // qmfc2.ni t0, vf19
|
||||
bc = ((s64)c->sgpr64(a1)) > 0; // bgtz a1, L46
|
||||
c->mov128_gpr_vf(a3, vf20); // qmfc2.ni a3, vf20
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
|
||||
block_2:
|
||||
c->ppach(a1, r0, t1); // ppach a1, r0, t1
|
||||
c->sw(v1, 20, a0); // sw v1, 20(a0)
|
||||
c->ppach(a2, r0, t2); // ppach a2, r0, t2
|
||||
c->sw(v1, 52, a0); // sw v1, 52(a0)
|
||||
c->ppach(t0, r0, t0); // ppach t0, r0, t0
|
||||
c->sw(a1, 16, a0); // sw a1, 16(a0)
|
||||
c->ppach(a1, r0, a3); // ppach a1, r0, a3
|
||||
c->sw(a2, 48, a0); // sw a2, 48(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t0, 80, a0); // sw t0, 80(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(a1, 112, a0); // sw a1, 112(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(v1, 84, a0); // sw v1, 84(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(v1, 116, a0); // sw v1, 116(a0)
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, 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
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("generic-envmap-dproc", execute, 256);
|
||||
}
|
||||
|
||||
} // namespace generic_envmap_dproc
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace generic_interp_dproc {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
get_fake_spad_addr(at, cache.fake_scratchpad_data, 0, c);// lui at, 28672
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(v1, 80, at); // lw v1, 80(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 60, at); // lw a0, 60(at)
|
||||
bc = c->sgpr64(v1) == 0; // beq v1, r0, L44
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(t0, 8, v1); // lw t0, 8(v1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a2, 4, a0); // lw a2, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lh(a0, 0, v1); // lh a0, 0(v1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lh(a1, 2, v1); // lh a1, 2(v1)
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L44
|
||||
c->lh(a0, 4, v1); // lh a0, 4(v1)
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
c->dsll(t1, a0, 5); // dsll t1, a0, 5
|
||||
c->lh(a0, 12, v1); // lh a0, 12(v1)
|
||||
c->daddiu(a3, a1, 7); // daddiu a3, a1, 7
|
||||
c->lh(a1, 14, v1); // lh a1, 14(v1)
|
||||
bc = c->sgpr64(a1) == 0; // beq a1, r0, L44
|
||||
c->daddu(v1, t1, a2); // daddu v1, t1, a2
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
c->pextlh(a0, a0, a0); // pextlh a0, a0, a0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlw(a0, a0, a0); // pextlw a0, a0, a0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(a0, a0, a0); // pcpyld a0, a0, a0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlh(a1, a1, a1); // pextlh a1, a1, a1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlw(a1, a1, a1); // pextlw a1, a1, a1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(a1, a1, a1); // pcpyld a1, a1, a1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlw(a2, a2, a2); // pextlw a2, a2, a2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(a2, a2, a2); // pcpyld a2, a2, a2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->dsra(a3, a3, 3); // dsra a3, a3, 3
|
||||
// nop // sll r0, r0, 0
|
||||
c->dsll(a3, a3, 4); // dsll a3, a3, 4
|
||||
c->ld(t1, 0, t0); // ld t1, 0(t0)
|
||||
c->daddu(a3, t0, a3); // daddu a3, t0, a3
|
||||
c->daddiu(t0, t0, 8); // daddiu t0, t0, 8
|
||||
c->pextlb(t1, r0, t1); // pextlb t1, r0, t1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psllh(t2, t1, 5); // psllh t2, t1, 5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextuh(t1, r0, t2); // pextuh t1, r0, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlh(t2, r0, t2); // pextlh t2, r0, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->paddw(t2, t2, a2); // paddw t2, t2, a2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
//beq r0, r0, L43 // beq r0, r0, L43
|
||||
c->pcpyud(t5, t2, r0); // pcpyud t5, t2, r0
|
||||
goto block_5; // branch always
|
||||
|
||||
|
||||
block_4:
|
||||
c->dsrl32(t5, t6, 0); // dsrl32 t5, t6, 0
|
||||
c->dsrl32(t4, t3, 0); // dsrl32 t4, t3, 0
|
||||
c->pextuh(t1, r0, t2); // pextuh t1, r0, t2
|
||||
c->sw(t6, 16, v1); // sw t6, 16(v1)
|
||||
c->pextlh(t2, r0, t2); // pextlh t2, r0, t2
|
||||
c->sw(t5, 48, v1); // sw t5, 48(v1)
|
||||
c->paddw(t2, t2, a2); // paddw t2, t2, a2
|
||||
c->sw(t3, 80, v1); // sw t3, 80(v1)
|
||||
c->pcpyud(t5, t2, r0); // pcpyud t5, t2, r0
|
||||
c->sw(t4, 112, v1); // sw t4, 112(v1)
|
||||
c->daddiu(t0, t0, 8); // daddiu t0, t0, 8
|
||||
c->daddiu(v1, v1, 128); // daddiu v1, v1, 128
|
||||
|
||||
block_5:
|
||||
c->paddw(t1, t1, a2); // paddw t1, t1, a2
|
||||
c->lwu(t3, 16, t2); // lwu t3, 16(t2)
|
||||
c->pcpyud(t6, t1, r0); // pcpyud t6, t1, r0
|
||||
c->lwu(t4, 16, t5); // lwu t4, 16(t5)
|
||||
c->dsrl32(t8, t2, 0); // dsrl32 t8, t2, 0
|
||||
c->lwu(t2, 16, t1); // lwu t2, 16(t1)
|
||||
c->dsrl32(t9, t5, 0); // dsrl32 t9, t5, 0
|
||||
c->lwu(t5, 16, t6); // lwu t5, 16(t6)
|
||||
c->dsrl32(t7, t1, 0); // dsrl32 t7, t1, 0
|
||||
c->lwu(t1, 16, t8); // lwu t1, 16(t8)
|
||||
c->dsrl32(t8, t6, 0); // dsrl32 t8, t6, 0
|
||||
c->lwu(t6, 16, t9); // lwu t6, 16(t9)
|
||||
c->pextlw(t4, t4, t3); // pextlw t4, t4, t3
|
||||
c->lwu(t3, 16, t7); // lwu t3, 16(t7)
|
||||
c->pextlw(t2, t5, t2); // pextlw t2, t5, t2
|
||||
c->lwu(t5, 16, t8); // lwu t5, 16(t8)
|
||||
c->pcpyld(t2, t2, t4); // pcpyld t2, t2, t4
|
||||
c->lwu(t4, 16, v1); // lwu t4, 16(v1)
|
||||
c->pextlw(t6, t6, t1); // pextlw t6, t6, t1
|
||||
c->lwu(t1, 48, v1); // lwu t1, 48(v1)
|
||||
c->pextlw(t3, t5, t3); // pextlw t3, t5, t3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(t3, t3, t6); // pcpyld t3, t3, t6
|
||||
c->lwu(t5, 80, v1); // lwu t5, 80(v1)
|
||||
c->pextlw(t1, t1, t4); // pextlw t1, t1, t4
|
||||
c->lwu(t4, 112, v1); // lwu t4, 112(v1)
|
||||
c->pmulth(r0, t2, a1); // pmulth r0, t2, a1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlw(t2, t4, t5); // pextlw t2, t4, t5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pmaddh(r0, t3, a1); // pmaddh r0, t3, a1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(t1, t2, t1); // pcpyld t1, t2, t1
|
||||
c->ld(t2, 0, t0); // ld t2, 0(t0)
|
||||
c->pmaddh(r0, t1, a0); // pmaddh r0, t1, a0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlb(t1, r0, t2); // pextlb t1, r0, t2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psllh(t2, t1, 5); // psllh t2, t1, 5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// Unknown instr: pmfhl.lw t3
|
||||
c->pmfhl_lw(t3);
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
// Unknown instr: pmfhl.uw t1
|
||||
c->pmfhl_uw(t1);
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psraw(t3, t3, 8); // psraw t3, t3, 8
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psraw(t1, t1, 8); // psraw t1, t1, 8
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pinteh(t6, t1, t3); // pinteh t6, t1, t3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
bc = c->sgpr64(t0) != c->sgpr64(a3); // bne t0, a3, L42
|
||||
c->pcpyud(t3, t6, r0); // pcpyud t3, t6, r0
|
||||
if (bc) {goto block_4;} // branch non-likely
|
||||
|
||||
c->dsrl32(a0, t6, 0); // dsrl32 a0, t6, 0
|
||||
c->sw(t6, 16, v1); // sw t6, 16(v1)
|
||||
c->dsrl32(a1, t3, 0); // dsrl32 a1, t3, 0
|
||||
c->sw(a0, 48, v1); // sw a0, 48(v1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t3, 80, v1); // sw t3, 80(v1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(a1, 112, v1); // sw a1, 112(v1)
|
||||
|
||||
block_7:
|
||||
//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
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("generic-interp-dproc", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace generic_interp_dproc
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace generic_no_light_dproc {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->daddiu(sp, sp, -128); // daddiu sp, sp, -128
|
||||
c->sd(ra, 12432, at); // sd ra, 12432(at)
|
||||
c->sq(s0, 12448, at); // sq s0, 12448(at)
|
||||
c->sq(s1, 12464, at); // sq s1, 12464(at)
|
||||
c->sq(s2, 12480, at); // sq s2, 12480(at)
|
||||
c->sq(s3, 12496, at); // sq s3, 12496(at)
|
||||
c->sq(s4, 12512, at); // sq s4, 12512(at)
|
||||
c->sq(s5, 12528, at); // sq s5, 12528(at)
|
||||
c->sq(gp, 12544, at); // sq gp, 12544(at)
|
||||
get_fake_spad_addr(at, cache.fake_scratchpad_data, 0, c);// lui at, 28672
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a1, 60, at); // lw a1, 60(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 52, at); // lw a0, 52(at)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(v1, 0, a1); // lw v1, 0(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a2, 4, a1); // lw a2, 4(a1)
|
||||
c->daddiu(a0, a0, 3); // daddiu a0, a0, 3
|
||||
// nop // sll r0, r0, 0
|
||||
c->dsra(a0, a0, 2); // dsra a0, a0, 2
|
||||
// nop // sll r0, r0, 0
|
||||
c->dsll(a0, a0, 3); // dsll a0, a0, 3
|
||||
c->addiu(a3, r0, 255); // addiu a3, r0, 255
|
||||
c->lui(a1, -2); // lui a1, -2
|
||||
c->addiu(t1, r0, 256); // addiu t1, r0, 256
|
||||
c->ori(a1, a1, 65534); // ori a1, a1, 65534
|
||||
c->daddu(a0, v1, a0); // daddu a0, v1, a0
|
||||
c->pextlw(a1, a1, a1); // pextlw a1, a1, a1
|
||||
c->lw(t2, 20, at); // lw t2, 20(at)
|
||||
c->pextlw(a1, a1, a1); // pextlw a1, a1, a1
|
||||
c->lw(t3, 24, at); // lw t3, 24(at)
|
||||
c->pextlw(a2, a2, a2); // pextlw a2, a2, a2
|
||||
c->lw(t5, 28, at); // lw t5, 28(at)
|
||||
c->pextlw(a2, a2, a2); // pextlw a2, a2, a2
|
||||
c->lw(t4, 32, at); // lw t4, 32(at)
|
||||
c->pcpyh(a3, a3); // pcpyh a3, a3
|
||||
c->lw(t6, 36, at); // lw t6, 36(at)
|
||||
c->pcpyld(a3, a3, a3); // pcpyld a3, a3, a3
|
||||
c->lq(t0, 12160, at); // lq t0, 12160(at)
|
||||
c->pcpyh(t1, t1); // pcpyh t1, t1
|
||||
c->ld(t7, 0, v1); // ld t7, 0(v1)
|
||||
c->pcpyld(t1, t1, t1); // pcpyld t1, t1, t1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlh(t8, r0, t7); // pextlh t8, r0, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pand(t7, t8, a3); // pand t7, t8, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->psllw(t7, t7, 5); // psllw t7, t7, 5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->daddiu(t2, t2, -48); // daddiu t2, t2, -48
|
||||
c->daddiu(t3, t3, -16); // daddiu t3, t3, -16
|
||||
c->daddiu(t4, t4, -16); // daddiu t4, t4, -16
|
||||
c->daddiu(t5, t5, -16); // daddiu t5, t5, -16
|
||||
//beq r0, r0, L34 // beq r0, r0, L34
|
||||
c->daddiu(t6, t6, -16); // daddiu t6, t6, -16
|
||||
goto block_3; // branch always
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_2:
|
||||
c->pextlh(t8, r0, gp); // pextlh t8, r0, gp
|
||||
c->sq(t7, 0, t2); // sq t7, 0(t2)
|
||||
c->pand(t7, t8, a3); // pand t7, t8, a3
|
||||
c->sq(t9, 16, t2); // sq t9, 16(t2)
|
||||
c->psllw(t7, t7, 5); // psllw t7, t7, 5
|
||||
c->sq(ra, 32, t2); // sq ra, 32(t2)
|
||||
|
||||
block_3:
|
||||
c->paddw(s3, t7, a2); // paddw s3, t7, a2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->dsrl32(s2, s3, 0); // dsrl32 s2, s3, 0
|
||||
c->daddiu(t2, t2, 48); // daddiu t2, t2, 48
|
||||
c->pcpyud(s5, s3, r0); // pcpyud s5, s3, r0
|
||||
c->lq(t7, 0, s3); // lq t7, 0(s3)
|
||||
c->dsrl32(s4, s5, 0); // dsrl32 s4, s5, 0
|
||||
c->daddiu(t3, t3, 16); // daddiu t3, t3, 16
|
||||
c->pand(t8, t8, t1); // pand t8, t8, t1
|
||||
c->lq(t9, 0, s2); // lq t9, 0(s2)
|
||||
c->psraw(gp, t8, 8); // psraw gp, t8, 8
|
||||
c->lq(t8, 0, s5); // lq t8, 0(s5)
|
||||
c->pextuw(s1, t9, t7); // pextuw s1, t9, t7
|
||||
c->lq(ra, 0, s4); // lq ra, 0(s4)
|
||||
c->daddiu(t5, t5, 16); // daddiu t5, t5, 16
|
||||
c->daddiu(v1, v1, 8); // daddiu v1, v1, 8
|
||||
c->daddiu(t4, t4, 16); // daddiu t4, t4, 16
|
||||
c->daddiu(t6, t6, 16); // daddiu t6, t6, 16
|
||||
c->pextuw(s0, ra, t8); // pextuw s0, ra, t8
|
||||
c->lq(s3, 16, s3); // lq s3, 16(s3)
|
||||
c->pcpyud(s1, s1, s0); // pcpyud s1, s1, s0
|
||||
c->lq(s2, 16, s2); // lq s2, 16(s2)
|
||||
c->paddh(s0, s1, t0); // paddh s0, s1, t0
|
||||
c->lq(s1, 16, s5); // lq s1, 16(s5)
|
||||
c->pand(s5, s0, a1); // pand s5, s0, a1
|
||||
c->lq(s0, 16, s4); // lq s0, 16(s4)
|
||||
c->pextlw(s4, s2, s3); // pextlw s4, s2, s3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextuw(s3, s2, s3); // pextuw s3, s2, s3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextlw(s2, s0, s1); // pextlw s2, s0, s1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextuw(s0, s0, s1); // pextuw s0, s0, s1
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(s1, s2, s4); // pcpyld s1, s2, s4
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyud(s4, s4, s2); // pcpyud s4, s4, s2
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyud(s3, s3, s0); // pcpyud s3, s3, s0
|
||||
c->sq(s4, 0, t4); // sq s4, 0(t4)
|
||||
c->pand(s4, s1, a1); // pand s4, s1, a1
|
||||
c->sq(s3, 0, t3); // sq s3, 0(t3)
|
||||
c->por(s4, s4, gp); // por s4, s4, gp
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->por(gp, s5, gp); // por gp, s5, gp
|
||||
c->sq(s4, 0, t6); // sq s4, 0(t6)
|
||||
c->prot3w(ra, ra); // prot3w ra, ra
|
||||
c->sq(gp, 0, t5); // sq gp, 0(t5)
|
||||
c->prot3w(t9, t9); // prot3w t9, t9
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextuw(s5, t9, t7); // pextuw s5, t9, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcpyld(t9, t8, t9); // pcpyld t9, t8, t9
|
||||
c->ld(gp, 0, v1); // ld gp, 0(v1)
|
||||
c->pcpyld(t7, s5, t7); // pcpyld t7, s5, t7
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pextuw(t8, ra, t8); // pextuw t8, ra, t8
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
bc = c->sgpr64(v1) != c->sgpr64(a0); // bne v1, a0, L33
|
||||
c->pcpyld(ra, ra, t8); // pcpyld ra, ra, t8
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(t7, 0, t2); // sq t7, 0(t2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(t9, 16, t2); // sq t9, 16(t2)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(ra, 32, t2); // sq ra, 32(t2)
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
|
||||
c->ld(ra, 12432, at); // ld ra, 12432(at)
|
||||
c->lq(gp, 12544, at); // lq gp, 12544(at)
|
||||
c->lq(s5, 12528, at); // lq s5, 12528(at)
|
||||
c->lq(s4, 12512, at); // lq s4, 12512(at)
|
||||
c->lq(s3, 12496, at); // lq s3, 12496(at)
|
||||
c->lq(s2, 12480, at); // lq s2, 12480(at)
|
||||
c->lq(s1, 12464, at); // lq s1, 12464(at)
|
||||
c->lq(s0, 12448, at); // lq s0, 12448(at)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 128); // daddiu sp, sp, 128
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("generic-no-light-dproc", execute, 256);
|
||||
}
|
||||
|
||||
} // namespace generic_no_light_dproc
|
||||
} // namespace Mips2C
|
||||
|
||||
|
||||
|
||||
@@ -114,16 +114,6 @@ namespace generic_prepare_dma_double {
|
||||
extern u64 execute(void* ctxt);
|
||||
}
|
||||
|
||||
namespace generic_envmap_dproc {
|
||||
extern u64 execute(void* ctxt);
|
||||
}
|
||||
namespace generic_interp_dproc {
|
||||
extern u64 execute(void* ctxt);
|
||||
}
|
||||
namespace generic_no_light_dproc {
|
||||
extern u64 execute(void* ctxt);
|
||||
}
|
||||
|
||||
namespace generic_tie_convert {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
@@ -2092,17 +2082,17 @@ u64 execute(void* ctxt) {
|
||||
call_addr = c->gprs[v1].du32[0]; // function call:
|
||||
// Unknown instr: sllv v0, ra, r0
|
||||
// c->jalr(call_addr); // jalr ra, v1
|
||||
generic_envmap_dproc::execute(c);
|
||||
// generic_envmap_dproc::execute(c);
|
||||
c->lw(v1, 756, at); // lw v1, 756(at)
|
||||
call_addr = c->gprs[v1].du32[0]; // function call:
|
||||
// Unknown instr: sllv v0, ra, r0
|
||||
// c->jalr(call_addr); // jalr ra, v1
|
||||
generic_interp_dproc::execute(c);
|
||||
// generic_interp_dproc::execute(c);
|
||||
c->lw(v1, 760, at); // lw v1, 760(at)
|
||||
call_addr = c->gprs[v1].du32[0]; // function call:
|
||||
// Unknown instr: sllv v0, ra, r0
|
||||
// c->jalr(call_addr); // jalr ra, v1
|
||||
generic_no_light_dproc::execute(c);
|
||||
// generic_no_light_dproc::execute(c);
|
||||
c->lw(v1, 40, at); // lw v1, 40(at)
|
||||
c->lw(a0, 56, at); // lw a0, 56(at)
|
||||
c->mov64(a3, v1); // or a3, v1, r0
|
||||
|
||||
@@ -1,581 +0,0 @@
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/kernel/jak1/kscheme.h"
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
using namespace jak1;
|
||||
namespace Mips2C::jak1 {
|
||||
|
||||
struct RippleVu0 {
|
||||
Vf data_mem[256];
|
||||
void sq(const Vf& reg, u16 addr) {
|
||||
ASSERT(addr < 256);
|
||||
data_mem[addr] = reg;
|
||||
}
|
||||
Vf lq(u16 addr) {
|
||||
ASSERT(addr < 256);
|
||||
return data_mem[addr];
|
||||
}
|
||||
} gRippleVu0;
|
||||
|
||||
namespace ripple_execute_init {
|
||||
struct Cache {
|
||||
void* cos_poly_vec; // *cos-poly-vec*
|
||||
} cache;
|
||||
|
||||
// clang-format off
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->daddiu(sp, sp, -16); // daddiu sp, sp, -16
|
||||
c->sd(fp, 8, sp); // sd fp, 8(sp)
|
||||
c->mov64(fp, t9); // or fp, t9, r0
|
||||
c->load_symbol(v1, cache.cos_poly_vec); // lw v1, *cos-poly-vec*(s7)
|
||||
c->lqc2(vf7, 0, v1); // lqc2 vf7, 0(v1)
|
||||
c->fprs[f0] = 0.024543691; // lwc1 f0, L50(fp)
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
c->mov128_vf_gpr(vf6, v1); // qmtc2.i vf6, v1
|
||||
c->mov128_gpr_vf(v1, vf6); // qmfc2.i v1, vf6
|
||||
c->addiu(v1, r0, 128); // addiu v1, r0, 128
|
||||
u16 vi2 = c->gpr_src(v1).du16[0]; // ctc2.i vi2, v1
|
||||
c->gprs[v1].du64[0] = vi2; // cfc2.i v1, vi2
|
||||
c->fprs[f0] = 1.0; // lwc1 f0, L61(fp)
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
c->mov128_vf_gpr(vf9, v1); // qmtc2.i vf9, v1
|
||||
c->mov128_gpr_vf(v1, vf9); // qmfc2.i v1, vf9
|
||||
u16 vi1 = 0; // viaddi vi1, vi0, 0
|
||||
c->addiu(v1, r0, 128); // addiu v1, r0, 128
|
||||
c->vmove(DEST::xyzw, vf5, vf6); // vmove.xyzw vf5, vf6
|
||||
|
||||
block_1:
|
||||
c->vmul(DEST::xyzw, vf1, vf5, vf5); // vmul.xyzw vf1, vf5, vf5
|
||||
c->vadda_bc(DEST::xyzw, BC::w, vf0, vf0); // vaddaw.xyzw acc, vf0, vf0
|
||||
c->vadd(DEST::x, vf5, vf5, vf6); // vadd.x vf5, vf5, vf6
|
||||
c->vsub_bc(DEST::y, BC::x, vf9, vf0, vf9); // vsubx.y vf9, vf0, vf9
|
||||
c->vmul(DEST::xyzw, vf2, vf1, vf1); // vmul.xyzw vf2, vf1, vf1
|
||||
c->vmadda_bc(DEST::xyzw, BC::x, vf1, vf7); // vmaddax.xyzw acc, vf1, vf7
|
||||
c->vmul(DEST::xyzw, vf3, vf2, vf1); // vmul.xyzw vf3, vf2, vf1
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf2, vf7); // vmadday.xyzw acc, vf2, vf7
|
||||
c->vmul(DEST::xyzw, vf4, vf2, vf2); // vmul.xyzw vf4, vf2, vf2
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf3, vf7); // vmaddaz.xyzw acc, vf3, vf7
|
||||
c->daddiu(v1, v1, -1); // daddiu v1, v1, -1
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf8, vf4, vf7); // vmaddw.xyzw vf8, vf4, vf7
|
||||
c->vadd_bc(DEST::y, BC::x, vf9, vf9, vf8); // vaddx.y vf9, vf9, vf8
|
||||
c->vsub(DEST::xyzw, vf10, vf0, vf9); // vsub.xyzw vf10, vf0, vf9
|
||||
gRippleVu0.sq(c->vfs[vf9].vf, vi1++); // vsqi.xyzw vf9, vi1
|
||||
c->vmove(DEST::xyzw, vf9, vf8); // vmove.xyzw vf9, vf8
|
||||
bc = c->sgpr64(v1) != 0; // bne v1, r0, L39
|
||||
gRippleVu0.sq(c->vfs[vf10].vf, vi2++); // vsqi.xyzw vf10, vi2
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
|
||||
c->ld(fp, 8, sp); // ld fp, 8(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 16); // daddiu sp, sp, 16
|
||||
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() {
|
||||
cache.cos_poly_vec = intern_from_c("*cos-poly-vec*").c();
|
||||
gLinkedFunctionTable.reg("ripple-execute-init", execute, 32);
|
||||
}
|
||||
|
||||
} // namespace ripple_execute_init
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace ripple_create_wave_table {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
void* setting_control; // *setting-control*
|
||||
void* atan; // atan
|
||||
void* cos; // cos
|
||||
void* ntsc; // ntsc
|
||||
void* pal; // pal
|
||||
void* ripple_update_waveform_offs; // ripple-update-waveform-offs
|
||||
void* sin; // sin
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u16 vi1, vi2;
|
||||
u32 call_addr = 0;
|
||||
c->daddiu(sp, sp, -80); // daddiu sp, sp, -80
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->sd(fp, 8, sp); // sd fp, 8(sp)
|
||||
c->mov64(fp, t9); // or fp, t9, r0
|
||||
c->sq(s4, 16, sp); // sq s4, 16(sp)
|
||||
c->sq(s5, 32, sp); // sq s5, 32(sp)
|
||||
c->sq(gp, 48, sp); // sq gp, 48(sp)
|
||||
c->swc1(f28, 64, sp); // swc1 f28, 64(sp)
|
||||
c->swc1(f30, 68, sp); // swc1 f30, 68(sp)
|
||||
c->mov64(gp, a0); // or gp, a0, r0
|
||||
c->lwu(v1, 4, gp); // lwu v1, 4(gp)
|
||||
bc = c->sgpr64(s7) != c->sgpr64(v1); // bne s7, v1, L30
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
if (bc) {goto block_9;} // branch non-likely
|
||||
|
||||
c->addiu(s5, r0, 0); // addiu s5, r0, 0
|
||||
//beq r0, r0, L29 // beq r0, r0, L29
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_7; // branch always
|
||||
|
||||
|
||||
block_2:
|
||||
c->addiu(v1, r0, 28); // addiu v1, r0, 28
|
||||
c->mult3(v1, v1, s5); // mult3 v1, v1, s5
|
||||
c->daddiu(v1, v1, 16); // daddiu v1, v1, 16
|
||||
c->daddu(s4, v1, gp); // daddu s4, v1, gp
|
||||
c->load_symbol(t9, cache.atan); // lw t9, atan(s7)
|
||||
c->lh(v1, 10, s4); // lh v1, 10(s4)
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->cvtsw(f0, f0); // cvt.s.w f0, f0
|
||||
c->mfc1(a0, f0); // mfc1 a0, f0
|
||||
c->lh(v1, 8, s4); // lh v1, 8(s4)
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->cvtsw(f0, f0); // cvt.s.w f0, f0
|
||||
c->mfc1(a1, f0); // mfc1 a1, f0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->sll(v0, ra, 0); // sll v0, ra, 0
|
||||
c->jalr(call_addr); // jalr ra, t9
|
||||
c->mtc1(f28, v0); // mtc1 f28, v0
|
||||
c->fprs[f0] = 16.0; // lwc1 f0, L60(fp)
|
||||
c->lh(v1, 8, s4); // lh v1, 8(s4)
|
||||
c->lh(a0, 8, s4); // lh a0, 8(s4)
|
||||
c->mult3(v1, v1, a0); // mult3 v1, v1, a0
|
||||
c->lh(a0, 10, s4); // lh a0, 10(s4)
|
||||
c->lh(a1, 10, s4); // lh a1, 10(s4)
|
||||
c->mult3(a0, a0, a1); // mult3 a0, a0, a1
|
||||
c->daddu(v1, v1, a0); // daddu v1, v1, a0
|
||||
c->mtc1(f1, v1); // mtc1 f1, v1
|
||||
c->cvtsw(f1, f1); // cvt.s.w f1, f1
|
||||
c->sqrts(f1, f1); // sqrt.s f1, f1
|
||||
c->divs(f30, f0, f1); // div.s f30, f0, f1
|
||||
c->load_symbol(t9, cache.cos); // lw t9, cos(s7)
|
||||
c->mfc1(a0, f28); // mfc1 a0, f28
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->sll(v0, ra, 0); // sll v0, ra, 0
|
||||
c->jalr(call_addr); // jalr ra, t9
|
||||
c->mtc1(f0, v0); // mtc1 f0, v0
|
||||
c->fprs[f1] = 65536.0; // lwc1 f1, L52(fp)
|
||||
c->divs(f1, f1, f30); // div.s f1, f1, f30
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->swc1(f0, 16, s4); // swc1 f0, 16(s4)
|
||||
c->load_symbol(t9, cache.sin); // lw t9, sin(s7)
|
||||
c->mfc1(a0, f28); // mfc1 a0, f28
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->sll(v0, ra, 0); // sll v0, ra, 0
|
||||
c->jalr(call_addr); // jalr ra, t9
|
||||
c->mtc1(f0, v0); // mtc1 f0, v0
|
||||
c->fprs[f1] = 65536.0; // lwc1 f1, L52(fp)
|
||||
c->divs(f1, f1, f30); // div.s f1, f1, f30
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->swc1(f0, 20, s4); // swc1 f0, 20(s4)
|
||||
c->load_symbol(v1, cache.setting_control); // lw v1, *setting-control*(s7)
|
||||
c->lwu(v1, 80, v1); // lwu v1, 80(v1)
|
||||
c->load_symbol_addr(a0, cache.ntsc); // daddiu a0, s7, ntsc
|
||||
bc = c->sgpr64(v1) != c->sgpr64(a0); // bne v1, a0, L27
|
||||
c->mov64(a0, s7); // or a0, s7, r0
|
||||
if (bc) {goto block_4;} // branch non-likely
|
||||
|
||||
c->fprs[f0] = 0.016666668; // lwc1 f0, L55(fp)
|
||||
c->fprs[f1] = -65536.0; // lwc1 f1, L53(fp)
|
||||
c->divs(f1, f1, f30); // div.s f1, f1, f30
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->lwc1(f1, 12, s4); // lwc1 f1, 12(s4)
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->swc1(f0, 24, s4); // swc1 f0, 24(s4)
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
//beq r0, r0, L28 // beq r0, r0, L28
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_6; // branch always
|
||||
|
||||
|
||||
block_4:
|
||||
c->load_symbol_addr(a0, cache.pal); // daddiu a0, s7, pal
|
||||
bc = c->sgpr64(v1) != c->sgpr64(a0); // bne v1, a0, L28
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
if (bc) {goto block_6;} // branch non-likely
|
||||
|
||||
c->fprs[f0] = 0.02; // lwc1 f0, L51(fp)
|
||||
c->fprs[f1] = -65536.0; // lwc1 f1, L53(fp)
|
||||
c->divs(f1, f1, f30); // div.s f1, f1, f30
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->lwc1(f1, 12, s4); // lwc1 f1, 12(s4)
|
||||
c->muls(f0, f0, f1); // mul.s f0, f0, f1
|
||||
c->swc1(f0, 24, s4); // swc1 f0, 24(s4)
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
|
||||
block_6:
|
||||
c->daddiu(s5, s5, 1); // daddiu s5, s5, 1
|
||||
|
||||
block_7:
|
||||
c->lw(v1, 0, gp); // lw v1, 0(gp)
|
||||
c->slt(v1, s5, v1); // slt v1, s5, v1
|
||||
bc = c->sgpr64(v1) != 0; // bne v1, r0, L26
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
c->daddiu(v1, s7, 8); // daddiu v1, s7, #t
|
||||
c->sw(v1, 4, gp); // sw v1, 4(gp)
|
||||
|
||||
block_9:
|
||||
c->load_symbol(t9, cache.ripple_update_waveform_offs);// lw t9, ripple-update-waveform-offs(s7)
|
||||
c->mov64(a0, gp); // or a0, gp, r0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->sll(v0, ra, 0); // sll v0, ra, 0
|
||||
c->jalr(call_addr); // jalr ra, t9
|
||||
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 0, c);// lui v1, 28672
|
||||
c->addiu(a0, r0, 64); // addiu a0, r0, 64
|
||||
c->mov64(a1, v1); // or a1, v1, r0
|
||||
|
||||
block_10:
|
||||
c->daddiu(a0, a0, -1); // daddiu a0, a0, -1
|
||||
c->sq(r0, 0, a1); // sq r0, 0(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L31
|
||||
c->daddiu(a1, a1, 16); // daddiu a1, a1, 16
|
||||
if (bc) {goto block_10;} // branch non-likely
|
||||
|
||||
c->addiu(a0, r0, 0); // addiu a0, r0, 0
|
||||
//beq r0, r0, L35 // beq r0, r0, L35
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_17; // branch always
|
||||
|
||||
|
||||
block_12:
|
||||
c->addiu(a1, r0, 28); // addiu a1, r0, 28
|
||||
c->mult3(a1, a1, a0); // mult3 a1, a1, a0
|
||||
c->daddiu(a1, a1, 16); // daddiu a1, a1, 16
|
||||
c->daddu(a1, a1, gp); // daddu a1, a1, gp
|
||||
c->fprs[f0] = 16384.0; // lwc1 f0, L54(fp)
|
||||
c->fprs[f1] = 0.00390625; // lwc1 f1, L63(fp)
|
||||
c->lwc1(f2, 4, a1); // lwc1 f2, 4(a1)
|
||||
c->muls(f1, f1, f2); // mul.s f1, f1, f2
|
||||
c->adds(f0, f0, f1); // add.s f0, f0, f1
|
||||
c->fprs[f1] = 0.00390625; // lwc1 f1, L63(fp)
|
||||
c->lwc1(f2, 16, a1); // lwc1 f2, 16(a1)
|
||||
c->muls(f1, f1, f2); // mul.s f1, f1, f2
|
||||
c->fprs[f2] = 0.00390625; // lwc1 f2, L63(fp)
|
||||
c->lwc1(f3, 20, a1); // lwc1 f3, 20(a1)
|
||||
c->muls(f2, f2, f3); // mul.s f2, f2, f3
|
||||
c->lwc1(f3, 0, a1); // lwc1 f3, 0(a1)
|
||||
c->addiu(a1, r0, 255); // addiu a1, r0, 255
|
||||
c->mfc1(a2, f0); // mfc1 a2, f0
|
||||
c->mov128_vf_gpr(vf1, a2); // qmtc2.i vf1, a2
|
||||
c->mfc1(a2, f1); // mfc1 a2, f1
|
||||
c->mov128_vf_gpr(vf2, a2); // qmtc2.i vf2, a2
|
||||
c->mfc1(a2, f2); // mfc1 a2, f2
|
||||
c->mov128_vf_gpr(vf3, a2); // qmtc2.i vf3, a2
|
||||
c->mfc1(a2, f3); // mfc1 a2, f3
|
||||
c->mov128_vf_gpr(vf4, a2); // qmtc2.i vf4, a2
|
||||
vi1 = c->gpr_src(a1).du16[0]; // ctc2.i vi1, a1
|
||||
c->mov64(a1, v1); // or a1, v1, r0
|
||||
c->addiu(a2, r0, 16); // addiu a2, r0, 16
|
||||
c->vmove(DEST::xyzw, vf6, vf0); // vmove.xyzw vf6, vf0
|
||||
|
||||
block_13:
|
||||
c->addiu(a3, r0, 16); // addiu a3, r0, 16
|
||||
c->vmove(DEST::xyzw, vf5, vf0); // vmove.xyzw vf5, vf0
|
||||
|
||||
block_14:
|
||||
c->lw(at, 0, a1); // lw at, 0(a1)
|
||||
c->vadda_bc(DEST::xyzw, BC::x, vf1, vf0); // vaddax.xyzw acc, vf1, vf0
|
||||
c->vmadda(DEST::xyzw, vf2, vf5); // vmadda.xyzw acc, vf2, vf5
|
||||
c->vmadd(DEST::xyzw, vf7, vf3, vf6); // vmadd.xyzw vf7, vf3, vf6
|
||||
c->mov128_vf_gpr(vf10, at); // qmtc2.i vf10, at
|
||||
c->vadd_bc(DEST::xyzw, BC::w, vf5, vf5, vf0); // vaddw.xyzw vf5, vf5, vf0
|
||||
c->vftoi0(DEST::xyzw, vf8, vf7); // vftoi0.xyzw vf8, vf7
|
||||
vi2 = c->vfs[vf8].vf.x_as_u16(); // vmtirx vi2, vf8
|
||||
c->vitof0(DEST::xyzw, vf8, vf8); // vitof0.xyzw vf8, vf8
|
||||
vi2 &= vi1; // Unknown instr: viand vi2, vi2, vi1
|
||||
c->vfs[vf9].vf = gRippleVu0.lq(vi2++); // Unknown instr: vlqi.xyzw vf9, vi2
|
||||
c->vsub(DEST::xyzw, vf7, vf7, vf8); // vsub.xyzw vf7, vf7, vf8
|
||||
c->vadda_bc(DEST::xyzw, BC::x, vf0, vf9); // vaddax.xyzw acc, vf0, vf9
|
||||
c->vmadd_bc(DEST::xyzw, BC::y, vf9, vf7, vf9); // vmaddy.xyzw vf9, vf7, vf9
|
||||
c->vadda_bc(DEST::xyzw, BC::x, vf10, vf0); // vaddax.xyzw acc, vf10, vf0
|
||||
c->vmadd(DEST::xyzw, vf10, vf9, vf4); // vmadd.xyzw vf10, vf9, vf4
|
||||
c->mov128_gpr_vf(at, vf10); // qmfc2.i at, vf10
|
||||
c->sw(at, 0, a1); // sw at, 0(a1)
|
||||
c->daddiu(a3, a3, -1); // daddiu a3, a3, -1
|
||||
bc = c->sgpr64(a3) != 0; // bne a3, r0, L34
|
||||
c->daddiu(a1, a1, 4); // daddiu a1, a1, 4
|
||||
if (bc) {goto block_14;} // branch non-likely
|
||||
|
||||
c->daddiu(a2, a2, -1); // daddiu a2, a2, -1
|
||||
bc = c->sgpr64(a2) != 0; // bne a2, r0, L33
|
||||
c->vadd_bc(DEST::xyzw, BC::w, vf6, vf6, vf0); // vaddw.xyzw vf6, vf6, vf0
|
||||
if (bc) {goto block_13;} // branch non-likely
|
||||
|
||||
c->mov128_gpr_vf(a1, vf6); // qmfc2.i a1, vf6
|
||||
c->daddiu(a0, a0, 1); // daddiu a0, a0, 1
|
||||
|
||||
block_17:
|
||||
c->lw(a1, 0, gp); // lw a1, 0(gp)
|
||||
c->slt(a1, a0, a1); // slt a1, a0, a1
|
||||
bc = c->sgpr64(a1) != 0; // bne a1, r0, L32
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_12;} // branch non-likely
|
||||
|
||||
c->mov64(a0, s7); // or a0, s7, r0
|
||||
c->mov64(a0, s7); // or a0, s7, r0
|
||||
c->fprs[f1] = 128.0; // lwc1 f1, L57(fp)
|
||||
c->fprs[f0] = 255.0; // lwc1 f0, L56(fp)
|
||||
c->lwc1(f2, 12, gp); // lwc1 f2, 12(gp)
|
||||
c->mfc1(a0, f2); // mfc1 a0, f2
|
||||
c->mov128_vf_gpr(vf16, a0); // qmtc2.i vf16, a0
|
||||
c->mfc1(a0, f1); // mfc1 a0, f1
|
||||
c->mov128_vf_gpr(vf14, a0); // qmtc2.i vf14, a0
|
||||
c->mfc1(a0, f0); // mfc1 a0, f0
|
||||
c->mov128_vf_gpr(vf15, a0); // qmtc2.i vf15, a0
|
||||
c->vmax_bc(DEST::xyzw, BC::x, vf16, vf0, vf16); // vmaxx.xyzw vf16, vf0, vf16
|
||||
c->vmini_bc(DEST::w, BC::x, vf16, vf0, vf0); // vminix.w vf16, vf0, vf0
|
||||
c->mov64(v1, v1); // or v1, v1, r0
|
||||
c->addiu(v0, r0, 15); // addiu v0, r0, 15
|
||||
|
||||
block_19:
|
||||
c->addiu(a0, r0, 15); // addiu a0, r0, 15
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_20:
|
||||
c->addiu(a2, r0, 4); // addiu a2, r0, 4
|
||||
c->addiu(at, r0, -60); // addiu at, r0, -60
|
||||
c->movz(a2, at, a0); // movz a2, at, a0
|
||||
c->addiu(a1, r0, 64); // addiu a1, r0, 64
|
||||
c->addiu(at, r0, -960); // addiu at, r0, -960
|
||||
c->daddu(a2, a2, v1); // daddu a2, a2, v1
|
||||
c->movz(a1, at, v0); // movz a1, at, v0
|
||||
c->lw(at, 0, v1); // lw at, 0(v1)
|
||||
c->lw(a2, 0, a2); // lw a2, 0(a2)
|
||||
c->daddu(a1, a1, v1); // daddu a1, a1, v1
|
||||
c->lw(a1, 0, a1); // lw a1, 0(a1)
|
||||
c->mov128_vf_gpr(vf11, at); // qmtc2.i vf11, at
|
||||
c->mov128_vf_gpr(vf12, a2); // qmtc2.i vf12, a2
|
||||
c->mov128_vf_gpr(vf13, a1); // qmtc2.i vf13, a1
|
||||
c->vadd_bc(DEST::xyzw, BC::x, vf11, vf0, vf11); // vaddx.xyzw vf11, vf0, vf11
|
||||
c->vsub_bc(DEST::y, BC::x, vf11, vf11, vf12); // vsubx.y vf11, vf11, vf12
|
||||
c->vsub_bc(DEST::z, BC::x, vf11, vf11, vf13); // vsubx.z vf11, vf11, vf13
|
||||
c->vmul(DEST::yzw, vf11, vf11, vf16); // vmul.yzw vf11, vf11, vf16
|
||||
c->vadd_bc(DEST::xyzw, BC::x, vf11, vf11, vf14); // vaddx.xyzw vf11, vf11, vf14
|
||||
c->vmax_bc(DEST::xyzw, BC::x, vf11, vf11, vf0); // vmaxx.xyzw vf11, vf11, vf0
|
||||
c->vmini_bc(DEST::xyzw, BC::x, vf11, vf11, vf15); // vminix.xyzw vf11, vf11, vf15
|
||||
c->vftoi0(DEST::xyzw, vf11, vf11); // vftoi0.xyzw vf11, vf11
|
||||
c->mov128_gpr_vf(at, vf11); // qmfc2.i at, vf11
|
||||
c->ppach(at, at, at); // ppach at, at, at
|
||||
c->ppacb(at, at, at); // ppacb at, at, at
|
||||
c->sw(at, 1024, v1); // sw at, 1024(v1)
|
||||
c->daddiu(v1, v1, 4); // daddiu v1, v1, 4
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L37
|
||||
c->daddiu(a0, a0, -1); // daddiu a0, a0, -1
|
||||
if (bc) {goto block_20;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(v0) != 0; // bne v0, r0, L36
|
||||
c->daddiu(v0, v0, -1); // daddiu v0, v0, -1
|
||||
if (bc) {goto block_19;} // branch non-likely
|
||||
|
||||
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
||||
c->ld(fp, 8, sp); // ld fp, 8(sp)
|
||||
c->lwc1(f30, 68, sp); // lwc1 f30, 68(sp)
|
||||
c->lwc1(f28, 64, sp); // lwc1 f28, 64(sp)
|
||||
c->lq(gp, 48, sp); // lq gp, 48(sp)
|
||||
c->lq(s5, 32, sp); // lq s5, 32(sp)
|
||||
c->lq(s4, 16, sp); // lq s4, 16(sp)
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 80); // daddiu sp, sp, 80
|
||||
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() {
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
cache.setting_control = intern_from_c("*setting-control*").c();
|
||||
cache.atan = intern_from_c("atan").c();
|
||||
cache.cos = intern_from_c("cos").c();
|
||||
cache.ntsc = intern_from_c("ntsc").c();
|
||||
cache.pal = intern_from_c("pal").c();
|
||||
cache.ripple_update_waveform_offs = intern_from_c("ripple-update-waveform-offs").c();
|
||||
cache.sin = intern_from_c("sin").c();
|
||||
gLinkedFunctionTable.reg("ripple-create-wave-table", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace ripple_create_wave_table
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace ripple_apply_wave_table {
|
||||
struct Cache {
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
|
||||
bool bc = false;
|
||||
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 0, c);// lui v1, 28672
|
||||
c->daddiu(v1, v1, 1024); // daddiu v1, v1, 1024
|
||||
c->lwu(a1, 4, a0); // lwu a1, 4(a0)
|
||||
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
|
||||
c->lwu(a2, 8, a0); // lwu a2, 8(a0)
|
||||
c->lwu(a3, 12, a0); // lwu a3, 12(a0)
|
||||
c->lhu(a0, 18, a0); // lhu a0, 18(a0)
|
||||
c->addiu(t0, r0, 0); // addiu t0, r0, 0
|
||||
//beq r0, r0, L24 // beq r0, r0, L24
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_4; // branch always
|
||||
|
||||
|
||||
block_1:
|
||||
c->lbu(t1, 0, a3); // lbu t1, 0(a3)
|
||||
c->lbu(t3, 0, a1); // lbu t3, 0(a1)
|
||||
c->daddiu(t3, t3, 3); // daddiu t3, t3, 3
|
||||
c->dsrl(t3, t3, 2); // dsrl t3, t3, 2
|
||||
c->dsll(t3, t3, 4); // dsll t3, t3, 4
|
||||
c->daddu(t2, t2, t3); // daddu t2, t2, t3
|
||||
c->mov64(t4, t2); // or t4, t2, r0
|
||||
c->mov64(t3, t1); // or t3, t1, r0
|
||||
c->mov64(t5, t4); // or t5, t4, r0
|
||||
c->mov64(t4, a2); // or t4, a2, r0
|
||||
|
||||
block_2:
|
||||
c->lb(t6, 0, t4); // lb t6, 0(t4)
|
||||
c->lb(t7, 1, t4); // lb t7, 1(t4)
|
||||
c->andi(t6, t6, 15); // andi t6, t6, 15
|
||||
c->andi(t7, t7, 15); // andi t7, t7, 15
|
||||
c->sll(t7, t7, 4); // sll t7, t7, 4
|
||||
c->daddu(t6, t6, t7); // daddu t6, t6, t7
|
||||
c->sll(t6, t6, 2); // sll t6, t6, 2
|
||||
c->daddu(t8, t6, v1); // daddu t8, t6, v1
|
||||
c->lb(t6, 0, t8); // lb t6, 0(t8)
|
||||
c->lb(t7, 1, t8); // lb t7, 1(t8)
|
||||
c->lb(t8, 2, t8); // lb t8, 2(t8)
|
||||
c->sb(t6, 7, t5); // sb t6, 7(t5)
|
||||
c->sb(t7, 2, t5); // sb t7, 2(t5)
|
||||
c->sb(t8, 10, t5); // sb t8, 10(t5)
|
||||
c->daddiu(t3, t3, -1); // daddiu t3, t3, -1
|
||||
c->daddiu(t4, t4, 2); // daddiu t4, t4, 2
|
||||
bc = c->sgpr64(t3) != 0; // bne t3, r0, L23
|
||||
c->daddiu(t5, t5, 12); // daddiu t5, t5, 12
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
c->lbu(t3, 2, a1); // lbu t3, 2(a1)
|
||||
c->lbu(t4, 1, a1); // lbu t4, 1(a1)
|
||||
c->daddiu(t4, t4, 3); // daddiu t4, t4, 3
|
||||
c->dsrl(t4, t4, 2); // dsrl t4, t4, 2
|
||||
c->daddu(t3, t3, t4); // daddu t3, t3, t4
|
||||
c->dsll(t3, t3, 4); // dsll t3, t3, 4
|
||||
c->daddu(t2, t2, t3); // daddu t2, t2, t3
|
||||
c->lbu(t3, 3, a1); // lbu t3, 3(a1)
|
||||
c->dsll(t3, t3, 1); // dsll t3, t3, 1
|
||||
c->daddiu(t3, t3, 4); // daddiu t3, t3, 4
|
||||
c->daddu(a1, a1, t3); // daddu a1, a1, t3
|
||||
c->dsll(t1, t1, 1); // dsll t1, t1, 1
|
||||
c->daddiu(t1, t1, 15); // daddiu t1, t1, 15
|
||||
c->andi(t1, t1, 65520); // andi t1, t1, 65520
|
||||
c->daddu(a2, a2, t1); // daddu a2, a2, t1
|
||||
c->daddiu(a3, a3, 2); // daddiu a3, a3, 2
|
||||
c->mov64(t1, a3); // or t1, a3, r0
|
||||
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
|
||||
|
||||
block_4:
|
||||
c->slt(t1, t0, a0); // slt t1, t0, a0
|
||||
bc = c->sgpr64(t1) != 0; // bne t1, r0, L22
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
c->mov64(v0, s7); // or v0, s7, 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() {
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
gLinkedFunctionTable.reg("ripple-apply-wave-table", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace ripple_apply_wave_table
|
||||
} // namespace Mips2C
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace ripple_matrix_scale {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->mov128_vf_gpr(vf1, a3); // qmtc2.i vf1, a3
|
||||
c->mov128_vf_gpr(vf2, a2); // qmtc2.i vf2, a2
|
||||
c->mov128_vf_gpr(vf3, t0); // qmtc2.i vf3, t0
|
||||
c->mov64(v1, t1); // or v1, t1, r0
|
||||
|
||||
block_1:
|
||||
c->lqc2(vf5, 16, a0); // lqc2 vf5, 16(a0)
|
||||
c->lqc2(vf6, 48, a0); // lqc2 vf6, 48(a0)
|
||||
c->lqc2(vf7, 64, a0); // lqc2 vf7, 64(a0)
|
||||
c->lqc2(vf8, 96, a0); // lqc2 vf8, 96(a0)
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf4, vf5, vf2); // vmulx.xyzw vf4, vf5, vf2
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf5, vf5, vf1); // vmulx.xyzw vf5, vf5, vf1
|
||||
c->lq(a2, 0, a0); // lq a2, 0(a0)
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf7, vf7, vf3); // vmulx.xyzw vf7, vf7, vf3
|
||||
c->lq(v1, 32, a0); // lq v1, 32(a0)
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf8, vf8, vf3); // vmulx.xyzw vf8, vf8, vf3
|
||||
c->sq(a2, 0, t1); // sq a2, 0(t1)
|
||||
c->lq(a2, 80, a0); // lq a2, 80(a0)
|
||||
c->vsub(DEST::xyzw, vf6, vf6, vf4); // vsub.xyzw vf6, vf6, vf4
|
||||
c->sq(v1, 32, t1); // sq v1, 32(t1)
|
||||
c->sqc2(vf5, 16, t1); // sqc2 vf5, 16(t1)
|
||||
c->sq(a2, 80, t1); // sq a2, 80(t1)
|
||||
c->daddiu(a1, a1, -1); // daddiu a1, a1, -1
|
||||
c->sqc2(vf7, 64, t1); // sqc2 vf7, 64(t1)
|
||||
c->addiu(a0, a0, 128); // addiu a0, a0, 128
|
||||
c->sqc2(vf6, 48, t1); // sqc2 vf6, 48(t1)
|
||||
c->addiu(t1, t1, 128); // addiu t1, t1, 128
|
||||
bc = c->sgpr64(a1) != 0; // bne a1, r0, L12
|
||||
c->sqc2(vf8, -32, t1); // sqc2 vf8, -32(t1)
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, 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
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
gLinkedFunctionTable.reg("ripple-matrix-scale", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace ripple_matrix_scale
|
||||
} // namespace Mips2C
|
||||
@@ -81,10 +81,6 @@ namespace generic_light_proc { extern void link(); }
|
||||
namespace generic_envmap_proc { extern void link(); }
|
||||
namespace high_speed_reject { extern void link(); }
|
||||
namespace generic_prepare_dma_single { extern void link(); }
|
||||
namespace ripple_create_wave_table { extern void link(); }
|
||||
namespace ripple_execute_init { extern void link(); }
|
||||
namespace ripple_apply_wave_table { extern void link(); }
|
||||
namespace ripple_matrix_scale { extern void link(); }
|
||||
namespace init_ocean_far_regs { extern void link(); }
|
||||
namespace render_ocean_quad { extern void link(); }
|
||||
namespace draw_large_polygon_ocean { extern void link(); }
|
||||
@@ -108,9 +104,6 @@ namespace shadow_xform_verts { extern void link(); }
|
||||
namespace draw_inline_array_instance_tie { extern void link(); }
|
||||
namespace draw_inline_array_prototype_tie_generic_asm { extern void link(); }
|
||||
namespace generic_tie_dma_to_spad_sync { extern void link(); }
|
||||
namespace generic_envmap_dproc { extern void link(); }
|
||||
namespace generic_interp_dproc { extern void link(); }
|
||||
namespace generic_no_light_dproc { extern void link(); }
|
||||
namespace generic_tie_convert { extern void link(); }
|
||||
} // namespace jak1
|
||||
|
||||
@@ -437,12 +430,7 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
|
||||
jak1::mercneric_convert::link, jak1::high_speed_reject::link}},
|
||||
{"generic-effect",
|
||||
{jak1::generic_prepare_dma_double::link, jak1::generic_light_proc::link,
|
||||
jak1::generic_envmap_proc::link, jak1::generic_prepare_dma_single::link,
|
||||
jak1::generic_envmap_dproc::link, jak1::generic_interp_dproc::link,
|
||||
jak1::generic_no_light_dproc::link}},
|
||||
{"ripple",
|
||||
{jak1::ripple_execute_init::link, jak1::ripple_create_wave_table::link,
|
||||
jak1::ripple_apply_wave_table::link, jak1::ripple_matrix_scale::link}},
|
||||
jak1::generic_envmap_proc::link, jak1::generic_prepare_dma_single::link}},
|
||||
{"ocean",
|
||||
{jak1::init_ocean_far_regs::link, jak1::render_ocean_quad::link,
|
||||
jak1::draw_large_polygon_ocean::link}},
|
||||
|
||||
@@ -19,23 +19,34 @@
|
||||
(defun transform-float-point ((in vector) (out vector4w))
|
||||
"Transform in with the cached camera registers, perform perspective division and GS offset and
|
||||
depth clamping, convert to 28.4 fixed point, store the result in out, and return out. The input
|
||||
precedes the output, unlike most destructive vector functions."
|
||||
precedes the output, unlike most destructive vector functions.
|
||||
This requires VU0 registers set up by init-for-transform"
|
||||
(with-vf0
|
||||
(with-vf (vf4 vf1 vf2 vf3 vf9 vf8 vf6)
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
(vf5 :class vf))
|
||||
(.lvf vf5 (&-> in quad))
|
||||
|
||||
;; set vf5 = vf * model-matrix
|
||||
(.mul.w.vf acc vf4 vf5)
|
||||
(.add.mul.x.vf acc vf1 vf5 acc)
|
||||
(.add.mul.y.vf acc vf2 vf5 acc)
|
||||
(.add.mul.z.vf vf5 vf3 vf5 acc)
|
||||
|
||||
;; perspective divide and apply vf9.x (fog scale)
|
||||
(.div.vf Q vf9 vf5 :fsf #b0 :ftf #b11)
|
||||
(.wait.vf)
|
||||
(.mul.vf.xyz vf5 vf5 Q)
|
||||
|
||||
;; add hvdf offset
|
||||
(.add.vf vf5 vf5 vf8)
|
||||
|
||||
;; clamp fog 0 - 255
|
||||
(.max.x.vf.w vf5 vf5 vf0)
|
||||
(.min.x.vf.w vf5 vf5 vf6)
|
||||
|
||||
;; convert to GS fixed point
|
||||
(vftoi4.xyzw vf5 vf5)
|
||||
(.svf (&-> out quad) vf5)
|
||||
out))))
|
||||
@@ -508,32 +519,17 @@
|
||||
(defun-debug add-debug-matrix ((enable-draw symbol) (bucket bucket-id) (xform matrix))
|
||||
"Draw the three two-meter basis axes of xform at its translation, using red for x, green for y,
|
||||
and blue for z. Return xform."
|
||||
(add-debug-vector enable-draw
|
||||
bucket
|
||||
(-> xform vector 3)
|
||||
(-> xform vector 0)
|
||||
(meters 2)
|
||||
(new 'static 'rgba :r #xff :a #x80))
|
||||
(add-debug-vector enable-draw
|
||||
bucket
|
||||
(-> xform vector 3)
|
||||
(-> xform vector 1)
|
||||
(meters 2)
|
||||
(new 'static 'rgba :g #xff :a #x80))
|
||||
(add-debug-vector enable-draw
|
||||
bucket
|
||||
(-> xform vector 3)
|
||||
(-> xform vector 2)
|
||||
(meters 2)
|
||||
(new 'static 'rgba :b #xff :a #x80))
|
||||
(add-debug-vector enable-draw bucket (-> xform vector 3) (-> xform vector 0) (meters 2) (static-rgba #xff 0 0 #x80))
|
||||
(add-debug-vector enable-draw bucket (-> xform vector 3) (-> xform vector 1) (meters 2) (static-rgba 0 #xff 0 #x80))
|
||||
(add-debug-vector enable-draw bucket (-> xform vector 3) (-> xform vector 2) (meters 2) (static-rgba 0 0 #xff #x80))
|
||||
xform)
|
||||
|
||||
(defun-debug add-debug-rot-matrix ((enable-draw symbol) (bucket bucket-id) (rotation matrix) (origin vector))
|
||||
"Draw the three two-meter basis axes of rotation at origin, using red for x, green for y, and blue
|
||||
for z. Return rotation."
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 0) (meters 2) (new 'static 'rgba :r #xff :a #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 1) (meters 2) (new 'static 'rgba :g #xff :a #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 2) (meters 2) (new 'static 'rgba :b #xff :a #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 0) (meters 2) (static-rgba #xff 0 0 #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 1) (meters 2) (static-rgba 0 #xff 0 #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> rotation vector 2) (meters 2) (static-rgba 0 0 #xff #x80))
|
||||
rotation)
|
||||
|
||||
;; WARN: Stack slot load at 32 mismatch: defined as size 4, got size 16
|
||||
@@ -564,31 +560,27 @@
|
||||
lines at both ends. An optional orientation rotates the local xz plane before translation."
|
||||
(if (not enable-draw) (return #f))
|
||||
(let ((angle start-angle)
|
||||
(start-point (new 'stack-no-clear 'vector)))
|
||||
(set! (-> start-point quad) (the-as uint128 0))
|
||||
(let ((end-point (new 'stack-no-clear 'vector)))
|
||||
(set! (-> end-point quad) (the-as uint128 0))
|
||||
(let ((i 0))
|
||||
(while (< i 12)
|
||||
(set! (-> start-point x) (* radius (sin angle)))
|
||||
(set! (-> start-point y) 0.0)
|
||||
(set! (-> start-point z) (* radius (cos angle)))
|
||||
(set! (-> start-point w) 1.0)
|
||||
(+! angle (the float (/ (the int (- end-angle start-angle)) 12)))
|
||||
(set! (-> end-point x) (* radius (sin angle)))
|
||||
(set! (-> end-point y) 0.0)
|
||||
(set! (-> end-point z) (* radius (cos angle)))
|
||||
(set! (-> end-point w) 1.0)
|
||||
(when orientation
|
||||
(vector-matrix*! start-point start-point orientation)
|
||||
(vector-matrix*! end-point end-point orientation))
|
||||
(vector+! start-point start-point center)
|
||||
(vector+! end-point end-point center)
|
||||
(add-debug-line #t bucket start-point end-point color #f (the-as rgba -1))
|
||||
(cond
|
||||
((zero? i) (add-debug-line #t bucket start-point center color #f (the-as rgba -1)))
|
||||
((= i 11) (add-debug-line #t bucket end-point center color #f (the-as rgba -1))))
|
||||
(+! i 1)))))
|
||||
(start-point (new-stack-vector0))
|
||||
(end-point (new-stack-vector0))
|
||||
(i 0))
|
||||
(while (< i 12)
|
||||
(let ((start start-point))
|
||||
(set-vector! start (* radius (sin angle)) 0.0 (* radius (cos angle)) 1.0))
|
||||
(+! angle (the float (/ (the int (- end-angle start-angle)) 12)))
|
||||
(let ((end end-point))
|
||||
(set-vector! end (* radius (sin angle)) 0.0 (* radius (cos angle)) 1.0))
|
||||
(when orientation
|
||||
(vector-matrix*! start-point start-point orientation)
|
||||
(vector-matrix*! end-point end-point orientation))
|
||||
(vector+! start-point start-point center)
|
||||
(vector+! end-point end-point center)
|
||||
(add-debug-line #t bucket start-point end-point color #f (the-as rgba -1))
|
||||
(cond
|
||||
((zero? i)
|
||||
(add-debug-line #t bucket start-point center color #f (the-as rgba -1)))
|
||||
((= i 11)
|
||||
(add-debug-line #t bucket end-point center color #f (the-as rgba -1))))
|
||||
(+! i 1)))
|
||||
#f)
|
||||
|
||||
(defun-debug add-debug-curve ((enable-draw symbol)
|
||||
@@ -602,16 +594,15 @@
|
||||
vertex over normalized progress from zero through one."
|
||||
(if (not enable-draw) (return #f))
|
||||
(let ((previous (new-stack-vector0))
|
||||
(current (new 'stack-no-clear 'vector)))
|
||||
(set! (-> current quad) (the-as uint128 0))
|
||||
(let ((segment-count (* num-cverts 4)))
|
||||
(curve-evaluate! current (-> knots 0) cverts num-cverts knots num-knots)
|
||||
(let ((i 0))
|
||||
(while (< i segment-count)
|
||||
(set! (-> previous quad) (-> current quad))
|
||||
(curve-evaluate! current (/ (the float (+ i 1)) (the float segment-count)) cverts num-cverts knots num-knots)
|
||||
(add-debug-line #t bucket previous current color #f (the-as rgba -1))
|
||||
(+! i 1)))))
|
||||
(current (new-stack-vector0))
|
||||
(segment-count (* num-cverts 4)))
|
||||
(curve-evaluate! current (-> knots 0) cverts num-cverts knots num-knots)
|
||||
(let ((i 0))
|
||||
(while (< i segment-count)
|
||||
(set! (-> previous quad) (-> current quad))
|
||||
(curve-evaluate! current (/ (the float (+ i 1)) (the float segment-count)) cverts num-cverts knots num-knots)
|
||||
(add-debug-line #t bucket previous current color #f (the-as rgba -1))
|
||||
(+! i 1))))
|
||||
#f)
|
||||
|
||||
(defun-debug add-debug-curve2 ((enable-draw symbol) (bucket bucket-id) (curve-data curve) (color rgba) (unused-option symbol))
|
||||
@@ -637,23 +628,21 @@
|
||||
highlight-index is drawn white while the remaining points use color."
|
||||
(when enable-draw
|
||||
(dotimes (i count)
|
||||
(let ((point (new 'stack-no-clear 'vector)))
|
||||
(set! (-> point quad) (the-as uint128 0))
|
||||
(let ((point (new-stack-vector0)))
|
||||
(set! (-> point quad) (-> points i quad))
|
||||
(if (!= fixed-y 0.0) (set! (-> point y) fixed-y))
|
||||
(let ((draw-text add-debug-text-3d)
|
||||
(draw-enabled #t)
|
||||
(draw-bucket bucket))
|
||||
(format (clear *temp-string*) "~d" i)
|
||||
(draw-text draw-enabled draw-bucket *temp-string* point (font-color white) (the-as vector2h #f)))
|
||||
(add-debug-x #t bucket point (if (= i highlight-index) (new 'static 'rgba :r #xff :g #xff :b #xff :a #x80) color)))))
|
||||
(if (!= fixed-y 0.0)
|
||||
(set! (-> point y) fixed-y))
|
||||
(add-debug-text-3d #t bucket (string-format "~d" i) point (font-color white) (the-as vector2h #f))
|
||||
(add-debug-x #t bucket point (if (= i highlight-index) (static-rgba #xff #xff #xff #x80) color)))))
|
||||
#f)
|
||||
|
||||
(defun-debug debug-percent-bar ((enable-draw symbol) (bucket bucket-id) (x int) (y int) (fraction float) (color rgba))
|
||||
"Draw a 255-pixel background bar and a ten-pixel-high colored fill at screen position x,y. The
|
||||
fill width is 255 times fraction."
|
||||
(if (not enable-draw) (return #f))
|
||||
(with-dma-buffer-add-bucket ((dma-buff (-> *display* frames (-> *display* on-screen) frame debug-buf)) bucket) :bucket-group (-> *display* frames (-> *display* on-screen) frame bucket-group) (draw-sprite2d-xy dma-buff x y 255 14 (new 'static 'rgba :a #x40)) (draw-sprite2d-xy dma-buff x (+ y 2) (the int (* 255.0 fraction)) 10 color))
|
||||
(with-dma-buffer-add-bucket ((dma-buff (-> (current-frame) debug-buf)) bucket)
|
||||
(draw-sprite2d-xy dma-buff x y 255 14 (static-rgba 0 0 0 #x40))
|
||||
(draw-sprite2d-xy dma-buff x (+ y 2) (the int (* 255.0 fraction)) 10 color))
|
||||
#f)
|
||||
|
||||
(defun-debug debug-pad-display ((pad cpad-info))
|
||||
@@ -716,20 +705,14 @@
|
||||
the level-scaled endpoint. The sphere color is derived from the light color."
|
||||
(if (not enable-draw) (return #f))
|
||||
(when (!= (-> light-data levels x) 0.0)
|
||||
(add-debug-vector enable-draw
|
||||
bucket
|
||||
origin
|
||||
(-> light-data direction)
|
||||
(meters 3)
|
||||
(new 'static 'rgba :r #xff :g #xff :b #xff :a #x80))
|
||||
(add-debug-vector enable-draw bucket origin (-> light-data direction) (meters 3) (static-rgba #xff #xff #xff #x80))
|
||||
(let ((position (vector+*! (new-stack-vector0) origin (-> light-data direction) (* 12288.0 (-> light-data levels x))))
|
||||
(packed-color (logior (logior (logior (shr (shl (the int (* 128.0 (-> light-data color w))) 56) 32)
|
||||
(shr (shl (the int (* 128.0 (-> light-data color z))) 56) 40))
|
||||
(shr (shl (the int (* 128.0 (-> light-data color y))) 56) 48))
|
||||
(shr (shl (the int (* 128.0 (-> light-data color x))) 56) 56))))
|
||||
(format (clear *temp-string*) "~S ~,,2f" label (-> light-data levels x))
|
||||
(let ((text *temp-string*))
|
||||
(add-debug-text-sphere enable-draw bucket position (* 2048.0 (-> light-data levels x)) text (the-as rgba packed-color)))))
|
||||
(packed-color (static-rgba (the int (* 128.0 (-> light-data color x)))
|
||||
(the int (* 128.0 (-> light-data color y)))
|
||||
(the int (* 128.0 (-> light-data color z)))
|
||||
(the int (* 128.0 (-> light-data color w)))))
|
||||
(text (string-format "~S ~,,2f" label (-> light-data levels x))))
|
||||
(add-debug-text-sphere enable-draw bucket position (* 2048.0 (-> light-data levels x)) text packed-color)))
|
||||
#f)
|
||||
|
||||
(defun-debug add-debug-lights ((enable-draw symbol) (bucket bucket-id) (lights (inline-array light)) (origin vector))
|
||||
@@ -809,26 +792,11 @@
|
||||
"Set the debug camera to the fixed position and rotation used to investigate DMA timeouts."
|
||||
(let ((position (new-stack-vector0))
|
||||
(rotation (new-stack-matrix0)))
|
||||
(set! (-> position x) -666764.4)
|
||||
(set! (-> position y) 21102.984)
|
||||
(set! (-> position z) 51613.348)
|
||||
(set! (-> position w) 1.0)
|
||||
(set! (-> rotation vector 0 x) -0.911)
|
||||
(set! (-> rotation vector 0 y) 0.0)
|
||||
(set! (-> rotation vector 0 z) 0.4122)
|
||||
(set! (-> rotation vector 0 w) 0.0)
|
||||
(set! (-> rotation vector 1 x) -0.0984)
|
||||
(set! (-> rotation vector 1 y) 0.971)
|
||||
(set! (-> rotation vector 1 z) -0.2174)
|
||||
(set! (-> rotation vector 1 w) 0.0)
|
||||
(set! (-> rotation vector 2 x) -0.4003)
|
||||
(set! (-> rotation vector 2 y) -0.2387)
|
||||
(set! (-> rotation vector 2 z) -0.8847)
|
||||
(set! (-> rotation vector 2 w) 0.0)
|
||||
(set! (-> rotation vector 3 x) 0.0)
|
||||
(set! (-> rotation vector 3 y) 0.0)
|
||||
(set! (-> rotation vector 3 z) 0.0)
|
||||
(set! (-> rotation vector 3 w) 1.0)
|
||||
(set-vector! position -666764.4 21102.984 51613.348 1.0)
|
||||
(set-vector! (-> rotation vector 0) -0.911 0.0 0.4122 0.0)
|
||||
(set-vector! (-> rotation vector 1) -0.0984 0.971 -0.2174 0.0)
|
||||
(set-vector! (-> rotation vector 2) -0.4003 -0.2387 -0.8847 0.0)
|
||||
(set-vector! (-> rotation vector 3) 0.0 0.0 0.0 1.0)
|
||||
(debug-set-camera-pos-rot! position rotation)))
|
||||
|
||||
(defun-debug display-file-info ()
|
||||
|
||||
@@ -15,15 +15,17 @@
|
||||
|
||||
;; note: changed for high fps
|
||||
|
||||
;; Bones.
|
||||
;; This file is a bit of a mess.
|
||||
;; It calculates skinning matrices for rendering, but also handles
|
||||
;; renderer-specific DMA generation for foreground rendering.
|
||||
|
||||
;; For bone calculations:
|
||||
;; There are 4 main functions used by the outside world:
|
||||
;; - bones-init. Call this before doing process-drawable DMA building.
|
||||
;; - draw-bones. Call this once for each process-drawable during DMA building.
|
||||
;; - bones-wrapup. Call this after all calls to draw-bones.
|
||||
;; the above 3 functions are done separate for different levels.
|
||||
;; - bones-mtx-calc-execute. Call this after all that.
|
||||
|
||||
;; It's more than just bones in here - submitting to merc is done from here.
|
||||
;; the above 3 functions are done separately for different levels.
|
||||
;; - bones-mtx-calc-execute then computes all bone matrices
|
||||
|
||||
(defglobalconstant BACKWARD_COMPAT_MERC_CLIP #f)
|
||||
|
||||
@@ -36,24 +38,11 @@
|
||||
:bitfield #t
|
||||
;; Write per-bone ripple deformation data after calculating the skinning matrices.
|
||||
(write-ripple-data 0)
|
||||
;; Use identity instead of camera rotation for screen-space bones. HUD draw paths set this.
|
||||
(no-cam-rot 1)
|
||||
(bncfl02 2) ;; bits 2-15 are unused in Jak 1
|
||||
(bncfl03 3)
|
||||
(bncfl04 4)
|
||||
(bncfl05 5)
|
||||
(bncfl06 6)
|
||||
(bncfl07 7)
|
||||
(bncfl08 8)
|
||||
(bncfl09 9)
|
||||
(bncfl10 10)
|
||||
(bncfl11 11)
|
||||
(bncfl12 12)
|
||||
(bncfl13 13)
|
||||
(bncfl14 14)
|
||||
(bncfl15 15))
|
||||
;; Use identity instead of camera rotation for screen-space bones. For HUD drawing.
|
||||
(no-cam-rot 1))
|
||||
|
||||
;; this type represents a "calculation" that will be performed at later time.
|
||||
;; this type represents a "calculation" that will be performed at later time,
|
||||
;; it computes all skinning matrices for a single geometry.
|
||||
(deftype bone-calculation (structure)
|
||||
((flags bone-calc-flags :offset-assert 0)
|
||||
(num-bones uint16 :offset-assert 2)
|
||||
@@ -203,15 +192,11 @@
|
||||
;; VU / DMA
|
||||
;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The scratchpad holds a terrain-context: a short header naming the level and its mood, then a work
|
||||
;; area each renderer overlays with its own record. The bone calculator's is bone-mem, and that is
|
||||
;; where the sixteen in every scratchpad address below comes from.
|
||||
;; Address helper for scratchpad access
|
||||
(defmacro bones-spr-offset (&rest path)
|
||||
`(+ (offset-of terrain-context work) (offset-of bone-memory ,@path)))
|
||||
|
||||
;; Two banks, each holding sixteen joints' bind poses, sixteen bone transforms, and sixteen finished
|
||||
;; 128-byte pris-mtx records. Only the first two arrays are declared in bone-buffer; the output area is
|
||||
;; the third field the type comments out, and it begins where the bone array ends.
|
||||
;; double-buffered output, holds 16 bones.
|
||||
(defmacro bones-spr-bank-output (bank)
|
||||
`(+ (bones-spr-offset buffer ,bank bone 0) (* 16 (type-size bone))))
|
||||
|
||||
@@ -222,28 +207,12 @@
|
||||
(defconstant BONES-SPR-BONE-B (bones-spr-offset buffer 1 bone 0))
|
||||
(defconstant BONES-SPR-OUTPUT-B (bones-spr-bank-output 1))
|
||||
|
||||
;; Sixteen bones per bank is what the two 4608-byte buffers hold, and it is also the unroll of the
|
||||
;; bank loop below.
|
||||
(defconstant BONES-PER-BANK 16)
|
||||
|
||||
;; Only the 64-byte bind-pose matrix of each 80-byte joint is wanted, so the joint transfer runs in
|
||||
;; DMA interleave mode with SQWC set to "copy four quadwords, skip one" -- see bones-set-sqwc. That is
|
||||
;; why the joint transfer's chcr differs from the bone and output transfers.
|
||||
;; Interleave copy is used to extract the bind-pose matrix (64 bytes) from each joint (80 bytes)
|
||||
(defconstant DMA-CHCR-START-INTERLEAVE (new 'static 'dma-chcr :mod 2 :str 1))
|
||||
|
||||
;; Poll an SPR channel until it stops. Twenty instructions, in this order:
|
||||
;;
|
||||
;; (label poll) 1 l.w of chcr
|
||||
;; ... 2..4 three no-ops, the load-delay gap plus slack
|
||||
;; ... 5 and.i against the start bit
|
||||
;; ... 6 no-op
|
||||
;; ... 7,8 b.z to ready with a no-op delay slot
|
||||
;; ... 9..18 ten no-ops
|
||||
;; ... 19,20 b back to poll with a no-op delay slot
|
||||
;; (label ready)
|
||||
;;
|
||||
;; The ten no-ops in the not-taken path are the point: a busy channel is re-read at a fixed, generous
|
||||
;; interval instead of hammering the bus, and the whole thing is branch-free on the ready path.
|
||||
;; Poll an SPR channel until it stops.
|
||||
(defmacro dma-wait-spr! (poll-label ready-label channel status)
|
||||
`(begin
|
||||
(label ,poll-label)
|
||||
@@ -259,10 +228,9 @@
|
||||
(#when PC_PORT
|
||||
(define bones-vu0-block (new 'static 'vu-function :length 63 :qlength 32)))
|
||||
|
||||
;; Entry 0 composes one bone transform with its inverse bind pose, derives the inverse-transpose
|
||||
;; normal matrix, applies camera rotation, and leaves transformed position rows in vf13-vf16 and
|
||||
;; normal rows in vf9-vf11. Entry 54 rotates three light directions in vf4-vf6 by vf1-vf3 and
|
||||
;; returns them in vf7-vf9.
|
||||
|
||||
;; Entry 0: compute one bone transform, including normal matrix (writes mtx vf13-vf16, ntmx vf9-vf11)
|
||||
;; Entry 54: rotate light directions in vf4-vf6 by vf1-vf3, return in vf7-vf9
|
||||
(#unless PC_PORT
|
||||
(defvu0 bones-vu0-block
|
||||
(vu-pair (nop) (mulax.xyzw ACC vf05 vf01)) ;; 0: transform * bind-pose columns
|
||||
@@ -350,7 +318,6 @@
|
||||
(set! (-> (the-as dma-bank-control #x1000e000) sqwc) (new 'static 'dma-sqwc :sqwc #x1 :tqwc #x1)))
|
||||
(none))
|
||||
|
||||
;; ?? used by generic merc
|
||||
(define *merc-global-array* (new 'global 'merc-global-array))
|
||||
|
||||
(defun vu-lights<-light-group! ((arg0 vu-lights) (arg1 light-group))
|
||||
@@ -2570,7 +2537,7 @@
|
||||
(set! (-> dma-buf base) (the-as pointer (-> (the-as (pointer uint32) s2-0) 1)))
|
||||
(set! s2-0 (-> dma-buf base))
|
||||
(if (not (and (= f30-0 0.0) (= (-> sv-144 last-frame-scale) 0.0)))
|
||||
(ripple-make-request (the-as ripple-wave (-> sv-144 waveform)) (-> geom effect effect-idx)))
|
||||
(ripple-make-request (-> sv-144 waveform) (-> geom effect effect-idx)))
|
||||
(set! (-> sv-144 last-frame-scale) f30-0))))
|
||||
;; additional check on PC to force mercneric for blend shapes
|
||||
(#when PC_PORT
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(deftype ripple-request (structure)
|
||||
((waveform ripple-wave)
|
||||
((waveform ripple-wave-set)
|
||||
(effect merc-effect))
|
||||
:pack-me)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
(define *ripple-globals* (new 'global 'ripple-globals))
|
||||
|
||||
(defun ripple-make-request ((waveform ripple-wave) (effect merc-effect))
|
||||
(defun ripple-make-request ((waveform ripple-wave-set) (effect merc-effect))
|
||||
"Queue an effect to receive a waveform during this frame. Ignore duplicate effects and requests
|
||||
beyond the sixteen-entry buffer."
|
||||
(let ((request-count (-> *ripple-globals* count))
|
||||
@@ -31,7 +31,8 @@
|
||||
(already-queued 0))
|
||||
(when (< request-count 16)
|
||||
(dotimes (i request-count)
|
||||
(if (= effect (-> requests i effect)) (set! already-queued 1)))
|
||||
(if (= effect (-> requests i effect))
|
||||
(set! already-queued 1)))
|
||||
(when (zero? already-queued)
|
||||
(set! (-> requests request-count effect) effect)
|
||||
(set! (-> requests request-count waveform) waveform)
|
||||
@@ -54,11 +55,6 @@
|
||||
0
|
||||
(none))
|
||||
|
||||
(#when PC_PORT
|
||||
(def-mips2c ripple-execute-init (function none))
|
||||
(def-mips2c ripple-create-wave-table (function ripple-wave-set int))
|
||||
(def-mips2c ripple-apply-wave-table (function merc-effect symbol)))
|
||||
|
||||
;; Ripple generation uses VU0 data memory for its cosine interpolation table and the scratchpad for
|
||||
;; the 16 by 16 height/normal field. The EE versions retain the vector pipeline and packed vertex
|
||||
;; writes used by the renderer.
|
||||
@@ -504,6 +500,167 @@
|
||||
(nop!)
|
||||
(nop!))))
|
||||
|
||||
;; Plain-GOAL ripple implementation.
|
||||
(deftype ripple-cosine-table (structure)
|
||||
((entry vector 256 :inline)))
|
||||
|
||||
(define *ripple-cosine-table* (new 'global 'ripple-cosine-table))
|
||||
|
||||
(defun ripple-cosine-table-init ((table ripple-cosine-table))
|
||||
"Build the cosine interpolation table used by the plain-GOAL ripple generator. The first half
|
||||
covers zero through pi; negated copies in the second half complete the cycle."
|
||||
(let ((phase-step 0.024543691)
|
||||
(phase 0.024543691)
|
||||
(sample 1.0))
|
||||
(dotimes (i 128)
|
||||
;; Match the original degree-eight cosine polynomial. Keeping the delta beside each sample
|
||||
;; lets the table generator linearly interpolate the low eight phase bits.
|
||||
(let* ((phase-squared (square phase))
|
||||
(phase-fourth (square phase-squared))
|
||||
(phase-sixth (* phase-fourth phase-squared))
|
||||
(phase-eighth (square phase-fourth))
|
||||
(next-sample (+ 1.0
|
||||
(* phase-squared (-> *cos-poly-vec* x))
|
||||
(* phase-fourth (-> *cos-poly-vec* y))
|
||||
(* phase-sixth (-> *cos-poly-vec* z))
|
||||
(* phase-eighth (-> *cos-poly-vec* w))))
|
||||
(delta (- next-sample sample))
|
||||
(positive-entry (-> table entry i))
|
||||
(negative-entry (-> table entry (+ i 128))))
|
||||
(set! (-> positive-entry x) sample)
|
||||
(set! (-> positive-entry y) delta)
|
||||
(set! (-> negative-entry x) (- sample))
|
||||
(set! (-> negative-entry y) (- delta))
|
||||
(set! sample next-sample)
|
||||
(+! phase phase-step))))
|
||||
(none))
|
||||
|
||||
(ripple-cosine-table-init *ripple-cosine-table*)
|
||||
|
||||
(defun ripple-execute-init ()
|
||||
;; nothing to initialize in the re-written ripple implementation.
|
||||
(none))
|
||||
|
||||
(defun ripple-create-wave-table ((wave-set ripple-wave-set))
|
||||
"Sum the wave set into a 16 by 16 height grid, then pack height and x/z slopes into the
|
||||
scratchpad table consumed by MERC vertices. The grid wraps in both directions so it tiles."
|
||||
;; Build wave deltas
|
||||
(when (not (-> wave-set converted))
|
||||
(dotimes (i (-> wave-set count))
|
||||
(let* ((wave (-> wave-set wave i))
|
||||
(direction (atan (the float (-> wave zdiv)) (the float (-> wave xdiv))))
|
||||
(wavelength (/ 16.0
|
||||
(sqrtf (the float (+ (square (the int (-> wave xdiv)))
|
||||
(square (the int (-> wave zdiv))))))))
|
||||
(phase-per-cell (/ 65536.0 wavelength)))
|
||||
(set! (-> wave xmul) (* (cos direction) phase-per-cell))
|
||||
(set! (-> wave zmul) (* (sin direction) phase-per-cell))
|
||||
(cond
|
||||
((= (-> *setting-control* current video-mode) 'ntsc)
|
||||
(set! (-> wave delta) (* 0.016666668 (- phase-per-cell) (-> wave speed))))
|
||||
((= (-> *setting-control* current video-mode) 'pal)
|
||||
(set! (-> wave delta) (* 0.02 (- phase-per-cell) (-> wave speed)))))))
|
||||
(set! (-> wave-set converted) #t))
|
||||
|
||||
;; update wave phases
|
||||
(ripple-update-waveform-offs wave-set)
|
||||
(let ((heights (scratchpad-ptr float))
|
||||
(packed-table (scratchpad-ptr uint8 :offset 1024)))
|
||||
|
||||
;; initialize heights to zero
|
||||
(dotimes (grid-index 256)
|
||||
(set! (-> heights grid-index) 0.0))
|
||||
|
||||
;; Add each wave to the height table
|
||||
(dotimes (wave-index (-> wave-set count))
|
||||
(let* ((wave (-> wave-set wave wave-index))
|
||||
(phase-base (+ 16384.0 (* 0.00390625 (-> wave offs))))
|
||||
(phase-x-step (* 0.00390625 (-> wave xmul)))
|
||||
(phase-z-step (* 0.00390625 (-> wave zmul))))
|
||||
(dotimes (grid-z 16)
|
||||
(dotimes (grid-x 16)
|
||||
(let* ((grid-index (+ grid-x (* grid-z 16)))
|
||||
(phase (+ phase-base
|
||||
(* (the float grid-x) phase-x-step)
|
||||
(* (the float grid-z) phase-z-step)))
|
||||
(table-index (the int phase))
|
||||
(fraction (- phase (the float table-index)))
|
||||
(entry (-> *ripple-cosine-table* entry (logand table-index #xff)))
|
||||
(sample (+ (-> entry x) (* fraction (-> entry y)))))
|
||||
(+! (-> heights grid-index) (* sample (-> wave scale))))))))
|
||||
|
||||
;; Create packed vertex data in MERC vertex format [pos-y, nrm-x, nrm-z, PAD]
|
||||
(dotimes (grid-z 16)
|
||||
(dotimes (grid-x 16)
|
||||
(let* ((grid-index (+ grid-x (* grid-z 16)))
|
||||
(right-index (+ (mod (+ grid-x 1) 16) (* grid-z 16)))
|
||||
(down-index (+ grid-x (* (mod (+ grid-z 1) 16) 16)))
|
||||
(height (-> heights grid-index))
|
||||
(normal-scale (fmax 0.0 (-> wave-set normal-scale)))
|
||||
(packed-index (* grid-index 4)))
|
||||
;; height
|
||||
(set! (-> packed-table packed-index)
|
||||
(the-as uint (the int (fmax 0.0 (fmin 255.0 (+ 128.0 height))))))
|
||||
;; finite difference to get normal X
|
||||
(set! (-> packed-table (+ packed-index 1))
|
||||
(the-as uint
|
||||
(the int
|
||||
(fmax 0.0
|
||||
(fmin 255.0
|
||||
(+ 128.0 (* normal-scale (- height (-> heights right-index)))))))))
|
||||
;; finite difference to get normal Y
|
||||
(set! (-> packed-table (+ packed-index 2))
|
||||
(the-as uint
|
||||
(the int
|
||||
(fmax 0.0
|
||||
(fmin 255.0
|
||||
(+ 128.0 (* normal-scale (- height (-> heights down-index)))))))))
|
||||
(set! (-> packed-table (+ packed-index 3)) 128))))
|
||||
0))
|
||||
|
||||
(defun ripple-apply-wave-table ((effect merc-effect))
|
||||
"Patch the packed height and normal bytes of every rippled MERC vertex. Each two-byte query uses
|
||||
its low nibbles as x/z coordinates in the 16 by 16 table."
|
||||
(let ((packed-table (scratchpad-ptr uint8 :offset 1024))
|
||||
(fragment (-> effect frag-geo))
|
||||
(fragment-control (-> effect frag-ctrl))
|
||||
(queries (the-as (pointer uint8) (-> effect blend-data)))
|
||||
(blend-control (-> effect blend-ctrl)))
|
||||
(dotimes (fragment-index (the-as int (-> effect frag-count)))
|
||||
(let* ((vertex-count (-> blend-control blend-vtx-count))
|
||||
;; Unsigned-four data is qword-aligned immediately before the packed vertices.
|
||||
(vertex-data (the-as merc-vtx
|
||||
(&+ (the-as pointer fragment)
|
||||
(logand (* (+ (-> fragment-control unsigned-four-count) 3) 4)
|
||||
#xfff0)))))
|
||||
(dotimes (vertex-index (the-as int vertex-count))
|
||||
(let* ((table-x (logand (-> queries (* vertex-index 2)) #xf))
|
||||
(table-z (logand (-> queries (+ (* vertex-index 2) 1)) #xf))
|
||||
(table-index (* (+ table-x (* table-z 16)) 4))
|
||||
(vertex (the-as merc-vtx
|
||||
(&+ (the-as pointer vertex-data) (* vertex-index 12)))))
|
||||
(set! (-> vertex pos-y) (-> packed-table table-index))
|
||||
(set! (-> vertex nrm-x) (-> packed-table (+ table-index 1)))
|
||||
(set! (-> vertex nrm-z) (-> packed-table (+ table-index 2)))))
|
||||
|
||||
;; Advance the four packed streams independently; their fragment records have different
|
||||
;; alignment and variable-length tails.
|
||||
(set! fragment
|
||||
(the-as merc-fragment
|
||||
(&+ (the-as pointer vertex-data)
|
||||
(* (+ (-> fragment-control fp-qwc)
|
||||
(/ (+ (-> fragment-control lump-four-count) 3) 4))
|
||||
16))))
|
||||
(set! fragment-control
|
||||
(the-as merc-fragment-control
|
||||
(&+ (the-as pointer fragment-control)
|
||||
(+ 4 (* (-> fragment-control mat-xfer-count) 2)))))
|
||||
(set! queries
|
||||
(the-as (pointer uint8)
|
||||
(&+ queries (logand (+ (* vertex-count 2) 15) #xfff0))))
|
||||
(set! blend-control (the-as merc-blend-ctrl (&+ (the-as pointer blend-control) 2))))))
|
||||
#f)
|
||||
|
||||
(defun ripple-execute ()
|
||||
"Build each requested waveform table once, apply it to every queued effect that shares that
|
||||
waveform, and clear the request list."
|
||||
@@ -520,10 +677,10 @@
|
||||
(protect ((-> *setting-control* current video-mode))
|
||||
(when (= (-> *setting-control* current video-mode) 'custom)
|
||||
(set! (-> *setting-control* current video-mode) 'ntsc))
|
||||
(ripple-create-wave-table (the-as ripple-wave-set waveform)))
|
||||
(ripple-create-wave-table waveform))
|
||||
(while (!= match-index request-count)
|
||||
(when (= waveform (-> requests match-index waveform))
|
||||
(ripple-apply-wave-table (-> requests match-index effect))
|
||||
(ripple-apply-wave-table (-> requests match-index effect))
|
||||
(set! (-> requests match-index waveform) #f))
|
||||
(+! match-index 1))))
|
||||
(+! request-index 1)))
|
||||
@@ -531,9 +688,6 @@
|
||||
0)
|
||||
(none))
|
||||
|
||||
(#when PC_PORT
|
||||
(def-mips2c ripple-matrix-scale (function pointer int float float float pointer none)))
|
||||
|
||||
(defun-debug ripple-add-debug-sphere ((drawable process-drawable) (grid-point vector) (x-slope float) (z-slope float))
|
||||
"Transform one local ripple-grid point by the drawable's inverse yaw and root translation, then
|
||||
draw a debug sphere at the resulting world position. x-slope and z-slope displace the local x/z
|
||||
|
||||
@@ -4874,7 +4874,4 @@
|
||||
(def-mips2c generic-prepare-dma-single (function none))
|
||||
(def-mips2c generic-prepare-dma-double (function none))
|
||||
(def-mips2c generic-light-proc (function none))
|
||||
(def-mips2c generic-envmap-proc (function none))
|
||||
(def-mips2c generic-envmap-dproc (function none))
|
||||
(def-mips2c generic-interp-dproc (function none))
|
||||
(def-mips2c generic-no-light-dproc (function none)))
|
||||
(def-mips2c generic-envmap-proc (function none)))
|
||||
|
||||
@@ -6,19 +6,6 @@
|
||||
;; Generic conversion calls this library at several entry points. Entry 0 lights four vertices,
|
||||
;; entry 48 calculates four environment-map coordinates, and entries 104 through 292 stage and
|
||||
;; transform packed TIE vertices in VU0 data memory.
|
||||
;;
|
||||
;; This is a library, not a pipeline: no main loop, eighteen independently callable entries, and no
|
||||
;; constants of its own beyond what the EE crosses in. It is uploaded at program address zero, so a
|
||||
;; callms immediate is an index into the instruction pairs below.
|
||||
;;
|
||||
;; Both of the four-vertex entries run a group behind the caller, so the values the EE collects after a
|
||||
;; call belong to the group it submitted on the previous call. The caller therefore stores results from
|
||||
;; before the loop body's own call, and the drain entries exist purely to publish the last group. The
|
||||
;; two get there differently, though. Entry 0 opens by copying vf17-vf20 into vf21-vf24 outright. Entry
|
||||
;; 48 has no such copy: its last two pairs start the fourth vertex's arithmetic and the first thirteen
|
||||
;; pairs of the next call finish it, with vf05-vf08, vf29 and vf30 carrying the pipeline across the call
|
||||
;; boundary. Two consequences of that for a caller - its first call's output is garbage, so it must call
|
||||
;; twice before reading anything, and no other VU0 entry may be used between two entry-48 calls.
|
||||
(defconstant GENERIC-VU0-LIGHT 0) ;; light four vertices
|
||||
(defconstant GENERIC-VU0-ENVMAP 48) ;; four reflected environment-map coordinates
|
||||
|
||||
|
||||
@@ -1322,29 +1322,17 @@
|
||||
"Fill the Generic VU1 constant block from the active camera and select alpha blending for its
|
||||
triangle-strip GIF tag."
|
||||
(let ((camera *math-camera*))
|
||||
(set-vector!
|
||||
(-> constants fog)
|
||||
(-> camera pfog0)
|
||||
(-> camera fog-min)
|
||||
(-> camera fog-max)
|
||||
3071.0))
|
||||
(set-vector! (-> constants fog) (-> camera pfog0) (-> camera fog-min) (-> camera fog-max) 3071.0))
|
||||
(set! (-> constants adgif tag) (new 'static 'gif-tag64 :nloop #x7 :nreg #x1))
|
||||
(set! (-> constants adgif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d)))
|
||||
(set! (-> constants adgif regs) (gs-reg-list a+d))
|
||||
(set! (-> constants giftag tag)
|
||||
(new 'static
|
||||
'gif-tag64
|
||||
:pre #x1
|
||||
:nreg #x3
|
||||
:prim
|
||||
(new 'static
|
||||
'gs-prim
|
||||
:prim (gs-prim-type tri-strip)
|
||||
:iip #x1
|
||||
:tme #x1
|
||||
:fge #x1
|
||||
:abe alpha-blend)))
|
||||
(set! (-> constants giftag regs)
|
||||
(new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2)))
|
||||
(new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe alpha-blend)))
|
||||
(set! (-> constants giftag regs) (gs-reg-list st rgbaq xyzf2))
|
||||
(vector-copy! (-> constants hvdf-offset) (-> *math-camera* hvdf-off))
|
||||
(vector-copy! (-> constants hmge-scale) (-> *math-camera* hmge-scale))
|
||||
(vector-copy! (-> constants invh-scale) (-> *math-camera* inv-hmge-scale))
|
||||
@@ -1382,65 +1370,37 @@
|
||||
(upload-packet (the-as dma-packet (-> buffer base))))
|
||||
(set! (-> upload-packet dma) (new 'static 'dma-tag :qwc #x3 :id (dma-tag-id cnt)))
|
||||
(set! (-> upload-packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> upload-packet vif1)
|
||||
(new 'static 'vif-tag :imm #x3 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> upload-packet vif1) (new 'static 'vif-tag :imm #x3 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> buffer base) (the-as pointer (&+ upload-packet 16))))
|
||||
(let* ((buffer dma-buf)
|
||||
(direct-tag (the-as gs-gif-tag (-> buffer base))))
|
||||
(set! (-> direct-tag tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x2))
|
||||
(set! (-> direct-tag regs)
|
||||
(new 'static
|
||||
'gif-tag-regs
|
||||
:regs0 (gif-reg-id a+d)
|
||||
:regs1 (gif-reg-id a+d)
|
||||
:regs2 (gif-reg-id a+d)
|
||||
:regs3 (gif-reg-id a+d)
|
||||
:regs4 (gif-reg-id a+d)
|
||||
:regs5 (gif-reg-id a+d)
|
||||
:regs6 (gif-reg-id a+d)
|
||||
:regs7 (gif-reg-id a+d)
|
||||
:regs8 (gif-reg-id a+d)
|
||||
:regs9 (gif-reg-id a+d)
|
||||
:regs10 (gif-reg-id a+d)
|
||||
:regs11 (gif-reg-id a+d)
|
||||
:regs12 (gif-reg-id a+d)
|
||||
:regs13 (gif-reg-id a+d)
|
||||
:regs14 (gif-reg-id a+d)
|
||||
:regs15 (gif-reg-id a+d)))
|
||||
(set! (-> direct-tag regs) GIF_REGS_ALL_AD)
|
||||
(set! (-> buffer base) (the-as pointer (&+ direct-tag 16))))
|
||||
(let* ((buffer dma-buf)
|
||||
(gs-registers (-> buffer base)))
|
||||
(set! (-> (the-as (pointer gs-test) gs-registers) 0)
|
||||
(new 'static
|
||||
'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:afail #x1
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal)))
|
||||
(set! (-> (the-as (pointer uint64) gs-registers) 1) (the-as uint (gs-reg test-1)))
|
||||
(set! (-> (the-as (pointer gs-zbuf) gs-registers) 2) zbuf)
|
||||
(set! (-> (the-as (pointer uint64) gs-registers) 3) (the-as uint (gs-reg zbuf-1)))
|
||||
(set! (-> buffer base) (&+ gs-registers 32)))
|
||||
(dma-buffer-add-uint64 dma-buf
|
||||
(new 'static
|
||||
'gs-test
|
||||
:ate #x1
|
||||
:atst (gs-atest greater-equal)
|
||||
:aref #x26
|
||||
:afail #x1
|
||||
:zte #x1
|
||||
:ztst (gs-ztest greater-equal))
|
||||
(the-as uint (gs-reg test-1))
|
||||
zbuf
|
||||
(the-as uint (gs-reg zbuf-1)))
|
||||
(generic-add-constants dma-buf alpha-blend)
|
||||
;; MSCALF with a zero immediate: entry GENERIC-VU1-INIT, which loads the constant block we just
|
||||
;; uploaded and then falls through into the reset entry.
|
||||
(let* ((buffer dma-buf)
|
||||
(start-packet (the-as dma-packet (-> buffer base))))
|
||||
(set! (-> start-packet dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> start-packet vif0)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> start-packet vif0) (new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> start-packet vif1) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
(set! (-> buffer base) (the-as pointer (&+ start-packet 16))))
|
||||
(let ((vif-state (the-as (pointer int32) (-> dma-buf base))))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 0)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 1)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd offset)))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 0) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 1) (new 'static 'vif-tag :cmd (vif-cmd offset)))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 2) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 3)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> (the-as (pointer vif-tag) vif-state) 3) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> vif-state 4) 0)
|
||||
(set! (-> vif-state 5) 0)
|
||||
(set! (-> vif-state 6) 0)
|
||||
|
||||
@@ -6,30 +6,25 @@
|
||||
(require "engine/gfx/lights.gc")
|
||||
(require "engine/gfx/generic/generic-h.gc")
|
||||
|
||||
;; A generic sink is a bucket plus the VU1 buffer rotation belonging to that bucket. There is one per
|
||||
;; place in the draw order where converted foreground geometry can be inserted: level 0, level 1, and
|
||||
;; default each contribute a tfrag sink and a pris sink, then shrub, then the two level water sinks.
|
||||
;; A sink outlives a single conversion pass - MERC and TIE can both feed the same bucket in one frame
|
||||
;; - which is why the buffer addresses are kept here and not in the scratchpad work area.
|
||||
;; A generic sink is a bucket plus the VU1 buffer rotation belonging to that bucket.
|
||||
;; There's one per level x texture-group pair, plus one for shrub.
|
||||
;; Both MERC and TIE can submit to these and VU1 buffer state must be consistent,
|
||||
;; so these are stored globally instead of in rendering code like normal.
|
||||
(define *generic-foreground-sinks*
|
||||
(new 'static 'boxed-array :type generic-dma-foreground-sink :length 0 :allocated-length 9))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 0) (-> *level* level0 tfrag-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 1) (-> *level* level0 pris-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 2) (-> *level* level1 tfrag-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 3) (-> *level* level1 pris-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 4) (-> *level* level-default tfrag-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 5) (-> *level* level-default pris-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 6) (new 'static 'generic-dma-foreground-sink :bucket (bucket-id shrub-generic1)))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 7) (-> *level* level0 water-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(set! (-> *generic-foreground-sinks* 8) (-> *level* level1 water-tex-foreground-sink-group generic-sink))
|
||||
|
||||
(defun generic-dma-foreground-sink-init ((sink generic-dma-foreground-sink))
|
||||
|
||||
@@ -7,37 +7,33 @@
|
||||
(require "kernel/gstring-h.gc")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
;; BLERC applies animated blend targets to packed MERC vertices. It is used heavily for facial
|
||||
;; expressions, but the format can deform any marked vertices. Animation data supplies one signed
|
||||
;; coefficient per target; the active target deltas are accumulated with the base vertex and the
|
||||
;; result is clamped back into MERC's packed byte layout.
|
||||
;; BLERC applies animated blend targets to packed MERC vertices for facial animation.
|
||||
;; The animation data specifies a weight for each target and the BLERC code modifies
|
||||
;; the MERC vertices in place, overwriting them with interpolated targets from BLERC
|
||||
;; data.
|
||||
;;
|
||||
;; Work is gathered into one DMA chain during drawable updates. blerc-execute streams that chain
|
||||
;; through the two 8 KiB scratchpad halves, computes one block while the next is arriving, and
|
||||
;; copies completed vertices back to the fragment's lump data. The MERC renderer therefore sees the
|
||||
;; updated positions and normals without needing a second geometry format.
|
||||
;; Work is gathered into one DMA chain during drawable updates. A later call to blerc-execute
|
||||
;; DMAs the chain to the scratchpad where the vertices are modified, then copied back.
|
||||
;;
|
||||
;; BLERC vertex modification races MERC rendering. It's unclear exactly how this worked,
|
||||
;; but it's likely that DMA bus arbitration prevented rednering from seeing half-updated frags.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(define *stats-blerc* #f)
|
||||
|
||||
;; Control data appended to one scratchpad output block. tag links the queued work blocks. overlap is
|
||||
;; the number of target rows that follow the base row, which is the same thing as the number of
|
||||
;; targets whose coefficient came out nonzero for this frame -- setup-blerc-chains-for-one-fragment
|
||||
;; counts exactly those, and blerc-a-fragment uses it as the length of the replicated-coefficient
|
||||
;; table and nothing else.
|
||||
;; control info for a single block
|
||||
(deftype blerc-block-header (structure)
|
||||
((tag generic-merc-tag :inline :offset-assert 0)
|
||||
(vtx-count uint32 :offset-assert 16)
|
||||
(overlap uint32 :offset-assert 20)
|
||||
(lump-dest uint32 :offset-assert 24)
|
||||
(lump-qwc uint32 :offset-assert 28))
|
||||
((tag generic-merc-tag :inline :offset-assert 0) ;; DMA chain of work blocks
|
||||
(vtx-count uint32 :offset-assert 16) ;; vertex count in block
|
||||
(overlap uint32 :offset-assert 20) ;; number of blend targets to use
|
||||
(lump-dest uint32 :offset-assert 24) ;; EE address of MERC fragment to modify
|
||||
(lump-qwc uint32 :offset-assert 28)) ;; number of quadwords in MERC data
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
:flag-assert #x900000020)
|
||||
|
||||
;; One scratchpad work block. output holds at most 53 packed 16-byte vertex records. The DMA chain
|
||||
;; that describes its base and target rows begins immediately after header, outside this type.
|
||||
;; single block of vertex data to process + control info.
|
||||
(deftype blerc-block (structure)
|
||||
((output uint8 848 :offset-assert 0)
|
||||
(header blerc-block-header :inline :offset-assert 848))
|
||||
@@ -45,9 +41,8 @@
|
||||
:size-assert #x370
|
||||
:flag-assert #x900000370)
|
||||
|
||||
;; One quadword per active blend target, each holding that target's signed coefficient replicated into
|
||||
;; all eight halfword lanes so PMADDH can take it directly. blerc-a-fragment builds it in *gsf-buffer*
|
||||
;; at the start of every block; forty is the most targets a MERC asset declares.
|
||||
;; cache of broadcasted target weights. repl-mult[i] stores the 16-bit weight replicated 8 times for
|
||||
;; target i.
|
||||
(deftype blerc-dcache (structure)
|
||||
((repl-mult vector 40 :inline :offset-assert 0))
|
||||
:method-count-assert 9
|
||||
@@ -56,22 +51,20 @@
|
||||
|
||||
;; Per-frame chain endpoints and optional range/workload statistics.
|
||||
(deftype blerc-globals (structure)
|
||||
((first uint32 :offset-assert 0)
|
||||
(next uint32 :offset-assert 4)
|
||||
(min-val int16 :offset-assert 8)
|
||||
((first uint32 :offset-assert 0) ;; DMA chain start
|
||||
(next uint32 :offset-assert 4) ;; DMA chain current pointer
|
||||
(min-val int16 :offset-assert 8) ;; min/max value seen, used for debug
|
||||
(max-val int16 :offset-assert 10)
|
||||
(fragment-count int32 :offset-assert 12)
|
||||
(vtx-count int32 :offset-assert 16)
|
||||
(target-vtx-count int32 :offset-assert 20))
|
||||
(fragment-count int32 :offset-assert 12) ;; merc fragments
|
||||
(vtx-count int32 :offset-assert 16) ;; output vertices written
|
||||
(target-vtx-count int32 :offset-assert 20));; blend target vertices read
|
||||
:method-count-assert 9
|
||||
:size-assert #x18
|
||||
:flag-assert #x900000018)
|
||||
|
||||
(define *blerc-globals* (new 'global 'blerc-globals))
|
||||
|
||||
;; BLERC assigns block-a to scratchpad address 0 and block-b to address 8192. dummy is the first
|
||||
;; half's variable DMA-chain area. The second half's chain likewise continues beyond block-b and
|
||||
;; therefore past the declared end of this type into the remainder of the 16 KiB scratchpad.
|
||||
;; Scratchpad memory layout. dummy, and the data after block-b are used for DMA memory.
|
||||
(deftype blerc-context (structure)
|
||||
((block-a blerc-block :inline :offset-assert 0)
|
||||
(dummy uint8 7312 :offset-assert 880)
|
||||
@@ -80,32 +73,23 @@
|
||||
:size-assert #x2370
|
||||
:flag-assert #x900002370)
|
||||
|
||||
;; Both halves of the scratchpad hold a blerc-block, and the second one is reached by adding this.
|
||||
;; Nothing else in blerc-context is addressed, so the offset comes from the type.
|
||||
|
||||
(defconstant BLERC-BLOCK-B (offset-of blerc-context block-b))
|
||||
|
||||
;; The DMA payload for a block is appended immediately after its header, and DMAtag transfer is on,
|
||||
;; so the source chain's tags land in the scratchpad too. The first tag quadword is therefore always
|
||||
;; here, and the index row it introduces at +16.
|
||||
;; Offset of transferred data (after header)
|
||||
(defconstant BLERC-SPR-CHAIN (+ (offset-of blerc-block header) (type-size blerc-block-header)))
|
||||
|
||||
;; chcr's start bit stays set while a channel is running, so it is both the poll mask and, on its
|
||||
;; own, "go" for an ordinary transfer.
|
||||
;; og:preserve-this these three want to live in dma-h.gc: shadow-cpu and the generic renderers all
|
||||
;; define or use the same values, and merc is simply the first file in load order that needs them.
|
||||
|
||||
;; constant to write to DMA register to start chain transfer
|
||||
(defconstant DMA-CHCR-START-SPR-CHAIN (new 'static 'dma-chcr :mod 1 :tte 1 :str 1))
|
||||
|
||||
;; A scratchpad address is only meaningful modulo 16 KiB to the SPR channels; the #x70000000 the EE
|
||||
;; uses to reach the same memory has to come off first.
|
||||
;; Mask to get scratchpad offsets from the EE scratchpad addresses starting at #x70000000
|
||||
(defconstant SPR-ADDRESS-MASK #x3fff)
|
||||
|
||||
;; The packed accumulator runs in 13 fractional bits: a base vertex byte is multiplied by 8192 and
|
||||
;; each target's signed byte delta by that target's signed coefficient, then the sum is shifted back
|
||||
;; down. blerc-data coefficients are built as +/- 64 * 64, so a coefficient of 64 * 64 is 1.0 here.
|
||||
|
||||
;; BLERC uses integer math. When accumulating, uses 13-bit fixed-point, so 8192 == 1
|
||||
(defconstant BLERC-FRACTION-BITS 13)
|
||||
(defconstant BLERC-ONE 8192)
|
||||
|
||||
(defconstant BLERC-FRACTION-BITS 13)
|
||||
|
||||
(defun-debug blerc-stats-init ()
|
||||
"Print the preceding BLERC frame's optional range and workload statistics, then reset them."
|
||||
@@ -117,8 +101,10 @@
|
||||
" ~D blend target computations (~F average)~%"
|
||||
(-> *blerc-globals* target-vtx-count)
|
||||
(/ (the float (-> *blerc-globals* target-vtx-count)) (the float (-> *blerc-globals* vtx-count))))
|
||||
(if (< (-> *blerc-globals* min-val) 0) (format *stdcon* "MINIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* min-val)))
|
||||
(if (< 255 (-> *blerc-globals* max-val)) (format *stdcon* "MAXIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* max-val))))
|
||||
(if (< (-> *blerc-globals* min-val) 0)
|
||||
(format *stdcon* "MINIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* min-val)))
|
||||
(if (< 255 (-> *blerc-globals* max-val))
|
||||
(format *stdcon* "MAXIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* max-val))))
|
||||
(let ((stats *blerc-globals*))
|
||||
(set! (-> stats min-val) 255)
|
||||
(set! (-> stats max-val) 0)
|
||||
@@ -131,7 +117,9 @@
|
||||
(defun blerc-init ()
|
||||
"Begin a BLERC frame by clearing the queued-chain head and tail after resetting statistics."
|
||||
(blerc-stats-init)
|
||||
(let ((state *blerc-globals*)) (set! (-> state first) (the-as uint 0)) (set! (-> state next) (the-as uint 0)))
|
||||
(let ((state *blerc-globals*))
|
||||
(set! (-> state first) (the-as uint 0))
|
||||
(set! (-> state next) (the-as uint 0)))
|
||||
0
|
||||
(none))
|
||||
|
||||
@@ -223,8 +211,7 @@
|
||||
;; ... the tag's fourth word
|
||||
;; BLERC-SPR-CHAIN + n*stride [tag][index row] the packed matrix/destination halfwords
|
||||
;;
|
||||
;; where n is header.overlap and stride is (tag qwc + 1) * 16 -- the row plus its own tag. Because
|
||||
;; every row is the same length the stride is read once, out of the first tag's low byte.
|
||||
;; where n is header.overlap and stride is (tag qwc + 1) * 16 -- the row plus its own tag.
|
||||
;;
|
||||
;; *gsf-buffer* is borrowed as the replicated-coefficient table, and the finished vertices are
|
||||
;; written to output at block + 0 for the caller to send back to header.lump-dest.
|
||||
@@ -412,8 +399,7 @@
|
||||
;; fromSPR copy that returns it -- so at steady state one block is arriving, one is being blended,
|
||||
;; and one is going back to main memory.
|
||||
;;
|
||||
;; The blend kernel in the middle is blerc-a-fragment inlined, because the whole point is to keep
|
||||
;; both DMA channels live across it.
|
||||
;; The blend kernel in the middle is blerc-a-fragment inlined.
|
||||
(rlet ((block :reg a0 :type blerc-block) ;; the half being blended
|
||||
(work :reg a2 :type blerc-block) ;; ... and the copy of that pointer the kernel uses
|
||||
(to-spr-a :reg a0 :type dma-bank-spr) ;; the toSPR channel, while block A is being seeded
|
||||
@@ -701,12 +687,16 @@
|
||||
"Interpolate the drawable's signed blend-target weights for its current animation frame and queue
|
||||
its level-zero MERC geometry. After BLERC is disabled, queue one zero-weight pass to restore the
|
||||
base vertices."
|
||||
|
||||
;; this function is what generates BLERC weights from animation data.
|
||||
;; first, check if animation is valid and blerc is enabled
|
||||
(let* ((root-channel (-> drawable skel root-channel 0))
|
||||
(anim-group (-> root-channel frame-group)))
|
||||
(when (and anim-group
|
||||
(> (-> drawable skel active-channels) 0)
|
||||
(zero? (-> drawable draw cur-lod))
|
||||
(logtest? (-> drawable skel status) (janim-status blerc)))
|
||||
;; find weights
|
||||
(let ((frame-weights (-> anim-group blerc-data)))
|
||||
(when frame-weights
|
||||
(let* ((merc-geo (-> drawable draw mgeo))
|
||||
@@ -717,7 +707,7 @@
|
||||
(target-weights (new 'stack-no-clear 'array 'int16 128)))
|
||||
(let ((target-count (-> merc-geo header blend-target-count)))
|
||||
(cond
|
||||
((< frame-index (+ (-> anim-group data 0 length) -1))
|
||||
((< frame-index (+ (-> anim-group data 0 length) -1)) ;; interpolation needed
|
||||
(let* ((next-frame-weights (&+ current-frame-weights target-count))
|
||||
(next-frame-scale (* 64.0 (- frame (the float frame-index))))
|
||||
(current-frame-scale (- 64.0 next-frame-scale)))
|
||||
@@ -727,16 +717,19 @@
|
||||
(+ (* (the float (+ (-> current-frame-weights i) -64)) current-frame-scale)
|
||||
(* (the float (+ (-> next-frame-weights i) -64)) next-frame-scale)))))))
|
||||
(else
|
||||
;; at end of animation, just grab last frame's weights
|
||||
(dotimes (i (the-as int target-count))
|
||||
(set! (-> target-weights i) (the-as int (* (+ (-> current-frame-weights i) -64) 64)))))))
|
||||
(setup-blerc-chains merc-geo target-weights (-> *display* frames (-> *display* on-screen) frame global-buf)))
|
||||
(setup-blerc-chains merc-geo target-weights (-> (current-frame) global-buf)))
|
||||
(logior! (-> drawable skel status) (janim-status blerc-done))
|
||||
(return (the-as object #f))))))
|
||||
|
||||
;; when disabling blerc, restore vertices to default.
|
||||
(when (logtest? (-> drawable skel status) (janim-status blerc-done))
|
||||
(logclear! (-> drawable skel status) (janim-status blerc-done))
|
||||
(setup-blerc-chains (-> drawable draw lod-set lod 0 geo)
|
||||
(new 'static 'array int16 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
|
||||
(-> *display* frames (-> *display* on-screen) frame global-buf)))
|
||||
(-> (current-frame) global-buf)))
|
||||
0)
|
||||
|
||||
;; PC uses the ported chain builder so scratchpad references target its mirror.
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
((and eye-ctrl (= (logand (the-as texture-id -256) (-> shader texture-id)) #x1cf06f00))
|
||||
;; eye slot 0
|
||||
(adgif-shader-login shader)
|
||||
(let ((eye-texture-block (get-eye-block (-> eye-ctrl eye-slot) 0))) (set! (-> shader tex0 tbp0) eye-texture-block))
|
||||
(let ((eye-texture-block (get-eye-block (-> eye-ctrl eye-slot) 0)))
|
||||
(set! (-> shader tex0 tbp0) eye-texture-block))
|
||||
(set! (-> shader tex0 tw) 5)
|
||||
(set! (-> shader tex0 th) 5)
|
||||
(set! (-> shader tex0 tcc) 1)
|
||||
@@ -48,7 +49,8 @@
|
||||
((and eye-ctrl (= (logand (the-as texture-id -256) (-> shader texture-id)) #x1cf07000))
|
||||
;; eye slot 1
|
||||
(adgif-shader-login shader)
|
||||
(let ((eye-texture-block (get-eye-block (-> eye-ctrl eye-slot) 1))) (set! (-> shader tex0 tbp0) eye-texture-block))
|
||||
(let ((eye-texture-block (get-eye-block (-> eye-ctrl eye-slot) 1)))
|
||||
(set! (-> shader tex0 tbp0) eye-texture-block))
|
||||
(set! (-> shader tex0 tw) 5)
|
||||
(set! (-> shader tex0 th) 5)
|
||||
(set! (-> shader tex0 tcc) 1)
|
||||
@@ -122,7 +124,8 @@
|
||||
"Account for the base art data, packed fragment control and geometry, blend targets, and eye
|
||||
animation owned by this MERC asset."
|
||||
;; do extra
|
||||
(if (-> this extra) (mem-usage (-> this extra) usage flags))
|
||||
(if (-> this extra)
|
||||
(mem-usage (-> this extra) usage flags))
|
||||
;; do merc ctrls in each effect:
|
||||
(let ((ctrl-mem (+ 32 80 (* (-> this header effect-count) 32))))
|
||||
(dotimes (effect-idx (the-as int (-> this header effect-count)))
|
||||
@@ -158,7 +161,7 @@
|
||||
|
||||
(defmethod login ((this merc-ctrl))
|
||||
"Log in every effect and eye shader, collect texture masks, and move the effect marked
|
||||
translucent to the final effect slot. Discard an unrelocated low-address eye-control value."
|
||||
translucent to the final effect slot."
|
||||
;; so we can find it
|
||||
(set! *merc-ctrl-header* (-> this header))
|
||||
;; clear masks. logging in will set these for textures we need.
|
||||
@@ -168,6 +171,7 @@
|
||||
(dotimes (effect-idx (the-as int (-> this header effect-count)))
|
||||
(login-adgifs (-> this effect effect-idx)))
|
||||
;; Translucent geometry occupies the final effect slot expected by the MERC submission code.
|
||||
;; This code swaps the last slot with the translucent geometry.
|
||||
(let ((translucent-effect-index -1)
|
||||
(effect-count (-> this header effect-count)))
|
||||
(dotimes (effect-index (the-as int effect-count))
|
||||
@@ -184,7 +188,7 @@
|
||||
;; login eye.
|
||||
(cond
|
||||
((not (logtest? -65536 (the-as int (-> this header eye-ctrl))))
|
||||
;; A linked eye-control pointer must not fit in the unrelocated low 16-bit form.
|
||||
;; Set eye-ctrl to 0 if it's not a valid pointer
|
||||
(set! (-> this header eye-ctrl) (the-as merc-eye-ctrl 0))
|
||||
0)
|
||||
(else
|
||||
@@ -314,16 +318,11 @@
|
||||
|
||||
(defun merc-vu1-init-buffer ((dma-bucket bucket-id) (test gs-test) (unused int))
|
||||
"If bucket-id received drawing commands, prepend a MERC VU1/GS initialization chain using test
|
||||
and link it to the bucket's previous head. The third argument is reserved and currently unused."
|
||||
;; Drawing has already filled the buckets, so this can skip empty ones and splice initialization
|
||||
;; only in front of work that will run. display-frame-finish calls this after the previous DMA is
|
||||
;; synchronized.
|
||||
(let ((bucket (-> *display* frames (-> *display* on-screen) frame bucket-group dma-bucket)))
|
||||
and link it to the bucket's previous head."
|
||||
(let ((bucket (-> (current-frame) bucket-group dma-bucket)))
|
||||
(when (!= bucket (-> bucket last))
|
||||
(let* ((dma-buf (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
(draw-data-start (-> dma-buf base)) ;; remember old beginning
|
||||
)
|
||||
;; Upload and initialize MERC, then send the bucket's GS TEST value through VIF DIRECT.
|
||||
(let* ((dma-buf (-> (current-frame) global-buf))
|
||||
(draw-data-start (-> dma-buf base)))
|
||||
(set! (-> dma-buf base) (the-as pointer (merc-vu1-initialize-chain (the-as dma-gif-packet (-> dma-buf base)))))
|
||||
(let* ((buffer-for-vif-tag dma-buf)
|
||||
(vif-packet (the-as object (-> buffer-for-vif-tag base))))
|
||||
@@ -331,18 +330,12 @@
|
||||
(set! (-> (the-as dma-packet vif-packet) vif0) (new 'static 'vif-tag))
|
||||
(set! (-> (the-as dma-packet vif-packet) vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> buffer-for-vif-tag base) (&+ (the-as pointer vif-packet) 16)))
|
||||
(let* ((buffer-for-gif-tag dma-buf)
|
||||
(gif-packet (the-as object (-> buffer-for-gif-tag base))))
|
||||
(set! (-> (the-as gs-gif-tag gif-packet) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> (the-as gs-gif-tag gif-packet) regs) GIF_REGS_ALL_AD)
|
||||
(set! (-> buffer-for-gif-tag base) (&+ (the-as pointer gif-packet) 16)))
|
||||
(dma-buffer-add-gif-tag dma-buf (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1) GIF_REGS_ALL_AD)
|
||||
(let* ((buffer-for-test dma-buf)
|
||||
(test-packet (-> buffer-for-test base)))
|
||||
(set! (-> (the-as (pointer gs-test) test-packet) 0) test)
|
||||
(set! (-> (the-as (pointer gs-reg64) test-packet) 1) (gs-reg64 test-1))
|
||||
(set! (-> buffer-for-test base) (&+ test-packet 16)))
|
||||
;; The new prefix jumps to the bucket's previous head; the bucket now starts at the saved
|
||||
;; global-buffer cursor.
|
||||
(let ((chain-tail (the-as object (-> dma-buf base))))
|
||||
(set! (-> (the-as dma-packet chain-tail) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> bucket next)))
|
||||
(set! (-> (the-as dma-packet chain-tail) vif0) (new 'static 'vif-tag))
|
||||
@@ -354,8 +347,7 @@
|
||||
|
||||
(defun merc-vu1-init-buffers ()
|
||||
"After drawing has filled the MERC buckets, prepend initialization chains to each nonempty
|
||||
enabled bucket. Ordinary buckets use alpha reference #x26; water uses #x80 and preserves the
|
||||
framebuffer on alpha failure."
|
||||
enabled bucket."
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask merc))
|
||||
(merc-vu1-init-buffer (bucket-id merc-tfrag-tex0)
|
||||
(new 'static 'gs-test :ate #x1 :atst (gs-atest greater-equal) :aref #x26 :zte #x1 :ztst (gs-ztest greater-equal))
|
||||
|
||||
@@ -4,15 +4,28 @@
|
||||
(require "engine/gfx/sprite/sprite.gc")
|
||||
(require "engine/gfx/math-camera.gc")
|
||||
|
||||
;; The sprite distortion renderer draws circular warps by sampling the current framebuffer around
|
||||
;; projected particle positions. The particle's turn count selects the radial mesh resolution, and
|
||||
;; its RGB lanes are reused as two radial scales and a framebuffer-sample displacement.
|
||||
;; Draws the heat-haze/water-warp particles. These distort
|
||||
;; a roughly circular area underneath the particle.
|
||||
|
||||
;; The mesh contains two conentric rings of vertices. Both rings have `turns` vertices.
|
||||
;; So `turns = 3` would be a triangle, turns = 4 is a square, etc.
|
||||
|
||||
;; There is a triangle fan at the center, using the vertices of the inner ring,
|
||||
;; and a triangle strip in between the inner and outer rings.
|
||||
;; The center and outer ring sample the framebuffer at their current position and
|
||||
;; the inner ring samples at an offset. This makes the center and edge of the distort sprite
|
||||
;; have no distortion, eliminating discontinuities and making the effect clearly centered around
|
||||
;; the sprite's center.
|
||||
|
||||
;; This geometry is controlled by the color: red controls the outer ring radius, g the inner,
|
||||
;; and b the sampling location of the inner ring. Setting g = b will effectively disable the effect,
|
||||
;; increasing the difference will increase the strength.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; For every turn count from 3 through 11, entry stores alternating screen-space directions and
|
||||
;; framebuffer texture-coordinate offsets. ientry maps a turn count to its first direction pair in
|
||||
;; VU1 memory. The final angle-zero pair closes the eleven-turn table.
|
||||
;; Unit spokes for every supported side count. Each spoke is stored twice: once in projected screen
|
||||
;; units for the mesh, then in framebuffer ST units for sampling. ientry points VU1 at the right set
|
||||
;; for a given `turns`; the last angle-zero pair closes the 11-sided set.
|
||||
(deftype sprite-distorter-sine-tables (basic)
|
||||
((aspx float)
|
||||
(aspy float)
|
||||
@@ -51,10 +64,8 @@
|
||||
(define *sprite-distorter-sine-tables* (new 'global 'sprite-distorter-sine-tables))
|
||||
|
||||
(defun sprite-distorter-generate-tables ()
|
||||
"Rebuild the radial warp direction tables for the current projection. For each turn count from
|
||||
3 through 11, store one screen-space direction and one framebuffer-texture offset per segment;
|
||||
adjacent tables share the angle-zero closing pair. These values are generated at runtime because
|
||||
both the on-screen directions and framebuffer sampling offsets depend on the active projection."
|
||||
"Build the spoke tables used by the distortion mesh. Each spoke has matching screen-space and
|
||||
framebuffer-ST directions, and the tables are rebuilt when the projection changes."
|
||||
(let ((tables *sprite-distorter-sine-tables*))
|
||||
(let ((entry-index 0)
|
||||
(turn-table-index 0)
|
||||
@@ -75,7 +86,7 @@
|
||||
(let ((angle (* 65536.0 (/ (the float i) (the float turns)))))
|
||||
(set-vector! (-> tables entry entry-index) (* (sin angle) aspect-x) (* (cos angle) aspect-y) 0.0 0.0)
|
||||
(let ((next-entry-index (+ entry-index 1)))
|
||||
;; The framebuffer is sampled on the 512 by 256 render grid.
|
||||
;; Same spoke as above, converted to the framebuffer's 512x256 ST grid.
|
||||
(set-vector! (-> tables entry next-entry-index)
|
||||
(* (/ aspect-x 512) (sin angle))
|
||||
(* (/ aspect-y 256) (cos angle))
|
||||
@@ -116,8 +127,8 @@
|
||||
(define sprite-distort-vu1-block (new 'static 'vu-function)))
|
||||
|
||||
(defun sprite-init-distorter ((dma-buff dma-buffer) (frame-base-pointer uint))
|
||||
"Configure the GS to sample the current framebuffer without writing depth, upload the radial warp
|
||||
tables, and load the sprite-distortion VU1 program."
|
||||
"Set up framebuffer sampling for the distortion pass, upload the spoke tables, and load its VU1
|
||||
program."
|
||||
;;(format #t "distorter: ~d~%" (-> *sprite-aux-list* entry))
|
||||
;; set up GS registers
|
||||
(dma-buffer-add-gs-set dma-buff
|
||||
@@ -165,10 +176,8 @@
|
||||
(none))
|
||||
|
||||
(defun sprite-draw-distorters ((dma-buff dma-buffer))
|
||||
"Project each enabled warp sprite with its selected camera or screen matrix, discard clipped
|
||||
sprites, replace an invalid radial turn count with 11, and shrink warps that cross the lower
|
||||
screen edge. Pack visible sprites into VU1 batches of at most 170 and draw each as radial
|
||||
framebuffer-texture strips."
|
||||
"Project the distortion particles, clip them, and send the visible discs to VU1 in batches of at
|
||||
most 170. Bad side counts fall back to 11, and discs are shrunk to stay on the framebuffer."
|
||||
(local-vars (clip-flags int) (warp-sprite sprite-vec-data-2d) (center-st pointer) (warp-params pointer))
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
@@ -226,8 +235,8 @@
|
||||
(set! clip-flags (vu-clip vf10 0)) ;; safe to just drop the higher bits.
|
||||
(b! (logtest? clip-flags 63) cfg-21 :delay (.add.vf vf1 vf1 vf9))
|
||||
(.max.x.vf.w vf1 vf1 vf0)
|
||||
;; Pack the projected center, its framebuffer ST coordinate, and the three warp scales
|
||||
;; consumed by one VU1 invocation.
|
||||
;; VU1 gets the projected centre, its matching framebuffer ST, and the particle's RGB:
|
||||
;; red = seamless outer radius, green = warp-ring radius, blue = sample radius there.
|
||||
(.svf (&-> (the-as vector packed-sprite) quad) vf1)
|
||||
(.svf (&-> (the-as vector warp-params) quad) vf2)
|
||||
(set! (-> (the-as vector packed-sprite) w) 255.0)
|
||||
@@ -244,9 +253,8 @@
|
||||
(bottom-t (+ center-t (* (-> (the-as (pointer float) warp-params)) projection-y)))
|
||||
(visible-scale 256.0)
|
||||
(warp-scale (-> (the-as (pointer float) warp-params))))
|
||||
;; Keep the warp inside the lower edge of the visible framebuffer and cap its radius at
|
||||
;; 128 pixels. Scale all three parameters together so the two radii and sampling
|
||||
;; displacement retain their proportions.
|
||||
;; Keep the outer edge inside the bottom of the framebuffer and cap it at 128 pixels.
|
||||
;; Scale all three radii together so the shape of the warp does not change.
|
||||
(if (< (the float (-> *video-parms* screen-sy)) bottom-t)
|
||||
(set! visible-scale (/ (- (the float (-> *video-parms* screen-sy)) center-t) projection-y)))
|
||||
(if (< 128.0 visible-scale) (set! visible-scale 128.0))
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
;; aux list
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The sparticle callback records a four-byte reference to each submitted CPU particle's 2D warp
|
||||
;; sprite here. The one-element data field is the start of trailing variable-length reference
|
||||
;; storage consumed by the framebuffer-distortion renderer.
|
||||
;; The aux list stores distortion particles that are handled by the separate
|
||||
;; sprite-distort renderer. Distorion sprites use the add-to-sprite-aux-list
|
||||
;; callback to add themselves to the aux list on each frame.
|
||||
|
||||
(deftype sprite-aux-list (basic)
|
||||
((num-entries int32) ;; capacity
|
||||
@@ -102,7 +102,7 @@
|
||||
0
|
||||
(none))
|
||||
|
||||
;; The sprite-frame-data is data transferred to VU1 and remains there for all chunks of sprites.
|
||||
;; Uploaded to VU1 once per frame
|
||||
(deftype sprite-frame-data (structure)
|
||||
((cdata vector 16 :inline)
|
||||
(hmge-scale vector :inline)
|
||||
@@ -145,9 +145,6 @@
|
||||
;; 904 its HVDF offset, or the first of the screen-space table
|
||||
;; 905 - 979 75 user HVDF offsets, uploaded only for the screen-space pass
|
||||
;; 980 - 1020 sprite-frame-data
|
||||
;;
|
||||
;; The chunk limit falls out of the input buffer: eight quadwords per sprite plus the header must fit
|
||||
;; in 400, and 48 is what the exporter and the sparticle system were built around.
|
||||
(defconstant SPRITE-VU-HEADER 0)
|
||||
|
||||
(defconstant SPRITE-VU-VEC-DATA (+ SPRITE-VU-HEADER 1))
|
||||
@@ -322,8 +319,7 @@
|
||||
(set! (-> data fog-clamp z) 2048.0)
|
||||
(none))
|
||||
|
||||
;; The original 854-pair VU1 program is documented in sprite-vu1.gc. PC rendering does not execute
|
||||
;; it, but the DMA-list builder still requires a valid object.
|
||||
;; The original 854-pair VU1 program is documented in sprite-vu1.gc.
|
||||
(#when PC_PORT
|
||||
(define sprite-vu1-block (new 'static 'vu-function)))
|
||||
|
||||
@@ -332,7 +328,7 @@
|
||||
;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; There are two global sprite arrays, one for 2D and one for 3D. Each has two groups, although 3D
|
||||
;; sprites only use group 0. Each sprite occupies three vector quadwords and five shader quadwords.
|
||||
;; sprites only use group 0.
|
||||
|
||||
(defmethod new sprite-array-2d ((allocation symbol) (type-to-make type) (group-0-size int) (group-1-size int))
|
||||
"Allocate a 2D sprite array with the requested capacity for its world and screen groups."
|
||||
|
||||
Reference in New Issue
Block a user