diff options
Diffstat (limited to 'src/boot_O2')
| -rw-r--r-- | src/boot_O2/__osMalloc.c | 249 | ||||
| -rw-r--r-- | src/boot_O2/boot_0x80086280.c | 11 | ||||
| -rw-r--r-- | src/boot_O2/boot_0x800862E0.c | 20 | ||||
| -rw-r--r-- | src/boot_O2/boot_0x80086FA0.c | 78 | ||||
| -rw-r--r-- | src/boot_O2/gfxprint.c | 188 | ||||
| -rw-r--r-- | src/boot_O2/mtxuty-cvt.c | 19 | ||||
| -rw-r--r-- | src/boot_O2/stackcheck.c | 23 |
7 files changed, 574 insertions, 14 deletions
diff --git a/src/boot_O2/__osMalloc.c b/src/boot_O2/__osMalloc.c new file mode 100644 index 000000000..0a418a2d9 --- /dev/null +++ b/src/boot_O2/__osMalloc.c @@ -0,0 +1,249 @@ +#include <ultra64.h> +#include <global.h> + +#define FILL_ALLOCBLOCK (1 << 0) +#define FILL_FREEBLOCK (1 << 1) +#define CHECK_FREE_BLOCK (1 << 2) + +#define NODE_MAGIC (0x7373) + +#define BLOCK_UNINIT_MAGIC (0xAB) +#define BLOCK_UNINIT_MAGIC_32 (0xABABABAB) +#define BLOCK_ALLOC_MAGIC (0xCD) +#define BLOCK_ALLOC_MAGIC_32 (0xCDCDCDCD) +#define BLOCK_FREE_MAGIC (0xEF) +#define BLOCK_FREE_MAGIC_32 (0xEFEFEFEF) + +extern OSMesg sArenaLockMsg[1]; + +void ArenaImpl_LockInit(Arena* arena) { + osCreateMesgQueue(&arena->lock, sArenaLockMsg, ARRAY_COUNT(sArenaLockMsg)); +} + +void ArenaImpl_Lock(Arena* arena) { + osSendMesg(&arena->lock, NULL, OS_MESG_BLOCK); +} + +void ArenaImpl_Unlock(Arena* arena) { + osRecvMesg(&arena->lock, NULL, OS_MESG_BLOCK); +} + +ArenaNode* heap_get_tail(Arena* arena) { + ArenaNode* last; + ArenaNode* iter; + + last = arena->head; + + if (last != NULL) { + iter = last->next; + while (iter != NULL) { + last = iter; + iter = iter->next; + } + } + return last; +} + +void __osMallocInit(Arena* arena, void* start, u32 size) { + bzero(arena, sizeof(*arena)); + ArenaImpl_LockInit(arena); + __osMallocAddBlock(arena, start, size); + arena->isInit = 1; +} + +void __osMallocAddBlock(Arena* arena, void* start, s32 size) { + s32 diff; + s32 size2; + ArenaNode* firstNode; + ArenaNode* lastNode; + + if (start != NULL) { + firstNode = (ArenaNode*)ALIGN16((u32)start); + diff = (s32)firstNode - (s32)start; + size2 = (size - diff) & ~0xF; + + if (size2 > (s32)sizeof(ArenaNode)) { + firstNode->next = NULL; + firstNode->prev = NULL; + firstNode->size = size2 - sizeof(ArenaNode); + firstNode->isFree = 1; + firstNode->magic = NODE_MAGIC; + ArenaImpl_Lock(arena); + lastNode = heap_get_tail(arena); + if (lastNode == NULL) { + arena->head = firstNode; + arena->start = start; + } else { + firstNode->prev = lastNode; + lastNode->next = firstNode; + } + ArenaImpl_Unlock(arena); + } + } +} + + +void __osMallocCleanup(Arena* arena) { + bzero(arena, sizeof(*arena)); +} + +u8 __osMallocIsInitalized(Arena* arena) { + return arena->isInit; +} + +void* __osMalloc(Arena* arena, u32 size) { + ArenaNode* iter; + ArenaNode* newNode; + void* alloc; + u32 blockSize; + alloc = NULL; + + size = ALIGN16(size); + ArenaImpl_Lock(arena); + iter = arena->head; + + while (iter != NULL) { + if (iter->isFree && iter->size >= size) { + ArenaNode* next; + blockSize = ALIGN16(size) + sizeof(ArenaNode); + if (blockSize < iter->size) { + newNode = (ArenaNode*)((u32)iter + blockSize); + newNode->next = iter->next; + newNode->prev = iter; + newNode->size = iter->size - blockSize; + newNode->isFree = 1; + newNode->magic = NODE_MAGIC; + + iter->next = newNode; + iter->size = size; + next = newNode->next; + if (next) { + next->prev = newNode; + } + } + + iter->isFree = 0; + alloc = (void*)((u32)iter + sizeof(ArenaNode)); + break; + } + + iter = iter->next; + } + ArenaImpl_Unlock(arena); + + return alloc; +} + + +void* __osMallocR(Arena* arena, u32 size) { + ArenaNode* iter; + ArenaNode* newNode; + u32 blockSize; + void* alloc = NULL; + + size = ALIGN16(size); + ArenaImpl_Lock(arena); + iter = heap_get_tail(arena); + + while (iter != NULL) { + if (iter->isFree && iter->size >= size) { + ArenaNode* next; + blockSize = ALIGN16(size) + sizeof(ArenaNode); + if (blockSize < iter->size) { + newNode = (ArenaNode*)((u32)iter + (iter->size - size)); + newNode->next = iter->next; + newNode->prev = iter; + newNode->size = size; + newNode->magic = NODE_MAGIC; + + iter->next = newNode; + iter->size -= blockSize; + next = newNode->next; + if (next) { + next->prev = newNode; + } + iter = newNode; + } + + iter->isFree = 0; + alloc = (void*)((u32)iter + sizeof(ArenaNode)); + break; + } + iter = iter->prev; + } + ArenaImpl_Unlock(arena); + + return alloc; +} + +void __osFree(Arena* arena, void* ptr) { + ArenaNode* node; + ArenaNode* next; + ArenaNode* prev; + ArenaNode* newNext; + + ArenaImpl_Lock(arena); + node = (ArenaNode*)((u32)ptr - sizeof(ArenaNode)); + + if (ptr == NULL || (node->magic != NODE_MAGIC) || node->isFree) { + goto end; + } + + next = node->next; + prev = node->prev; + node->isFree = 1; + + newNext = next; + if ((u32)next == (u32)node + sizeof(ArenaNode) + node->size && next->isFree) { + newNext = next->next; + if (newNext != NULL) { + newNext->prev = node; + } + + node->size += next->size + sizeof(ArenaNode); + + node->next = newNext; + next = newNext; + } + + if (prev != NULL && prev->isFree && (u32)node == (u32)prev + sizeof(ArenaNode) + prev->size) { + if (next) { + next->prev = prev; + } + prev->next = next; + prev->size += node->size + sizeof(ArenaNode); + } + +end: + ArenaImpl_Unlock(arena); +} + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/__osMalloc/__osRealloc.asm") + +void __osAnalyzeArena(Arena* arena, u32* outMaxFree, u32* outFree, u32* outAlloc) { + ArenaNode* iter; + + ArenaImpl_Lock(arena); + + *outMaxFree = 0; + *outFree = 0; + *outAlloc = 0; + + iter = arena->head; + while (iter != NULL) { + if (iter->isFree) { + *outFree += iter->size; + if (*outMaxFree < iter->size) { + *outMaxFree = iter->size; + } + } else { + *outAlloc += iter->size; + } + + iter = iter->next; + } + + ArenaImpl_Unlock(arena); +} + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/__osMalloc/__osCheckArena.asm") diff --git a/src/boot_O2/boot_0x80086280.c b/src/boot_O2/boot_0x80086280.c new file mode 100644 index 000000000..e2aeff70f --- /dev/null +++ b/src/boot_O2/boot_0x80086280.c @@ -0,0 +1,11 @@ +#include <ultra64.h> +#include <global.h> + +void assert_fail(const char* file, u32 lineNum) { + osGetThreadId(NULL); + Fault_AddHungupAndCrash(file, lineNum); +} + +void func_800862B4(void) { + Fault_AddHungupAndCrash("Reset", 0); +} diff --git a/src/boot_O2/boot_0x800862E0.c b/src/boot_O2/boot_0x800862E0.c new file mode 100644 index 000000000..f9f462056 --- /dev/null +++ b/src/boot_O2/boot_0x800862E0.c @@ -0,0 +1,20 @@ +#include <ultra64.h> +#include <global.h> + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/StartHeap_AllocMin1.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/StartHeap_FreeNull.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_8008633C.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_800863AC.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_8008641C.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_800864EC.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_80086588.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/StartHeap_Init.asm") + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/boot_0x800862E0/func_80086620.asm") diff --git a/src/boot_O2/boot_0x80086FA0.c b/src/boot_O2/boot_0x80086FA0.c new file mode 100644 index 000000000..9454d4654 --- /dev/null +++ b/src/boot_O2/boot_0x80086FA0.c @@ -0,0 +1,78 @@ +#include <ultra64.h> +#include <global.h> + +#define RAND_MULTIPLIER 1664525 +#define RAND_INCREMENT 1013904223 + +/** + * Gets the next integer in the sequence of pseudo-random numbers. + */ +s32 Rand_Next(void) { + return sRandInt = (sRandInt * 1664525) + 1013904223; +} + +/** + * Seeds the pseudo-random number generator by providing a starting value. + */ +void Rand_Seed(u32 seed) { + sRandInt = seed; +} + +/** + * Returns a pseudo-random floating-point number between 0.0f and 1.0f, by generating + * the next integer and masking it to an IEEE-754 compliant floating-point number + * between 1.0f and 2.0f, returning the result subtract 1.0f. + */ +f32 Rand_ZeroOne(void) { + sRandInt = (sRandInt * RAND_MULTIPLIER) + RAND_INCREMENT; + sRandFloat = ((sRandInt >> 9) | 0x3F800000); + return *((f32*)&sRandFloat) - 1.0f; +} + +/** + * Returns a pseudo-random floating-point number between -0.5f and 0.5f by the same + * manner in which Rand_ZeroOne generates its result. + */ +f32 Rand_Centered(void) { + sRandInt = (sRandInt * RAND_MULTIPLIER) + RAND_INCREMENT; + sRandFloat = ((sRandInt >> 9) | 0x3F800000); + return *((f32*)&sRandFloat) - 1.5f; +} + +/** + * Seeds a pseudo-random number at rndNum with a provided seed. + */ +void Rand_Seed_Variable(u32* rndNum, u32 seed) { + *rndNum = seed; +} + +/** + * Generates the next pseudo-random integer from the provided rndNum. + */ +u32 Rand_Next_Variable(u32* rndNum) { + return *rndNum = (*rndNum * RAND_MULTIPLIER) + RAND_INCREMENT; +} + +/** + * Generates the next pseudo-random floating-point number between 0.0f and + * 1.0f from the provided rndNum. + */ +f32 Rand_ZeroOne_Variable(u32* rndNum) { + u32 next = (*rndNum * RAND_MULTIPLIER) + RAND_INCREMENT; + // clang-format off + *rndNum = next; sRandFloat = (next >> 9) | 0x3F800000; + // clang-format on + return *((f32*)&sRandFloat) - 1.0f; +} + +/** + * Generates the next pseudo-random floating-point number between -0.5f and + * 0.5f from the provided rndNum. + */ +f32 Rand_Centered_Variable(u32* rndNum) { + u32 next = (*rndNum * RAND_MULTIPLIER) + RAND_INCREMENT; + // clang-format off + *rndNum = next; sRandFloat = (next >> 9) | 0x3F800000; + // clang-format on + return *((f32*)&sRandFloat) - 1.5f; +} diff --git a/src/boot_O2/gfxprint.c b/src/boot_O2/gfxprint.c new file mode 100644 index 000000000..2d4331bb9 --- /dev/null +++ b/src/boot_O2/gfxprint.c @@ -0,0 +1,188 @@ +#include <ultra64.h> +#include <global.h> + +extern u16 sGfxPrintFontTLUT[64]; +extern u16 sGfxPrintUnkTLUT[16]; +extern u8 sGfxPrintUnkData[8]; +extern u8 sGfxPrintFontData[2048]; + +#define gDPSetPrimColorMod(pkt, m, l, rgba) \ + { \ + Gfx* _g = (Gfx*)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \ + _g->words.w1 = (rgba); \ + } + +void GfxPrint_InitDlist(GfxPrint* this) { + s32 width = 16; + s32 height = 256; + s32 i; + + gDPPipeSync(this->dlist++); + gDPSetOtherMode(this->dlist++, + G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_IA16 | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PRIM | G_RM_XLU_SURF | G_RM_XLU_SURF2); + gDPSetCombineMode(this->dlist++, G_CC_DECALRGBA, G_CC_DECALRGBA); + gDPLoadTextureBlock_4b(this->dlist++, sGfxPrintFontData, G_IM_FMT_CI, width, height, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTLUT(this->dlist++, 64, 256, sGfxPrintFontTLUT); + + for (i = 1; i < 4; i++) { + gDPSetTile(this->dlist++, G_IM_FMT_CI, G_IM_SIZ_4b, 1, 0, i * 2, i, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD); + gDPSetTileSize(this->dlist++, i * 2, 0, 0, 60, 1020); + } + + gDPSetPrimColorMod(this->dlist++, 0, 0, this->color.rgba); + + gDPLoadMultiTile_4b(this->dlist++, sGfxPrintUnkData, 0, 1, G_IM_FMT_CI, 2, 8, 0, 0, 1, 7, 4, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 1, 3, G_TX_NOLOD, G_TX_NOLOD); + + gDPLoadTLUT(this->dlist++, 16, 320, sGfxPrintUnkTLUT); + + for (i = 1; i < 4; i++) { + gDPSetTile(this->dlist++, G_IM_FMT_CI, G_IM_SIZ_4b, 1, 0, i * 2 + 1, 4, G_TX_NOMIRROR | G_TX_WRAP, 3, + G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 1, G_TX_NOLOD); + gDPSetTileSize(this->dlist++, i * 2 + 1, 0, 0, 4, 28); + } +} + +void GfxPrint_SetColor(GfxPrint* this, u32 r, u32 g, u32 b, u32 a) { + this->color.r = r; + this->color.g = g; + this->color.b = b; + this->color.a = a; + gDPPipeSync(this->dlist++); + gDPSetPrimColorMod(this->dlist++, 0, 0, this->color.rgba); +} + +void GfxPrint_SetPosPx(GfxPrint* this, s32 x, s32 y) { + this->posX = this->baseX + (x << 2); + this->posY = this->baseY + (y << 2); +} + +void GfxPrint_SetPos(GfxPrint* this, s32 x, s32 y) { + GfxPrint_SetPosPx(this, x << 3, y << 3); +} + +void GfxPrint_SetBasePosPx(GfxPrint* this, s32 x, s32 y) { + this->baseX = x << 2; + this->baseY = y << 2; +} + +/* regalloc in the final gSPTextureRectangle */ +#ifdef NON_MATCHING +void GfxPrint_PrintCharImpl(GfxPrint* this, u8 c) { + u32 tile = (c & 0xFF) * 2; + + if (this->flag & GFXPRINT_UPDATE_MODE) { + this->flag &= ~GFXPRINT_UPDATE_MODE; + + gDPPipeSync(this->dlist++); + if (this->flag & GFXPRINT_USE_RGBA16) { + gDPSetTextureLUT(this->dlist++, G_TT_RGBA16); + gDPSetCycleType(this->dlist++, G_CYC_2CYCLE); + gDPSetRenderMode(this->dlist++, G_RM_OPA_CI, G_RM_XLU_SURF2); + gDPSetCombineMode(this->dlist++, G_CC_INTERFERENCE, G_CC_PASS2); + } else { + gDPSetTextureLUT(this->dlist++, G_TT_IA16); + gDPSetCycleType(this->dlist++, G_CYC_1CYCLE); + gDPSetRenderMode(this->dlist++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPSetCombineMode(this->dlist++, G_CC_MODULATEIDECALA_PRIM, G_CC_MODULATEIDECALA_PRIM); + } + } + + if (this->flag & GFXPRINT_FLAG4) { + gDPSetPrimColorMod(this->dlist++, 0, 0, 0); + + gSPTextureRectangle(this->dlist++, this->posX + 4, this->posY + 4, this->posX + 4 + 32, this->posY + 4 + 32, + (c & 3) << 1, (u16)(c & 4) * 64, (u16)(c >> 3) * 256, 1024, 1024); + + + gDPSetPrimColorMod(this->dlist++, 0, 0, this->color.rgba); + } + + + gSPTextureRectangle(this->dlist++, this->posX, this->posY, this->posX + 32, this->posY + 32, (u16)(tile & 7), + (u16)(c & 4) * 64, (u16)(c >> 3) * 256, 1024, 1024); + + + this->posX += 32; +} +#else +#pragma GLOBAL_ASM("./asm/non_matchings/boot/gfxprint/GfxPrint_PrintCharImpl.asm") +#endif + +#pragma GLOBAL_ASM("./asm/non_matchings/boot/gfxprint/GfxPrint_PrintChar.asm") + +void GfxPrint_PrintStringWithSize(GfxPrint* this, const void* buffer, size_t charSize, size_t charCount) { + const char* str = (const char*)buffer; + size_t count = charSize * charCount; + + while (count) { + GfxPrint_PrintChar(this, *str++); + count--; + } +} + +void GfxPrint_PrintString(GfxPrint* this, const char* str) { + while (*str) { + GfxPrint_PrintChar(this, *(str++)); + } +} + +GfxPrint* GfxPrint_Callback(GfxPrint* this, const char* str, size_t size) { + GfxPrint_PrintStringWithSize(this, str, sizeof(char), size); + return this; +} + +void GfxPrint_Init(GfxPrint* this) { + this->flag &= ~GFXPRINT_OPEN; + + this->callback = GfxPrint_Callback; + + this->dlist = NULL; + this->posX = 0; + this->posY = 0; + this->baseX = 0; + this->baseY = 0; + this->color.rgba = 0; + this->flag &= ~GFXPRINT_FLAG1; + this->flag &= ~GFXPRINT_USE_RGBA16; + this->flag |= GFXPRINT_FLAG4; + this->flag |= GFXPRINT_UPDATE_MODE; +} + +void GfxPrint_Destroy(GfxPrint* this) { + +} + +void GfxPrint_Open(GfxPrint* this, Gfx* dlist) { + if (!(this->flag & GFXPRINT_OPEN)) { + this->flag |= GFXPRINT_OPEN; + this->dlist = dlist; + GfxPrint_InitDlist(this); + } +} + +Gfx* GfxPrint_Close(GfxPrint* this) { + Gfx* ret; + + this->flag &= ~GFXPRINT_OPEN; + ret = this->dlist; + this->dlist = NULL; + return ret; +} + +void GfxPrint_VPrintf(GfxPrint* this, const char* fmt, va_list args) { + func_80087900(&this->callback, fmt, args); +} + +void GfxPrint_Printf(GfxPrint* this, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + GfxPrint_VPrintf(this, fmt, args); +} diff --git a/src/boot_O2/mtxuty-cvt.c b/src/boot_O2/mtxuty-cvt.c new file mode 100644 index 000000000..78be5e3b5 --- /dev/null +++ b/src/boot_O2/mtxuty-cvt.c @@ -0,0 +1,19 @@ +#include <ultra64.h> +#include <global.h> + +void MtxConv_F2L(MatrixInternal* m1, MtxF* m2) { + s32 i; + s32 j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + s32 value = (m2->mf[i][j] * 0x10000); + m1->intPart[i][j] = value >> 16; + m1->fracPart[i][j] = value; + } + } +} + +void MtxConv_L2F(MtxF* m1, MatrixInternal* m2) { + guMtxL2F(m1, (Mtx *)m2); +} diff --git a/src/boot_O2/stackcheck.c b/src/boot_O2/stackcheck.c index 1c7790d97..142f824a7 100644 --- a/src/boot_O2/stackcheck.c +++ b/src/boot_O2/stackcheck.c @@ -69,13 +69,11 @@ void StackCheck_Cleanup(StackEntry* entry) { if (inconsistency) {} } -#ifdef NON_MATCHING -// Missing useless move -s32 StackCheck_GetState(StackEntry* entry) { +StackStatus StackCheck_GetState(StackEntry* entry) { u32* last; u32 used; u32 free; - s32 ret; + s32 status; for (last = (u32*)entry->head; (u32)last < entry->tail; last++) { if (entry->initValue != *last) { @@ -87,23 +85,20 @@ s32 StackCheck_GetState(StackEntry* entry) { free = (u32)last - entry->head; if (free == 0) { - return 2; - } - - if (free < entry->minSpace && entry->minSpace != -1) { - return 1; + status = STACK_STATUS_OVERFLOW; + } else if (free < (u32)entry->minSpace && entry->minSpace != -1) { + status = STACK_STATUS_WARNING; + } else { + status = STACK_STATUS_OK; } - return 0; + return status; } -#else -#pragma GLOBAL_ASM("./asm/non_matchings/boot/stackcheck/StackCheck_GetState.asm") -#endif u32 StackCheck_CheckAll() { u32 ret = 0; - StackEntry* iter = sStackInfoListStart; + while(iter) { u32 state = StackCheck_GetState(iter); if (state) { |
