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 = nullptr;
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 = nullptr;
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 nullptr;
92 }
93
94 smallestBlockFound = 0;
95 nextHeapNode = nullptr;
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 nullptr;
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 = nullptr;
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 nullptr;
165 }
166
167 foundNodeLength = 0;
168 nextNode = nullptr;
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 nullptr;
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 == nullptr) {
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 nullptr;
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 == nullptr) {
317 return nullptr;
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 ASSERT_MSG(((u32)vramDest & 7) == 0, "dma_copy: dest not 8-byte aligned");
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:41
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:58
s32 round(f32 x)
Definition 43F0.c:572
u8 sIntegerDigits[]
Definition 43F0.c:20
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:352
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:442
void dma_write_block(Addr dramAddr, u32 devAddr, s32 size)
Definition 43F0.c:476
f32 sCosineTable[]
Definition 43F0.c:7
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:56
void * _heap_malloc(HeapNode *head, u32 size)
Definition 43F0.c:77
f32 rand_float(void)
Definition 43F0.c:504
f32 cos_rad(f32 theta)
Definition 43F0.c:717
u32 gRandSeed
Definition 43F0.c:27
s32 rand_int_internal(u32 max)
Definition 43F0.c:509
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:662
f32 sAtanFactors[]
Definition 43F0.c:29
void sin_cos_rad(f32 theta, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:706
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:685
f32 get_player_normal_yaw(void)
Definition 43F0.c:658
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:96
#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:19
#define PM_CC_PRIM_FULL_ALPHA
Definition macros.h:295
#define PI_D
Definition macros.h:138
#define DEG_TO_BINANG(x)
Definition macros.h:143
#define SHT_MINV
Definition macros.h:148
#define ARRAY_COUNT(arr)
Definition macros.h:39
#define QUART(x)
Definition macros.h:179
#define RAD_TO_BINANG(x)
Definition macros.h:144
#define DEG_TO_RAD(deg)
Definition macros.h:145
#define ASSERT_MSG(condition, msg, args...)
Definition macros.h:65
#define CUBE(x)
Definition macros.h:178
#define SQ(x)
Definition macros.h:177
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