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