mirror of
https://github.com/open-goal/jak-project
synced 2026-09-10 04:22:13 -04:00
up to sync-info
This commit is contained in:
@@ -305,6 +305,14 @@
|
||||
"rewrite":
|
||||
"(dma-buffer-add-cnt-vif2 $buf 0 $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
// Explicit transfer sizes retain a qwc field in the dma-tag constructor.
|
||||
"name": "dma-buffer-add-cnt-vif2-qwc-object-packet",
|
||||
"match":
|
||||
"(let* (($alias $buf) ($packet (the-as object (-> $alias base)))) (set! (-> (the-as dma-packet $packet) dma) (new 'static 'dma-tag :qwc $qwc :id (dma-tag-id cnt))) (set! (-> (the-as dma-packet $packet) vif0) $vif0) (set! (-> (the-as dma-packet $packet) vif1) $vif1) (set! (-> $alias base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-cnt-vif2 $buf $qwc $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-cnt-vif2-typed-packet",
|
||||
"match":
|
||||
@@ -312,6 +320,41 @@
|
||||
"rewrite":
|
||||
"(dma-buffer-add-cnt-vif2 $buf 0 $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-cnt-vif2-qwc-typed-packet",
|
||||
"match":
|
||||
"(let* (($alias $buf) ($packet (the-as dma-packet (-> $alias base)))) (set! (-> $packet dma) (new 'static 'dma-tag :qwc $qwc :id (dma-tag-id cnt))) (set! (-> $packet vif0) $vif0) (set! (-> $packet vif1) $vif1) (set! (-> $alias base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-cnt-vif2 $buf $qwc $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-next-vif2-object-packet",
|
||||
"match":
|
||||
"(let (($packet (the-as object (-> $buf base)))) (set! (-> (the-as dma-packet $packet) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr $addr)) (set! (-> (the-as dma-packet $packet) vif0) $vif0) (set! (-> (the-as dma-packet $packet) vif1) $vif1) (set! (-> $buf base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-next-vif2 $buf 0 $addr $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-next-vif2-no-address-object-packet",
|
||||
"match":
|
||||
"(let (($packet (the-as object (-> $buf base)))) (set! (-> (the-as dma-packet $packet) dma) (new 'static 'dma-tag :id (dma-tag-id next))) (set! (-> (the-as dma-packet $packet) vif0) $vif0) (set! (-> (the-as dma-packet $packet) vif1) $vif1) (set! (-> $buf base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-next-vif2 $buf 0 0 $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-next-vif2-typed-packet",
|
||||
"match":
|
||||
"(let (($packet (the-as dma-packet (-> $buf base)))) (set! (-> $packet dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr $addr)) (set! (-> $packet vif0) $vif0) (set! (-> $packet vif1) $vif1) (set! (-> $buf base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-next-vif2 $buf 0 $addr $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-next-vif2-no-address-typed-packet",
|
||||
"match":
|
||||
"(let (($packet (the-as dma-packet (-> $buf base)))) (set! (-> $packet dma) (new 'static 'dma-tag :id (dma-tag-id next))) (set! (-> $packet vif0) $vif0) (set! (-> $packet vif1) $vif1) (set! (-> $buf base) (&+ (the-as pointer $packet) 16)))",
|
||||
"rewrite":
|
||||
"(dma-buffer-add-next-vif2 $buf 0 0 $vif0 $vif1)"
|
||||
},
|
||||
{
|
||||
"name": "dma-buffer-add-gif-tag-object-packet",
|
||||
"match":
|
||||
|
||||
@@ -172,8 +172,6 @@ set(RUNTIME_SOURCE
|
||||
mips2c/jak1_functions/sparticle.cpp
|
||||
mips2c/jak1_functions/test_func.cpp
|
||||
mips2c/jak1_functions/texture.cpp
|
||||
mips2c/jak1_functions/tfrag.cpp
|
||||
mips2c/jak1_functions/tie_methods.cpp
|
||||
mips2c/jak1_functions/time_of_day.cpp
|
||||
mips2c/jak2_functions/bones.cpp
|
||||
mips2c/jak2_functions/collide_cache.cpp
|
||||
|
||||
@@ -1,912 +0,0 @@
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/kernel/jak1/kscheme.h"
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
using namespace jak1;
|
||||
namespace Mips2C::jak1 {
|
||||
namespace draw_inline_array_tfrag {
|
||||
struct Cache {
|
||||
void* tfrag_work; // *tfrag-work*
|
||||
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
||||
void* transform_regs;
|
||||
} cache;
|
||||
|
||||
// t0 = tfrag work
|
||||
// t8 = tfrags
|
||||
// t9 = tfrag count
|
||||
// clang-format off
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
load_vfs_from_tf_regs(cache.transform_regs, c);
|
||||
bool bc = false;
|
||||
c->daddiu(sp, sp, -128); // daddiu sp, sp, -128
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->sq(s0, 16, sp); // sq s0, 16(sp)
|
||||
c->sq(s1, 32, sp); // sq s1, 32(sp)
|
||||
c->sq(s2, 48, sp); // sq s2, 48(sp)
|
||||
c->sq(s3, 64, sp); // sq s3, 64(sp)
|
||||
c->sq(s4, 80, sp); // sq s4, 80(sp)
|
||||
c->sq(s5, 96, sp); // sq s5, 96(sp)
|
||||
c->sq(gp, 112, sp); // sq gp, 112(sp)
|
||||
c->lui(t2, 5120); // lui t2, 5120 = (0x14000000)
|
||||
c->lw(v1, 4, a3); // lw v1, 4(a3)
|
||||
c->lui(t3, 4096); // lui t3, 4096 = (0x10000000)
|
||||
c->lui(t1, 4096); // lui t1, 4096 = (0x10000000)
|
||||
// Unknown instr: sync.l
|
||||
// Unknown instr: cache dxwbin v1, 0
|
||||
// Unknown instr: sync.l
|
||||
// Unknown instr: cache dxwbin v1, 1
|
||||
// Unknown instr: sync.l
|
||||
c->load_symbol(t0, cache.tfrag_work); // lw t0, *tfrag-work*(s7)
|
||||
c->ori(t4, t3, 54272); // ori t4, t3, 54272 = (0x1000D400) SPR TO
|
||||
c->ori(t1, t1, 53248); // ori t1, t1, 53248 = (0x1000D000) SPR FROM
|
||||
|
||||
// patched access to scratchpad
|
||||
// c->lui(t5, 28672); // lui t5, 28672 = (0x70000000)
|
||||
get_fake_spad_addr(t5, cache.fake_scratchpad_data, 0, c);
|
||||
|
||||
c->lqc2(vf3, 80, t0); // lqc2 vf3, 80(t0)
|
||||
c->sw(a3, 176, t0); // sw a3, 176(t0)
|
||||
c->ori(a3, t5, 2064); // ori a3, t5, 2064
|
||||
c->addiu(t3, r0, 0); // addiu t3, r0, 0
|
||||
c->ori(t5, t5, 1040); // ori t5, t5, 1040
|
||||
c->vmax_bc(DEST::xyzw, BC::w, vf1, vf0, vf0); // vmaxw.xyzw vf1, vf0, vf0
|
||||
c->lh(t7, 0, a0); // lh t7, 0(a0)
|
||||
c->lqc2(vf4, 96, t0); // lqc2 vf4, 96(t0)
|
||||
c->addiu(a1, a1, -4); // addiu a1, a1, -4
|
||||
c->addiu(t6, r0, 0); // addiu t6, r0, 0
|
||||
c->mov64(ra, a3); // or ra, a3, r0
|
||||
|
||||
block_1:
|
||||
bc = c->sgpr64(t7) != 0; // bne t7, r0, L42
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_4;} // branch non-likely
|
||||
|
||||
c->addiu(a0, a0, 2); // addiu a0, a0, 2
|
||||
c->addiu(a1, a1, 1024); // addiu a1, a1, 1024
|
||||
c->daddiu(a2, a2, -16); // daddiu a2, a2, -16
|
||||
c->lh(t7, 0, a0); // lh t7, 0(a0)
|
||||
bc = ((s64)c->sgpr64(a2)) <= 0; // blez a2, L69
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_55;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L41 // beq r0, r0, L41
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_1; // branch always
|
||||
|
||||
|
||||
block_4:
|
||||
|
||||
// this block is just waiting for any in-progress SPR TO's to end
|
||||
// we can just skip it.
|
||||
/*
|
||||
c->lw(t7, 0, t4); // lw t7, 0(t4)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t7, t7, 256); // andi t7, t7, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t7) != 0; // bne t7, r0, L42
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_4;} // branch non-likely
|
||||
*/
|
||||
|
||||
// this is setting up a scratchpad TO transfer.
|
||||
{
|
||||
// set MADR
|
||||
//c->sw(a1, 16, t4); // sw a1, 16(t4)
|
||||
u32 madr = c->sgpr64(a1);
|
||||
|
||||
c->xori(t7, t5, 1024); // xori t7, t5, 1024
|
||||
|
||||
// set SADR
|
||||
//c->sw(t7, 128, t4); // sw t7, 128(t4)
|
||||
u32 sadr = c->sgpr64(t7);
|
||||
|
||||
c->addiu(t7, r0, 64); // addiu t7, r0, 64
|
||||
|
||||
// set QWC
|
||||
//c->sw(t7, 32, t4); // sw t7, 32(t4)
|
||||
u32 qwc = c->sgpr64(t7);
|
||||
|
||||
c->addiu(t7, r0, 256); // addiu t7, r0, 256
|
||||
|
||||
// GO!
|
||||
//c->sw(t7, 0, t4); // sw t7, 0(t4)
|
||||
spad_to_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
// nop // sll r0, r0, 0
|
||||
}
|
||||
|
||||
|
||||
block_6:
|
||||
c->mov64(gp, a0); // or gp, a0, r0
|
||||
// fprintf(stderr, "block_6: gp = 0x%lx\n", c->sgpr64(gp));
|
||||
c->xori(t5, t5, 1024); // xori t5, t5, 1024
|
||||
c->daddiu(a0, a0, 2); // daddiu a0, a0, 2
|
||||
c->mov64(t9, a0); // or t9, a0, r0
|
||||
c->mov64(t8, t5); // or t8, t5, r0
|
||||
c->daddiu(t7, a2, -16); // daddiu t7, a2, -16
|
||||
bc = ((s64)c->sgpr64(t7)) > 0; // bgtz t7, L45
|
||||
c->lh(t7, 0, a0); // lh t7, 0(a0)
|
||||
if (bc) {goto block_10;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L48 // beq r0, r0, L48
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_14; // branch always
|
||||
|
||||
|
||||
block_8:
|
||||
c->daddiu(a2, a2, -16); // daddiu a2, a2, -16
|
||||
c->addiu(a0, a0, 2); // addiu a0, a0, 2
|
||||
bc = ((s64)c->sgpr64(a2)) <= 0; // blez a2, L48
|
||||
c->lh(t7, 0, a0); // lh t7, 0(a0)
|
||||
if (bc) {goto block_14;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_10:
|
||||
bc = c->sgpr64(t7) == 0; // beq t7, r0, L44
|
||||
c->addiu(a1, a1, 1024); // addiu a1, a1, 1024
|
||||
if (bc) {goto block_8;} // branch non-likely
|
||||
|
||||
|
||||
// this is waiting on spad transfer and incrementing wait counts
|
||||
// block_11:
|
||||
/*
|
||||
c->lw(t7, 0, t4); // lw t7, 0(t4)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t7, t7, 256); // andi t7, t7, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t7) == 0; // beq t7, r0, L47
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_13;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(t7, 188, t0); // lw t7, 188(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(t7, t7, 1); // daddiu t7, t7, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t7, 188, t0); // sw t7, 188(t0)
|
||||
//beq r0, r0, L46 // beq r0, r0, L46
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_11; // branch always
|
||||
*/
|
||||
|
||||
|
||||
// tfrag bank loop?
|
||||
// block_13:
|
||||
{
|
||||
//c->sw(a1, 16, t4); // sw a1, 16(t4)
|
||||
u32 madr = c->sgpr64(a1);
|
||||
c->xori(t7, t5, 1024); // xori t7, t5, 1024
|
||||
//c->sw(t7, 128, t4); // sw t7, 128(t4)
|
||||
u32 sadr = c->sgpr64(t7);
|
||||
c->addiu(t7, r0, 64); // addiu t7, r0, 64
|
||||
//c->sw(t7, 32, t4); // sw t7, 32(t4)
|
||||
u32 qwc = c->sgpr64(t7);
|
||||
c->addiu(t7, r0, 256); // addiu t7, r0, 256
|
||||
//beq r0, r0, L49 // beq r0, r0, L49
|
||||
//c->sw(t7, 0, t4); // sw t7, 0(t4)
|
||||
spad_to_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
}
|
||||
goto block_16; // branch always
|
||||
|
||||
|
||||
block_14:
|
||||
/*
|
||||
c->lw(t7, 0, t4); // lw t7, 0(t4)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(t7, t7, 256); // andi t7, t7, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t7) == 0; // beq t7, r0, L49
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_16;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(t7, 188, t0); // lw t7, 188(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(t7, t7, 1); // daddiu t7, t7, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t7, 188, t0); // sw t7, 188(t0)
|
||||
//beq r0, r0, L48 // beq r0, r0, L48
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_14; // branch always
|
||||
*/
|
||||
|
||||
|
||||
block_16:
|
||||
c->lb(t7, 0, gp); // lb t7, 0(gp)
|
||||
c->addiu(gp, gp, 1); // addiu gp, gp, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(gp, 160, t0); // sw gp, 160(t0)
|
||||
bc = c->sgpr64(t7) != 0; // bne t7, r0, L50
|
||||
c->sw(t9, 164, t0); // sw t9, 164(t0)
|
||||
if (bc) {goto block_18;} // branch non-likely
|
||||
|
||||
c->daddiu(a2, a2, -8); // daddiu a2, a2, -8
|
||||
c->addiu(t8, t8, 512); // addiu t8, t8, 512
|
||||
//beq r0, r0, L65 // beq r0, r0, L65
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_47; // branch always
|
||||
|
||||
|
||||
block_18:
|
||||
c->addiu(t9, r0, 128); // addiu t9, r0, 128
|
||||
c->lqc2(vf2, 16, t8); // lqc2 vf2, 16(t8)
|
||||
|
||||
block_19:
|
||||
c->daddiu(gp, t6, -124); // daddiu gp, t6, -124
|
||||
// fprintf(stderr, "block_19: gp = 0x%lx\n", c->sgpr64(gp));
|
||||
// nop // sll r0, r0, 0
|
||||
bc = ((s64)c->sgpr64(gp)) <= 0; // blez gp, L54
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_23;} // branch non-likely
|
||||
|
||||
|
||||
// block_20:
|
||||
/*
|
||||
c->lw(ra, 0, t1); // lw ra, 0(t1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(ra, ra, 256); // andi ra, ra, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(ra) == 0; // beq ra, r0, L53
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_22;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(ra, 184, t0); // lw ra, 184(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(ra, ra, 1); // daddiu ra, ra, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(ra, 184, t0); // sw ra, 184(t0)
|
||||
//beq r0, r0, L52 // beq r0, r0, L52
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_20; // branch always
|
||||
*/
|
||||
|
||||
|
||||
// block_22:
|
||||
{
|
||||
//c->sw(a3, 128, t1); // sw a3, 128(t1)
|
||||
u32 sadr = c->sgpr64(a3);
|
||||
c->xori(a3, a3, 6144); // xori a3, a3, 6144
|
||||
//c->sw(v1, 16, t1); // sw v1, 16(t1)
|
||||
u32 madr = c->sgpr64(v1);
|
||||
c->sll(ra, t6, 4); // sll ra, t6, 4
|
||||
c->addu(v1, v1, ra); // addu v1, v1, ra
|
||||
c->mov64(ra, a3); // or ra, a3, r0
|
||||
//c->sw(t6, 32, t1); // sw t6, 32(t1)
|
||||
u32 qwc = c->sgpr64(t6);
|
||||
c->addiu(t6, r0, 256); // addiu t6, r0, 256
|
||||
//c->sw(t6, 0, t1); // sw t6, 0(t1)
|
||||
spad_from_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
c->addiu(t6, r0, 0); // addiu t6, r0, 0
|
||||
}
|
||||
|
||||
block_23:
|
||||
c->and_(gp, t7, t9); // and gp, t7, t9
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf16, vf2); // vmulax.xyzw acc, vf16, vf2
|
||||
bc = c->sgpr64(gp) == 0; // beq gp, r0, L64
|
||||
c->lwu(gp, 36, t8); // lwu gp, 36(t8)
|
||||
if (bc) {goto block_46;} // branch non-likely
|
||||
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf17, vf2); // vmadday.xyzw acc, vf17, vf2
|
||||
c->lbu(s5, 45, t8); // lbu s5, 45(t8)
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf18, vf2); // vmaddaz.xyzw acc, vf18, vf2
|
||||
c->sw(gp, 4, t0); // sw gp, 4(t0)
|
||||
c->vmsuba_bc(DEST::xyzw, BC::w, vf19, vf0); // vmsubaw.xyzw acc, vf19, vf0
|
||||
c->sh(s5, 0, t0); // sh s5, 0(t0)
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf5, vf1, vf2); // vmaddw.xyzw vf5, vf1, vf2
|
||||
c->lwu(gp, 32, t8); // lwu gp, 32(t8)
|
||||
// fprintf(stderr, "block_23-0 gp = 0x%lx\n", c->sgpr64(gp));
|
||||
c->vmula_bc(DEST::xyzw, BC::w, vf27, vf0); // vmulaw.xyzw acc, vf27, vf0
|
||||
c->lbu(s5, 47, t8); // lbu s5, 47(t8)
|
||||
c->vmadda_bc(DEST::xyzw, BC::x, vf24, vf2); // vmaddax.xyzw acc, vf24, vf2
|
||||
c->sw(gp, 20, t0); // sw gp, 20(t0)
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf25, vf2); // vmadday.xyzw acc, vf25, vf2
|
||||
c->sh(s5, 16, t0); // sh s5, 16(t0)
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf26, vf2); // vmaddaz.xyzw acc, vf26, vf2
|
||||
c->lwu(gp, 32, t8); // lwu gp, 32(t8)
|
||||
c->mov128_gpr_vf(s5, vf5); // qmfc2.i s5, vf5
|
||||
c->lbu(s4, 44, t8); // lbu s4, 44(t8)
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf6, vf1, vf2); // vmaddw.xyzw vf6, vf1, vf2
|
||||
c->sw(gp, 36, t0); // sw gp, 36(t0)
|
||||
c->vmsub_bc(DEST::xyzw, BC::w, vf8, vf1, vf2); // vmsubw.xyzw vf8, vf1, vf2
|
||||
c->sh(s4, 32, t0); // sh s4, 32(t0)
|
||||
c->pcgtw(s5, r0, s5); // pcgtw s5, r0, s5
|
||||
c->lwu(gp, 40, t8); // lwu gp, 40(t8)
|
||||
// fprintf(stderr, "block_23-1: gp = 0x%lx\n", c->sgpr64(gp));
|
||||
c->ppach(s5, r0, s5); // ppach s5, r0, s5
|
||||
c->lbu(s4, 46, t8); // lbu s4, 46(t8)
|
||||
c->vadd_bc(DEST::xyzw, BC::z, vf6, vf3, vf6); // vaddz.xyzw vf6, vf3, vf6
|
||||
c->sw(gp, 52, t0); // sw gp, 52(t0)
|
||||
c->vadd_bc(DEST::xyzw, BC::z, vf7, vf3, vf8); // vaddz.xyzw vf7, vf3, vf8
|
||||
c->sw(t3, 12, t0); // sw t3, 12(t0)
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L63
|
||||
c->sh(s4, 48, t0); // sh s4, 48(t0)
|
||||
if (bc) {goto block_45;} // branch non-likely
|
||||
|
||||
c->vmini(DEST::xyzw, vf4, vf4, vf8); // vmini.xyzw vf4, vf4, vf8
|
||||
c->sw(t3, 28, t0); // sw t3, 28(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(s5, 53, t8); // lbu s5, 53(t8)
|
||||
c->mov128_gpr_vf(gp, vf6); // qmfc2.i gp, vf6
|
||||
c->sw(t3, 44, t0); // sw t3, 44(t0)
|
||||
c->mov128_gpr_vf(s3, vf7); // qmfc2.i s3, vf7
|
||||
c->lbu(s4, 56, t8); // lbu s4, 56(t8)
|
||||
c->pcgtw(s2, r0, gp); // pcgtw s2, r0, gp
|
||||
c->lw(gp, 12, t8); // lw gp, 12(t8)
|
||||
// fprintf(stderr, "loaded gp: 0x%lx from tfragment: 0x%lx\n", c->sgpr64(gp), c->sgpr64(t8));
|
||||
c->pcgtw(s3, r0, s3); // pcgtw s3, r0, s3
|
||||
c->sb(s4, 76, t0); // sb s4, 76(t0)
|
||||
c->pinteh(s4, s2, s3); // pinteh s4, s2, s3
|
||||
c->lbu(s2, 54, t8); // lbu s2, 54(t8)
|
||||
c->ppacb(s3, r0, s4); // ppacb s3, r0, s4
|
||||
c->lbu(s1, 55, t8); // lbu s1, 55(t8)
|
||||
bc = c->sgpr64(s3) == 0; // beq s3, r0, L56
|
||||
c->dsrl32(s4, s3, 8); // dsrl32 s4, s3, 8
|
||||
if (bc) {goto block_36;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(s2) == 0; // beq s2, r0, L56
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_36;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(s1) == 0; // beq s1, r0, L55
|
||||
c->dsrl(s5, s3, 16); // dsrl s5, s3, 16
|
||||
if (bc) {goto block_33;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(s5) == 0; // beq s5, r0, L55
|
||||
c->dsrl32(s5, s3, 24); // dsrl32 s5, s3, 24
|
||||
if (bc) {goto block_33;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(s5) != 0; // bne s5, r0, L64
|
||||
c->addiu(s5, s1, 3); // addiu s5, s1, 3
|
||||
if (bc) {goto block_46;} // branch non-likely
|
||||
|
||||
c->sra(s4, s5, 2); // sra s4, s5, 2
|
||||
c->mov64(s5, s1); // or s5, s1, r0
|
||||
c->sll(t3, s4, 2); // sll t3, s4, 2
|
||||
c->sh(s4, 64, t0); // sh s4, 64(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sb(t3, 78, t0); // sb t3, 78(t0)
|
||||
c->daddiu(t6, t6, 3); // daddiu t6, t6, 3
|
||||
c->lq(s2, 32, t0); // lq s2, 32(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(s1, 48, t0); // lq s1, 48(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t3, 64, t0); // lq t3, 64(t0)
|
||||
c->sq(s2, 0, ra); // sq s2, 0(ra)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(s1, 16, ra); // sq s1, 16(ra)
|
||||
c->dsrl32(s2, s3, 16); // dsrl32 s2, s3, 16
|
||||
c->sq(t3, 32, ra); // sq t3, 32(ra)
|
||||
c->daddiu(ra, ra, 48); // daddiu ra, ra, 48
|
||||
bc = c->sgpr64(s2) != 0; // bne s2, r0, L57
|
||||
c->ori(t3, t2, 18); // ori t3, t2, 18
|
||||
if (bc) {goto block_38;} // branch non-likely
|
||||
|
||||
c->dsrl32(t3, s3, 8); // dsrl32 t3, s3, 8
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t3) != 0; // bne t3, r0, L57
|
||||
c->ori(t3, t2, 16); // ori t3, t2, 16
|
||||
if (bc) {goto block_38;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L57 // beq r0, r0, L57
|
||||
c->ori(t3, t2, 14); // ori t3, t2, 14
|
||||
goto block_38; // branch always
|
||||
|
||||
|
||||
block_33:
|
||||
bc = c->sgpr64(s4) != 0; // bne s4, r0, L64
|
||||
c->addiu(s5, s2, 3); // addiu s5, s2, 3
|
||||
if (bc) {goto block_46;} // branch non-likely
|
||||
|
||||
c->sra(s4, s5, 2); // sra s4, s5, 2
|
||||
c->mov64(s5, s2); // or s5, s2, r0
|
||||
c->sll(t3, s4, 2); // sll t3, s4, 2
|
||||
c->sh(s4, 64, t0); // sh s4, 64(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sb(t3, 78, t0); // sb t3, 78(t0)
|
||||
c->daddiu(t6, t6, 2); // daddiu t6, t6, 2
|
||||
c->lq(s2, 16, t0); // lq s2, 16(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lq(t3, 64, t0); // lq t3, 64(t0)
|
||||
c->sq(s2, 0, ra); // sq s2, 0(ra)
|
||||
c->dsrl(s3, s3, 8); // dsrl s3, s3, 8
|
||||
c->sq(t3, 16, ra); // sq t3, 16(ra)
|
||||
c->daddiu(ra, ra, 32); // daddiu ra, ra, 32
|
||||
bc = c->sgpr64(s3) != 0; // bne s3, r0, L57
|
||||
c->ori(t3, t2, 10); // ori t3, t2, 10
|
||||
if (bc) {goto block_38;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L57 // beq r0, r0, L57
|
||||
c->ori(t3, t2, 8); // ori t3, t2, 8
|
||||
goto block_38; // branch always
|
||||
|
||||
|
||||
block_36:
|
||||
bc = c->sgpr64(s4) != 0; // bne s4, r0, L64
|
||||
c->addiu(s4, s5, 3); // addiu s4, s5, 3
|
||||
if (bc) {goto block_46;} // branch non-likely
|
||||
|
||||
c->sra(s4, s4, 2); // sra s4, s4, 2
|
||||
// nop // sll r0, r0, 0
|
||||
c->sll(t3, s4, 2); // sll t3, s4, 2
|
||||
c->sh(s4, 64, t0); // sh s4, 64(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sb(t3, 78, t0); // sb t3, 78(t0)
|
||||
c->ori(t3, t2, 6); // ori t3, t2, 6
|
||||
c->lq(s3, 0, t0); // lq s3, 0(t0)
|
||||
c->daddiu(t6, t6, 2); // daddiu t6, t6, 2
|
||||
c->lq(s2, 64, t0); // lq s2, 64(t0)
|
||||
c->sq(s3, 0, ra); // sq s3, 0(ra)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sq(s2, 16, ra); // sq s2, 16(ra)
|
||||
c->daddiu(ra, ra, 32); // daddiu ra, ra, 32
|
||||
|
||||
block_38:
|
||||
c->addiu(s3, r0, 127); // addiu s3, r0, 127
|
||||
c->daddu(s2, t6, s4); // daddu s2, t6, s4
|
||||
c->dsubu(s3, s3, s2); // dsubu s3, s3, s2
|
||||
// nop // sll r0, r0, 0
|
||||
bc = ((s64)c->sgpr64(s3)) >= 0; // bgez s3, L60
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_42;} // branch non-likely
|
||||
|
||||
|
||||
// block_39:
|
||||
/*
|
||||
c->lw(ra, 0, t1); // lw ra, 0(t1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(ra, ra, 256); // andi ra, ra, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(ra) == 0; // beq ra, r0, L59
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_41;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(ra, 184, t0); // lw ra, 184(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(ra, ra, 1); // daddiu ra, ra, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(ra, 184, t0); // sw ra, 184(t0)
|
||||
//beq r0, r0, L58 // beq r0, r0, L58
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_39; // branch always
|
||||
*/
|
||||
|
||||
|
||||
// block_41:
|
||||
{
|
||||
//c->sw(a3, 128, t1); // sw a3, 128(t1)
|
||||
u32 sadr = c->sgpr64(a3);
|
||||
c->xori(a3, a3, 6144); // xori a3, a3, 6144
|
||||
//c->sw(v1, 16, t1); // sw v1, 16(t1)
|
||||
u32 madr = c->sgpr64(v1);
|
||||
c->sll(ra, t6, 4); // sll ra, t6, 4
|
||||
c->addu(v1, v1, ra); // addu v1, v1, ra
|
||||
c->mov64(ra, a3); // or ra, a3, r0
|
||||
//c->sw(t6, 32, t1); // sw t6, 32(t1)
|
||||
u32 qwc = c->sgpr64(t6);
|
||||
c->addiu(t6, r0, 256); // addiu t6, r0, 256
|
||||
//c->sw(t6, 0, t1); // sw t6, 0(t1)
|
||||
spad_from_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
c->addiu(t6, r0, 0); // addiu t6, r0, 0
|
||||
}
|
||||
|
||||
block_42:
|
||||
c->daddu(t6, t6, s4); // daddu t6, t6, s4
|
||||
c->sw(t8, 168, t0); // sw t8, 168(t0)
|
||||
c->ld(s4, 0, gp); // ld s4, 0(gp)
|
||||
c->daddiu(t8, gp, 8); // daddiu t8, gp, 8
|
||||
c->daddiu(gp, s5, -4); // daddiu gp, s5, -4
|
||||
// fprintf(stderr, "block_42: gp = 0x%lx\n", c->sgpr64(gp));
|
||||
c->lq(s5, 128, t0); // lq s5, 128(t0)
|
||||
c->pextlh(s4, r0, s4); // pextlh s4, r0, s4
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->paddw(s2, s4, s5); // paddw s2, s4, s5
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->lw(s4, 0, s2); // lw s4, 0(s2)
|
||||
c->dsra32(s3, s2, 0); // dsra32 s3, s2, 0
|
||||
c->lw(s3, 0, s3); // lw s3, 0(s3)
|
||||
c->pcpyud(s1, s2, s2); // pcpyud s1, s2, s2
|
||||
c->lw(s2, 0, s1); // lw s2, 0(s1)
|
||||
c->dsra32(s1, s1, 0); // dsra32 s1, s1, 0
|
||||
bc = ((s64)c->sgpr64(gp)) <= 0; // blez gp, L62
|
||||
c->lw(s1, 0, s1); // lw s1, 0(s1)
|
||||
if (bc) {goto block_44;} // branch non-likely
|
||||
|
||||
|
||||
block_43:
|
||||
c->ld(s0, 0, t8); // ld s0, 0(t8)
|
||||
c->daddiu(ra, ra, 16); // daddiu ra, ra, 16
|
||||
c->daddiu(t8, t8, 8); // daddiu t8, t8, 8
|
||||
c->sw(s4, -16, ra); // sw s4, -16(ra)
|
||||
c->daddiu(gp, gp, -4); // daddiu gp, gp, -4
|
||||
c->sw(s3, -12, ra); // sw s3, -12(ra)
|
||||
c->pextlh(s4, r0, s0); // pextlh s4, r0, s0
|
||||
c->sw(s2, -8, ra); // sw s2, -8(ra)
|
||||
c->paddw(s2, s4, s5); // paddw s2, s4, s5
|
||||
// this one is storing a 0!
|
||||
c->sw(s1, -4, ra); // sw s1, -4(ra)
|
||||
c->lw(s4, 0, s2); // lw s4, 0(s2)
|
||||
c->dsra32(s3, s2, 0); // dsra32 s3, s2, 0
|
||||
c->lw(s3, 0, s3); // lw s3, 0(s3)
|
||||
c->pcpyud(s1, s2, s2); // pcpyud s1, s2, s2
|
||||
c->lw(s2, 0, s1); // lw s2, 0(s1)
|
||||
c->dsra32(s1, s1, 0); // dsra32 s1, s1, 0
|
||||
bc = ((s64)c->sgpr64(gp)) > 0; // bgtz gp, L61
|
||||
c->lw(s1, 0, s1); // lw s1, 0(s1)
|
||||
if (bc) {goto block_43;} // branch non-likely
|
||||
|
||||
|
||||
block_44:
|
||||
c->daddiu(ra, ra, 16); // daddiu ra, ra, 16
|
||||
c->lw(t8, 168, t0); // lw t8, 168(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(s4, -16, ra); // sw s4, -16(ra)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(s3, -12, ra); // sw s3, -12(ra)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(s2, -8, ra); // sw s2, -8(ra)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(s1, -4, ra); // sw s1, -4(ra)
|
||||
|
||||
block_45:
|
||||
c->xor_(t7, t7, t9); // xor t7, t7, t9
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_46:
|
||||
c->daddiu(t8, t8, 64); // daddiu t8, t8, 64
|
||||
c->srl(t9, t9, 1); // srl t9, t9, 1
|
||||
c->addiu(a2, a2, -1); // addiu a2, a2, -1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t9) != 0; // bne t9, r0, L51
|
||||
c->lqc2(vf2, 16, t8); // lqc2 vf2, 16(t8)
|
||||
if (bc) {goto block_19;} // branch non-likely
|
||||
|
||||
|
||||
block_47:
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(gp, 160, t0); // lw gp, 160(t0)
|
||||
// fprintf(stderr, "block_47: gp = 0x%lx\n", c->sgpr64(gp));
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(t9, 164, t0); // lw t9, 164(t0)
|
||||
bc = c->sgpr64(gp) != c->sgpr64(t9); // bne gp, t9, L49
|
||||
c->sb(t7, -1, gp); // sb t7, -1(gp)
|
||||
if (bc) {goto block_16;} // branch non-likely
|
||||
|
||||
bc = ((s64)c->sgpr64(a2)) > 0; // bgtz a2, L43
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_6;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(t6) == 0; // beq t6, r0, L68
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_53;} // branch non-likely
|
||||
|
||||
|
||||
// block_50:
|
||||
/*
|
||||
c->lw(a0, 0, t1); // lw a0, 0(t1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(a0, a0, 256); // andi a0, a0, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(a0) == 0; // beq a0, r0, L67
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_52;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 184, t0); // lw a0, 184(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a0, a0, 1); // daddiu a0, a0, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(a0, 184, t0); // sw a0, 184(t0)
|
||||
//beq r0, r0, L66 // beq r0, r0, L66
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_50; // branch always
|
||||
*/
|
||||
|
||||
|
||||
// block_52:
|
||||
{
|
||||
//c->sw(a3, 128, t1); // sw a3, 128(t1)
|
||||
u32 sadr = c->sgpr64(a3);
|
||||
c->xori(a0, a3, 6144); // xori a0, a3, 6144
|
||||
//c->sw(v1, 16, t1); // sw v1, 16(t1)
|
||||
u32 madr = c->sgpr64(v1);
|
||||
c->sll(a1, t6, 4); // sll a1, t6, 4
|
||||
c->addu(v1, v1, a1); // addu v1, v1, a1
|
||||
c->mov64(a0, a0); // or a0, a0, r0
|
||||
//c->sw(t6, 32, t1); // sw t6, 32(t1)
|
||||
u32 qwc = c->sgpr64(t6);
|
||||
c->addiu(a0, r0, 256); // addiu a0, r0, 256
|
||||
//c->sw(a0, 0, t1); // sw a0, 0(t1)
|
||||
spad_from_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
|
||||
c->addiu(a0, r0, 0); // addiu a0, r0, 0
|
||||
}
|
||||
|
||||
block_53:
|
||||
/*
|
||||
c->lw(a0, 0, t1); // lw a0, 0(t1)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->andi(a0, a0, 256); // andi a0, a0, 256
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(a0) == 0; // beq a0, r0, L69
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_55;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 184, t0); // lw a0, 184(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(a0, a0, 1); // daddiu a0, a0, 1
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(a0, 184, t0); // sw a0, 184(t0)
|
||||
//beq r0, r0, L68 // beq r0, r0, L68
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_53; // branch always
|
||||
*/
|
||||
|
||||
|
||||
block_55:
|
||||
c->lw(a0, 176, t0); // lw a0, 176(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(t3, 172, t0); // sw t3, 172(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sqc2(vf4, 112, t0); // sqc2 vf4, 112(t0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(v1, 4, a0); // sw v1, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
|
||||
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
||||
c->lq(gp, 112, sp); // lq gp, 112(sp)
|
||||
c->lq(s5, 96, sp); // lq s5, 96(sp)
|
||||
c->lq(s4, 80, sp); // lq s4, 80(sp)
|
||||
c->lq(s3, 64, sp); // lq s3, 64(sp)
|
||||
c->lq(s2, 48, sp); // lq s2, 48(sp)
|
||||
c->lq(s1, 32, sp); // lq s1, 32(sp)
|
||||
c->lq(s0, 16, sp); // lq s0, 16(sp)
|
||||
//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];
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
void link() {
|
||||
cache.tfrag_work = intern_from_c("*tfrag-work*").c();
|
||||
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
||||
cache.transform_regs = intern_from_c("*transform-regs*").c();
|
||||
gLinkedFunctionTable.reg("draw-inline-array-tfrag", execute, 512);
|
||||
}
|
||||
|
||||
} // namespace draw_inline_array_tfrag
|
||||
} // namespace Mips2C::jak1
|
||||
|
||||
// clang-format off
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak1 {
|
||||
namespace stats_tfrag_asm {
|
||||
struct Cache {
|
||||
void* tfrag_work; // *tfrag-work*
|
||||
void* transform_regs;
|
||||
} cache;
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
load_vfs_from_tf_regs(cache.transform_regs, c);
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
c->load_symbol(v1, cache.tfrag_work); // lw v1, *tfrag-work*(s7)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a1, 4, a0); // lw a1, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lqc2(vf10, 12, a0); // lqc2 vf10, 12(a0)
|
||||
bc = c->sgpr64(a1) == 0; // beq a1, r0, L7
|
||||
c->lqc2(vf14, 80, v1); // lqc2 vf14, 80(v1)
|
||||
if (bc) {goto block_15;} // branch non-likely
|
||||
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf16, vf10); // vmulax.xyzw acc, vf16, vf10
|
||||
c->lb(a2, 49, a0); // lb a2, 49(a0)
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf17, vf10); // vmadday.xyzw acc, vf17, vf10
|
||||
c->lb(a2, 50, a0); // lb a2, 50(a0)
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf18, vf10); // vmaddaz.xyzw acc, vf18, vf10
|
||||
c->lb(a0, 51, a0); // lb a0, 51(a0)
|
||||
c->vmsub_bc(DEST::xyzw, BC::w, vf9, vf19, vf0); // vmsubw.xyzw vf9, vf19, vf0
|
||||
// nop // sll r0, r0, 0
|
||||
c->vmula_bc(DEST::xyzw, BC::w, vf27, vf0); // vmulaw.xyzw acc, vf27, vf0
|
||||
// nop // sll r0, r0, 0
|
||||
c->vmadda_bc(DEST::xyzw, BC::x, vf24, vf10); // vmaddax.xyzw acc, vf24, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf25, vf10); // vmadday.xyzw acc, vf25, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vadd_bc(DEST::xyzw, BC::w, vf9, vf9, vf10); // vaddw.xyzw vf9, vf9, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vmadd_bc(DEST::xyzw, BC::z, vf11, vf26, vf10); // vmaddz.xyzw vf11, vf26, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vadd_bc(DEST::xyzw, BC::w, vf12, vf11, vf10); // vaddw.xyzw vf12, vf11, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vsub_bc(DEST::xyzw, BC::w, vf13, vf11, vf10); // vsubw.xyzw vf13, vf11, vf10
|
||||
// nop // sll r0, r0, 0
|
||||
c->vsub_bc(DEST::xyzw, BC::z, vf11, vf0, vf12); // vsubz.xyzw vf11, vf0, vf12
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(a3, vf9); // qmfc2.i a3, vf9
|
||||
// nop // sll r0, r0, 0
|
||||
c->pcgtw(a3, r0, a3); // pcgtw a3, r0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->ppach(a3, r0, a3); // ppach a3, r0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
bc = c->sgpr64(a3) != 0; // bne a3, r0, L7
|
||||
c->vadd_bc(DEST::xyzw, BC::z, vf12, vf14, vf12); // vaddz.xyzw vf12, vf14, vf12
|
||||
if (bc) {goto block_15;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->vadd_bc(DEST::xyzw, BC::z, vf13, vf14, vf13); // vaddz.xyzw vf13, vf14, vf13
|
||||
c->mov128_gpr_vf(t0, vf12); // qmfc2.i t0, vf12
|
||||
// nop // sll r0, r0, 0
|
||||
c->mov128_gpr_vf(a3, vf13); // qmfc2.i a3, vf13
|
||||
// nop // sll r0, r0, 0
|
||||
c->pcgtw(t0, r0, t0); // pcgtw t0, r0, t0
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pcgtw(a3, r0, a3); // pcgtw a3, r0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->pinteh(a3, t0, a3); // pinteh a3, t0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
c->ppacb(a3, r0, a3); // ppacb a3, r0, a3
|
||||
c->mfc1(r0, f31); // mfc1 r0, f31
|
||||
bc = c->sgpr64(a3) == 0; // beq a3, r0, L5
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_12;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(a2) == 0; // beq a2, r0, L5
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_12;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(a0) == 0; // beq a0, r0, L3
|
||||
c->dsrl(a0, a3, 16); // dsrl a0, a3, 16
|
||||
if (bc) {goto block_9;} // branch non-likely
|
||||
|
||||
bc = c->sgpr64(a0) == 0; // beq a0, r0, L3
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_9;} // branch non-likely
|
||||
|
||||
c->dsrl32(a0, a3, 24); // dsrl32 a0, a3, 24
|
||||
c->lbu(a2, 4, a1); // lbu a2, 4(a1)
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L2
|
||||
c->lw(a0, 148, v1); // lw a0, 148(v1)
|
||||
if (bc) {goto block_8;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 144, v1); // lw a0, 144(v1)
|
||||
|
||||
block_8:
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(v1, 12, a1); // lbu v1, 12(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a3, 4, a0); // lw a3, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a1, 8, a0); // lw a1, 8(a0)
|
||||
c->addu(a2, a3, a2); // addu a2, a3, a2
|
||||
c->sw(a2, 4, a0); // sw a2, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lh(a2, 2, a0); // lh a2, 2(a0)
|
||||
c->daddu(v1, a1, v1); // daddu v1, a1, v1
|
||||
c->sw(v1, 8, a0); // sw v1, 8(a0)
|
||||
c->daddiu(v1, a2, 1); // daddiu v1, a2, 1
|
||||
c->sh(v1, 2, a0); // sh v1, 2(a0)
|
||||
//beq r0, r0, L7 // beq r0, r0, L7
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_15; // branch always
|
||||
|
||||
|
||||
block_9:
|
||||
c->dsrl32(a0, a3, 8); // dsrl32 a0, a3, 8
|
||||
c->lbu(a2, 2, a1); // lbu a2, 2(a1)
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L4
|
||||
c->lw(a0, 148, v1); // lw a0, 148(v1)
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a0, 144, v1); // lw a0, 144(v1)
|
||||
|
||||
block_11:
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(v1, 10, a1); // lbu v1, 10(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a3, 4, a0); // lw a3, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a1, 8, a0); // lw a1, 8(a0)
|
||||
c->addu(a2, a3, a2); // addu a2, a3, a2
|
||||
c->sw(a2, 4, a0); // sw a2, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lh(a2, 2, a0); // lh a2, 2(a0)
|
||||
c->daddu(v1, a1, v1); // daddu v1, a1, v1
|
||||
c->sw(v1, 8, a0); // sw v1, 8(a0)
|
||||
c->daddiu(v1, a2, 1); // daddiu v1, a2, 1
|
||||
c->sh(v1, 2, a0); // sh v1, 2(a0)
|
||||
//beq r0, r0, L7 // beq r0, r0, L7
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_15; // branch always
|
||||
|
||||
|
||||
block_12:
|
||||
c->dsrl32(a0, a3, 8); // dsrl32 a0, a3, 8
|
||||
c->lbu(a2, 0, a1); // lbu a2, 0(a1)
|
||||
bc = c->sgpr64(a0) != 0; // bne a0, r0, L6
|
||||
c->lw(a0, 148, v1); // lw a0, 148(v1)
|
||||
if (bc) {goto block_14;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L6 // beq r0, r0, L6
|
||||
c->lw(a0, 144, v1); // lw a0, 144(v1)
|
||||
goto block_14; // branch always
|
||||
|
||||
|
||||
block_14:
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(v1, 8, a1); // lbu v1, 8(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a3, 4, a0); // lw a3, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a1, 8, a0); // lw a1, 8(a0)
|
||||
c->addu(a2, a3, a2); // addu a2, a3, a2
|
||||
c->sw(a2, 4, a0); // sw a2, 4(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lh(a2, 2, a0); // lh a2, 2(a0)
|
||||
c->daddu(v1, a1, v1); // daddu v1, a1, v1
|
||||
c->sw(v1, 8, a0); // sw v1, 8(a0)
|
||||
c->daddiu(v1, a2, 1); // daddiu v1, a2, 1
|
||||
c->sh(v1, 2, a0); // sh v1, 2(a0)
|
||||
|
||||
block_15:
|
||||
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.tfrag_work = intern_from_c("*tfrag-work*").c();
|
||||
cache.transform_regs = intern_from_c("*transform-regs*").c();
|
||||
gLinkedFunctionTable.reg("stats-tfrag-asm", execute, 512);
|
||||
}
|
||||
|
||||
} // namespace stats_tfrag_asm
|
||||
} // namespace Mips2C
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,8 +41,6 @@ namespace init_boundary_regs { extern void link(); }
|
||||
namespace render_boundary_quad { extern void link(); }
|
||||
namespace render_boundary_tri { extern void link(); }
|
||||
namespace draw_boundary_polygon { extern void link(); }
|
||||
namespace draw_inline_array_tfrag { extern void link(); }
|
||||
namespace stats_tfrag_asm { extern void link(); }
|
||||
namespace time_of_day_interp_colors_scratch { extern void link(); }
|
||||
namespace method_12_collide_mesh { extern void link(); }
|
||||
namespace method_11_collide_mesh { extern void link(); }
|
||||
@@ -97,8 +95,6 @@ namespace shadow_scissor_top { extern void link(); }
|
||||
namespace shadow_scissor_edges { extern void link(); }
|
||||
namespace shadow_calc_dual_verts { extern void link(); }
|
||||
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 jak1
|
||||
|
||||
namespace jak2 {
|
||||
@@ -397,7 +393,6 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
|
||||
{"load-boundary",
|
||||
{jak1::init_boundary_regs::link, jak1::render_boundary_quad::link,
|
||||
jak1::render_boundary_tri::link, jak1::draw_boundary_polygon::link}},
|
||||
{"tfrag", {jak1::draw_inline_array_tfrag::link, jak1::stats_tfrag_asm::link}},
|
||||
{"time-of-day", {jak1::time_of_day_interp_colors_scratch::link}},
|
||||
{"collide-probe", {jak1::collide_probe_node::link, jak1::collide_probe_instance_tie::link}},
|
||||
{"collide-mesh",
|
||||
@@ -434,10 +429,7 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
|
||||
jak1::shadow_find_single_edges::link, jak1::shadow_find_facing_single_tris::link,
|
||||
jak1::shadow_init_vars::link, jak1::shadow_scissor_top::link,
|
||||
jak1::shadow_scissor_edges::link, jak1::shadow_calc_dual_verts::link,
|
||||
jak1::shadow_xform_verts::link}},
|
||||
{"tie-methods",
|
||||
{jak1::draw_inline_array_instance_tie::link,
|
||||
jak1::draw_inline_array_prototype_tie_generic_asm::link}}},
|
||||
jak1::shadow_xform_verts::link}}},
|
||||
/////////// JAK 2
|
||||
{{"collide-func",
|
||||
{jak2::collide_do_primitives::link, jak2::moving_sphere_triangle_intersect::link}},
|
||||
|
||||
@@ -127,6 +127,17 @@
|
||||
(set! (-> ,pkt vif0) ,vif0)
|
||||
(set! (-> ,pkt vif1) ,vif1))))
|
||||
|
||||
(defmacro dma-buffer-add-next-vif2 (buf qwc addr vif0 vif1)
|
||||
"Append a NEXT dma-packet. It transfers qwc quadwords following the tag, then continues at addr;
|
||||
vif0 and vif1 occupy the tag-transfer command words."
|
||||
(with-gensyms (pkt)
|
||||
`(dma-buffer-add-base-type ,buf
|
||||
,pkt
|
||||
dma-packet
|
||||
(set! (-> ,pkt dma) (new 'static 'dma-tag :id (dma-tag-id next) :qwc ,qwc :addr (the-as int ,addr)))
|
||||
(set! (-> ,pkt vif0) ,vif0)
|
||||
(set! (-> ,pkt vif1) ,vif1))))
|
||||
|
||||
(defmacro dma-buffer-add-ret (buf)
|
||||
"Append a RET dma-packet with two VIF no-ops."
|
||||
(with-gensyms (pkt)
|
||||
@@ -255,4 +266,5 @@
|
||||
"Bind a dma-buffer to a variable and use it on a block to allow adding things to a new bucket.
|
||||
usage: (with-dma-buffer-add-bucket ((buffer-name buffer) bucket-id) &rest body)
|
||||
example: (with-dma-buffer-add-bucket ((buf (-> (current-frame) debug-buf)) (bucket-id debug-no-zbuf)) ...)"
|
||||
`(let ((,(caar bindings) ,(cadar bindings))) (with-dma-bucket (,(caar bindings) ,bucket-group ,(cadr bindings)) ,@body)))
|
||||
`(let ((,(caar bindings) ,(cadar bindings)))
|
||||
(with-dma-bucket (,(caar bindings) ,bucket-group ,(cadr bindings)) ,@body)))
|
||||
|
||||
@@ -9,29 +9,6 @@
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; The static templates shrubbery.gc copies and patches while it builds the frame's shrub DMA chains.
|
||||
;;
|
||||
;; matrix-tmpl and count-tmpl are one twenty-position cycle over the two VU1 instance rings. mod-count
|
||||
;; is the position: 0 through 9 fill ring A's ten slots and 10 through 19 fill ring B's. Position k's
|
||||
;; matrix packet unpacks five quadwords to that ring's slot, and the count packet at a group boundary
|
||||
;; writes how many instances the ring holds.
|
||||
;;
|
||||
;; The DMA tag ids are the interesting part. Records are appended backwards -- each new tag's ADDR is
|
||||
;; patched to the record appended before it -- so the chain runs newest-first, and a next tag is all
|
||||
;; that is needed in the middle of a group. At the four group boundaries, positions 0, 9, 10 and 19,
|
||||
;; the tag is a cnt instead, so the chain flows on by adjacency into whatever the EE wrote
|
||||
;; immediately after it: the count packet when a ring has just filled, or an MSCALF that runs the
|
||||
;; draw entry when the next group opens. Read in DMA order, one prototype's chain is the current
|
||||
;; partial group followed by each earlier full group in reverse, each ending in its own MSCALF.
|
||||
;;
|
||||
;; mscalf-tmpl and mscalf-ret-tmpl are that MSCALF, in next and ret flavours. The chain is entered
|
||||
;; with a call, so the earliest group -- the last one the DMAC reaches -- has to return instead of
|
||||
;; jumping onward, and the builder picks the ret flavour when the bucket has no earlier group.
|
||||
;;
|
||||
;; The six near packets pair two matrix destinations with three packed-stream destinations, so the EE
|
||||
;; can rotate to a free packet while an earlier chain still names the last one. start-bank records
|
||||
;; which of the two model-init entries each ring position needs; entry 17 leaves the draw entry
|
||||
;; reading ring A and entry 21 leaves it reading ring B, which is why positions 1 through 10 want one
|
||||
;; and 0 and 11 through 19 want the other.
|
||||
(define *instance-shrub-work*
|
||||
(new 'static
|
||||
'instance-shrub-work
|
||||
@@ -507,8 +484,6 @@
|
||||
:start-bank
|
||||
(new 'static 'array uint8 20 #x0 #x1 #x1 #x1 #x1 #x1 #x1 #x1 #x1 #x1 #x1 #x0 #x0 #x0 #x0 #x0 #x0 #x0 #x0 #x0)))
|
||||
|
||||
;; Both flavours start the draw entry. Patched here rather than written into the static data because
|
||||
;; the entry address is a property of the microprogram, not of the packet.
|
||||
(set! (-> *instance-shrub-work* mscalf-tmpl vif0 imm) SHRUB-VU-ENTRY-DRAW)
|
||||
|
||||
(set! (-> *instance-shrub-work* mscalf-ret-tmpl vif0 imm) SHRUB-VU-ENTRY-DRAW)
|
||||
@@ -587,10 +562,8 @@
|
||||
(shr (shl (+ stream-vu-address 2) 54) 54)
|
||||
:num (-> fragment vtx-cnt)))
|
||||
(set! (-> dma-state base) (&+ (the-as pointer vertex-packet) 16)))
|
||||
(let* ((dma-state dma-buf)
|
||||
(run-packet (the-as object (-> dma-state base))))
|
||||
(set! (-> (the-as dma-packet run-packet) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet run-packet) vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> (the-as dma-packet run-packet) vif1) (new 'static 'vif-tag :imm #xa :cmd (vif-cmd mscal) :msk #x1))
|
||||
(set! (-> dma-state base) (&+ (the-as pointer run-packet) 16)))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf
|
||||
0
|
||||
(new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
(new 'static 'vif-tag :imm #xa :cmd (vif-cmd mscal) :msk #x1))
|
||||
dma-buf)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,10 @@
|
||||
(require "engine/gfx/tfrag/tfrag-h.gc")
|
||||
(require "engine/math/matrix-h.gc")
|
||||
(require "engine/camera/cam-debug-h.gc")
|
||||
|
||||
;; TFRAG-NEAR renders tfrags with clipping for triangles that intersect the view frustum.
|
||||
;; This is unused on PC where OpenGL handles clipping in the normal path.
|
||||
(#when PC_PORT
|
||||
;; The PC terrain renderer consumes extracted mesh data and does not execute this VU1 program.
|
||||
(define tnear-vu1-block (new 'static 'vu-function :length #x0 :qlength #x0)))
|
||||
|
||||
;; VU1 data memory for the near-terrain program. The two input banks and the shared frame constants sit
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
;; lookup starts at scratchpad byte 6160, one quadword past the colors overlay's nominal start.
|
||||
;;
|
||||
;; Colors are the only part of a terrain patch that is not already sitting in the level file as a VIF
|
||||
;; chain, because they follow the time of day. The CNT template above unpacks them V4-8 on a 1/2 cycle
|
||||
;; chain, because they change based on time-of-day. The CNT template above unpacks them V4-8 on a 1/2 cycle
|
||||
;; so they land in the odd VU quadwords, which is exactly the space the vertex positions leave empty
|
||||
;; when they unpack on a 2/1 cycle - one vertex is a position quadword followed by its color quadword.
|
||||
;; tfragment.color-offset is where in that interleave the patch's colors start.
|
||||
|
||||
+1266
-1296
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
;; Ordinary TIE is allowed to be careless about the view volume: it either rejects a fragment
|
||||
;; outright or projects it and lets the GS scissor the result. That stops working the moment a
|
||||
;; triangle straddles the camera plane, because dividing by a w near zero throws coordinates off to
|
||||
;; infinity and the GS has no way to recover. So the instance pass hands anything that comes near the
|
||||
;; infinity and the GS uses fixed point. So the instance pass hands anything that comes near the
|
||||
;; guard volume to this renderer instead, which keeps positions homogeneous long enough to clip them
|
||||
;; properly.
|
||||
;;
|
||||
|
||||
@@ -5,20 +5,6 @@
|
||||
(require "engine/dma/dma-buffer.gc")
|
||||
(require "engine/math/vector-h.gc")
|
||||
|
||||
;; The DMA and VIF packets TIE builds its chains out of, initialized once at load time.
|
||||
;;
|
||||
;; Nothing here is sent as it stands. The packet builders in tie-methods.gc copy these quadwords into
|
||||
;; scratchpad and patch in the addresses, transfer lengths, and chain links for the instance or
|
||||
;; fragment they are working on. Keeping the constant words in a static template means the inner loop
|
||||
;; writes three or four words instead of assembling a packet from scratch, which matters when it is
|
||||
;; doing it once per instance.
|
||||
;;
|
||||
;; Fields left at zero below are the patched ones. The suspicious-looking VIF immediates are VU
|
||||
;; addresses: #x80c6 is 198 with its mask bits, #xc0cc is 204, #x4346 is 838.
|
||||
;;
|
||||
;; The instance stream is six V4-32 quadwords to VU 198 -- the transform, morph, and fog -- followed
|
||||
;; by packed V4-8 palette indices at 204. upload-color-2 and upload-color-ret are the same upload with
|
||||
;; different endings: both start VU entry 0, one continues the DMA chain and one returns from it.
|
||||
(define *instance-tie-work*
|
||||
(new 'static
|
||||
'instance-tie-work
|
||||
@@ -57,24 +43,9 @@
|
||||
:refl-fade-fac -0.000625
|
||||
:refl-fade-end 409600.0))
|
||||
|
||||
;; Both endings start entry 0 with an MSCAL; only their DMA tag differs. Assigned after the static
|
||||
;; definition because the same field is written twice and the second write is the one that survives.
|
||||
(set! (-> *instance-tie-work* upload-color-2 vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1))
|
||||
|
||||
(set! (-> *instance-tie-work* upload-color-ret vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1))
|
||||
|
||||
;; The same idea for prototype geometry, where the templates are bigger and there are three sets of
|
||||
;; them: ordinary, near, and Generic.
|
||||
;;
|
||||
;; A fragment upload is a palette (128 packed colors to VU 838), then the shaders and strip templates
|
||||
;; as V4-32 at VU 0, then the packed points as V4-8 at 0 and V4-16 at 50. The near path inserts one
|
||||
;; more V4-8 block at 30 for the data its clipper needs.
|
||||
;;
|
||||
;; Two MSCALs are threaded through the middle of that. Entry 4 is empty and exists only to wait for
|
||||
;; the previous VU1 invocation to finish reading the area about to be overwritten; entry 6 installs the
|
||||
;; newly arrived fragment's shader and strip templates into both of its GIF output banks. Putting them
|
||||
;; inside the upload rather than before it lets the palette transfer overlap the previous fragment's
|
||||
;; drawing.
|
||||
(define *prototype-tie-work*
|
||||
(new 'static
|
||||
'prototype-tie-work
|
||||
@@ -165,8 +136,6 @@
|
||||
(new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
:clamp #x8000ff00ff00ff))
|
||||
|
||||
;; Thread the two MSCALs into both upload chains. Same reason as the instance endings above: these
|
||||
;; fields are written twice and the second write wins.
|
||||
(set! (-> *prototype-tie-work* upload-model-1 vif0) (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscal) :msk #x1))
|
||||
|
||||
(set! (-> *prototype-tie-work* upload-model-3 vif0) (new 'static 'vif-tag :imm #x6 :cmd (vif-cmd mscal) :msk #x1))
|
||||
|
||||
@@ -12,33 +12,20 @@
|
||||
;; Each fragment carries its own adgif shaders, packed points, strip packet templates, and a shared
|
||||
;; time-of-day color palette; each instance record carries a transform, a wind phase, a LOD morph
|
||||
;; weight, and the palette indices its vertices should use. Upload the fragment once, then let VU1
|
||||
;; chew through every instance that picked it. That is the whole trick, and it is why a level can
|
||||
;; afford several thousand crates and huts.
|
||||
;; chew through every instance that picked it.
|
||||
;;
|
||||
;; The three interesting details, in the order you will meet them below:
|
||||
;;
|
||||
;; * Level of detail is continuous, not stepped, and it is a tessellation rather than a swap. The
|
||||
;; "tessellating" in the name is literal: a coarser geometry is the same surface with one level of
|
||||
;; subdivision removed. A vertex that exists only at the finer level -- an interpolated point, or
|
||||
;; "dvert" -- was created by splitting an edge, and it stores two vectors: where it was authored,
|
||||
;; and the displacement that puts it back on the edge it split. It also stores the palette indices
|
||||
;; * Level of detail uses a similar strategy to TFRAG where vertices collapse back to the midpoint
|
||||
;; of an edge, creating degenerate triangles that can be removed without any popping.
|
||||
;; These use a different format than tfrag: each simplifying vertex stores its own position
|
||||
;; and the vector to move it back to the edge. It also stores the palette indices
|
||||
;; of that edge's two endpoints. Given t = the instance's morph weight, rising from 0 at the near
|
||||
;; edge of the LOD band to 1 at the far edge:
|
||||
;;
|
||||
;; position = authored + t * displacement
|
||||
;; color = (1 - t) * own + t * (color(parent1) + color(parent2)) / 2
|
||||
;;
|
||||
;; so at t = 1 the vertex has moved onto its parents' edge and taken that edge's shading, the
|
||||
;; surface it belongs to *is* the coarser surface, and the triangles about to disappear are already
|
||||
;; degenerate. Nothing pops. The reciprocal band lengths in the prototype's rdists are what make t
|
||||
;; reach 1 precisely at the plane where the coarser geometry takes over.
|
||||
;;
|
||||
;; Note which half of that is pinned by the hardware and which is data. The color blend is always
|
||||
;; the plain average of the two parents -- the 0.5 is an immediate in the microprogram, not
|
||||
;; something the exporter chooses. The displacement is authored, so nothing here forces the vertex
|
||||
;; to land on the edge midpoint specifically; it is only the color that assumes it did. A collapse
|
||||
;; to any other point on the edge would still be geometrically crack-free but would shade very
|
||||
;; slightly wrong, so midpoint is the reading the two halves agree on.
|
||||
;; so at t = 1 the vertex has moved onto its parents' edge and taken that edge's shading, so
|
||||
;; the degenerate triangle can be removed.
|
||||
;;
|
||||
;; T-junctions and cracks are avoided by a separate and much blunter decision: the LOD is chosen
|
||||
;; per instance, not per fragment, so every fragment of a prototype is always at the same
|
||||
@@ -56,14 +43,9 @@
|
||||
;; owns by an offset carried in its own data. Nothing walks a strip list afterwards to collect
|
||||
;; vertices.
|
||||
;;
|
||||
;; Worth knowing because TFRAG, the other background renderer, is the opposite: it transforms into an
|
||||
;; TFRAG is the opposite design for GIF building: it transforms into an
|
||||
;; intermediate array and then a separate pass walks an exported draw-point table, follows each entry
|
||||
;; to a vertex, and copies it into the GIF buffer through a sequential cursor -- a gather. Almost
|
||||
;; every structural difference between the two follows from that one choice, including why TFRAG can
|
||||
;; redirect a strip by rewriting one record while TIE cannot, and why TIE needs three rotating output
|
||||
;; banks where TFRAG needs two.
|
||||
;;
|
||||
;; Three consequences here, and they explain most of what looks odd further down:
|
||||
;; to a vertex, and copies it into the GIF buffer through a sequential cursor -- a gather.
|
||||
;;
|
||||
;; There is no index buffer, so a vertex used by two triangle strips needs a slot in each. The
|
||||
;; exporter finds those and gives them a second offset; the renderer transforms once and stores the
|
||||
@@ -73,10 +55,7 @@
|
||||
;; tag's count per fragment per frame. So every conditional below changes *what* goes into a slot,
|
||||
;; never *whether* a slot is filled.
|
||||
;;
|
||||
;; And there is no per-vertex branch in the steady state: the tails are handled by duplicating the
|
||||
;; loop once per slot instead of testing, which is why the same twenty instructions appear as flush,
|
||||
;; short, and dual-destination variants.
|
||||
;; * GIF output rotates through three banks, not two, and the reason is entry 6 rather than entry 0.
|
||||
;; * GIF output rotates through three banks, not two, to double buffer fragment and instance swaps.
|
||||
;; Within one fragment the two banks named by gifbuf alternate per instance in the ordinary
|
||||
;; double-buffered way: each entry-0 invocation rotates gifbuf, fills gifbuf.x, kicks it, and
|
||||
;; stops, so the bank being filled is never the bank the GIF is draining. The third bank exists
|
||||
@@ -86,7 +65,6 @@
|
||||
;; the freshly kicked one alone. With two banks it would have to overwrite geometry the GIF had not
|
||||
;; read yet.
|
||||
;;
|
||||
;; What lives where, since the data is spread across four levels of ownership and it matters which:
|
||||
;;
|
||||
;; per level the visibility string. One bit per instance, in BVH order, so a word of zeroes skips
|
||||
;; 32 instances without a transfer.
|
||||
@@ -100,17 +78,11 @@
|
||||
;;
|
||||
;; The palette is the part worth being clear about. The colors themselves belong to the prototype and are
|
||||
;; expanded and uploaded once per prototype per frame, to VU 838, where all of its fragments and all of
|
||||
;; its instances read the same 128 entries. What each instance owns is not colors but *indices* into
|
||||
;; them -- one per vertex, packed four to a quadword for base points and one quadword per interpolated
|
||||
;; point, uploaded to VU 204 with the instance's transform. So two crates built from the same prototype
|
||||
;; share every color yet can be lit completely differently, one standing in sunlight and one in shadow,
|
||||
;; at the cost of one byte per vertex.
|
||||
;; its instances read the same 128 entries. Each prototype has its own indices into
|
||||
;; that per-prototype pallete.
|
||||
;;
|
||||
;; That is also why the palette upload sits *outside* the fragment loop and the index upload *inside*
|
||||
;; the per-instance chain: the expensive thing happens once, the cheap thing happens thousands of times.
|
||||
;;
|
||||
;; GENERIC models can also be routed into the TIE packet path; see generic-tie-convert and
|
||||
;; generic-tie-execute.
|
||||
;; TIE can emit to generic to handle environment maps, but we don't need this on PC: instead we just
|
||||
;; send all TIE to the PC renderers which handles environment mapping.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
@@ -137,7 +109,8 @@
|
||||
"Return the array header size plus storage for its active inline TIE instances."
|
||||
(the-as int (+ (-> drawable-inline-array-instance-tie size) (* (+ (-> this length) -1) 64))))
|
||||
|
||||
;; INFO: this function exists in multiple non-identical object files
|
||||
;; This method is mistakenly duplicated, this earlier definition is overwritten by the later one.
|
||||
;; OpenGOAL flags this as an error, so we comment out on PC.
|
||||
(#unless PC_PORT
|
||||
(defmethod login ((this drawable-tree-instance-tie))
|
||||
"Leave this TIE instance tree unchanged."
|
||||
@@ -223,8 +196,8 @@
|
||||
(dotimes (i (-> this debug-lines length))
|
||||
(+! (-> usage data 14 count) (-> (the-as (pointer int32) (-> this debug-lines i)) 0))
|
||||
(let ((debug-line-bytes (asize-of (the-as basic (-> this debug-lines i)))))
|
||||
;; TODO: the count is charged to tie-debug above, but the bytes are charged to tie-colors
|
||||
;; here. Verify which category the report intends.
|
||||
;; ????: the count is charged to tie-debug above, but the bytes are charged to tie-colors
|
||||
;; here.
|
||||
(+! (-> usage data 12 used) debug-line-bytes)
|
||||
(+! (-> usage data 12 total) (logand -16 (+ debug-line-bytes 15))))))
|
||||
(label cfg-13)
|
||||
@@ -286,11 +259,6 @@
|
||||
;; TIE Renderer
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The nine constant quadwords uploaded to VU1 966 through 974 once per frame. Six carry packet
|
||||
;; templates and the persistent buffer state installed by entry 8; the last three are the alpha-test
|
||||
;; packet and its two selectable TEST states. The overlays let the setup code write each quadword
|
||||
;; through whichever view is convenient -- GS types for the tags, vector for the float-biased
|
||||
;; addresses, qword for the integer bank addresses -- without a pile of casts.
|
||||
(deftype tie-consts (structure)
|
||||
((data uint32 24)
|
||||
(vector vector 6 :inline :overlay-at (-> data 0))
|
||||
@@ -352,23 +320,18 @@
|
||||
;; draining. The third bank is for the fragment boundary. Entry 6 has to write templates into *both*
|
||||
;; banks it will use, and at that moment the last instance of the previous fragment has an outstanding
|
||||
;; kick on one of the two banks it was using. Rotating in the longest-idle bank keeps entry 6 away from
|
||||
;; it. Two banks would not be enough; four would buy nothing.
|
||||
;; it.
|
||||
;;
|
||||
;; Deriving the third address by subtracting the two live ones from their sum costs two vector
|
||||
;; subtractions and no integer lookup, which is the only reason extra.x exists.
|
||||
;;
|
||||
;; Vertices are not assigned to a bank or a slot by their position in the stream. Each vertex carries
|
||||
;; its own destination offset in the w lane of its position quadword; add the current bank's biased
|
||||
;; address, mtir it out, and that is where the triplet goes. No output cursor, no ordering constraint
|
||||
;; between vertices -- which is exactly what lets the render loops keep four of them in flight.
|
||||
;; address, mtir it out, and that is where the triplet goes.
|
||||
;;
|
||||
;; That addressing scheme is also how reuse works. The strip templates are prebuilt with a fixed slot
|
||||
;; per vertex per strip, so there is no index buffer and a vertex belonging to two strips has to appear
|
||||
;; in both. Such a vertex carries a second offset in the w lane of its ST quadword and the
|
||||
;; dual-destination loop variants store the identical ST, RGBAQ and XYZF2 triplet to both slots -- same
|
||||
;; texture coordinates, same time-of-day color, same screen position, transformed once. Anything else
|
||||
;; would show: a position difference opens a crack, and an ST or color difference draws a visible seam
|
||||
;; down the shared edge. Both offsets are inside the bank currently being filled.
|
||||
;; texture coordinates, same time-of-day color, same screen position, transformed once.
|
||||
;;
|
||||
;; The four group-terminating addresses arrive as offsets relative to whichever bank the exporter had
|
||||
;; in mind, so kick-addr remembers the base they are currently expressed against and each instance
|
||||
@@ -1714,14 +1677,8 @@
|
||||
BASE/OFFSET, mode, and cycle state for the packed instance stream. alpha-blend controls the geometry
|
||||
primitive's ABE bit."
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
;; Install the microprogram and set the caller-selected TEST state before any TIE packets.
|
||||
(dma-buffer-add-vu-function dma-buf tie-vu1-block 1)
|
||||
(let* ((v1-3 dma-buf)
|
||||
(direct-packet (the-as dma-packet (-> v1-3 base))))
|
||||
(set! (-> direct-packet dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> direct-packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> direct-packet vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer direct-packet) 16)))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf #x2 (new 'static 'vif-tag) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(let* ((v1-4 dma-buf)
|
||||
(direct-gif (the-as gs-gif-tag (-> v1-4 base))))
|
||||
(set! (-> direct-gif tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
@@ -1732,7 +1689,6 @@
|
||||
(set! (-> (the-as (pointer gs-test) test-data) 0) test-state)
|
||||
(set! (-> (the-as (pointer gs-reg64) test-data) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ test-data 16)))
|
||||
;; Upload tie-consts to VU address 966.
|
||||
(let ((constant-qwc 9))
|
||||
(let* ((v1-6 dma-buf)
|
||||
(constant-packet (the-as dma-packet (-> v1-6 base))))
|
||||
@@ -1742,27 +1698,13 @@
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer constant-packet) 16)))
|
||||
(tie-init-consts (the-as tie-consts (-> dma-buf base)) alpha-blend)
|
||||
(&+! (-> dma-buf base) (* constant-qwc 16)))
|
||||
;; Entry 8 initializes the persistent GIF and instance-bank registers.
|
||||
(let* ((v1-9 dma-buf)
|
||||
(init-packet (the-as dma-packet (-> v1-9 base))))
|
||||
(set! (-> init-packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> init-packet vif0) (new 'static 'vif-tag :imm #x8 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
(set! (-> init-packet vif1) (new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(set! (-> v1-9 base) (&+ (the-as pointer init-packet) 16)))
|
||||
;; #x4b000000 is 2^23. When an upload selects VIF's additive mode, adding a small packed
|
||||
;; integer places it in the mantissa of an exactly representable float; mtir can recover the
|
||||
;; low address or index bits without a separate integer conversion.
|
||||
(let* ((v1-10 dma-buf)
|
||||
(row-packet (the-as dma-packet (-> v1-10 base))))
|
||||
(set! (-> row-packet dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> row-packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> row-packet vif1) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(set! (-> v1-10 base) (&+ (the-as pointer row-packet) 16)))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf
|
||||
0
|
||||
(new 'static 'vif-tag :imm #x8 :cmd (vif-cmd mscalf) :msk #x1)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf #x2 (new 'static 'vif-tag) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
|
||||
(let ((row-data (the-as (pointer uint32) (-> dma-buf base))))
|
||||
(set! (-> (the-as (inline-array vector4w) row-data) 0 x) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) row-data) 0 y) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) row-data) 0 z) #x4b000000)
|
||||
(set! (-> (the-as (inline-array vector4w) row-data) 0 w) #x4b000000)
|
||||
(set-vector! (-> (the-as (inline-array vector4w) row-data) 0) #x4b000000 #x4b000000 #x4b000000 #x4b000000)
|
||||
(set! (-> (the-as (pointer vif-tag) row-data) 4) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> (the-as (pointer vif-tag) row-data) 5) (new 'static 'vif-tag :imm #x2c :cmd (vif-cmd offset)))
|
||||
(set! (-> (the-as (pointer vif-tag) row-data) 6) (new 'static 'vif-tag :cmd (vif-cmd stmod)))
|
||||
@@ -1776,32 +1718,15 @@
|
||||
"Append the TIE shutdown packets, restoring the normal GS TEST state and clearing the VIF mask,
|
||||
mode, and ROW state changed by tie-init-engine."
|
||||
(when (logtest? *vu1-enable-user* (vu1-renderer-mask tie))
|
||||
;; Restore the ordinary alpha/depth test used after TIE drawing.
|
||||
(let* ((v1-3 dma-buf)
|
||||
(direct-packet (the-as dma-packet (-> v1-3 base))))
|
||||
(set! (-> direct-packet dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> direct-packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> direct-packet vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer direct-packet) 16)))
|
||||
(let* ((v1-4 dma-buf)
|
||||
(direct-gif (the-as gs-gif-tag (-> v1-4 base))))
|
||||
(set! (-> direct-gif tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
|
||||
(set! (-> direct-gif regs) GIF_REGS_ALL_AD)
|
||||
(set! (-> v1-4 base) (&+ (the-as pointer direct-gif) 16)))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf #x2 (new 'static 'vif-tag) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
|
||||
(dma-buffer-add-gif-tag dma-buf (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1) GIF_REGS_ALL_AD)
|
||||
(let* ((v1-5 dma-buf)
|
||||
(test-data (-> v1-5 base)))
|
||||
(set! (-> (the-as (pointer gs-test) test-data) 0)
|
||||
(new 'static 'gs-test :atst (gs-atest not-equal) :zte #x1 :ztst (gs-ztest greater-equal)))
|
||||
(set! (-> (the-as (pointer gs-reg64) test-data) 1) (gs-reg64 test-1))
|
||||
(set! (-> v1-5 base) (&+ test-data 16)))
|
||||
;; Clear the VIF mask, run the empty entry 4 to finish the VU invocation, and restore the
|
||||
;; default mode and all-zero ROW register for the following renderer.
|
||||
(let* ((v1-6 dma-buf)
|
||||
(mask-packet (the-as dma-packet (-> v1-6 base))))
|
||||
(set! (-> mask-packet dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
|
||||
(set! (-> mask-packet vif0) (new 'static 'vif-tag :cmd (vif-cmd stmask)))
|
||||
(set! (-> mask-packet vif1) (new 'static 'vif-tag))
|
||||
(set! (-> v1-6 base) (&+ (the-as pointer mask-packet) 16)))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf #x2 (new 'static 'vif-tag :cmd (vif-cmd stmask)) (new 'static 'vif-tag))
|
||||
(let* ((v1-7 dma-buf)
|
||||
(reset-data (the-as (pointer uint32) (-> v1-7 base))))
|
||||
(set! (-> (the-as (pointer vif-tag) reset-data) 0) (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd mscalf) :msk #x1))
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
(defmethod setup-params! ((this sync-info) (period uint) (phase float) (ease-out float) (ease-in float))
|
||||
"Set the period in 300 Hz game-time ticks and the initial phase as a fraction of that period.
|
||||
The base clock ignores ease-out and ease-in, which are retained for the shared subtype interface."
|
||||
The base sync-info class ignores ease-out and ease-in."
|
||||
(set! (-> this period) period)
|
||||
(let* ((period-float (the float period))
|
||||
(phase-ticks (* phase period-float)))
|
||||
@@ -75,9 +75,8 @@
|
||||
phase; the period is converted to 300 Hz game-time ticks. Return true when the resource exists,
|
||||
otherwise install the supplied defaults and return false. The base clock ignores default-ease-out
|
||||
and default-ease-in."
|
||||
(local-vars (sync-tag res-tag))
|
||||
(set! sync-tag (new 'static 'res-tag))
|
||||
(let ((params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(let* ((sync-tag (new 'static 'res-tag))
|
||||
(params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(cond
|
||||
(params
|
||||
(setup-params! this
|
||||
@@ -86,53 +85,57 @@
|
||||
0.15
|
||||
0.15)
|
||||
#t)
|
||||
(else (setup-params! this default-period default-phase 0.15 0.15) #f))))
|
||||
(else
|
||||
(setup-params! this default-period default-phase 0.15 0.15)
|
||||
#f))))
|
||||
|
||||
(defmethod load-params! ((this sync-info-eased) (proc process) (default-period uint) (default-phase float) (default-ease-out float) (default-ease-in float))
|
||||
"Load the sync resource from proc. Four floats supply period seconds, initial phase,
|
||||
ease-out, and ease-in; a two-value resource uses the supplied easing defaults. Return true when the
|
||||
resource exists, otherwise install every supplied default and return false."
|
||||
(local-vars (sync-tag res-tag))
|
||||
(set! sync-tag (new 'static 'res-tag))
|
||||
(let ((params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(let* ((sync-tag (new 'static 'res-tag))
|
||||
(params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(cond
|
||||
(params
|
||||
(if (>= (-> sync-tag elt-count) (the-as uint 4))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
(-> (the-as (pointer float) params) 2)
|
||||
(-> (the-as (pointer float) params) 3))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
default-ease-out
|
||||
default-ease-in))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
(-> (the-as (pointer float) params) 2)
|
||||
(-> (the-as (pointer float) params) 3))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
default-ease-out
|
||||
default-ease-in))
|
||||
#t)
|
||||
(else (setup-params! this default-period default-phase default-ease-out default-ease-in) #f))))
|
||||
(else
|
||||
(setup-params! this default-period default-phase default-ease-out default-ease-in)
|
||||
#f))))
|
||||
|
||||
(defmethod load-params! ((this sync-info-paused) (proc process) (default-period uint) (default-phase float) (default-pause-after-out float) (default-pause-after-in float))
|
||||
"Load the sync resource from proc. Four floats supply period seconds, initial phase,
|
||||
pause-after-out, and pause-after-in; a two-value resource uses the supplied pause defaults. Return
|
||||
true when the resource exists, otherwise install every supplied default and return false."
|
||||
(local-vars (sync-tag res-tag))
|
||||
(set! sync-tag (new 'static 'res-tag))
|
||||
(let ((params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(let* ((sync-tag (new 'static 'res-tag))
|
||||
(params (res-lump-data (-> proc entity) 'sync pointer :tag-ptr (& sync-tag))))
|
||||
(cond
|
||||
(params
|
||||
(if (>= (-> sync-tag elt-count) (the-as uint 4))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
(-> (the-as (pointer float) params) 2)
|
||||
(-> (the-as (pointer float) params) 3))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
default-pause-after-out
|
||||
default-pause-after-in))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
(-> (the-as (pointer float) params) 2)
|
||||
(-> (the-as (pointer float) params) 3))
|
||||
(setup-params! this
|
||||
(the-as uint (the int (* 300.0 (-> (the-as (pointer float) params) 0))))
|
||||
(-> (the-as (pointer float) params) 1)
|
||||
default-pause-after-out
|
||||
default-pause-after-in))
|
||||
#t)
|
||||
(else (setup-params! this default-period default-phase default-pause-after-out default-pause-after-in) #f))))
|
||||
(else
|
||||
(setup-params! this default-period default-phase default-pause-after-out default-pause-after-in)
|
||||
#f))))
|
||||
|
||||
(defmethod get-current-phase-no-mod ((this sync-info))
|
||||
"Return the base clock's wrapped phase from 0 through 1 without applying a subtype's easing
|
||||
|
||||
@@ -286,6 +286,57 @@ TEST(Demacro, Jak1RecognizesDmaBucketConstruction) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Demacro, Jak1RecognizesDmaCntPacketsWithExplicitQwc) {
|
||||
const auto rules =
|
||||
demacro::load_rules(file_util::get_file_path({"decompiler/config/jak1/demacro.jsonc"}));
|
||||
const std::string source = R"((begin
|
||||
(let* ((dma-state dma-buf)
|
||||
(mask-packet (the-as object (-> dma-state base))))
|
||||
(set! (-> (the-as dma-packet mask-packet) dma)
|
||||
(new 'static 'dma-tag :qwc #x3 :id (dma-tag-id cnt)))
|
||||
(set! (-> (the-as dma-packet mask-packet) vif0)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd stmask)))
|
||||
(set! (-> (the-as dma-packet mask-packet) vif1) (new 'static 'vif-tag))
|
||||
(set! (-> dma-state base) (&+ (the-as pointer mask-packet) 16)))
|
||||
(let* ((dma-state dma-buf)
|
||||
(packet (the-as dma-packet (-> dma-state base))))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :qwc qwc :id (dma-tag-id cnt)))
|
||||
(set! (-> packet vif0) vif0)
|
||||
(set! (-> packet vif1) vif1)
|
||||
(set! (-> dma-state base) (&+ (the-as pointer packet) 16))))
|
||||
)";
|
||||
const auto result = demacro::rewrite(source, rules);
|
||||
EXPECT_EQ(result.rewrite_count(), 2);
|
||||
EXPECT_EQ(result.source, R"((begin
|
||||
(dma-buffer-add-cnt-vif2 dma-buf #x3 (new 'static 'vif-tag :cmd (vif-cmd stmask)) (new 'static 'vif-tag))
|
||||
(dma-buffer-add-cnt-vif2 dma-buf qwc vif0 vif1))
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Demacro, Jak1RecognizesDmaNextPackets) {
|
||||
const auto rules =
|
||||
demacro::load_rules(file_util::get_file_path({"decompiler/config/jak1/demacro.jsonc"}));
|
||||
const std::string source = R"((begin
|
||||
(let ((packet (the-as object (-> dma-buf base))))
|
||||
(set! (-> (the-as dma-packet packet) dma)
|
||||
(new 'static 'dma-tag :id (dma-tag-id next) :addr next-address))
|
||||
(set! (-> (the-as dma-packet packet) vif0) vif0)
|
||||
(set! (-> (the-as dma-packet packet) vif1) vif1)
|
||||
(set! (-> dma-buf base) (&+ (the-as pointer packet) 16)))
|
||||
(let ((packet (the-as dma-packet (-> dma-buf base))))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> packet vif1) (new 'static 'vif-tag))
|
||||
(set! (-> dma-buf base) (&+ (the-as pointer packet) 16))))
|
||||
)";
|
||||
const auto result = demacro::rewrite(source, rules);
|
||||
EXPECT_EQ(result.rewrite_count(), 2);
|
||||
EXPECT_EQ(result.source, R"((begin
|
||||
(dma-buffer-add-next-vif2 dma-buf 0 next-address vif0 vif1)
|
||||
(dma-buffer-add-next-vif2 dma-buf 0 0 (new 'static 'vif-tag) (new 'static 'vif-tag)))
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Demacro, Jak1RecognizesInlinedFontEnumSetters) {
|
||||
const auto rules =
|
||||
demacro::load_rules(file_util::get_file_path({"decompiler/config/jak1/demacro.jsonc"}));
|
||||
|
||||
Reference in New Issue
Block a user