Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
imgfx.c
Go to the documentation of this file.
1#include "common.h"
2#include "ld_addrs.h"
3#include "sprite.h"
4#include "imgfx.h"
5
6
7#if VERSION_JP // TODO remove once segments are split
8extern Addr imgfx_data_ROM_START;
9#endif
10
11typedef union ImgFXIntVars {
12 s32 raw[2][4];
13 struct {
14 s32 anim[4];
15 s32 color[4];
17 // type-specific anim args (sharing first 0x10 bytes)
18 struct {
19 s32 type;
20 s32 interval; // always 1 or 2 in practice
21 s32 step; // always 1 in practice
23 struct {
24 Vec3i mag;
26 // type-specific color args (sharing second 0x10 bytes)
27 struct {
28 char unk_00[0x10];
29 s32 r;
30 s32 g;
31 s32 b;
32 s32 a;
34 struct {
35 char unk_00[0x10];
36 s32 mode;
37 s32 noiseAmt;
38 char unk_18[4];
39 s32 alphaAmt;
41 struct {
42 char unk_00[0x10];
43 ImgFXOverlayTexture* pattern;
44 s32 alpha;
47
48typedef union ImgFXFloatVars {
49 f32 raw[2][4];
50 // type-specific anim state (sharing first 0x10 bytes)
51 struct {
52 f32 curFrame;
53 f32 curIdx;
55 struct {
56 f32 phase1;
57 f32 phase2;
58 f32 phase3;
60 // type-specific color state (sharing second 0x10 bytes)
61 struct {
62 char unk_00[0x10];
63 f32 posX;
64 f32 posY;
67
68typedef struct ImgFXState {
69 /* 0x00 */ u8 arrayIdx;
70 /* 0x01 */ u8 meshType;
71 /* 0x02 */ u8 renderType;
72 /* 0x03 */ u8 subdivX;
73 /* 0x04 */ u8 subdivY;
74 /* 0x05 */ s8 lastAnimCmd;
75 /* 0x06 */ s8 lastColorCmd;
76 /* 0x07 */ char unk_07[0x1];
77 /* 0x08 */ u16 firstVtxIdx;
78 /* 0x0A */ u16 lastVtxIdx;
79 /* 0x0C */ u16 unk_0C;
80 /* 0x0E */ s16 unk_0E;
81 /* 0x10 */ s16 nextIdx;
82 /* 0x14 */ s32 flags;
83 /* 0x18 */ char unk_18[0x4];
84 /* 0x1C */ ImgFXIntVars ints;
86 /* 0x5C */ Color_RGBA8* colorBuf;
87 /* 0x60 */ u16 colorBufCount;
88 /* 0x62 */ char unk_62[0x2];
89 /* 0x64 */ u8* curAnimOffset;
90 /* 0x68 */ Vtx* vtxBufs[2];
91 /* 0x70 */ Gfx* gfxBufs[2];
92 /* 0x78 */ s32 otherModeL;
93} ImgFXState; // size = 0x7C
94
95typedef struct ImgFXCacheEntry {
96 /* 0x00 */ s32* data;
97 /* 0x04 */ u8 staleCooldownTimer;
98 /* 0x05 */ u8 usingContextualHeap;
99 /* 0x06 */ char unk_06[0x2];
100} ImgFXCacheEntry; // size = 0x8
101
103 IMGFX_ANIM_FLAG_ABSOLUTE_COORDS = 1, // image-relative (in percent) when unset
104};
105
106typedef struct ImgFXRenderMode {
107 /* 0x0 */ s32 mode1;
108 /* 0x4 */ s32 mode2;
109 /* 0x8 */ u8 flags; // only checks TRUE so far. some kind of switch?
110} ImgFXRenderMode; // size = 0xC
111
113
115
122
123// Data
125
127
128Lights2 ImgFXLights = gdSPDefLights2(144, 144, 144, 255, 255, 255, 0, 0, 120, 255, 255, 255, 0, 0, 136);
129
131 .vp = {
132 .vscale = { 640, 480, 511, 0 },
133 .vtrans = { 640, 480, 511, 0 },
134 }
135};
136
138 .vp = {
139 .vscale = { 640, 480, 511, 0 },
140 .vtrans = { 640, 480, 512, 0 },
141 }
142};
143
145
147 gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
148 gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH),
149 gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
150 gsDPSetAlphaCompare(G_AC_NONE),
151 gsSPSetOtherMode(G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 18,
152 G_AD_DISABLE | G_CD_DISABLE | G_TC_FILT | G_TF_BILERP | G_TP_PERSP),
153 gsSPEndDisplayList(),
154};
155
156//TODO figure out bits
158 [IMGFX_RENDER_DEFAULT] { 0x00441208, 0x00111208, 0 },
159 [IMGFX_RENDER_MULTIPLY_RGB] { 0x00441208, 0x00111208, 0 },
160 [IMGFX_RENDER_MULTIPLY_ALPHA] { 0x00404B40, 0x00104B40, IMGFX_RENDER_NO_OVERRIDE },
161 [IMGFX_RENDER_MULTIPLY_RGBA] { 0x00404B40, 0x00104B40, IMGFX_RENDER_NO_OVERRIDE },
162 [IMGFX_RENDER_MODULATE_PRIM_RGB] { 0x00441208, 0x00111208, 0 },
163 [IMGFX_RENDER_MODULATE_PRIM_RGBA] { 0x00404B40, 0x00104B40, IMGFX_RENDER_NO_OVERRIDE },
164 [IMGFX_RENDER_MULTIPLY_SHADE_RGB] { 0x00441208, 0x00111208, 0 },
167 [IMGFX_RENDER_MODULATE_SHADE_RGB] { 0x00441208, 0x00111208, 0 },
169 [IMGFX_RENDER_ANIM] { 0x00441208, 0x00111208, 0 },
170 [IMGFX_RENDER_HOLOGRAM] { 0x00404B40, 0x00104B40, IMGFX_RENDER_NO_OVERRIDE },
171 [IMGFX_RENDER_COLOR_FILL] { 0x00441208, 0x00111208, 0 },
172 [IMGFX_RENDER_OVERLAY_RGB] { 0x00441208, 0x00111208, 0 },
173 [IMGFX_RENDER_OVERLAY_RGBA] { 0x00404B40, 0x00104B40, IMGFX_RENDER_NO_OVERRIDE },
174 [IMGFX_RENDER_UNUSED] { 0x00441208, 0x00111208, 0 },
175};
176
177extern Addr shock_header;
178extern Addr shiver_header;
181extern Addr startle_header;
183extern Addr unfurl_header;
186extern Addr unused_1_header;
187extern Addr unused_2_header;
188extern Addr unused_3_header;
197
198// all relative to imgfx_data_ROM_START
221
225void imgfx_make_mesh(ImgFXState* state);
229//ImgFXAnimHeader* imgfx_load_anim(ImgFXState* state);
235void imgfx_wavy_init(ImgFXState* state);
238
241}
242
243void imgfx_init(void) {
244 s32 i;
245
246 for (i = 0; i < ARRAY_COUNT(ImgFXVtxBuffers); i++) {
248 }
249
251
252 for (i = 0; i < ARRAY_COUNT(*ImgFXInstances); i++) {
255 }
256
257 for (i = 0; i < ARRAY_COUNT(ImgFXDataCache); i++) {
258 ImgFXDataCache[i].data = NULL;
261 }
262
263 imgfx_vtxCount = 0;
265}
266
267void func_8013A4D0(void) {
268 s32 i;
269
271 imgfx_vtxCount = 0;
273
274 (*ImgFXInstances)[0].flags |= IMGFX_FLAG_VALID;
275
276 for (i = 1; i < ARRAY_COUNT(*ImgFXInstances); i++) {
277 if (((*ImgFXInstances)[i].flags & IMGFX_FLAG_VALID) && (*ImgFXInstances)[i].lastAnimCmd != IMGFX_SET_ANIM) {
279 }
280 }
281
282 for (i = 1; i < ARRAY_COUNT(*ImgFXInstances); i++) {
283 if ((*ImgFXInstances)[i].flags & IMGFX_FLAG_VALID && (*ImgFXInstances)[i].colorBuf != NULL) {
284 if ((*ImgFXInstances)[i].lastColorCmd == IMGFX_COLOR_BUF_SET_MULTIPLY) {
285 continue;
286 }
287 if ((*ImgFXInstances)[i].lastColorCmd == IMGFX_COLOR_BUF_SET_MODULATE) {
288 continue;
289 }
290 general_heap_free((*ImgFXInstances)[i].colorBuf);
291 (*ImgFXInstances)[i].colorBuf = NULL;
292 (*ImgFXInstances)[i].colorBufCount = 0;
293 }
294 }
295}
296
297void imgfx_add_to_cache(void* data, s8 usingContextualHeap) {
298 s32 i;
299
300 for (i = 0; i < ARRAY_COUNT(ImgFXDataCache); i++) {
301 if (ImgFXDataCache[i].data == NULL) {
302 ImgFXDataCache[i].data = data;
304 ImgFXDataCache[i].usingContextualHeap = usingContextualHeap;
305 return;
306 }
307 }
308}
309
311 s32 i;
312
313 for (i = 0; i < ARRAY_COUNT(ImgFXDataCache); i++) {
314 if (ImgFXDataCache[i].data != NULL) {
316
317 if (ImgFXDataCache[i].staleCooldownTimer == 0) {
318 if (ImgFXDataCache[i].usingContextualHeap) {
319 heap_free(ImgFXDataCache[i].data);
320 ImgFXDataCache[i].data = NULL;
321 } else {
323 ImgFXDataCache[i].data = NULL;
324 }
325
328 }
329 }
330 }
331}
332
336
337// request some number of imgfx instances. returns the id of the first assigned instance, or -1 if not enough are free.
339 s32 numAssigned;
340 s32 foundAny;
341 s32 iPrev;
342 s32 firstIdx;
343 s32 i;
344
345 numAssigned = 0;
346 for (i = 1; i < ARRAY_COUNT(*ImgFXInstances); i++) {
347 if (!((*ImgFXInstances)[i].flags & IMGFX_FLAG_VALID)) {
348 numAssigned++;
349 }
350 }
351
352 if (numAssigned < count) {
353 return -1;
354 }
355
356 firstIdx = 0;
357 foundAny = FALSE;
358 numAssigned = 0;
359 iPrev = -1;
360 for (i = 1; i < ARRAY_COUNT(*ImgFXInstances); i++) {
361 if ((*ImgFXInstances)[i].flags & IMGFX_FLAG_VALID) {
362 continue;
363 }
364
365 if (!foundAny) {
366 firstIdx = i;
367 foundAny = TRUE;
368 } else {
369 (*ImgFXInstances)[iPrev].nextIdx = i;
370 }
371
372 (*ImgFXInstances)[i].arrayIdx = i;
374 numAssigned++;
375 (*ImgFXInstances)[i].flags |= IMGFX_FLAG_VALID;
376 iPrev = i;
377 if (numAssigned == count) {
378 (*ImgFXInstances)[i].nextIdx = -1;
379 break;
380 }
381 }
382
383 return firstIdx;
384}
385
387 if (idx < MAX_IMGFX_INSTANCES) {
388 (*ImgFXInstances)[idx].flags = 0;
389 (*ImgFXInstances)[idx].nextIdx = -1;
390 }
391}
392
394 if (idx < MAX_IMGFX_INSTANCES) {
395 s32 next;
396
397 do {
398 next = (*ImgFXInstances)[idx].nextIdx;
400 idx = next;
401 } while (next != -1);
402 }
403}
404
406 if (idx < 0 || idx >= MAX_IMGFX_INSTANCES) {
407 return -1;
408 }
409
410 if (idx >= MAX_IMGFX_INSTANCES) {
411 return 0xFF;
412 } else {
413 return (*ImgFXInstances)[idx].nextIdx;
414 }
415}
416
418 return &(*ImgFXInstances)[idx];
419}
420
422 if (state->curAnimOffset != NULL) {
423 state->curAnimOffset = NULL;
424 }
425 if (state->vtxBufs[0] != NULL) {
426 imgfx_add_to_cache(state->vtxBufs[0], TRUE);
427 state->vtxBufs[0] = NULL;
428 }
429 if (state->vtxBufs[1] != NULL) {
430 imgfx_add_to_cache(state->vtxBufs[1], TRUE);
431 state->vtxBufs[1] = NULL;
432 }
433 if (state->gfxBufs[0] != NULL) {
434 imgfx_add_to_cache(state->gfxBufs[0], TRUE);
435 state->gfxBufs[0] = NULL;
436 }
437 if (state->gfxBufs[1] != NULL) {
438 imgfx_add_to_cache(state->gfxBufs[1], TRUE);
439 state->gfxBufs[1] = NULL;
440 }
441}
442
444 state->curAnimOffset = NULL;
445 state->vtxBufs[0] = NULL;
446 state->vtxBufs[1] = NULL;
447 state->gfxBufs[0] = NULL;
448 state->gfxBufs[1] = NULL;
449 state->colorBuf = NULL;
450 state->colorBufCount = 0;
451}
452
454 s32 i;
455 s32 j;
456
457 state->nextIdx = -1;
458 state->lastAnimCmd = IMGFX_CLEAR;
459 state->lastColorCmd = IMGFX_CLEAR;
460 state->flags = 0;
463 state->firstVtxIdx = 0;
464 state->lastVtxIdx = 0;
465 state->unk_0C = 0;
466 state->unk_0E = 0;
467 state->ints.raw[0][3] = 255;
468 state->ints.raw[1][3] = 255;
469 state->subdivX = 0;
470 state->subdivY = 0;
471 state->firstVtxIdx = 0;
472 state->lastVtxIdx = 0;
473
474 for (i = 0; i < ARRAY_COUNT(state->ints.raw); i++) {
475 for (j = 0; j < ARRAY_COUNT(state->ints.raw[0]); j++) {
476 state->ints.raw[i][j] = 0;
477 }
478 }
479
480 for (i = 0; i < ARRAY_COUNT(state->floats.raw); i++) {
481 for (j = 0; j < ARRAY_COUNT(state->floats.raw[0]); j++) {
482 state->floats.raw[i][j] = 0;
483 }
484 }
485}
486
487void imgfx_update(u32 idx, ImgFXType type, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 flags) {
488 ImgFXState* state = &(*ImgFXInstances)[idx];
489 s32 oldFlags;
490 u8 r, g, b, a;
491
492 if (!(state->flags & IMGFX_FLAG_VALID) || (idx >= MAX_IMGFX_INSTANCES)) {
493 return;
494 }
495
496 switch (type) {
497 case IMGFX_CLEAR:
498 case IMGFX_RESET:
499 oldFlags = state->flags;
501 imgfx_init_instance(state);
502 state->flags = oldFlags;
503 state->lastAnimCmd = IMGFX_CLEAR;
504 state->lastColorCmd = IMGFX_CLEAR;
507 state->ints.raw[0][0] = -1;
508 state->ints.raw[1][0] = -1;
509
510 state->flags &= IMGFX_FLAG_VALID;
511 if (flags != 0) {
512 state->flags |= flags;
513 } else {
514 state->flags |= 0; // required to match
515 }
516 return;
517 case IMGFX_UNK_1:
518 state->lastAnimCmd = IMGFX_CLEAR;
520 state->ints.raw[0][0] = -1;
521 return;
522 case IMGFX_UNK_2:
523 state->lastColorCmd = IMGFX_CLEAR;
525 state->ints.raw[1][0] = -1;
526 return;
528 if (state->colorBuf != NULL) {
529 heap_free(state->colorBuf);
530 }
531 state->colorBufCount = imgfxArg1 * 4;
532 state->colorBuf = heap_malloc(state->colorBufCount);
533 return;
534 case IMGFX_OVERLAY:
536 if (type == state->lastColorCmd
537 && imgfxArg1 == (s32) state->ints.overlay.pattern
538 && imgfxArg2 == state->ints.overlay.alpha
539 ) {
540 // no paramaters have changed
541 return;
542 }
543 break;
544 case IMGFX_SET_ANIM:
545 if (state->lastAnimCmd == type
546 && state->ints.anim.type == imgfxArg1
547 && state->ints.anim.interval == imgfxArg2
548 && state->ints.anim.step == imgfxArg3
549 ) {
550 // no paramaters have changed
551 return;
552 }
553 break;
554 default:
555 if (type != IMGFX_HOLOGRAM && state->lastColorCmd == IMGFX_HOLOGRAM) {
557 state->subdivX = 1;
558 state->subdivY = 1;
559 }
560 break;
561 }
562
563 if (type != IMGFX_SET_ANIM && state->lastAnimCmd == IMGFX_SET_ANIM) {
564 state->lastAnimCmd = IMGFX_CLEAR;
565 }
566
567 if (type == IMGFX_SET_WAVY || type == IMGFX_SET_ANIM) {
568 state->lastAnimCmd = type;
569 state->ints.args.anim[0] = imgfxArg1;
570 state->ints.args.anim[1] = imgfxArg2;
571 state->ints.args.anim[2] = imgfxArg3;
572 state->ints.args.anim[3] = imgfxArg4;
573 } else if (type >= IMGFX_SET_COLOR && type <= IMGFX_OVERLAY_XLU) {
574 state->lastColorCmd = type;
575 state->ints.args.color[0] = imgfxArg1;
576 state->ints.args.color[1] = imgfxArg2;
577 state->ints.args.color[2] = imgfxArg3;
578 state->ints.args.color[3] = imgfxArg4;
579 }
580
581 state->flags &= IMGFX_FLAG_VALID;
582 if (flags != 0) {
583 state->flags |= flags;
584 }
586
587 switch (type) {
588 case IMGFX_RESET:
591 break;
592 case IMGFX_SET_WAVY:
593 state->subdivX = 4;
594 state->subdivY = 4;
596 imgfx_wavy_init(state);
597 break;
598 case IMGFX_SET_ANIM:
601 state->floats.anim.curFrame = 0.0f;
602 state->floats.anim.curIdx = 0.0f;
603 state->flags |= IMGFX_FLAG_200;
604 break;
605 case IMGFX_SET_COLOR:
606 case IMGFX_SET_ALPHA:
607 case IMGFX_SET_TINT:
608 if (imgfxArg1 >= 255 && imgfxArg2 >= 255 && imgfxArg3 >= 255 && imgfxArg4 >= 255) {
609 // no color + no transparency
611 } else if (imgfxArg4 >= 255) {
612 // some color + no transparency
614 } else if (imgfxArg1 >= 255 && imgfxArg2 >= 255 && imgfxArg3 >= 255) {
615 // no color + transparency
617 } else {
618 // some color + transparency
620 }
621 break;
624 if (imgfxArg4 == 255.0) {
626 } else {
628 }
629 break;
631 if (imgfxArg1 < state->colorBufCount) {
632 // unpack and store color
633 r = (imgfxArg2 & 0xFF000000) >> 24;
634 g = (imgfxArg2 & 0xFF0000) >> 16;
635 b = (imgfxArg2 & 0xFF00) >> 8;
636 a = (imgfxArg2 & 0xFF);
637 state->colorBuf[imgfxArg1].r = r;
638 state->colorBuf[imgfxArg1].g = g;
639 state->colorBuf[imgfxArg1].b = b;
640 state->colorBuf[imgfxArg1].a = a;
641
643
644 if (a == 255) {
646 } else {
648 }
649 }
650 break;
652 if (imgfxArg1 < state->colorBufCount) {
653 // unpack and store color
654 r = (imgfxArg2 & 0xFF000000) >> 24;
655 g = (imgfxArg2 & 0xFF0000) >> 16;
656 b = (imgfxArg2 & 0xFF00) >> 8;
657 a = (imgfxArg2 & 0xFF);
658 state->colorBuf[imgfxArg1].r = r;
659 state->colorBuf[imgfxArg1].g = g;
660 state->colorBuf[imgfxArg1].b = b;
661 state->colorBuf[imgfxArg1].a = a;
662
664
665 if (a == 255) {
667 } else {
669 }
670 }
671 break;
672 case IMGFX_HOLOGRAM:
674 break;
675 case IMGFX_FILL_COLOR:
677 break;
678 case IMGFX_OVERLAY:
680 state->meshType = IMGFX_MESH_STRIP;
681 if (imgfxArg2 >= 255) {
683 } else {
685 }
686 state->floats.overlay.posX = 0.0f;
687 state->floats.overlay.posY = 0.0f;
688 break;
689 case IMGFX_CLEAR:
690 break;
691 }
692}
693
694void imgfx_set_state_flags(s32 idx, u16 flagBits, s32 mode) {
695 if ((*ImgFXInstances)[idx].flags & IMGFX_FLAG_VALID) {
696 if (mode) {
697 (*ImgFXInstances)[idx].flags |= flagBits;
698 } else {
699 (*ImgFXInstances)[idx].flags &= ~flagBits;
700 }
701 }
702}
703
704s32 imgfx_appendGfx_component(s32 idx, ImgFXTexture* ifxImg, u32 flagBits, Matrix4f mtx) {
705 ImgFXState* state = &(*ImgFXInstances)[idx];
706 s32 ret = 0;
707
708 if (ifxImg->alpha == 0) {
709 return 0;
710 }
711
712 state->arrayIdx = idx;
713 state->flags |= flagBits;
723
724 if (idx < 0 || idx >= MAX_IMGFX_INSTANCES) {
725 return 0;
726 }
727
728 if (idx >= MAX_IMGFX_INSTANCES || state == NULL) {
729 return 0;
730 }
731
732 imgfx_make_mesh(state);
733 imgfx_appendGfx_mesh(state, mtx);
734
735 if (state->flags & IMGFX_FLAG_ANIM_DONE) {
736 state->ints.raw[0][0] = -1;
737 state->ints.raw[1][0] = -1;
738 state->lastAnimCmd = IMGFX_CLEAR;
739 state->meshType = 0;
743 ret = 1;
744 } else if (state->flags & IMGFX_FLAG_4000) {
745 ret = 2;
746 } else if (state->flags & IMGFX_FLAG_20000) {
747 state->lastAnimCmd = IMGFX_CLEAR;
748 state->lastColorCmd = IMGFX_CLEAR;
751 state->ints.raw[0][0] = -1;
752 state->ints.raw[1][0] = -1;
753 state->flags &= IMGFX_FLAG_VALID;
754 ret = 1;
755 }
756 return ret;
757}
758
760 switch (state->meshType) {
762 if (state->ints.raw[1][2] == 0) {
763 state->subdivX = 1;
764 state->subdivY = 16;
765 } else {
766 state->subdivX = 1;
767 state->subdivY = 1;
768 }
769 // fallthrough
772 break;
775 break;
777 case IMGFX_MESH_STRIP:
779 break;
780 default:
781 return;
782 }
783
784 if (state->lastAnimCmd == IMGFX_SET_WAVY) {
786 }
787
788 switch (state->lastColorCmd) {
792 break;
793 }
794}
795
797 s16 skipModeChange = FALSE;
798 s32 primAlpha = state->ints.color.a;
799 s32 renderType = state->renderType;
800 s8 angle1;
801 s8 angle2;
802 f32 ifxImgAlpha;
803 ImgFXRenderMode* renderMode;
804 s32 mode1;
805 s32 mode2;
806 s32 dirX1;
807 s32 dirZ2;
808
809 gDPPipeSync(gMainGfxPos++);
810
811 if (!(state->flags & IMGFX_FLAG_SKIP_GFX_SETUP)) {
812 gSPDisplayList(gMainGfxPos++, DefaultImgFXSetupGfx);
813 if (state->flags & IMGFX_FLAG_NO_FILTERING) {
814 gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
815 }
816 if (state->flags & IMGFX_FLAG_G_CULL_BACK) {
817 gSPSetGeometryMode(gMainGfxPos++, G_CULL_BACK);
818 }
819 if (state->flags & IMGFX_FLAG_G_CULL_FRONT) {
820 gSPSetGeometryMode(gMainGfxPos++, G_CULL_FRONT);
821 }
822
823 renderMode = &ImgFXRenderModes[state->renderType];
824
825 mode1 = renderMode->mode1;
826 mode2 = renderMode->mode2;
827 if (renderMode->flags & IMGFX_RENDER_NO_OVERRIDE) {
828 skipModeChange = TRUE;
829 }
830
831 ifxImgAlpha = (f32) ImgFXCurrentTexturePtr->alphaMultiplier / 255.0;
832
833 // some modes dont support alpha < 255 and must be replaced
834 if (!skipModeChange && (ImgFXCurrentTexturePtr->alphaMultiplier < 255)) {
835 state->ints.color.a = 255;
836 switch (state->renderType) {
839 renderType = IMGFX_RENDER_MULTIPLY_ALPHA;
840 break;
843 renderType = IMGFX_RENDER_MULTIPLY_RGBA;
844 break;
847 break;
848 }
849 primAlpha = state->ints.color.a * ifxImgAlpha;
850 //TODO figure out bits
851 mode1 = 0x404B40;
852 mode2 = 0x104B40;
853 skipModeChange = TRUE;
854 }
855
856 if ((state->flags & IMGFX_FLAG_400) && !skipModeChange) {
857 mode1 &= ~CVG_DST_FULL;
858 mode2 &= ~CVG_DST_FULL;
859 mode1 |= (ALPHA_CVG_SEL | IM_RD);
860 mode2 |= (ALPHA_CVG_SEL | IM_RD);
861 }
862
863 if (state->flags & IMGFX_FLAG_40) {
864 gSPClearGeometryMode(gMainGfxPos++, G_ZBUFFER);
865 } else {
866 gSPSetGeometryMode(gMainGfxPos++, G_ZBUFFER);
867 if (skipModeChange) {
868 mode1 |= Z_CMP;
869 mode2 |= Z_CMP;
870 } else {
871 mode1 |= (Z_CMP | Z_UPD);
872 mode2 |= (Z_CMP | Z_UPD);
873 }
874 }
875 state->otherModeL = mode2;
876 gDPSetRenderMode(gMainGfxPos++, mode1, mode2);
877
878 switch (renderType) {
880 // color: texture * prim
881 // alpha: texture
882 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIDECALA_PRIM, G_CC_MODULATEIDECALA_PRIM);
883 gDPSetPrimColor(gMainGfxPos++, 0, 0, state->ints.color.r, state->ints.color.g,
884 state->ints.color.b, 0);
885 break;
887 // color: texture
888 // alpha: texture * prim
889 if (primAlpha <= 0) {
890 return;
891 }
892 gDPSetCombineMode(gMainGfxPos++, PM_CC_02, PM_CC_02);
893 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, primAlpha);
894 break;
896 // color: texture * prim
897 // alpha: texture * prim
898 if (primAlpha <= 0) {
899 return;
900 }
901 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
902 gDPSetPrimColor(gMainGfxPos++, 0, 0, state->ints.color.r, state->ints.color.g,
903 state->ints.color.b, primAlpha);
904 break;
906 // color: lerp from prim color to 1 based on texture intensity
907 // alpha: texture
908 gDPSetCombineMode(gMainGfxPos++, PM_CC_5B, PM_CC_5B);
909 gDPSetPrimColor(gMainGfxPos++, 0, 0, state->ints.color.r, state->ints.color.g,
910 state->ints.color.b, 0);
911 break;
913 // color: lerp from prim color to 1 based on texture intensity
914 // alpha: texture * vtx
915 if (primAlpha <= 0) {
916 return;
917 }
918 gDPSetCombineMode(gMainGfxPos++, PM_CC_5C, PM_CC_5C);
919 gDPSetPrimColor(gMainGfxPos++, 0, 0, state->ints.color.r, state->ints.color.g,
920 state->ints.color.b, primAlpha);
921 break;
923 // color: modulate vtx color by texture intensity
924 // alpha: texture
925 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
926 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_SHADING_SMOOTH);
927 gSPClearGeometryMode(gMainGfxPos++, G_LIGHTING);
928 break;
930 // color: lerp from vtx color to 1 based on texture intensity
931 // alpha: texture
932 gDPSetCombineMode(gMainGfxPos++, PM_CC_5D, PM_CC_5D);
933 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_SHADING_SMOOTH);
934 gSPClearGeometryMode(gMainGfxPos++, G_LIGHTING);
935 break;
937 // color: texture
938 // alpha: texture * vtx color
939 gDPSetCombineMode(gMainGfxPos++, PM_CC_12, PM_CC_12);
940 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_SHADING_SMOOTH);
941 gSPClearGeometryMode(gMainGfxPos++, G_LIGHTING);
942 break;
944 // color: modulate vtx color by texture intensity
945 // alpha: modulate vtx alpha by texture intensity
946 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIA, G_CC_MODULATEIA);
947 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_SHADING_SMOOTH);
948 gSPClearGeometryMode(gMainGfxPos++, G_LIGHTING);
949 break;
951 // color: lerp from vtx color to 1 based on texture intensity
952 // alpha: vtx color * texture
953 gDPSetCombineMode(gMainGfxPos++, PM_CC_5E, PM_CC_5E);
954 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_SHADING_SMOOTH);
955 gSPClearGeometryMode(gMainGfxPos++, G_LIGHTING);
956 break;
958 if (state->flags & (IMGFX_FLAG_2000 | IMGFX_FLAG_8000)) {
959 Camera* currentCam = &gCameras[gCurrentCameraID];
960
961 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
962 gSPSetGeometryMode(gMainGfxPos++, G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
963
964 angle1 = cosine(currentCam->curYaw) * 120.0f;
965 angle2 = cosine(currentCam->curYaw + 90.0f) * 120.0f;
966 dirX1 = -angle1;
967 dirZ2 = -angle2;
968 ImgFXLights.l[0].l.dir[0] = dirX1;
969 ImgFXLights.l[1].l.dir[0] = angle1;
970 ImgFXLights.l[0].l.dir[2] = angle2;
971 ImgFXLights.l[1].l.dir[2] = dirZ2;
972 gSPSetLights2(gMainGfxPos++, ImgFXLights);
973 break;
974 }
975 gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
976 break;
978 if (state->ints.hologram.mode == IMGFX_HOLOGRAM_NOISE) {
979 primAlpha = state->ints.hologram.alphaAmt * ifxImgAlpha;
980 // color: blend texure and noise
981 // alpha: texure * prim
983 gDPSetPrimColor(gMainGfxPos++, 0, 0,
984 state->ints.hologram.noiseAmt,
985 state->ints.hologram.noiseAmt,
986 state->ints.hologram.noiseAmt,
987 primAlpha);
988 } else if (state->ints.hologram.mode == IMGFX_HOLOGRAM_DITHER) {
989 primAlpha = state->ints.hologram.alphaAmt * ifxImgAlpha;
990 // color: texture
991 // alpha: texture * prim
992 gDPSetCombineMode(gMainGfxPos++, PM_CC_02, PM_CC_02);
993 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, primAlpha);
994 gDPSetAlphaCompare(gMainGfxPos++, G_AC_DITHER);
995 } else if (state->ints.hologram.mode == IMGFX_HOLOGRAM_THRESHOLD) {
996 s32 blendAlpha = state->ints.hologram.alphaAmt + state->ints.hologram.noiseAmt;
997 if (blendAlpha > 255) {
998 blendAlpha = 255;
999 }
1000 primAlpha = state->ints.hologram.alphaAmt * ifxImgAlpha;
1001 // color: texture
1002 // alpha: texture * prim
1003 gDPSetCombineMode(gMainGfxPos++, PM_CC_02, PM_CC_02);
1004 gDPSetAlphaDither(gMainGfxPos++, G_AD_NOISE);
1005 gDPSetAlphaCompare(gMainGfxPos++, G_AC_THRESHOLD);
1006 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, primAlpha);
1007 gDPSetBlendColor(gMainGfxPos++, 0, 0, 0, blendAlpha);
1008 }
1009 break;
1011 // color: prim
1012 // alpha: texture
1014 gDPSetPrimColor(gMainGfxPos++, 0, 0, state->ints.color.r, state->ints.color.g,
1015 state->ints.color.b, 0);
1016 break;
1020 // color: texture
1021 // alpha: texture
1022 gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
1023 break;
1025 // color: texture
1026 // alpha: texture * prim
1027 gDPSetCombineMode(gMainGfxPos++, PM_CC_02, PM_CC_02);
1028 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, state->ints.overlay.alpha);
1029 break;
1030 }
1031 }
1032
1033 switch (state->meshType) {
1034 case IMGFX_MESH_DEFAULT:
1035 imgfx_appendGfx_mesh_basic(state, mtx);
1036 break;
1039 imgfx_appendGfx_mesh_grid(state, mtx);
1040 break;
1042 imgfx_appendGfx_mesh_anim(state, mtx);
1043 break;
1044 case IMGFX_MESH_STRIP:
1045 imgfx_appendGfx_mesh_basic(state, mtx);
1046 gDPPipeSync(gMainGfxPos++);
1047 imgfx_appendGfx_mesh_strip(state, mtx);
1048 break;
1049 }
1050
1051 gDPPipeSync(gMainGfxPos++);
1052
1053 if (state->renderType == IMGFX_RENDER_HOLOGRAM) {
1054 gDPSetAlphaCompare(gMainGfxPos++, G_AC_NONE);
1055 gDPSetAlphaDither(gMainGfxPos++, G_AD_DISABLE);
1056 }
1057}
1058
1060 s32 offsetY;
1061 s32 offsetX;
1062 s32 stepY;
1063 s32 rightColor;
1064 s32 leftColor;
1065 s32 temp2;
1066 s32 nextY;
1067
1068 stepY = (128 * 32) / ImgFXCurrentTexturePtr->tex.width;
1069 if (stepY > ImgFXCurrentTexturePtr->tex.height) {
1071 }
1072
1075 state->firstVtxIdx = imgfx_vtxCount;
1076
1077 // create first pair of vertices to begin the strip
1078 // 'left' side
1079 imgfx_vtxBuf[imgfx_vtxCount].v.ob[0] = offsetX;
1080 imgfx_vtxBuf[imgfx_vtxCount].v.ob[1] = offsetY;
1081 imgfx_vtxBuf[imgfx_vtxCount].v.ob[2] = 0;
1082 imgfx_vtxBuf[imgfx_vtxCount].v.tc[0] = (0 + 256) * 32;
1083 imgfx_vtxBuf[imgfx_vtxCount].v.tc[1] = temp2 = (0 + 256) * 32; // required to match
1084 imgfx_vtxBuf[imgfx_vtxCount].v.cn[0] = 240;
1085 imgfx_vtxBuf[imgfx_vtxCount].v.cn[1] = 240;
1086 imgfx_vtxBuf[imgfx_vtxCount].v.cn[2] = 240;
1087 // 'right' side
1089 imgfx_vtxBuf[imgfx_vtxCount + 1].v.ob[1] = offsetY;
1090 imgfx_vtxBuf[imgfx_vtxCount + 1].v.ob[2] = 0;
1091 imgfx_vtxBuf[imgfx_vtxCount + 1].v.tc[0] = (ImgFXCurrentTexturePtr->tex.width + 256) * 32;
1092 imgfx_vtxBuf[imgfx_vtxCount + 1].v.tc[1] = temp2;
1093 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[0] = 120;
1094 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[1] = 120;
1095 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[2] = 120;
1096
1097 // create remaining pairs of vertices along the strip
1098 nextY = stepY;
1099 while (TRUE) {
1100 rightColor = (nextY * 120) / ImgFXCurrentTexturePtr->tex.height;
1101 leftColor = rightColor + 120;
1102 imgfx_vtxCount += 2;
1103
1104 // 'left' side
1105 imgfx_vtxBuf[imgfx_vtxCount].v.ob[0] = offsetX;
1106 imgfx_vtxBuf[imgfx_vtxCount].v.ob[1] = offsetY - stepY;
1107 imgfx_vtxBuf[imgfx_vtxCount].v.ob[2] = 0;
1108 imgfx_vtxBuf[imgfx_vtxCount].v.tc[0] = (0 + 256) * 32;
1109 imgfx_vtxBuf[imgfx_vtxCount].v.tc[1] = (nextY + 256) * 32;
1110 imgfx_vtxBuf[imgfx_vtxCount].v.cn[0] = leftColor;
1111 imgfx_vtxBuf[imgfx_vtxCount].v.cn[1] = leftColor;
1112 imgfx_vtxBuf[imgfx_vtxCount].v.cn[2] = leftColor;
1113
1114 // 'right' side
1116 imgfx_vtxBuf[imgfx_vtxCount + 1].v.ob[1] = offsetY - stepY;
1117 imgfx_vtxBuf[imgfx_vtxCount + 1].v.ob[2] = 0;
1118 imgfx_vtxBuf[imgfx_vtxCount + 1].v.tc[0] = (ImgFXCurrentTexturePtr->tex.width + 256) * 32;
1119 imgfx_vtxBuf[imgfx_vtxCount + 1].v.tc[1] = (nextY + 256) * 32;
1120 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[0] = rightColor;
1121 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[1] = rightColor;
1122 imgfx_vtxBuf[imgfx_vtxCount + 1].v.cn[2] = rightColor;
1123
1124 if (nextY != ImgFXCurrentTexturePtr->tex.height) {
1125 offsetY -= stepY;
1126 if (ImgFXCurrentTexturePtr->tex.height < nextY + stepY) {
1127 stepY = ImgFXCurrentTexturePtr->tex.height - nextY;
1128 }
1129 } else {
1130 imgfx_vtxCount += 2;
1131 break;
1132 }
1133 nextY += stepY;
1134 }
1135
1136 state->lastVtxIdx = imgfx_vtxCount - 1;
1137 state->subdivX = 1;
1138 state->subdivY = ((state->lastVtxIdx - state->firstVtxIdx) - 1) / 2;
1139}
1140
1142 f32 divSizeX;
1143 f32 divSizeY;
1144 f32 posX;
1145 f32 posY;
1146 f32 texU;
1147 f32 texV;
1148 Vtx* vtx;
1149 s32 i;
1150
1151 state->firstVtxIdx = imgfx_vtxCount;
1152 divSizeX = ImgFXCurrentTexturePtr->tex.width / (f32) state->subdivX;
1153 divSizeY = ImgFXCurrentTexturePtr->tex.height / (f32) state->subdivY;
1155 texV = 0.0f;
1157
1158 for (i = 0; i <= state->subdivY; i++) {
1159 s32 j;
1160
1161 if (i == state->subdivY) {
1164 }
1165
1167 texU = 0.0f;
1168 for (j = 0; j <= state->subdivX; vtx++, j++) {
1169 if (j == state->subdivX) {
1172 }
1173 vtx->n.ob[0] = posX;
1174 vtx->n.ob[1] = posY;
1175 vtx->n.ob[2] = 0;
1176 vtx->n.tc[0] = ((s32) texU + 256) * 32;
1177 vtx->n.tc[1] = ((s32) texV + 256) * 32;
1179 posX += divSizeX;
1180 texU += divSizeX;
1181 }
1182 posY -= divSizeY;
1183 texV += divSizeY;
1184 }
1185 state->lastVtxIdx = imgfx_vtxCount - 1;
1186}
1187
1189 u8* romStart = (s32) ImgFXAnimOffsets[state->ints.anim.type] + imgfx_data_ROM_START;
1190 ImgFXAnimHeader* anim = &ImgFXAnimHeaders[state->arrayIdx];
1191
1192 if (state->curAnimOffset != romStart) {
1193 u8* romEnd;
1194 s32 i;
1195
1196 state->curAnimOffset = romStart;
1197
1198 dma_copy(state->curAnimOffset, state->curAnimOffset + sizeof(*anim), anim);
1199
1200 if (state->vtxBufs[0] != NULL) {
1201 imgfx_add_to_cache(state->vtxBufs[0], 1);
1202 state->vtxBufs[0] = NULL;
1203 }
1204 if (state->vtxBufs[1] != NULL) {
1205 imgfx_add_to_cache(state->vtxBufs[1], 1);
1206 state->vtxBufs[1] = NULL;
1207 }
1208 if (state->gfxBufs[0] != NULL) {
1209 imgfx_add_to_cache(state->gfxBufs[0], 1);
1210 state->gfxBufs[0] = NULL;
1211 }
1212 if (state->gfxBufs[1] != NULL) {
1213 // imgfx_add_to_cache(state->gfxBufs[1], 1);
1214 romEnd = (u8*) state->gfxBufs[1]; // required to match
1215 imgfx_add_to_cache(state->gfxBufs[1], 1);
1216 state->gfxBufs[1] = NULL;
1217 }
1218 state->vtxBufs[0] = heap_malloc(anim->vtxCount * sizeof(Vtx));
1219 state->vtxBufs[1] = heap_malloc(anim->vtxCount * sizeof(Vtx));
1220 state->gfxBufs[0] = heap_malloc(anim->gfxCount * sizeof(Gfx));
1221 state->gfxBufs[1] = heap_malloc(anim->gfxCount * sizeof(Gfx));
1222
1223 romStart = imgfx_data_ROM_START + (s32)anim->gfxOffset;
1224 romEnd = romStart + anim->gfxCount * sizeof(Gfx);
1225 dma_copy(romStart, romEnd, state->gfxBufs[0]);
1226 dma_copy(romStart, romEnd, state->gfxBufs[1]);
1227
1228 // Search through the state's displaylists for vertex commands
1229 // and adjust their addresses to point into the vertex buffers
1230 for (i = 0; i < ARRAY_COUNT(state->gfxBufs); i++) {
1231 Gfx* gfxBuffer = state->gfxBufs[i];
1232 s32 j = 0;
1233 u32 cmd;
1234
1235 // Loop over the displaylist commands until we hit an ENDDL
1236 do {
1237 u32 w0 = gfxBuffer[j++].words.w0;
1238 cmd = w0 >> 0x18;
1239
1240 // If this command is a vertex command, adjust the vertex buffer address
1241 if (cmd == G_VTX) {
1242 // ImgFXVtx structs are 0xC bytes while Vtx are 0x10, so we need a (4/3) scaling factor
1243 // to compute a new, equivalent Vtx[i] address for an existing ImgFXVtx[i] address.
1244 // Unfortunately, using sizeof here does not match.
1245 gfxBuffer[j-1].words.w1 = ((((s32) gfxBuffer[j-1].words.w1 - (s32) anim->keyframesOffset) / 3) * 4) +
1246 (s32) state->vtxBufs[i];
1247 }
1248 } while (cmd != G_ENDDL);
1249 }
1250 }
1251
1252 return anim;
1253}
1254
1256 s32 absKeyframeInterval;
1257 s32 nextKeyIdx;
1258 s32 curKeyIdx;
1259 ImgFXVtx* curKeyframe = NULL;
1260 ImgFXVtx* nextKeyframe = NULL;
1261 s32 keyframeInterval = state->ints.anim.interval;
1262 s32 animStep = state->ints.anim.step;
1263 s32 curSubframe = state->floats.anim.curFrame;
1264 ImgFXAnimHeader* header = imgfx_load_anim(state);
1265 u8* romStart;
1266 f32 lerpAlpha;
1267 s32 i;
1268
1269 if (header == NULL) {
1270 return;
1271 }
1272
1273 if (state->flags & IMGFX_FLAG_200) {
1274 state->flags &= ~IMGFX_FLAG_200;
1275 if (state->flags & IMGFX_FLAG_REVERSE_ANIM) {
1276 state->floats.anim.curIdx = header->keyframesCount - 1;
1277 }
1278 }
1279 curKeyIdx = state->floats.anim.curIdx;
1280 absKeyframeInterval = abs(keyframeInterval);
1281 if (state->flags & IMGFX_FLAG_4000) {
1282 nextKeyIdx = curKeyIdx;
1283 } else {
1284 if (state->flags & IMGFX_FLAG_REVERSE_ANIM) {
1285 nextKeyIdx = curKeyIdx - 1;
1286 if (nextKeyIdx < 0) {
1287 nextKeyIdx = curKeyIdx;
1288 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1289 nextKeyIdx = header->keyframesCount - 1;
1290 }
1291 }
1292 } else {
1293 nextKeyIdx = curKeyIdx + 1;
1294 if (nextKeyIdx == header->keyframesCount) {
1295 nextKeyIdx = curKeyIdx;
1296 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1297 nextKeyIdx = 0;
1298 }
1299 }
1300 }
1301 }
1302
1303 // find the current + next keyframe vertex data
1304 curKeyframe = heap_malloc(header->vtxCount * sizeof(ImgFXVtx));
1305 romStart = (u8*)((s32)imgfx_data_ROM_START + (s32) header->keyframesOffset + curKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
1306 dma_copy(romStart, romStart + header->vtxCount * sizeof(ImgFXVtx), curKeyframe);
1307 if (keyframeInterval > 1) {
1308 nextKeyframe = heap_malloc(header->vtxCount * sizeof(*nextKeyframe));
1309 romStart = (u8*)((s32)imgfx_data_ROM_START + (s32) header->keyframesOffset + nextKeyIdx * header->vtxCount * sizeof(ImgFXVtx));
1310 dma_copy(romStart, romStart + header->vtxCount * sizeof(ImgFXVtx), nextKeyframe);
1311 }
1312
1313 lerpAlpha = (f32) curSubframe / (f32) keyframeInterval;
1314 for (i = 0; i < header->vtxCount; i++) {
1315 if (state->meshType != IMGFX_MESH_ANIMATED) {
1316 return;
1317 }
1318
1319 if (keyframeInterval > 1) {
1320 // get vertex position, interpolated between keyframes
1321 if (header->flags & IMGFX_ANIM_FLAG_ABSOLUTE_COORDS) {
1322 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[0] = (s16)(curKeyframe[i].ob[0] + (nextKeyframe[i].ob[0] - curKeyframe[i].ob[0]) * lerpAlpha);
1323 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[1] = (s16)(curKeyframe[i].ob[1] + (nextKeyframe[i].ob[1] - curKeyframe[i].ob[1]) * lerpAlpha);
1324 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[2] = (s16)(curKeyframe[i].ob[2] + (nextKeyframe[i].ob[2] - curKeyframe[i].ob[2]) * lerpAlpha);
1325 } else {
1326 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[0] = (s16)(curKeyframe[i].ob[0] + (nextKeyframe[i].ob[0] - curKeyframe[i].ob[0]) * lerpAlpha) * 0.01 * ImgFXCurrentTexturePtr->tex.width;
1327 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[1] = (s16)(curKeyframe[i].ob[1] + (nextKeyframe[i].ob[1] - curKeyframe[i].ob[1]) * lerpAlpha) * 0.01 * ImgFXCurrentTexturePtr->tex.height;
1328 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[2] = (s16)(curKeyframe[i].ob[2] + (nextKeyframe[i].ob[2] - curKeyframe[i].ob[2]) * lerpAlpha) * 0.01 * ((ImgFXCurrentTexturePtr->tex.width + ImgFXCurrentTexturePtr->tex.height) / 2);
1329 }
1330 // get vertex color
1331 if (state->flags & (IMGFX_FLAG_2000 | IMGFX_FLAG_8000)) {
1332 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[0] = (s16)(curKeyframe[i].cn[0] + (nextKeyframe[i].cn[0] - curKeyframe[i].cn[0]) * lerpAlpha);
1333 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[1] = (s16)(curKeyframe[i].cn[1] + (nextKeyframe[i].cn[1] - curKeyframe[i].cn[1]) * lerpAlpha);
1334 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[2] = (s16)(curKeyframe[i].cn[2] + (nextKeyframe[i].cn[2] - curKeyframe[i].cn[2]) * lerpAlpha);
1335 } else {
1336 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[0] =
1337 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[1] =
1338 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[2] = 240.0 - (curKeyframe[i].tc[0] + curKeyframe[i].tc[1]) * 1.2;
1339 }
1340 } else {
1341 // get vertex position
1342 if (header->flags & IMGFX_ANIM_FLAG_ABSOLUTE_COORDS) {
1343 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[0] = curKeyframe[i].ob[0];
1344 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[1] = curKeyframe[i].ob[1];
1345 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[2] = curKeyframe[i].ob[2];
1346 } else {
1347 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[0] = curKeyframe[i].ob[0] * 0.01 * ImgFXCurrentTexturePtr->tex.width;
1348 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[1] = curKeyframe[i].ob[1] * 0.01 * ImgFXCurrentTexturePtr->tex.height;
1349 state->vtxBufs[gCurrentDisplayContextIndex][i].v.ob[2] = curKeyframe[i].ob[2] * 0.01 * ((ImgFXCurrentTexturePtr->tex.width + ImgFXCurrentTexturePtr->tex.height) / 2);
1350 }
1351 // get vertex color
1352 if (state->flags & (IMGFX_FLAG_2000 | IMGFX_FLAG_8000)) {
1353 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[0] = curKeyframe[i].cn[0];
1354 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[1] = curKeyframe[i].cn[1];
1355 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[2] = curKeyframe[i].cn[2];
1356 } else {
1357 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[0] =
1358 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[1] =
1359 state->vtxBufs[gCurrentDisplayContextIndex][i].v.cn[2] = 240.0 - (curKeyframe[i].tc[0] + curKeyframe[i].tc[1]) * 1.2;
1360 }
1361 }
1362 // get vertex tex coords
1363 if (header->flags & IMGFX_ANIM_FLAG_ABSOLUTE_COORDS) {
1364 state->vtxBufs[gCurrentDisplayContextIndex][i].v.tc[0] = (curKeyframe[i].tc[0] + 256) * 32;
1365 state->vtxBufs[gCurrentDisplayContextIndex][i].v.tc[1] = (curKeyframe[i].tc[1] + 256) * 32;
1366 } else {
1367 state->vtxBufs[gCurrentDisplayContextIndex][i].v.tc[0] = ((s32)(curKeyframe[i].tc[0] * 0.01 * ImgFXCurrentTexturePtr->tex.width) + 256) * 32;
1368 state->vtxBufs[gCurrentDisplayContextIndex][i].v.tc[1] = ((s32)(curKeyframe[i].tc[1] * 0.01 * ImgFXCurrentTexturePtr->tex.height) + 256) * 32;
1369 }
1370 }
1371
1372 state->firstVtxIdx = 0;
1373 state->lastVtxIdx = header->vtxCount - 1;
1374
1375 heap_free(curKeyframe);
1376 if (nextKeyframe != NULL) {
1377 heap_free(nextKeyframe);
1378 }
1379
1380 if (animStep == 0 || gGameStatusPtr->frameCounter % animStep != 0) {
1381 return;
1382 }
1383
1384 if (keyframeInterval > 0) {
1385 curSubframe++;
1386 if (curSubframe >= keyframeInterval) {
1387 if (state->flags & IMGFX_FLAG_REVERSE_ANIM) {
1388 curKeyIdx--;
1389 if (curKeyIdx < 0) {
1390 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1391 curKeyIdx = header->keyframesCount - 1;
1392 } else {
1393 if (state->flags & IMGFX_FLAG_800) {
1394 curKeyIdx = 0;
1395 state->flags |= IMGFX_FLAG_4000;
1396 } else {
1397 state->flags |= IMGFX_FLAG_ANIM_DONE;
1398 }
1399 }
1400 }
1401 } else {
1402 curKeyIdx++;
1403 if (curKeyIdx >= header->keyframesCount) {
1404 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1405 curKeyIdx = 0;
1406 } else {
1407 if (state->flags & IMGFX_FLAG_800) {
1408 curKeyIdx--;
1409 state->flags |= IMGFX_FLAG_4000;
1410 } else {
1411 state->flags |= IMGFX_FLAG_ANIM_DONE;
1412 }
1413 }
1414 }
1415 }
1416 curSubframe = 0;
1417 }
1418 } else if (keyframeInterval < 0) {
1419 if (state->flags & IMGFX_FLAG_REVERSE_ANIM) {
1420 curKeyIdx -= absKeyframeInterval;
1421 if (curKeyIdx < 0) {
1422 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1423 curKeyIdx += header->keyframesCount;
1424 } else {
1425 if (state->flags & IMGFX_FLAG_800) {
1426 curKeyIdx = 0;
1427 state->flags |= IMGFX_FLAG_4000;
1428 } else {
1429 state->flags |= IMGFX_FLAG_ANIM_DONE;
1430 }
1431 }
1432 }
1433 } else {
1434 curKeyIdx += absKeyframeInterval;
1435 if (curKeyIdx >= header->keyframesCount) {
1436 if (state->flags & IMGFX_FLAG_LOOP_ANIM) {
1437 curKeyIdx %= header->keyframesCount;
1438 } else {
1439 if (state->flags & IMGFX_FLAG_800) {
1440 curKeyIdx = header->keyframesCount - 1;
1441 state->flags |= IMGFX_FLAG_4000;
1442 } else {
1443 state->flags |= IMGFX_FLAG_ANIM_DONE;
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1450 state->floats.anim.curFrame = curSubframe;
1451 state->floats.anim.curIdx = curKeyIdx;
1452}
1453
1455 s32 i;
1456
1457 if (!(state->flags & IMGFX_FLAG_SKIP_TEX_SETUP)) {
1458 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
1459 gDPLoadTLUT_pal16(gMainGfxPos++, 0, ImgFXCurrentTexturePtr->tex.palette);
1460 }
1461
1462 i = state->firstVtxIdx;
1463
1464 while (TRUE) {
1465 Camera* cam;
1466 s32 uls = (imgfx_vtxBuf[i + 0].v.tc[0] >> 0x5) - 256;
1467 s32 ult = (imgfx_vtxBuf[i + 0].v.tc[1] >> 0x5) - 256;
1468 s32 lrs = (imgfx_vtxBuf[i + 3].v.tc[0] >> 0x5) - 256;
1469 s32 lrt = (imgfx_vtxBuf[i + 3].v.tc[1] >> 0x5) - 256;
1470 s32 someFlags = IMGFX_FLAG_100000 | IMGFX_FLAG_80000;
1471 s32 alpha;
1472 s32 alpha2;
1473
1474 if (!(state->flags & IMGFX_FLAG_SKIP_TEX_SETUP)) {
1476 && (state->arrayIdx != 0)
1477 && (state->flags & someFlags)
1478 && ( state->renderType == IMGFX_RENDER_DEFAULT
1482 ) {
1484 ImgFXCurrentTexturePtr->tex.raster, G_IM_FMT_CI,
1486 uls, ult, // top left
1487 lrs - 1, lrt - 1, // bottom right
1488 0, // palette
1489 G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, // clamp wrap mirror
1490 8, 8, // mask
1491 G_TX_NOLOD, G_TX_NOLOD, // shift,
1492 0x100, 0x100); // scroll
1493 gDPSetTile(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0x100, 2, 0,
1494 G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP,
1495 G_TX_NOMASK, G_TX_NOLOD);
1496 gDPSetTileSize(gMainGfxPos++, 2, 0, 0, 252, 0);
1497
1498 alpha = 255;
1499 switch (state->renderType) {
1501 break;
1504 alpha = state->ints.color.a;
1505 break;
1507 alpha = -1;
1508 break;
1509 }
1510
1512 && ((*ImgFXInstances)[0].arrayIdx != 0)
1513 && (state->flags & someFlags)
1514 ) {
1515 cam = &gCameras[gCurrentCamID];
1516
1518 gSPViewport(gMainGfxPos++, &D_8014EE50);
1519 } else {
1520 gSPViewport(gMainGfxPos++, &cam->vpAlt);
1521 }
1522
1523 gDPSetRenderMode(gMainGfxPos++, G_RM_PASS, state->otherModeL);
1524
1525 if (alpha == -1) {
1526 gDPSetCombineMode(gMainGfxPos++, PM_CC_0D, PM_CC_0C);
1527 } else {
1528 gDPSetEnvColor(gMainGfxPos++, 0, 0, 0, alpha);
1529 gDPSetCombineMode(gMainGfxPos++, PM_CC_0B, PM_CC_0C);
1530 }
1531
1532 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[i], 4, 0);
1533 gSP2Triangles(gMainGfxPos++, 0, 2, 1, 0, 1, 2, 3, 0);
1534 gDPPipeSync(gMainGfxPos++);
1535 }
1536 create_shading_palette(mtx, uls, ult, lrs, lrt, alpha, state->otherModeL);
1537 } else {
1539 ImgFXCurrentTexturePtr->tex.raster, G_IM_FMT_CI,
1541 uls, ult, // top left
1542 lrs - 1, lrt - 1, // bottom right
1543 0, // palette
1544 G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, // clamp wrap mirror
1545 8, 8, // mask
1546 G_TX_NOLOD, G_TX_NOLOD, // shift,
1547 0x100, 0x100); // scroll
1548
1550 && state->arrayIdx != 0
1551 && (state->flags & someFlags)
1552 ) {
1553 alpha2 = 255;
1554 cam = &gCameras[gCurrentCamID];
1555
1557 gSPViewport(gMainGfxPos++, &D_8014EE50);
1558 } else {
1559 gSPViewport(gMainGfxPos++, &cam->vpAlt);
1560 }
1561
1562 if (alpha2 == 255) {
1563 gDPSetRenderMode(gMainGfxPos++, G_RM_AA_ZB_TEX_EDGE, G_RM_AA_ZB_TEX_EDGE2);
1564 } else {
1565 gDPSetRenderMode(gMainGfxPos++, G_RM_ZB_XLU_SURF, G_RM_ZB_XLU_SURF2);
1566 }
1567
1568 switch (state->renderType) {
1570 alpha2 = 255;
1571 break;
1574 alpha2 = state->ints.color.a;
1575 break;
1577 alpha2 = -1;
1578 break;
1579 }
1580
1581 if (alpha2 == -1) {
1582 gDPSetCombineMode(gMainGfxPos++, PM_CC_59, PM_CC_59);
1583 } else {
1584 gDPSetEnvColor(gMainGfxPos++, 0, 0, 0, alpha2);
1585 gDPSetCombineMode(gMainGfxPos++, PM_CC_0A, PM_CC_0A);
1586 }
1587
1588 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[i], 4, 0);
1589 gSP2Triangles(gMainGfxPos++, 0, 2, 1, 0, 1, 2, 3, 0);
1590 gDPPipeSync(gMainGfxPos++);
1591
1592 if (alpha2 == 255) {
1593 gDPSetRenderMode(gMainGfxPos++, G_RM_AA_ZB_TEX_EDGE, G_RM_AA_ZB_TEX_EDGE2);
1594 } else {
1595 gDPSetRenderMode(gMainGfxPos++, G_RM_ZB_XLU_SURF, G_RM_ZB_XLU_SURF2);
1596 }
1597
1598 gDPSetEnvColor(gMainGfxPos++, 100, 100, 100, 255);
1599 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, alpha2);
1600 gDPSetCombineMode(gMainGfxPos++, PM_CC_5A, PM_CC_5A);
1601 gDPSetColorDither(gMainGfxPos++, G_CD_MAGICSQ);
1602 }
1603 }
1604 }
1605
1607 && (*ImgFXInstances)[0].arrayIdx != 0
1608 && (state->flags & someFlags)
1609 ) {
1610 cam = &gCameras[gCurrentCamID];
1612 gSPViewport(gMainGfxPos++, &D_8014EE40);
1613 D_8014EE50.vp.vtrans[0] = D_8014EE40.vp.vtrans[0] + gGameStatusPtr->altViewportOffset.x;
1614 D_8014EE50.vp.vtrans[1] = D_8014EE40.vp.vtrans[1] + gGameStatusPtr->altViewportOffset.y;
1615 } else {
1616 gSPViewport(gMainGfxPos++, &cam->vp);
1617 }
1618 }
1619
1620 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[i], 4, 0);
1621 gSP2Triangles(gMainGfxPos++, 0, 2, 1, 0, 1, 2, 3, 0);
1622
1623 if (i + 3 >= state->lastVtxIdx) {
1624 break;
1625 }
1626
1627 i += 2;
1628 }
1629}
1630
1632 s32 i, j;
1633 s32 firstVtxIdx;
1634
1635 if (!(state->flags & IMGFX_FLAG_SKIP_TEX_SETUP)) {
1636 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
1637 gDPLoadTLUT_pal16(gMainGfxPos++, 0, ImgFXCurrentTexturePtr->tex.palette);
1638 }
1639
1640 firstVtxIdx = state->firstVtxIdx;
1641 for (i = 0; i < state->subdivY; i++) {
1642 for (j = 0; j < state->subdivX; j++) {
1643 s32 ulIdx = firstVtxIdx + i * (state->subdivX + 1) + j;
1644 s32 urIdx = firstVtxIdx + i * (state->subdivX + 1) + j + 1;
1645 s32 llIdx = firstVtxIdx + (i + 1) * (state->subdivX + 1) + j;
1646 s32 lrIdx = firstVtxIdx + (i + 1) * (state->subdivX + 1) + j + 1;
1647 if (!(state->flags & IMGFX_FLAG_SKIP_TEX_SETUP)) {
1649 && (*ImgFXInstances)[0].arrayIdx != 0
1650 && (state->flags & (IMGFX_FLAG_100000 | IMGFX_FLAG_80000))
1651 && (state->renderType == IMGFX_RENDER_DEFAULT
1654 ) {
1655 s32 alpha = 255;
1657 ImgFXCurrentTexturePtr->tex.raster, G_IM_FMT_CI,
1659 (imgfx_vtxBuf[ulIdx].v.tc[0] >> 5) - 0x100, (imgfx_vtxBuf[ulIdx].v.tc[1] >> 5) - 0x100, // top left
1660 (imgfx_vtxBuf[lrIdx].v.tc[0] >> 5) - 0x100 - 1, (imgfx_vtxBuf[lrIdx].v.tc[1] >> 5) - 0x100 - 1, // bottom right
1661 0, // palette
1662 G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, // clamp wrap mirror
1663 8, 8, // mask
1664 G_TX_NOLOD, G_TX_NOLOD, // shift,
1665 0x100, 0x100); // scroll
1666 gDPSetTile(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0x0100, 2, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
1667 gDPSetTileSize(gMainGfxPos++, 2, 0, 0, 63 << 2, 0);
1668 switch (state->renderType) {
1670 alpha = 255;
1671 break;
1673 alpha = state->ints.color.a;
1674 break;
1676 alpha = -1;
1677 break;
1678
1679 }
1681 (imgfx_vtxBuf[ulIdx].v.tc[0] >> 5) - 0x100, (imgfx_vtxBuf[ulIdx].v.tc[1] >> 5) - 0x100,
1682 (imgfx_vtxBuf[lrIdx].v.tc[0] >> 5) - 0x100, (imgfx_vtxBuf[lrIdx].v.tc[1] >> 5) - 0x100,
1683 alpha, state->otherModeL);
1684 } else {
1686 ImgFXCurrentTexturePtr->tex.raster, G_IM_FMT_CI,
1688 (imgfx_vtxBuf[ulIdx].v.tc[0] >> 5) - 0x100, (imgfx_vtxBuf[ulIdx].v.tc[1] >> 5) - 0x100, // top left
1689 (imgfx_vtxBuf[lrIdx].v.tc[0] >> 5) - 0x100 - 1, (imgfx_vtxBuf[lrIdx].v.tc[1] >> 5) - 0x100 - 1, // bottom right
1690 0, // palette
1691 G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, // clamp wrap mirror
1692 8, 8, // mask
1693 G_TX_NOLOD, G_TX_NOLOD, // shift,
1694 0x100, 0x100); // scroll
1695 }
1696 }
1697
1698 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[ulIdx], 1, 0);
1699 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[urIdx], 1, 1);
1700 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[llIdx], 1, 2);
1701 gSPVertex(gMainGfxPos++, &imgfx_vtxBuf[lrIdx], 1, 3);
1702 gSP2Triangles(gMainGfxPos++, 0, 2, 1, 0, 1, 2, 3, 0);
1703 }
1704 }
1705}
1706
1708 if (state->vtxBufs[gCurrentDisplayContextIndex] == NULL || state->gfxBufs[gCurrentDisplayContextIndex] == NULL) {
1709 return;
1710 }
1711
1712 guScale(&gDisplayContext->matrixStack[gMatrixListPos], 0.1f, 0.1f, 0.1f);
1713 gSPMatrix(gMainGfxPos++, VIRTUAL_TO_PHYSICAL(&gDisplayContext->matrixStack[gMatrixListPos++]), G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
1714
1715 if (!(state->flags & IMGFX_FLAG_SKIP_TEX_SETUP)) {
1716 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
1717 gDPLoadTLUT_pal16(gMainGfxPos++, 0, ImgFXCurrentTexturePtr->tex.palette);
1719 && (state->flags & (IMGFX_FLAG_100000 | IMGFX_FLAG_80000))
1720 && (state->renderType == IMGFX_RENDER_DEFAULT
1723 || state->renderType == IMGFX_RENDER_ANIM)
1724 ) {
1725 s32 alpha = 255;
1729 G_TX_CLAMP, G_TX_CLAMP, 8, 8, G_TX_NOLOD, G_TX_NOLOD,
1730 256, 256);
1731 gDPSetTile(gMainGfxPos++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0x0100, 2, 0,
1732 G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
1733 gDPSetTileSize(gMainGfxPos++, 2, 0, 0, 252, 0);
1734
1735 switch (state->renderType) {
1737 case IMGFX_RENDER_ANIM:
1738 alpha = 255;
1739 break;
1741 alpha = state->ints.color.a;
1742 break;
1744 alpha = -1;
1745 break;
1746
1747 }
1749 } else {
1753 G_TX_CLAMP, G_TX_CLAMP, 8, 8, G_TX_NOLOD, G_TX_NOLOD,
1754 256, 256);
1755 }
1756 }
1757 gSPDisplayList(gMainGfxPos++, state->gfxBufs[gCurrentDisplayContextIndex]);
1758 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
1759}
1760
1762 ImgFXOverlayTexture* ufs = state->ints.overlay.pattern;
1763 s32 shifts = integer_log(ufs->width, 2);
1764 s32 shiftt = integer_log(ufs->height, 2);
1765 s32 uls, ult;
1766 s32 lrs, lrt;
1767
1769 gSPMatrix(gMainGfxPos++, VIRTUAL_TO_PHYSICAL(&gDisplayContext->matrixStack[gMatrixListPos++]), G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
1770 gDPSetRenderMode(gMainGfxPos++, G_RM_ZB_XLU_DECAL, G_RM_ZB_XLU_DECAL2);
1771
1772 if (state->renderType == IMGFX_RENDER_OVERLAY_RGBA) {
1773 s32 alpha = state->ints.overlay.alpha;
1774 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, alpha);
1775 gDPSetCombineMode(gMainGfxPos++, PM_CC_05, PM_CC_05);
1776 } else {
1777 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIA, G_CC_MODULATEIA);
1778 }
1779 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
1780 gDPLoadTLUT_pal16(gMainGfxPos++, 0, ufs->palette);
1781 gDPScrollTextureTile_4b(gMainGfxPos++, ufs->raster, G_IM_FMT_CI, ufs->width, ufs->height,
1782 0, 0, ufs->width - 1, ufs->height - 1, 0,
1783 G_TX_WRAP, G_TX_WRAP, shifts, shiftt, G_TX_NOLOD, G_TX_NOLOD,
1784 256, 256);
1785
1786 uls = state->floats.overlay.posX;
1787 ult = state->floats.overlay.posY;
1788 lrs = ufs->width * 4 + state->floats.overlay.posX;
1789 lrt = ufs->height * 4 + state->floats.overlay.posY;
1790 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, uls, ult, lrs, lrt);
1791
1792 state->floats.overlay.posX = (s32)(state->floats.overlay.posX + ufs->offsetX) % (ufs->width * 4);
1793 state->floats.overlay.posY = (s32)(state->floats.overlay.posY + ufs->offsetY) % (ufs->height * 4);
1794 gSPDisplayList(gMainGfxPos++, ufs->displayList);
1795 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
1796}
1797
1799 state->floats.wavy.phase1 = 0.0f;
1800 state->floats.wavy.phase2 = 50.0f;
1801 state->floats.wavy.phase3 = 30.0f;
1802}
1803
1805 Vtx* v1;
1806 Vtx* v2;
1807 Vtx* v3;
1808 f32 vx;
1809 f32 vy;
1810 f32 vz;
1811 f32 angle1;
1812 f32 angle2;
1813 f32 angle3;
1814 f32 phase1;
1815 f32 phase2;
1816 f32 phase3;
1817 s32 angleInc;
1818 s32 amt;
1819 s32 sign;
1820 s32 i;
1821
1822 phase1 = (f32) gGameStatusPtr->frameCounter / 10.3;
1823 while (phase1 > 360.0) {
1824 phase1 -= 360.0;
1825 }
1826
1827 phase2 = (f32) (gGameStatusPtr->frameCounter + 40) / 11.2;
1828 while (phase2 > 360.0) {
1829 phase2 -= 360.0;
1830 }
1831
1832 phase3 = (f32) (gGameStatusPtr->frameCounter + 25) / 10.8;
1833 while (phase3 > 360.0) {
1834 phase3 -= 360.0;
1835 }
1836
1837 state->floats.wavy.phase1 = phase1;
1838 state->floats.wavy.phase2 = phase2;
1839 state->floats.wavy.phase3 = phase3;
1840
1841 if (state->floats.wavy.phase1 >= 360.0) {
1842 state->floats.wavy.phase1-= 360.0;
1843 }
1844
1845 if (state->floats.wavy.phase2 >= 360.0) {
1846 state->floats.wavy.phase2 -= 360.0;
1847 }
1848
1849 if (state->floats.wavy.phase3 >= 360.0) {
1850 state->floats.wavy.phase3 -= 360.0;
1851 }
1852
1853 sign = 0;
1854 angleInc = 0;
1855 amt = (state->lastVtxIdx - state->firstVtxIdx) - state->subdivX;
1856
1857 for (i = 0; i < amt; i++) {
1858 angle1 = state->floats.wavy.phase1 + (angleInc * 45) + (sign * 180);
1859 angle2 = state->floats.wavy.phase2 + (angleInc * 45) + (sign * 180);
1860 angle3 = state->floats.wavy.phase3 + (angleInc * 45) + (sign * 180);
1861
1862 //TODO find better match
1863 v1 = (Vtx*)((state->firstVtxIdx + i) * sizeof(Vtx) + (s32)imgfx_vtxBuf);
1864 vx = v1->v.ob[0];
1865 v1->v.ob[0] = (vx + (sin_deg(angle1) * state->ints.wavy.mag.x));
1866
1867 v2 = (Vtx*)((state->firstVtxIdx + i) * sizeof(Vtx) + (s32)imgfx_vtxBuf);
1868 vy = v2->v.ob[1];
1869 v2->v.ob[1] = (vy + (sin_deg(angle2) * state->ints.wavy.mag.y));
1870
1871 v3 = (Vtx*)((state->firstVtxIdx + i) * sizeof(Vtx) + (s32)imgfx_vtxBuf);
1872 vz = v3->v.ob[2];
1873 v3->v.ob[2] = (vz + (sin_deg(angle3) * state->ints.wavy.mag.z));
1874
1875 angleInc++;
1876 if (i % (state->subdivX + 1) == 0) {
1877 angleInc = 0;
1878 sign = !sign;
1879 }
1880 }
1881}
1882
1884 f32 alpha = (f32)ImgFXCurrentTexturePtr->alphaMultiplier / 255.0;
1885 s32 vtxCount = state->lastVtxIdx - state->firstVtxIdx;
1886 s32 i;
1887
1888 for (i = 0; i <= vtxCount; i++) {
1889 imgfx_vtxBuf[state->firstVtxIdx + i].v.cn[0] = state->colorBuf[i].r;
1890 imgfx_vtxBuf[state->firstVtxIdx + i].v.cn[1] = state->colorBuf[i].g;
1891 imgfx_vtxBuf[state->firstVtxIdx + i].v.cn[2] = state->colorBuf[i].b;
1892 imgfx_vtxBuf[state->firstVtxIdx + i].v.cn[3] = state->colorBuf[i].a * alpha;
1893 }
1894}
Vec2b altViewportOffset
Mtx matrixStack[0x200]
f32 Matrix4f[4][4]
s8 flags
Definition demo_api.c:15
#define sin_deg
@ SPR_SHADING_FLAG_SET_VIEWPORT
Definition enums.h:5208
@ SPR_SHADING_FLAG_ENABLED
Definition enums.h:5207
@ IMGFX_RENDER_MULTIPLY_RGBA
Definition enums.h:5164
@ IMGFX_RENDER_MULTIPLY_SHADE_ALPHA
Definition enums.h:5168
@ IMGFX_RENDER_HOLOGRAM
Definition enums.h:5173
@ IMGFX_RENDER_MULTIPLY_SHADE_RGB
Definition enums.h:5167
@ IMGFX_RENDER_OVERLAY_RGBA
Definition enums.h:5176
@ IMGFX_RENDER_MODULATE_PRIM_RGBA
Definition enums.h:5166
@ IMGFX_RENDER_MULTIPLY_RGB
Definition enums.h:5162
@ IMGFX_RENDER_ANIM
Definition enums.h:5172
@ IMGFX_RENDER_DEFAULT
Definition enums.h:5161
@ IMGFX_RENDER_MULTIPLY_SHADE_RGBA
Definition enums.h:5169
@ IMGFX_RENDER_OVERLAY_RGB
Definition enums.h:5175
@ IMGFX_RENDER_MODULATE_PRIM_RGB
Definition enums.h:5165
@ IMGFX_RENDER_MULTIPLY_ALPHA
Definition enums.h:5163
@ IMGFX_RENDER_MODULATE_SHADE_RGB
Definition enums.h:5170
@ IMGFX_RENDER_MODULATE_SHADE_RGBA
Definition enums.h:5171
@ IMGFX_RENDER_COLOR_FILL
Definition enums.h:5174
@ IMGFX_RENDER_UNUSED
Definition enums.h:5177
ImgFXType
Definition enums.h:5116
@ IMGFX_SET_ALPHA
Definition enums.h:5124
@ IMGFX_COLOR_BUF_SET_MULTIPLY
Definition enums.h:5128
@ IMGFX_RESET
Definition enums.h:5120
@ IMGFX_HOLOGRAM
Definition enums.h:5130
@ IMGFX_SET_COLOR
Definition enums.h:5123
@ IMGFX_OVERLAY_XLU
Definition enums.h:5133
@ IMGFX_OVERLAY
Definition enums.h:5132
@ IMGFX_CLEAR
Definition enums.h:5117
@ IMGFX_SET_WAVY
Definition enums.h:5121
@ IMGFX_ALLOC_COLOR_BUF
Definition enums.h:5134
@ IMGFX_FILL_COLOR
Definition enums.h:5131
@ IMGFX_COLOR_BUF_SET_MODULATE
Definition enums.h:5129
@ IMGFX_SET_CREDITS_FADE
Definition enums.h:5127
@ IMGFX_SET_TINT
Definition enums.h:5125
@ IMGFX_SET_WHITE_FADE
Definition enums.h:5126
@ IMGFX_SET_ANIM
Definition enums.h:5122
@ IMGFX_UNK_2
Definition enums.h:5119
@ IMGFX_UNK_1
Definition enums.h:5118
@ IMGFX_ANIM_VERTICAL_PIPE_CURL
Definition enums.h:5140
@ IMGFX_ANIM_HORIZONTAL_PIPE_CURL
Definition enums.h:5141
@ IMGFX_ANIM_SHIVER
Definition enums.h:5139
@ IMGFX_ANIM_FLIP_CARD_1
Definition enums.h:5154
@ IMGFX_ANIM_FLUTTER_DOWN
Definition enums.h:5143
@ IMGFX_ANIM_SHUFFLE_CARDS
Definition enums.h:5153
@ IMGFX_ANIM_STARTLE
Definition enums.h:5142
@ IMGFX_ANIM_SPIRIT_CAPTURE
Definition enums.h:5146
@ IMGFX_ANIM_UNUSED_2
Definition enums.h:5148
@ IMGFX_ANIM_FLIP_CARD_2
Definition enums.h:5155
@ IMGFX_ANIM_UNUSED_1
Definition enums.h:5147
@ IMGFX_ANIM_TUTANKOOPA_SWIRL_1
Definition enums.h:5152
@ IMGFX_ANIM_FLIP_CARD_3
Definition enums.h:5156
@ IMGFX_ANIM_TUTANKOOPA_SWIRL_2
Definition enums.h:5151
@ IMGFX_ANIM_UNFURL
Definition enums.h:5144
@ IMGFX_ANIM_CYMBAL_CRUSH
Definition enums.h:5157
@ IMGFX_ANIM_SHOCK
Definition enums.h:5138
@ IMGFX_ANIM_TUTANKOOPA_GATHER
Definition enums.h:5150
@ IMGFX_ANIM_UNUSED_3
Definition enums.h:5149
@ IMGFX_ANIM_GET_IN_BED
Definition enums.h:5145
@ IMGFX_RENDER_NO_OVERRIDE
Definition enums.h:5181
@ IMGFX_HOLOGRAM_DITHER
Definition enums.h:5194
@ IMGFX_HOLOGRAM_NOISE
Definition enums.h:5193
@ IMGFX_HOLOGRAM_THRESHOLD
Definition enums.h:5195
@ CONTEXT_PAUSE
Definition enums.h:3531
@ IMGFX_MESH_STRIP
Definition enums.h:5189
@ IMGFX_MESH_GRID_WAVY
Definition enums.h:5186
@ IMGFX_MESH_GRID_UNUSED
Definition enums.h:5188
@ IMGFX_MESH_ANIMATED
Definition enums.h:5187
@ IMGFX_MESH_DEFAULT
Definition enums.h:5185
@ IMGFX_FLAG_8000
Definition enums.h:5108
@ IMGFX_FLAG_SKIP_TEX_SETUP
Definition enums.h:5098
@ IMGFX_FLAG_40
Definition enums.h:5099
@ IMGFX_FLAG_ANIM_DONE
Definition enums.h:5105
@ IMGFX_FLAG_VALID
Definition enums.h:5093
@ IMGFX_FLAG_G_CULL_BACK
Definition enums.h:5094
@ IMGFX_FLAG_LOOP_ANIM
Definition enums.h:5100
@ IMGFX_FLAG_20000
Definition enums.h:5110
@ IMGFX_FLAG_G_CULL_FRONT
Definition enums.h:5095
@ IMGFX_FLAG_100000
Definition enums.h:5113
@ IMGFX_FLAG_REVERSE_ANIM
Definition enums.h:5101
@ IMGFX_FLAG_NO_FILTERING
Definition enums.h:5109
@ IMGFX_FLAG_2000
Definition enums.h:5106
@ IMGFX_FLAG_200
Definition enums.h:5102
@ IMGFX_FLAG_80000
Definition enums.h:5112
@ IMGFX_FLAG_800
Definition enums.h:5104
@ IMGFX_FLAG_SKIP_GFX_SETUP
Definition enums.h:5097
@ IMGFX_FLAG_4000
Definition enums.h:5107
@ IMGFX_FLAG_400
Definition enums.h:5103
s32 sign(s32 value)
Definition 43F0.c:376
s32 integer_log(s32 number, u32 base)
f32 cosine(s16 arg0)
Definition 43F0.c:354
u32 dma_copy(Addr romStart, Addr romEnd, void *vramDest)
Definition 43F0.c:444
void * _heap_malloc(HeapNode *head, u32 size)
Definition 43F0.c:78
s32 heap_free(void *ptr)
Definition heap.c:42
s32 general_heap_free(void *data)
Definition heap.c:18
void * heap_malloc(s32 size)
Definition heap.c:34
#define gDPScrollMultiTile2_4b(pkt, timg, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, shifts, shiftt, scrolls, scrollt)
Definition gbi_custom.h:6
#define gDPScrollTextureTile_4b(pkt, timg, fmt, width, height, uls, ult, lrs, lrt, pal, cms, cmt, masks, maskt, shifts, shiftt, scrolls, scrollt)
Definition gbi_custom.h:39
Addr startle_header
s8 lastAnimCmd
Definition imgfx.c:74
void imgfx_release_instance(u32 idx)
Definition imgfx.c:386
ImgFXState ImgFXInstanceList[MAX_IMGFX_INSTANCES]
Definition imgfx.c:112
struct ImgFXFloatVars::@129 anim
void imgfx_wavy_init(ImgFXState *state)
Definition imgfx.c:1798
Addr unfurl_header
u16 firstVtxIdx
Definition imgfx.c:77
Addr vertical_pipe_curl_header
void imgfx_update_cache(void)
Definition imgfx.c:333
u16 unk_0C
Definition imgfx.c:79
Vtx * vtxBufs[2]
Definition imgfx.c:90
u8 subdivY
Definition imgfx.c:73
char unk_06[0x2]
Definition imgfx.c:99
u8 subdivX
Definition imgfx.c:72
s32 flags
Definition imgfx.c:82
void imgfx_clear_instance_data(ImgFXState *state)
Definition imgfx.c:443
void imgfx_appendGfx_mesh_strip(ImgFXState *, Matrix4f mtx)
Definition imgfx.c:1761
struct ImgFXFloatVars::@131 overlay
Addr shuffle_cards_header
struct ImgFXIntVars::@124 anim
Lights2 ImgFXLights
Definition imgfx.c:128
s32 imgfx_get_next_instance(s32 idx)
Definition imgfx.c:405
Addr unused_2_header
BSS ImgFXAnimHeader ImgFXAnimHeaders[MAX_IMGFX_INSTANCES]
Definition imgfx.c:120
ImgFXAnimHeader * imgfx_load_anim(ImgFXState *state)
Definition imgfx.c:1188
void imgfx_mesh_make_strip(ImgFXState *state)
Definition imgfx.c:1059
ImgFXWorkingTexture * ImgFXCurrentTexturePtr
Definition imgfx.c:124
u16 lastVtxIdx
Definition imgfx.c:78
ImgFXRenderMode ImgFXRenderModes[]
Definition imgfx.c:157
void imgfx_update_cache_impl(void)
Definition imgfx.c:310
u16 imgfx_vtxCount
Definition imgfx.c:126
s32 otherModeL
Definition imgfx.c:92
struct ImgFXIntVars::@126 color
void imgfx_set_vtx_buf_capacity(s16 arg0)
Definition imgfx.c:239
s16 unk_0E
Definition imgfx.c:80
BSS Vtx * ImgFXVtxBuffers[2]
Definition imgfx.c:117
void imgfx_mesh_load_colors(ImgFXState *state)
Definition imgfx.c:1883
Addr flip_card_2_header
struct ImgFXIntVars::@123 args
ImgFXState * imgfx_get_instance(s32 idx)
Definition imgfx.c:417
s8 lastColorCmd
Definition imgfx.c:75
void imgfx_add_to_cache(void *data, s8 usingContextualHeap)
Definition imgfx.c:297
u8 renderType
Definition imgfx.c:71
void imgfx_mesh_make_grid(ImgFXState *state)
Definition imgfx.c:1141
s32 imgfx_get_free_instances(s32 count)
Definition imgfx.c:338
u8 usingContextualHeap
Definition imgfx.c:98
Gfx * gfxBufs[2]
Definition imgfx.c:91
ImgFXIntVars ints
Definition imgfx.c:84
Vp D_8014EE40
Definition imgfx.c:130
u16 colorBufCount
Definition imgfx.c:87
u8 meshType
Definition imgfx.c:70
BSS ImgFXInstanceList * ImgFXInstances
Definition imgfx.c:119
Vp D_8014EE50
Definition imgfx.c:137
s32 raw[2][4]
Definition imgfx.c:12
void imgfx_appendGfx_mesh_basic(ImgFXState *, Matrix4f mtx)
Definition imgfx.c:1454
s32 imgfx_appendGfx_component(s32 idx, ImgFXTexture *ifxImg, u32 flagBits, Matrix4f mtx)
Definition imgfx.c:704
void imgfx_appendGfx_mesh_anim(ImgFXState *, Matrix4f mtx)
Definition imgfx.c:1707
ImgFXFloatVars floats
Definition imgfx.c:85
Addr horizontal_pipe_curl_header
char unk_07[0x1]
Definition imgfx.c:76
BSS Vtx * imgfx_vtxBuf
Definition imgfx.c:118
void imgfx_set_state_flags(s32 idx, u16 flagBits, s32 mode)
Definition imgfx.c:694
Addr flip_card_1_header
void imgfx_appendGfx_mesh_grid(ImgFXState *, Matrix4f mtx)
Definition imgfx.c:1631
void imgfx_init(void)
Definition imgfx.c:243
ImgFXAnimFlags
Definition imgfx.c:102
@ IMGFX_ANIM_FLAG_ABSOLUTE_COORDS
Definition imgfx.c:103
Addr shiver_header
Addr tutankoopa_gather_header
struct ImgFXIntVars::@125 wavy
void imgfx_appendGfx_mesh(ImgFXState *state, Matrix4f mtx)
Definition imgfx.c:796
Addr unused_3_header
void func_8013A4D0(void)
Definition imgfx.c:267
struct ImgFXIntVars::@128 overlay
u8 * ImgFXAnimOffsets[]
Definition imgfx.c:199
void imgfx_release_instance_chain(u32 idx)
Definition imgfx.c:393
Addr get_in_bed_header
f32 raw[2][4]
Definition imgfx.c:49
Addr unused_1_header
s32 * data
Definition imgfx.c:96
Addr flutter_down_header
u8 arrayIdx
Definition imgfx.c:69
s16 nextIdx
Definition imgfx.c:81
u16 ImgFXVtxBufferCapacity
Definition imgfx.c:144
u8 * curAnimOffset
Definition imgfx.c:89
Gfx DefaultImgFXSetupGfx[]
Definition imgfx.c:146
struct ImgFXFloatVars::@130 wavy
Addr flip_card_3_header
HeapNode heap_spriteHead
Definition heaps3.c:4
void imgfx_update(u32 idx, ImgFXType type, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 flags)
Definition imgfx.c:487
void imgfx_init_instance(ImgFXState *state)
Definition imgfx.c:453
Addr tutankoopa_swirl_2_header
Addr shock_header
Addr cymbal_crush_header
void imgfx_cache_instance_data(ImgFXState *state)
Definition imgfx.c:421
BSS ImgFXCacheEntry ImgFXDataCache[8]
Definition imgfx.c:121
char unk_62[0x2]
Definition imgfx.c:88
struct ImgFXIntVars::@127 hologram
Color_RGBA8 * colorBuf
Definition imgfx.c:86
char unk_18[0x4]
Definition imgfx.c:83
void imgfx_mesh_make_wavy(ImgFXState *state)
Definition imgfx.c:1804
u8 staleCooldownTimer
Definition imgfx.c:97
BSS ImgFXWorkingTexture ImgFXCurrentTexture
Definition imgfx.c:116
void imgfx_mesh_anim_update(ImgFXState *state)
Definition imgfx.c:1255
void imgfx_make_mesh(ImgFXState *state)
Definition imgfx.c:759
Addr tutankoopa_swirl_1_header
Addr spirit_capture_header
u8 tc[2]
Definition imgfx.h:9
s16 ob[3]
Definition imgfx.h:8
u16 keyframesCount
Definition imgfx.h:19
ImgFXVtx * keyframesOffset
Definition imgfx.h:15
s8 cn[3]
Definition imgfx.h:10
Gfx * gfxOffset
Definition imgfx.h:16
#define PM_CC_0A
Definition macros.h:285
#define PM_CC_05
Definition macros.h:280
#define PM_CC_5D
Definition macros.h:504
#define PM_CC_59
Definition macros.h:499
#define PM_CC_0C
Definition macros.h:289
#define PM_CC_0B
Definition macros.h:287
#define BSS
Definition macros.h:7
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define PM_CC_5B
Definition macros.h:502
#define PM_CC_5A
Definition macros.h:500
#define PM_CC_5E
Definition macros.h:505
#define PM_CC_IMGFX_COLOR_FILL
Definition macros.h:447
#define MAX_IMGFX_INSTANCES
Definition macros.h:98
#define PM_CC_0D
Definition macros.h:288
#define PM_CC_5C
Definition macros.h:503
#define VIRTUAL_TO_PHYSICAL(addr)
Definition macros.h:47
#define PM_CC_12
Definition macros.h:295
#define PM_CC_IMGFX_HOLOGRAM
Definition macros.h:448
#define PM_CC_02
Definition macros.h:277
void create_shading_palette(Matrix4f mtx, s32 uls, s32 ult, s32 lrs, s32 lrt, s32 alpha, s32)
u8 Addr[]
Linker symbol address, as in ld_addrs.h.
Definition types.h:16
GameStatus * gGameStatusPtr
Definition main_loop.c:32
Camera gCameras[4]
Definition cam_main.c:17
Gfx * gMainGfxPos
Definition cam_main.c:15
u16 gMatrixListPos
Definition main_loop.c:45
SpriteShadingProfile * gSpriteShadingProfile
s32 gCurrentCameraID
Definition cam_math.c:4
s32 gCurrentDisplayContextIndex
Definition main_loop.c:47
DisplayContext * gDisplayContext
Definition cam_main.c:16
s16 gCurrentCamID
Definition cam_main.c:13