up to collide-probe

This commit is contained in:
water111
2026-08-31 15:10:16 -07:00
parent 0de650cd31
commit 251b0659cb
21 changed files with 3466 additions and 4730 deletions
+23
View File
@@ -327,6 +327,29 @@
"rewrite":
"(dma-buffer-add-cnt-vif2 $buf $qwc $vif0 $vif1)"
},
{
// A direct buffer cursor needs no alias binding, so let insertion leaves a single let.
"name": "dma-buffer-add-cnt-vif2-direct-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 cnt))) (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-cnt-vif2 $buf 0 $vif0 $vif1)"
},
{
// Constructor keyword order follows the original instruction order and is not canonicalized.
"name": "dma-buffer-add-cnt-vif2-qwc-after-id-object-packet",
"match":
"(let* (($alias $buf) ($packet (the-as object (-> $alias base)))) (set! (-> (the-as dma-packet $packet) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc $qwc)) (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-ref-vif2-object-packet",
"match":
"(let (($packet (the-as object (-> $buf base)))) (set! (-> (the-as dma-packet $packet) dma) (new 'static 'dma-tag :qwc $qwc :id (dma-tag-id ref) :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-ref-vif2 $buf $qwc $addr $vif0 $vif1)"
},
{
"name": "dma-buffer-add-next-vif2-object-packet",
"match":
@@ -2740,6 +2740,13 @@
[2, "v1", "(pointer process-drawable)"]
],
"update-time-of-day": [[46, "v0", "(array float)"]],
"sky-add-frame-data": [
[[3, 16], "a1", "dma-packet"],
[[18, 75], "a0", "sky-frame-data"],
[[92, 103], "v1", "dma-packet"]
],
"sky-upload": [[[11, 22], "v1", "dma-packet"]],
"sky-draw": [[[1, 12], "a0", "dma-packet"]],
"sky-make-light": [[[10, 23], "a0", "sky-sun-data"]],
"make-sky-textures": [
[[90, 94], "a0", "dma-packet"],
-2
View File
@@ -161,7 +161,6 @@ set(RUNTIME_SOURCE
mips2c/jak1_functions/collide_cache.cpp
mips2c/jak1_functions/collide_edge_grab.cpp
mips2c/jak1_functions/collide_mesh.cpp
mips2c/jak1_functions/collide_probe.cpp
mips2c/jak1_functions/generic_merc.cpp
mips2c/jak1_functions/merc_blend_shape.cpp
mips2c/jak1_functions/ocean_vu0.cpp
@@ -170,7 +169,6 @@ set(RUNTIME_SOURCE
mips2c/jak1_functions/sky_tng.cpp
mips2c/jak1_functions/test_func.cpp
mips2c/jak1_functions/texture.cpp
mips2c/jak1_functions/time_of_day.cpp
mips2c/jak2_functions/bones.cpp
mips2c/jak2_functions/collide_cache.cpp
File diff suppressed because it is too large Load Diff
-272
View File
@@ -1,272 +0,0 @@
//--------------------------MIPS2C---------------------
#include "game/kernel/jak1/kscheme.h"
#include "game/mips2c/mips2c_private.h"
using namespace jak1;
// clang-format off
namespace Mips2C::jak1 {
namespace time_of_day_interp_colors_scratch {
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, -16); // daddiu sp, sp, -16
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
// nop // sll r0, r0, 0
c->lui(v1, 28672); // lui v1, 28672 0x7000
c->daddiu(t4, a1, 12); // daddiu t4, a1, 12
//c->ori(v1, v1, 2064); // ori v1, v1, 2064 SPAD mods
get_fake_spad_addr(v1, cache.fake_scratchpad_data, 2064, c);
// Unknown instr: ld a3, L168(fp)
// L168:
// .word 0xff00ff
// .word 0x8000ff
c->gprs[a3].du32[0] = 0xff00ff;
c->gprs[a3].du32[1] = 0x8000ff;
c->lui(t0, 4096); // lui t0, 4096
c->lw(t1, 4, a1); // lw t1, 4(a1)
c->ori(a1, t0, 54272); // ori a1, t0, 54272 = (0x1000D400) SPR TO
c->lq(t0, 1852, a2); // lq t0, 1852(a2)
c->addiu(t2, t1, 31); // addiu t2, t1, 31
c->lq(t1, 1868, a2); // lq t1, 1868(a2)
c->sra(t3, t2, 5); // sra t3, t2, 5
c->lq(t2, 1884, a2); // lq t2, 1884(a2)
c->sll(t3, t3, 5); // sll t3, t3, 5
c->lq(a2, 1900, a2); // lq a2, 1900(a2)
// wait for DMA to finish, can just remove this
/*
block_1:
c->lw(t5, 0, a1); // lw t5, 0(a1)
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
c->andi(t5, t5, 256); // andi t5, t5, 256
// nop // sll r0, r0, 0
bc = c->sgpr64(t5) != 0; // bne t5, r0, L62
// nop // sll r0, r0, 0
if (bc) {goto block_1;} // branch non-likely
*/
{
// c->sw(t4, 16, a1); // sw t4, 16(a1)
u32 madr = c->sgpr64(t4);
c->daddiu(t3, t3, -32); // daddiu t3, t3, -32
// c->sw(v1, 128, a1); // sw v1, 128(a1)
u32 sadr = c->sgpr64(v1);
c->addiu(t5, r0, 64); // addiu t5, r0, 64
//c->sw(t5, 32, a1); // sw t5, 32(a1)
u32 qwc = c->sgpr64(t5);
c->addiu(t5, r0, 256); // addiu t5, r0, 256
// c->sw(t5, 0, a1); // sw t5, 0(a1)
spad_to_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
c->daddiu(t4, t4, 1024); // daddiu t4, t4, 1024
}
block_3:
c->mov64(t6, v1); // or t6, v1, r0
c->xori(v1, v1, 1024); // xori v1, v1, 1024
bc = ((s64)c->sgpr64(t3)) <= 0; // blez t3, L66
c->daddiu(t3, t3, -32); // daddiu t3, t3, -32
if (bc) {goto block_7;} // branch non-likely
/*
block_4:
c->lw(t5, 0, a1); // lw t5, 0(a1)
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
c->andi(t5, t5, 256); // andi t5, t5, 256
// nop // sll r0, r0, 0
bc = c->sgpr64(t5) == 0; // beq t5, r0, L65
// nop // sll r0, r0, 0
if (bc) {goto block_6;} // branch non-likely
// 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
//beq r0, r0, L64 // beq r0, r0, L64
// nop // sll r0, r0, 0
goto block_4; // branch always
*/
{
// block_6:
// c->sw(t4, 16, a1); // sw t4, 16(a1)
u32 madr = c->sgpr64(t4);
// nop // sll r0, r0, 0
// c->sw(v1, 128, a1); // sw v1, 128(a1)
u32 sadr = c->sgpr64(v1);
c->addiu(t5, r0, 64); // addiu t5, r0, 64
// c->sw(t5, 32, a1); // sw t5, 32(a1)
u32 qwc = c->sgpr64(t5);
c->addiu(t5, r0, 256); // addiu t5, r0, 256
// c->sw(t5, 0, a1); // sw t5, 0(a1)
spad_to_dma(cache.fake_scratchpad_data, madr, sadr, qwc);
c->daddiu(t4, t4, 1024); // daddiu t4, t4, 1024
//beq r0, r0, L67 // beq r0, r0, L67
// nop // sll r0, r0, 0
}
goto block_9; // branch always
block_7:
/*
c->lw(t5, 0, a1); // lw t5, 0(a1)
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
c->andi(t5, t5, 256); // andi t5, t5, 256
// nop // sll r0, r0, 0
bc = c->sgpr64(t5) == 0; // beq t5, r0, L67
// nop // sll r0, r0, 0
if (bc) {goto block_9;} // branch non-likely
// 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
//beq r0, r0, L66 // beq r0, r0, L66
// nop // sll r0, r0, 0
goto block_7; // branch always
*/
/*
fmt::print("{} -> {} [{}]\n", c->gprs[a0].du32[0], c->gprs[t5].du32[0], c->gprs[t3].ds64[0]);
fmt::print("[2] t0: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t0].du16[0], c->gprs[t0].du16[1], c->gprs[t0].du16[2], c->gprs[t0].du16[3], c->gprs[t0].du16[4], c->gprs[t0].du16[5], c->gprs[t0].du16[6], c->gprs[t0].du16[7]);
fmt::print("[2] t1: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t1].du16[0], c->gprs[t1].du16[1], c->gprs[t1].du16[2], c->gprs[t1].du16[3], c->gprs[t1].du16[4], c->gprs[t1].du16[5], c->gprs[t1].du16[6], c->gprs[t1].du16[7]);
fmt::print("[2] t2: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t2].du16[0], c->gprs[t2].du16[1], c->gprs[t2].du16[2], c->gprs[t2].du16[3], c->gprs[t2].du16[4], c->gprs[t2].du16[5], c->gprs[t2].du16[6], c->gprs[t2].du16[7]);
fmt::print("[2] a2: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}\n", c->gprs[a2].du16[0], c->gprs[a2].du16[1], c->gprs[a2].du16[2], c->gprs[a2].du16[3], c->gprs[a2].du16[4], c->gprs[a2].du16[5], c->gprs[a2].du16[6], c->gprs[a2].du16[7]);
*/
block_9:
c->lq(t9, 12, t6); // lq t9, 12(t6)
c->daddiu(t5, a0, 128); // daddiu t5, a0, 128
c->lq(t7, 28, t6); // lq t7, 28(t6)
// nop // sll r0, r0, 0
c->pextlb(t8, r0, t9); // pextlb t8, r0, t9
c->mfc1(r0, f31); // mfc1 r0, f31
c->pextub(t9, r0, t9); // pextub t9, r0, t9
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmulth(r0, t8, t0); // pmulth r0, t8, t0
c->mfc1(r0, f31); // mfc1 r0, f31
c->pextlb(t8, r0, t7); // pextlb t8, r0, t7
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmaddh(r0, t9, t1); // pmaddh r0, t9, t1
c->mfc1(r0, f31); // mfc1 r0, f31
c->pextub(t7, r0, t7); // pextub t7, r0, t7
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmaddh(r0, t8, t2); // pmaddh r0, t8, t2
c->lq(t8, 44, t6); // lq t8, 44(t6)
c->addiu(t6, t6, 32); // addiu t6, t6, 32
// nop // sll r0, r0, 0
c->pmaddh(r0, t7, a2); // pmaddh r0, t7, a2
c->lq(t7, 28, t6); // lq t7, 28(t6)
c->pextlb(t9, r0, t8); // pextlb t9, r0, t8
c->mfc1(r0, f31); // mfc1 r0, f31
block_10:
c->pextub(t8, r0, t8); // pextub t8, r0, t8
// fmt::print("[0] t1: {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t1].du32[0], c->gprs[t1].du32[1], c->gprs[t1].du32[2], c->gprs[t1].du32[3]);
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmfhl_lh(ra); // pmfhl.lh ra
// fmt::print("[1] ra: {:02x} {:02x} {:02x} {:02x}\n", c->gprs[ra].du32[0], c->gprs[ra].du32[1], c->gprs[ra].du32[2], c->gprs[ra].du32[3]);
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmulth(r0, t9, t0); // pmulth r0, t9, t0
c->mfc1(r0, f31); // mfc1 r0, f31
c->psrlh(t9, ra, 6); // psrlh t9, ra, 6
// fmt::print("[3] t9: {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t9].du32[0], c->gprs[t9].du32[1], c->gprs[t9].du32[2], c->gprs[t9].du32[3]);
c->mfc1(r0, f31); // mfc1 r0, f31
c->pcpyud(ra, t9, t9); // pcpyud ra, t9, t9
c->mfc1(r0, f31); // mfc1 r0, f31
c->paddh(t9, ra, t9); // paddh t9, ra, t9
c->mfc1(r0, f31); // mfc1 r0, f31
c->pminh(t9, t9, a3); // pminh t9, t9, a3
c->mfc1(r0, f31); // mfc1 r0, f31
c->ppacb(ra, r0, t9); // ppacb ra, r0, t9
c->mfc1(r0, f31); // mfc1 r0, f31
c->pextlb(t9, r0, t7); // pextlb t9, r0, t7
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmaddh(r0, t8, t1); // pmaddh r0, t8, t1
c->sw(ra, 0, a0); // sw ra, 0(a0)
c->pextub(t7, r0, t7); // pextub t7, r0, t7
c->mfc1(r0, f31); // mfc1 r0, f31
c->pmaddh(r0, t9, t2); // pmaddh r0, t9, t2
c->lq(t8, 44, t6); // lq t8, 44(t6)
c->addiu(t6, t6, 32); // addiu t6, t6, 32
c->addiu(a0, a0, 4); // addiu a0, a0, 4
c->pmaddh(r0, t7, a2); // pmaddh r0, t7, a2
c->lq(t7, 28, t6); // lq t7, 28(t6)
/*
fmt::print(" N0");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
fmt::print(" {:02x}", c->gprs[t8].du8[i*4 + j]);
}
fmt::print(" |");
}
fmt::print("\n N1");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
fmt::print(" {:02x}", c->gprs[t7].du8[i*4 + j]);
}
fmt::print(" |");
}
fmt::print("\n");
*/
// fmt::print("next: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}\n", c->gprs[t8].du32[0], c->gprs[t8].du32[1], c->gprs[t8].du32[2], c->gprs[t8].du32[3],
// c->gprs[t7].du32[0], c->gprs[t7].du32[1], c->gprs[t7].du32[2], c->gprs[t7].du32[3]);
bc = c->sgpr64(a0) != c->sgpr64(t5); // bne a0, t5, L68
c->pextlb(t9, r0, t8); // pextlb t9, r0, t8
if (bc) {goto block_10;} // branch non-likely
bc = ((s64)c->sgpr64(t3)) >= 0; // bgez t3, L63
// nop // sll r0, r0, 0
if (bc) {goto block_3;} // branch non-likely
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
c->ld(ra, 0, sp); // ld ra, 0(sp)
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
// 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("time-of-day-interp-colors-scratch", execute, 512);
}
} // namespace time_of_day_interp_colors_scratch
} // namespace Mips2C
+22 -18
View File
@@ -25,28 +25,28 @@
;; moving-sphere-moving-sphere-intersect
;; unused
(defconstant COLLISION_MISS -100000000.0)
(defglobalconstant COLLIDE_FUNC_COUNTERS #t)
(#when COLLIDE_FUNC_COUNTERS
(define *raw-ray-sphere-intersect-count* 0)
(define *ray-sphere-intersect-count* 0)
(define *ray-circle-intersect-count* 0)
(define *ray-cylinder-intersect-count* 0)
(define *collide-do-primitives-count* 0)
(define *moving-sphere-triangle-intersect-count* 0)
(define *moving-sphere-sphere-intersect-count* 0)
(define *moving-sphere-moving-sphere-intersect-count* 0)
)
(define *raw-ray-sphere-intersect-count* 0)
(define *ray-sphere-intersect-count* 0)
(define *ray-circle-intersect-count* 0)
(define *ray-cylinder-intersect-count* 0)
(define *collide-do-primitives-count* 0)
(define *moving-sphere-triangle-intersect-count* 0)
(define *moving-sphere-sphere-intersect-count* 0)
(define *moving-sphere-moving-sphere-intersect-count* 0)
(define *collide-probe-make-list-count* 0)
(define *collide-probe-make-list-item-count* 0)
(define *collide-probe-make-list-timer* (new 'global 'stopwatch)))
(defun raw-ray-sphere-intersect ((origin vector) (direction vector) (radius float))
"Check if a ray intersects a sphere at the origin.
Return the fraction along the ray where the intersection occurs, or COLLISION_MISS
if there is no collision."
;; This function is rewritten in plain GOAL
;; Parameterize the ray with:
;; ray(t) = origin + t * direction with 0 <= t <= 1
;; A point p is on the origin if:
@@ -62,10 +62,8 @@
;; a = dot(dir, dir)
;; b = dot(dir, origin)
;; c = dot(origin, origin) - r^2
(#when COLLIDE_FUNC_COUNTERS
(+! *raw-ray-sphere-intersect-count* 1))
;; this matches the order of operations in the original, just in case rounding matters.
(let ((c (+ (+ (square (-> origin x))
(square (-> origin y)))
@@ -464,10 +462,9 @@
(set! contact-fraction COLLISION_MISS)))
contact-fraction))
(#when COLLIDE_FUNC_COUNTERS
(defun clear-collide-func-counters ()
"Clear the collision function counters at the start of a frame."
"Clear the collision function counters and probe-list profile at the start of a frame."
(set! *raw-ray-sphere-intersect-count* 0)
(set! *ray-sphere-intersect-count* 0)
(set! *ray-circle-intersect-count* 0)
@@ -476,10 +473,12 @@
(set! *moving-sphere-triangle-intersect-count* 0)
(set! *moving-sphere-sphere-intersect-count* 0)
(set! *moving-sphere-moving-sphere-intersect-count* 0)
(set! *collide-probe-make-list-count* 0)
(set! *collide-probe-make-list-item-count* 0)
(stopwatch-init *collide-probe-make-list-timer*)
(none))
(defun display-collide-func-counters ()
"Display the collision function counters, three per line."
"Display the collision function counters and probe-list frame totals."
(format *stdcon*
" krrs ~7D rs ~7D rc ~7D~%"
*raw-ray-sphere-intersect-count*
@@ -494,4 +493,9 @@
" mss ~7D msms ~7D~%"
*moving-sphere-sphere-intersect-count*
*moving-sphere-moving-sphere-intersect-count*)
(format *stdcon*
" probe-list ~7D calls ~7D items ~3D us~%"
*collide-probe-make-list-count*
*collide-probe-make-list-item-count*
(the int (* 1000000.0 (stopwatch-elapsed-seconds *collide-probe-make-list-timer*))))
(none)))
@@ -0,0 +1,955 @@
(#unless PC_PORT
;; A BASIC value points just after its allocation's type word. Raw EE loads from such a value
;; therefore subtract four from the displayed field offset.
(defconstant PROBE-BASIC-BIAS 4)
(defconstant PROBE-STACK-CHILD (offset-of collide-probe-stack-elem child)) ;; 0
(defconstant PROBE-STACK-COUNT (offset-of collide-probe-stack-elem count)) ;; 4
;; The work kind occupies the high halfword of collide-probe-stack-elem.count.
(defconstant PROBE-STACK-KIND (+ (offset-of collide-probe-stack-elem count) 2)) ;; 6
(defconstant PROBE-STACK-STRIDE (type-size collide-probe-stack-elem)) ;; 8
(defconstant PROBE-DRAWABLE-CHILD-COUNT (- (offset-of draw-node child-count) PROBE-BASIC-BIAS)) ;; 2
(defconstant PROBE-DRAWABLE-FLAGS (- (offset-of draw-node flags) PROBE-BASIC-BIAS)) ;; 3
(defconstant PROBE-DRAWABLE-CHILD (- (offset-of draw-node child) PROBE-BASIC-BIAS)) ;; 4
;; The same four-byte payload is draw-node.child or collide-fragment.mesh according to work kind.
(defconstant PROBE-CANDIDATE-PAYLOAD PROBE-DRAWABLE-CHILD)
(defconstant PROBE-DRAWABLE-BSPHERE (- (offset-of draw-node bsphere) PROBE-BASIC-BIAS)) ;; 12
(defconstant PROBE-DRAW-NODE-STRIDE (type-size draw-node)) ;; 32
(defconstant PROBE-INSTANCE-STRIDE (type-size instance-tie)) ;; 64
(defconstant PROBE-FRAGMENT-STRIDE (type-size collide-fragment)) ;; 32
(defconstant PROBE-FRAGMENT-MESH (- (offset-of collide-fragment mesh) PROBE-BASIC-BIAS)) ;; 4
(defconstant PROBE-BUCKET-COLLIDE-FRAG (- (offset-of prototype-bucket-tie collide-frag) PROBE-BASIC-BIAS)) ;; 136
(defconstant PROBE-FRAGMENT-ARRAY-LENGTH (- (offset-of drawable-inline-array-collide-fragment length) PROBE-BASIC-BIAS)) ;; 2
;; data is an inline BASIC array. This displacement passes its type word and lands on the first
;; collide-fragment's GOAL pointer.
(defconstant PROBE-FRAGMENT-ARRAY-DATA (offset-of drawable-inline-array-collide-fragment data 0)) ;; 32
(defconstant PROBE-INSTANCE-BUCKET (- (offset-of instance-tie bucket-ptr) PROBE-BASIC-BIAS)) ;; 8
(defconstant PROBE-INSTANCE-BSPHERE (- (offset-of instance-tie bsphere) PROBE-BASIC-BIAS)) ;; 12
(defconstant PROBE-INSTANCE-ORIGIN-LOW (- (offset-of instance-tie origin data 0) PROBE-BASIC-BIAS)) ;; 28
(defconstant PROBE-INSTANCE-MAX-SCALE (- (offset-of instance-tie max-scale) PROBE-BASIC-BIAS)) ;; 34
(defconstant PROBE-INSTANCE-FLAGS (- (offset-of instance-tie flags) PROBE-BASIC-BIAS)) ;; 42
(defconstant PROBE-INSTANCE-ORIGIN-HIGH (- (offset-of instance-tie origin data 8) PROBE-BASIC-BIAS)) ;; 44
(defconstant PROBE-QUERY-MIN (offset-of collide-work collide-box4w min)) ;; 16
(defconstant PROBE-QUERY-MAX (offset-of collide-work collide-box4w max)) ;; 32
(defconstant PROBE-QUERY-ROW-X (offset-of collide-work inv-mat vector 0)) ;; 48
(defconstant PROBE-QUERY-ROW-Y (offset-of collide-work inv-mat vector 1)) ;; 64
(defconstant PROBE-QUERY-ROW-Z (offset-of collide-work inv-mat vector 2)) ;; 80
(defconstant PROBE-QUERY-TRANSLATION (offset-of collide-work inv-mat vector 3)) ;; 96
(defconstant PROBE-RESULT-COUNT (offset-of collide-list num-items)) ;; 0
(defconstant PROBE-RESULT-ITEMS (offset-of collide-list items 0)) ;; 16
;; collide-list-item is eight bytes as a structure, but this fixed inline array gives each
;; physical slot sixteen-byte alignment.
(defconstant PROBE-RESULT-ITEM-STRIDE 16)
(defconstant PROBE-RESULT-MESH (offset-of collide-list-item mesh)) ;; 0
(defconstant PROBE-RESULT-INSTANCE (offset-of collide-list-item inst))) ;; 4
;; The inverse probe transform establishes an axis-aligned box space for the rotated line-sphere
;; query. Entry 0 transforms four bounding spheres into that space and leaves integer minimum and
;; maximum corners in vf9..vf16. Entry 32 rebuilds a compressed TIE instance transform around its
;; world bounding-sphere center and composes it with the probe transform. Entry 54 uses the composed
;; transform and the instance's maximum scale to conservatively bound four prototype fragments;
;; vf22.x/y/z/w holds one scaled radius for each sphere. The EE rejects the resulting boxes against
;; collide-work.collide-box4w.
(#unless PC_PORT
(defvu0 collide-vu0-block
(rlet ((probe-row-x :reg vf01)
(probe-row-y :reg vf02)
(probe-row-z :reg vf03)
(probe-translation :reg vf04)
(sphere-0 :reg vf05)
(sphere-1 :reg vf06)
(sphere-2 :reg vf07)
(sphere-3 :reg vf08)
(min-0 :reg vf09)
(max-0 :reg vf10)
(min-1 :reg vf11)
(max-1 :reg vf12)
(min-2 :reg vf13)
(max-2 :reg vf14)
(min-3 :reg vf15)
(max-3 :reg vf16))
;; Transform the four centers and expand each result by its source sphere radius.
(vu-pair (nop) (mulaw.xyzw ACC probe-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC probe-row-x sphere-0))
(vu-pair (nop) (madday.xyzw ACC probe-row-y sphere-0))
(vu-pair (nop) (maddz.xyz sphere-0 probe-row-z sphere-0))
(vu-pair (nop) (mulaw.xyzw ACC probe-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC probe-row-x sphere-1))
(vu-pair (nop) (madday.xyzw ACC probe-row-y sphere-1))
(vu-pair (nop) (maddz.xyz sphere-1 probe-row-z sphere-1))
(vu-pair (nop) (mulaw.xyzw ACC probe-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC probe-row-x sphere-2))
(vu-pair (nop) (madday.xyzw ACC probe-row-y sphere-2))
(vu-pair (nop) (maddz.xyz sphere-2 probe-row-z sphere-2))
(vu-pair (nop) (mulaw.xyzw ACC probe-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC probe-row-x sphere-3))
(vu-pair (nop) (madday.xyzw ACC probe-row-y sphere-3))
(vu-pair (nop) (maddz.xyz sphere-3 probe-row-z sphere-3))
(vu-pair (nop) (subw.xyz min-0 sphere-0 sphere-0))
(vu-pair (nop) (subw.xyz min-1 sphere-1 sphere-1))
(vu-pair (nop) (subw.xyz min-2 sphere-2 sphere-2))
(vu-pair (nop) (subw.xyz min-3 sphere-3 sphere-3))
(vu-pair (nop) (addw.xyz max-0 sphere-0 sphere-0))
(vu-pair (nop) (addw.xyz max-1 sphere-1 sphere-1))
(vu-pair (nop) (addw.xyz max-2 sphere-2 sphere-2))
(vu-pair (nop) (addw.xyz max-3 sphere-3 sphere-3))
(vu-pair (nop) (ftoi0.xyzw min-0 min-0))
(vu-pair (nop) (ftoi0.xyzw min-1 min-1))
(vu-pair (nop) (ftoi0.xyzw min-2 min-2))
(vu-pair (nop) (ftoi0.xyzw min-3 min-3))
(vu-pair (nop) (ftoi0.xyzw max-0 max-0))
(vu-pair (nop) (ftoi0.xyzw max-1 max-1))
(vu-pair (nop) (ftoi0.xyzw max-2 max-2 :e))
(vu-pair (nop) (ftoi0.xyzw max-3 max-3)))
(label compose-instance-transform)
(rlet ((probe-row-x :reg vf01)
(probe-row-y :reg vf02)
(probe-row-z :reg vf03)
(probe-translation :reg vf04)
(instance-row-x :reg vf17)
(instance-row-y :reg vf18)
(instance-row-z :reg vf19)
(instance-translation :reg vf20)
(instance-max-scale :reg vf21)
(instance-origin :reg vf23))
;; Basis rows are signed Q12 fixed point and maximum scale is unsigned Q12. Translation
;; is quantized in 64-unit steps relative to the instance's world bounding-sphere center.
(vu-pair (nop) (itof0.xyzw instance-translation instance-translation))
(vu-pair (nop) (itof12.xyzw instance-row-x instance-row-x))
(vu-pair (nop) (itof12.xyzw instance-row-y instance-row-y))
(vu-pair (nop) (itof12.xyzw instance-row-z instance-row-z))
(vu-pair (nop) (add.xyz instance-translation instance-translation instance-origin))
(vu-pair (nop) (itof12.xyzw instance-max-scale instance-max-scale))
;; Compose the instance translation and three basis rows into the probe's box space.
(vu-pair (nop) (mulax.xyzw ACC probe-row-x instance-translation))
(vu-pair (nop) (madday.xyzw ACC probe-row-y instance-translation))
(vu-pair (nop) (maddaz.xyzw ACC probe-row-z instance-translation))
(vu-pair (nop) (maddw.xyz instance-translation probe-translation vf00))
(vu-pair (nop) (mulax.xyzw ACC probe-row-x instance-row-x))
(vu-pair (nop) (madday.xyzw ACC probe-row-y instance-row-x))
(vu-pair (nop) (maddaz.xyzw ACC probe-row-z instance-row-x))
(vu-pair (nop) (maddx.xyz instance-row-x probe-translation vf00))
(vu-pair (nop) (mulax.xyzw ACC probe-row-x instance-row-y))
(vu-pair (nop) (madday.xyzw ACC probe-row-y instance-row-y))
(vu-pair (nop) (maddaz.xyzw ACC probe-row-z instance-row-y))
(vu-pair (nop) (maddx.xyz instance-row-y probe-translation vf00))
(vu-pair (nop) (mulax.xyzw ACC probe-row-x instance-row-z))
(vu-pair (nop) (madday.xyzw ACC probe-row-y instance-row-z))
(vu-pair (nop) (maddaz.xyzw ACC probe-row-z instance-row-z :e))
(vu-pair (nop) (maddx.xyz instance-row-z probe-translation vf00)))
(label transform-prototype-spheres)
(rlet ((instance-row-x :reg vf17)
(instance-row-y :reg vf18)
(instance-row-z :reg vf19)
(instance-translation :reg vf20)
(instance-max-scale :reg vf21)
(scaled-radii :reg vf22)
(sphere-0 :reg vf05)
(sphere-1 :reg vf06)
(sphere-2 :reg vf07)
(sphere-3 :reg vf08)
(min-0 :reg vf09)
(max-0 :reg vf10)
(min-1 :reg vf11)
(max-1 :reg vf12)
(min-2 :reg vf13)
(max-2 :reg vf14)
(min-3 :reg vf15)
(max-3 :reg vf16))
;; Transform each prototype sphere and conservatively scale its radius by the instance.
(vu-pair (nop) (mulaw.xyzw ACC instance-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC instance-row-x sphere-0))
(vu-pair (nop) (madday.xyzw ACC instance-row-y sphere-0))
(vu-pair (nop) (maddz.xyzw min-0 instance-row-z sphere-0))
(vu-pair (nop) (mulaw.xyzw ACC instance-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC instance-row-x sphere-1))
(vu-pair (nop) (madday.xyzw ACC instance-row-y sphere-1))
(vu-pair (nop) (maddz.xyzw min-1 instance-row-z sphere-1))
(vu-pair (nop) (mulaw.xyzw ACC instance-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC instance-row-x sphere-2))
(vu-pair (nop) (madday.xyzw ACC instance-row-y sphere-2))
(vu-pair (nop) (maddz.xyzw min-2 instance-row-z sphere-2))
(vu-pair (nop) (mulaw.xyzw ACC instance-translation vf00))
(vu-pair (nop) (maddax.xyzw ACC instance-row-x sphere-3))
(vu-pair (nop) (madday.xyzw ACC instance-row-y sphere-3))
(vu-pair (nop) (maddz.xyzw min-3 instance-row-z sphere-3))
(vu-pair (nop) (mulw.x scaled-radii instance-max-scale sphere-0))
(vu-pair (nop) (mulw.y scaled-radii instance-max-scale sphere-1))
(vu-pair (nop) (mulw.z scaled-radii instance-max-scale sphere-2))
(vu-pair (nop) (mulw.w scaled-radii instance-max-scale sphere-3))
(vu-pair (nop) (addx.xyz max-0 min-0 scaled-radii))
(vu-pair (nop) (subx.xyz min-0 min-0 scaled-radii))
(vu-pair (nop) (addy.xyz max-1 min-1 scaled-radii))
(vu-pair (nop) (suby.xyz min-1 min-1 scaled-radii))
(vu-pair (nop) (addz.xyz max-2 min-2 scaled-radii))
(vu-pair (nop) (subz.xyz min-2 min-2 scaled-radii))
(vu-pair (nop) (addw.xyz max-3 min-3 scaled-radii))
(vu-pair (nop) (subw.xyz min-3 min-3 scaled-radii))
(vu-pair (nop) (ftoi0.xyzw max-0 max-0))
(vu-pair (nop) (ftoi0.xyzw min-0 min-0))
(vu-pair (nop) (ftoi0.xyzw max-1 max-1))
(vu-pair (nop) (ftoi0.xyzw min-1 min-1))
(vu-pair (nop) (ftoi0.xyzw max-2 max-2))
(vu-pair (nop) (ftoi0.xyzw min-2 min-2))
(vu-pair (nop) (ftoi0.xyzw max-3 max-3 :e))
(vu-pair (nop) (ftoi0.xyzw min-3 min-3)))))
(#unless PC_PORT
(defun collide-probe-node ((nodes (inline-array draw-node)) (node-count int) (result collide-list))
"Traverse node-count draw nodes against the active rotated line-sphere probe. Bounding spheres
are culled four at a time in VU0; overlapping child spans are visited through the scratchpad
stack, and surviving collision-fragment meshes are appended to result with no instance.
Callers must stay within the stack's 1024 entries and the result's 256 entries."
(rlet ((stack-top :reg a0)
(query-min :reg a1 :class i128)
(result :reg a2)
(query-max :reg a3 :class i128)
(stack-base :reg v1)
(result-count :reg t0)
(result-cursor :reg t1)
(span :reg t2)
(remaining :reg t3)
(kind :reg t4)
(probe-row-x :reg vf1)
(probe-row-y :reg vf2)
(probe-row-z :reg vf3)
(probe-translation :reg vf4)
(sphere-0 :reg vf5)
(sphere-1 :reg vf6)
(sphere-2 :reg vf7)
(sphere-3 :reg vf8)
(min-0 :reg vf9)
(max-0 :reg vf10)
(min-1 :reg vf11)
(max-1 :reg vf12)
(min-2 :reg vf13)
(max-2 :reg vf14)
(min-3 :reg vf15)
(max-3 :reg vf16))
(asm-block save-state-and-seed-stack
(rlet ((work :reg t0)
(seed-kind :reg a1))
(add.i sp sp -96)
(s.d ra sp)
(s.q s2 sp 16)
(s.q s3 sp 32)
(s.q s4 sp 48)
(s.q s5 sp 64)
(s.q gp sp 80)
(m! work *collide-work*)
(m! stack-base *collide-probe-stack*)
(s.w nodes stack-base PROBE-STACK-CHILD)
(add.i stack-top stack-base PROBE-STACK-STRIDE)
(s.h node-count stack-base PROBE-STACK-COUNT)
(add.i seed-kind r0 1)
(s.h seed-kind stack-base PROBE-STACK-KIND))
(rlet ((work :reg t0))
(l.q query-min work PROBE-QUERY-MIN)
(l.q query-max work PROBE-QUERY-MAX)
(l.vf probe-row-x work PROBE-QUERY-ROW-X)
(l.vf probe-row-y work PROBE-QUERY-ROW-Y)
(l.vf probe-row-z work PROBE-QUERY-ROW-Z)
(l.vf probe-translation work PROBE-QUERY-TRANSLATION))
(l.w result-count result PROBE-RESULT-COUNT)
(sll result-cursor result-count 4)
(add result-cursor result-cursor result)
(add.i result-cursor result-cursor PROBE-RESULT-ITEMS))
;; Work entries are popped from the end. Their count word is split into a remaining halfword
;; and a kind halfword even though the reflected structure exposes it as one uint32.
(asm-block pop-span
(label pop-span)
(b.eq stack-top stack-base done :delay (nop!))
(add.i stack-top stack-top (- PROBE-STACK-STRIDE))
(l.w span stack-top PROBE-STACK-CHILD)
(l.hu remaining stack-top PROBE-STACK-COUNT)
(l.hu kind stack-top PROBE-STACK-KIND))
;; Drawable arrays are padded, so this path can fetch all four spheres before remaining
;; determines which results are consumed.
(asm-block cull-four-spheres
(label cull-four)
(l.vf sphere-0 span PROBE-DRAWABLE-BSPHERE)
(l.vf sphere-1 span (+ PROBE-DRAWABLE-BSPHERE PROBE-DRAW-NODE-STRIDE))
(add.i t5 remaining -4)
(l.vf sphere-2 span (+ PROBE-DRAWABLE-BSPHERE (* 2 PROBE-DRAW-NODE-STRIDE)))
(b.lt t5 r0 reduce-four :delay (l.vf sphere-3 span (+ PROBE-DRAWABLE-BSPHERE (* 3 PROBE-DRAW-NODE-STRIDE))))
(pref span (+ PROBE-DRAWABLE-BSPHERE (* 4 PROBE-DRAW-NODE-STRIDE)) :hint 0)
(label reduce-four)
(callms 0)
(nop!)
(m t5 min-0)
(m t6 max-0)
(m s2 min-1)
(m s3 max-1)
(m s4 min-2)
(m s5 max-2)
(m ra min-3)
(m t9 max-3)
;; Each packed result is nonzero if candidate-min exceeds query-max or query-min exceeds
;; candidate-max. Packing the high halfwords and shifting drops W, leaving the XYZ reject.
(pcgt.w t5 t5 query-max)
(l.w t8 span PROBE-CANDIDATE-PAYLOAD)
(pcgt.w t7 query-min t6)
(l.w t6 span (+ PROBE-CANDIDATE-PAYLOAD PROBE-DRAW-NODE-STRIDE))
(or.q t5 t5 t7)
(l.w t7 span (+ PROBE-CANDIDATE-PAYLOAD (* 2 PROBE-DRAW-NODE-STRIDE)))
(ppach gp r0 t5)
(l.w t5 span (+ PROBE-CANDIDATE-PAYLOAD (* 3 PROBE-DRAW-NODE-STRIDE)))
(pcgt.w s2 s2 query-max)
(mmi-nop!)
(pcgt.w s3 query-min s3)
(mmi-nop!)
(or.q s3 s2 s3)
(mmi-nop!)
(ppach s3 r0 s3)
(mmi-nop!)
(pcgt.w s4 s4 query-max)
(mmi-nop!)
(pcgt.w s5 query-min s5)
(mmi-nop!)
(or.q s5 s4 s5)
(mmi-nop!)
(ppach s5 r0 s5)
(mmi-nop!)
(pcgt.w ra ra query-max)
(mmi-nop!)
(pcgt.w t9 query-min t9)
(mmi-nop!)
(or.q t9 ra t9)
(mmi-nop!)
(ppach t9 r0 t9)
(mmi-nop!)
(sll s4 gp 16)
(sll gp s3 16)
(sll ra s5 16)
(sll t9 t9 16))
;; A nonzero kind describes draw nodes. Push each overlapping child span back onto the LIFO.
(asm-block push-overlapping-children
(b.z kind append-fragment-leaves :delay (nop!))
(b.nz s4 after-node-0 :delay (add.i remaining remaining -1))
(nop!)
(l.bu s5 span PROBE-DRAWABLE-CHILD-COUNT)
(nop!)
(l.bu s4 span PROBE-DRAWABLE-FLAGS)
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t8 stack-top -8)
(nop!)
(s.h s5 stack-top -4)
(nop!)
(s.h s4 stack-top -2)
(label after-node-0)
(b.z remaining finish-node-group :delay (nop!))
(b.nz gp after-node-1 :delay (add.i remaining remaining -1))
(nop!)
(l.bu t8 span (+ PROBE-DRAWABLE-CHILD-COUNT PROBE-DRAW-NODE-STRIDE))
(nop!)
(l.bu gp span (+ PROBE-DRAWABLE-FLAGS PROBE-DRAW-NODE-STRIDE))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t6 stack-top -8)
(nop!)
(s.h t8 stack-top -4)
(nop!)
(s.h gp stack-top -2)
(label after-node-1)
(b.z remaining finish-node-group :delay (nop!))
(b.nz ra after-node-2 :delay (add.i remaining remaining -1))
(nop!)
(l.bu t6 span (+ PROBE-DRAWABLE-CHILD-COUNT (* 2 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t8 span (+ PROBE-DRAWABLE-FLAGS (* 2 PROBE-DRAW-NODE-STRIDE)))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t7 stack-top -8)
(nop!)
(s.h t6 stack-top -4)
(nop!)
(s.h t8 stack-top -2)
(label after-node-2)
(b.z remaining finish-node-group :delay (nop!))
(b.nz t9 finish-node-group :delay (add.i remaining remaining -1))
(nop!)
(l.bu t6 span (+ PROBE-DRAWABLE-CHILD-COUNT (* 3 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t7 span (+ PROBE-DRAWABLE-FLAGS (* 3 PROBE-DRAW-NODE-STRIDE)))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t5 stack-top -8)
(nop!)
(s.h t6 stack-top -4)
(nop!)
(s.h t7 stack-top -2)
(label finish-node-group)
(b.gt remaining r0 cull-four :delay (add.i span span (* 4 PROBE-DRAW-NODE-STRIDE)))
(b pop-span :delay (nop!)))
;; Kind zero means the span consists of collision-fragment leaves. The shared candidate
;; payload is their mesh field; non-instanced results carry #f in the instance slot.
(asm-block append-fragment-leaves
(label append-fragment-leaves)
(b.nz s4 after-fragment-0 :delay (add.i remaining remaining -1))
(add.i result-count result-count 1)
(s.w t8 result-cursor PROBE-RESULT-MESH)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w s7 result-cursor (- PROBE-RESULT-INSTANCE PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-0)
(b.z remaining finish-fragment-group :delay (nop!))
(b.nz gp after-fragment-1 :delay (add.i remaining remaining -1))
(add.i result-count result-count 1)
(s.w t6 result-cursor PROBE-RESULT-MESH)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w s7 result-cursor (- PROBE-RESULT-INSTANCE PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-1)
(b.z remaining finish-fragment-group :delay (nop!))
(b.nz ra after-fragment-2 :delay (add.i remaining remaining -1))
(add.i result-count result-count 1)
(s.w t7 result-cursor PROBE-RESULT-MESH)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w s7 result-cursor (- PROBE-RESULT-INSTANCE PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-2)
(b.z remaining finish-fragment-group :delay (nop!))
(b.nz t9 finish-fragment-group :delay (add.i remaining remaining -1))
(add.i result-count result-count 1)
(s.w t5 result-cursor PROBE-RESULT-MESH)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w s7 result-cursor (- PROBE-RESULT-INSTANCE PROBE-RESULT-ITEM-STRIDE))
(label finish-fragment-group)
(b.gt remaining r0 cull-four :delay (add.i span span (* 4 PROBE-DRAW-NODE-STRIDE)))
(b pop-span :delay (nop!)))
(asm-block finish
(label done)
(nop!)
(s.w result-count result PROBE-RESULT-COUNT)
(m v0 r0)
(l.d ra sp)
(l.q gp sp 80)
(l.q s5 sp 64)
(l.q s4 sp 48)
(l.q s3 sp 32)
(l.q s2 sp 16)
(jr ra :delay (add.i sp sp 96))
(nop! :count 3)))))
(#unless PC_PORT
(defun collide-probe-instance-tie ((drawables object) (drawable-count int) (result collide-list) (draw-node-span? int))
"Traverse an instance-TIE tree against the active rotated line-sphere probe. Draw-node spans and
direct instance spans share an eight-byte scratchpad stack. Surviving instances contribute
their prototype collision fragments after the packed instance transform is composed with the
probe transform in VU0. draw-node-span? is one for draw nodes and zero for direct instances.
Callers must stay within the stack's 1024 entries and the result's 256 entries."
(rlet ((stack-top :reg a0)
(instance-batch-count :reg a1)
(result :reg a2)
(node-batch-count :reg a3)
(stack-base :reg v1)
(query-min :reg t0 :class i128)
(query-max :reg t1 :class i128)
(kind :reg t2)
(remaining :reg t3)
(span :reg t4)
(probe-row-x :reg vf1)
(probe-row-y :reg vf2)
(probe-row-z :reg vf3)
(probe-translation :reg vf4)
(sphere-0 :reg vf5)
(sphere-1 :reg vf6)
(sphere-2 :reg vf7)
(sphere-3 :reg vf8)
(min-0 :reg vf9)
(max-0 :reg vf10)
(min-1 :reg vf11)
(max-1 :reg vf12)
(min-2 :reg vf13)
(max-2 :reg vf14)
(min-3 :reg vf15)
(max-3 :reg vf16))
;; Seed the work stack with either the root draw-node span or the direct instance span.
(rlet ((work :reg t2))
(asm-block save-state-and-seed-stack
(label entry)
(add.i sp sp -80)
(s.d ra sp)
(s.q s3 sp 16)
(s.q s4 sp 32)
(s.q s5 sp 48)
(s.q gp sp 64)
(m! work *collide-work*)
(m! stack-base *collide-probe-stack*)
(s.w drawables stack-base PROBE-STACK-CHILD)
(add.i stack-top stack-base PROBE-STACK-STRIDE)
(s.h drawable-count stack-base PROBE-STACK-COUNT)
(s.h draw-node-span? stack-base PROBE-STACK-KIND)
(add.i instance-batch-count r0 0)
(add.i node-batch-count r0 0)
(l.q query-min work PROBE-QUERY-MIN)
(l.q query-max work PROBE-QUERY-MAX)
(l.vf probe-row-x work PROBE-QUERY-ROW-X)
(l.vf probe-row-y work PROBE-QUERY-ROW-Y)
(l.vf probe-row-z work PROBE-QUERY-ROW-Z)
(l.vf probe-translation work PROBE-QUERY-TRANSLATION)))
;; Negative work kinds are individual instances. Zero denotes a direct instance span, and a
;; positive kind denotes a draw-node span.
(asm-block pop-work
(label pop-work)
(b.eq stack-top stack-base done :delay (nop!))
(add.i stack-top stack-top (- PROBE-STACK-STRIDE))
(l.w span stack-top PROBE-STACK-CHILD)
(l.h kind stack-top PROBE-STACK-KIND)
(l.hu remaining stack-top PROBE-STACK-COUNT)
(b.lt kind r0 process-instance :delay (nop!)))
;; Both span kinds expose a bounding sphere at the same offset. Draw nodes are 32 bytes while
;; instances are 64, so the paths use different strides. Their separate batch counters are
;; retained here but are not consumed below.
(asm-block load-broadphase-four
(label load-broadphase-four)
(b.z kind load-instance-four :delay (nop!))
(l.vf sphere-0 span PROBE-DRAWABLE-BSPHERE)
(add.i node-batch-count node-batch-count 1)
(l.vf sphere-1 span (+ PROBE-DRAWABLE-BSPHERE PROBE-DRAW-NODE-STRIDE))
(add.i t5 remaining -4)
(l.vf sphere-2 span (+ PROBE-DRAWABLE-BSPHERE (* 2 PROBE-DRAW-NODE-STRIDE)))
(b.lt t5 r0 node-prefetched :delay (l.vf sphere-3 span (+ PROBE-DRAWABLE-BSPHERE (* 3 PROBE-DRAW-NODE-STRIDE))))
(pref span (+ PROBE-DRAWABLE-BSPHERE (* 4 PROBE-DRAW-NODE-STRIDE)) :hint 0)
(label node-prefetched)
(b reduce-broadphase-four :delay (nop!))
(label load-instance-four)
(l.vf sphere-0 span PROBE-INSTANCE-BSPHERE)
(add.i instance-batch-count instance-batch-count 1)
(l.vf sphere-1 span (+ PROBE-INSTANCE-BSPHERE PROBE-INSTANCE-STRIDE))
(add.i t5 remaining -4)
(l.vf sphere-2 span (+ PROBE-INSTANCE-BSPHERE (* 2 PROBE-INSTANCE-STRIDE)))
(b.lt t5 r0 reduce-broadphase-four :delay (l.vf sphere-3 span (+ PROBE-INSTANCE-BSPHERE (* 3 PROBE-INSTANCE-STRIDE))))
(pref span (+ PROBE-INSTANCE-BSPHERE (* 4 PROBE-INSTANCE-STRIDE)) :hint 0)
(pref span (+ PROBE-INSTANCE-BSPHERE (* 6 PROBE-INSTANCE-STRIDE)) :hint 0))
;; VU0 transforms four spheres to query-box space. The EE combines the two separating-axis
;; comparisons, packs their XYZ results, and leaves one reject bit in each scalar.
(asm-block reduce-broadphase-four
(label reduce-broadphase-four)
(callms 0)
(m s5 min-0)
(m t7 max-0)
(m gp min-1)
(m ra max-1)
(m t9 min-2)
(m t8 max-2)
(m t6 min-3)
(m t5 max-3)
(nop!)
(pcgt.w s5 s5 query-max)
(mmi-nop!)
(pcgt.w t7 query-min t7)
(mmi-nop!)
(or.q t7 s5 t7)
(mmi-nop!)
(ppach t7 r0 t7)
(mmi-nop!)
(pcgt.w gp gp query-max)
(mmi-nop!)
(pcgt.w ra query-min ra)
(mmi-nop!)
(or.q ra gp ra)
(mmi-nop!)
(ppach ra r0 ra)
(mmi-nop!)
(pcgt.w t9 t9 query-max)
(mmi-nop!)
(pcgt.w t8 query-min t8)
(mmi-nop!)
(or.q t8 t9 t8)
(mmi-nop!)
(ppach t8 r0 t8)
(mmi-nop!)
(pcgt.w t6 t6 query-max)
(mmi-nop!)
(pcgt.w t5 query-min t5)
(mmi-nop!)
(or.q t5 t6 t5)
(mmi-nop!)
(ppach t5 r0 t5)
(mmi-nop!)
(sll t9 t7 16)
(sll t7 ra 16)
(sll t6 t8 16)
(sll t5 t5 16))
;; For a draw-node span, push each overlapping child span. The flags byte becomes the next
;; work kind, so children-are-draw-nodes naturally selects the next interpretation.
(asm-block queue-node-children
(b.z kind queue-instance-hits :delay (nop!))
(b.nz t9 after-node-0 :delay (add.i remaining remaining -1))
(nop!)
(l.w t8 span PROBE-DRAWABLE-CHILD)
(nop!)
(l.bu t9 span PROBE-DRAWABLE-CHILD-COUNT)
(nop!)
(l.bu ra span PROBE-DRAWABLE-FLAGS)
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t8 stack-top (- PROBE-STACK-STRIDE))
(nop!)
(s.h t9 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h ra stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-node-0)
(b.z remaining finish-node-group :delay (nop!))
(b.nz t7 after-node-1 :delay (add.i remaining remaining -1))
(nop!)
(l.w t7 span (+ PROBE-DRAWABLE-CHILD PROBE-DRAW-NODE-STRIDE))
(nop!)
(l.bu t8 span (+ PROBE-DRAWABLE-CHILD-COUNT PROBE-DRAW-NODE-STRIDE))
(nop!)
(l.bu t9 span (+ PROBE-DRAWABLE-FLAGS PROBE-DRAW-NODE-STRIDE))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t7 stack-top (- PROBE-STACK-STRIDE))
(nop!)
(s.h t8 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t9 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-node-1)
(b.z remaining finish-node-group :delay (nop!))
(b.nz t6 after-node-2 :delay (add.i remaining remaining -1))
(nop!)
(l.w t6 span (+ PROBE-DRAWABLE-CHILD (* 2 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t7 span (+ PROBE-DRAWABLE-CHILD-COUNT (* 2 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t8 span (+ PROBE-DRAWABLE-FLAGS (* 2 PROBE-DRAW-NODE-STRIDE)))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t6 stack-top (- PROBE-STACK-STRIDE))
(nop!)
(s.h t7 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t8 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-node-2)
(b.z remaining finish-node-group :delay (nop!))
(b.nz t5 finish-node-group :delay (add.i remaining remaining -1))
(nop!)
(l.w t5 span (+ PROBE-DRAWABLE-CHILD (* 3 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t6 span (+ PROBE-DRAWABLE-CHILD-COUNT (* 3 PROBE-DRAW-NODE-STRIDE)))
(nop!)
(l.bu t7 span (+ PROBE-DRAWABLE-FLAGS (* 3 PROBE-DRAW-NODE-STRIDE)))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w t5 stack-top (- PROBE-STACK-STRIDE))
(nop!)
(s.h t6 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t7 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label finish-node-group)
(b.gt remaining r0 load-broadphase-four :delay (add.i span span (* 4 PROBE-DRAW-NODE-STRIDE)))
(b pop-work :delay (nop!)))
;; A direct span cannot be processed until its prototype data is known. Queue each surviving
;; instance as a negative-kind single item, preserving the same LIFO traversal order.
(asm-block queue-instance-hits
(label queue-instance-hits)
(b.nz t9 after-instance-0 :delay (add.i remaining remaining -1))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w span stack-top (- PROBE-STACK-STRIDE))
(add.i t8 r0 -1)
(s.h r0 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t8 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-instance-0)
(b.z remaining finish-instance-group :delay (add.i span span PROBE-INSTANCE-STRIDE))
(b.nz t7 after-instance-1 :delay (add.i remaining remaining -1))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w span stack-top (- PROBE-STACK-STRIDE))
(add.i t7 r0 -1)
(s.h r0 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t7 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-instance-1)
(b.z remaining finish-instance-group :delay (add.i span span PROBE-INSTANCE-STRIDE))
(b.nz t6 after-instance-2 :delay (add.i remaining remaining -1))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w span stack-top (- PROBE-STACK-STRIDE))
(add.i t6 r0 -1)
(s.h r0 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t6 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label after-instance-2)
(b.z remaining finish-instance-group :delay (add.i span span PROBE-INSTANCE-STRIDE))
(b.nz t5 finish-instance-group :delay (add.i remaining remaining -1))
(add.i stack-top stack-top PROBE-STACK-STRIDE)
(s.w span stack-top (- PROBE-STACK-STRIDE))
(add.i t5 r0 -1)
(s.h r0 stack-top (- PROBE-STACK-COUNT PROBE-STACK-STRIDE))
(nop!)
(s.h t5 stack-top (- PROBE-STACK-KIND PROBE-STACK-STRIDE))
(label finish-instance-group)
(b.gt remaining r0 load-broadphase-four :delay (add.i span span PROBE-INSTANCE-STRIDE))
(b pop-work :delay (nop!)))
(rlet ((instance :reg t2)
(instance-row-x :reg vf17)
(instance-row-y :reg vf18)
(instance-row-z :reg vf19)
(instance-translation :reg vf20)
(instance-max-scale :reg vf21)
(scaled-radii :reg vf22)
(instance-origin :reg vf23))
;; TIE stores its affine transform as signed halfwords. Translation is split across the two
;; matrix halves and encoded in 64-unit steps; basis rows use signed Q12 fixed point and
;; max-scale is unsigned Q12. VU entry 32 converts and composes this with the probe inverse.
(asm-block decode-instance-transform
(label process-instance)
(rlet ((queued-instance :reg t4))
(m instance queued-instance)
(rlet ((instance-flags :reg t4)
(bucket :reg t3)
(fragment-array :reg t6))
(l.hu instance-flags queued-instance PROBE-INSTANCE-FLAGS)
(nop!)
(l.w bucket instance PROBE-INSTANCE-BUCKET)
;; The branch tests flags before its delay load replaces the same register.
(b.nz instance-flags finish-instance :delay (l.hu t4 instance PROBE-INSTANCE-MAX-SCALE))
(nop!)
(l.w fragment-array bucket PROBE-BUCKET-COLLIDE-FRAG)
(nop!)))
(rlet ((max-scale-bits :reg t4 :class i128)
(origin-high-bits :reg t3 :class i128)
(origin-low-bits :reg t5 :class i128)
(fragment-array :reg t6))
(l.q origin-high-bits instance PROBE-INSTANCE-ORIGIN-HIGH)
(b.z fragment-array finish-instance :delay (l.q origin-low-bits instance PROBE-INSTANCE-ORIGIN-LOW))
(pextlw max-scale-bits max-scale-bits max-scale-bits)
(mmi-nop!)
(pcpyld max-scale-bits max-scale-bits max-scale-bits)
(mmi-nop!)
(pcpyud t8 origin-high-bits r0)
(mmi-nop!)
(pcpyud t7 origin-low-bits r0)
(mmi-nop!)
(pextlh t8 t8 r0)
(mmi-nop!)
(sra.w t8 t8 10)
(mmi-nop!)
(pextlh t9 origin-low-bits r0))
(rlet ((max-scale-bits :reg t4 :class i128)
(origin-high-bits :reg t3 :class i128)
(fragment-count :reg t5)
(fragment-array :reg t6))
(l.hu fragment-count fragment-array PROBE-FRAGMENT-ARRAY-LENGTH)
(sra.w t9 t9 16)
(mmi-nop!)
(pextlh t7 t7 r0)
(m instance-translation t8)
(sra.w t7 t7 16)
(m instance-row-x t9)
(pextlh origin-high-bits origin-high-bits r0)
(m instance-row-y t7)
(sra.w origin-high-bits origin-high-bits 16)
(l.vf instance-origin instance PROBE-INSTANCE-BSPHERE)
(m instance-row-z origin-high-bits)
(rlet ((result-count :reg t3))
(l.w result-count result PROBE-RESULT-COUNT))
(m instance-max-scale max-scale-bits)
(add.i t7 fragment-count -4)
(callms 32)))
(rlet ((result-count :reg t3)
(result-cursor :reg t4)
(fragment-count :reg t5)
(fragment-cursor :reg t6))
(asm-block prepare-fragment-cursor
(sll result-cursor result-count 4)
(add result-cursor result-cursor result)
(add fragment-count fragment-count r0)
(add.i result-cursor result-cursor PROBE-RESULT-ITEMS)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-ARRAY-DATA)
(b.lt t7 r0 cull-fragment-tail :delay (l.q t7 fragment-cursor PROBE-DRAWABLE-BSPHERE))
(nop!)
(l.q t8 fragment-cursor (+ PROBE-DRAWABLE-BSPHERE PROBE-FRAGMENT-STRIDE))
(nop!)
(l.q t9 fragment-cursor (+ PROBE-DRAWABLE-BSPHERE (* 2 PROBE-FRAGMENT-STRIDE)))
(nop!)
(l.q ra fragment-cursor (+ PROBE-DRAWABLE-BSPHERE (* 3 PROBE-FRAGMENT-STRIDE)))
(nop!)
(m.ni sphere-0 t7)
(nop!)
(m.ni sphere-1 t8)
(nop!)
(m.ni sphere-2 t9)
(nop!)
(m.ni sphere-3 ra))
;; Entry 54 transforms four prototype spheres by the composed instance transform and scales
;; their radii conservatively. The EE then performs the same packed XYZ rejection as above.
(asm-block cull-four-fragments
(label cull-four-fragments)
;; Entry 54 raises E before its final drain instruction; wait for completion
;; before transferring the eight integer bounds back to the EE.
(callms 54)
(nop! :count 3)
(vnop)
(nop!)
(m s3 max-0)
(nop!)
(m t9 min-0)
(nop!)
(m s4 max-1)
(nop!)
(m s5 min-1)
(nop!)
(m gp max-2)
(nop!)
(m ra min-2)
(nop!)
(m t8 max-3)
(nop!)
(m t7 min-3)
(nop!)
(pcgt.w s3 query-min s3)
(mmi-nop!)
(pcgt.w t9 t9 query-max)
(mmi-nop!)
(or.q t9 t9 s3)
(mmi-nop!)
(ppach t9 r0 t9)
(mmi-nop!)
(pcgt.w s4 query-min s4)
(mmi-nop!)
(pcgt.w s5 s5 query-max)
(mmi-nop!)
(or.q s5 s5 s4)
(mmi-nop!)
(ppach s5 r0 s5)
(mmi-nop!)
(pcgt.w gp query-min gp)
(mmi-nop!)
(pcgt.w ra ra query-max)
(mmi-nop!)
(or.q ra ra gp)
(mmi-nop!)
(ppach ra r0 ra)
(mmi-nop!)
(pcgt.w t8 query-min t8)
(mmi-nop!)
(pcgt.w t7 t7 query-max)
(mmi-nop!)
(or.q t7 t7 t8)
(mmi-nop!)
(ppach t7 r0 t7)
(mmi-nop!)
(sll gp t9 16)
(sll t9 s5 16)
(sll t8 ra 16)
(sll t7 t7 16))
;; Append the mesh pointer and originating instance for each surviving fragment. The result
;; cursor follows the list's physical sixteen-byte inline spacing.
(asm-block append-four-fragments
(b.nz gp after-fragment-0 :delay (nop!))
(nop!)
(l.w ra fragment-cursor PROBE-FRAGMENT-MESH)
(add.i result-count result-count 1)
(s.w instance result-cursor PROBE-RESULT-INSTANCE)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w ra result-cursor (- PROBE-RESULT-MESH PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-0)
(add.i fragment-count fragment-count -1)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-STRIDE)
(b.z fragment-count finish-fragment-group :delay (nop!))
(b.nz t9 after-fragment-1 :delay (nop!))
(nop!)
(l.w t9 fragment-cursor PROBE-FRAGMENT-MESH)
(add.i result-count result-count 1)
(s.w instance result-cursor PROBE-RESULT-INSTANCE)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w t9 result-cursor (- PROBE-RESULT-MESH PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-1)
(add.i fragment-count fragment-count -1)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-STRIDE)
(b.z fragment-count finish-fragment-group :delay (nop!))
(b.nz t8 after-fragment-2 :delay (nop!))
(nop!)
(l.w t8 fragment-cursor PROBE-FRAGMENT-MESH)
(add.i result-count result-count 1)
(s.w instance result-cursor PROBE-RESULT-INSTANCE)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w t8 result-cursor (- PROBE-RESULT-MESH PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-2)
(add.i fragment-count fragment-count -1)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-STRIDE)
(b.z fragment-count finish-fragment-group :delay (nop!))
(b.nz t7 after-fragment-3 :delay (nop!))
(nop!)
(l.w t7 fragment-cursor PROBE-FRAGMENT-MESH)
(add.i result-count result-count 1)
(s.w instance result-cursor PROBE-RESULT-INSTANCE)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w t7 result-cursor (- PROBE-RESULT-MESH PROBE-RESULT-ITEM-STRIDE))
(label after-fragment-3)
(add.i fragment-count fragment-count -1)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-STRIDE)
(b.z fragment-count finish-fragment-group :delay (l.vf sphere-0 fragment-cursor PROBE-DRAWABLE-BSPHERE))
(nop!)
(l.vf sphere-1 fragment-cursor (+ PROBE-DRAWABLE-BSPHERE PROBE-FRAGMENT-STRIDE))
(nop!)
(l.vf sphere-2 fragment-cursor (+ PROBE-DRAWABLE-BSPHERE (* 2 PROBE-FRAGMENT-STRIDE)))
(b cull-four-fragments :delay (l.vf sphere-3 fragment-cursor (+ PROBE-DRAWABLE-BSPHERE (* 3 PROBE-FRAGMENT-STRIDE)))))
(asm-block finish-fragment-group
(label finish-fragment-group)
(nop!)
(s.w result-count result PROBE-RESULT-COUNT)
(b pop-work :delay (nop!)))
;; Fewer than four remaining fragments use the same composed transform inline. The sphere's
;; center is transformed, its radius is multiplied by max-scale, and its integer bounds are
;; rejected before the mesh is appended.
(asm-block cull-fragment-tail
(label cull-fragment-tail)
(rlet ((tail-center :reg vf24)
(tail-max :reg vf25))
(m sphere-0 t7)
(nop!)
(mula.w.vf instance-translation vf0)
(nop!)
(madda.x.vf instance-row-x sphere-0)
(nop!)
(madda.y.vf instance-row-y sphere-0)
(nop!)
(madd.z.vf tail-center instance-row-z sphere-0)
(nop!)
(mul.w.vf.x scaled-radii instance-max-scale sphere-0)
(nop!)
(add.x.vf.xyz tail-max tail-center scaled-radii)
(nop!)
(rlet ((tail-min :reg vf24))
(sub.x.vf.xyz tail-min tail-center scaled-radii)
(nop!)
(ftoi.vf tail-max tail-max)
(nop!)
(ftoi.vf tail-min tail-min)
(nop!)
(m t8 tail-max)
(nop!)
(m t7 tail-min)
(nop!)
(pcgt.w t8 query-min t8)
(mmi-nop!)
(pcgt.w t7 t7 query-max)
(mmi-nop!)
(or.q t7 t7 t8)
(mmi-nop!)
(ppach t7 r0 t7)
(mmi-nop!)
(sll t7 t7 16)
(nop!)
(b.nz t7 after-tail-fragment :delay (nop!))
(nop!)
(l.w t7 fragment-cursor PROBE-FRAGMENT-MESH)
(add.i result-count result-count 1)
(s.w instance result-cursor PROBE-RESULT-INSTANCE)
(add.i result-cursor result-cursor PROBE-RESULT-ITEM-STRIDE)
(s.w t7 result-cursor (- PROBE-RESULT-MESH PROBE-RESULT-ITEM-STRIDE))
(label after-tail-fragment)
(add.i fragment-count fragment-count -1)
(add.i fragment-cursor fragment-cursor PROBE-FRAGMENT-STRIDE)
(b.gt fragment-count r0 cull-fragment-tail :delay (l.q t7 fragment-cursor PROBE-DRAWABLE-BSPHERE))
(nop!)
(s.w result-count result PROBE-RESULT-COUNT))))
(asm-block finish-instance (label finish-instance) (b pop-work :delay (nop!)))))
(asm-block restore-state
(label done)
(m v0 r0)
(l.d ra sp)
(l.q gp sp 64)
(l.q s5 sp 48)
(l.q s4 sp 32)
(l.q s3 sp 16)
(jr ra :delay (add.i sp sp 80))
(nop! :count 2)))))
File diff suppressed because it is too large Load Diff
+22 -81
View File
@@ -12,31 +12,22 @@
(defun make-light-kit ((group light-group) (heading float) (dir0-level float) (dir1-level float) (dir2-level float))
"Build a three-directional-light kit. dir0 and dir1 are opposing warm diagonal lights rotated
around Y by heading in 65,536-units-per-turn rotation units; dir2 points straight down. The
around Y by heading in rotation units; dir2 points straight down. The
three level arguments set their respective light strengths."
(let ((rotation (new 'stack-no-clear 'matrix)))
(matrix-rotate-y! rotation heading)
(let ((dir0 (-> group dir0)))
(set! (-> dir0 direction x) -0.612)
(set! (-> dir0 direction y) 0.5)
(set! (-> dir0 direction z) 0.612)
(set! (-> dir0 direction w) 0.0))
(set-vector! (-> dir0 direction) -0.612 0.5 0.612 0.0))
(set-vector! (-> group dir0 color) 0.8 0.775 0.7 1.0)
(set! (-> group dir0 levels x) dir0-level)
(let ((dir1 (-> group dir1)))
(set! (-> dir1 direction x) 0.612)
(set! (-> dir1 direction y) 0.5)
(set! (-> dir1 direction z) -0.612)
(set! (-> dir1 direction w) 0.0))
(set-vector! (-> dir1 direction) 0.612 0.5 -0.612 0.0))
(set-vector! (-> group dir1 color) 0.8 0.775 0.7 1.0)
(set! (-> group dir1 levels x) dir1-level)
(vector-matrix*! (-> group dir0 direction) (-> group dir0 direction) rotation)
(vector-matrix*! (-> group dir1 direction) (-> group dir1 direction) rotation))
(let ((dir2 (-> group dir2)))
(set! (-> dir2 direction x) 0.0)
(set! (-> dir2 direction y) -1.0)
(set! (-> dir2 direction z) 0.0)
(set! (-> dir2 direction w) 0.0))
(set-vector! (-> dir2 direction) 0.0 -1.0 0.0 0.0))
(set-vector! (-> group dir2 color) 0.8 0.775 0.7 1.0)
(set! (-> group dir2 levels x) dir2-level)
(none))
@@ -47,10 +38,7 @@
(let ((group (-> context light-group 2)))
(make-light-kit group 2730.6667 1.0 1.0 0.8)
(let ((dir2 (-> group dir2)))
(set! (-> dir2 direction x) 0.0)
(set! (-> dir2 direction y) -1.0)
(set! (-> dir2 direction z) 0.0)
(set! (-> dir2 direction w) 0.0))
(set-vector! (-> dir2 direction) 0.0 -1.0 0.0 0.0))
(set-vector! (-> group dir2 color) 0.75 0.375 0.0 1.0))
(make-light-kit (-> context light-group 3) 53703.11 0.9 0.9 0.5)
(make-light-kit (-> context light-group 4) 54613.332 0.9 0.9 0.4)
@@ -71,39 +59,24 @@
"Initialize Village 2 light groups 1 through 6 with the authored directional colors and levels."
(let ((group (-> context light-group 1)))
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 0.375 0.25 0.25 1.0)
(set! (-> group dir0 levels x) 1.0)
(let ((directional (-> group dir1)))
(set! (-> directional direction x) -0.6119)
(set! (-> directional direction y) 0.5)
(set! (-> directional direction z) -0.6119)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) -0.6119 0.5 -0.6119 1.0))
(set-vector! (-> group dir1 color) 0.25 0.75 1.0 1.0)
(set! (-> group dir1 levels x) 0.666)
(let ((directional (-> group dir2)))
(set! (-> directional direction x) 0.9961)
(set! (-> directional direction y) 0.0)
(set! (-> directional direction z) -0.0871)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.9961 0.0 -0.0871 1.0))
(set-vector! (-> group dir2 color) 0.0 0.25 1.0 1.0)
(set! (-> group dir2 levels x) 1.0))
(let ((group (-> context light-group 2)))
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.2239)
(set! (-> directional direction y) 0.5)
(set! (-> directional direction z) 0.836)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.2239 0.5 0.836 1.0))
(set-vector! (-> group dir0 color) 0.8 0.8 0.8 1.0)
(set! (-> group dir0 levels x) 0.7)
(let ((directional (-> group dir1)))
(set! (-> directional direction x) -0.2959)
(set! (-> directional direction y) 0.5)
(set! (-> directional direction z) -0.8133)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) -0.2959 0.5 -0.8133 1.0))
(set-vector! (-> group dir1 color) 0.8 0.8 0.8 1.0)
(set! (-> group dir1 levels x) 0.7))
(let ((group (-> context light-group 3)))
@@ -114,10 +87,7 @@
(set-vector! (-> group dir0 color) 0.675 0.45 0.15 1.0))
(let ((group (-> context light-group 5)))
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.2425)
(set! (-> directional direction y) -0.9701)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 0.0))
(set-vector! (-> directional direction) 0.2425 -0.9701 0.0 0.0))
(set-vector! (-> group dir0 color) 2.0 1.0 0.0 1.0)
(set! (-> group dir1 levels x) 0.0)
(set! (-> group dir2 levels x) 0.0))
@@ -133,82 +103,53 @@
(let ((group (-> context light-group 1)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(let ((group (-> context light-group 2)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(let ((group (-> context light-group 3)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(let ((group (-> context light-group 4)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(let ((group (-> context light-group 5)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(let ((group (-> context light-group 6)))
(make-light-kit group 0.0 1.0 0.0 0.0)
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) 1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 1.0 0.0 1.0))
(set-vector! (-> group dir0 color) 1.0 0.9 0.0 1.0))
(none))
(defun make-village3-light-kit ((context mood-context))
"Initialize Village 3 light groups 1 and 2 with cyan upper and amber downward lighting."
(let ((group (-> context light-group 1)))
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.6281)
(set! (-> directional direction y) 0.7208)
(set! (-> directional direction z) 0.2929)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.6281 0.7208 0.2929 1.0))
(set-vector! (-> group dir0 color) 0.5 1.0 1.0 1.0)
(set! (-> group dir0 levels x) 1.0)
(let ((directional (-> group dir2)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) -1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 -1.0 0.0 1.0))
(set-vector! (-> group dir2 color) 0.625 0.375 0.1 1.0))
(let ((group (-> context light-group 2)))
(let ((directional (-> group dir0)))
(set! (-> directional direction x) 0.6281)
(set! (-> directional direction y) 0.7208)
(set! (-> directional direction z) 0.2929)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.6281 0.7208 0.2929 1.0))
(set-vector! (-> group dir0 color) 0.25 0.5 0.5 1.0)
(set! (-> group dir0 levels x) 1.0)
(let ((directional (-> group dir2)))
(set! (-> directional direction x) 0.0)
(set! (-> directional direction y) -1.0)
(set! (-> directional direction z) 0.0)
(set! (-> directional direction w) 1.0))
(set-vector! (-> directional direction) 0.0 -1.0 0.0 1.0))
(set-vector! (-> group dir2 color) 0.625 0.375 0.1 1.0))
(none))
+219 -376
View File
@@ -30,223 +30,115 @@
(set! (-> *target* sidekick 0 draw light-index) (the-as uint light-index))
light-index)))
(#when PC_PORT
(defun update-mood-itimes ((context mood-context))
"Convert the eight floating palette weights into the packed values used by time-of-day palette
interpolation. Each times vector has one in xyz and its weight in w, so multiplying xyz by w
broadcasts the weight. Conversion to 20.12 fixed point followed by a six-bit arithmetic shift
produces 4.6 values; packing pairs of 32-bit lanes into high halfwords stores all eight weights
in four itimes quadwords."
(local-vars
(slot0-raw uint128)
(slot0-fixed uint128)
(packed01 uint128)
(packed45 uint128)
(slot1-raw uint128)
(slot1-fixed uint128)
(packed23 uint128)
(packed67 uint128)
(slot2-raw uint128)
(slot2-fixed uint128)
(slot3-raw uint128)
(slot3-fixed uint128)
(slot4-raw uint128)
(slot4-fixed uint128)
(slot5-raw uint128)
(slot5-fixed uint128)
(slot6-raw uint128)
(slot6-fixed uint128)
(slot7-raw uint128)
(slot7-fixed uint128))
;; og:preserve-this pc mood debug
(with-pc
(case *mood-override-debug*
(('copy #t) (dotimes (mti 8) (set! (-> context times mti w) (-> *mood-override-table* mti))))
(('mult) (dotimes (mti 8) (*! (-> context times mti w) (-> *mood-override-table* mti))))))
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
(vf8 :class vf))
(nop!)
(nop!)
(.lvf vf1 (&-> context times 0 quad))
(nop!)
(.lvf vf2 (&-> context times 1 quad))
(.mul.w.vf.xyz vf1 vf1 vf1)
(.lvf vf3 (&-> context times 2 quad))
(.mul.w.vf.xyz vf2 vf2 vf2)
(.lvf vf4 (&-> context times 3 quad))
(.mul.w.vf.xyz vf3 vf3 vf3)
(.lvf vf5 (&-> context times 4 quad))
(.mul.w.vf.xyz vf4 vf4 vf4)
(.lvf vf6 (&-> context times 5 quad))
(.mul.w.vf.xyz vf5 vf5 vf5)
(.lvf vf7 (&-> context times 6 quad))
(.mul.w.vf.xyz vf6 vf6 vf6)
(.lvf vf8 (&-> context times 7 quad))
(.mul.w.vf.xyz vf7 vf7 vf7)
(nop!)
(.mul.w.vf.xyz vf8 vf8 vf8)
(nop!)
(vftoi12.xyzw vf1 vf1)
(nop!)
(vftoi12.xyzw vf2 vf2)
(nop!)
(vftoi12.xyzw vf3 vf3)
(nop!)
(vftoi12.xyzw vf4 vf4)
(nop!)
(vftoi12.xyzw vf5 vf5)
(nop!)
(vftoi12.xyzw vf6 vf6)
(nop!)
(vftoi12.xyzw vf7 vf7)
(nop!)
(vftoi12.xyzw vf8 vf8)
(nop!)
(.mov slot0-raw vf1)
(nop!)
(.mov slot1-raw vf2)
(nop!)
(.mov slot2-raw vf3)
(.pw.sra slot0-fixed slot0-raw 6)
(.mov slot3-raw vf4)
(.pw.sra slot1-fixed slot1-raw 6)
(.mov slot4-raw vf5)
(.pw.sra slot2-fixed slot2-raw 6)
(.mov slot5-raw vf6)
(.pw.sra slot3-fixed slot3-raw 6)
(.mov slot6-raw vf7)
(.pw.sra slot4-fixed slot4-raw 6)
(.mov slot7-raw vf8)
(.pw.sra slot5-fixed slot5-raw 6)
(.pw.sra slot6-fixed slot6-raw 6)
(nop!)
(.pw.sra slot7-fixed slot7-raw 6)
(nop!)
(.ppach packed01 slot1-fixed slot0-fixed)
(nop!)
(.ppach packed23 slot3-fixed slot2-fixed)
(set! (-> context itimes 0 quad) packed01)
(.ppach packed45 slot5-fixed slot4-fixed)
(set! (-> context itimes 1 quad) packed23)
(.ppach packed67 slot7-fixed slot6-fixed)
(set! (-> context itimes 2 quad) packed45)
(nop!)
(set! (-> context itimes 3 quad) packed67)
0
(none))))
(#unless PC_PORT
(defun update-mood-itimes ((context mood-context))
"Convert the eight floating palette weights into the packed values used by time-of-day palette
interpolation. Each times vector has one in xyz and its weight in w, so multiplying xyz by w
broadcasts the weight. Conversion to 20.12 fixed point followed by a six-bit arithmetic shift
produces 4.6 values; packing pairs of 32-bit lanes into high halfwords stores all eight weights
in four itimes quadwords."
(rlet ((time-data (&-> context times 0 quad))
(itime-data (&-> context itimes 0 quad))
(time0 :reg vf1)
(time1 :reg vf2)
(time2 :reg vf3)
(time3 :reg vf4)
(time4 :reg vf5)
(time5 :reg vf6)
(time6 :reg vf7)
(time7 :reg vf8)
(slot0-raw :class i128)
(slot0-fixed :class i128)
(packed01 :class i128)
(packed45 :class i128)
(slot1-raw :class i128)
(slot1-fixed :class i128)
(packed23 :class i128)
(packed67 :class i128)
(slot2-raw :class i128)
(slot2-fixed :class i128)
(slot3-raw :class i128)
(slot3-fixed :class i128)
(slot4-raw :class i128)
(slot4-fixed :class i128)
(slot5-raw :class i128)
(slot5-fixed :class i128)
(slot6-raw :class i128)
(slot6-fixed :class i128)
(slot7-raw :class i128)
(slot7-fixed :class i128))
(nop!)
(nop!)
(l.vf time0 time-data)
(nop!)
(l.vf time1 time-data 16)
(mul.w.vf.xyz time0 time0 time0)
(l.vf time2 time-data 32)
(mul.w.vf.xyz time1 time1 time1)
(l.vf time3 time-data 48)
(mul.w.vf.xyz time2 time2 time2)
(l.vf time4 time-data 64)
(mul.w.vf.xyz time3 time3 time3)
(l.vf time5 time-data 80)
(mul.w.vf.xyz time4 time4 time4)
(l.vf time6 time-data 96)
(mul.w.vf.xyz time5 time5 time5)
(l.vf time7 time-data 112)
(mul.w.vf.xyz time6 time6 time6)
(nop!)
(mul.w.vf.xyz time7 time7 time7)
(nop!)
(ftoi.vf time0 time0 :fixed 12)
(nop!)
(ftoi.vf time1 time1 :fixed 12)
(nop!)
(ftoi.vf time2 time2 :fixed 12)
(nop!)
(ftoi.vf time3 time3 :fixed 12)
(nop!)
(ftoi.vf time4 time4 :fixed 12)
(nop!)
(ftoi.vf time5 time5 :fixed 12)
(nop!)
(ftoi.vf time6 time6 :fixed 12)
(nop!)
(ftoi.vf time7 time7 :fixed 12)
(nop!)
(m slot0-raw time0)
(nop!)
(m slot1-raw time1)
(nop!)
(m slot2-raw time2)
(sra.w slot0-fixed slot0-raw 6)
(m slot3-raw time3)
(sra.w slot1-fixed slot1-raw 6)
(m slot4-raw time4)
(sra.w slot2-fixed slot2-raw 6)
(m slot5-raw time5)
(sra.w slot3-fixed slot3-raw 6)
(m slot6-raw time6)
(sra.w slot4-fixed slot4-raw 6)
(m slot7-raw time7)
(sra.w slot5-fixed slot5-raw 6)
(sra.w slot6-fixed slot6-raw 6)
(mmi-nop!)
(sra.w slot7-fixed slot7-raw 6)
(mmi-nop!)
(ppach packed01 slot1-fixed slot0-fixed)
(mmi-nop!)
(ppach packed23 slot3-fixed slot2-fixed)
(s.q packed01 itime-data)
(ppach packed45 slot5-fixed slot4-fixed)
(s.q packed23 itime-data 16)
(ppach packed67 slot7-fixed slot6-fixed)
(s.q packed45 itime-data 32)
(nop!)
(s.q packed67 itime-data 48)
0
(none))))
(defun update-mood-itimes ((context mood-context))
"Convert the eight floating palette weights into the packed values used by time-of-day palette
interpolation. Each times vector has one in xyz and its weight in w, so multiplying xyz by w
broadcasts the weight. Conversion to 20.12 fixed point followed by a six-bit arithmetic shift
produces 4.6 values; packing pairs of 32-bit lanes into high halfwords stores all eight weights
in four itimes quadwords."
(local-vars
(slot0-raw uint128)
(slot0-fixed uint128)
(packed01 uint128)
(packed45 uint128)
(slot1-raw uint128)
(slot1-fixed uint128)
(packed23 uint128)
(packed67 uint128)
(slot2-raw uint128)
(slot2-fixed uint128)
(slot3-raw uint128)
(slot3-fixed uint128)
(slot4-raw uint128)
(slot4-fixed uint128)
(slot5-raw uint128)
(slot5-fixed uint128)
(slot6-raw uint128)
(slot6-fixed uint128)
(slot7-raw uint128)
(slot7-fixed uint128))
;; og:preserve-this pc mood debug
(with-pc
(case *mood-override-debug*
(('copy #t) (dotimes (mti 8) (set! (-> context times mti w) (-> *mood-override-table* mti))))
(('mult) (dotimes (mti 8) (*! (-> context times mti w) (-> *mood-override-table* mti))))))
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
(vf8 :class vf))
(nop!)
(nop!)
(.lvf vf1 (&-> context times 0 quad))
(nop!)
(.lvf vf2 (&-> context times 1 quad))
(.mul.w.vf.xyz vf1 vf1 vf1)
(.lvf vf3 (&-> context times 2 quad))
(.mul.w.vf.xyz vf2 vf2 vf2)
(.lvf vf4 (&-> context times 3 quad))
(.mul.w.vf.xyz vf3 vf3 vf3)
(.lvf vf5 (&-> context times 4 quad))
(.mul.w.vf.xyz vf4 vf4 vf4)
(.lvf vf6 (&-> context times 5 quad))
(.mul.w.vf.xyz vf5 vf5 vf5)
(.lvf vf7 (&-> context times 6 quad))
(.mul.w.vf.xyz vf6 vf6 vf6)
(.lvf vf8 (&-> context times 7 quad))
(.mul.w.vf.xyz vf7 vf7 vf7)
(nop!)
(.mul.w.vf.xyz vf8 vf8 vf8)
(nop!)
(vftoi12.xyzw vf1 vf1)
(nop!)
(vftoi12.xyzw vf2 vf2)
(nop!)
(vftoi12.xyzw vf3 vf3)
(nop!)
(vftoi12.xyzw vf4 vf4)
(nop!)
(vftoi12.xyzw vf5 vf5)
(nop!)
(vftoi12.xyzw vf6 vf6)
(nop!)
(vftoi12.xyzw vf7 vf7)
(nop!)
(vftoi12.xyzw vf8 vf8)
(nop!)
(.mov slot0-raw vf1)
(nop!)
(.mov slot1-raw vf2)
(nop!)
(.mov slot2-raw vf3)
(.pw.sra slot0-fixed slot0-raw 6)
(.mov slot3-raw vf4)
(.pw.sra slot1-fixed slot1-raw 6)
(.mov slot4-raw vf5)
(.pw.sra slot2-fixed slot2-raw 6)
(.mov slot5-raw vf6)
(.pw.sra slot3-fixed slot3-raw 6)
(.mov slot6-raw vf7)
(.pw.sra slot4-fixed slot4-raw 6)
(.mov slot7-raw vf8)
(.pw.sra slot5-fixed slot5-raw 6)
(.pw.sra slot6-fixed slot6-raw 6)
(nop!)
(.pw.sra slot7-fixed slot7-raw 6)
(nop!)
(.ppach packed01 slot1-fixed slot0-fixed)
(nop!)
(.ppach packed23 slot3-fixed slot2-fixed)
(set! (-> context itimes 0 quad) packed01)
(.ppach packed45 slot5-fixed slot4-fixed)
(set! (-> context itimes 1 quad) packed23)
(.ppach packed67 slot7-fixed slot6-fixed)
(set! (-> context itimes 2 quad) packed45)
(nop!)
(set! (-> context itimes 3 quad) packed67)
0
(none)))
(defun update-mood-prt-color ((context mood-context))
"Derive a missing particle tint from seventy-five percent ambient light and twenty-five percent
@@ -255,14 +147,11 @@
(ambient-color (-> groups 0 ambi color))
(directional-color (new 'stack-no-clear 'vector)))
(vector4-lerp! directional-color (-> groups 0 dir0 color) (-> groups 0 dir1 color) (-> groups 0 dir1 levels x))
(set! (-> context current-prt-color x)
(* 0.5 (+ (-> ambient-color x) (* 0.5 (+ (-> ambient-color x) (-> directional-color x))))))
(set! (-> context current-prt-color y)
(* 0.5 (+ (-> ambient-color y) (* 0.5 (+ (-> ambient-color y) (-> directional-color y))))))
(set! (-> context current-prt-color z)
(* 0.5 (+ (-> ambient-color z) (* 0.5 (+ (-> ambient-color z) (-> directional-color z))))))
(set! (-> context current-prt-color w)
(* 0.5 (+ (-> ambient-color w) (* 0.5 (+ (-> ambient-color w) (-> directional-color w)))))))
(set-vector! (-> context current-prt-color)
(* 0.5 (+ (-> ambient-color x) (* 0.5 (+ (-> ambient-color x) (-> directional-color x)))))
(* 0.5 (+ (-> ambient-color y) (* 0.5 (+ (-> ambient-color y) (-> directional-color y)))))
(* 0.5 (+ (-> ambient-color z) (* 0.5 (+ (-> ambient-color z) (-> directional-color z)))))
(* 0.5 (+ (-> ambient-color w) (* 0.5 (+ (-> ambient-color w) (-> directional-color w)))))))
(let ((shadow-color (-> context current-shadow-color)))
(vector-copy! shadow-color (-> context current-prt-color))
shadow-color))
@@ -292,12 +181,12 @@
(let ((snapshot (-> context mood-lights-table data snapshot-a-index)))
(set! (-> context times snapshot-a-index w) 1.0)
(vector-copy! (-> context current-prt-color) (-> snapshot prt-color))
(set! (-> groups 0 ambi color quad) (-> snapshot amb-color quad))
(vector-copy! (-> groups 0 ambi color) (-> snapshot amb-color))
(set! (-> groups 0 ambi levels x) 1.0)
(vector-copy! (-> context current-shadow) (-> snapshot shadow))
(let ((color-level (+ (* 2.0 (-> snapshot lgt-color x)) (* 4.0 (-> snapshot lgt-color y)) (-> snapshot lgt-color z))))
(set! (-> groups 0 dir0 direction quad) (-> snapshot direction quad))
(set! (-> groups 0 dir0 color quad) (-> snapshot lgt-color quad))
(vector-copy! (-> groups 0 dir0 direction) (-> snapshot direction))
(vector-copy! (-> groups 0 dir0 color) (-> snapshot lgt-color))
(set! (-> groups 0 dir0 levels x) 1.0)
(set! (-> groups 0 dir0 levels y) color-level)))
(set! (-> *time-of-day-context* light-masks-0 level-index) (the-as uint (ash 1 snapshot-a-index)))
@@ -316,21 +205,21 @@
(let ((color-level-a (* (+ (* 2.0 (-> snapshot-a lgt-color x)) (* 4.0 (-> snapshot-a lgt-color y)) (-> snapshot-a lgt-color z))
(- 1.0 blend)))
(color-level-b (* (+ (* 2.0 (-> snapshot-b lgt-color x)) (* 4.0 (-> snapshot-b lgt-color y)) (-> snapshot-b lgt-color z)) blend)))
(set! (-> groups 0 dir0 direction quad) (-> snapshot-a direction quad))
(set! (-> groups 0 dir0 color quad) (-> snapshot-a lgt-color quad))
(vector-copy! (-> groups 0 dir0 direction) (-> snapshot-a direction))
(vector-copy! (-> groups 0 dir0 color) (-> snapshot-a lgt-color))
(set! (-> groups 0 dir0 levels x) (- 1.0 blend))
(set! (-> groups 0 dir0 levels y) color-level-a)
(set! (-> groups 0 dir1 direction quad) (-> snapshot-b direction quad))
(set! (-> groups 0 dir1 color quad) (-> snapshot-b lgt-color quad))
(vector-copy! (-> groups 0 dir1 direction) (-> snapshot-b direction))
(vector-copy! (-> groups 0 dir1 color) (-> snapshot-b lgt-color))
(set! (-> groups 0 dir1 levels x) blend)
(set! (-> groups 0 dir1 levels y) color-level-b)))
(set! (-> *time-of-day-context* light-masks-0 level-index) (the-as uint (ash 1 snapshot-a-index)))
(set! (-> *time-of-day-context* light-masks-1 level-index) (the-as uint (ash 1 snapshot-b-index)))
(set! (-> *time-of-day-context* light-interp level-index) blend)))
(if (and (= (-> context current-prt-color x) 0.0)
(= (-> context current-prt-color y) 0.0)
(= (-> context current-prt-color z) 0.0))
(update-mood-prt-color context))
(= (-> context current-prt-color y) 0.0)
(= (-> context current-prt-color z) 0.0))
(update-mood-prt-color context))
blend))
(defun update-mood-sky-texture ((context mood-context) (hour float))
@@ -1084,9 +973,10 @@
(cond
((and (= egg-top-reminder 2) (nonzero? blue-transition-time))
(if (< (the-as uint 60) blue-transition-time)
(set! (-> context times 2 w) 2.0)
(set! (-> context times 2 w) (* 0.033333335 (the float blue-transition-time))))
(if (not (paused?)) (set! (-> context state 2) (+ blue-transition-time -1)))
(set! (-> context times 2 w) 2.0)
(set! (-> context times 2 w) (* 0.033333335 (the float blue-transition-time))))
(if (not (paused?))
(set! (-> context state 2) (+ blue-transition-time -1)))
(set! (-> context times 1 w) 1.0)
(update-mood-jungleb-blue context hour level-index))
((and (nonzero? egg-top-reminder) (!= blue-transition-time 180))
@@ -1098,23 +988,14 @@
(set! (-> context state 1) (the-as uint 0))
(set! (-> context state 0) (the-as uint 255))
(let ((fog-snapshot (-> context mood-fog-table data)))
(set! (-> fog-snapshot 0 fog-color x) 0.0)
(set! (-> fog-snapshot 0 fog-color y) 0.0)
(set! (-> fog-snapshot 0 fog-color z) 0.0)
(set! (-> fog-snapshot 0 fog-color w) 128.0))
(set-vector! (-> fog-snapshot 0 fog-color) 0.0 0.0 0.0 128.0))
(set! (-> context mood-fog-table data 0 fog-dists x) 98304.0)
(set-vector! (-> context mood-fog-table data 0 erase-color) 0.0 0.0 0.0 128.0)
(let ((sun-snapshot (-> context mood-sun-table data)))
(set! (-> sun-snapshot 0 sun-color x) 0.0)
(set! (-> sun-snapshot 0 sun-color y) 0.0)
(set! (-> sun-snapshot 0 sun-color z) 0.0)
(set! (-> sun-snapshot 0 sun-color w) 0.0))
(set-vector! (-> sun-snapshot 0 sun-color) 0.0 0.0 0.0 0.0))
(set-vector! (-> context mood-sun-table data 0 env-color) 48.0 60.0 96.0 255.0)
(let ((light-snapshot (-> context mood-lights-table data)))
(set! (-> light-snapshot 0 direction x) 0.0)
(set! (-> light-snapshot 0 direction y) 1.0)
(set! (-> light-snapshot 0 direction z) 0.0)
(set! (-> light-snapshot 0 direction w) 0.0))
(set-vector! (-> light-snapshot 0 direction) 0.0 1.0 0.0 0.0))
(set-vector! (-> context mood-lights-table data 0 lgt-color) 0.287 0.283 0.4 1.0)
(set-vector! (-> context mood-lights-table data 0 amb-color) 0.166125 0.2125 0.4 1.0)
(set-vector! (-> context mood-lights-table data 0 prt-color) 0.14235 0.1645 0.2875 1.0)
@@ -1127,10 +1008,7 @@
(let ((group (-> context light-group 2)))
(quad-copy! (the-as pointer group) (the-as pointer (-> context light-group)) 12)
(let ((down-light (-> group dir2)))
(set! (-> down-light direction x) 0.0)
(set! (-> down-light direction y) 1.0)
(set! (-> down-light direction z) 0.0)
(set! (-> down-light direction w) 0.0))
(set-vector! (-> down-light direction) 0.0 1.0 0.0 0.0))
(set-vector! (-> group dir2 color) 0.0 0.5 0.75 1.0)
(set! (-> group dir2 levels x) 1.0))
(let ((jungle-group (-> *jungle-mood* light-group 1))
@@ -1138,10 +1016,7 @@
(let ((ambient-offset (new 'stack-no-clear 'vector)))
(quad-copy! (the-as pointer group) (the-as pointer (-> context light-group)) 12)
(let ((down-light (-> group dir2)))
(set! (-> down-light direction x) 0.0)
(set! (-> down-light direction y) 1.0)
(set! (-> down-light direction z) 0.0)
(set! (-> down-light direction w) 0.0))
(set-vector! (-> down-light direction) 0.0 1.0 0.0 0.0))
(set-vector! (-> group dir2 color) 0.4 0.25 0.1 1.0)
(set! (-> group dir2 levels x) 1.0)
(set-vector! ambient-offset 0.25 0.25 0.25 0.0)
@@ -1149,7 +1024,7 @@
(quad-copy! (the-as pointer jungle-group) (the-as pointer group) 12))
(let ((landmark-position (new 'stack-no-clear 'vector))
(target-position (target-joint-pos)))
(set-vector! landmark-position 1482752.0 (-> target-position y) -985088.0 1.0)
(set-vector! landmark-position (meters 362) (-> target-position y) -985088.0 1.0)
(let ((distance (vector-vector-distance landmark-position target-position)))
(when (< distance 81920.0)
(let ((horizontal-fade (* 0.000034877234 (+ -53248.0 distance)))
@@ -1161,31 +1036,26 @@
(let* ((height-level (- 1.0 (fmax 0.0 (fmin 1.0 height-fade))))
(fire-level (* (- 1.0 (fmax 0.0 (fmin 1.0 horizontal-fade))) height-level)))
(let ((down-light (-> groups 0 dir2)))
(set! (-> down-light direction x) 0.0)
(set! (-> down-light direction y) 1.0)
(set! (-> down-light direction z) 0.0)
(set! (-> down-light direction w) 0.0))
(set-vector! (-> down-light direction) 0.0 1.0 0.0 0.0))
(set-vector! (-> groups 0 dir2 color) 0.4 0.25 0.1 1.0)
(set! (-> groups 0 dir2 levels x) fire-level)
(let ((down-light (-> jungle-groups 0 dir2)))
(set! (-> down-light direction x) 0.0)
(set! (-> down-light direction y) 1.0)
(set! (-> down-light direction z) 0.0)
(set! (-> down-light direction w) 0.0))
(set-vector! (-> down-light direction) 0.0 1.0 0.0 0.0))
(set-vector! (-> jungle-groups 0 dir2 color) 0.4 0.25 0.1 1.0)
(set! (-> jungle-groups 0 dir2 levels x) fire-level)
(set-vector! bright-ambient 0.25 0.25 0.25 0.0)
(vector+! bright-ambient bright-ambient (the-as vector (-> groups 0 ambi color)))
(vector4-lerp! (-> groups 0 ambi color) (-> groups 0 ambi color) bright-ambient fire-level)))))
(set-vector! landmark-position 1146880.0 (-> target-position y) -1232896.0 1.0)
(if (< (vector-vector-distance landmark-position target-position) 10240.0) (set! *teleport* #t))
(set-vector! landmark-position 1781760.0 -163840.0 -1038336.0 1.0)
(set-vector! landmark-position (meters 280) (-> target-position y) (meters -301) 1.0)
(if (< (vector-vector-distance landmark-position target-position) 10240.0)
(set! *teleport* #t))
(set-vector! landmark-position (meters 435) (meters -40) -1038336.0 1.0)
(let ((distance (vector-vector-distance landmark-position target-position)))
(when (< distance 147456.0)
(let ((fade (* 0.000030517578 (+ -114688.0 distance))))
(set-target-light-index 2)
(set! (-> *time-of-day-context* target-interp) (- 1.0 (fmax 0.0 (fmin 1.0 fade)))))))
(set-vector! landmark-position 1105920.0 -188416.0 -1204224.0 1.0)
(set-vector! landmark-position (meters 270) (meters -46) (meters -294) 1.0)
(let ((distance (vector-vector-distance landmark-position target-position)))
(when (< distance 106496.0)
(let ((fade (* 0.000030517578 (+ -73728.0 distance))))
@@ -1449,7 +1319,7 @@
(none))
(defun update-mood-darkcave ((context mood-context) (hour float) (level-index int))
"Update Dark Eco Plant's mood, lava glow, and proximity-based local lighting."
"Update"
(when (not (paused?))
(clear-mood-times context)
(set! (-> context times 0 w) 1.0)
@@ -1561,8 +1431,7 @@
(time uint8)))
(defun update-mood-village3 ((context mood-context) (hour float) (level-index int))
"Update Volcanic Crater's mood, lava and caustic effects, local light kits, and target lighting
transitions."
"Update Volcanic Crater's mood, lava effects, local light kits, and target lighting transitions."
(update-mood-fog context hour)
(update-mood-sky-texture context hour)
(clear-mood-times context)
@@ -1574,31 +1443,19 @@
(dark-ambient-color (new 'stack-no-clear 'vector))
(up-direction (new 'stack-no-clear 'vector)))
(let ((snapshot (-> context mood-lights-table data)))
(set! (-> snapshot 0 direction x) -0.067)
(set! (-> snapshot 0 direction y) 0.25)
(set! (-> snapshot 0 direction z) 0.966)
(set! (-> snapshot 0 direction w) 0.0))
(set-vector! (-> snapshot 0 direction) -0.067 0.25 0.966 0.0))
(set-vector! (-> context mood-lights-table data 0 lgt-color) 0.0 0.0 0.0 1.0)
(set-vector! (-> context mood-lights-table data 0 amb-color) 0.449 0.35 0.599 1.0)
(let ((snapshot (-> context mood-lights-table data 1)))
(set! (-> snapshot direction x) 0.259)
(set! (-> snapshot direction y) 0.966)
(set! (-> snapshot direction z) 0.0)
(set! (-> snapshot direction w) 0.0))
(set-vector! (-> snapshot direction) 0.259 0.966 0.0 0.0))
(set-vector! (-> context mood-lights-table data 1 lgt-color) 0.66 0.436 0.291 1.0)
(set-vector! (-> context mood-lights-table data 1 amb-color) 0.358 0.575 0.716 1.0)
(let ((snapshot (-> context mood-lights-table data 2)))
(set! (-> snapshot direction x) -0.067)
(set! (-> snapshot direction y) 0.25)
(set! (-> snapshot direction z) -0.966)
(set! (-> snapshot direction w) 0.0))
(set-vector! (-> snapshot direction) -0.067 0.25 -0.966 0.0))
(set-vector! (-> context mood-lights-table data 2 lgt-color) 0.0 0.0 0.0 1.0)
(set-vector! (-> context mood-lights-table data 2 amb-color) 0.383 0.366 0.599 1.0)
(let ((snapshot (-> context mood-lights-table data 3)))
(set! (-> snapshot direction x) 0.866)
(set! (-> snapshot direction y) 0.5)
(set! (-> snapshot direction z) 0.0)
(set! (-> snapshot direction w) 0.0))
(set-vector! (-> snapshot direction) 0.866 0.5 0.0 0.0))
(set-vector! (-> context mood-lights-table data 3 lgt-color) 0.0 0.0 0.0 1.0)
(set-vector! (-> context mood-lights-table data 3 amb-color) 0.304 0.409 0.76 1.0)
(let ((group (-> context light-group 1)))
@@ -1638,11 +1495,12 @@
(let ((lava-blend (* 0.015625 (the float (logand (-> mood-state time) 63)))))
(set! (-> mood-state scale) (the float (the int (rand-vu-float-range 128.0 255.0))))
(set! (-> context times 7 w) (* lava-blend (-> mood-state scale)))))))
(else (set-vector! local-light-color 0.19 0.128 0.128 1.0)))))
(else
(set-vector! local-light-color 0.19 0.128 0.128 1.0)))))
(let ((landmark-position (new 'stack-no-clear 'vector))
(target-position (target-joint-pos)))
0.0
(set-vector! landmark-position 4454400.0 196608.0 -14725120.0 1.0)
(set-vector! landmark-position 4454400.0 (meters 48) (meters -3595) 1.0)
(let ((distance (vector-vector-distance landmark-position target-position)))
(when (< distance 122880.0)
(let ((fade (* 0.000016276043 (+ -61440.0 distance))))
@@ -1742,7 +1600,7 @@
(when *time-of-day-effects*
(let ((landmark-position (new 'stack-no-clear 'vector))
(camera-position (-> *math-camera* trans)))
(set-vector! landmark-position 868352.0 151552.0 -7720960.0 1.0)
(set-vector! landmark-position (meters 212) (meters 37) (meters -1885) 1.0)
(let ((distance (vector-vector-distance landmark-position camera-position)))
(cond
((< distance 614400.0)
@@ -1750,12 +1608,16 @@
(let* ((distance-fade (* 0.0000048828124 (+ -409600.0 distance)))
(phase-blend (fmax 0.0 (fmin 1.0 distance-fade))))
(let ((mood-state (the-as ogre-states (-> context state))))
(if (not (paused?)) (+! (-> mood-state lava-time) (rand-vu-float-range 64.0 2048.0)))
(if (not (movie?)) (update-mood-lightning context 2 2 18 4 0.5 #f))
(if (not (paused?))
(+! (-> mood-state lava-time) (rand-vu-float-range 64.0 2048.0)))
(if (not (movie?))
(update-mood-lightning context 2 2 18 4 0.5 #f))
(cond
((or (nonzero? *lightning-time2*) (movie?))
(if (not (paused?)) (+! (-> mood-state lava-fade) 0.2))
(if (< 1.0 (-> mood-state lava-fade)) (set! (-> mood-state lava-fade) 1.0))
(if (not (paused?))
(+! (-> mood-state lava-fade) 0.2))
(if (< 1.0 (-> mood-state lava-fade))
(set! (-> mood-state lava-fade) 1.0))
(let* ((lava-fade (-> mood-state lava-fade))
(lava-light (-> context light-group 0 dir2))
(lava-level (+ 0.875 (* 0.125 (sin (-> mood-state lava-time)))))
@@ -1764,26 +1626,24 @@
(set-vector! (-> lava-light color) 1.0 0.38 0.0 1.0)
(set! (-> lava-light levels x) (* lava-level (- 1.0 phase-blend) lava-fade))
(set! (-> lava-light levels y) (* lava-color-level (- 1.0 phase-blend) lava-fade))))
(else (set! (-> mood-state lava-fade) 0.0))))
(else
(set! (-> mood-state lava-fade) 0.0))))
(let ((groups (-> context light-group))
(phase-groups (-> *ogre2-mood* light-group)))
(cond
((= phase-blend 0.0)
(set! (-> groups 0 dir0 direction quad) (-> phase-groups 0 dir0 direction quad))
(set! (-> groups 0 dir0 color quad) (-> phase-groups 0 dir0 color quad))
(set! (-> groups 0 dir0 levels quad) (-> phase-groups 0 dir0 levels quad))
(set! (-> groups 0 dir1 direction quad) (-> phase-groups 0 dir1 direction quad))
(set! (-> groups 0 dir1 color quad) (-> phase-groups 0 dir1 color quad))
(set! (-> groups 0 dir1 levels quad) (-> phase-groups 0 dir1 levels quad))
(set! (-> groups 0 ambi direction quad) (-> phase-groups 0 ambi direction quad))
(set! (-> groups 0 ambi color quad) (-> phase-groups 0 ambi color quad))
(set! (-> groups 0 ambi levels quad) (-> phase-groups 0 ambi levels quad))
(vector-copy! (-> groups 0 dir0 direction) (-> phase-groups 0 dir0 direction))
(vector-copy! (-> groups 0 dir0 color) (-> phase-groups 0 dir0 color))
(vector-copy! (-> groups 0 dir0 levels) (-> phase-groups 0 dir0 levels))
(vector-copy! (-> groups 0 dir1 direction) (-> phase-groups 0 dir1 direction))
(vector-copy! (-> groups 0 dir1 color) (-> phase-groups 0 dir1 color))
(vector-copy! (-> groups 0 dir1 levels) (-> phase-groups 0 dir1 levels))
(vector-copy! (-> groups 0 ambi direction) (-> phase-groups 0 ambi direction))
(vector-copy! (-> groups 0 ambi color) (-> phase-groups 0 ambi color))
(vector-copy! (-> groups 0 ambi levels) (-> phase-groups 0 ambi levels))
(vector-copy! (-> context current-shadow) (-> *ogre2-mood* current-shadow)))
(else
(vector4-lerp! (the-as vector (-> groups 0))
(the-as vector (-> phase-groups 0))
(the-as vector (-> groups 0))
phase-blend)
(vector4-lerp! (-> groups 0 dir0 direction) (-> phase-groups 0 dir0 direction) (-> groups 0 dir0 direction) phase-blend)
(vector4-lerp! (-> groups 0 dir0 color) (-> phase-groups 0 dir0 color) (-> groups 0 dir0 color) phase-blend)
(vector4-lerp! (-> groups 0 dir0 levels) (-> phase-groups 0 dir0 levels) (-> groups 0 dir0 levels) phase-blend)
(vector4-lerp! (-> groups 0 dir1 direction) (-> phase-groups 0 dir1 direction) (-> groups 0 dir1 direction) phase-blend)
@@ -1794,7 +1654,7 @@
(vector4-lerp! (-> groups 0 ambi levels) (-> phase-groups 0 ambi levels) (-> groups 0 ambi levels) phase-blend)
(vector4-lerp! (-> context current-shadow) (-> *ogre2-mood* current-shadow) (-> context current-shadow) phase-blend))))))
(else
(set-vector! landmark-position 2973696.0 184320.0 -13414400.0 1.0)
(set-vector! landmark-position (meters 726) (meters 45) (meters -3275) 1.0)
(let ((distance (vector-vector-distance landmark-position camera-position)))
(when (< distance 1298432.0)
(update-mood-quick *ogre3-mood* 0 0 0 level-index)
@@ -1804,27 +1664,24 @@
(phase-groups (-> *ogre3-mood* light-group)))
(cond
((= phase-blend 0.0)
(set! (-> groups 0 dir0 direction quad) (-> phase-groups 0 dir0 direction quad))
(set! (-> groups 0 dir0 color quad) (-> phase-groups 0 dir0 color quad))
(set! (-> groups 0 dir0 levels quad) (-> phase-groups 0 dir0 levels quad))
(set! (-> groups 0 dir1 direction quad) (-> phase-groups 0 dir1 direction quad))
(set! (-> groups 0 dir1 color quad) (-> phase-groups 0 dir1 color quad))
(set! (-> groups 0 dir1 levels quad) (-> phase-groups 0 dir1 levels quad))
(set! (-> groups 0 dir2 direction quad) (-> phase-groups 0 dir2 direction quad))
(set! (-> groups 0 dir2 color quad) (-> phase-groups 0 dir2 color quad))
(set! (-> groups 0 dir2 levels quad) (-> phase-groups 0 dir2 levels quad))
(set! (-> groups 0 ambi direction quad) (-> phase-groups 0 ambi direction quad))
(set! (-> groups 0 ambi color quad) (-> phase-groups 0 ambi color quad))
(set! (-> groups 0 ambi levels quad) (-> phase-groups 0 ambi levels quad))
(vector-copy! (-> groups 0 dir0 direction) (-> phase-groups 0 dir0 direction))
(vector-copy! (-> groups 0 dir0 color) (-> phase-groups 0 dir0 color))
(vector-copy! (-> groups 0 dir0 levels) (-> phase-groups 0 dir0 levels))
(vector-copy! (-> groups 0 dir1 direction) (-> phase-groups 0 dir1 direction))
(vector-copy! (-> groups 0 dir1 color) (-> phase-groups 0 dir1 color))
(vector-copy! (-> groups 0 dir1 levels) (-> phase-groups 0 dir1 levels))
(vector-copy! (-> groups 0 dir2 direction) (-> phase-groups 0 dir2 direction))
(vector-copy! (-> groups 0 dir2 color) (-> phase-groups 0 dir2 color))
(vector-copy! (-> groups 0 dir2 levels) (-> phase-groups 0 dir2 levels))
(vector-copy! (-> groups 0 ambi direction) (-> phase-groups 0 ambi direction))
(vector-copy! (-> groups 0 ambi color) (-> phase-groups 0 ambi color))
(vector-copy! (-> groups 0 ambi levels) (-> phase-groups 0 ambi levels))
(vector-copy! (-> context current-shadow) (-> *ogre3-mood* current-shadow))
(vector-copy! (-> context current-fog fog-color) (-> *ogre3-mood* current-fog fog-color))
(vector-copy! (-> context current-fog fog-dists) (-> *ogre3-mood* current-fog fog-dists))
(vector-copy! (-> context current-fog erase-color) (-> *ogre3-mood* current-fog erase-color)))
(else
(vector4-lerp! (the-as vector (-> groups 0))
(the-as vector (-> phase-groups 0))
(the-as vector (-> groups 0))
phase-blend)
(vector4-lerp! (-> groups 0 dir0 direction) (-> phase-groups 0 dir0 direction) (-> groups 0 dir0 direction) phase-blend)
(vector4-lerp! (-> groups 0 dir0 color) (-> phase-groups 0 dir0 color) (-> groups 0 dir0 color) phase-blend)
(vector4-lerp! (-> groups 0 dir0 levels) (-> phase-groups 0 dir0 levels) (-> groups 0 dir0 levels) phase-blend)
(vector4-lerp! (-> groups 0 dir1 direction) (-> phase-groups 0 dir1 direction) (-> groups 0 dir1 direction) phase-blend)
@@ -1882,21 +1739,18 @@
(groups (-> context light-group)))
(let ((snapshot (-> context mood-lights-table data 2)))
(set! (-> context times 2 w) palette-fade)
(vector+float*! (the-as vector (-> groups 0)) (the-as vector (-> groups 0)) (-> snapshot direction) palette-fade)
(vector+float*! (-> groups 0 dir0 direction) (-> groups 0 dir0 direction) (-> snapshot direction) palette-fade)
(vector+float*! (-> groups 0 dir0 color) (-> groups 0 dir0 color) (-> snapshot lgt-color) palette-fade))
(vector-normalize! (the-as vector (-> groups 0)) 1.0)))
(vector-normalize! (-> groups 0 dir0 direction) 1.0)))
(let ((arena-position (new 'stack-no-clear 'vector))
(camera-position (-> *math-camera* trans)))
(set-vector! arena-position 12378112.0 1990656.0 -19873792.0 1.0)
(set-vector! arena-position (meters 3022) (meters 486) (meters -4852) 1.0)
(let ((distance (vector-vector-distance arena-position camera-position)))
(when (< distance 819200.0)
(let* ((distance-fade (* 0.0000048828124 (+ -614400.0 distance)))
(arena-light-level (- 1.0 (fmax 0.0 (fmin 1.0 distance-fade)))))
(let ((arena-light (-> *finalboss2-mood* light-group 0 dir2)))
(set! (-> arena-light direction x) 0.0)
(set! (-> arena-light direction y) -1.0)
(set! (-> arena-light direction z) 0.0)
(set! (-> arena-light direction w) 1.0))
(set-vector! (-> arena-light direction) 0.0 -1.0 0.0 1.0))
(set-vector! (-> *finalboss2-mood* light-group 0 dir2 color) 1.0 0.8 2.0 1.0)
(set! (-> *finalboss2-mood* light-group 0 dir2 levels x) arena-light-level)))))
(cond
@@ -1905,10 +1759,7 @@
(secret-light-fade (fmax 0.0 (fmin 1.0 secret-light-time)))
(groups (-> context light-group)))
(let ((secret-light (-> groups 0 dir2)))
(set! (-> secret-light direction x) -0.5768)
(set! (-> secret-light direction y) 0.1697)
(set! (-> secret-light direction z) -0.799)
(set! (-> secret-light direction w) 1.0))
(set-vector! (-> secret-light direction) -0.5768 0.1697 -0.799 1.0))
(set-vector! (-> groups 0 dir2 color) 1.0 1.0 1.0 1.0)
(set! (-> groups 0 dir2 levels x) secret-light-fade)
(let ((shadow-direction (-> context current-shadow)))
@@ -1924,7 +1775,8 @@
(set! (-> *default-shadow-settings* shadow-dir x) (-> shadow-direction x))
(set! (-> *default-shadow-settings* shadow-dir y) (-> shadow-direction y))
(set! (-> *default-shadow-settings* shadow-dir z) (-> shadow-direction z)))))
(else (set-time! (-> mood-state secret-time))))
(else
(set-time! (-> mood-state secret-time))))
(let* ((sun-time (* 0.00019607843 (the float (- (current-time) (-> mood-state start-time)))))
(sun-fade (fmax 0.0 (fmin 1.0 sun-time)))
(sun-fade (fmax 0.0 (fmin 1.0 sun-fade))))
@@ -1955,22 +1807,19 @@
(groups (-> context light-group)))
(let ((snapshot (-> context mood-lights-table data 2)))
(set! (-> context times 2 w) palette-fade)
(vector+float*! (the-as vector (-> groups 0)) (the-as vector (-> groups 0)) (-> snapshot direction) palette-fade)
(vector+float*! (-> groups 0 dir0 direction) (-> groups 0 dir0 direction) (-> snapshot direction) palette-fade)
(vector+float*! (-> groups 0 dir0 color) (-> groups 0 dir0 color) (-> snapshot lgt-color) palette-fade))
(vector-normalize! (the-as vector (-> groups 0)) 1.0))
(vector-normalize! (-> groups 0 dir0 direction) 1.0))
(let ((arena-position (new 'stack-no-clear 'vector))
(camera-position (-> *math-camera* trans)))
(set-vector! arena-position 12378112.0 1990656.0 -19873792.0 1.0)
(set-vector! arena-position (meters 3022) (meters 486) (meters -4852) 1.0)
(let ((distance (vector-vector-distance arena-position camera-position)))
(when (< distance 819200.0)
(let* ((distance-fade (* 0.0000048828124 (+ -614400.0 distance)))
(groups (-> context light-group))
(arena-light-level (- 1.0 (fmax 0.0 (fmin 1.0 distance-fade)))))
(let ((arena-light (-> groups 0 dir2)))
(set! (-> arena-light direction x) 0.0)
(set! (-> arena-light direction y) -1.0)
(set! (-> arena-light direction z) 0.0)
(set! (-> arena-light direction w) 1.0))
(set-vector! (-> arena-light direction) 0.0 -1.0 0.0 1.0))
(set-vector! (-> groups 0 dir2 color) 1.0 0.8 2.0 1.0)
(set! (-> groups 0 dir2 levels x) arena-light-level))))))))
(update-mood-itimes context)
@@ -1996,21 +1845,24 @@
(set! (-> context times 3 w) (-> *palette-fade-controls* control 3 fade))
(update-mood-flames context 4 3 0 0.45 0.001953125 1.0)
(update-mood-light context 1 4 5 0.875 0.25 20.0 32)
(if (not (paused?)) (+! (-> context state 5) 1))
(if (not (paused?))
(+! (-> context state 5) 1))
(let ((state-data (the-as (pointer number) (-> context state))))
(let ((light-flicker (+ 0.5 (* 0.5 (cos (the float (* (logand (+ (-> (the-as (pointer uint8) state-data) 5) 32) 255) 512)))))))
(cond
((movie?))
((nonzero? (-> (the-as (pointer uint8) state-data) 7))
(set! (-> context times 2 w) 1.0)
(if (not (paused?)) (+! (-> (the-as (pointer uint8) state-data) 7) -1)))
(if (not (paused?))
(+! (-> (the-as (pointer uint8) state-data) 7) -1)))
((nonzero? (-> (the-as (pointer uint8) state-data) 6))
(if (not (paused?)) (+! (-> (the-as (pointer uint8) state-data) 6) -1)))
(if (not (paused?))
(+! (-> (the-as (pointer uint8) state-data) 6) -1)))
(else
(set! (-> (the-as (pointer uint8) state-data) 7) (the-as uint (the int (rand-vu-float-range 2.0 20.0))))
(if (zero? (the int (rand-vu-float-range 0.0 3.0)))
(set! (-> (the-as (pointer uint8) state-data) 6) (the-as uint (the int (rand-vu-float-range 2.0 120.0))))
(set! (-> (the-as (pointer uint8) state-data) 6) (the-as uint (the int (rand-vu-float-range 2.0 20.0)))))))
(set! (-> (the-as (pointer uint8) state-data) 6) (the-as uint (the int (rand-vu-float-range 2.0 120.0))))
(set! (-> (the-as (pointer uint8) state-data) 6) (the-as uint (the int (rand-vu-float-range 2.0 20.0)))))))
(let ((light-color (new 'stack-no-clear 'vector))
(warm-light-color (new 'stack-no-clear 'vector))
(groups (-> context light-group)))
@@ -2018,15 +1870,12 @@
(set-vector! warm-light-color 0.75 0.725 0.5 1.0)
(vector4-lerp! light-color light-color warm-light-color light-flicker)
(let ((primary-group (-> groups 0)))
(set! (-> primary-group dir0 direction x) 0.0)
(set! (-> primary-group dir0 direction y) 1.0)
(set! (-> primary-group dir0 direction z) 0.0)
(set! (-> primary-group dir0 direction w) 1.0))
(set! (-> groups 0 dir0 color quad) (-> light-color quad))
(set-vector! (-> primary-group dir0 direction) 0.0 1.0 0.0 1.0))
(vector-copy! (-> groups 0 dir0 color) light-color)
(set! (-> groups 0 dir0 levels x) 1.0)))
(let ((landmark-position (new 'stack-no-clear 'vector))
(target-position (target-joint-pos)))
(set-vector! landmark-position 11227136.0 (-> target-position y) -20164608.0 1.0)
(set-vector! landmark-position (meters 2741) (-> target-position y) (meters -4923) 1.0)
(let ((distance (vector-vector-distance landmark-position target-position)))
(when (< distance 409600.0)
(let* ((distance-fade (* 0.000048828126 (+ -389120.0 distance)))
@@ -2034,7 +1883,7 @@
(set! (-> context current-fog fog-dists y) (* 4096.0 (+ 250.0 (* 300.0 fog-fade))))))))
(let ((shield-position (new 'stack-no-clear 'vector))
(camera-position (-> *math-camera* trans)))
(set-vector! shield-position 11427840.0 (-> camera-position y) -19251200.0 1.0)
(set-vector! shield-position (meters 2790) (-> camera-position y) (meters -4700) 1.0)
(let ((distance (vector-vector-distance shield-position camera-position))
(groups (-> context light-group)))
(cond
@@ -2042,45 +1891,39 @@
(let* ((distance-fade (* 0.000012207031 (+ -409600.0 distance)))
(shield-proximity (- 1.0 (fmax 0.0 (fmin 1.0 distance-fade))))
(shield-flicker (+ 0.5
(* 0.125 (cos (the float (* 4000 (/ (-> *display* time-factor) 5) (-> *display* integral-frame-counter))))) ;; og:preserve-this changed for high fps
(* 0.125
(cos (the float (shl (the int (* (/ (-> *display* time-factor) 5) (-> *display* integral-frame-counter))) 11)))) ;; og:preserve-this changed for high fps
(* 0.25 (cos (the float (* 1500 (/ (-> *display* time-factor) 5) (-> *display* integral-frame-counter))))) ;; og:preserve-this changed for high fps
))
(* 0.125 (cos (the float (* 4000 (-> *display* integral-frame-counter)))))
(* 0.125 (cos (the float (shl (-> *display* integral-frame-counter) 11))))
(* 0.25 (cos (the float (* 1500 (-> *display* integral-frame-counter)))))))
(shield-color (new 'stack-no-clear 'vector)))
(let ((bright-shield-color (new 'stack-no-clear 'vector)))
(set-vector! shield-color 0.275 0.1 1.025 1.0)
(set-vector! bright-shield-color 0.35 0.1 1.1 1.0)
(vector4-lerp! bright-shield-color shield-color bright-shield-color shield-flicker)
(cond
((= (-> *palette-fade-controls* control 7 fade) 1.0) (set! (-> (the-as (pointer float) state-data) 2) 1.0))
((= (-> *palette-fade-controls* control 7 fade) 1.0)
(set! (-> (the-as (pointer float) state-data) 2) 1.0))
(else
(if (not (paused?)) (+! (-> (the-as (pointer float) state-data) 2) -0.1))
(if (not (paused?))
(+! (-> (the-as (pointer float) state-data) 2) -0.1))
(set! (-> (the-as (pointer float) state-data) 2) (fmax 0.0 (fmin 1.0 (-> (the-as (pointer float) state-data) 2))))))
(set-vector! shield-color 0.1 0.1 0.1 1.0)
(let ((shield-fade (* (-> (the-as (pointer float) state-data) 2) shield-proximity)))
(vector4-lerp! shield-color shield-color bright-shield-color shield-fade)
(set! (-> context times 7 w) (* (+ 0.8 (/ shield-flicker 10)) shield-fade))))
(let ((shield-light (-> groups 0 dir1)))
(set! (-> shield-light direction x) 0.0)
(set! (-> shield-light direction y) -1.0)
(set! (-> shield-light direction z) 0.0)
(set! (-> shield-light direction w) 1.0))
(set! (-> groups 0 dir1 color quad) (-> shield-color quad)))
(set-vector! (-> shield-light direction) 0.0 -1.0 0.0 1.0))
(vector-copy! (-> groups 0 dir1 color) shield-color))
(set! (-> groups 0 dir1 levels x) 1.0))
(else
(let ((shield-light (-> groups 0 dir1)))
(set! (-> shield-light direction x) 0.0)
(set! (-> shield-light direction y) -1.0)
(set! (-> shield-light direction z) 0.0)
(set! (-> shield-light direction w) 1.0))
(set-vector! (-> shield-light direction) 0.0 -1.0 0.0 1.0))
(set-vector! (-> groups 0 dir1 color) 0.1 0.1 0.1 1.0)
(set! (-> groups 0 dir1 levels x) 1.0))))))
(let ((landmark-position (new 'stack-no-clear 'vector))
(target-position (target-joint-pos)))
0.0
(when (< 204800.0 (-> target-position y))
(set-vector! landmark-position 11440128.0 (-> target-position y) -19298304.0 1.0)
(set-vector! landmark-position (meters 2793) (-> target-position y) -19298304.0 1.0)
(let ((distance (vector-vector-distance landmark-position target-position))
(groups (-> context light-group)))
(when (< distance 172032.0)
@@ -553,9 +553,6 @@
(label output-complete))
(none))))
(#when PC_PORT
(def-mips2c time-of-day-interp-colors-scratch (function (pointer rgba) time-of-day-palette mood-context none)))
(defun init-time-of-day-context ((context time-of-day-context))
"Initialize the fixed title-screen directional and ambient light colors and enable their levels."
(set-vector! (-> context title-light-group dir0 color) 0.82 0.82 0.82 1.0)
@@ -0,0 +1,832 @@
;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/gfx/sky/sky-tng.gc")
;; Reference-only Emotion Engine implementation of the original inline VU0 sky polygon renderer.
;; This file is intentionally not part of any project or DGO manifest.
;; Each sky vertex is three consecutive quadwords:
;;
;; +0x00 homogeneous position
;; +0x10 perspective texture coordinates (s, t, q, unused)
;; +0x20 floating-point RGBA
;;
;; Polygon lists are closed by repeating the first complete 48-byte record after the last distinct
;; vertex. render-sky-tri and render-sky-quad transform their input into the scratch pages at
;; #x70003000 and #x70003800, preserving STQ and color. draw-large-polygon alternates those pages
;; through four Sutherland-Hodgman clipping passes before emitting ST/RGBAQ/XYZF into the DMA
;; buffer. The persistent VU0 registers are initialized once per layer:
;;
;; vf31..vf28 camera rows scaled into the homogeneous clip volume
;; vf26 inverse homogeneous scale used after clipping
;; vf25 screen/fog offset, with z forced to zero
;; vf24 normalized scrolling texture offset
;; vf23.x GS layer depth (zero normally, 256 for the base layer)
;; vf13 pfog0, fog-min, fog-max, and the 3071 fog ceiling
(#unless PC_PORT
(asm-data (label sky-fog-ceiling)
(word #x453ff000) ;; 3071.0
(label sky-screen-offset-2049)
(word #x45001000) ;; 2049.0
(label sky-texel-phase-scale)
(word #x37800000) ;; 1 / 65536
(label sky-screen-offset-2047)
(word #x44ffe000)) ;; 2047.0
(defun init-sky-regs ()
"Load the camera, projection, fog, and initial layer state used by the inline VU0 sky path.
Select vertical screen offset 2049 when camera translation y is positive and 2047 otherwise."
(declare (asm-func none))
(rlet ((camera :reg v1)
(screen-offset :reg a0)
(work :reg a1)
(address :reg a2)
(function-base :reg fp)
(result :reg v0))
(add.i sp sp -32)
(s.d function-base sp 8)
(m function-base t9)
(m! camera *math-camera*)
(add.i screen-offset sp 16)
(s.q r0 screen-offset)
(m work screen-offset)
(lea.field address camera (hvdf-off))
(l.q address address)
(s.q address work)
(m f0 r0)
(l.s.field f1 camera (trans y))
(c.lt.s f0 f1)
(b.fpf sky-use-2047-offset :delay (nop!))
(l.s f0 function-base sky-screen-offset-2049)
(s.s f0 screen-offset 4)
(m work f0)
(b sky-screen-offset-ready :delay (nop!))
(label sky-use-2047-offset)
(l.s f0 function-base sky-screen-offset-2047)
(s.s f0 screen-offset 4)
(m work f0)
(label sky-screen-offset-ready)
;; Keep the fog range beside the runtime texture state so the projection loop can retain it
;; in vf13 without further scalar loads.
(m! work *sky-tng-data*)
(lea.field work work (fog))
(l.s.field f0 camera (pfog0))
(s.s f0 work)
(l.s.field f0 camera (fog-min))
(s.s f0 work 4)
(l.s.field f0 camera (fog-max))
(s.s f0 work 8)
(l.s f0 function-base sky-fog-ceiling)
(s.s f0 work 12)
(asm-block load-persistent-sky-vectors
(l.vf vf31 camera 572)
(l.vf vf30 camera 588)
(l.vf vf29 camera 604)
(l.vf vf28 camera 620)
(l.vf vf14 camera 700)
(l.vf vf26 camera 716)
(l.vf vf25 screen-offset)
(m! camera *sky-tng-data*)
(l.vf vf13 camera 60)
(mul.vf vf31 vf31 vf14)
(mul.vf vf30 vf30 vf14)
(mul.vf vf29 vf29 vf14)
(mul.vf vf28 vf28 vf14)
(vmove.z vf25 vf0)
(vmove.xyzw vf24 vf0)
(vmove.xyzw vf23 vf0))
(m camera vf23)
(m result r0)
(l.d function-base sp 8)
(jr ra :delay (add.i sp sp 32))
(nop! :count 3)))
(defun set-tex-offset ((s-offset int) (t-offset int))
"Convert wrapped 16-bit texture phases to normalized offsets in vf24.xy; clear z and w."
(declare (asm-func none))
(rlet ((offset :reg v1)
(function-base :reg fp)
(result :reg v0))
(add.i sp sp -32)
(s.d function-base sp 8)
(m function-base t9)
(add.i offset sp 16)
(s.q r0 offset)
(l.s f0 function-base sky-texel-phase-scale)
(m f1 a0)
(cvt.s.w f1 f1)
(mul.s f0 f0 f1)
(s.s f0 offset)
(l.s f0 function-base sky-texel-phase-scale)
(m f1 a1)
(cvt.s.w f1 f1)
(mul.s f0 f0 f1)
(s.s f0 offset 4)
(m f0 r0)
(s.s f0 offset 8)
(m f0 r0)
(s.s f0 offset 12)
(l.vf vf24 offset)
(m offset vf24)
(m result r0)
(l.d function-base sp 8)
(jr ra :delay (add.i sp sp 32))
(nop! :count 2)))
(defun draw-large-polygon ()
"Clip the closed scratch polygon against the four side planes, then append its GS vertices.
The private calling convention carries the polygon count in t0, the DMA buffer in a1, and
the alternating scratch pages in t4 and t5. Return #f if clipping removes every vertex."
(declare (asm-func none))
(nop!)
(add.i sp sp -8)
(nop!)
(s.d ra sp)
;; Sutherland-Hodgman clipping alternates pages so that each pass may stream its output without
;; disturbing unread input. t2 selects x or y within each position; the positive helper tests
;; component <= w and the negative helper tests component >= -w.
(asm-block clip-sky-side-planes
(m! t9 clip-polygon-against-positive-hyperplane)
(m a2 t4)
(m a3 t5)
(jalr ra t9 :delay (add t2 a2 r0))
(b.z t0 sky-polygon-clipped-away :delay (nop!))
(m a2 t5)
(m a3 t4)
(jalr ra t9 :delay (add.i t2 a2 4))
(b.z t0 sky-polygon-clipped-away :delay (m! t9 clip-polygon-against-negative-hyperplane))
(m a2 t4)
(m a3 t5)
(jalr ra t9 :delay (add t2 a2 r0))
(b.z t0 sky-polygon-clipped-away :delay (nop!))
(m a2 t5)
(m a3 t4)
(jalr ra t9 :delay (add.i t2 a2 4))
(b.z t0 sky-polygon-clipped-away :delay (l.w.field a3 a1 (base))))
;; vf27 is the GIF tag for this polygon. Its first word is replaced by the clipped vertex
;; count before ST/RGBAQ/XYZF records are written behind it.
(m a2 t4)
(nop!)
(s.vf vf27 a3)
(add.i a3 a3 16)
(s.w t0 a3 -16)
(nop!)
(label emit-sky-polygon-vertices)
(asm-block project-sky-vertex
(l.vf vf1 a2)
(nop!)
(l.vf vf2 a2 16)
(nop!)
(l.vf vf3 a2 32)
;; Recover 1/w after clipping, undo the homogeneous clip scale, and convert the packed color.
(vdiv Q vf0.w vf1.w)
(mul.vf vf1 vf1 vf26)
(nop!)
(ftoi.vf vf3 vf3)
(nop!)
;; Add the scrolling phase before perspective division so STQ remains perspective correct.
(add.vf vf2 vf2 vf24)
(nop!)
(waitq)
(nop!)
(vmulq.xyz vf1 vf1 Q)
(s.vf vf3 a3 16)
(vmulq.xyzw vf2 vf2 Q)
(add.i a2 a2 48)
;; Map to GS screen space. vf23.x selects the layer depth, while w becomes the clamped fog
;; value carried in XYZF after 12.4 fixed-point conversion.
(add.vf vf1 vf1 vf25)
(add.i a3 a3 48)
(vmulz.z vf1 vf1 vf0)
(nop!)
(vminiz.w vf1 vf1 vf13)
(nop!)
(vaddx.z vf1 vf1 vf23)
(nop!)
(vmaxy.w vf1 vf1 vf13)
(nop!)
(s.vf vf2 a3 -48)
(add.i t0 t0 -1)
(vftoi4.xyzw vf1 vf1)
(nop!)
(b.nz t0 emit-sky-polygon-vertices :delay (s.vf vf1 a3 -16)))
(s.w.field a3 a1 (base))
(nop!)
(l.d ra sp)
(add.i v0 s7 8)
(jr ra :delay (add.i sp sp 8))
(label sky-polygon-clipped-away)
(l.d ra sp)
(m v0 s7)
(jr ra :delay (add.i sp sp 8))
(jr ra :delay (add sp sp r0))
(nop! :count 2))
(defun clip-polygon-against-positive-hyperplane ()
"Clip a closed scratch polygon against component <= w. t2 points at the selected x or y
component of the first position, a2 and a3 are the input and output pages, and t0 is replaced
by the output vertex count. Every crossing interpolates position, STQ, and color together."
(declare (asm-func none))
(asm-block classify-first-positive-vertex
(nop!)
(m t1 t0)
(add.i t0 r0 0)
(l.s f1 t2)
(add.i t2 t2 48)
(l.s f0 a2 12)
(m t3 a3)
(l.vf vf1 a2)
(add.i a2 a2 48)
(c.lt.s f0 f1)
(l.vf vf2 a2 -32)
(b.fpf positive-inside-a :delay (l.vf vf3 a2 -16)))
;; The a/b paths alternate vf1..vf3 and vf4..vf6 as the previous and current records. This
;; avoids moving the three qwords at every edge while retaining the closed-list traversal.
(asm-block walk-positive-outside
(label positive-outside-a)
(l.s f3 t2)
(add.i t2 t2 48)
(l.s f2 a2 12)
(add.i t1 t1 -1)
(l.vf vf4 a2)
(add.i a2 a2 48)
(c.lt.s f2 f3)
(l.vf vf5 a2 -32)
(b.fpf positive-enter-from-a :delay (l.vf vf6 a2 -16))
(b.z t1 positive-clip-finish :delay (nop!))
(label positive-outside-b)
(l.s f1 t2)
(add.i t2 t2 48)
(l.s f0 a2 12)
(add.i t1 t1 -1)
(l.vf vf1 a2)
(add.i a2 a2 48)
(c.lt.s f0 f1)
(l.vf vf2 a2 -32)
(b.fpf positive-enter-from-b :delay (l.vf vf3 a2 -16))
(b.nz t1 positive-outside-a :delay (nop!))
(b positive-clip-finish :delay (nop!))
;; Outside -> inside: solve the plane distance linearly and append only the crossing point.
;; The inside endpoint remains current and is emitted by the following inside path.
(label positive-enter-from-a)
(sub.s f7 f0 f1)
(sub.vf vf7 vf4 vf1)
(sub.s f8 f2 f3)
(sub.vf vf8 vf5 vf2)
(sub.s f5 f7 f8)
(sub.vf vf9 vf6 vf3)
(div.s f6 f7 f5)
(add.i a3 a3 48)
(m v1 f6)
(m vf10 v1)
(add.i t0 t0 1)
(mula.w.vf vf1 vf0)
(add.i t6 s7 8)
(vmaddx.xyzw vf7 vf7 vf10)
(nop!)
(mula.w.vf vf2 vf0)
(nop!)
(vmaddx.xyzw vf8 vf8 vf10)
(nop!)
(mula.w.vf vf3 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 positive-inside-b :delay (s.vf vf9 a3 -16))
(b positive-clip-finish :delay (nop!))
(label positive-enter-from-b)
(sub.s f7 f0 f1)
(sub.vf vf7 vf1 vf4)
(sub.s f8 f2 f3)
(sub.vf vf8 vf2 vf5)
(sub.s f5 f8 f7)
(sub.vf vf9 vf3 vf6)
(div.s f6 f8 f5)
(add.i a3 a3 48)
(m v1 f6)
(m vf10 v1)
(add.i t0 t0 1)
(mula.w.vf vf4 vf0)
(add.i t6 s7 8)
(vmaddx.xyzw vf7 vf7 vf10)
(nop!)
(mula.w.vf vf5 vf0)
(nop!)
(vmaddx.xyzw vf8 vf8 vf10)
(nop!)
(mula.w.vf vf6 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.z t1 positive-clip-finish :delay (s.vf vf9 a3 -16)))
;; Inside -> inside copies the previous record. If the next record is outside, the leave path
;; copies the inside endpoint and appends the crossing point as a second record.
(asm-block walk-positive-inside
(label positive-inside-a)
(l.s f3 t2)
(add.i t2 t2 48)
(l.s f2 a2 12)
(add.i t1 t1 -1)
(l.vf vf4 a2)
(add.i a2 a2 48)
(c.lt.s f2 f3)
(l.vf vf5 a2 -32)
(b.fpt positive-leave-from-a :delay (l.vf vf6 a2 -16))
(s.vf vf1 a3)
(add.i a3 a3 48)
(s.vf vf2 a3 -32)
(add.i t0 t0 1)
(b.z t1 positive-clip-finish :delay (s.vf vf3 a3 -16))
(label positive-inside-b)
(l.s f1 t2)
(add.i t2 t2 48)
(l.s f0 a2 12)
(add.i t1 t1 -1)
(l.vf vf1 a2)
(add.i a2 a2 48)
(c.lt.s f0 f1)
(l.vf vf2 a2 -32)
(b.fpt positive-leave-from-b :delay (l.vf vf3 a2 -16))
(s.vf vf4 a3)
(add.i a3 a3 48)
(s.vf vf5 a3 -32)
(add.i t0 t0 1)
(b.nz t1 positive-inside-a :delay (s.vf vf6 a3 -16))
(b positive-clip-finish :delay (nop!))
(label positive-leave-from-a)
(sub.s f7 f0 f1)
(sub.vf vf7 vf1 vf4)
(sub.s f8 f2 f3)
(sub.vf vf8 vf2 vf5)
(sub.s f5 f8 f7)
(sub.vf vf9 vf3 vf6)
(div.s f6 f8 f5)
(add.i a3 a3 96)
(m v1 f6)
(m vf10 v1)
(s.vf vf1 a3 -96)
(mula.w.vf vf4 vf0)
(s.vf vf2 a3 -80)
(vmaddx.xyzw vf7 vf7 vf10)
(s.vf vf3 a3 -64)
(mula.w.vf vf5 vf0)
(add.i t0 t0 2)
(vmaddx.xyzw vf8 vf8 vf10)
(add.i t6 s7 8)
(mula.w.vf vf6 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 positive-outside-b :delay (s.vf vf9 a3 -16))
(b positive-clip-finish :delay (nop!))
(label positive-leave-from-b)
(sub.s f7 f0 f1)
(sub.vf vf7 vf4 vf1)
(sub.s f8 f2 f3)
(sub.vf vf8 vf5 vf2)
(sub.s f5 f7 f8)
(sub.vf vf9 vf6 vf3)
(div.s f6 f7 f5)
(add.i a3 a3 96)
(m v1 f6)
(m vf10 v1)
(s.vf vf4 a3 -96)
(mula.w.vf vf1 vf0)
(s.vf vf5 a3 -80)
(vmaddx.xyzw vf7 vf7 vf10)
(s.vf vf6 a3 -64)
(mula.w.vf vf2 vf0)
(add.i t0 t0 2)
(vmaddx.xyzw vf8 vf8 vf10)
(add.i t6 s7 8)
(mula.w.vf vf3 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 positive-outside-a :delay (s.vf vf9 a3 -16)))
;; Restore the closed representation expected by the next clipping pass.
(asm-block close-positive-polygon
(label positive-clip-finish)
(l.vf vf1 t3)
(nop!)
(l.vf vf2 t3 16)
(nop!)
(l.vf vf3 t3 32)
(nop!)
(s.vf vf1 a3)
(nop!)
(s.vf vf2 a3 16)
(nop!)
(jr ra :delay (s.vf vf3 a3 32))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun clip-polygon-against-negative-hyperplane ()
"Clip a closed scratch polygon against component >= -w. This is the negative-plane mirror of
clip-polygon-against-positive-hyperplane and uses the same private registers and closed output
format."
(declare (asm-func none))
(asm-block classify-first-negative-vertex
(nop!)
(m t1 t0)
(add.i t0 r0 0)
(l.s f0 a2 12)
(m t3 a3)
(l.s f1 t2)
(add.i t2 t2 48)
(l.vf vf1 a2)
(neg.s f0 f0)
(nop!)
(l.vf vf2 a2 16)
(c.lt.s f1 f0)
(add.i a2 a2 48)
(b.fpf negative-inside-a :delay (l.vf vf3 a2 -16)))
;; The two paths alternate register triples instead of copying the current 48-byte record.
(asm-block walk-negative-outside
(label negative-outside-a)
(l.s f2 a2 12)
(add.i t1 t1 -1)
(l.s f3 t2)
(add.i t2 t2 48)
(l.vf vf4 a2)
(neg.s f2 f2)
(nop!)
(l.vf vf5 a2 16)
(c.lt.s f3 f2)
(add.i a2 a2 48)
(b.fpf negative-enter-from-a :delay (l.vf vf6 a2 -16))
(b.z t1 negative-clip-finish :delay (nop!))
(label negative-outside-b)
(l.s f0 a2 12)
(add.i t1 t1 -1)
(l.s f1 t2)
(add.i t2 t2 48)
(l.vf vf1 a2)
(neg.s f0 f0)
(nop!)
(l.vf vf2 a2 16)
(c.lt.s f1 f0)
(add.i a2 a2 48)
(b.fpf negative-enter-from-b :delay (l.vf vf3 a2 -16))
(b.nz t1 negative-outside-a :delay (nop!))
(b negative-clip-finish :delay (nop!))
;; Outside -> inside writes the interpolated crossing. f6 is the edge fraction measured from
;; the outside endpoint; the same fraction is applied to position, STQ, and color.
(label negative-enter-from-a)
(sub.s f7 f0 f1)
(sub.vf vf7 vf4 vf1)
(sub.s f8 f2 f3)
(sub.vf vf8 vf5 vf2)
(sub.s f5 f7 f8)
(sub.vf vf9 vf6 vf3)
(div.s f6 f7 f5)
(add.i a3 a3 48)
(m v1 f6)
(m vf10 v1)
(add.i t0 t0 1)
(mula.w.vf vf1 vf0)
(add.i t6 s7 8)
(vmaddx.xyzw vf7 vf7 vf10)
(nop!)
(mula.w.vf vf2 vf0)
(nop!)
(vmaddx.xyzw vf8 vf8 vf10)
(nop!)
(mula.w.vf vf3 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 negative-inside-b :delay (s.vf vf9 a3 -16))
(b negative-clip-finish :delay (nop!))
(label negative-enter-from-b)
(sub.s f7 f0 f1)
(sub.vf vf7 vf1 vf4)
(sub.s f8 f2 f3)
(sub.vf vf8 vf2 vf5)
(sub.s f5 f8 f7)
(sub.vf vf9 vf3 vf6)
(div.s f6 f8 f5)
(add.i a3 a3 48)
(m v1 f6)
(m vf10 v1)
(add.i t0 t0 1)
(mula.w.vf vf4 vf0)
(add.i t6 s7 8)
(vmaddx.xyzw vf7 vf7 vf10)
(nop!)
(mula.w.vf vf5 vf0)
(nop!)
(vmaddx.xyzw vf8 vf8 vf10)
(nop!)
(mula.w.vf vf6 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.z t1 negative-clip-finish :delay (s.vf vf9 a3 -16)))
;; Inside runs copy their previous record. A leaving edge emits the inside endpoint followed
;; by the intersection, which is why those paths advance the output by two records.
(asm-block walk-negative-inside
(label negative-inside-a)
(l.s f2 a2 12)
(add.i t1 t1 -1)
(l.s f3 t2)
(add.i t2 t2 48)
(l.vf vf4 a2)
(neg.s f2 f2)
(nop!)
(l.vf vf5 a2 16)
(c.lt.s f3 f2)
(add.i a2 a2 48)
(b.fpt negative-leave-from-a :delay (l.vf vf6 a2 -16))
(s.vf vf1 a3)
(add.i a3 a3 48)
(s.vf vf2 a3 -32)
(add.i t0 t0 1)
(b.z t1 negative-clip-finish :delay (s.vf vf3 a3 -16))
(label negative-inside-b)
(l.s f0 a2 12)
(add.i t1 t1 -1)
(l.s f1 t2)
(add.i t2 t2 48)
(l.vf vf1 a2)
(neg.s f0 f0)
(nop!)
(l.vf vf2 a2 16)
(c.lt.s f1 f0)
(add.i a2 a2 48)
(b.fpt negative-leave-from-b :delay (l.vf vf3 a2 -16))
(s.vf vf4 a3)
(add.i a3 a3 48)
(s.vf vf5 a3 -32)
(add.i t0 t0 1)
(b.nz t1 negative-inside-a :delay (s.vf vf6 a3 -16))
(b negative-clip-finish :delay (nop!))
(label negative-leave-from-a)
(sub.s f7 f0 f1)
(sub.vf vf7 vf1 vf4)
(sub.s f8 f2 f3)
(sub.vf vf8 vf2 vf5)
(sub.s f5 f8 f7)
(sub.vf vf9 vf3 vf6)
(div.s f6 f8 f5)
(add.i a3 a3 96)
(m v1 f6)
(m vf10 v1)
(s.vf vf1 a3 -96)
(mula.w.vf vf4 vf0)
(s.vf vf2 a3 -80)
(vmaddx.xyzw vf7 vf7 vf10)
(s.vf vf3 a3 -64)
(mula.w.vf vf5 vf0)
(add.i t0 t0 2)
(vmaddx.xyzw vf8 vf8 vf10)
(add.i t6 s7 8)
(mula.w.vf vf6 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 negative-outside-b :delay (s.vf vf9 a3 -16))
(b negative-clip-finish :delay (nop!))
(label negative-leave-from-b)
(sub.s f7 f0 f1)
(sub.vf vf7 vf4 vf1)
(sub.s f8 f2 f3)
(sub.vf vf8 vf5 vf2)
(sub.s f5 f7 f8)
(sub.vf vf9 vf6 vf3)
(div.s f6 f7 f5)
(add.i a3 a3 96)
(m v1 f6)
(m vf10 v1)
(s.vf vf4 a3 -96)
(mula.w.vf vf1 vf0)
(s.vf vf5 a3 -80)
(vmaddx.xyzw vf7 vf7 vf10)
(s.vf vf6 a3 -64)
(mula.w.vf vf2 vf0)
(add.i t0 t0 2)
(vmaddx.xyzw vf8 vf8 vf10)
(add.i t6 s7 8)
(mula.w.vf vf3 vf0)
(nop!)
(vmaddx.xyzw vf9 vf9 vf10)
(nop!)
(s.vf vf7 a3 -48)
(nop!)
(s.vf vf8 a3 -32)
(nop!)
(b.nz t1 negative-outside-a :delay (s.vf vf9 a3 -16)))
(asm-block close-negative-polygon
(label negative-clip-finish)
(l.vf vf1 t3)
(nop!)
(l.vf vf2 t3 16)
(nop!)
(l.vf vf3 t3 32)
(nop!)
(s.vf vf1 a3)
(nop!)
(s.vf vf2 a3 16)
(nop!)
(jr ra :delay (s.vf vf3 a3 32))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-sky-quad ((vertices (inline-array sky-vertex)) (dma-buf dma-buffer))
"Transform four sky vertices into a closed five-record scratch polygon and tail-call the
clipping and packet conversion path."
(declare (asm-func none))
;; vf31..vf28 are the persistent camera rows from init-sky-regs. Only x, y, and w are retained;
;; z is cleared so the final layer depth is supplied explicitly by vf23.x.
(asm-block prepare-sky-quad
(m v1 a0)
(m! v1 *math-camera*)
;; Refresh the homogeneous scale with the rest of the camera state before building the page.
(l.vf vf14 v1 700)
(lui t4 #x7000)
(ori t4 t4 #x3000)
(lui t5 #x7000)
(ori t5 t5 #x3800)
(lui v1 #x3000)
(m a3 t4)
(or a0 a0 v1)
(nop!)
(l.vf vf1 a0)
(add.i t0 r0 4)
(l.vf vf2 a0 16)
(nop!)
(l.vf vf3 a0 32)
(mula.x.vf vf31 vf1)
(l.vf vf4 a0 48)
(madda.y.vf vf30 vf1)
(l.vf vf5 a0 64)
(madda.z.vf vf29 vf1)
(l.vf vf6 a0 80)
(vmaddw.xyw vf1 vf28 vf1)
(l.vf vf7 a0 96)
(vmove.z vf1 vf0)
(l.vf vf8 a0 112)
(mula.x.vf vf31 vf4)
(l.vf vf9 a0 128)
(madda.y.vf vf30 vf4)
(l.vf vf10 a0 144)
(madda.z.vf vf29 vf4)
(l.vf vf11 a0 160)
(vmaddw.xyw vf4 vf28 vf4)
(l.vf vf12 a0 176)
(vmove.z vf4 vf0))
(asm-block finish-sky-quad
(s.vf vf2 a3 16)
(mula.x.vf vf31 vf7)
(s.vf vf3 a3 32)
(madda.y.vf vf30 vf7)
(s.vf vf5 a3 64)
(madda.z.vf vf29 vf7)
(s.vf vf6 a3 80)
(vmaddw.xyw vf7 vf28 vf7)
(s.vf vf8 a3 112)
(vmove.z vf7 vf0)
(s.vf vf9 a3 128)
(mula.x.vf vf31 vf10)
(s.vf vf11 a3 160)
(madda.y.vf vf30 vf10)
(s.vf vf12 a3 176)
(madda.z.vf vf29 vf10)
(s.vf vf2 a3 208)
(vmaddw.xyw vf10 vf28 vf10)
(s.vf vf3 a3 224)
(vmove.z vf10 vf0)
(s.vf vf1 a3)
(nop!)
;; Repeat record zero after record three to close the list.
(s.vf vf1 a3 192)
(nop!)
(s.vf vf4 a3 48)
(nop!)
(s.vf vf7 a3 96)
(nop!)
(s.vf vf10 a3 144)
(m! t9 draw-large-polygon)
(jr t9 :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-sky-tri ((vertices (inline-array sky-vertex)) (dma-buf dma-buffer))
"Transform three sky vertices into a closed four-record scratch polygon and tail-call the
clipping and packet conversion path."
(declare (asm-func none))
(asm-block prepare-sky-triangle
(m v1 a0)
(lui t4 #x7000)
(ori t4 t4 #x3000)
(lui t5 #x7000)
(ori t5 t5 #x3800)
(lui v1 #x3000)
(m a3 t4)
(or a0 a0 v1)
(nop!)
(l.vf vf1 a0)
(add.i t0 r0 3)
(l.vf vf2 a0 16)
(nop!)
(l.vf vf3 a0 32)
(mula.x.vf vf31 vf1)
(l.vf vf4 a0 48)
(madda.y.vf vf30 vf1)
(l.vf vf5 a0 64)
(madda.z.vf vf29 vf1)
(l.vf vf6 a0 80)
(vmaddw.xyw vf1 vf28 vf1)
(l.vf vf7 a0 96)
(vmove.z vf1 vf0)
(l.vf vf8 a0 112)
(mula.x.vf vf31 vf4)
(l.vf vf9 a0 128)
(madda.y.vf vf30 vf4)
(s.vf vf2 a3 16)
(madda.z.vf vf29 vf4)
(s.vf vf3 a3 32)
(vmaddw.xyw vf4 vf28 vf4)
(s.vf vf5 a3 64)
(vmove.z vf4 vf0)
(s.vf vf6 a3 80)
(mula.x.vf vf31 vf7)
(s.vf vf8 a3 112)
(madda.y.vf vf30 vf7)
(s.vf vf9 a3 128)
(madda.z.vf vf29 vf7)
(s.vf vf2 a3 160)
(vmaddw.xyw vf7 vf28 vf7)
(s.vf vf3 a3 176)
(vmove.z vf7 vf0)
(s.vf vf1 a3)
(nop!)
;; Repeat record zero after record two to close the list.
(s.vf vf1 a3 144)
(nop!)
(s.vf vf4 a3 48)
(nop!)
(s.vf vf7 a3 96)
(m! t9 draw-large-polygon)
(jr t9 :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun sky-duplicate-polys ((dma-buf dma-buffer) (begin (pointer uint128)) (end (pointer uint128)))
"Append the half-open quadword range [begin, end) to dma-buf. An empty or reversed range writes
nothing."
(declare (asm-func none))
(rlet ((cursor :reg v1)
(quad :reg a3 :class i128)
(result :reg v0))
(l.w.field cursor a0 (base))
(b sky-duplicate-test :delay (nop!))
(label sky-duplicate-copy)
(l.q quad a1)
(s.q quad cursor)
(add.i cursor cursor 16)
(add.i a1 a1 16)
(label sky-duplicate-test)
(slt a3 a1 a2)
(b.nz a3 sky-duplicate-copy :delay (nop!))
(m a1 s7)
(s.w.field cursor a0 (base))
(m result r0)
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun close-sky-buffer ((dma-buf dma-buffer))
"Append the #x8000 terminator for a large-polygon stream and advance the buffer by one qword."
(declare (asm-func none))
(rlet ((terminator :reg v1)
(cursor :reg v0))
(nop!)
(ori terminator r0 #x8000)
(l.w.field cursor a0 (base))
(s.q r0 cursor)
(nop!)
(s.w terminator cursor)
(add.i cursor cursor 16)
(jr ra :delay (s.w.field cursor a0 (base)))
(jr ra :delay (add sp sp r0))
(nop! :count 2))))
File diff suppressed because it is too large Load Diff
@@ -2,6 +2,7 @@
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/gfx/sky/sky-h.gc")
(defun sky-set-sun-radii ((parms sky-parms) (index sky-sun-index) (sun-radius float) (halo-radius float) (aurora-radius float))
"Set the apparent sun, halo, and aurora radii in the sun record selected by index's low bit."
(let ((sun-index (logand index (sky-sun-index green-sun))))
+70 -231
View File
@@ -54,17 +54,20 @@
"Point dst-light toward the selected sun or moon, assign light-color's RGB bytes as normalized
floats while replacing its alpha with 1, and enable the light's first level."
(let* ((orbit-data (-> parms orbit orbit-index))
(body-data (if (= orbit-index (sky-orbit-index moon)) (-> parms upload-data moon) (-> parms upload-data sun orbit-index)))
(body-data (if (= orbit-index (sky-orbit-index moon))
(-> parms upload-data moon)
(-> parms upload-data sun orbit-index)))
(byte-to-float 0.003921569)
(inverse-distance (/ 1.0 (-> orbit-data dist)))
(dst dst-light))
(set! (-> dst direction x) (* (-> (the-as sky-sun-data body-data) pos x) inverse-distance))
(set! (-> dst direction y) (* (-> (the-as sky-sun-data body-data) pos y) inverse-distance))
(set! (-> dst direction z) (* (-> (the-as sky-sun-data body-data) pos z) inverse-distance))
(set! (-> dst color x) (* (the float (-> light-color r)) byte-to-float))
(set! (-> dst color y) (* (the float (-> light-color g)) byte-to-float))
(set! (-> dst color z) (* (the float (-> light-color b)) byte-to-float))
(set! (-> dst color w) 1.0)
(set-vector! (-> dst color)
(* (the float (-> light-color r)) byte-to-float)
(* (the float (-> light-color g)) byte-to-float)
(* (the float (-> light-color b)) byte-to-float)
1.0)
(set! (-> dst levels x) 1.0))
(none))
@@ -359,228 +362,64 @@
(vu-pair (nop) (nop)) ;; #x0cc
))
(#unless PC_PORT
;; Function-relative constants used while constructing the per-frame VIF and GIF records.
(asm-data (label sky-radius)
(word #x4a7a0000) ;; 4096000.0
(label sky-no-kick)
(word #x45400000) ;; 3072.0, which becomes the GS ADC bit after FTOI4
(label sky-sun-strip-tag)
(word #x00008022 #x20264000)
(label sky-sun-fan-tag)
(word #x00008012 #x2026c000)
(label sky-alpha-tag)
(word #x00000001 #x10000000))
(defun sky-add-frame-data ((dma-buf dma-buffer) (unused object))
"Append the 18-qword frame block, update its lighting and celestial upload image, and append the
VIF reference that transfers the 27 celestial-data qwords to VU address 256."
(declare (asm-func none) (allow-saved-regs))
;; sky-frame-data is uploaded to VU address 291. Its first seven qwords contain the camera
;; transform, projection scale/offset, fog scale, legacy 4096000 radius field, and ADC no-kick
;; value. strip-giftag and save[5] are left untouched; this program loads the shared color A+D
;; record and the later sun-specific fan, strip, and alpha records.
(rlet ((buffer :reg gp)
(frame-qwc :reg v1)
(cursor :reg a1)
(camera :reg a2)
(function-base :reg fp)
(result :reg v0))
(add.i sp sp -32)
(s.d ra sp)
(s.d function-base sp 8)
(m function-base t9)
(s.q buffer sp 16)
(m buffer a0)
(asm-block append-frame-unpack
(add.i frame-qwc r0 18)
(m a0 buffer)
(l.w.field cursor a0 (base))
(lui a2 #x1000)
(sll32 a3 frame-qwc 16)
(srl32 a3 a3 16)
(or a2 a2 a3)
(s.d a2 cursor)
(lui a2 256)
(ori a2 a2 1028) ;; STCYCL 4,4
(s.w a2 cursor 8)
(lui a2 #x6c00)
(ori a2 a2 291)
(sll32 a3 frame-qwc 24)
(srl32 a3 a3 8)
(or a2 a2 a3) ;; UNPACK V4-32, 18 qwords, VU address 291
(s.w a2 cursor 12)
(add.i cursor cursor 16)
(s.w.field cursor a0 (base)))
(asm-block fill-camera-frame-data
(l.w.field a0 buffer (base))
(add cursor r0 a0)
(m! camera *math-camera*)
(lea.field t1 camera (camera-temp))
(l.q camera t1)
(l.q a3 t1 16)
(l.q t0 t1 32)
(l.q t1 t1 48)
(s.q camera cursor)
(s.q a3 cursor 16)
(s.q t0 cursor 32)
(s.q t1 cursor 48)
(add.i cursor a0 64)
(m! camera *math-camera*)
(lea.field camera camera (hmge-scale))
(l.q camera camera)
(s.q camera cursor)
(add.i cursor a0 80)
(m! camera *math-camera*)
(lea.field camera camera (hvdf-off))
(l.q camera camera)
(s.q camera cursor)
;; Keep the sky on its fixed GS depth plane instead of applying the camera's Z offset.
(m f0 r0)
(s.s f0 a0 88)
(m! cursor *math-camera*)
(l.s.field f0 cursor (pfog0))
(s.s f0 a0 96)
(l.s f0 function-base sky-radius)
(s.s f0 a0 100)
(l.s f0 function-base sky-no-kick)
(s.s f0 a0 108))
(asm-block fill-gif-state
;; Constant RGBAQ A+D record: RGBA=(128,96,96,32), Q=1.
(lui cursor #x2060)
(ori cursor cursor #x6080)
(s.w cursor a0 128)
(lui cursor #x3f80)
(s.w cursor a0 132)
(add.i cursor r0 1)
(s.w cursor a0 136)
(s.w r0 a0 140)
;; Gouraud, alpha-blended fan and strip tags, each alternating A+D color and XYZF2.
(l.d cursor function-base sky-sun-fan-tag)
(pcpyld cursor r0 cursor)
(s.d cursor a0 224)
(add.i cursor r0 78)
(s.d cursor a0 232)
(l.d cursor function-base sky-sun-strip-tag)
(pcpyld cursor r0 cursor)
(s.d cursor a0 240)
(add.i cursor r0 78)
(s.d cursor a0 248)
;; ALPHA_1 value 0x44 and its one-register A+D GIF tag.
(add.i cursor r0 68)
(s.d cursor a0 256)
(add.i cursor r0 66)
(s.d cursor a0 264)
(l.d cursor function-base sky-alpha-tag)
(pcpyld cursor r0 cursor)
(s.d cursor a0 272)
(add.i cursor r0 14)
(s.d cursor a0 280))
(l.w.field a0 buffer (base))
(sll frame-qwc frame-qwc 4)
(add frame-qwc a0 frame-qwc)
(s.w.field frame-qwc buffer (base))
;; Convert the current primary light group into the VU layout retained by sky-parms.
(m! t9 vu-lights<-light-group!)
(m! frame-qwc *sky-parms*)
(lea.field a0 frame-qwc (default-vu-lights))
(m! frame-qwc *time-of-day-context*)
(lea.field a1 frame-qwc (light-group 0))
(jalr ra t9 :delay (sll v0 ra 0))
;; Refresh the standalone 27-qword image, then reference it with an UNPACK to address 256.
(m! t9 qmem-copy<-!)
(m! frame-qwc *sky-upload-data*)
(lea.field a0 frame-qwc (data))
(m! frame-qwc *sky-parms*)
(lea.field a1 frame-qwc (upload-data data))
(add.i a2 r0 432)
(jalr ra t9 :delay (sll v0 ra 0))
(l.w.field frame-qwc buffer (base))
(lui a0 #x3000)
(ori a0 a0 27)
(m! a1 *sky-upload-data*)
(lea.field a1 a1 (data))
(sll32 a1 a1 1)
(srl a1 a1 1)
(or a0 a0 a1)
(s.d a0 frame-qwc)
(s.w r0 frame-qwc 8)
(lui a0 #x6c1b)
(ori a0 a0 256)
(s.w a0 frame-qwc 12) ;; UNPACK V4-32, 27 qwords, VU address 256
(add.i frame-qwc frame-qwc 16)
(s.w.field frame-qwc buffer (base))
(m result s7)
(l.d ra sp)
(l.d function-base sp 8)
(l.q buffer sp 16)
(jr ra :delay (add.i sp sp 32))
(nop! :count 2)))
(defun sky-upload ((dma-buf dma-buffer) (unused object))
"Upload the old sky VU1 program and frame data, then append an MSCALF packet for entry zero."
(declare (asm-func none) (allow-saved-regs))
(rlet ((buffer :reg gp)
(legacy-arg :reg s5)
(cursor :reg v1)
(result :reg v0))
(add.i sp sp -48)
(s.d ra sp)
(s.q legacy-arg sp 16)
(s.q buffer sp 32)
(m buffer a0)
(m legacy-arg a1)
(m! t9 dma-buffer-add-vu-function)
(m a0 buffer)
(m! a1 sky-vu1-block)
(add.i a2 r0 1)
(jalr ra t9 :delay (sll v0 ra 0))
(m! t9 sky-add-frame-data)
(m a0 buffer)
(m a1 legacy-arg)
(jalr ra t9 :delay (sll v0 ra 0))
(l.w.field cursor buffer (base))
(lui a0 #x1000)
(s.d a0 cursor)
(lui a0 #x1500)
(add.i a1 r0 0)
(sll32 a1 a1 16)
(srl32 a1 a1 16)
(or a0 a0 a1)
(s.w a0 cursor 8)
(lui a0 #x1000)
(s.w a0 cursor 12)
(add.i cursor cursor 16)
(s.w.field cursor buffer (base))
(m result r0)
(l.d ra sp)
(l.q buffer sp 32)
(l.q legacy-arg sp 16)
(jr ra :delay (add.i sp sp 48))
(nop! :count 3)))
(defun sky-draw ((dma-buf dma-buffer))
"Append the MSCALF packet that enters sky-vu1-block at draw-sun-0."
(declare (asm-func none))
(rlet ((buffer :reg v1)
(cursor :reg a0)
(command :reg a1)
(entry :reg a2)
(result :reg v0))
(m buffer a0)
(l.w.field cursor buffer (base))
(lui command #x1000)
(s.d command cursor)
(lui command #x1500)
(add.i entry r0 191)
(sll32 entry entry 16)
(srl32 entry entry 16)
(or command command entry)
(s.w command cursor 8)
(lui command #x1000)
(s.w command cursor 12)
(add.i cursor cursor 16)
(s.w.field cursor buffer (base))
(m result r0)
(jr ra :delay (add sp sp r0))
(nop! :count 2))))
(defun sky-add-frame-data ((dma-buf dma-buffer) (unused object))
"Append the old sky renderer's 18-quadword frame constants, refresh its VU light block, copy
the current circle, sun, and moon data into contiguous upload storage, and append the VIF
transfer for that 27-quadword image."
(let ((frame-qwc 18))
(dma-buffer-add-cnt-vif2 dma-buf
frame-qwc
(new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
(new 'static 'vif-tag :imm #x123 :cmd (vif-cmd unpack-v4-32) :num frame-qwc))
(let ((frame (the-as sky-frame-data (-> dma-buf base))))
(dotimes (i 4)
(set! (-> frame world-homo-matrix vector i quad) (-> *math-camera* camera-temp vector i quad)))
(vector-copy! (-> frame hmge-scale) (-> *math-camera* hmge-scale))
(vector-copy! (-> frame hvdf-offset) (-> *math-camera* hvdf-off))
;; The sky uses a fixed GS depth plane rather than the camera's z offset.
(set! (-> frame hvdf-offset z) 0.0)
(set! (-> frame pfog0) (-> *math-camera* pfog0))
(set! (-> frame radius) 4096000.0)
(set! (-> frame nokick) 3072.0)
(set-vector! (-> frame col-adgif vector4w) #x20606080 #x3f800000 1 0)
(set! (-> frame sun-fan-giftag dword 0) (the-as uint #x2026c00000008012))
(set! (-> frame sun-fan-giftag dword 1) (the-as uint 78))
(set! (-> frame sun-strip-giftag dword 0) (the-as uint #x2026400000008022))
(set! (-> frame sun-strip-giftag dword 1) (the-as uint 78))
(set! (-> frame sun-alpha dword 0) (the-as uint 68))
(set! (-> frame sun-alpha dword 1) (the-as uint 66))
(set! (-> frame sun-alpha-giftag dword 0) (the-as uint #x1000000000000001))
(set! (-> frame sun-alpha-giftag dword 1) (the-as uint 14)))
(&+! (-> dma-buf base) (* frame-qwc 16)))
(vu-lights<-light-group! (-> *sky-parms* default-vu-lights) (-> *time-of-day-context* light-group 0))
(qmem-copy<-! (the-as pointer (-> *sky-upload-data* circle))
(the-as pointer (-> *sky-parms* upload-data circle))
432)
(dma-buffer-add-ref-vif2 dma-buf
#x1b
(the-as int (-> *sky-upload-data* circle))
(new 'static 'vif-tag)
(new 'static 'vif-tag :imm #x100 :num #x1b :cmd (vif-cmd unpack-v4-32)))
#f)
(defun sky-upload ((dma-buf dma-buffer) (unused object))
"Upload the old sky VU1 program and its current frame and celestial data, then start the
program's setup entry point."
(dma-buffer-add-vu-function dma-buf sky-vu1-block 1)
(sky-add-frame-data dma-buf unused)
(dma-buffer-add-cnt-vif2 dma-buf
0
(new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #x0)
(new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
(none))
(defun sky-draw ((dma-buf dma-buffer))
"Append the VIF command that starts the old sky VU1 program's draw entry point."
(dma-buffer-add-cnt-vif2 dma-buf
0
(new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #xbf)
(new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
(none))
;; set the suns
(sky-set-sun-radii *sky-parms* (sky-sun-index sun) 60.0 200.0 300.0)
@@ -589,10 +428,10 @@
(sky-set-sun-colors *sky-parms*
(sky-sun-index green-sun)
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x80)
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x80)
(new 'static 'rgba :r #xc2 :g #xfe :b #x78 :a #x20)
(new 'static 'rgba :r #xc2 :g #xfe :b #x78))
(static-rgba #xc2 #xfe #x78 #x80)
(static-rgba #xc2 #xfe #x78 #x80)
(static-rgba #xc2 #xfe #x78 #x20)
(static-rgba #xc2 #xfe #x78 0))
(sky-set-orbit *sky-parms* (sky-orbit-index sun) 12.5 -15.0 0.0 9950.0 300.0 300.0)
+20 -11
View File
@@ -48,12 +48,15 @@
(defmethod art-group-get-by-name ((this level) (name string))
"Return this level's art group whose name matches name, or false."
(countdown (i (-> this art-group art-group-array length))
(if (name= (-> this art-group art-group-array i name) name) (return (-> this art-group art-group-array i))))
(if (name= (-> this art-group art-group-array i name) name)
(return (-> this art-group art-group-array i))))
(the-as art-group #f))
(defmethod bsp-name ((this level))
"Return the loaded BSP name when available, otherwise return this level's requested name."
(if (and (!= (-> this status) 'inactive) (-> this bsp) (nonzero? (-> this bsp name))) (-> this bsp name) (-> this name)))
(if (and (!= (-> this status) 'inactive)(-> this bsp) (nonzero? (-> this bsp name)))
(-> this bsp name)
(-> this name)))
;;;;;;;;;;;;;;;;;;;;;;;;;
;; BSP
@@ -67,9 +70,10 @@
(defun add-bsp-drawable ((bsp-data bsp-header) (level-data level) (unused symbol) (display-frame-data display-frame))
"Draw a level BSP for the current display frame and optionally append its strip-line debug view."
;; do the draw
;; do the draw (just adds to background queues, real drawing is deferred again.)
(draw bsp-data bsp-data display-frame-data)
(if (nonzero? *display-strip-lines*) (debug-draw bsp-data bsp-data display-frame-data))
(if (nonzero? *display-strip-lines*)
(debug-draw bsp-data bsp-data display-frame-data))
(none))
(defmethod print ((this level))
@@ -80,7 +84,7 @@
(defmethod relocate ((this bsp-header) (heap kheap) (name (pointer uint8)))
"Validate a newly linked BSP for the currently loading level, preserve the corrected title and
demo names, and connect the BSP and level to each other. Reject invalid types, versions, and
visibility lists longer than 2048 entries."
visibility lists longer than 2048 bytes."
;; we expect that we'll have a loading-level set when we link/login a bsp-header
(let ((loading-level (-> *level* loading-level)))
(if loading-level
@@ -114,7 +118,8 @@
(defmethod load-required-packages ((this level))
"Load the common package requested by a non-debug BSP when its level package list is nonempty."
(when (not (or (not (-> this bsp)) (= *kernel-boot-mode* 'debug-boot)))
(if (not (null? (-> this info packages))) (load-package "common" global)))
(if (not (null? (-> this info packages)))
(load-package "common" global)))
this)
;;;;;;;;;;;;;;
@@ -265,7 +270,9 @@
(defmethod level-status ((this level-group) (level-name symbol))
"Return the status of the loaded level matching level-name, or false."
(let ((loaded-level (level-get *level* level-name))) (if loaded-level (-> loaded-level status))))
(let ((loaded-level (level-get *level* level-name)))
(if loaded-level
(-> loaded-level status))))
(defmethod level-status-set! ((this level) (want-status symbol))
"Move this level toward want-status through the legal load, login, birth, activation,
@@ -304,7 +311,7 @@
(remove-by-param1 *background-draw-engine* (-> this bsp))
(add-connection *background-draw-engine*
*dproc*
(the (function object object object object object) add-bsp-drawable)
add-bsp-drawable
(-> this bsp)
this
#f)
@@ -1037,7 +1044,7 @@
0)
(defun update-sound-banks ()
"Reconcile the two resident sound-bank slots with the distinct banks required by active levels.
"Set up sound banks based on the currently loaded levels.
Do nothing while the loader RPC is busy or a movie is active, report more than two requirements,
and perform at most one load or unload per call."
(if (nonzero? (rpc-busy? RPC-SOUND-LOADER)) (return 0))
@@ -1122,7 +1129,8 @@
(define-extern *entity* entity)
(set! *entity* (the entity #f)))))))))
(let ((ordinary-slots-empty #f))
(if (and (= (-> *level* level0 status) 'inactive) (= (-> *level* level1 status) 'inactive)) (set! ordinary-slots-empty #t))
(if (and (= (-> *level* level0 status) 'inactive) (= (-> *level* level1 status) 'inactive))
(set! ordinary-slots-empty #t))
(if discarded-level (return 0))
(let ((need-level0 #f)
(need-level1 #f))
@@ -1367,7 +1375,8 @@
(format *stdcon*
" nick ~A cur ~S cont ~A~%~%"
(-> *load-state* vis-nick)
(let ((lev-name (and *target* (-> *target* current-level name)))) (if lev-name (symbol->string lev-name)))
(let ((lev-name (and *target* (-> *target* current-level name))))
(if lev-name (symbol->string lev-name)))
(-> *game-info* current-continue name))
; (let ((t9-16 format)
; (a0-53 *stdcon*)
@@ -0,0 +1,415 @@
;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/level/load-boundary.gc")
;; Reference-only Emotion Engine implementation of the original inline VU0 boundary renderer.
;; This file is intentionally not part of any project or DGO manifest.
;; Boundary faces use the sky clipper's closed 48-byte polygon records:
;;
;; +0x00 homogeneous position
;; +0x10 perspective texture coordinates
;; +0x20 floating-point RGBA
;;
;; The input uses three consecutive lbvtx values for each logical vertex. The first two logical
;; colors hold the forward- and backward-facing display colors; the remaining vertices reuse the
;; selected color. Triangles become records 0, 1, 2, 0 and quads become 0, 1, 2, 3, 0 in the
;; #x70003000 scratch page. draw-boundary-polygon alternates that page with #x70003800 while the
;; sky clippers apply x <= w, y <= w, x >= -w, and y >= -w.
(#unless PC_PORT
(asm-data (label boundary-fog-ceiling) (word #x453ff000)) ;; 3071.0
(defun init-boundary-regs ()
"Load the camera, homogeneous projection, fog range, and zero texture phase used by boundary
drawing. Unlike the sky path, vf25 keeps the camera's ordinary homogeneous screen offset."
(declare (asm-func none))
(rlet ((camera :reg v1 :type math-camera)
(fog-data :reg a0 :type sky-tng-data)
(function-base :reg fp)
(result :reg v0)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28)
(homogeneous-scale :reg vf14)
(inverse-homogeneous-scale :reg vf26)
(screen-offset :reg vf25)
(texture-offset :reg vf24)
(fog-range :reg vf13))
(add.i sp sp -16)
(s.d function-base sp 8)
(m function-base t9)
(m! camera *math-camera*)
(m! fog-data *sky-tng-data*)
(lea.field fog-data fog-data (fog))
;; Keep fog parameters resident in vf13 so the packet loop needs no scalar camera loads.
(l.s.field f0 camera (pfog0))
(s.s f0 fog-data)
(l.s.field f0 camera (fog-min))
(s.s f0 fog-data 4)
(l.s.field f0 camera (fog-max))
(s.s f0 fog-data 8)
(l.s f0 function-base boundary-fog-ceiling)
(s.s f0 fog-data 12)
(asm-block load-boundary-camera-state
(l.vf.field camera-x camera (camera-temp vector 0 quad))
(l.vf.field camera-y camera (camera-temp vector 1 quad))
(l.vf.field camera-z camera (camera-temp vector 2 quad))
(l.vf.field camera-w camera (camera-temp vector 3 quad))
(l.vf.field homogeneous-scale camera (hmge-scale quad))
(l.vf.field inverse-homogeneous-scale camera (inv-hmge-scale quad))
(l.vf.field screen-offset camera (hvdf-off quad))
(rlet ((sky-data :reg v1 :type sky-tng-data))
;; Load the packed fog limits after the last camera field access.
(m! sky-data *sky-tng-data*)
(l.vf.field fog-range sky-data (fog)))
(mul.vf camera-x camera-x homogeneous-scale)
(mul.vf camera-y camera-y homogeneous-scale)
(mul.vf camera-z camera-z homogeneous-scale)
(mul.vf camera-w camera-w homogeneous-scale)
(vmove.xyzw texture-offset vf0))
;; Mirror the cleared texture phase in the EE register file.
(rlet ((texture-offset-bits :reg v1))
(m texture-offset-bits texture-offset))
(m result r0)
(l.d function-base sp 8)
(jr ra :delay (add.i sp sp 16))
(nop! :count 2)))
(defun draw-boundary-polygon ()
"Clip a closed boundary polygon against the four side planes and append ST/RGBAQ/XYZF records.
The private calling convention carries the vertex count in t0, DMA buffer in a1, and scratch
pages in t4 and t5. Return #f when clipping removes every vertex."
(declare (asm-func none))
(rlet ((dma-buf :reg a1 :type dma-buffer)
(input-page :reg a2)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(component :reg t2)
(clip-function :reg t9)
(position :reg vf1)
(stq :reg vf2)
(color :reg vf3)
(gif-tag :reg vf27)
(inverse-homogeneous-scale :reg vf26)
(screen-offset :reg vf25)
(texture-offset :reg vf24)
(fog-range :reg vf13)
(result :reg v0))
(nop!)
(add.i sp sp -8)
(nop!)
(s.d ra sp)
;; Each pass streams into the other scratch page. component points at x for the first and
;; third passes and y for the second and fourth.
(asm-block clip-boundary-side-planes
(m! clip-function clip-polygon-against-positive-hyperplane)
(m input-page page-a)
(m output page-b)
(jalr ra clip-function :delay (add component input-page r0))
(b.z vertex-count boundary-polygon-clipped-away :delay (nop!))
(m input-page page-b)
(m output page-a)
(jalr ra clip-function :delay (add.i component input-page 4))
(b.z vertex-count boundary-polygon-clipped-away :delay (m! clip-function clip-polygon-against-negative-hyperplane))
(m input-page page-a)
(m output page-b)
(jalr ra clip-function :delay (add component input-page r0))
(b.z vertex-count boundary-polygon-clipped-away :delay (nop!))
(m input-page page-b)
(m output page-a)
(jalr ra clip-function :delay (add.i component input-page 4))
(b.z vertex-count boundary-polygon-clipped-away :delay (l.w.field output dma-buf (base))))
;; vf27 supplies the fixed GIF tag. The clipped count replaces its first word before emitting
;; one three-qword GS vertex for every remaining polygon point.
(m input-page page-a)
(nop!)
(s.vf gif-tag output)
(add.i output output 16)
(s.w vertex-count output -16)
(nop!)
(label emit-boundary-vertices)
(asm-block project-boundary-vertex
(l.vf position input-page)
(nop!)
(l.vf stq input-page 16)
(nop!)
(l.vf color input-page 32)
(div.w.w Q vf0 position)
(mul.vf position position inverse-homogeneous-scale)
(nop!)
(ftoi.vf color color)
(nop!)
(add.vf stq stq texture-offset)
(nop!)
(waitq)
(nop!)
(mulq.vf.xyz position position Q)
(s.vf color output 16)
(mulq.vf stq stq Q)
(add.i input-page input-page 48)
(add.vf position position screen-offset)
(add.i output output 48)
;; Boundary geometry keeps projected depth instead of using the sky layer value.
;; Clamp z to the near side of the GS range, and fog between fog-min and fog-max.
(max.z.vf.z position position vf0)
(nop!)
(min.z.vf.w position position fog-range)
(nop!)
(max.y.vf.w position position fog-range)
(nop!)
(s.vf stq output -48)
(add.i vertex-count vertex-count -1)
(ftoi.vf position position :fixed 4)
(nop!)
(b.nz vertex-count emit-boundary-vertices :delay (s.vf position output -16)))
(s.w.field output dma-buf (base))
(nop!)
(l.d ra sp)
(add.i result s7 8)
(jr ra :delay (add.i sp sp 8))
(label boundary-polygon-clipped-away)
(l.d ra sp)
(m result s7)
(jr ra :delay (add.i sp sp 8))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-boundary-quad ((vertices lbvtx) (dma-buf dma-buffer))
"Transform four boundary vertices into a closed scratch polygon, select the forward or backward
display color from its camera-facing sign, and tail-call draw-boundary-polygon."
(declare (asm-func none))
(rlet ((vertex-data :reg a0)
(input-copy :reg v1)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(draw-function :reg t9)
(facing-bits :reg v0)
(point-0 :reg vf1)
(tex-0 :reg vf2)
(forward-color :reg vf3)
(point-1 :reg vf4)
(tex-1 :reg vf5)
(backward-color :reg vf6)
(point-2 :reg vf7)
(tex-2 :reg vf8)
(point-3-and-facing :reg vf10)
(tex-3 :reg vf11)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28)
(homogeneous-scale :reg vf14))
(m input-copy vertex-data)
(rlet ((camera :reg v1 :type math-camera))
(m! camera *math-camera*)
;; Refresh the homogeneous scale with the rest of the boundary camera state.
(l.vf.field homogeneous-scale camera (hmge-scale quad)))
(lui page-a #x7000)
(ori page-a page-a #x3000)
(lui page-b #x7000)
(ori page-b page-b #x3800)
(m output page-a)
;; Each logical input record is position, STQ, and color. Only the first two colors are
;; loaded: forward-color is installed provisionally, then replaced when the face points the
;; other way.
(asm-block transform-boundary-quad
(nop!)
(l.vf point-0 vertex-data)
(add.i vertex-count r0 4)
(l.vf tex-0 vertex-data 16)
(nop!)
(l.vf forward-color vertex-data 32)
(mula.x.vf camera-x point-0)
(l.vf point-1 vertex-data 48)
(madda.y.vf camera-y point-0)
(l.vf tex-1 vertex-data 64)
(madda.z.vf camera-z point-0)
(l.vf backward-color vertex-data 80)
(madd.w.vf point-0 camera-w point-0)
(l.vf point-2 vertex-data 96)
(nop!)
(l.vf tex-2 vertex-data 112)
(mula.x.vf camera-x point-1)
(nop!)
(madda.y.vf camera-y point-1)
(l.vf point-3-and-facing vertex-data 144)
(madda.z.vf camera-z point-1)
(l.vf tex-3 vertex-data 160)
(madd.w.vf point-1 camera-w point-1)
(nop! :count 2)
(s.vf tex-0 output 16)
(mula.x.vf camera-x point-2)
(s.vf forward-color output 32)
(madda.y.vf camera-y point-2)
(s.vf tex-1 output 64)
(madda.z.vf camera-z point-2)
(s.vf forward-color output 80)
(madd.w.vf point-2 camera-w point-2)
(s.vf tex-2 output 112)
(nop!)
(s.vf forward-color output 128)
(mula.x.vf camera-x point-3-and-facing)
(s.vf tex-3 output 160)
(madda.y.vf camera-y point-3-and-facing)
(s.vf forward-color output 176)
(madda.z.vf camera-z point-3-and-facing)
(s.vf tex-0 output 208)
(madd.w.vf point-3-and-facing camera-w point-3-and-facing)
(s.vf forward-color output 224)
(nop!)
(s.vf point-0 output)
(nop!)
(s.vf point-0 output 192)
(nop!)
(s.vf point-1 output 48)
(nop!)
(s.vf point-2 output 96)
(nop!)
(s.vf point-3-and-facing output 144))
;; The scalar triple product dot(cross(p1-p0, p2-p0), p0) determines which side faces the
;; camera origin after transformation. The sum is placed in vf10.y; moving the low 64 bits
;; into v0 makes that lane's sign available to the integer branch.
(asm-block choose-boundary-quad-color
(m! draw-function draw-boundary-polygon)
(sub.vf point-1 point-1 point-0)
(nop!)
(sub.vf point-2 point-2 point-0)
(nop!)
(outer.product.a.vf acc point-1 point-2)
(nop!)
(outer.product.b.vf point-3-and-facing point-2 point-1 acc)
(nop!)
(mul.vf point-3-and-facing point-3-and-facing point-0)
(nop!)
(add.x.vf.y point-3-and-facing point-3-and-facing point-3-and-facing)
(nop!)
(add.z.vf.y point-3-and-facing point-3-and-facing point-3-and-facing)
(nop!)
(m facing-bits point-3-and-facing)
(nop!)
(b.ge facing-bits r0 use-backward-quad-color :delay (nop!))
(jr draw-function :delay (nop!)))
(label use-backward-quad-color)
;; Recolor only the four distinct records. The duplicate closure retains the provisional
;; color, which also participates in interpolation if clipping crosses the final edge.
(s.vf backward-color output 32)
(nop!)
(s.vf backward-color output 80)
(nop!)
(s.vf backward-color output 128)
(nop!)
(s.vf backward-color output 176)
(nop!)
(jr draw-function :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-boundary-tri ((vertices lbvtx) (dma-buf dma-buffer))
"Transform three boundary vertices into a closed scratch polygon, select the forward or backward
display color from its camera-facing sign, and tail-call draw-boundary-polygon."
(declare (asm-func none))
(rlet ((vertex-data :reg a0)
(input-copy :reg v1)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(draw-function :reg t9)
(facing-bits :reg v0)
(point-0 :reg vf1)
(tex-0 :reg vf2)
(forward-color :reg vf3)
(point-1 :reg vf4)
(tex-1 :reg vf5)
(backward-color :reg vf6)
(point-2 :reg vf7)
(tex-2 :reg vf8)
(facing :reg vf10)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28))
(m input-copy vertex-data)
(lui page-a #x7000)
(ori page-a page-a #x3000)
(lui page-b #x7000)
(ori page-b page-b #x3800)
(m output page-a)
(asm-block transform-boundary-triangle
(nop!)
(l.vf point-0 vertex-data)
(add.i vertex-count r0 3)
(l.vf tex-0 vertex-data 16)
(nop!)
(l.vf forward-color vertex-data 32)
(mula.x.vf camera-x point-0)
(l.vf point-1 vertex-data 48)
(madda.y.vf camera-y point-0)
(l.vf tex-1 vertex-data 64)
(madda.z.vf camera-z point-0)
(l.vf backward-color vertex-data 80)
(madd.w.vf point-0 camera-w point-0)
(l.vf point-2 vertex-data 96)
(nop!)
(l.vf tex-2 vertex-data 112)
(mula.x.vf camera-x point-1)
(nop!)
(madda.y.vf camera-y point-1)
(s.vf tex-0 output 16)
(madda.z.vf camera-z point-1)
(s.vf forward-color output 32)
(madd.w.vf point-1 camera-w point-1)
(s.vf tex-1 output 64)
(nop!)
(s.vf forward-color output 80)
(mula.x.vf camera-x point-2)
(s.vf tex-2 output 112)
(madda.y.vf camera-y point-2)
(s.vf forward-color output 128)
(madda.z.vf camera-z point-2)
(s.vf tex-0 output 160)
(madd.w.vf point-2 camera-w point-2)
(s.vf forward-color output 176)
(nop!)
(s.vf point-0 output)
(nop!)
(s.vf point-0 output 144)
(nop!)
(s.vf point-1 output 48)
(nop!)
(s.vf point-2 output 96))
(asm-block choose-boundary-triangle-color
(m! draw-function draw-boundary-polygon)
(sub.vf point-1 point-1 point-0)
(nop!)
(sub.vf point-2 point-2 point-0)
(nop!)
(outer.product.a.vf acc point-1 point-2)
(nop!)
(outer.product.b.vf facing point-2 point-1 acc)
(nop!)
(mul.vf facing facing point-0)
(nop!)
(add.x.vf.y facing facing facing)
(nop!)
(add.z.vf.y facing facing facing)
(nop!)
(m facing-bits facing)
(nop!)
(b.ge facing-bits r0 use-backward-triangle-color :delay (nop!))
(jr draw-function :delay (nop!)))
(label use-backward-triangle-color)
;; The fourth record repeats point zero, so it receives the selected color as well.
(s.vf backward-color output 32)
(nop!)
(s.vf backward-color output 80)
(nop!)
(s.vf backward-color output 128)
(nop!)
(s.vf backward-color output 176)
(nop!)
(jr draw-function :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2))))
@@ -16,7 +16,7 @@
;; Boundary coordinates and the byte-sized links used while triangulating a closed polygon.
;; v0/v1/v2 are previous/next/active in *triangulation-buffer*, then triangle vertex indices in
;; load-boundary.data[0..tri-cnt). ix remembers the original vertex ordinal.
;; load-boundary.data[0..tri-cnt). ix is the original vertex index.
(deftype lbvtx (structure)
((x float)
(y float)
@@ -33,16 +33,14 @@
:type uint8
(invalid 0) ;; No command.
(load 1) ;; Replace the desired pair of loaded levels.
(cmd2 2) ;; Reserved; no executor or boundary data uses it.
(cmd2 2) ;; Unused
(display 3) ;; Set a loaded level's display mode.
(vis 4) ;; Select the active visibility nickname.
(force-vis 5) ;; Bypass BSP visibility outside this level's inside boxes.
(checkpt 6) ;; Select a continue point.
)
;; Command to execute when crossing. bparm is reserved padding; parm contains the two GOAL object
;; parameters. The named overlays describe the meanings used by each command without changing the
;; original generic lev0/lev1 vocabulary.
;; Command to execute when crossing.
(deftype load-boundary-crossing-command (structure)
((cmd load-boundary-cmd)
(bparm uint8 3)
+142 -508
View File
@@ -36,9 +36,9 @@
;; The editor uses the same system as sky for drawing large polygons.
;; The PC renderer keeps the persistent VU0 state in the MIPS2C context.
(#when PC_PORT
(def-mips2c init-boundary-regs (function none)))
;; Boundary rendering shares the sky polygon renderer's clipping logic.
;; Projection differs in two ways: it uses the camera's ordinary
;; screen offset and preserves projected depth instead of replacing it with a sky layer depth.
(defun-debug add-boundary-shader ((shader-texture texture-id) (dma-buf dma-buffer))
"Append the fixed five-register ADGIF shader used by
@@ -66,418 +66,119 @@
(&+! (-> dma-buf base) 80)
(none))
;; The polygon conversion and both entry points use that same context on PC.
(#when PC_PORT
(def-mips2c draw-boundary-polygon function)
(def-mips2c render-boundary-quad (function lbvtx dma-buffer none))
(def-mips2c render-boundary-tri (function lbvtx dma-buffer none)))
(defun init-boundary-regs ()
"Snapshot the camera, projection, fog, and roof giftag used by subsequent boundary polygon calls."
(let ((state *sky-polygon-renderer*))
(dotimes (i 4)
(sky-vector4*! (-> state transform vector i) (-> *math-camera* camera-temp vector i) (-> *math-camera* hmge-scale)))
(vector-copy! (-> state inv-hmge-scale) (-> *math-camera* inv-hmge-scale))
(vector-copy! (-> state screen-offset) (-> *math-camera* hvdf-off))
(set-vector! (-> state fog-clamp) (-> *math-camera* pfog0) (-> *math-camera* fog-min) (-> *math-camera* fog-max) 3071.0)
(vector-copy! (-> *sky-tng-data* fog) (-> state fog-clamp))
(set-vector! (-> state texture-offset) 0.0 0.0 0.0 0.0)
(set-sky-giftag (-> *sky-tng-data* giftag-roof)))
(none))
;; Boundary faces use the sky clipper's closed 48-byte polygon records:
;;
;; +0x00 homogeneous position
;; +0x10 perspective texture coordinates
;; +0x20 floating-point RGBA
;;
;; The input uses three consecutive lbvtx values for each logical vertex. The first two logical
;; colors hold the forward- and backward-facing display colors; the remaining vertices reuse the
;; selected color. Triangles become records 0, 1, 2, 0 and quads become 0, 1, 2, 3, 0 in the
;; #x70003000 scratch page. draw-boundary-polygon alternates that page with #x70003800 while the
;; sky clippers apply x <= w, y <= w, x >= -w, and y >= -w.
(#unless PC_PORT
(asm-data (label boundary-fog-ceiling) (word #x453ff000)) ;; 3071.0
(defun init-boundary-regs ()
"Load the camera, homogeneous projection, fog range, and zero texture phase used by boundary
drawing. Unlike the sky path, vf25 keeps the camera's ordinary homogeneous screen offset."
(declare (asm-func none))
(rlet ((camera :reg v1 :type math-camera)
(fog-data :reg a0 :type sky-tng-data)
(function-base :reg fp)
(result :reg v0)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28)
(homogeneous-scale :reg vf14)
(inverse-homogeneous-scale :reg vf26)
(screen-offset :reg vf25)
(texture-offset :reg vf24)
(fog-range :reg vf13))
(add.i sp sp -16)
(s.d function-base sp 8)
(m function-base t9)
(m! camera *math-camera*)
(m! fog-data *sky-tng-data*)
(lea.field fog-data fog-data (fog))
;; Keep fog parameters resident in vf13 so the packet loop needs no scalar camera loads.
(l.s.field f0 camera (pfog0))
(s.s f0 fog-data)
(l.s.field f0 camera (fog-min))
(s.s f0 fog-data 4)
(l.s.field f0 camera (fog-max))
(s.s f0 fog-data 8)
(l.s f0 function-base boundary-fog-ceiling)
(s.s f0 fog-data 12)
(asm-block load-boundary-camera-state
(l.vf.field camera-x camera (camera-temp vector 0 quad))
(l.vf.field camera-y camera (camera-temp vector 1 quad))
(l.vf.field camera-z camera (camera-temp vector 2 quad))
(l.vf.field camera-w camera (camera-temp vector 3 quad))
(l.vf.field homogeneous-scale camera (hmge-scale quad))
(l.vf.field inverse-homogeneous-scale camera (inv-hmge-scale quad))
(l.vf.field screen-offset camera (hvdf-off quad))
(rlet ((sky-data :reg v1 :type sky-tng-data))
;; Load the packed fog limits after the last camera field access.
(m! sky-data *sky-tng-data*)
(l.vf.field fog-range sky-data (fog)))
(mul.vf camera-x camera-x homogeneous-scale)
(mul.vf camera-y camera-y homogeneous-scale)
(mul.vf camera-z camera-z homogeneous-scale)
(mul.vf camera-w camera-w homogeneous-scale)
(vmove.xyzw texture-offset vf0))
;; Mirror the cleared texture phase in the EE register file.
(rlet ((texture-offset-bits :reg v1)) (m texture-offset-bits texture-offset))
(m result r0)
(l.d function-base sp 8)
(jr ra :delay (add.i sp sp 16))
(nop! :count 2)))
(defun draw-boundary-polygon ()
"Clip a closed boundary polygon against the four side planes and append ST/RGBAQ/XYZF records.
The private calling convention carries the vertex count in t0, DMA buffer in a1, and scratch
pages in t4 and t5. Return #f when clipping removes every vertex."
(declare (asm-func none))
(rlet ((dma-buf :reg a1 :type dma-buffer)
(input-page :reg a2)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(component :reg t2)
(clip-function :reg t9)
(position :reg vf1)
(stq :reg vf2)
(color :reg vf3)
(gif-tag :reg vf27)
(inverse-homogeneous-scale :reg vf26)
(screen-offset :reg vf25)
(texture-offset :reg vf24)
(fog-range :reg vf13)
(result :reg v0))
(nop!)
(add.i sp sp -8)
(nop!)
(s.d ra sp)
;; Each pass streams into the other scratch page. component points at x for the first and
;; third passes and y for the second and fourth.
(asm-block clip-boundary-side-planes
(m! clip-function clip-polygon-against-positive-hyperplane)
(m input-page page-a)
(m output page-b)
(jalr ra clip-function :delay (add component input-page r0))
(b.z vertex-count boundary-polygon-clipped-away :delay (nop!))
(m input-page page-b)
(m output page-a)
(jalr ra clip-function :delay (add.i component input-page 4))
(b.z vertex-count boundary-polygon-clipped-away :delay (m! clip-function clip-polygon-against-negative-hyperplane))
(m input-page page-a)
(m output page-b)
(jalr ra clip-function :delay (add component input-page r0))
(b.z vertex-count boundary-polygon-clipped-away :delay (nop!))
(m input-page page-b)
(m output page-a)
(jalr ra clip-function :delay (add.i component input-page 4))
(b.z vertex-count boundary-polygon-clipped-away :delay (l.w.field output dma-buf (base))))
;; vf27 supplies the fixed GIF tag. The clipped count replaces its first word before emitting
;; one three-qword GS vertex for every remaining polygon point.
(m input-page page-a)
(nop!)
(s.vf gif-tag output)
(add.i output output 16)
(s.w vertex-count output -16)
(nop!)
(label emit-boundary-vertices)
(asm-block project-boundary-vertex
(l.vf position input-page)
(nop!)
(l.vf stq input-page 16)
(nop!)
(l.vf color input-page 32)
(div.w.w Q vf0 position)
(mul.vf position position inverse-homogeneous-scale)
(nop!)
(ftoi.vf color color)
(nop!)
(add.vf stq stq texture-offset)
(nop!)
(waitq)
(nop!)
(mulq.vf.xyz position position Q)
(s.vf color output 16)
(mulq.vf stq stq Q)
(add.i input-page input-page 48)
(add.vf position position screen-offset)
(add.i output output 48)
;; Boundary geometry keeps projected depth instead of using the sky layer value.
;; Clamp z to the near side of the GS range, and fog between fog-min and fog-max.
(max.z.vf.z position position vf0)
(nop!)
(min.z.vf.w position position fog-range)
(nop!)
(max.y.vf.w position position fog-range)
(nop!)
(s.vf stq output -48)
(add.i vertex-count vertex-count -1)
(ftoi.vf position position :fixed 4)
(nop!)
(b.nz vertex-count emit-boundary-vertices :delay (s.vf position output -16)))
(s.w.field output dma-buf (base))
(nop!)
(l.d ra sp)
(add.i result s7 8)
(jr ra :delay (add.i sp sp 8))
(label boundary-polygon-clipped-away)
(l.d ra sp)
(m result s7)
(jr ra :delay (add.i sp sp 8))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-boundary-quad ((vertices lbvtx) (dma-buf dma-buffer))
"Transform four boundary vertices into a closed scratch polygon, select the forward or backward
display color from its camera-facing sign, and tail-call draw-boundary-polygon."
(declare (asm-func none))
(rlet ((vertex-data :reg a0)
(input-copy :reg v1)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(draw-function :reg t9)
(facing-bits :reg v0)
(point-0 :reg vf1)
(tex-0 :reg vf2)
(forward-color :reg vf3)
(point-1 :reg vf4)
(tex-1 :reg vf5)
(backward-color :reg vf6)
(point-2 :reg vf7)
(tex-2 :reg vf8)
(point-3-and-facing :reg vf10)
(tex-3 :reg vf11)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28)
(homogeneous-scale :reg vf14))
(m input-copy vertex-data)
(rlet ((camera :reg v1 :type math-camera))
(m! camera *math-camera*)
;; Refresh the homogeneous scale with the rest of the boundary camera state.
(l.vf.field homogeneous-scale camera (hmge-scale quad)))
(lui page-a #x7000)
(ori page-a page-a #x3000)
(lui page-b #x7000)
(ori page-b page-b #x3800)
(m output page-a)
;; Each logical input record is position, STQ, and color. Only the first two colors are
;; loaded: forward-color is installed provisionally, then replaced when the face points the
;; other way.
(asm-block transform-boundary-quad
(nop!)
(l.vf point-0 vertex-data)
(add.i vertex-count r0 4)
(l.vf tex-0 vertex-data 16)
(nop!)
(l.vf forward-color vertex-data 32)
(mula.x.vf camera-x point-0)
(l.vf point-1 vertex-data 48)
(madda.y.vf camera-y point-0)
(l.vf tex-1 vertex-data 64)
(madda.z.vf camera-z point-0)
(l.vf backward-color vertex-data 80)
(madd.w.vf point-0 camera-w point-0)
(l.vf point-2 vertex-data 96)
(nop!)
(l.vf tex-2 vertex-data 112)
(mula.x.vf camera-x point-1)
(nop!)
(madda.y.vf camera-y point-1)
(l.vf point-3-and-facing vertex-data 144)
(madda.z.vf camera-z point-1)
(l.vf tex-3 vertex-data 160)
(madd.w.vf point-1 camera-w point-1)
(nop! :count 2)
(s.vf tex-0 output 16)
(mula.x.vf camera-x point-2)
(s.vf forward-color output 32)
(madda.y.vf camera-y point-2)
(s.vf tex-1 output 64)
(madda.z.vf camera-z point-2)
(s.vf forward-color output 80)
(madd.w.vf point-2 camera-w point-2)
(s.vf tex-2 output 112)
(nop!)
(s.vf forward-color output 128)
(mula.x.vf camera-x point-3-and-facing)
(s.vf tex-3 output 160)
(madda.y.vf camera-y point-3-and-facing)
(s.vf forward-color output 176)
(madda.z.vf camera-z point-3-and-facing)
(s.vf tex-0 output 208)
(madd.w.vf point-3-and-facing camera-w point-3-and-facing)
(s.vf forward-color output 224)
(nop!)
(s.vf point-0 output)
(nop!)
(s.vf point-0 output 192)
(nop!)
(s.vf point-1 output 48)
(nop!)
(s.vf point-2 output 96)
(nop!)
(s.vf point-3-and-facing output 144))
;; The scalar triple product dot(cross(p1-p0, p2-p0), p0) determines which side faces the
;; camera origin after transformation. The sum is placed in vf10.y; moving the low 64 bits
;; into v0 makes that lane's sign available to the integer branch.
(asm-block choose-boundary-quad-color
(m! draw-function draw-boundary-polygon)
(sub.vf point-1 point-1 point-0)
(nop!)
(sub.vf point-2 point-2 point-0)
(nop!)
(outer.product.a.vf acc point-1 point-2)
(nop!)
(outer.product.b.vf point-3-and-facing point-2 point-1 acc)
(nop!)
(mul.vf point-3-and-facing point-3-and-facing point-0)
(nop!)
(add.x.vf.y point-3-and-facing point-3-and-facing point-3-and-facing)
(nop!)
(add.z.vf.y point-3-and-facing point-3-and-facing point-3-and-facing)
(nop!)
(m facing-bits point-3-and-facing)
(nop!)
(b.ge facing-bits r0 use-backward-quad-color :delay (nop!))
(jr draw-function :delay (nop!)))
(label use-backward-quad-color)
;; Recolor only the four distinct records. The duplicate closure retains the provisional
;; color, which also participates in interpolation if clipping crosses the final edge.
(s.vf backward-color output 32)
(nop!)
(s.vf backward-color output 80)
(nop!)
(s.vf backward-color output 128)
(nop!)
(s.vf backward-color output 176)
(nop!)
(jr draw-function :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2)))
(defun render-boundary-tri ((vertices lbvtx) (dma-buf dma-buffer))
"Transform three boundary vertices into a closed scratch polygon, select the forward or backward
display color from its camera-facing sign, and tail-call draw-boundary-polygon."
(declare (asm-func none))
(rlet ((vertex-data :reg a0)
(input-copy :reg v1)
(output :reg a3)
(page-a :reg t4)
(page-b :reg t5)
(vertex-count :reg t0)
(draw-function :reg t9)
(facing-bits :reg v0)
(point-0 :reg vf1)
(tex-0 :reg vf2)
(forward-color :reg vf3)
(point-1 :reg vf4)
(tex-1 :reg vf5)
(backward-color :reg vf6)
(point-2 :reg vf7)
(tex-2 :reg vf8)
(facing :reg vf10)
(camera-x :reg vf31)
(camera-y :reg vf30)
(camera-z :reg vf29)
(camera-w :reg vf28))
(m input-copy vertex-data)
(lui page-a #x7000)
(ori page-a page-a #x3000)
(lui page-b #x7000)
(ori page-b page-b #x3800)
(m output page-a)
(asm-block transform-boundary-triangle
(nop!)
(l.vf point-0 vertex-data)
(add.i vertex-count r0 3)
(l.vf tex-0 vertex-data 16)
(nop!)
(l.vf forward-color vertex-data 32)
(mula.x.vf camera-x point-0)
(l.vf point-1 vertex-data 48)
(madda.y.vf camera-y point-0)
(l.vf tex-1 vertex-data 64)
(madda.z.vf camera-z point-0)
(l.vf backward-color vertex-data 80)
(madd.w.vf point-0 camera-w point-0)
(l.vf point-2 vertex-data 96)
(nop!)
(l.vf tex-2 vertex-data 112)
(mula.x.vf camera-x point-1)
(nop!)
(madda.y.vf camera-y point-1)
(s.vf tex-0 output 16)
(madda.z.vf camera-z point-1)
(s.vf forward-color output 32)
(madd.w.vf point-1 camera-w point-1)
(s.vf tex-1 output 64)
(nop!)
(s.vf forward-color output 80)
(mula.x.vf camera-x point-2)
(s.vf tex-2 output 112)
(madda.y.vf camera-y point-2)
(s.vf forward-color output 128)
(madda.z.vf camera-z point-2)
(s.vf tex-0 output 160)
(madd.w.vf point-2 camera-w point-2)
(s.vf forward-color output 176)
(nop!)
(s.vf point-0 output)
(nop!)
(s.vf point-0 output 144)
(nop!)
(s.vf point-1 output 48)
(nop!)
(s.vf point-2 output 96))
(asm-block choose-boundary-triangle-color
(m! draw-function draw-boundary-polygon)
(sub.vf point-1 point-1 point-0)
(nop!)
(sub.vf point-2 point-2 point-0)
(nop!)
(outer.product.a.vf acc point-1 point-2)
(nop!)
(outer.product.b.vf facing point-2 point-1 acc)
(nop!)
(mul.vf facing facing point-0)
(nop!)
(add.x.vf.y facing facing facing)
(nop!)
(add.z.vf.y facing facing facing)
(nop!)
(m facing-bits facing)
(nop!)
(b.ge facing-bits r0 use-backward-triangle-color :delay (nop!))
(jr draw-function :delay (nop!)))
(label use-backward-triangle-color)
;; The fourth record repeats point zero, so it receives the selected color as well.
(s.vf backward-color output 32)
(nop!)
(s.vf backward-color output 80)
(nop!)
(s.vf backward-color output 128)
(nop!)
(s.vf backward-color output 176)
(nop!)
(jr draw-function :delay (nop!))
(jr ra :delay (add sp sp r0))
(nop! :count 2))))
(defun boundary-emit-polygon! ((vertices (inline-array sky-vertex)) (vertex-count int) (dma-buf dma-buffer))
"Append one boundary GIF tag and its perspective-correct ST, RGBAQ, and 12.4 XYZF records."
(let* ((state *sky-polygon-renderer*)
(packet-start (-> dma-buf base))
(giftag (the-as gs-gif-tag packet-start))
(output (the-as (pointer uint128) (&+ packet-start 16))))
(set! (-> giftag qword) (-> state giftag qword))
(set! (-> (the-as (pointer uint32) packet-start) 0) vertex-count)
(dotimes (i vertex-count)
(let* ((vertex (-> vertices i))
(q (/ 1.0 (-> vertex pos w)))
(st (new 'stack-no-clear 'vector))
(color-int (new 'stack-no-clear 'vector))
(projected (new 'stack-no-clear 'vector))
(projected-int (new 'stack-no-clear 'vector)))
(vector-copy! st (-> vertex stq))
(+! (-> st x) (-> state texture-offset x))
(+! (-> st y) (-> state texture-offset y))
(sky-vector4-float*! st st q)
(vector-cvt.w.s! color-int (-> vertex col))
(sky-vector4*! projected (-> vertex pos) (-> state inv-hmge-scale))
(*! (-> projected x) q)
(*! (-> projected y) q)
(*! (-> projected z) q)
(+! (-> projected x) (-> state screen-offset x))
(+! (-> projected y) (-> state screen-offset y))
(+! (-> projected z) (-> state screen-offset z))
(+! (-> projected w) (-> state screen-offset w))
(set! (-> projected z) (max (-> projected z) 0.0))
(set! (-> projected w) (max (-> state fog-clamp y) (min (-> projected w) (-> state fog-clamp z))))
(sky-vector4-float*! projected projected 16.0)
(vector-cvt.w.s! projected-int projected)
(set! (-> output (* i 3)) (-> st quad))
(set! (-> output (+ (* i 3) 1)) (-> color-int quad))
(set! (-> output (+ (* i 3) 2)) (-> projected-int quad))))
(set! (-> dma-buf base) (&+ packet-start (* (+ 1 (* vertex-count 3)) 16))))
(none))
(defun draw-boundary-polygon ()
"Clip the current boundary polygon against the four homogeneous side planes, then emit it."
(let* ((state *sky-polygon-renderer*)
(vertices-a (-> state vertices-a))
(vertices-b (-> state vertices-b))
(vertex-count (-> state vertex-count)))
(when (nonzero? vertex-count)
(set! vertex-count (sky-clip-polygon! vertices-a vertices-b vertex-count 0 #t)))
(when (nonzero? vertex-count)
(set! vertex-count (sky-clip-polygon! vertices-b vertices-a vertex-count 1 #t)))
(when (nonzero? vertex-count)
(set! vertex-count (sky-clip-polygon! vertices-a vertices-b vertex-count 0 #f)))
(when (nonzero? vertex-count)
(set! vertex-count (sky-clip-polygon! vertices-b vertices-a vertex-count 1 #f)))
(when (nonzero? vertex-count)
(boundary-emit-polygon! vertices-a vertex-count (-> state dma-buf))))
(none))
(defun boundary-back-facing? ((vertices (inline-array sky-vertex)))
"Test the transformed triangle's scalar triple product, matching the original VU facing branch."
(let* ((p0 (-> vertices 0 pos))
(p1 (-> vertices 1 pos))
(p2 (-> vertices 2 pos))
(edge-1-x (- (-> p1 x) (-> p0 x)))
(edge-1-y (- (-> p1 y) (-> p0 y)))
(edge-1-z (- (-> p1 z) (-> p0 z)))
(edge-2-x (- (-> p2 x) (-> p0 x)))
(edge-2-y (- (-> p2 y) (-> p0 y)))
(edge-2-z (- (-> p2 z) (-> p0 z)))
(normal-x (- (* edge-1-y edge-2-z) (* edge-1-z edge-2-y)))
(normal-y (- (* edge-1-z edge-2-x) (* edge-1-x edge-2-z)))
(normal-z (- (* edge-1-x edge-2-y) (* edge-1-y edge-2-x))))
(>= (+ (* normal-x (-> p0 x)) (* normal-y (-> p0 y)) (* normal-z (-> p0 z))) 0.0)))
(defun render-boundary-polygon ((vertices lbvtx) (dma-buf dma-buffer) (vertex-count int))
"Transform a boundary polygon, select its forward or backward display color, clip it, and emit it."
(let* ((state *sky-polygon-renderer*)
(input (the-as (inline-array sky-vertex) vertices))
(output (-> state vertices-a)))
(set! (-> state dma-buf) dma-buf)
(set! (-> state vertex-count) vertex-count)
(dotimes (i vertex-count)
(let ((dst (-> output i))
(src (-> input i)))
;; Unlike sky geometry, boundary polygons retain transformed z for depth and facing.
(vector-matrix*! (-> dst pos) (-> src pos) (-> state transform))
(vector-copy! (-> dst stq) (-> src stq))))
(let ((color (if (boundary-back-facing? output) (-> input 1 col) (-> input 0 col))))
(dotimes (i vertex-count)
(vector-copy! (-> output i col) color)))
(draw-boundary-polygon))
(none))
(defun render-boundary-quad ((vertices lbvtx) (dma-buf dma-buffer))
"Transform and render a four-vertex boundary face."
(render-boundary-polygon vertices dma-buf 4)
(none))
(defun render-boundary-tri ((vertices lbvtx) (dma-buf dma-buffer))
"Transform and render a three-vertex boundary face."
(render-boundary-polygon vertices dma-buf 3)
(none))
;; the polygon curently rendering.
(define *boundary-polygon*
@@ -502,8 +203,7 @@
"Build and draw the vertical quad joining two boundary vertices
between bot-plane and top-plane. uv-phase? selects the alternate UV orientation used to flash the
selected boundary."
(rlet ((vf27 :class vf))
(let ((start (-> boundary data start-index)))
(let ((start (-> boundary data start-index)))
(let ((end (-> boundary data end-index)))
(let ((polygon-pos (-> *boundary-polygon* 0)))
(set! (-> polygon-pos x) (-> start x))
@@ -569,19 +269,14 @@
(set! (-> polygon-uv z) 1.0)
(set! (-> polygon-uv v w) 1.0))))
(init-boundary-regs)
(#unless PC_PORT
(.lvf vf27 (&-> *sky-tng-data* giftag-roof qword)))
(#when PC_PORT
(set-sky-vf27 (&-> *sky-tng-data* giftag-roof qword)))
(render-boundary-quad (-> *boundary-polygon* 0) dma-buf)
0
(none)))
(none))
(defun-debug draw-boundary-cap ((boundary load-boundary) (plane-y float) (dma-buf dma-buffer) (uv-phase? symbol))
"Draw every cached triangle of a closed boundary at plane-y.
uv-phase? selects the alternate UV orientation used to flash the selected boundary."
(rlet ((vf27 :class vf))
(dotimes (i (-> boundary tri-cnt))
(dotimes (i (-> boundary tri-cnt))
(let ((v0 (-> boundary data (-> boundary data i v0)))
(v1 (-> boundary data (-> boundary data i v1)))
(v2 (-> boundary data (-> boundary data i v2))))
@@ -634,13 +329,9 @@
(set! (-> polygon-uv z) 1.0)
(set! (-> polygon-uv v w) 1.0))))
(init-boundary-regs)
(#unless PC_PORT
(.lvf vf27 (&-> *sky-tng-data* giftag-roof qword)))
(#when PC_PORT
(set-sky-vf27 (&-> *sky-tng-data* giftag-roof qword)))
(render-boundary-tri (-> *boundary-polygon* 0) dma-buf))
0
(none)))
(none))
(defun-debug boundary-set-color ((color-vertex lbvtx) (command load-boundary-crossing-command))
"Set a debug polygon color from command's load-boundary command
@@ -693,88 +384,30 @@
0
(none))
(#unless PC_PORT
(defun-debug render-boundary ((boundary load-boundary))
"Append debug rendering for boundary to the debug DMA bucket. Closed
boundaries draw their triangulated top cap; open boundaries draw vertical side quads. The selected
boundary alternates UV phase to flash."
(let* ((uv-phase? (or (!= boundary (-> *lb-editor-parms* boundary)) (logtest? (-> *display* real-actual-frame-counter) 4)))
(dma-buf (-> *display* frames (-> *display* on-screen) frame global-buf))
(packet-start (-> dma-buf base)))
(let* ((buffer dma-buf)
(cnt-tag (the-as object (-> buffer base))))
(set! (-> (the-as dma-packet cnt-tag) dma) (new 'static 'dma-tag :qwc #x4 :id (dma-tag-id cnt)))
(set! (-> (the-as dma-packet cnt-tag) vif0) (new 'static 'vif-tag))
(set! (-> (the-as dma-packet cnt-tag) vif1) (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd direct) :msk #x1))
(set! (-> buffer base) (&+ (the-as pointer cnt-tag) 16)))
(let* ((buffer dma-buf)
(giftag (the-as object (-> buffer base))))
(set! (-> (the-as gs-gif-tag giftag) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x3))
(set! (-> (the-as gs-gif-tag giftag) regs) GIF_REGS_ALL_AD)
(set! (-> buffer base) (&+ (the-as pointer giftag) 16)))
(let* ((buffer dma-buf)
(gs-state (-> buffer base)))
(set! (-> (the-as (pointer gs-zbuf) gs-state) 0) (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24)))
(set! (-> (the-as (pointer gs-reg64) gs-state) 1) (gs-reg64 zbuf-1))
(set! (-> (the-as (pointer gs-test) gs-state) 2)
(new 'static 'gs-test :ate #x1 :atst (gs-atest greater-equal) :aref #x26 :zte #x1 :ztst (gs-ztest greater-equal)))
(set! (-> (the-as (pointer gs-reg64) gs-state) 3) (gs-reg64 test-1))
(set! (-> (the-as (pointer gs-alpha) gs-state) 4) (new 'static 'gs-alpha :b #x1 :d #x1))
(set! (-> (the-as (pointer gs-reg64) gs-state) 5) (gs-reg64 alpha-1))
(set! (-> buffer base) (&+ gs-state 48)))
(defun-debug render-boundary ((boundary load-boundary))
"Append debug rendering for boundary to the debug DMA bucket. Closed boundaries draw their
triangulated top cap; open boundaries draw vertical side quads. The selected boundary
alternates UV phase to flash."
(let ((uv-phase? (or (!= boundary (-> *lb-editor-parms* boundary)) (logtest? (-> *display* real-actual-frame-counter) 4))))
(with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (bucket-id debug))
(dma-buffer-add-gs-set-flusha dma-buf
(zbuf-1 (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24)))
(test-1 (new 'static 'gs-test :ate #x1 :atst (gs-atest greater-equal) :aref #x26 :zte #x1 :ztst (gs-ztest greater-equal)))
(alpha-1 (new 'static 'gs-alpha :b #x1 :d #x1)))
(boundary-set-color (-> *boundary-polygon* 2) (-> boundary cmd-fwd))
(boundary-set-color (-> *boundary-polygon* 5) (-> boundary cmd-bwd))
(let ((vif-block (the-as object (-> dma-buf base))))
(&+! (-> dma-buf base) 16)
(add-boundary-shader (new 'static 'texture-id :index #x33 :page #x2) dma-buf)
(cond
((logtest? (-> boundary flags) (load-boundary-flags closed))
(draw-boundary-cap boundary (-> boundary top-plane) dma-buf uv-phase?))
(else
(dotimes (i (the-as int (+ (-> boundary num-points) -1)))
(draw-boundary-side boundary i (+ i 1) dma-buf uv-phase?))))
(close-sky-buffer dma-buf)
(let ((block-qwc (/ (the-as int (+ (- -16 (the-as int vif-block)) (the-as int (-> dma-buf base)))) 16)))
(set! (-> (the-as dma-packet vif-block) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc block-qwc))
(set! (-> (the-as dma-packet vif-block) vif0) (new 'static 'vif-tag))
(set! (-> (the-as dma-packet vif-block) vif1) (new 'static 'vif-tag :cmd (vif-cmd direct) :msk #x1 :imm block-qwc))))
(let ((packet-end (-> dma-buf base)))
(let ((next-tag (the-as object (-> dma-buf base))))
(set! (-> (the-as dma-packet next-tag) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
(set! (-> (the-as dma-packet next-tag) vif0) (new 'static 'vif-tag))
(set! (-> (the-as dma-packet next-tag) vif1) (new 'static 'vif-tag))
(set! (-> dma-buf base) (&+ (the-as pointer next-tag) 16)))
(dma-bucket-insert-tag (-> *display* frames (-> *display* on-screen) frame bucket-group)
(bucket-id debug)
packet-start
(the-as (pointer dma-tag) packet-end))))
0
(none)))
(#when PC_PORT
(defun-debug render-boundary ((boundary load-boundary))
"Append debug rendering for boundary to the debug DMA bucket. Closed boundaries draw their
triangulated top cap; open boundaries draw vertical side quads. The selected boundary
alternates UV phase to flash."
(let ((uv-phase? (or (!= boundary (-> *lb-editor-parms* boundary)) (logtest? (-> *display* real-actual-frame-counter) 4))))
(with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (bucket-id debug))
(dma-buffer-add-gs-set-flusha dma-buf
(zbuf-1 (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24)))
(test-1 (new 'static 'gs-test :ate #x1 :atst (gs-atest greater-equal) :aref #x26 :zte #x1 :ztst (gs-ztest greater-equal)))
(alpha-1 (new 'static 'gs-alpha :b #x1 :d #x1)))
(boundary-set-color (-> *boundary-polygon* 2) (-> boundary cmd-fwd))
(boundary-set-color (-> *boundary-polygon* 5) (-> boundary cmd-bwd))
(with-cnt-vif-block-qwc (dma-buf)
(add-boundary-shader (new 'static 'texture-id :index #x33 :page #x2) dma-buf)
(cond
((logtest? (-> boundary flags) (load-boundary-flags closed))
(draw-boundary-cap boundary (-> boundary top-plane) dma-buf uv-phase?))
(else
(dotimes (i (the-as int (+ (-> boundary num-points) -1)))
(draw-boundary-side boundary i (+ i 1) dma-buf uv-phase?))))
(close-sky-buffer dma-buf))))
0
(none)))
(with-cnt-vif-block-qwc (dma-buf)
(add-boundary-shader (new 'static 'texture-id :index #x33 :page #x2) dma-buf)
(cond
((logtest? (-> boundary flags) (load-boundary-flags closed))
(draw-boundary-cap boundary (-> boundary top-plane) dma-buf uv-phase?))
(else
(dotimes (i (the-as int (+ (-> boundary num-points) -1)))
(draw-boundary-side boundary i (+ i 1) dma-buf uv-phase?))))
(close-sky-buffer dma-buf))))
0
(none))
;;;;;;;;;;;;;;;;;;;;;;;;;
;; Load Boundary File
@@ -1479,6 +1112,7 @@
(return (load-boundary-crossing-result none)))
(let ((plane-scale (/ (- (-> current-pos y) (-> previous-pos y)) (- (-> boundary top-plane) (-> previous-pos y))))
(crossing-point (new 'stack-no-clear 'vector)))
;; This is incorrect --
(set! (-> crossing-point x) (+ (-> previous-pos x) (* plane-scale (- (-> current-pos x) (-> previous-pos x)))))
(set! (-> crossing-point y) (+ (-> previous-pos y) (* plane-scale (- (-> current-pos y) (-> previous-pos y)))))
(set! (-> crossing-point z) (+ (-> previous-pos z) (* plane-scale (- (-> current-pos z) (-> previous-pos z)))))
+1 -3
View File
@@ -106,9 +106,7 @@
(defun load-game-text-info ((group-name string) (destination-symbol symbol) (heap kheap))
"Synchronously ensure group-name is loaded in the selected language into heap and publish the
linked game-text-info through destination-symbol. Reuse matching data; otherwise reset the heap,
load and link the language/group TXT file, and clear destination-symbol on link failure. EE maps
English to UK English in SCEE territory; PC reads its selected text language. Errors are reported
while the function always returns zero."
load and link the language/group TXT file, and clear destination-symbol on link failure."
(local-vars (result int) (loaded-text game-text-info) (language-id language-enum) (load-size int) (heap-free int))
(set! loaded-text (the-as game-text-info (-> destination-symbol value)))
;; split languages in PC port
+32
View File
@@ -313,6 +313,38 @@ TEST(Demacro, Jak1RecognizesDmaCntPacketsWithExplicitQwc) {
)");
}
TEST(Demacro, Jak1RecognizesDirectDmaCntAndRefPackets) {
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 cnt)))
(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* ((dma-state dma-buf)
(packet (the-as object (-> dma-state base))))
(set! (-> (the-as dma-packet packet) dma)
(new 'static 'dma-tag :id (dma-tag-id cnt) :qwc qwc))
(set! (-> (the-as dma-packet packet) vif0) vif0)
(set! (-> (the-as dma-packet packet) vif1) vif1)
(set! (-> dma-state base) (&+ (the-as pointer packet) 16)))
(let ((packet (the-as object (-> dma-buf base))))
(set! (-> (the-as dma-packet packet) dma)
(new 'static 'dma-tag :qwc qwc :id (dma-tag-id ref) :addr addr))
(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))))
)";
const auto result = demacro::rewrite(source, rules);
EXPECT_EQ(result.rewrite_count(), 3);
EXPECT_EQ(result.source, R"((begin
(dma-buffer-add-cnt-vif2 dma-buf 0 vif0 vif1)
(dma-buffer-add-cnt-vif2 dma-buf qwc vif0 vif1)
(dma-buffer-add-ref-vif2 dma-buf qwc addr vif0 vif1))
)");
}
TEST(Demacro, Jak1RecognizesDmaNextPackets) {
const auto rules =
demacro::load_rules(file_util::get_file_path({"decompiler/config/jak1/demacro.jsonc"}));