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