diff --git a/actors/common1_geo.c b/actors/common1_geo.c index cfc2ba63c..0a4ad099a 100644 --- a/actors/common1_geo.c +++ b/actors/common1_geo.c @@ -42,8 +42,6 @@ #include "game/behaviors/orange_number.inc.c" #include "game/behaviors/mushroom_1up.inc.c" #include "game/behaviors/spawn_star_exit.inc.c" -#include "game/behaviors/boo.inc.c" -#include "game/behaviors/boo_cage.inc.c" #include "game/behaviors/celebration_star.inc.c" #include "game/behaviors/flame.inc.c" #include "game/behaviors/spawn_star.inc.c" diff --git a/actors/group15_geo.c b/actors/group15_geo.c index b8891c203..c0c80edad 100644 --- a/actors/group15_geo.c +++ b/actors/group15_geo.c @@ -17,3 +17,4 @@ #include "game/behaviors/camera_lakitu.inc.c" // TODO: 104 label, follow cam documentation #include "game/behaviors/mips.inc.c" #include "game/behaviors/toad.inc.c" +#include "game/behaviors/castle_boo.inc.c" diff --git a/actors/group9_geo.c b/actors/group9_geo.c index 688bca412..1df49e226 100644 --- a/actors/group9_geo.c +++ b/actors/group9_geo.c @@ -22,3 +22,5 @@ #include "game/behaviors/mad_piano.inc.c" #include "game/behaviors/flying_bookend_switch.inc.c" #include "game/behaviors/beta_boo_key.inc.c" +#include "game/behaviors/boo_cage.inc.c" +#include "game/behaviors/boo.inc.c" diff --git a/sm64.ld b/sm64.ld index 2b843e6af..aa51859ec 100755 --- a/sm64.ld +++ b/sm64.ld @@ -381,7 +381,7 @@ SECTIONS /* 0x268020 0x268020-0 [0] */ BEGIN_SEG(intro, 0x14000000) { - KEEP(BUILD_DIR/levels/intro/script.o(.*data)); + KEEP(BUILD_DIR/levels/intro/script.o(.*data*)); KEEP(BUILD_DIR/levels/intro/script.o(.rodata*)); KEEP(BUILD_DIR/levels/intro/script.o(.text)); KEEP(BUILD_DIR/levels/intro/geo.o(.data)); @@ -430,10 +430,18 @@ SECTIONS BEGIN_SEG(menu, 0x14000000) { - KEEP(BUILD_DIR/levels/menu/script.o(.data)); + KEEP(BUILD_DIR/levels/menu/script.o(.*data*)); + KEEP(BUILD_DIR/levels/menu/script.o(.rodata*)); + KEEP(BUILD_DIR/levels/menu/script.o(.text)); KEEP(BUILD_DIR/levels/menu/geo.o(.data)); } END_SEG(menu) + BEGIN_NOLOAD(menu) + { + KEEP(BUILD_DIR/levels/menu/script.o(.bss*)); + } + END_NOLOAD(menu) + BEGIN_SEG(menu_segment_7, 0x07000000) { KEEP(BUILD_DIR/levels/menu/leveldata.szp.o(.data)); diff --git a/src/buffers/buffers.c b/src/buffers/buffers.c index 1e9ab4095..662d3a96a 100644 --- a/src/buffers/buffers.c +++ b/src/buffers/buffers.c @@ -20,6 +20,7 @@ ALIGNED8 u8 gThread5Stack[0x2000]; #if ENABLE_RUMBLE ALIGNED8 u8 gThread6Stack[0x2000]; #endif +ALIGNED8 u8 gThread7Stack[0x1000]; // 0x400 bytes #if UNF ALIGNED16 u8 gGfxSPTaskStack[SP_DRAM_STACK_SIZE8]; diff --git a/src/buffers/buffers.h b/src/buffers/buffers.h index f063a023c..f0ea8cd9a 100644 --- a/src/buffers/buffers.h +++ b/src/buffers/buffers.h @@ -19,6 +19,7 @@ extern u8 gThread5Stack[]; #if ENABLE_RUMBLE extern u8 gThread6Stack[]; #endif +extern u8 gThread7Stack[]; extern u8 gGfxSPTaskYieldBuffer[]; diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index 8f3e89cd1..ff58946e7 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -800,67 +800,6 @@ void bhv_animated_texture_loop(void) { cur_obj_set_pos_to_home_with_debug(); } -void bhv_boo_in_castle_loop(void) { - s16 targetAngle; - - o->oBooBaseScale = 2.0f; - - if (o->oAction == 0) { - cur_obj_hide(); - - /*if (gHudDisplay.stars < 12) { - obj_mark_for_deletion(o); - }*/ - - if (gMarioCurrentRoom == 1) { - o->oAction++; - } - } else if (o->oAction == 1) { - cur_obj_unhide(); - - o->oOpacity = 180; - - if (o->oTimer == 0) { - cur_obj_scale(o->oBooBaseScale); - } - - if (o->oDistanceToMario < 1000.0f) { - o->oAction++; - cur_obj_play_sound_2(SOUND_OBJ_BOO_LAUGH_LONG); - } - - o->oForwardVel = 0.0f; - targetAngle = o->oAngleToMario; - } else { - cur_obj_forward_vel_approach_upward(32.0f, 1.0f); - - o->oHomeX = -1000.0f; - o->oHomeZ = -9000.0f; - - targetAngle = cur_obj_angle_to_home(); - - if (o->oPosZ < -5000.0f) { - if (o->oOpacity > 0) { - o->oOpacity -= 20; - } else { - o->oOpacity = 0; - } - } - - if (o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) { - o->oAction = 1; - } - } - - o->oVelY = 0.0f; - - targetAngle = cur_obj_angle_to_home(); - - cur_obj_rotate_yaw_toward(targetAngle, 0x5A8); - boo_oscillate(TRUE); - cur_obj_move_using_fvel_and_gravity(); -} - void bhv_boo_staircase(void) { f32 targetY = 0.0f; diff --git a/src/game/behaviors/castle_boo.inc.c b/src/game/behaviors/castle_boo.inc.c new file mode 100644 index 000000000..3db79815c --- /dev/null +++ b/src/game/behaviors/castle_boo.inc.c @@ -0,0 +1,73 @@ + +static void boo_oscillate(s32 ignoreOpacity) { + o->oFaceAnglePitch = sins(o->oBooOscillationTimer) * 0x400; + + if (o->oOpacity == 0xFF || ignoreOpacity == TRUE) { + o->header.gfx.scale[0] = sins(o->oBooOscillationTimer) * 0.08 + o->oBooBaseScale; + o->header.gfx.scale[1] = -sins(o->oBooOscillationTimer) * 0.08 + o->oBooBaseScale; + o->header.gfx.scale[2] = o->header.gfx.scale[0]; + o->oGravity = sins(o->oBooOscillationTimer) * o->oBooBaseScale; + o->oBooOscillationTimer += 0x400; + } +} + +void bhv_boo_in_castle_loop(void) { + s16 targetAngle; + + o->oBooBaseScale = 2.0f; + + if (o->oAction == 0) { + cur_obj_hide(); + + /*if (gHudDisplay.stars < 12) { + obj_mark_for_deletion(o); + }*/ + + if (gMarioCurrentRoom == 1) { + o->oAction++; + } + } else if (o->oAction == 1) { + cur_obj_unhide(); + + o->oOpacity = 180; + + if (o->oTimer == 0) { + cur_obj_scale(o->oBooBaseScale); + } + + if (o->oDistanceToMario < 1000.0f) { + o->oAction++; + cur_obj_play_sound_2(SOUND_OBJ_BOO_LAUGH_LONG); + } + + o->oForwardVel = 0.0f; + targetAngle = o->oAngleToMario; + } else { + cur_obj_forward_vel_approach_upward(32.0f, 1.0f); + + o->oHomeX = -1000.0f; + o->oHomeZ = -9000.0f; + + targetAngle = cur_obj_angle_to_home(); + + if (o->oPosZ < -5000.0f) { + if (o->oOpacity > 0) { + o->oOpacity -= 20; + } else { + o->oOpacity = 0; + } + } + + if (o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) { + o->oAction = 1; + } + } + + o->oVelY = 0.0f; + + targetAngle = cur_obj_angle_to_home(); + + cur_obj_rotate_yaw_toward(targetAngle, 0x5A8); + boo_oscillate(TRUE); + cur_obj_move_using_fvel_and_gravity(); +} diff --git a/src/game/load_thread.c b/src/game/load_thread.c new file mode 100644 index 000000000..8d29ffea9 --- /dev/null +++ b/src/game/load_thread.c @@ -0,0 +1,109 @@ +#include +#include "sm64.h" +#include "load_thread.h" +#include "memory.h" + +u8 loadStatus = 0; +s32 gLoadQueueSize = 0; +struct LoadTaskStruct *loadQueueTable[LOAD_QUEUE_SIZE]; +struct MemoryPool *loadHeap; + +s32 append_load_segment(s32 segment, u8 *startAddr, u8 *endAddr, s32 side, s32 priority, u8 *startBss, u8 *endBss, s32 compressed) +{ + if (gLoadQueueSize >= LOAD_QUEUE_SIZE) + return LOAD_ERROR_QUEUE_FULL; + if ((loadQueueTable[gLoadQueueSize] = mem_pool_alloc(loadHeap, sizeof(struct LoadTaskStruct))) == NULL) + return LOAD_ERROR_ALLOC_FAILED; + + loadQueueTable[gLoadQueueSize]->segment = segment; + loadQueueTable[gLoadQueueSize]->startAddr = startAddr; + loadQueueTable[gLoadQueueSize]->endAddr = endAddr; + loadQueueTable[gLoadQueueSize]->side = side; + loadQueueTable[gLoadQueueSize]->priority = priority; + loadQueueTable[gLoadQueueSize]->startBss = startBss; + loadQueueTable[gLoadQueueSize]->endBss = endBss; + if (compressed > 1) + compressed = 1; + loadQueueTable[gLoadQueueSize]->type = LOAD_QUEUE_SEGMENT_RAW + compressed; + + gLoadQueueSize++; + return 0; +} + +s32 append_load_dma(u8 *dest, u8 *startAddr, u8 *endAddr, s32 priority, s32 compressed) +{ + if (gLoadQueueSize >= LOAD_QUEUE_SIZE) + return LOAD_ERROR_QUEUE_FULL; + if ((loadQueueTable[gLoadQueueSize] = mem_pool_alloc(loadHeap, sizeof(struct LoadTaskStruct))) == NULL) + return LOAD_ERROR_ALLOC_FAILED; + + loadQueueTable[gLoadQueueSize]->startAddr = startAddr; + loadQueueTable[gLoadQueueSize]->endAddr = endAddr; + loadQueueTable[gLoadQueueSize]->priority = priority; + loadQueueTable[gLoadQueueSize]->startBss = dest; + if (compressed > 1) + compressed = 1; + loadQueueTable[gLoadQueueSize]->type = LOAD_QUEUE_DMA_RAW + compressed; + + gLoadQueueSize++; + return 0; +} + + +void process_load_queue(void) +{ + s32 i, j, bestPrio; + if (gLoadQueueSize == 0) + { + loadStatus = 0; + return; + } + loadStatus = 1; + for (i = 0; i < gLoadQueueSize; i++) + { + bestPrio = 0; + for (j = 0; j < LOAD_QUEUE_SIZE; j++) + { + if (loadQueueTable[j] == NULL) + continue; + if (loadQueueTable[j]->priority > bestPrio) + bestPrio = j; + } + if (loadQueueTable[bestPrio] == NULL) + continue; + switch (loadQueueTable[bestPrio]->type) + { + case LOAD_QUEUE_SEGMENT_RAW: + load_segment(loadQueueTable[bestPrio]->segment, loadQueueTable[bestPrio]->startAddr, loadQueueTable[bestPrio]->endAddr, + loadQueueTable[bestPrio]->side, loadQueueTable[bestPrio]->startBss, loadQueueTable[bestPrio]->endBss); + break; + case LOAD_QUEUE_SEGMENT_COMPRESSED: + load_segment_decompress(loadQueueTable[bestPrio]->segment, loadQueueTable[bestPrio]->startAddr, loadQueueTable[bestPrio]->endAddr); + break; + case LOAD_QUEUE_DMA_RAW: + dma_read(loadQueueTable[bestPrio]->startBss, loadQueueTable[bestPrio]->startAddr, loadQueueTable[bestPrio]->endAddr); + break; + } + mem_pool_free(loadHeap, loadQueueTable[bestPrio]); + gLoadQueueSize--; + } + loadStatus = 0; +} + +void thread7_load(UNUSED void *arg) +{ + #ifdef PUPPYPRINT + OSTime lastTime = 0; + #endif + loadHeap = main_pool_alloc(0x4000, MEMORY_POOL_LEFT); + while (TRUE) + { + #ifdef PUPPYPRINT + lastTime = osGetTime(); + #endif + process_load_queue(); + #ifdef PUPPYPRINT + //profiler_update(loadThreadTime, lastTime); + #endif + } +} diff --git a/src/game/load_thread.h b/src/game/load_thread.h new file mode 100644 index 000000000..fc7b9f9b0 --- /dev/null +++ b/src/game/load_thread.h @@ -0,0 +1,31 @@ +#ifndef LOAD_THREAD_H +#define LOAD_THREAD_H + +#define LOAD_QUEUE_SIZE 64 + +#define LOAD_QUEUE_SEGMENT_RAW 1 +#define LOAD_QUEUE_SEGMENT_COMPRESSED 2 +#define LOAD_QUEUE_DMA_RAW 3 +#define LOAD_QUEUE_DMA_COMPRESSED 4 +#define LOAD_ERROR_QUEUE_FULL 1 +#define LOAD_ERROR_ALLOC_FAILED 2 + +struct LoadTaskStruct +{ + u8 type; + u8 side; + u8 segment; + u8 *startAddr; + u8 *endAddr; + u8 *startBss; + u8 *endBss; + u8 priority; +}; + +extern void thread7_load(UNUSED void *arg); +extern u8 loadStatus; +extern struct LoadTaskStruct *loadQueueTable[LOAD_QUEUE_SIZE]; +extern s32 append_load_dma(u8 *dest, u8 *startAddr, u8 *endAddr, s32 priority, s32 compressed); +extern s32 append_load_segment(s32 segment, u8 *startAddr, u8 *endAddr, s32 side, s32 priority, u8 *startBss, u8 *endBss, s32 compressed); + +#endif diff --git a/src/game/main.c b/src/game/main.c index 5988a7774..e6822fb7d 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -19,6 +19,7 @@ #include "usb/debug.h" #endif #include "puppyprint.h" +#include "load_thread.h" // Message IDs #define MESG_SP_COMPLETE 100 @@ -31,6 +32,7 @@ OSThread D_80339210; // unused? OSThread gIdleThread; OSThread gMainThread; OSThread gGameLoopThread; +OSThread gLoadThread; OSThread gSoundThread; OSIoMesg gDmaIoMesg; @@ -346,6 +348,9 @@ void thread3_main(UNUSED void *arg) { create_thread(&gGameLoopThread, 5, thread5_game_loop, NULL, gThread5Stack + 0x2000, 10); osStartThread(&gGameLoopThread); + create_thread(&gLoadThread, 7, thread7_load, NULL, gThread7Stack + 0x1000, 1); + osStartThread(&gLoadThread); + while (TRUE) { OSMesg msg; @@ -503,10 +508,10 @@ extern u32 gISVFlag; void osInitialize_fakeisv() { /* global flag to skip `__checkHardware_isv` from being called. */ gISVFlag = 0x49533634; // 'IS64' - + /* printf writes go to this address, cen64(1) has this hardcoded. */ gISVDbgPrnAdrs = 0x13FF0000; - + /* `__printfunc`, used by `osSyncPrintf` will be set. */ __osInitialize_isv(); } diff --git a/src/game/memory.h b/src/game/memory.h index 592ab2c7e..50b46a355 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -58,6 +58,7 @@ void *main_pool_realloc(void *addr, u32 size); u32 main_pool_available(void); u32 main_pool_push_state(void); u32 main_pool_pop_state(void); +extern void dma_read(u8 *dest, u8 *srcStart, u8 *srcEnd); #ifndef NO_SEGMENTED_MEMORY void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side, u8 *bssStart, u8 *bssEnd);