Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
43F0.c
Go to the documentation of this file.
1#include "common.h"
2#include "nu/nusys.h"
3#include <string.h>
4
6
7f32 sCosineTable[] = {
8 0.0f, 0.017452f, 0.034899f, 0.052336f, 0.069756f, 0.087156f, 0.104528f, 0.121869f, 0.139173f,
9 0.156434f, 0.173648f, 0.190809f, 0.207912f, 0.224951f, 0.241922f, 0.258819f, 0.275637f, 0.292372f, 0.309017f,
10 0.325568f, 0.34202f, 0.358368f, 0.374607f, 0.390731f, 0.406737f, 0.422618f, 0.438371f, 0.45399f, 0.469472f,
11 0.48481f, 0.5f, 0.515038f, 0.529919f, 0.544639f, 0.559193f, 0.573576f, 0.587785f, 0.601815f, 0.615661f, 0.62932f,
12 0.642788f, 0.656059f, 0.669131f, 0.681998f, 0.694658f, 0.707107f, 0.71934f, 0.731354f, 0.743145f, 0.75471f,
13 0.766044f, 0.777146f, 0.788011f, 0.798636f, 0.809017f, 0.819152f, 0.829038f, 0.838671f, 0.848048f, 0.857167f,
14 0.866025f, 0.87462f, 0.882948f, 0.891007f, 0.898794f, 0.906308f, 0.913545f, 0.920505f, 0.927184f, 0.93358f,
15 0.939693f, 0.945519f, 0.951057f, 0.956305f, 0.961262f, 0.965926f, 0.970296f, 0.97437f, 0.978148f, 0.981627f,
16 0.984808f, 0.987688f, 0.990268f, 0.992546f, 0.994522f, 0.996195f, 0.997564f, 0.99863f, 0.999391f, 0.999848f, 1.0f
17};
18
19// Digits for bases up to 36
21 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
22 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
23 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
24 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
25};
26
27u32 gRandSeed = 1;
28
29f32 sAtanFactors[] = {
30 1.0f, 1.273187f, 1.27303f, 1.272768f, 1.272402f, 1.271932f, 1.271358f, 1.270681f, 1.269902f, 1.269021f, 1.268038f,
31 1.266956f, 1.265774f, 1.264494f, 1.263116f, 1.261643f, 1.260075f, 1.258413f, 1.256659f, 1.254815f, 1.252881f,
32 1.250859f, 1.248752f, 1.24656f, 1.244285f, 1.241929f, 1.239494f, 1.236981f, 1.234393f, 1.231731f, 1.228997f,
33 1.226192f, 1.22332f, 1.220382f, 1.217379f, 1.214315f, 1.211189f, 1.208006f, 1.204766f, 1.201471f, 1.198124f,
34 1.194727f, 1.191281f, 1.187787f, 1.18425f, 1.180669f, 1.177047f, 1.173386f, 1.169687f, 1.165952f, 1.162184f,
35 1.158384f, 1.154553f, 1.150693f, 1.146806f, 1.142893f, 1.138957f, 1.134998f, 1.131018f, 1.127019f, 1.123002f,
36 1.118969f, 1.11492f, 1.110858f, 1.106783f, 1.102697f, 1.098601f, 1.094496f, 1.090384f, 1.086266f, 1.082142f,
37 1.078014f, 1.073883f, 1.06975f, 1.065616f, 1.061482f, 1.057348f, 1.053216f, 1.049087f, 1.04496f, 1.040838f,
38 1.036721f, 1.03261f, 1.028504f, 1.024406f, 1.020316f, 1.016234f, 1.01216f, 1.008097f, 1.004043f, 1.0f
39};
40
41Gfx D_80074580[] = {
42 gsDPPipeSync(),
43 gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_OFF),
44 gsDPSetCycleType(G_CYC_1CYCLE),
45 gsDPSetTexturePersp(G_TP_NONE),
46 gsDPSetTextureDetail(G_TD_CLAMP),
47 gsDPSetTextureLOD(G_TL_TILE),
48 gsDPSetTextureFilter(G_TF_POINT),
49 gsDPSetTextureLUT(G_TT_NONE),
50 gsDPSetTextureConvert(G_TC_FILT),
51 gsSPEndDisplayList(),
52};
53
54void dma_write_block(Addr dramAddr, u32 devAddr, s32 size);
55
56#define ROM_CHUNK_SIZE 0x2000
57
58f32 length2D(f32 x, f32 y) {
59 return sqrtf(SQ(x) + SQ(y));
60}
61
62HeapNode* _heap_create(HeapNode* addr, u32 size) {
63 if (size < 32) {
64 return (HeapNode*)-1;
65 } else {
66 HeapNode* heapNode = (HeapNode*)ALIGN16((u32)addr);
67
68 size -= ((u8*)heapNode - (u8*)addr);
69 heapNode->next = NULL;
70 heapNode->length = size - sizeof(HeapNode);
71 heapNode->allocated = 0;
72 heapNode->capacity = size;
73 return heapNode;
74 }
75}
76
77void* _heap_malloc(HeapNode* head, u32 size) {
78 HeapNode* nextHeapNode;
79 HeapNode* pPrevHeapNode = NULL;
80 u32 newBlockSize;
81 u32 curBlockLength;
82 HeapNode* curHeapNode;
83 u32 smallestBlockFound;
84 u16 HeapEntryID;
85 u16 HeapEntryID2;
86
87 // must allocate 16 bytes or more at minimum or fail
88 size = ALIGN16(size);
89 if (!size) {
90 debug_printf("warning: attempt to malloc less than 16 bytes\n");
91 return NULL;
92 }
93
94 smallestBlockFound = 0;
95 nextHeapNode = NULL;
96
97 // find the smallest block we can fit into in the free list
98 for (curHeapNode = head; ; curHeapNode = curHeapNode->next) {
99 if (!curHeapNode->allocated) {
100 curBlockLength = curHeapNode->length;
101 if ((curBlockLength >= size) && (curBlockLength < smallestBlockFound || !smallestBlockFound)) {
102 pPrevHeapNode = curHeapNode;
103 smallestBlockFound = curBlockLength;
104 nextHeapNode = curHeapNode->next;
105 }
106 }
107 if (!curHeapNode->next) {
108 break;
109 }
110 }
111
112 // find out the required block size with header
113 newBlockSize = size + sizeof(HeapNode);
114
115 // if we found a block see if we need to split it up
116 if (smallestBlockFound) {
117 if (smallestBlockFound >= newBlockSize) {
118 // update previous to the proper size for the block being returned
119 pPrevHeapNode->next = (HeapNode*)((u8*)pPrevHeapNode + newBlockSize);
120 pPrevHeapNode->length = size;
121
122 // update the entry id on allocation
123 HeapEntryID = heap_nextMallocID;
124 pPrevHeapNode->allocated = TRUE;
125 heap_nextMallocID = HeapEntryID + 1;
126 pPrevHeapNode->entryID = HeapEntryID;
127
128 // setup the new heap block entry
129 curHeapNode = pPrevHeapNode->next;
130 curHeapNode->next = nextHeapNode;
131 curHeapNode->length = smallestBlockFound - newBlockSize;
132 curHeapNode->allocated = FALSE;
133 } else {
134 // take this entry out of the free linked list and mark as allocated
135 pPrevHeapNode->next = nextHeapNode;
136 pPrevHeapNode->length = smallestBlockFound;
137
138 // update the entry id on allocation
139 // note, usage of a single ID from above will result in wrong code
140 HeapEntryID2 = heap_nextMallocID;
141 pPrevHeapNode->allocated = TRUE;
142 heap_nextMallocID = HeapEntryID2 + 1;
143 pPrevHeapNode->entryID = HeapEntryID2;
144 }
145 return (u8*)pPrevHeapNode + sizeof(HeapNode);
146 }
147 debug_printf("warning: out of memory\n");
148 return NULL;
149}
150
151void* _heap_malloc_tail(HeapNode* head, u32 size) {
152 HeapNode* curNode;
153 u32 newNodeSize;
154 u32 foundNodeLength;
155 HeapNode* foundNode;
156 HeapNode* nextNode;
157
158 size = ALIGN16(size);
159 foundNode = NULL;
160
161 // make sure we have a size to allocate
162 if (!size) {
163 debug_printf("warning: attempt to malloc less than 16 bytes\n");
164 return NULL;
165 }
166
167 foundNodeLength = 0;
168 nextNode = NULL;
169
170 // find the smallest block we can fit into
171 for (curNode = head; ; curNode = curNode->next) {
172 if (!curNode->allocated) {
173 if (curNode->length >= size) {
174 foundNode = curNode;
175 foundNodeLength = curNode->length;
176 nextNode = curNode->next;
177 }
178 }
179
180 if (!curNode->next) {
181 break;
182 }
183 }
184
185 newNodeSize = size + sizeof(HeapNode);
186 if (foundNodeLength != 0) {
187 curNode = foundNode;
188
189 // we found a block to use, see if we can split it and return a portion
190 // or if we just need to return the whole block
191 if (foundNodeLength >= newNodeSize) {
192 // add a free block before this one
193 // this is where this function differs from heap_malloc, it returns
194 // the end of the block instead of the beginning when splitting it up
195 curNode->next = (HeapNode*)((u8*)curNode + foundNodeLength - size);
196 curNode->length = foundNodeLength - newNodeSize;
197 curNode->allocated = FALSE;
198
199 curNode = curNode->next;
200 curNode->next = nextNode;
201 curNode->length = size;
202 curNode->allocated = TRUE;
203
204 } else {
205 // just return this actual block
206 curNode->next = nextNode;
207 curNode->length = foundNodeLength;
208 curNode->allocated = TRUE;
209 }
210
211 return (u8*)curNode + sizeof(HeapNode);
212 }
213
214 // did not find a block
215 debug_printf("warning: out of memory\n");
216 return NULL;
217}
218
219u32 _heap_free(HeapNode* heapNodeList, void* addrToFree) {
220 u32 curNodeLength;
221 HeapNode* nextNode;
222 HeapNode* nodeToFreeHeader;
223 HeapNode* tempNode;
224 HeapNode* outNode;
225
226 // if no address to free then return
227 if (addrToFree == NULL) {
228 return TRUE;
229 }
230
231 // if we are not allocated then ignore this request
232 nodeToFreeHeader = (HeapNode*)((u8*)addrToFree - sizeof(HeapNode));
233 if (!nodeToFreeHeader->allocated) {
234 return TRUE;
235 }
236
237 nextNode = nodeToFreeHeader->next;
238 curNodeLength = nodeToFreeHeader->length;
239 outNode = nextNode;
240
241 // see if the next node after us is allocated, if not then adjust our size
242 // to include it and point nextNode to be the node after as it must be allocated
243 if (nextNode && !nextNode->allocated) {
244 curNodeLength += nextNode->length + sizeof(HeapNode);
245 nextNode = nextNode->next;
246 }
247
248 // walk the full heap node list looking for the block before our current entry
249 tempNode = heapNodeList;
250 while (TRUE) {
251 // get the pointer to the next block, if it matches the block being freed then
252 // exit the search
253 heapNodeList = tempNode->next;
254 if (heapNodeList == nodeToFreeHeader) {
255
256 // we found the node prior to us, if it is not allocated then adjust our total
257 // size to include it and change the header node pointer to point that block
258 if (!tempNode->allocated) {
259 curNodeLength += sizeof(HeapNode) + tempNode->length;
260 nodeToFreeHeader = tempNode;
261 }
262 break;
263 }
264
265 // if the node being freed is before the current node being looked at then we
266 // moved past our current node, bail out. Also bail if we hit the end of the list
267 if (nodeToFreeHeader < tempNode || !heapNodeList) {
268 break;
269 }
270
271 // move to the next node
272 tempNode = tempNode->next;
273 }
274
275 // update the node being free'd with a proper size and pointer to the next node that is
276 // allocated
277 outNode = nodeToFreeHeader;
278 outNode->next = nextNode;
279 outNode->length = curNodeLength;
280 outNode->allocated = FALSE;
281 return FALSE;
282}
283
284void* _heap_realloc(HeapNode* heapNodeList, void* addr, u32 newSize) {
285 u32 newSizeAligned;
286 HeapNode* nextNode;
287 HeapNode* curHeapAlloc;
288 HeapNode* newFreeBlock;
289 u32 newNodeLength;
290 HeapNode* nodeToUpdate;
291
292 curHeapAlloc = (HeapNode*)((u8*)addr - sizeof(HeapNode));
293 newSizeAligned = ALIGN16(newSize);
294
295 // check if the realloc is on an allocated node otherwise fail
296 if (!curHeapAlloc->allocated) {
297 return NULL;
298 }
299
300 nextNode = curHeapAlloc->next;
301 newNodeLength = curHeapAlloc->length;
302
303 // if we have a node after us and it isn't allocated then
304 // adjust the length and next node pointers to include the node after us
305 nodeToUpdate = nextNode;
306 if (nextNode && !nextNode->allocated) {
307 nextNode = nextNode->next;
308 newNodeLength += sizeof(HeapNode) + nodeToUpdate->length;
309 }
310
311 // check if the current block or current + next block (if free) are too small
312 nodeToUpdate = curHeapAlloc;
313 if (newNodeLength < newSizeAligned) {
314 // too small, allocatr a new node, copy data to it then free the current one
315 curHeapAlloc = _heap_malloc(heapNodeList, newSizeAligned);
316 if (curHeapAlloc == NULL) {
317 return NULL;
318 }
319
320 // minor interest note, copy the size of the newly allocated size
321 // instead of just how much data used to be stored, this results in copying
322 // excessive data
323 memcpy(curHeapAlloc, addr, newSizeAligned);
324 _heap_free(heapNodeList, addr);
325 return curHeapAlloc;
326 }
327
328 // see if there is room to add a new free block after us
329 if (newSizeAligned + sizeof(HeapNode) < newNodeLength) {
330 // room for a free block, create it
331 newFreeBlock = (HeapNode*)((u8*)addr + newSizeAligned);
332
333 // update current node
334 nodeToUpdate->next = newFreeBlock;
335 nodeToUpdate->length = newSizeAligned;
336
337 // create new node after the current one
338 nodeToUpdate = newFreeBlock;
339 nodeToUpdate->next = nextNode;
340 nodeToUpdate->length = (newNodeLength - newSizeAligned) - sizeof(HeapNode);
341 nodeToUpdate->allocated = FALSE;
342 } else {
343 // no room, update our next and length
344 nodeToUpdate->next = nextNode;
345 nodeToUpdate->length = newNodeLength;
346 }
347
348 // return the location we were at
349 return addr;
350}
351
352f32 cosine(s16 arg0) {
353 s16 temp360;
354 s16 idx;
355
356 temp360 = arg0 % 360;
357
358 if (temp360 < 0) {
359 temp360 += 360;
360 }
361
362 idx = temp360 % 180;
363 if (idx > 90) {
364 idx = 180 - idx;
365 }
366
367 if (temp360 >= 180) {
368 return -sCosineTable[idx];
369 } else {
370 return sCosineTable[idx];
371 }
372}
373
374s32 sign(s32 val) {
375 s32 sign = -1;
376
377 if (val >= 0) {
378 sign = val > 0;
379 }
380 return sign;
381}
382
383// Writes integer in base as a string to dest. base can range from 2 to 36
384char* int_to_string(s32 integer, char* dest, s32 base) {
385 u8 string[40]; // Even for binary this is a little long: 34 would suffice
386 s32 i = ARRAY_COUNT(string) - 2;
387 s32 negative = FALSE;
388 s64 longInteger = integer;
389
390 // handle negative integers
391 if (longInteger < 0) {
392 negative = TRUE;
393 longInteger *= -1;
394 }
395
396 // null-terminate string
397 string[ARRAY_COUNT(string) - 1] = '\0';
398
399 // extract digits, filling string from the back
400 while (TRUE) {
401 string[i] = sIntegerDigits[longInteger % base];
402 longInteger /= base;
403 if (longInteger == 0 || i == 0) {
404 break;
405 }
406 i--;
407 }
408
409 // Add - to negatives
410 if (negative) {
411 i--;
412 string[i] = '-';
413 }
414
415 // copy only populated part of string
416 strcpy(dest, &string[i]);
417
418 return dest;
419}
420
421void mem_clear(void* data, s32 numBytes) {
422 u8* addressableData = data;
423
424 while (numBytes > 0) {
425 *addressableData++ = 0;
426 numBytes--;
427 }
428}
429
430void transform_point(Matrix4f mtx, f32 inX, f32 inY, f32 inZ, f32 inS, f32* outX, f32* outY, f32* outZ, f32* outW) {
431 *outX = (mtx[0][0] * inX) + (mtx[1][0] * inY) + (mtx[2][0] * inZ) + mtx[3][0];
432 *outY = (mtx[0][1] * inX) + (mtx[1][1] * inY) + (mtx[2][1] * inZ) + mtx[3][1];
433 *outZ = (mtx[0][2] * inX) + (mtx[1][2] * inY) + (mtx[2][2] * inZ) + mtx[3][2];
434 *outW = (mtx[0][3] * inX) + (mtx[1][3] * inY) + (mtx[2][3] * inZ) + mtx[3][3];
435}
436
438 bcopy(src, dest, sizeof(Matrix4f));
439}
440
441// maybe u32
442u32 dma_copy(Addr romStart, Addr romEnd, void* vramDest) {
443 u32 length = romEnd - romStart;
444 s32 i;
445
446 osInvalICache(vramDest, length);
447
448 for (i = 0; i + ROM_CHUNK_SIZE < length; i += ROM_CHUNK_SIZE) {
449 nuPiReadRom((u32)romStart + i, vramDest + i, ROM_CHUNK_SIZE);
450 }
451
452 if (i != length) {
453 nuPiReadRom((u32)romStart + i, vramDest + i, length - i);
454 }
455
456 return length;
457}
458
459s32 dma_write(Addr romStart, Addr romEnd, void* vramDest) {
460 u32 length = romEnd - romStart;
461 s32 i;
462
463 for (i = 0; i + ROM_CHUNK_SIZE < length; i += ROM_CHUNK_SIZE) {
464 dma_write_block(romStart + i, (u32)vramDest + i, ROM_CHUNK_SIZE);
465 }
466
467 if (i != length) {
468 dma_write_block(romStart + i, (u32)vramDest + i, length - i);
469 }
470
471 return length;
472}
473
474void dma_write_block(Addr dramAddr, u32 devAddr, s32 size) {
475 OSIoMesg osIoMesg;
476 OSMesg osMesg;
477 OSMesgQueue osMesgQueue;
478
479 osWritebackDCache(dramAddr, size);
480 osCreateMesgQueue(&osMesgQueue, &osMesg, 1);
481
482 osIoMesg.hdr.pri = 0;
483 osIoMesg.hdr.retQueue = &osMesgQueue;
484 osIoMesg.dramAddr = dramAddr;
485 osIoMesg.devAddr = devAddr;
486 osIoMesg.size = size;
487
488 osEPiStartDma(nuPiCartHandle, &osIoMesg, 1);
489 osRecvMesg(&osMesgQueue, &osMesg, 1);
490}
491
492// advance the global RNG via LCG algorithm and return a random integer [0,2^32)
493u32 advance_rng(void) {
494 gRandSeed = gRandSeed * 0x5D588B65 + 1;
495
497
498 return gRandSeed;
499}
500
501// return a random float [0,1)
502f32 rand_float(void) {
503 return (advance_rng() & 0x7FFF) / 32768.0;
504}
505
506// return a random integer [0,max]
507s32 rand_int_internal(u32 max) {
508 u32 partitionSize = 0xFFFFFFFF;
509 u32 maxPlusOne = max + 1;
510 u32 result;
511
512 // split [0,2^32) into ``maxPlusOne`` equally sized partitions
513 // [0, partitionSize), [partitionSize, 2*partitionSize), ... [maxPlusOne*partitionSize, 2^32)
514 partitionSize /= maxPlusOne;
515 if (partitionSize == 0) {
516 partitionSize = 1;
517 }
518
519 // numbers in the leftover [maxPlusOne*partitionSize, 2^32) are rejected as they would return maxPlusOne
520 // this ensures the result is [0,max] whilst also ensuring each partition is the same size and equally probable
521 do {
522 // determine which partition the random number is in by dividing it by partitionSize
523 result = advance_rng() / partitionSize;
524 } while (result >= maxPlusOne);
525
526 return result;
527}
528
529// return a random integer [0,|max|] with specific distributions for |max| = 1 and |max| = 100
530s32 rand_int(s32 max) {
531 s32 ret = 0;
532
533 max = abs(max);
534
535 if (max != 0) {
536 switch (max) {
537 case 1:
538 // due to the off-by-one input of 1000 and the > operator being used,
539 // there is a 501/1001 chance of returning 0 and a 500/1001 chance of returning 1
540 // (assuming statistical randomness of rand_int_internal).
541 ret = rand_int_internal(1000) > 500;
542 break;
543 default:
544 ret = rand_int_internal(max);
545 break;
546 case 100:
547 ret = rand_int_internal(1009) / 10;
548 break;
549 }
550 }
551
552 return ret;
553}
554
555f32 signF(f32 val) {
556 f32 sign;
557
558 if (!(val > 0.0f)) {
559 sign = -1.0f;
560 if (!(val < 0.0f)) {
561 sign = 0.0f;
562 }
563 } else {
564 sign = 1.0f;
565 }
566
567 return sign;
568}
569
570s32 round(f32 x) {
571 if (!(x >= 0.0f)) {
572 return -(s32)(0.5 - x);
573 } else {
574 return (s32)(0.5 + x);
575 }
576}
577
578f32 clamp_angle(f32 theta) {
579 if (fabsf(theta) > 3600.0f) {
580 s32 thetaInt = theta;
581
582 if (thetaInt >= 0) {
583 thetaInt = -(thetaInt / 360 * 360) + thetaInt;
584 } else {
585 thetaInt = -thetaInt;
586 thetaInt = (thetaInt / 360 * 360) - thetaInt;
587 }
588
589 return thetaInt;
590 }
591
592 do {
593 if (theta < 0.0f) {
594 theta += 360.0f;
595 }
596 if (theta >= 360.0f) {
597 theta -= 360.0f;
598 }
599 } while (!(theta >= 0.0f) || !(theta < 360.0f));
600
601 return theta;
602}
603
604f32 get_clamped_angle_diff(f32 a, f32 b) {
605 if (fabsf(b - a) >= 180.0f) {
606 if (b < a) {
607 b += 360.0f;
608 } else {
609 b -= 360.0f;
610 }
611 }
612 return b - a;
613}
614
615f32 atan2(f32 startX, f32 startZ, f32 endX, f32 endZ) {
616 f32 dx = endX - startX;
617 f32 dz = endZ - startZ;
618 f32 absXDiff = fabsf(dx);
619 f32 absZDiff = fabsf(dz);
620 f32 ret;
621
622 if (absZDiff < absXDiff) {
623 ret = (absZDiff / absXDiff) * 45.0f;
624 ret *= sAtanFactors[round(2.0f * ret)];
625 if (dx >= 0.0f) {
626 if (dz >= 0.0f) {
627 return ret + 90.0f;
628 } else {
629 return 90.0f - ret;
630 }
631 }
632 if (dz >= 0.0f) {
633 return 270.0f - ret;
634 } else {
635 return ret + 270.0f;
636 }
637 } else {
638 if (absZDiff == 0.0f) {
639 return 0.0f;
640 }
641 ret = (absXDiff / absZDiff) * 45.0f;
642 ret *= sAtanFactors[round(2.0f * ret)];
643 if (dz >= 0.0f) {
644 if (dx >= 0.0f) {
645 return 180.0f - ret;
646 } else {
647 return ret + 180.0f;
648 }
649 } else if (!(dx >= 0.0f)) {
650 return 360.0f - ret;
651 }
652 }
653 return ret;
654}
655
659
661 f32 traceNormalX = gGameStatusPtr->playerGroundTraceNormal.x;
662 f32 traceNormalZ = gGameStatusPtr->playerGroundTraceNormal.z;
663 f32 sqrt = sqrtf(SQ(traceNormalX) + SQ(traceNormalZ));
664
665 return atan2(0.0f, 0.0f, sqrt, -gGameStatusPtr->playerGroundTraceNormal.y);
666}
667
668f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by) {
669 f32 xDiff = bx - ax;
670 f32 yDiff = by - ay;
671
672 return sqrtf(SQ(xDiff) + SQ(yDiff));
673}
674
675f32 dist3D(f32 ax, f32 ay, f32 az, f32 bx, f32 by, f32 bz) {
676 f32 xDiff = bx - ax;
677 f32 yDiff = by - ay;
678 f32 zDiff = bz - az;
679
680 return sqrtf(SQ(xDiff) + SQ(yDiff) + SQ(zDiff));
681}
682
683void add_vec2D_polar(f32* x, f32* y, f32 r, f32 theta) {
684 f32 sinTheta;
685 f32 cosTheta;
686
687 sin_cos_rad(DEG_TO_RAD(theta), &sinTheta, &cosTheta);
688 *x += r * sinTheta;
689 *y -= r * cosTheta;
690}
691
692// Effectively computes theta % 0x100000
694 f32 ret = theta;
695
696 if (theta >= 0x100000 || theta <= -0x100000) {
697 ret = theta / 0x100000;
698 ret = theta - (f32)(s32)ret * 0x100000;
699 }
700
701 return (s32) ret;
702}
703
704void sin_cos_rad(f32 theta, f32* outSinTheta, f32* outCosTheta) {
705 u16 binang = _wrap_trig_lookup_value(RAD_TO_BINANG(theta));
706
707 *outSinTheta = sins(binang) * SHT_MINV;
708 *outCosTheta = coss(binang) * SHT_MINV;
709}
710
711f32 sin_rad(f32 theta) {
712 return sins(_wrap_trig_lookup_value(RAD_TO_BINANG(theta))) * SHT_MINV;
713}
714
715f32 cos_rad(f32 theta) {
716 return coss(_wrap_trig_lookup_value(RAD_TO_BINANG(theta))) * SHT_MINV;
717}
718void sin_cos_deg(f32 theta, f32* outSinTheta, f32* outCosTheta) {
719 u16 binang = _wrap_trig_lookup_value(DEG_TO_BINANG(theta));
720
721 *outSinTheta = sins(binang) * SHT_MINV;
722 *outCosTheta = coss(binang) * SHT_MINV;
723}
724
725f32 sin_deg(f32 theta) {
726 return sins(_wrap_trig_lookup_value(DEG_TO_BINANG(theta))) * SHT_MINV;
727}
728
729f32 cos_deg(f32 theta) {
730 return coss(_wrap_trig_lookup_value(DEG_TO_BINANG(theta))) * SHT_MINV;
731}
732
733f32 update_lerp(s32 easing, f32 start, f32 end, s32 elapsed, s32 duration) {
734 s32 timeLeft;
735 f32 absMag;
736
737 if (duration == 0) {
738 return end;
739 }
740
741 switch (easing) {
742 case EASING_LINEAR:
743 return start + (end - start) * elapsed / duration;
745 return start + SQ(elapsed) * (end - start) / SQ(duration);
746 case EASING_CUBIC_IN:
747 return start + CUBE(elapsed) * (end - start) / CUBE(duration);
749 return start + QUART(elapsed) * (end - start) / QUART(duration);
751 return end - ((end - start) * cos_rad(((f32)elapsed / duration) * PI_D * 4.0) * (duration - elapsed) *
752 (duration - elapsed)) / SQ((f32)duration);
754 return end - ((end - start) * cos_rad((((f32)SQ(elapsed) / duration) * PI_D * 4.0) / 15.0) * (duration - elapsed) *
755 (duration - elapsed)) / SQ((f32)duration);
757 timeLeft = duration - elapsed;
758 return start + (end - start) - ((SQ(timeLeft) * (end - start))) / SQ(duration);
759 case EASING_CUBIC_OUT:
760 timeLeft = duration - elapsed;
761 return start + (end - start) - ((CUBE(timeLeft) * (end - start))) / CUBE(duration);
763 timeLeft = duration - elapsed;
764 return start + (end - start) - ((QUART(timeLeft) * (end - start))) / QUART(duration);
766 absMag = cos_rad((((f32)SQ(elapsed) / duration) * PI_D * 4.0) / 40.0) * (duration - elapsed) *
767 (duration - elapsed) / SQ((f32)duration);
768 if (absMag < 0.0f) {
769 absMag = -absMag;
770 }
771 return end - (end - start) * absMag;
773 return start + (end - start) * (1.0 - cos_rad(((f32)elapsed * PI_D) / (f32)duration)) * 0.5;
774 case EASING_SIN_OUT:
775 return start + (end - start) * sin_rad(((f32)elapsed * (PI_D / 2)) / (f32)duration);
776 case EASING_COS_IN:
777 return start + (end - start) * (1.0 - cos_rad(((f32)elapsed * (PI_D / 2)) / (f32)duration));
778 }
779
780 return 0.0f;
781}
782
783void appendGfx_startup_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 left, u16 top, u16 right, u16 bottom) {
784 gDPPipeSync(gMainGfxPos++);
785 gSPDisplayList(gMainGfxPos++, D_80074580);
786
787 if (a == 255) {
788 gDPSetRenderMode(gMainGfxPos++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
790 } else {
791 gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
792 gDPSetCombineMode(gMainGfxPos++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
793 }
794
795 gDPSetPrimColor(gMainGfxPos++, 0, 0, r, g, b, a);
796 gDPFillRectangle(gMainGfxPos++, left, top, right, bottom);
797
798 gDPPipeSync(gMainGfxPos++);
799 gDPSetRenderMode(gMainGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
800 gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
801}
802
803void startup_draw_prim_rect_COPY(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a) {
804 u16 temp;
805
806 if (right < left) {
807 temp = right;
808 right = left;
809 left = temp;
810 }
811
812 if (bottom < top) {
813 temp = bottom;
814 bottom = top;
815 top = temp;
816 }
817
818 appendGfx_startup_prim_rect(r, g, b, a, left, top, right, bottom);
819}
820
821void startup_draw_prim_rect(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a) {
822 u16 temp;
823
824 if (right < left) {
825 temp = right;
826 right = left;
827 left = temp;
828 }
829
830 if (bottom < top) {
831 temp = bottom;
832 bottom = top;
833 top = temp;
834 }
835
836 appendGfx_startup_prim_rect(r, g, b, a, left, top, right, bottom);
837}
f32 sin_rad(f32 theta)
Definition 43F0.c:711
void startup_draw_prim_rect_COPY(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a)
Definition 43F0.c:803
void startup_draw_prim_rect(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a)
Definition 43F0.c:821
f32 update_lerp(s32 easing, f32 start, f32 end, s32 elapsed, s32 duration)
Definition 43F0.c:733
void appendGfx_startup_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 left, u16 top, u16 right, u16 bottom)
Definition 43F0.c:783
u32 advance_rng(void)
Definition 43F0.c:493
Gfx D_80074580[]
Definition 43F0.c:41
u16 _wrap_trig_lookup_value(f32 theta)
Definition 43F0.c:693
f32 get_clamped_angle_diff(f32 a, f32 b)
Definition 43F0.c:604
f32 length2D(f32 x, f32 y)
Definition 43F0.c:58
s32 round(f32 x)
Definition 43F0.c:570
u8 sIntegerDigits[]
Definition 43F0.c:20
f32 dist3D(f32 ax, f32 ay, f32 az, f32 bx, f32 by, f32 bz)
Definition 43F0.c:675
f32 cosine(s16 arg0)
Definition 43F0.c:352
s32 dma_write(Addr romStart, Addr romEnd, void *vramDest)
Definition 43F0.c:459
u32 dma_copy(Addr romStart, Addr romEnd, void *vramDest)
Definition 43F0.c:442
void dma_write_block(Addr dramAddr, u32 devAddr, s32 size)
Definition 43F0.c:474
f32 sCosineTable[]
Definition 43F0.c:7
f32 signF(f32 val)
Definition 43F0.c:555
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:668
void sin_cos_deg(f32 theta, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:718
#define ROM_CHUNK_SIZE
Definition 43F0.c:56
void * _heap_malloc(HeapNode *head, u32 size)
Definition 43F0.c:77
f32 rand_float(void)
Definition 43F0.c:502
f32 cos_rad(f32 theta)
Definition 43F0.c:715
u32 gRandSeed
Definition 43F0.c:27
s32 rand_int_internal(u32 max)
Definition 43F0.c:507
void * _heap_malloc_tail(HeapNode *head, u32 size)
Definition 43F0.c:151
void * _heap_realloc(HeapNode *heapNodeList, void *addr, u32 newSize)
Definition 43F0.c:284
u32 _heap_free(HeapNode *heapNodeList, void *addrToFree)
Definition 43F0.c:219
void copy_matrix(Matrix4f src, Matrix4f dest)
Definition 43F0.c:437
u16 heap_nextMallocID
Definition 43F0.c:5
char * int_to_string(s32 integer, char *dest, s32 base)
Definition 43F0.c:384
f32 get_player_normal_pitch(void)
Definition 43F0.c:660
f32 sAtanFactors[]
Definition 43F0.c:29
void sin_cos_rad(f32 theta, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:704
HeapNode * _heap_create(HeapNode *addr, u32 size)
Definition 43F0.c:62
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:683
f32 get_player_normal_yaw(void)
Definition 43F0.c:656
s32 sign(s32 val)
Definition 43F0.c:374
Vec3f playerGroundTraceNormal
f32 Matrix4f[4][4]
struct HeapNode * next
#define debug_printf(fmt, args...)
Definition debug_menu.h:84
#define transform_point
#define sqrtf
#define sin_deg
#define rand_int
#define clamp_angle
#define cos_deg
#define atan2
#define mem_clear
@ EASING_SIN_OUT
Definition enums.h:521
@ EASING_COS_IN
Definition enums.h:522
@ EASING_CUBIC_IN
Definition enums.h:512
@ EASING_CUBIC_OUT
Definition enums.h:515
@ EASING_QUARTIC_IN
Definition enums.h:513
@ EASING_COS_BOUNCE
Definition enums.h:519
@ EASING_COS_SLOW_OVERSHOOT
Definition enums.h:517
@ EASING_QUADRATIC_IN
Definition enums.h:511
@ EASING_COS_IN_OUT
Definition enums.h:520
@ EASING_QUARTIC_OUT
Definition enums.h:516
@ EASING_QUADRATIC_OUT
Definition enums.h:514
@ EASING_LINEAR
Definition enums.h:510
@ EASING_COS_FAST_OVERSHOOT
Definition enums.h:518
f32 fabsf(f32 f)
#define ALIGN16(val)
Definition macros.h:20
#define PM_CC_PRIM_FULL_ALPHA
Definition macros.h:287
#define PI_D
Definition macros.h:131
#define DEG_TO_BINANG(x)
Definition macros.h:136
#define SHT_MINV
Definition macros.h:141
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define QUART(x)
Definition macros.h:172
#define RAD_TO_BINANG(x)
Definition macros.h:137
#define DEG_TO_RAD(deg)
Definition macros.h:138
#define CUBE(x)
Definition macros.h:171
#define SQ(x)
Definition macros.h:170
u8 Addr[]
Linker symbol address, as in ld_addrs.h.
Definition types.h:16
GameStatus * gGameStatusPtr
Definition main_loop.c:31
Gfx * gMainGfxPos
Definition cam_main.c:14