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 // find out the required block size with header
114 newBlockSize = size + sizeof(HeapNode);
115
116 // if we found a block see if we need to split it up
117 if (smallestBlockFound) {
118 if (smallestBlockFound >= newBlockSize) {
119 // update previous to the proper size for the block being returned
120 pPrevHeapNode->next = (HeapNode*)((u8*)pPrevHeapNode + newBlockSize);
121 pPrevHeapNode->length = size;
122
123 // update the entry id on allocation
124 HeapEntryID = heap_nextMallocID;
125 pPrevHeapNode->allocated = TRUE;
126 heap_nextMallocID = HeapEntryID + 1;
127 pPrevHeapNode->entryID = HeapEntryID;
128
129 // setup the new heap block entry
130 curHeapNode = pPrevHeapNode->next;
131 curHeapNode->next = nextHeapNode;
132 curHeapNode->length = smallestBlockFound - newBlockSize;
133 curHeapNode->allocated = FALSE;
134 } else {
135 // take this entry out of the free linked list and mark as allocated
136 pPrevHeapNode->next = nextHeapNode;
137 pPrevHeapNode->length = smallestBlockFound;
138
139 // update the entry id on allocation
140 // note, usage of a single ID from above will result in wrong code
141 HeapEntryID2 = heap_nextMallocID;
142 pPrevHeapNode->allocated = TRUE;
143 heap_nextMallocID = HeapEntryID2 + 1;
144 pPrevHeapNode->entryID = HeapEntryID2;
145 }
146 return (u8*)pPrevHeapNode + sizeof(HeapNode);
147 }
148 debug_printf("warning: out of memory\n");
149 return NULL;
150}
151
152void* _heap_malloc_tail(HeapNode* head, u32 size) {
153 HeapNode* curNode;
154 u32 newNodeSize;
155 u32 foundNodeLength;
156 HeapNode* foundNode;
157 HeapNode* nextNode;
158
159 size = ALIGN16(size);
160 foundNode = NULL;
161
162 // make sure we have a size to allocate
163 if (!size) {
164 debug_printf("warning: attempt to malloc less than 16 bytes\n");
165 return NULL;
166 }
167
168 foundNodeLength = 0;
169 nextNode = NULL;
170
171 // find the smallest block we can fit into
172 for (curNode = head; ; curNode = curNode->next) {
173 if (!curNode->allocated) {
174 if (curNode->length >= size) {
175 foundNode = curNode;
176 foundNodeLength = curNode->length;
177 nextNode = curNode->next;
178 }
179 }
180
181 if (!curNode->next) {
182 break;
183 }
184 }
185
186 newNodeSize = size + sizeof(HeapNode);
187 if (foundNodeLength != 0) {
188 curNode = foundNode;
189
190 // we found a block to use, see if we can split it and return a portion
191 // or if we just need to return the whole block
192 if (foundNodeLength >= newNodeSize) {
193 // add a free block before this one
194 // this is where this function differs from heap_malloc, it returns
195 // the end of the block instead of the beginning when splitting it up
196 curNode->next = (HeapNode*)((u8*)curNode + foundNodeLength - size);
197 curNode->length = foundNodeLength - newNodeSize;
198 curNode->allocated = FALSE;
199
200 curNode = curNode->next;
201 curNode->next = nextNode;
202 curNode->length = size;
203 curNode->allocated = TRUE;
204
205 } else {
206 // just return this actual block
207 curNode->next = nextNode;
208 curNode->length = foundNodeLength;
209 curNode->allocated = TRUE;
210 }
211
212 return (u8*)curNode + sizeof(HeapNode);
213 }
214
215 // did not find a block
216 debug_printf("warning: out of memory\n");
217 return NULL;
218}
219
220u32 _heap_free(HeapNode* heapNodeList, void* addrToFree) {
221 u32 curNodeLength;
222 HeapNode* nextNode;
223 HeapNode* nodeToFreeHeader;
224 HeapNode* tempNode;
225 HeapNode* outNode;
226
227 // if no address to free then return
228 if (addrToFree == NULL) {
229 return TRUE;
230 }
231
232 // if we are not allocated then ignore this request
233 nodeToFreeHeader = (HeapNode*)((u8*)addrToFree - sizeof(HeapNode));
234 if (!nodeToFreeHeader->allocated) {
235 return TRUE;
236 }
237
238 nextNode = nodeToFreeHeader->next;
239 curNodeLength = nodeToFreeHeader->length;
240 outNode = nextNode;
241
242 // see if the next node after us is allocated, if not then adjust our size
243 // to include it and point nextNode to be the node after as it must be allocated
244 if (nextNode && !nextNode->allocated) {
245 curNodeLength += nextNode->length + sizeof(HeapNode);
246 nextNode = nextNode->next;
247 }
248
249 // walk the full heap node list looking for the block before our current entry
250 tempNode = heapNodeList;
251 while (TRUE) {
252 // get the pointer to the next block, if it matches the block being freed then
253 // exit the search
254 heapNodeList = tempNode->next;
255 if (heapNodeList == nodeToFreeHeader) {
256
257 // we found the node prior to us, if it is not allocated then adjust our total
258 // size to include it and change the header node pointer to point that block
259 if (!tempNode->allocated) {
260 curNodeLength += sizeof(HeapNode) + tempNode->length;
261 nodeToFreeHeader = tempNode;
262 }
263 break;
264 }
265
266 // if the node being freed is before the current node being looked at then we
267 // moved past our current node, bail out. Also bail if we hit the end of the list
268 if (nodeToFreeHeader < tempNode || !heapNodeList) {
269 break;
270 }
271
272 // move to the next node
273 tempNode = tempNode->next;
274 }
275
276 // update the node being free'd with a proper size and pointer to the next node that is
277 // allocated
278 outNode = nodeToFreeHeader;
279 outNode->next = nextNode;
280 outNode->length = curNodeLength;
281 outNode->allocated = FALSE;
282 return FALSE;
283}
284
285void* _heap_realloc(HeapNode* heapNodeList, void* addr, u32 newSize) {
286 u32 newSizeAligned;
287 HeapNode* nextNode;
288 HeapNode* curHeapAlloc;
289 HeapNode* newFreeBlock;
290 u32 newNodeLength;
291 HeapNode* nodeToUpdate;
292
293 curHeapAlloc = (HeapNode*)((u8*)addr - sizeof(HeapNode));
294 newSizeAligned = ALIGN16(newSize);
295
296 // check if the realloc is on an allocated node otherwise fail
297 if (!curHeapAlloc->allocated) {
298 return NULL;
299 }
300
301 nextNode = curHeapAlloc->next;
302 newNodeLength = curHeapAlloc->length;
303
304 // if we have a node after us and it isn't allocated then
305 // adjust the length and next node pointers to include the node after us
306 nodeToUpdate = nextNode;
307 if (nextNode && !nextNode->allocated) {
308 nextNode = nextNode->next;
309 newNodeLength += sizeof(HeapNode) + nodeToUpdate->length;
310 }
311
312 // check if the current block or current + next block (if free) are too small
313 nodeToUpdate = curHeapAlloc;
314 if (newNodeLength < newSizeAligned) {
315 // too small, allocatr a new node, copy data to it then free the current one
316 curHeapAlloc = _heap_malloc(heapNodeList, newSizeAligned);
317 if (curHeapAlloc == NULL) {
318 return NULL;
319 }
320
321 // minor interest note, copy the size of the newly allocated size
322 // instead of just how much data used to be stored, this results in copying
323 // excessive data
324 memcpy(curHeapAlloc, addr, newSizeAligned);
325 _heap_free(heapNodeList, addr);
326 return curHeapAlloc;
327 }
328
329 // see if there is room to add a new free block after us
330 if (newSizeAligned + sizeof(HeapNode) < newNodeLength) {
331 // room for a free block, create it
332 newFreeBlock = (HeapNode*)((u8*)addr + newSizeAligned);
333
334 // update current node
335 nodeToUpdate->next = newFreeBlock;
336 nodeToUpdate->length = newSizeAligned;
337
338 // create new node after the current one
339 nodeToUpdate = newFreeBlock;
340 nodeToUpdate->next = nextNode;
341 nodeToUpdate->length = (newNodeLength - newSizeAligned) - sizeof(HeapNode);
342 nodeToUpdate->allocated = FALSE;
343 } else {
344 // no room, update our next and length
345 nodeToUpdate->next = nextNode;
346 nodeToUpdate->length = newNodeLength;
347 }
348
349 // return the location we were at
350 return addr;
351}
352
353f32 cosine(s16 arg0) {
354 s16 temp360;
355 s16 idx;
356
357 temp360 = arg0 % 360;
358
359 if (temp360 < 0) {
360 temp360 += 360;
361 }
362
363 idx = temp360 % 180;
364 if (idx > 90) {
365 idx = 180 - idx;
366 }
367
368 if (temp360 >= 180) {
369 return -sCosineTable[idx];
370 } else {
371 return sCosineTable[idx];
372 }
373}
374
375s32 sign(s32 val) {
376 s32 sign = -1;
377
378 if (val >= 0) {
379 sign = val > 0;
380 }
381 return sign;
382}
383
384// Writes integer in base as a string to dest. base can range from 2 to 36
385char* int_to_string(s32 integer, char* dest, s32 base) {
386 u8 string[40]; // Even for binary this is a little long: 34 would suffice
387 s32 i = ARRAY_COUNT(string) - 2;
388 s32 negative = FALSE;
389 s64 longInteger = integer;
390
391 // handle negative integers
392 if (longInteger < 0) {
393 negative = TRUE;
394 longInteger *= -1;
395 }
396
397 // null-terminate string
398 string[ARRAY_COUNT(string) - 1] = '\0';
399
400 // extract digits, filling string from the back
401 while (TRUE) {
402 string[i] = sIntegerDigits[longInteger % base];
403 longInteger /= base;
404 if (longInteger == 0 || i == 0) {
405 break;
406 }
407 i--;
408 }
409
410 // Add - to negatives
411 if (negative) {
412 i--;
413 string[i] = '-';
414 }
415
416 // copy only populated part of string
417 strcpy(dest, &string[i]);
418
419 return dest;
420}
421
422void mem_clear(void* data, s32 numBytes) {
423 u8* addressableData = data;
424
425 while (numBytes > 0) {
426 *addressableData++ = 0;
427 numBytes--;
428 }
429}
430
431void transform_point(Matrix4f mtx, f32 inX, f32 inY, f32 inZ, f32 inS, f32* outX, f32* outY, f32* outZ, f32* outW) {
432 *outX = (mtx[0][0] * inX) + (mtx[1][0] * inY) + (mtx[2][0] * inZ) + mtx[3][0];
433 *outY = (mtx[0][1] * inX) + (mtx[1][1] * inY) + (mtx[2][1] * inZ) + mtx[3][1];
434 *outZ = (mtx[0][2] * inX) + (mtx[1][2] * inY) + (mtx[2][2] * inZ) + mtx[3][2];
435 *outW = (mtx[0][3] * inX) + (mtx[1][3] * inY) + (mtx[2][3] * inZ) + mtx[3][3];
436}
437
439 bcopy(src, dest, sizeof(Matrix4f));
440}
441
442// maybe u32
443u32 dma_copy(Addr romStart, Addr romEnd, void* vramDest) {
444 u32 length = romEnd - romStart;
445 s32 i;
446
447 osInvalICache(vramDest, length);
448
449 for (i = 0; i + ROM_CHUNK_SIZE < length; i += ROM_CHUNK_SIZE) {
450 nuPiReadRom((u32)romStart + i, vramDest + i, ROM_CHUNK_SIZE);
451 }
452
453 if (i != length) {
454 nuPiReadRom((u32)romStart + i, vramDest + i, length - i);
455 }
456
457 return length;
458}
459
460s32 dma_write(Addr romStart, Addr romEnd, void* vramDest) {
461 u32 length = romEnd - romStart;
462 s32 i;
463
464 for (i = 0; i + ROM_CHUNK_SIZE < length; i += ROM_CHUNK_SIZE) {
465 dma_write_block(romStart + i, (u32)vramDest + i, ROM_CHUNK_SIZE);
466 }
467
468 if (i != length) {
469 dma_write_block(romStart + i, (u32)vramDest + i, length - i);
470 }
471
472 return length;
473}
474
475void dma_write_block(Addr dramAddr, u32 devAddr, s32 size) {
476 OSIoMesg osIoMesg;
477 OSMesg osMesg;
478 OSMesgQueue osMesgQueue;
479
480 osWritebackDCache(dramAddr, size);
481 osCreateMesgQueue(&osMesgQueue, &osMesg, 1);
482
483 osIoMesg.hdr.pri = 0;
484 osIoMesg.hdr.retQueue = &osMesgQueue;
485 osIoMesg.dramAddr = dramAddr;
486 osIoMesg.devAddr = devAddr;
487 osIoMesg.size = size;
488
489 osEPiStartDma(nuPiCartHandle, &osIoMesg, 1);
490 osRecvMesg(&osMesgQueue, &osMesg, 1);
491}
492
493// advance the global RNG via LCG algorithm and return a random integer [0,2^32)
494u32 advance_rng(void) {
495 gRandSeed = gRandSeed * 0x5D588B65 + 1;
496
498
499 return gRandSeed;
500}
501
502// return a random float [0,1)
503f32 rand_float(void) {
504 return (advance_rng() & 0x7FFF) / 32768.0;
505}
506
507// return a random integer [0,max]
508s32 rand_int_internal(u32 max) {
509 u32 partitionSize = 0xFFFFFFFF;
510 u32 maxPlusOne = max + 1;
511 u32 result;
512
513 // split [0,2^32) into ``maxPlusOne`` equally sized partitions
514 // [0, partitionSize), [partitionSize, 2*partitionSize), ... [maxPlusOne*partitionSize, 2^32)
515 partitionSize /= maxPlusOne;
516 if (partitionSize == 0) {
517 partitionSize = 1;
518 }
519
520 // numbers in the leftover [maxPlusOne*partitionSize, 2^32) are rejected as they would return maxPlusOne
521 // this ensures the result is [0,max] whilst also ensuring each partition is the same size and equally probable
522 do {
523 // determine which partition the random number is in by dividing it by partitionSize
524 result = advance_rng() / partitionSize;
525 } while (result >= maxPlusOne);
526
527 return result;
528}
529
530// return a random integer [0,|max|] with specific distributions for |max| = 1 and |max| = 100
531s32 rand_int(s32 max) {
532 s32 ret = 0;
533
534 max = abs(max);
535
536 if (max != 0) {
537 switch (max) {
538 case 1:
539 // due to the off-by-one input of 1000 and the > operator being used,
540 // there is a 501/1001 chance of returning 0 and a 500/1001 chance of returning 1
541 // (assuming statistical randomness of rand_int_internal).
542 ret = rand_int_internal(1000) > 500;
543 break;
544 default:
545 ret = rand_int_internal(max);
546 break;
547 case 100:
548 ret = rand_int_internal(1009) / 10;
549 break;
550 }
551 }
552
553 return ret;
554}
555
556f32 signF(f32 val) {
557 f32 sign;
558
559 if (!(val > 0.0f)) {
560 sign = -1.0f;
561 if (!(val < 0.0f)) {
562 sign = 0.0f;
563 }
564 } else {
565 sign = 1.0f;
566 }
567
568 return sign;
569}
570
571s32 round(f32 x) {
572 if (!(x >= 0.0f)) {
573 return -(s32)(0.5 - x);
574 } else {
575 return (s32)(0.5 + x);
576 }
577}
578
579f32 clamp_angle(f32 theta) {
580 if (fabsf(theta) > 3600.0f) {
581 s32 thetaInt = theta;
582
583 if (thetaInt >= 0) {
584 thetaInt = -(thetaInt / 360 * 360) + thetaInt;
585 } else {
586 thetaInt = -thetaInt;
587 thetaInt = (thetaInt / 360 * 360) - thetaInt;
588 }
589
590 return thetaInt;
591 }
592
593 do {
594 if (theta < 0.0f) {
595 theta += 360.0f;
596 }
597 if (theta >= 360.0f) {
598 theta -= 360.0f;
599 }
600 } while (!(theta >= 0.0f) || !(theta < 360.0f));
601
602 return theta;
603}
604
605f32 get_clamped_angle_diff(f32 a, f32 b) {
606 if (fabsf(b - a) >= 180.0f) {
607 if (b < a) {
608 b += 360.0f;
609 } else {
610 b -= 360.0f;
611 }
612 }
613 return b - a;
614}
615
616f32 atan2(f32 startX, f32 startZ, f32 endX, f32 endZ) {
617 f32 dx = endX - startX;
618 f32 dz = endZ - startZ;
619 f32 absXDiff = fabsf(dx);
620 f32 absZDiff = fabsf(dz);
621 f32 ret;
622
623 if (absZDiff < absXDiff) {
624 ret = (absZDiff / absXDiff) * 45.0f;
625 ret *= sAtanFactors[round(2.0f * ret)];
626 if (dx >= 0.0f) {
627 if (dz >= 0.0f) {
628 return ret + 90.0f;
629 } else {
630 return 90.0f - ret;
631 }
632 }
633 if (dz >= 0.0f) {
634 return 270.0f - ret;
635 } else {
636 return ret + 270.0f;
637 }
638 } else {
639 if (absZDiff == 0.0f) {
640 return 0.0f;
641 }
642 ret = (absXDiff / absZDiff) * 45.0f;
643 ret *= sAtanFactors[round(2.0f * ret)];
644 if (dz >= 0.0f) {
645 if (dx >= 0.0f) {
646 return 180.0f - ret;
647 } else {
648 return ret + 180.0f;
649 }
650 } else if (!(dx >= 0.0f)) {
651 return 360.0f - ret;
652 }
653 }
654 return ret;
655}
656
660
662 f32 traceNormalX = gGameStatusPtr->playerGroundTraceNormal.x;
663 f32 traceNormalZ = gGameStatusPtr->playerGroundTraceNormal.z;
664 f32 sqrt = sqrtf(SQ(traceNormalX) + SQ(traceNormalZ));
665
666 return atan2(0.0f, 0.0f, sqrt, -gGameStatusPtr->playerGroundTraceNormal.y);
667}
668
669f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by) {
670 f32 xDiff = bx - ax;
671 f32 yDiff = by - ay;
672
673 return sqrtf(SQ(xDiff) + SQ(yDiff));
674}
675
676f32 dist3D(f32 ax, f32 ay, f32 az, f32 bx, f32 by, f32 bz) {
677 f32 xDiff = bx - ax;
678 f32 yDiff = by - ay;
679 f32 zDiff = bz - az;
680
681 return sqrtf(SQ(xDiff) + SQ(yDiff) + SQ(zDiff));
682}
683
684void add_vec2D_polar(f32* x, f32* y, f32 r, f32 theta) {
685 f32 sinTheta;
686 f32 cosTheta;
687
688 sin_cos_rad(DEG_TO_RAD(theta), &sinTheta, &cosTheta);
689 *x += r * sinTheta;
690 *y -= r * cosTheta;
691}
692
693// Effectively computes theta % 0x100000
695 f32 ret = theta;
696
697 if (theta >= 0x100000 || theta <= -0x100000) {
698 ret = theta / 0x100000;
699 ret = theta - (f32)(s32)ret * 0x100000;
700 }
701
702 return (s32) ret;
703}
704
705void sin_cos_rad(f32 theta, f32* outSinTheta, f32* outCosTheta) {
706 u16 binang = _wrap_trig_lookup_value(RAD_TO_BINANG(theta));
707
708 *outSinTheta = sins(binang) * SHT_MINV;
709 *outCosTheta = coss(binang) * SHT_MINV;
710}
711
712f32 sin_rad(f32 theta) {
713 return sins(_wrap_trig_lookup_value(RAD_TO_BINANG(theta))) * SHT_MINV;
714}
715
716f32 cos_rad(f32 theta) {
717 return coss(_wrap_trig_lookup_value(RAD_TO_BINANG(theta))) * SHT_MINV;
718}
719void sin_cos_deg(f32 theta, f32* outSinTheta, f32* outCosTheta) {
720 u16 binang = _wrap_trig_lookup_value(DEG_TO_BINANG(theta));
721
722 *outSinTheta = sins(binang) * SHT_MINV;
723 *outCosTheta = coss(binang) * SHT_MINV;
724}
725
726f32 sin_deg(f32 theta) {
727 return sins(_wrap_trig_lookup_value(DEG_TO_BINANG(theta))) * SHT_MINV;
728}
729
730f32 cos_deg(f32 theta) {
731 return coss(_wrap_trig_lookup_value(DEG_TO_BINANG(theta))) * SHT_MINV;
732}
733
734f32 update_lerp(s32 easing, f32 start, f32 end, s32 elapsed, s32 duration) {
735 s32 timeLeft;
736 f32 absMag;
737
738 if (duration == 0) {
739 return end;
740 }
741
742 switch (easing) {
743 case EASING_LINEAR:
744 return start + (end - start) * elapsed / duration;
746 return start + SQ(elapsed) * (end - start) / SQ(duration);
747 case EASING_CUBIC_IN:
748 return start + CUBE(elapsed) * (end - start) / CUBE(duration);
750 return start + QUART(elapsed) * (end - start) / QUART(duration);
752 return end - ((end - start) * cos_rad(((f32)elapsed / duration) * PI_D * 4.0) * (duration - elapsed) *
753 (duration - elapsed)) / SQ((f32)duration);
755 return end - ((end - start) * cos_rad((((f32)SQ(elapsed) / duration) * PI_D * 4.0) / 15.0) * (duration - elapsed) *
756 (duration - elapsed)) / SQ((f32)duration);
758 timeLeft = duration - elapsed;
759 return start + (end - start) - ((SQ(timeLeft) * (end - start))) / SQ(duration);
760 case EASING_CUBIC_OUT:
761 timeLeft = duration - elapsed;
762 return start + (end - start) - ((CUBE(timeLeft) * (end - start))) / CUBE(duration);
764 timeLeft = duration - elapsed;
765 return start + (end - start) - ((QUART(timeLeft) * (end - start))) / QUART(duration);
767 absMag = cos_rad((((f32)SQ(elapsed) / duration) * PI_D * 4.0) / 40.0) * (duration - elapsed) *
768 (duration - elapsed) / SQ((f32)duration);
769 if (absMag < 0.0f) {
770 absMag = -absMag;
771 }
772 return end - (end - start) * absMag;
774 return start + (end - start) * (1.0 - cos_rad(((f32)elapsed * PI_D) / (f32)duration)) * 0.5;
775 case EASING_SIN_OUT:
776 return start + (end - start) * sin_rad(((f32)elapsed * (PI_D / 2)) / (f32)duration);
777 case EASING_COS_IN:
778 return start + (end - start) * (1.0 - cos_rad(((f32)elapsed * (PI_D / 2)) / (f32)duration));
779 }
780
781 return 0.0f;
782}
783
784void appendGfx_startup_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 left, u16 top, u16 right, u16 bottom) {
785 gDPPipeSync(gMainGfxPos++);
786 gSPDisplayList(gMainGfxPos++, D_80074580);
787
788 if (a == 255) {
789 gDPSetRenderMode(gMainGfxPos++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
791 } else {
792 gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
793 gDPSetCombineMode(gMainGfxPos++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
794 }
795
796 gDPSetPrimColor(gMainGfxPos++, 0, 0, r, g, b, a);
797 gDPFillRectangle(gMainGfxPos++, left, top, right, bottom);
798
799 gDPPipeSync(gMainGfxPos++);
800 gDPSetRenderMode(gMainGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
801 gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
802}
803
804void startup_draw_prim_rect_COPY(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a) {
805 u16 temp;
806
807 if (right < left) {
808 temp = right;
809 right = left;
810 left = temp;
811 }
812
813 if (bottom < top) {
814 temp = bottom;
815 bottom = top;
816 top = temp;
817 }
818
819 appendGfx_startup_prim_rect(r, g, b, a, left, top, right, bottom);
820}
821
822void startup_draw_prim_rect(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a) {
823 u16 temp;
824
825 if (right < left) {
826 temp = right;
827 right = left;
828 left = temp;
829 }
830
831 if (bottom < top) {
832 temp = bottom;
833 bottom = top;
834 top = temp;
835 }
836
837 appendGfx_startup_prim_rect(r, g, b, a, left, top, right, bottom);
838}
f32 sin_rad(f32 theta)
Definition 43F0.c:712
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:804
void startup_draw_prim_rect(s16 left, s16 top, s16 right, s16 bottom, u16 r, u16 g, u16 b, u16 a)
Definition 43F0.c:822
f32 update_lerp(s32 easing, f32 start, f32 end, s32 elapsed, s32 duration)
Definition 43F0.c:734
void appendGfx_startup_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 left, u16 top, u16 right, u16 bottom)
Definition 43F0.c:784
u32 advance_rng(void)
Definition 43F0.c:494
Gfx D_80074580[]
Definition 43F0.c:42
u16 _wrap_trig_lookup_value(f32 theta)
Definition 43F0.c:694
f32 get_clamped_angle_diff(f32 a, f32 b)
Definition 43F0.c:605
f32 length2D(f32 x, f32 y)
Definition 43F0.c:59
s32 round(f32 x)
Definition 43F0.c:571
u8 sIntegerDigits[]
Definition 43F0.c:21
f32 dist3D(f32 ax, f32 ay, f32 az, f32 bx, f32 by, f32 bz)
Definition 43F0.c:676
f32 cosine(s16 arg0)
Definition 43F0.c:353
s32 dma_write(Addr romStart, Addr romEnd, void *vramDest)
Definition 43F0.c:460
u32 dma_copy(Addr romStart, Addr romEnd, void *vramDest)
Definition 43F0.c:443
void dma_write_block(Addr dramAddr, u32 devAddr, s32 size)
Definition 43F0.c:475
f32 sCosineTable[]
Definition 43F0.c:8
f32 signF(f32 val)
Definition 43F0.c:556
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:669
void sin_cos_deg(f32 theta, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:719
#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:503
f32 cos_rad(f32 theta)
Definition 43F0.c:716
u32 gRandSeed
Definition 43F0.c:28
s32 rand_int_internal(u32 max)
Definition 43F0.c:508
void * _heap_malloc_tail(HeapNode *head, u32 size)
Definition 43F0.c:152
void * _heap_realloc(HeapNode *heapNodeList, void *addr, u32 newSize)
Definition 43F0.c:285
u32 _heap_free(HeapNode *heapNodeList, void *addrToFree)
Definition 43F0.c:220
void copy_matrix(Matrix4f src, Matrix4f dest)
Definition 43F0.c:438
u16 heap_nextMallocID
Definition 43F0.c:6
char * int_to_string(s32 integer, char *dest, s32 base)
Definition 43F0.c:385
f32 get_player_normal_pitch(void)
Definition 43F0.c:661
f32 sAtanFactors[]
Definition 43F0.c:30
void sin_cos_rad(f32 theta, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:705
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:684
f32 get_player_normal_yaw(void)
Definition 43F0.c:657
s32 sign(s32 val)
Definition 43F0.c:375
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: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:32
Gfx * gMainGfxPos
Definition cam_main.c:15