From 4cbe3af070ee8415217e7fe502874fda93eb2be1 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Mon, 11 May 2020 02:42:22 -0300 Subject: [PATCH 01/73] Added CLI functionality with --skip-intro option. --- src/game/level_update.c | 4 +++- src/pc/cliopts.c | 20 ++++++++++++++++++++ src/pc/cliopts.h | 10 ++++++++++ src/pc/pc_main.c | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/pc/cliopts.c create mode 100644 src/pc/cliopts.h diff --git a/src/game/level_update.c b/src/game/level_update.c index f278811e..8e1c0a99 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -28,6 +28,8 @@ #include "course_table.h" #include "thread6.h" +#include "pc/cliopts.h" + #define PLAY_MODE_NORMAL 0 #define PLAY_MODE_PAUSED 2 #define PLAY_MODE_CHANGE_AREA 3 @@ -1197,7 +1199,7 @@ s32 init_level(void) { if (gMarioState->action != ACT_UNINITIALIZED) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else { + } else if (gCLIOpts.SkipIntro == 0) { set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); val4 = 1; } diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c new file mode 100644 index 00000000..162b3e1a --- /dev/null +++ b/src/pc/cliopts.c @@ -0,0 +1,20 @@ +#include "cliopts.h" + +struct PCCLIOptions gCLIOpts; + +void parse_cli_opts(int argc, char* argv[]) +{ + // Initialize options with false values. + gCLIOpts.SkipIntro = 0; + + // Scan arguments for options + if (argc > 1) + { + int i; + for (i = 1; i < argc; i++) + { + if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro + gCLIOpts.SkipIntro = 1; + } + } +} \ No newline at end of file diff --git a/src/pc/cliopts.h b/src/pc/cliopts.h new file mode 100644 index 00000000..2f08cc4e --- /dev/null +++ b/src/pc/cliopts.h @@ -0,0 +1,10 @@ +#include "sm64.h" + +struct PCCLIOptions +{ + u8 SkipIntro; +}; + +extern struct PCCLIOptions gCLIOpts; + +void parse_cli_opts(int argc, char* argv[]); \ No newline at end of file diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 5b4bcd23..ca7adf51 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -18,6 +18,7 @@ #include "audio/audio_sdl.h" #include "audio/audio_null.h" +#include "cliopts.h" #include "configfile.h" OSMesg D_80339BEC; @@ -155,6 +156,7 @@ void main_func(void) { } int main(int argc, char *argv[]) { + parse_cli_opts(argc, argv); main_func(); return 0; } From bd93878c5605703797697963d5ab4e48fc6b93f5 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Mon, 11 May 2020 05:13:51 -0300 Subject: [PATCH 02/73] Add option in the configfile for skipping the intro Now it's possible to either provide the --skip-intro command line argument or have skip_intro set to 1 on the config file. --- src/game/level_update.c | 5 +++-- src/pc/configfile.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/game/level_update.c b/src/game/level_update.c index 8e1c0a99..698e8c7a 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -174,7 +174,8 @@ s8 D_8032C9E0 = 0; u8 unused3[4]; u8 unused4[2]; - +// For configfile intro skipping +extern unsigned int configSkipIntro; void basic_update(s16 *arg); @@ -1199,7 +1200,7 @@ s32 init_level(void) { if (gMarioState->action != ACT_UNINITIALIZED) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else if (gCLIOpts.SkipIntro == 0) { + } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) { set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); val4 = 1; } diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 4d38aaaf..6b1e83b0 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -69,6 +69,7 @@ bool configCameraInvertY = false; bool configEnableCamera = false; bool configCameraMouse = false; #endif +unsigned int configSkipIntro = 0; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen}, @@ -107,6 +108,7 @@ static const struct ConfigOption options[] = { {.name = "bettercam_aggression", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraAggr}, {.name = "bettercam_pan_level", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraPan}, #endif + {.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string From cdcea5c0f8a726ec5a9f6f3ac4cb58a19c18f83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Mon, 11 May 2020 18:31:59 -0300 Subject: [PATCH 03/73] Add what's skipintro is about --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fc8e1320..775b891f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# sm64pc +# sm64pc - skipintro branch + +This is a testing branch featuring a new CLI interface and support to skip the introductory Peach & Lakitu cutscenes, useful for development tests. + OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64). Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. From c98a263cf40520bf0d131eb2d1a2f90240787c98 Mon Sep 17 00:00:00 2001 From: uwabami Date: Tue, 12 May 2020 09:26:16 +0200 Subject: [PATCH 04/73] adding option to disable draw distance --- Makefile | 8 ++++++++ src/engine/behavior_script.c | 4 ++++ src/engine/surface_load.c | 4 ++++ src/game/behaviors/butterfly.inc.c | 3 ++- src/game/behaviors/chain_chomp.inc.c | 8 ++++++++ src/game/behaviors/coin.inc.c | 6 ++++++ src/game/behaviors/fish.inc.c | 4 ++++ src/game/behaviors/goomba.inc.c | 4 ++++ src/game/behaviors/heave_ho.inc.c | 4 ++++ src/game/behaviors/king_bobomb.inc.c | 4 ++++ src/game/behaviors/pokey.inc.c | 6 ++++++ src/game/behaviors/snufit.inc.c | 4 ++++ src/game/behaviors/triplet_butterfly.inc.c | 4 ++++ src/game/behaviors/water_bomb_cannon.inc.c | 8 ++++++++ src/game/behaviors/whirlpool.inc.c | 4 ++++ 15 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d4bd2846..efeb63e4 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,8 @@ COMPILER ?= ido # Disable better camera by default BETTERCAMERA ?= 0 +# Disable no drawing distance by default +NODRAWINGDISTANCE ?= 0 # Build for Emscripten/WebGL TARGET_WEB ?= 0 @@ -449,6 +451,12 @@ CC_CHECK += -DBETTERCAMERA CFLAGS += -DBETTERCAMERA endif +# Check for no drawing distance option +ifeq ($(NODRAWINGDISTANCE),1) +CC_CHECK += -DNODRAWINGDISTANCE +CFLAGS += -DNODRAWINGDISTANCE +endif + ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) ifeq ($(TARGET_WEB),1) diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index edd52478..feb6fefd 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -987,11 +987,15 @@ void cur_obj_update(void) { } else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) { if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) { // If the object has a render distance, check if it should be shown. +#ifndef NODRAWINGDISTANCE if (distanceFromMario > gCurrentObject->oDrawingDistance) { // Out of render distance, hide the object. gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; gCurrentObject->activeFlags |= ACTIVE_FLAG_FAR_AWAY; } else if (gCurrentObject->oHeldState == HELD_FREE) { +#else + if (distanceFromMario <= gCurrentObject->oDrawingDistance && gCurrentObject->oHeldState == HELD_FREE) { +#endif // In render distance (and not being held), show the object. gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; gCurrentObject->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY; diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 363f9afb..498fae0d 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -789,9 +789,13 @@ void load_object_collision_model(void) { } } +#ifndef NODRAWINGDISTANCE if (marioDist < gCurrentObject->oDrawingDistance) { +#endif gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; +#ifndef NODRAWINGDISTANCE } else { gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; } +#endif } diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c index d435d8d8..9296ed50 100644 --- a/src/game/behaviors/butterfly.inc.c +++ b/src/game/behaviors/butterfly.inc.c @@ -107,6 +107,7 @@ void bhv_butterfly_loop(void) { butterfly_act_return_home(); break; } - +#ifndef NODRAWINGDISTANCE set_object_visibility(o, 3000); +#endif } diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index a77c5d5f..9b9c3423 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -53,7 +53,9 @@ static void chain_chomp_act_uninitialized(void) { struct ChainSegment *segments; s32 i; +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 3000.0f) { +#endif segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment)); if (segments != NULL) { // Each segment represents the offset of a chain part to the pivot. @@ -81,7 +83,9 @@ static void chain_chomp_act_uninitialized(void) { cur_obj_unhide(); } } +#ifndef NODRAWINGDISTANCE } +#endif } /** @@ -359,10 +363,12 @@ static void chain_chomp_act_move(void) { f32 maxDistToPivot; // Unload chain if mario is far enough +#ifndef NODRAWINGDISTANCE if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f) { o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN; o->oForwardVel = o->oVelY = 0.0f; } else { +#endif cur_obj_update_floor_and_walls(); switch (o->oChainChompReleaseStatus) { @@ -446,7 +452,9 @@ static void chain_chomp_act_move(void) { o->oGravity = -4.0f; o->oChainChompTargetPitch = -0x3000; } +#ifndef NODRAWINGDISTANCE } +#endif } /** diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c index 913c5834..05619b96 100644 --- a/src/game/behaviors/coin.inc.c +++ b/src/game/behaviors/coin.inc.c @@ -184,17 +184,23 @@ void bhv_coin_formation_loop(void) { s32 bitIndex; switch (o->oAction) { case 0: +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2000.0f) { +#endif for (bitIndex = 0; bitIndex < 8; bitIndex++) { if (!(o->oCoinUnkF4 & (1 << bitIndex))) spawn_coin_in_formation(bitIndex, o->oBehParams2ndByte); } o->oAction++; +#ifndef NODRAWINGDISTANCE } +#endif break; case 1: +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 2100.0f) o->oAction++; +#endif break; case 2: o->oAction = 0; diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c index 839ab8d6..f652ef47 100644 --- a/src/game/behaviors/fish.inc.c +++ b/src/game/behaviors/fish.inc.c @@ -42,7 +42,9 @@ void fish_act_spawn(void) { * If the current level is Secret Aquarium, ignore this requirement. * Fish moves at random with a max-range of 700.0f. */ +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < minDistToMario || gCurrLevelNum == LEVEL_SA) { +#endif for (i = 0; i < schoolQuantity; i++) { fishObject = spawn_object(o, model, bhvFish); fishObject->oBehParams2ndByte = o->oBehParams2ndByte; @@ -50,7 +52,9 @@ void fish_act_spawn(void) { obj_translate_xyz_random(fishObject, 700.0f); } o->oAction = FISH_ACT_ACTIVE; +#ifndef NODRAWINGDISTANCE } +#endif } /** diff --git a/src/game/behaviors/goomba.inc.c b/src/game/behaviors/goomba.inc.c index 2dab2fec..bf47dda1 100644 --- a/src/game/behaviors/goomba.inc.c +++ b/src/game/behaviors/goomba.inc.c @@ -78,7 +78,9 @@ void bhv_goomba_triplet_spawner_update(void) { // If mario is close enough and the goombas aren't currently loaded, then // spawn them if (o->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 3000.0f) { +#endif // The spawner is capable of spawning more than 3 goombas, but this // is not used in the game dAngle = @@ -98,11 +100,13 @@ void bhv_goomba_triplet_spawner_update(void) { } o->oAction += 1; +#ifndef NODRAWINGDISTANCE } } else if (o->oDistanceToMario > 4000.0f) { // If mario is too far away, enter the unloaded action. The goombas // will detect this and unload themselves o->oAction = GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED; +#endif } } diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index 662bb0bd..2f9da864 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -73,14 +73,18 @@ void heave_ho_act_3(void) { void heave_ho_act_0(void) { cur_obj_set_pos_to_home(); +#ifndef NODRAWINGDISTANCE if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) { +#endif cur_obj_become_tangible(); cur_obj_unhide(); o->oAction = 1; +#ifndef NODRAWINGDISTANCE } else { cur_obj_become_intangible(); cur_obj_hide(); } +#endif } void (*sHeaveHoActions[])(void) = { heave_ho_act_0, heave_ho_act_1, heave_ho_act_2, heave_ho_act_3 }; diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index 63a75755..af1cb0a6 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -295,10 +295,14 @@ void king_bobomb_move(void) { cur_obj_move_using_fvel_and_gravity(); cur_obj_call_action_function(sKingBobombActions); exec_anim_sound_state(sKingBobombSoundStates); +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 5000.0f) +#endif cur_obj_enable_rendering(); +#ifndef NODRAWINGDISTANCE else cur_obj_disable_rendering(); +#endif } void bhv_king_bobomb_loop(void) { diff --git a/src/game/behaviors/pokey.inc.c b/src/game/behaviors/pokey.inc.c index df5d11f5..cfcc92c2 100644 --- a/src/game/behaviors/pokey.inc.c +++ b/src/game/behaviors/pokey.inc.c @@ -151,7 +151,9 @@ static void pokey_act_uninitialized(void) { s32 i; s16 partModel; +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2000.0f) { +#endif partModel = MODEL_POKEY_HEAD; for (i = 0; i < 5; i++) { @@ -170,7 +172,9 @@ static void pokey_act_uninitialized(void) { o->oPokeyNumAliveBodyParts = 5; o->oPokeyBottomBodyPartSize = 1.0f; o->oAction = POKEY_ACT_WANDER; +#ifndef NODRAWINGDISTANCE } +#endif } /** @@ -185,9 +189,11 @@ static void pokey_act_wander(void) { if (o->oPokeyNumAliveBodyParts == 0) { obj_mark_for_deletion(o); +#ifndef NODRAWINGDISTANCE } else if (o->oDistanceToMario > 2500.0f) { o->oAction = POKEY_ACT_UNLOAD_PARTS; o->oForwardVel = 0.0f; +#endif } else { treat_far_home_as_mario(1000.0f); cur_obj_update_floor_and_walls(); diff --git a/src/game/behaviors/snufit.inc.c b/src/game/behaviors/snufit.inc.c index f3a0c9ef..76e78c09 100644 --- a/src/game/behaviors/snufit.inc.c +++ b/src/game/behaviors/snufit.inc.c @@ -180,7 +180,11 @@ void bhv_snufit_loop(void) { void bhv_snufit_balls_loop(void) { // If far from Mario or in a different room, despawn. if ((o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) +#ifndef NODRAWINGDISTANCE || (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)) { +#else + || (o->oTimer != 0)) { +#endif obj_mark_for_deletion(o); } diff --git a/src/game/behaviors/triplet_butterfly.inc.c b/src/game/behaviors/triplet_butterfly.inc.c index 1c2b9265..3d16a9d2 100644 --- a/src/game/behaviors/triplet_butterfly.inc.c +++ b/src/game/behaviors/triplet_butterfly.inc.c @@ -54,9 +54,11 @@ static void triplet_butterfly_act_init(void) { } static void triplet_butterfly_act_wander(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 1500.0f) { obj_mark_for_deletion(o); } else { +#endif approach_f32_ptr(&o->oTripletButterflySpeed, 8.0f, 0.5f); if (o->oTimer < 60) { o->oTripletButterflyTargetYaw = cur_obj_angle_to_home(); @@ -82,7 +84,9 @@ static void triplet_butterfly_act_wander(void) { obj_move_pitch_approach(o->oTripletButterflyTargetPitch, 400); cur_obj_rotate_yaw_toward(o->oTripletButterflyTargetYaw, random_linear_offset(400, 800)); +#ifndef NODRAWINGDISTANCE } +#endif } static void triplet_butterfly_act_activate(void) { diff --git a/src/game/behaviors/water_bomb_cannon.inc.c b/src/game/behaviors/water_bomb_cannon.inc.c index 8e9ba33b..fb82e43c 100644 --- a/src/game/behaviors/water_bomb_cannon.inc.c +++ b/src/game/behaviors/water_bomb_cannon.inc.c @@ -38,19 +38,27 @@ void bhv_bubble_cannon_barrel_loop(void) { } void water_bomb_cannon_act_0(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2000.0f) { +#endif spawn_object(o, MODEL_CANNON_BARREL, bhvCannonBarrelBubbles); cur_obj_unhide(); o->oAction = 1; o->oMoveAnglePitch = o->oWaterCannonUnkFC = 0x1C00; +#ifndef NODRAWINGDISTANCE } +#endif } void water_bomb_cannon_act_1(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 2500.0f) { o->oAction = 2; } else if (o->oBehParams2ndByte == 0) { +#else + if (o->oBehParams2ndByte == 0) { +#endif if (o->oWaterCannonUnkF4 != 0) { o->oWaterCannonUnkF4 -= 1; } else { diff --git a/src/game/behaviors/whirlpool.inc.c b/src/game/behaviors/whirlpool.inc.c index 405e0518..5aebebd2 100644 --- a/src/game/behaviors/whirlpool.inc.c +++ b/src/game/behaviors/whirlpool.inc.c @@ -35,7 +35,9 @@ void whirpool_orient_graph(void) { } void bhv_whirlpool_loop(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 5000.0f) { +#endif o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; // not sure if actually an array @@ -52,10 +54,12 @@ void bhv_whirlpool_loop(void) { whirpool_orient_graph(); o->oFaceAngleYaw += 0x1F40; +#ifndef NODRAWINGDISTANCE } else { o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT] = 0; } +#endif cur_obj_play_sound_1(SOUND_ENV_WATER); From 5f99e2159222a12a070d7a9a1edc19aa1602becc Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Tue, 12 May 2020 16:08:34 +0200 Subject: [PATCH 05/73] extend cross compilation support --- Makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index d4bd2846..5e5d3881 100644 --- a/Makefile +++ b/Makefile @@ -424,14 +424,15 @@ else LD := $(CC) endif -CPP := cpp -P -OBJDUMP := objdump -OBJCOPY := objcopy +CPP := $(CROSS)cpp -P +OBJDUMP := $(CROSS)objdump +OBJCOPY := $(CROSS)objcopy PYTHON := python3 +SDLCONFIG := $(CROSS)sdl2-config ifeq ($(WINDOWS_BUILD),1) -CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(CROSS)sdl2-config --cflags` -CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(CROSS)sdl2-config --cflags` +CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags` +CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` else ifeq ($(TARGET_WEB),1) CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -s USE_SDL=2 @@ -439,8 +440,8 @@ CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fn # Linux / Other builds below else -CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(CROSS)sdl2-config --cflags` -CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(CROSS)sdl2-config --cflags` +CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(SDLCONFIG) --cflags` +CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` endif # Check for better camera option @@ -456,14 +457,14 @@ LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base ht else ifeq ($(WINDOWS_BUILD),1) -LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(CROSS)sdl2-config --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static +LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static else # Linux / Other builds below ifeq ($(TARGET_RPI),1) -LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(CROSS)sdl2-config --libs` -no-pie +LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(SDLCONFIG) --libs` -no-pie else -LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm -lGL `$(CROSS)sdl2-config --libs` -no-pie -lpthread +LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm -lGL `$(SDLCONFIG) --libs` -no-pie -lpthread endif endif endif #Added for Pi ifeq From bea82c00bcce52afb02cbc72a0f8d8163ad3a321 Mon Sep 17 00:00:00 2001 From: uwabami Date: Wed, 13 May 2020 09:25:45 +0200 Subject: [PATCH 06/73] Increase GFX_POOL_SIZE to fix overflow in 32bit version - thanks fgsfds --- src/game/display.h | 2 +- src/game/game_init.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/display.h b/src/game/display.h index 0c427111..877c4f0b 100644 --- a/src/game/display.h +++ b/src/game/display.h @@ -3,7 +3,7 @@ #include "types.h" -#define GFX_POOL_SIZE 6400 +#define GFX_POOL_SIZE 64000 extern u16 frameBufferIndex; extern u32 gGlobalTimer; diff --git a/src/game/game_init.h b/src/game/game_init.h index 68db7426..019bad4d 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -51,7 +51,7 @@ extern struct MarioAnimation gDemo; extern u8 gMarioAnims[]; extern u8 gDemoInputs[]; -#define GFX_POOL_SIZE 6400 +#define GFX_POOL_SIZE 64000 struct GfxPool { Gfx buffer[GFX_POOL_SIZE]; From d5d151f322ada2d9152a573aec00770d5720a4e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Wed, 13 May 2020 11:25:22 -0300 Subject: [PATCH 07/73] Fix some overflow issues As found out by @fgsfdsfgs, increase the GFX pool size as to eliminate current overflow-related crashes. --- src/game/display.h | 2 +- src/game/game_init.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/display.h b/src/game/display.h index 0c427111..877c4f0b 100644 --- a/src/game/display.h +++ b/src/game/display.h @@ -3,7 +3,7 @@ #include "types.h" -#define GFX_POOL_SIZE 6400 +#define GFX_POOL_SIZE 64000 extern u16 frameBufferIndex; extern u32 gGlobalTimer; diff --git a/src/game/game_init.h b/src/game/game_init.h index 68db7426..019bad4d 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -51,7 +51,7 @@ extern struct MarioAnimation gDemo; extern u8 gMarioAnims[]; extern u8 gDemoInputs[]; -#define GFX_POOL_SIZE 6400 +#define GFX_POOL_SIZE 64000 struct GfxPool { Gfx buffer[GFX_POOL_SIZE]; From cfeb310d70e32f34d55c80ea0694b2df916c0ed0 Mon Sep 17 00:00:00 2001 From: Hy! <3067205+Hyenadae@users.noreply.github.com> Date: Wed, 13 May 2020 11:35:22 -0300 Subject: [PATCH 08/73] Update to pisetup.sh Fixed current-directory asset placement hints and some minor text changes --- pisetup.sh | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/pisetup.sh b/pisetup.sh index cfd97320..5b34c233 100755 --- a/pisetup.sh +++ b/pisetup.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Super Mario 64 PC on Raspberry Pi +# Find latest updates and code on https://www.github.com/sm64pc/sm64pc +# ToDo: Test on more Pi models with fresh Raspbian and allow existing src folders to be updated. +# clear echo "This script will assist with compiling Super Mario 64 on Raspbian 10" echo "Note that accelerated OpenGL (vc4_drm) is required for maximum performance" @@ -65,7 +69,8 @@ clear echo "Super Mario 64 RPi Initial Setup" if [[ $pi != 4 ]] -then #Dumb idea, but quick hack. We CANNOT enable VC4 for Pi4. +then #Dumb idea, but quick hack. + #We CANNOT enable VC4 for Pi4 as it uses VC6 inxinf=$(inxi -Gx) echo "Checking for pre-enabled VC4 acceleration (inxi -Gx)" @@ -119,24 +124,24 @@ fixmem=$(cat /boot/cmdline.txt | grep cma=128M) else echo "" - echo "Warning: VC4 enabled, but your Rasp Pi has 512MB or less RAM" + echo "Warning: VC4 enabled, but your RasPi has 512MB or less RAM" echo "To ensure VC4_DRM and game compilation is succesful, video memory will be reduced" echo "gpu_mem=48M (config.txt) | cma=128M (cmdline.txt) will be written to /boot " echo "" read -p "Fix mem? (Y/N): " fixmem - if [[ $fixmem =~ "Y" ]] - then - sudo sh -c "echo 'gpu_mem=48' >> /boot/config.txt" - sudo sh -c "echo 'cma=128M' >> /boot/cmdline.txt" - sync - echo "Wrote configuration changes to SD card." - sleep 2 - else - echo "" - echo "Warning: Compilation freezes & errors are likely to occur on your Pi" - echo "" - sleep 3 + if [[ $fixmem =~ "Y" ]] + then + sudo sh -c "echo 'gpu_mem=48' >> /boot/config.txt" + sudo sh -c "echo 'cma=128M' >> /boot/cmdline.txt" + sync + echo "Wrote configuration changes to SD card." + sleep 2 + else + echo "" + echo "Warning: Compilation freezes & errors are likely to occur on your Pi" + echo "" + sleep 3 fi fi fi @@ -149,11 +154,12 @@ read -p "Reboot to enable changes? (Y/N): " fixstart if [[ $fixstart =~ "Y" ]] then echo "" - echo "Rebooting RasPi!" + echo "Rebooting RasPi in 4 seconds! Press Control-C to cancel." + sleep 4 sudo reboot fi -fi -fi #This should never run on a Pi 4 + fi +fi # "Should never run on a Pi 4" part ends here #-------------------------------------------------------------------------------- #------------------------------------------------------------------------------- @@ -182,7 +188,7 @@ fi #------------------------------------------------------------------------------------- clear echo "Optional: Compile SDL2 with 'KMSDRM' for enhanced performance?" -echo "KMSDRM allows Super Mario 64 to be run without GUI/Desktop enabled on boot." +echo "KMSDRM allows Super Mario 64 to be run without GUI/Desktop (Xorg) enabled on boot" echo "" echo "Warning: Compile could take up to an hour on older Raspberry Pi models" read -p "Proceed? (Y/N): " sdlcomp @@ -293,7 +299,12 @@ echo "" echo "Step 3. Compiling Super Mario 64 for the Raspberry Pi" echo "" echo "Warning: Super Mario 64 assets are required in order to compile" +if [[ $curdir ==1 ]] +then +echo "Assets will be extracted from "$PWD" " +else echo "Assets will be extracted from $HOME/src/sm64pi/sm64pc/baserom.(us/eu/jp).z64 " +fi if [[ $curdir == 1 ]] then @@ -312,12 +323,15 @@ else echo "" echo "Please satisfy this requirement before continuing." echo "Exiting Super Mario 64 RasPi setup and compilation script." +echo "" echo "Note: Re-run script once baserom(s) are inserted into" if [[ $curdir == 1 ]] then echo $PWD +echo "" else +echo "" echo $HOME/src/sm64pi/sm64pc/ fi From 47c4b7b41b296edaf4882493b513c16f658532a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Wed, 13 May 2020 13:23:52 -0300 Subject: [PATCH 09/73] Show the console on Windows setting `WINDOWS_CONSOLE=1` --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 5e5d3881..9edf6b8b 100644 --- a/Makefile +++ b/Makefile @@ -458,6 +458,9 @@ else ifeq ($(WINDOWS_BUILD),1) LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static +ifeq ($(WINDOWS_CONSOLE),1) +LDFLAGS += -mconsole +endif else # Linux / Other builds below From d2cff2838f79f82fb2f50bb7e9e234b5437cc053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Wed, 13 May 2020 21:18:22 -0300 Subject: [PATCH 10/73] Fix black edge caused by UB Seems to affect certain targets such as `aarch64`. This fix originally by @Emill. --- include/gfx_dimensions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gfx_dimensions.h b/include/gfx_dimensions.h index dfc0394d..5dc8f6b8 100644 --- a/include/gfx_dimensions.h +++ b/include/gfx_dimensions.h @@ -6,8 +6,8 @@ #include "pc/gfx/gfx_pc.h" #define GFX_DIMENSIONS_FROM_LEFT_EDGE(v) (SCREEN_WIDTH / 2 - SCREEN_HEIGHT / 2 * gfx_current_dimensions.aspect_ratio + (v)) #define GFX_DIMENSIONS_FROM_RIGHT_EDGE(v) (SCREEN_WIDTH / 2 + SCREEN_HEIGHT / 2 * gfx_current_dimensions.aspect_ratio - (v)) -#define GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(v) floorf(GFX_DIMENSIONS_FROM_LEFT_EDGE(v)) -#define GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(v) ceilf(GFX_DIMENSIONS_FROM_RIGHT_EDGE(v)) +#define GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(v) ((int)floorf(GFX_DIMENSIONS_FROM_LEFT_EDGE(v))) +#define GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(v) ((int)ceilf(GFX_DIMENSIONS_FROM_RIGHT_EDGE(v))) #define GFX_DIMENSIONS_ASPECT_RATIO (gfx_current_dimensions.aspect_ratio) #else #define GFX_DIMENSIONS_FROM_LEFT_EDGE(v) (v) From 87dac5d916bddb50f5193d96db09f1ddbd0b61ab Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 16:11:59 +0200 Subject: [PATCH 11/73] fix bugged Heave-Ho in Wet-Dry World --- src/game/behaviors/heave_ho.inc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index 2f9da864..2cbd1f0e 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -72,19 +72,19 @@ void heave_ho_act_3(void) { } void heave_ho_act_0(void) { - cur_obj_set_pos_to_home(); #ifndef NODRAWINGDISTANCE if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) { +#else + if (find_water_level(o->oPosX, o->oPosZ) < (o->oPosY - 50.0f)) { #endif + cur_obj_set_pos_to_home(); cur_obj_become_tangible(); cur_obj_unhide(); o->oAction = 1; -#ifndef NODRAWINGDISTANCE } else { cur_obj_become_intangible(); cur_obj_hide(); } -#endif } void (*sHeaveHoActions[])(void) = { heave_ho_act_0, heave_ho_act_1, heave_ho_act_2, heave_ho_act_3 }; From a773e68c15498e13b4486f70a1bdf6482147062b Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 16:24:00 +0200 Subject: [PATCH 12/73] fix Lakitu's cloud not appearing from a distance --- src/game/behaviors/enemy_lakitu.inc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/behaviors/enemy_lakitu.inc.c b/src/game/behaviors/enemy_lakitu.inc.c index 056c3f13..cacd732f 100644 --- a/src/game/behaviors/enemy_lakitu.inc.c +++ b/src/game/behaviors/enemy_lakitu.inc.c @@ -24,12 +24,16 @@ static struct ObjectHitbox sEnemyLakituHitbox = { * Wait for mario to approach, then spawn the cloud and become visible. */ static void enemy_lakitu_act_uninitialized(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2000.0f) { +#endif spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud); cur_obj_unhide(); o->oAction = ENEMY_LAKITU_ACT_MAIN; +#ifndef NODRAWINGDISTANCE } +#endif } /** From 8d2e0f5ffdca4df6dc6aea5d798b700d7ee7457b Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 17:07:14 +0200 Subject: [PATCH 13/73] fix Fwoosh in Tall, Tall Mountain --- src/game/behaviors/butterfly.inc.c | 1 + src/game/behaviors/cloud.inc.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c index 9296ed50..8c0e7145 100644 --- a/src/game/behaviors/butterfly.inc.c +++ b/src/game/behaviors/butterfly.inc.c @@ -107,6 +107,7 @@ void bhv_butterfly_loop(void) { butterfly_act_return_home(); break; } + #ifndef NODRAWINGDISTANCE set_object_visibility(o, 3000); #endif diff --git a/src/game/behaviors/cloud.inc.c b/src/game/behaviors/cloud.inc.c index e5cb9bed..fa82e3f4 100644 --- a/src/game/behaviors/cloud.inc.c +++ b/src/game/behaviors/cloud.inc.c @@ -47,10 +47,14 @@ static void cloud_act_spawn_parts(void) { * Wait for mario to approach, then unhide and enter the spawn parts action. */ static void cloud_act_fwoosh_hidden(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2000.0f) { +#endif cur_obj_unhide(); o->oAction = CLOUD_ACT_SPAWN_PARTS; +#ifndef NODRAWINGDISTANCE } +#endif } /** @@ -58,9 +62,11 @@ static void cloud_act_fwoosh_hidden(void) { * long enough, blow wind at him. */ static void cloud_fwoosh_update(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 2500.0f) { o->oAction = CLOUD_ACT_UNLOAD; } else { +#endif if (o->oCloudBlowing) { o->header.gfx.scale[0] += o->oCloudGrowSpeed; @@ -95,7 +101,9 @@ static void cloud_fwoosh_update(void) { } cur_obj_scale(o->header.gfx.scale[0]); +#ifndef NODRAWINGDISTANCE } +#endif } /** From 2bdb1ab5513887912fa42696c5943782c2ba9c8f Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 18:47:12 +0200 Subject: [PATCH 14/73] several fixes and improvements --- src/game/behaviors/bub.inc.c | 4 ++++ src/game/behaviors/butterfly.inc.c | 2 -- src/game/behaviors/fire_spitter.inc.c | 4 ++++ src/game/behaviors/lll_floating_wood_piece.inc.c | 6 ++++++ src/game/behaviors/lll_rotating_hex_flame.inc.c | 4 ++++ src/game/obj_behaviors.c | 4 ++++ 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/game/behaviors/bub.inc.c b/src/game/behaviors/bub.inc.c index e8e63096..7bf71690 100644 --- a/src/game/behaviors/bub.inc.c +++ b/src/game/behaviors/bub.inc.c @@ -8,11 +8,15 @@ void bub_spawner_act_0(void) { s32 i; s32 sp18 = o->oBirdChirpChirpUnkF4; +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 1500.0f) { +#endif for (i = 0; i < sp18; i++) spawn_object(o, MODEL_BUB, bhvBub); o->oAction = 1; +#ifndef NODRAWINGDISTANCE } +#endif } void bub_spawner_act_1(void) { diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c index 8c0e7145..d435d8d8 100644 --- a/src/game/behaviors/butterfly.inc.c +++ b/src/game/behaviors/butterfly.inc.c @@ -108,7 +108,5 @@ void bhv_butterfly_loop(void) { break; } -#ifndef NODRAWINGDISTANCE set_object_visibility(o, 3000); -#endif } diff --git a/src/game/behaviors/fire_spitter.inc.c b/src/game/behaviors/fire_spitter.inc.c index d64bcf7e..a703b03d 100644 --- a/src/game/behaviors/fire_spitter.inc.c +++ b/src/game/behaviors/fire_spitter.inc.c @@ -1,10 +1,14 @@ static void fire_spitter_act_idle(void) { approach_f32_ptr(&o->header.gfx.scale[0], 0.2f, 0.002f); +#ifndef NODRAWINGDISTANCE if (o->oTimer > 150 && o->oDistanceToMario < 800.0f && !(o->oMoveFlags & 0x00000078)) { +#endif o->oAction = FIRE_SPITTER_ACT_SPIT_FIRE; o->oFireSpitterScaleVel = 0.05f; +#ifndef NODRAWINGDISTANCE } +#endif } static void fire_spitter_act_spit_fire(void) { diff --git a/src/game/behaviors/lll_floating_wood_piece.inc.c b/src/game/behaviors/lll_floating_wood_piece.inc.c index a484471c..fad31f3f 100644 --- a/src/game/behaviors/lll_floating_wood_piece.inc.c +++ b/src/game/behaviors/lll_floating_wood_piece.inc.c @@ -14,18 +14,24 @@ void bhv_lll_floating_wood_bridge_loop(void) { s32 i; switch (o->oAction) { case 0: +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 2500.0f) { +#endif for (i = 1; i < 4; i++) { sp3C = spawn_object_relative(0, (i - 2) * 300, 0, 0, o, MODEL_LLL_WOOD_BRIDGE, bhvLllWoodPiece); sp3C->oLllWoodPieceUnkF4 = i * 4096; } o->oAction = 1; +#ifndef NODRAWINGDISTANCE } +#endif break; case 1: +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 2600.0f) o->oAction = 2; +#endif break; case 2: o->oAction = 0; diff --git a/src/game/behaviors/lll_rotating_hex_flame.inc.c b/src/game/behaviors/lll_rotating_hex_flame.inc.c index efabfca8..fc707330 100644 --- a/src/game/behaviors/lll_rotating_hex_flame.inc.c +++ b/src/game/behaviors/lll_rotating_hex_flame.inc.c @@ -30,7 +30,9 @@ void fire_bar_spawn_flames(s16 a0) { } void fire_bar_act_0(void) { +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario < 3000.0f) +#endif o->oAction = 1; } @@ -45,8 +47,10 @@ void fire_bar_act_1(void) { void fire_bar_act_2(void) { o->oAngleVelYaw = -0x100; o->oMoveAngleYaw += o->oAngleVelYaw; +#ifndef NODRAWINGDISTANCE if (o->oDistanceToMario > 3200.0f) o->oAction = 3; +#endif } void fire_bar_act_3(void) { diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index 0e2c7c86..68cebe5d 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -527,11 +527,15 @@ void set_object_visibility(struct Object *obj, s32 dist) { f32 objY = obj->oPosY; f32 objZ = obj->oPosZ; +#ifndef NODRAWINGDISTANCE if (is_point_within_radius_of_mario(objX, objY, objZ, dist) == TRUE) { +#endif obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; +#ifndef NODRAWINGDISTANCE } else { obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; } +#endif } /** From a26c36b6b4fb38683b82862ca77b6c1041efa10d Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 19:08:30 +0200 Subject: [PATCH 15/73] fix Fire Spitter --- src/game/behaviors/fire_spitter.inc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/game/behaviors/fire_spitter.inc.c b/src/game/behaviors/fire_spitter.inc.c index a703b03d..d64bcf7e 100644 --- a/src/game/behaviors/fire_spitter.inc.c +++ b/src/game/behaviors/fire_spitter.inc.c @@ -1,14 +1,10 @@ static void fire_spitter_act_idle(void) { approach_f32_ptr(&o->header.gfx.scale[0], 0.2f, 0.002f); -#ifndef NODRAWINGDISTANCE if (o->oTimer > 150 && o->oDistanceToMario < 800.0f && !(o->oMoveFlags & 0x00000078)) { -#endif o->oAction = FIRE_SPITTER_ACT_SPIT_FIRE; o->oFireSpitterScaleVel = 0.05f; -#ifndef NODRAWINGDISTANCE } -#endif } static void fire_spitter_act_spit_fire(void) { From 9db36183b4cd6c9cee897b6cdb97886ac8f4373d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Thu, 14 May 2020 14:47:59 -0300 Subject: [PATCH 16/73] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fc8e1320..92b4f75c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * Variable aspect ratio and resolution. The game can now correctly render at basically any window size. * Native xinput controller support. On Linux, DualShock 4 has been confirmed to work plug-and-play. * Analog camera control and mouse look. (Activate with `make BETTERCAMERA=1`.) + * An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCES=1`.) + * In-game control binding, currently available on the `testing` branch. ## Building For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki). From 2901e94d5c3ce8236775cf3a9f7e4149861092ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Thu, 14 May 2020 14:49:05 -0300 Subject: [PATCH 17/73] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92b4f75c..d28d5de0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * Variable aspect ratio and resolution. The game can now correctly render at basically any window size. * Native xinput controller support. On Linux, DualShock 4 has been confirmed to work plug-and-play. * Analog camera control and mouse look. (Activate with `make BETTERCAMERA=1`.) - * An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCES=1`.) + * An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCE=1`.) * In-game control binding, currently available on the `testing` branch. ## Building From e166fc15121ff037978b9f1c69e9684a22a429d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Thu, 14 May 2020 14:57:47 -0300 Subject: [PATCH 18/73] Remove patch as functionality has been merged --- enhancements/no_draw_distance/README.md | 10 - .../no_draw_distance/nodrawdistance.patch | 406 ------------------ 2 files changed, 416 deletions(-) delete mode 100644 enhancements/no_draw_distance/README.md delete mode 100644 enhancements/no_draw_distance/nodrawdistance.patch diff --git a/enhancements/no_draw_distance/README.md b/enhancements/no_draw_distance/README.md deleted file mode 100644 index dd890383..00000000 --- a/enhancements/no_draw_distance/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# No Draw Distances - -This is a work-in-progress by [wabberz](https://github.com/wabberz) that disables the drawing distance for most objects and enemies. - -**This will crash some levels in the 32-bit version**. - -[Related Push Request](https://github.com/sm64pc/sm64pc/pull/75). - -For instructions on how to apply patches, please refer to [the Wiki](https://github.com/sm64pc/sm64pc/wiki/Patches). - diff --git a/enhancements/no_draw_distance/nodrawdistance.patch b/enhancements/no_draw_distance/nodrawdistance.patch deleted file mode 100644 index b986b1a6..00000000 --- a/enhancements/no_draw_distance/nodrawdistance.patch +++ /dev/null @@ -1,406 +0,0 @@ -From c98a263cf40520bf0d131eb2d1a2f90240787c98 Mon Sep 17 00:00:00 2001 -From: uwabami -Date: Tue, 12 May 2020 09:26:16 +0200 -Subject: [PATCH] adding option to disable draw distance - ---- - Makefile | 8 ++++++++ - src/engine/behavior_script.c | 4 ++++ - src/engine/surface_load.c | 4 ++++ - src/game/behaviors/butterfly.inc.c | 3 ++- - src/game/behaviors/chain_chomp.inc.c | 8 ++++++++ - src/game/behaviors/coin.inc.c | 6 ++++++ - src/game/behaviors/fish.inc.c | 4 ++++ - src/game/behaviors/goomba.inc.c | 4 ++++ - src/game/behaviors/heave_ho.inc.c | 4 ++++ - src/game/behaviors/king_bobomb.inc.c | 4 ++++ - src/game/behaviors/pokey.inc.c | 6 ++++++ - src/game/behaviors/snufit.inc.c | 4 ++++ - src/game/behaviors/triplet_butterfly.inc.c | 4 ++++ - src/game/behaviors/water_bomb_cannon.inc.c | 8 ++++++++ - src/game/behaviors/whirlpool.inc.c | 4 ++++ - 15 files changed, 74 insertions(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index d4bd284..efeb63e 100644 ---- a/Makefile -+++ b/Makefile -@@ -27,6 +27,8 @@ COMPILER ?= ido - - # Disable better camera by default - BETTERCAMERA ?= 0 -+# Disable no drawing distance by default -+NODRAWINGDISTANCE ?= 0 - - # Build for Emscripten/WebGL - TARGET_WEB ?= 0 -@@ -449,6 +451,12 @@ CC_CHECK += -DBETTERCAMERA - CFLAGS += -DBETTERCAMERA - endif - -+# Check for no drawing distance option -+ifeq ($(NODRAWINGDISTANCE),1) -+CC_CHECK += -DNODRAWINGDISTANCE -+CFLAGS += -DNODRAWINGDISTANCE -+endif -+ - ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) - - ifeq ($(TARGET_WEB),1) -diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c -index edd5247..feb6fef 100644 ---- a/src/engine/behavior_script.c -+++ b/src/engine/behavior_script.c -@@ -987,11 +987,15 @@ void cur_obj_update(void) { - } else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) { - if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) { - // If the object has a render distance, check if it should be shown. -+#ifndef NODRAWINGDISTANCE - if (distanceFromMario > gCurrentObject->oDrawingDistance) { - // Out of render distance, hide the object. - gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; - gCurrentObject->activeFlags |= ACTIVE_FLAG_FAR_AWAY; - } else if (gCurrentObject->oHeldState == HELD_FREE) { -+#else -+ if (distanceFromMario <= gCurrentObject->oDrawingDistance && gCurrentObject->oHeldState == HELD_FREE) { -+#endif - // In render distance (and not being held), show the object. - gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; - gCurrentObject->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY; -diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c -index 363f9af..498fae0 100644 ---- a/src/engine/surface_load.c -+++ b/src/engine/surface_load.c -@@ -789,9 +789,13 @@ void load_object_collision_model(void) { - } - } - -+#ifndef NODRAWINGDISTANCE - if (marioDist < gCurrentObject->oDrawingDistance) { -+#endif - gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; -+#ifndef NODRAWINGDISTANCE - } else { - gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; - } -+#endif - } -diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c -index d435d8d..9296ed5 100644 ---- a/src/game/behaviors/butterfly.inc.c -+++ b/src/game/behaviors/butterfly.inc.c -@@ -107,6 +107,7 @@ void bhv_butterfly_loop(void) { - butterfly_act_return_home(); - break; - } -- -+#ifndef NODRAWINGDISTANCE - set_object_visibility(o, 3000); -+#endif - } -diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c -index a77c5d5..9b9c342 100644 ---- a/src/game/behaviors/chain_chomp.inc.c -+++ b/src/game/behaviors/chain_chomp.inc.c -@@ -53,7 +53,9 @@ static void chain_chomp_act_uninitialized(void) { - struct ChainSegment *segments; - s32 i; - -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 3000.0f) { -+#endif - segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment)); - if (segments != NULL) { - // Each segment represents the offset of a chain part to the pivot. -@@ -81,7 +83,9 @@ static void chain_chomp_act_uninitialized(void) { - cur_obj_unhide(); - } - } -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - /** -@@ -359,10 +363,12 @@ static void chain_chomp_act_move(void) { - f32 maxDistToPivot; - - // Unload chain if mario is far enough -+#ifndef NODRAWINGDISTANCE - if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f) { - o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN; - o->oForwardVel = o->oVelY = 0.0f; - } else { -+#endif - cur_obj_update_floor_and_walls(); - - switch (o->oChainChompReleaseStatus) { -@@ -446,7 +452,9 @@ static void chain_chomp_act_move(void) { - o->oGravity = -4.0f; - o->oChainChompTargetPitch = -0x3000; - } -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - /** -diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c -index 913c583..05619b9 100644 ---- a/src/game/behaviors/coin.inc.c -+++ b/src/game/behaviors/coin.inc.c -@@ -184,17 +184,23 @@ void bhv_coin_formation_loop(void) { - s32 bitIndex; - switch (o->oAction) { - case 0: -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 2000.0f) { -+#endif - for (bitIndex = 0; bitIndex < 8; bitIndex++) { - if (!(o->oCoinUnkF4 & (1 << bitIndex))) - spawn_coin_in_formation(bitIndex, o->oBehParams2ndByte); - } - o->oAction++; -+#ifndef NODRAWINGDISTANCE - } -+#endif - break; - case 1: -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario > 2100.0f) - o->oAction++; -+#endif - break; - case 2: - o->oAction = 0; -diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c -index 839ab8d..f652ef4 100644 ---- a/src/game/behaviors/fish.inc.c -+++ b/src/game/behaviors/fish.inc.c -@@ -42,7 +42,9 @@ void fish_act_spawn(void) { - * If the current level is Secret Aquarium, ignore this requirement. - * Fish moves at random with a max-range of 700.0f. - */ -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < minDistToMario || gCurrLevelNum == LEVEL_SA) { -+#endif - for (i = 0; i < schoolQuantity; i++) { - fishObject = spawn_object(o, model, bhvFish); - fishObject->oBehParams2ndByte = o->oBehParams2ndByte; -@@ -50,7 +52,9 @@ void fish_act_spawn(void) { - obj_translate_xyz_random(fishObject, 700.0f); - } - o->oAction = FISH_ACT_ACTIVE; -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - /** -diff --git a/src/game/behaviors/goomba.inc.c b/src/game/behaviors/goomba.inc.c -index 2dab2fe..bf47dda 100644 ---- a/src/game/behaviors/goomba.inc.c -+++ b/src/game/behaviors/goomba.inc.c -@@ -78,7 +78,9 @@ void bhv_goomba_triplet_spawner_update(void) { - // If mario is close enough and the goombas aren't currently loaded, then - // spawn them - if (o->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) { -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 3000.0f) { -+#endif - // The spawner is capable of spawning more than 3 goombas, but this - // is not used in the game - dAngle = -@@ -98,11 +100,13 @@ void bhv_goomba_triplet_spawner_update(void) { - } - - o->oAction += 1; -+#ifndef NODRAWINGDISTANCE - } - } else if (o->oDistanceToMario > 4000.0f) { - // If mario is too far away, enter the unloaded action. The goombas - // will detect this and unload themselves - o->oAction = GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED; -+#endif - } - } - -diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c -index 662bb0b..2f9da86 100644 ---- a/src/game/behaviors/heave_ho.inc.c -+++ b/src/game/behaviors/heave_ho.inc.c -@@ -73,14 +73,18 @@ void heave_ho_act_3(void) { - - void heave_ho_act_0(void) { - cur_obj_set_pos_to_home(); -+#ifndef NODRAWINGDISTANCE - if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) { -+#endif - cur_obj_become_tangible(); - cur_obj_unhide(); - o->oAction = 1; -+#ifndef NODRAWINGDISTANCE - } else { - cur_obj_become_intangible(); - cur_obj_hide(); - } -+#endif - } - - void (*sHeaveHoActions[])(void) = { heave_ho_act_0, heave_ho_act_1, heave_ho_act_2, heave_ho_act_3 }; -diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c -index 63a7575..af1cb0a 100644 ---- a/src/game/behaviors/king_bobomb.inc.c -+++ b/src/game/behaviors/king_bobomb.inc.c -@@ -295,10 +295,14 @@ void king_bobomb_move(void) { - cur_obj_move_using_fvel_and_gravity(); - cur_obj_call_action_function(sKingBobombActions); - exec_anim_sound_state(sKingBobombSoundStates); -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 5000.0f) -+#endif - cur_obj_enable_rendering(); -+#ifndef NODRAWINGDISTANCE - else - cur_obj_disable_rendering(); -+#endif - } - - void bhv_king_bobomb_loop(void) { -diff --git a/src/game/behaviors/pokey.inc.c b/src/game/behaviors/pokey.inc.c -index df5d11f..cfcc92c 100644 ---- a/src/game/behaviors/pokey.inc.c -+++ b/src/game/behaviors/pokey.inc.c -@@ -151,7 +151,9 @@ static void pokey_act_uninitialized(void) { - s32 i; - s16 partModel; - -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 2000.0f) { -+#endif - partModel = MODEL_POKEY_HEAD; - - for (i = 0; i < 5; i++) { -@@ -170,7 +172,9 @@ static void pokey_act_uninitialized(void) { - o->oPokeyNumAliveBodyParts = 5; - o->oPokeyBottomBodyPartSize = 1.0f; - o->oAction = POKEY_ACT_WANDER; -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - /** -@@ -185,9 +189,11 @@ static void pokey_act_wander(void) { - - if (o->oPokeyNumAliveBodyParts == 0) { - obj_mark_for_deletion(o); -+#ifndef NODRAWINGDISTANCE - } else if (o->oDistanceToMario > 2500.0f) { - o->oAction = POKEY_ACT_UNLOAD_PARTS; - o->oForwardVel = 0.0f; -+#endif - } else { - treat_far_home_as_mario(1000.0f); - cur_obj_update_floor_and_walls(); -diff --git a/src/game/behaviors/snufit.inc.c b/src/game/behaviors/snufit.inc.c -index f3a0c9e..76e78c0 100644 ---- a/src/game/behaviors/snufit.inc.c -+++ b/src/game/behaviors/snufit.inc.c -@@ -180,7 +180,11 @@ void bhv_snufit_loop(void) { - void bhv_snufit_balls_loop(void) { - // If far from Mario or in a different room, despawn. - if ((o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) -+#ifndef NODRAWINGDISTANCE - || (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)) { -+#else -+ || (o->oTimer != 0)) { -+#endif - obj_mark_for_deletion(o); - } - -diff --git a/src/game/behaviors/triplet_butterfly.inc.c b/src/game/behaviors/triplet_butterfly.inc.c -index 1c2b926..3d16a9d 100644 ---- a/src/game/behaviors/triplet_butterfly.inc.c -+++ b/src/game/behaviors/triplet_butterfly.inc.c -@@ -54,9 +54,11 @@ static void triplet_butterfly_act_init(void) { - } - - static void triplet_butterfly_act_wander(void) { -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario > 1500.0f) { - obj_mark_for_deletion(o); - } else { -+#endif - approach_f32_ptr(&o->oTripletButterflySpeed, 8.0f, 0.5f); - if (o->oTimer < 60) { - o->oTripletButterflyTargetYaw = cur_obj_angle_to_home(); -@@ -82,7 +84,9 @@ static void triplet_butterfly_act_wander(void) { - - obj_move_pitch_approach(o->oTripletButterflyTargetPitch, 400); - cur_obj_rotate_yaw_toward(o->oTripletButterflyTargetYaw, random_linear_offset(400, 800)); -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - static void triplet_butterfly_act_activate(void) { -diff --git a/src/game/behaviors/water_bomb_cannon.inc.c b/src/game/behaviors/water_bomb_cannon.inc.c -index 8e9ba33..fb82e43 100644 ---- a/src/game/behaviors/water_bomb_cannon.inc.c -+++ b/src/game/behaviors/water_bomb_cannon.inc.c -@@ -38,19 +38,27 @@ void bhv_bubble_cannon_barrel_loop(void) { - } - - void water_bomb_cannon_act_0(void) { -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 2000.0f) { -+#endif - spawn_object(o, MODEL_CANNON_BARREL, bhvCannonBarrelBubbles); - cur_obj_unhide(); - - o->oAction = 1; - o->oMoveAnglePitch = o->oWaterCannonUnkFC = 0x1C00; -+#ifndef NODRAWINGDISTANCE - } -+#endif - } - - void water_bomb_cannon_act_1(void) { -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario > 2500.0f) { - o->oAction = 2; - } else if (o->oBehParams2ndByte == 0) { -+#else -+ if (o->oBehParams2ndByte == 0) { -+#endif - if (o->oWaterCannonUnkF4 != 0) { - o->oWaterCannonUnkF4 -= 1; - } else { -diff --git a/src/game/behaviors/whirlpool.inc.c b/src/game/behaviors/whirlpool.inc.c -index 405e051..5aebebd 100644 ---- a/src/game/behaviors/whirlpool.inc.c -+++ b/src/game/behaviors/whirlpool.inc.c -@@ -35,7 +35,9 @@ void whirpool_orient_graph(void) { - } - - void bhv_whirlpool_loop(void) { -+#ifndef NODRAWINGDISTANCE - if (o->oDistanceToMario < 5000.0f) { -+#endif - o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; - - // not sure if actually an array -@@ -52,10 +54,12 @@ void bhv_whirlpool_loop(void) { - whirpool_orient_graph(); - - o->oFaceAngleYaw += 0x1F40; -+#ifndef NODRAWINGDISTANCE - } else { - o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; - gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT] = 0; - } -+#endif - - cur_obj_play_sound_1(SOUND_ENV_WATER); - From cc4641f2a955f5fafbe0235f0da6c8e1a492ae75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Thu, 14 May 2020 15:25:11 -0300 Subject: [PATCH 19/73] Add --skip-intro mention --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d28d5de0..4a633108 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * Analog camera control and mouse look. (Activate with `make BETTERCAMERA=1`.) * An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCE=1`.) * In-game control binding, currently available on the `testing` branch. + * Skip introductory Peach & Lakitu cutscenes with a `--skip-intro` CLI option, currently available on `testing` and `skip-intro` branches. ## Building For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki). From 8017d1dfa456dcf5adf16d25503d7543eefab542 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 15 May 2020 01:22:50 +0300 Subject: [PATCH 20/73] fix cursor on Mario head screen (fixes #28) gDPSetScissor fix originally by Emil --- src/goddard/renderer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/goddard/renderer.c b/src/goddard/renderer.c index b5b7fafb..06928dc7 100644 --- a/src/goddard/renderer.c +++ b/src/goddard/renderer.c @@ -22,6 +22,7 @@ #include "gd_math.h" #include "shape_helper.h" +#include "config.h" #include "gfx_dimensions.h" #define MAX_GD_DLS 1000 @@ -2326,7 +2327,7 @@ void start_view_dl(struct ObjView *view) { uly = lry - 1.0f; } - gDPSetScissor(next_gfx(), G_SC_NON_INTERLACE, ulx, uly, lrx, lry); + // gDPSetScissor(next_gfx(), G_SC_NON_INTERLACE, ulx, uly, lrx, lry); // N64 only gSPClearGeometryMode(next_gfx(), 0xFFFFFFFF); gSPSetGeometryMode(next_gfx(), G_LIGHTING | G_CULL_BACK | G_SHADING_SMOOTH | G_SHADE); if (view->flags & VIEW_ALLOC_ZBUF) { @@ -2985,9 +2986,9 @@ void update_cursor(void) { reset_dlnum_indices(sHandShape->gdDls[gGdFrameBuf]); if (gGdCtrl.btnApressed) { - gd_put_sprite((u16 *) gd_texture_hand_closed, sHandView->upperLeft.x, sHandView->upperLeft.y, 0x20, 0x20); + gd_put_sprite((u16 *) gd_texture_hand_closed, GFX_DIMENSIONS_FROM_LEFT_EDGE(sHandView->upperLeft.x), sHandView->upperLeft.y, 0x20, 0x20); } else { - gd_put_sprite((u16 *) gd_texture_hand_open, sHandView->upperLeft.x, sHandView->upperLeft.y, 0x20, 0x20); + gd_put_sprite((u16 *) gd_texture_hand_open, GFX_DIMENSIONS_FROM_LEFT_EDGE(sHandView->upperLeft.x), sHandView->upperLeft.y, 0x20, 0x20); } gd_enddlsplist_parent(); From 70ca0af987be1132abe2c3cb44c942cd6e33b9ca Mon Sep 17 00:00:00 2001 From: uncletrunks Date: Thu, 14 May 2020 20:31:52 -0500 Subject: [PATCH 21/73] adds cylindrical billboarding, enables it for trees. --- data/behavior_data.c | 14 +-- src/engine/behavior_script.c | 159 +++++++++++++++++--------------- src/engine/graph_node.h | 3 +- src/engine/math_util.c | 20 ++++ src/engine/math_util.h | 1 + src/game/behaviors/cannon.inc.c | 10 +- src/game/object_helpers.c | 6 +- src/game/object_helpers.h | 1 + src/game/rendering_graph_node.c | 9 +- 9 files changed, 134 insertions(+), 89 deletions(-) diff --git a/data/behavior_data.c b/data/behavior_data.c index 13212d3b..8fc3d518 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -114,7 +114,7 @@ // Often used to end behavior scripts that do not contain an infinite loop. #define BREAK() \ BC_B(0x0A) - + // Exits the behavior script, unused. #define BREAK_UNUSED() \ BC_B(0x0B) @@ -175,15 +175,15 @@ #define ADD_INT_RAND_RSHIFT(field, min, rshift) \ BC_BBH(0x17, field, min), \ BC_H(rshift) - + // No operation. Unused. #define CMD_NOP_1(field) \ BC_BB(0x18, field) - + // No operation. Unused. #define CMD_NOP_2(field) \ BC_BB(0x19, field) - + // No operation. Unused. #define CMD_NOP_3(field) \ BC_BB(0x1A, field) @@ -219,6 +219,9 @@ #define BILLBOARD() \ BC_B(0x21) +#define CYLBOARD() \ + BC_B(0x38) + // Hides the current object. #define HIDE() \ BC_B(0x22) @@ -3181,6 +3184,7 @@ const BehaviorScript bhvFloorTrapInCastle[] = { const BehaviorScript bhvTree[] = { BEGIN(OBJ_LIST_POLELIKE), BILLBOARD(), + CYLBOARD(), OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE), SET_INT(oInteractType, INTERACT_POLE), SET_HITBOX(/*Radius*/ 80, /*Height*/ 500), @@ -6105,5 +6109,3 @@ const BehaviorScript bhvIntroScene[] = { CALL_NATIVE(bhv_intro_scene_loop), END_LOOP(), }; - - diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index feb6fefd..539f3a32 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -98,10 +98,10 @@ static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) { // Retrieve the last behavior command address from the object's behavior stack. static uintptr_t cur_obj_bhv_stack_pop(void) { uintptr_t bhvAddr; - + gCurrentObject->bhvStackIndex--; bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex]; - + return bhvAddr; } @@ -115,7 +115,7 @@ static void stub_behavior_script_1(void) { // Usage: HIDE() static s32 bhv_cmd_hide(void) { cur_obj_hide(); - + gCurBhvCommand++; return BHV_PROC_CONTINUE; } @@ -124,7 +124,7 @@ static s32 bhv_cmd_hide(void) { // Usage: DISABLE_RENDERING() static s32 bhv_cmd_disable_rendering(void) { gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; - + gCurBhvCommand++; return BHV_PROC_CONTINUE; } @@ -133,7 +133,15 @@ static s32 bhv_cmd_disable_rendering(void) { // Usage: BILLBOARD() static s32 bhv_cmd_billboard(void) { gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_BILLBOARD; - + + gCurBhvCommand++; + return BHV_PROC_CONTINUE; +} + +// Command 0x +static s32 bhv_cmd_cylboard(void) { + gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_CYLBOARD; + gCurBhvCommand++; return BHV_PROC_CONTINUE; } @@ -142,9 +150,9 @@ static s32 bhv_cmd_billboard(void) { // Usage: SET_MODEL(modelID) static s32 bhv_cmd_set_model(void) { s32 modelID = BHV_CMD_GET_2ND_S16(0); - + gCurrentObject->header.gfx.sharedChild = gLoadedGraphNodes[modelID]; - + gCurBhvCommand++; return BHV_PROC_CONTINUE; } @@ -216,7 +224,7 @@ static s32 bhv_cmd_break_unused(void) { static s32 bhv_cmd_call(void) { const BehaviorScript *jumpAddress; gCurBhvCommand++; - + cur_obj_bhv_stack_push(BHV_CMD_GET_ADDR_OF_CMD(1)); // Store address of the next bhv command in the stack. jumpAddress = segmented_to_virtual(BHV_CMD_GET_VPTR(0)); gCurBhvCommand = jumpAddress; // Jump to the new address. @@ -300,7 +308,7 @@ static s32 bhv_cmd_begin_repeat(void) { static s32 bhv_cmd_end_repeat(void) { u32 count = cur_obj_bhv_stack_pop(); // Retrieve loop count from the stack. count--; - + if (count != 0) { gCurBhvCommand = (const BehaviorScript *) cur_obj_bhv_stack_pop(); // Jump back to the first command in the loop // Save address and count to the stack again @@ -320,7 +328,7 @@ static s32 bhv_cmd_end_repeat(void) { static s32 bhv_cmd_end_repeat_continue(void) { u32 count = cur_obj_bhv_stack_pop(); count--; - + if (count != 0) { gCurBhvCommand = (const BehaviorScript *) cur_obj_bhv_stack_pop(); // Jump back to the first command in the loop // Save address and count to the stack again @@ -546,7 +554,7 @@ static s32 bhv_cmd_drop_to_floor(void) { f32 x = gCurrentObject->oPosX; f32 y = gCurrentObject->oPosY; f32 z = gCurrentObject->oPosZ; - + f32 floor = find_floor_height(x, y + 200.0f, z); gCurrentObject->oPosY = floor; gCurrentObject->oMoveFlags |= OBJ_MOVE_ON_GROUND; @@ -665,7 +673,7 @@ static s32 bhv_cmd_nop_4(void) { static s32 bhv_cmd_begin(void) { // These objects were likely very early objects, which is why this code is here // instead of in the respective behavior scripts. - + // Initiate the room if the object is a haunted chair or the mad piano. if (cur_obj_has_behavior(bhvHauntedChair)) { bhv_init_room(); @@ -696,7 +704,7 @@ static void bhv_cmd_set_int_random_from_table(s32 tableSize) { } cur_obj_set_int(field, table[(s32)(tableSize * random_float())]); - + // Does not increment gCurBhvCommand or return a bhv status } @@ -719,7 +727,7 @@ static s32 bhv_cmd_set_int_random_from_table(void) { // Set the field to a random entry of the table. cur_obj_set_int(field, table[(s32)(tableSize * random_float())]); - + gCurBhvCommand += (tableSize / 2) + 1; return BHV_PROC_CONTINUE; } @@ -729,9 +737,9 @@ static s32 bhv_cmd_set_int_random_from_table(void) { // Usage: LOAD_COLLISION_DATA(collisionData) static s32 bhv_cmd_load_collision_data(void) { u32 *collisionData = segmented_to_virtual(BHV_CMD_GET_VPTR(1)); - + gCurrentObject->collisionData = collisionData; - + gCurBhvCommand += 2; return BHV_PROC_CONTINUE; } @@ -742,7 +750,7 @@ static s32 bhv_cmd_set_home(void) { gCurrentObject->oHomeX = gCurrentObject->oPosX; gCurrentObject->oHomeY = gCurrentObject->oPosY; gCurrentObject->oHomeZ = gCurrentObject->oPosZ; - + gCurBhvCommand++; return BHV_PROC_CONTINUE; } @@ -815,9 +823,9 @@ static s32 bhv_cmd_parent_bit_clear(void) { // Usage: SPAWN_WATER_DROPLET(dropletParams) static s32 bhv_cmd_spawn_water_droplet(void) { struct WaterDropletParams *dropletParams = BHV_CMD_GET_VPTR(1); - + spawn_water_droplet(gCurrentObject, dropletParams); - + gCurBhvCommand += 2; return BHV_PROC_CONTINUE; } @@ -842,62 +850,63 @@ void stub_behavior_script_2(void) { typedef s32 (*BhvCommandProc)(void); static BhvCommandProc BehaviorCmdTable[] = { - bhv_cmd_begin, - bhv_cmd_delay, - bhv_cmd_call, - bhv_cmd_return, - bhv_cmd_goto, - bhv_cmd_begin_repeat, - bhv_cmd_end_repeat, - bhv_cmd_end_repeat_continue, - bhv_cmd_begin_loop, - bhv_cmd_end_loop, - bhv_cmd_break, - bhv_cmd_break_unused, - bhv_cmd_call_native, - bhv_cmd_add_float, - bhv_cmd_set_float, - bhv_cmd_add_int, - bhv_cmd_set_int, - bhv_cmd_or_int, - bhv_cmd_bit_clear, - bhv_cmd_set_int_rand_rshift, - bhv_cmd_set_random_float, - bhv_cmd_set_random_int, - bhv_cmd_add_random_float, - bhv_cmd_add_int_rand_rshift, - bhv_cmd_nop_1, - bhv_cmd_nop_2, - bhv_cmd_nop_3, - bhv_cmd_set_model, - bhv_cmd_spawn_child, - bhv_cmd_deactivate, - bhv_cmd_drop_to_floor, - bhv_cmd_sum_float, - bhv_cmd_sum_int, - bhv_cmd_billboard, - bhv_cmd_hide, - bhv_cmd_set_hitbox, - bhv_cmd_nop_4, - bhv_cmd_delay_var, - bhv_cmd_begin_repeat_unused, - bhv_cmd_load_animations, - bhv_cmd_animate, - bhv_cmd_spawn_child_with_param, - bhv_cmd_load_collision_data, - bhv_cmd_set_hitbox_with_offset, - bhv_cmd_spawn_obj, - bhv_cmd_set_home, - bhv_cmd_set_hurtbox, - bhv_cmd_set_interact_type, - bhv_cmd_set_obj_physics, - bhv_cmd_set_interact_subtype, - bhv_cmd_scale, - bhv_cmd_parent_bit_clear, - bhv_cmd_animate_texture, - bhv_cmd_disable_rendering, - bhv_cmd_set_int_unused, - bhv_cmd_spawn_water_droplet, + bhv_cmd_begin, //00 + bhv_cmd_delay, //01 + bhv_cmd_call, //02 + bhv_cmd_return, //03 + bhv_cmd_goto, //04 + bhv_cmd_begin_repeat, //05 + bhv_cmd_end_repeat, //06 + bhv_cmd_end_repeat_continue, //07 + bhv_cmd_begin_loop, //08 + bhv_cmd_end_loop, //09 + bhv_cmd_break, //0A + bhv_cmd_break_unused, //0B + bhv_cmd_call_native, //0C + bhv_cmd_add_float, //0D + bhv_cmd_set_float, //0E + bhv_cmd_add_int, //0F + bhv_cmd_set_int, //10 + bhv_cmd_or_int, //11 + bhv_cmd_bit_clear, //12 + bhv_cmd_set_int_rand_rshift, //13 + bhv_cmd_set_random_float, //14 + bhv_cmd_set_random_int, //15 + bhv_cmd_add_random_float, //16 + bhv_cmd_add_int_rand_rshift, //17 + bhv_cmd_nop_1, //18 + bhv_cmd_nop_2, //19 + bhv_cmd_nop_3, //1A + bhv_cmd_set_model, //1B + bhv_cmd_spawn_child, //1C + bhv_cmd_deactivate, //1D + bhv_cmd_drop_to_floor, //1E + bhv_cmd_sum_float, //1F + bhv_cmd_sum_int, //20 + bhv_cmd_billboard, //21 + bhv_cmd_hide, //22 + bhv_cmd_set_hitbox, //23 + bhv_cmd_nop_4, //24 + bhv_cmd_delay_var, //25 + bhv_cmd_begin_repeat_unused, //26 + bhv_cmd_load_animations, //27 + bhv_cmd_animate, //28 + bhv_cmd_spawn_child_with_param, //29 + bhv_cmd_load_collision_data, //2A + bhv_cmd_set_hitbox_with_offset, //2B + bhv_cmd_spawn_obj, //2C + bhv_cmd_set_home, //2D + bhv_cmd_set_hurtbox, //2E + bhv_cmd_set_interact_type, //2F + bhv_cmd_set_obj_physics, //30 + bhv_cmd_set_interact_subtype, //31 + bhv_cmd_scale, //32 + bhv_cmd_parent_bit_clear, //33 + bhv_cmd_animate_texture, //34 + bhv_cmd_disable_rendering, //35 + bhv_cmd_set_int_unused, //36 + bhv_cmd_spawn_water_droplet, //37 + bhv_cmd_cylboard //38 }; // Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects. diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index ac05ed14..c99e5f32 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -30,12 +30,13 @@ extern Vec3s gVec3sOne; #define GRAPH_RENDER_Z_BUFFER (1 << 3) #define GRAPH_RENDER_INVISIBLE (1 << 4) #define GRAPH_RENDER_HAS_ANIMATION (1 << 5) +#define GRAPH_RENDER_CYLBOARD (1 << 6) // Whether the node type has a function pointer of type GraphNodeFunc #define GRAPH_NODE_TYPE_FUNCTIONAL 0x100 // Type used for Bowser and an unused geo function in obj_behaviors.c -#define GRAPH_NODE_TYPE_400 0x400 +#define GRAPH_NODE_TYPE_400 0x400 // The discriminant for different types of geo nodes #define GRAPH_NODE_TYPE_ROOT 0x001 diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 8643f5e0..8ce410d6 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -377,6 +377,26 @@ void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) { dest[3][3] = 1; } +void mtxf_cylboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) { //straight up mtxf_billboard but minus the dest[1][n] lines. transform for cylindrical billboards + dest[0][0] = coss(angle); + dest[0][1] = sins(angle); + dest[0][2] = 0; + dest[0][3] = 0; + + dest[2][0] = 0; + dest[2][1] = 0; + dest[2][2] = 1; + dest[2][3] = 0; + + dest[3][0] = + mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0]; + dest[3][1] = + mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1]; + dest[3][2] = + mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2]; + dest[3][3] = 1; +} + /** * Set 'dest' to a transformation matrix that aligns an object with the terrain * based on the normal. Used for enemies. diff --git a/src/engine/math_util.h b/src/engine/math_util.h index 650fe973..b8b7f1b8 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -56,6 +56,7 @@ void mtxf_lookat(f32 mtx[4][4], Vec3f b, Vec3f c, s16 d); void mtxf_rotate_zxy_and_translate(f32 mtx[4][4], Vec3f b, Vec3s c); void mtxf_rotate_xyz_and_translate(f32 mtx[4][4], Vec3f b, Vec3s c); void mtxf_billboard(f32 mtx1[4][4], f32 mtx2[4][4], Vec3f c, s16 d); +void mtxf_cylboard(f32 mtx1[4][4], f32 mtx2[4][4], Vec3f c, s16 d); void mtxf_align_terrain_normal(f32 mtx[4][4], Vec3f b, Vec3f c, s16 d); void mtxf_align_terrain_triangle(f32 mtx[4][4], Vec3f b, s16 c, f32 d); void mtxf_mul(f32 dest[4][4], f32 a[4][4], f32 b[4][4]); diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index 5f55ca83..a8cfcab3 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -17,9 +17,11 @@ void opened_cannon_act_0(void) { cur_obj_enable_rendering(); cur_obj_become_tangible(); } + cur_obj_become_tangible(); + cur_obj_enable_rendering(); if (o->oDistanceToMario < 500.0f) { - cur_obj_become_tangible(); - cur_obj_enable_rendering(); + //cur_obj_become_tangible(); + //cur_obj_enable_rendering(); if (o->oInteractStatus & INT_STATUS_INTERACTED && (!(o->oInteractStatus & INT_STATUS_TOUCHED_BOB_OMB))) // bob-omb explodes when it gets into a cannon @@ -30,8 +32,8 @@ void opened_cannon_act_0(void) { } else o->oInteractStatus = 0; } else { - cur_obj_become_intangible(); - cur_obj_disable_rendering(); + //cur_obj_become_intangible(); + //cur_obj_disable_rendering(); o->oCannonUnk10C = 0; } } diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 42ad0e57..e05f7743 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -984,7 +984,7 @@ BAD_RETURN(s16) cur_obj_reverse_animation(void) { BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) { s32 sp4 = o->header.gfx.unk38.animFrame; s32 sp0 = o->header.gfx.unk38.curAnim->unk08 - 2; - + if (sp4 == sp0) o->header.gfx.unk38.animFrame--; } @@ -1595,6 +1595,10 @@ void obj_set_billboard(struct Object *obj) { obj->header.gfx.node.flags |= GRAPH_RENDER_BILLBOARD; } +void obj_set_cylboard(struct Object *obj) { + obj->header.gfx.node.flags |= GRAPH_RENDER_CYLBOARD; +} + void cur_obj_set_hitbox_radius_and_height(f32 radius, f32 height) { o->hitboxRadius = radius; o->hitboxHeight = height; diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index 80806bde..577f8f66 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -292,6 +292,7 @@ extern void cur_obj_shake_y(f32); void cur_obj_start_cam_event(struct Object *obj, s32 cameraEvent); // extern ? set_mario_interact_hoot_if_in_range(?); void obj_set_billboard(struct Object *a0); +void obj_set_cylboard(struct Object *a0); void cur_obj_set_hitbox_radius_and_height(f32,f32); void cur_obj_set_hurtbox_radius_and_height(f32,f32); // extern ? obj_spawn_loot_coins(?); diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 93a9a8a3..dd66b033 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -803,8 +803,13 @@ static void geo_process_object(struct Object *node) { mtxf_mul(gMatStack[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix, gMatStack[gMatStackIndex]); } else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) { - mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], - node->header.gfx.pos, gCurGraphNodeCamera->roll); + if (node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD){ + mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], + node->header.gfx.pos, gCurGraphNodeCamera->roll); + } else { + mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], + node->header.gfx.pos, gCurGraphNodeCamera->roll); + } } else { mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); From 8e1412a2ac8e90cbf04b628d9df54ada69db55cc Mon Sep 17 00:00:00 2001 From: uncletrunks Date: Thu, 14 May 2020 20:47:55 -0500 Subject: [PATCH 22/73] more cylindrical billboarding stuff --- src/game/rendering_graph_node.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index dd66b033..70d31a00 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -802,14 +802,12 @@ static void geo_process_object(struct Object *node) { if (node->header.gfx.throwMatrix != NULL) { mtxf_mul(gMatStack[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix, gMatStack[gMatStackIndex]); + } else if (node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD) { + mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], + node->header.gfx.pos, gCurGraphNodeCamera->roll); } else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) { - if (node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD){ - mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], - node->header.gfx.pos, gCurGraphNodeCamera->roll); - } else { - mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], - node->header.gfx.pos, gCurGraphNodeCamera->roll); - } + mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], + node->header.gfx.pos, gCurGraphNodeCamera->roll); } else { mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); From 59d0cc16c194270427bfb42b83ca9feb498008dd Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Thu, 14 May 2020 23:02:04 -0300 Subject: [PATCH 23/73] Add include Oops! --- src/pc/cliopts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 162b3e1a..cd77ef12 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -1,4 +1,5 @@ #include "cliopts.h" +#include struct PCCLIOptions gCLIOpts; From a43ac2ebafe3650bb857731bda575c5c19976cfd Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Thu, 14 May 2020 23:04:07 -0300 Subject: [PATCH 24/73] Update README for merging --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 775b891f..1815517e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ -# sm64pc - skipintro branch - -This is a testing branch featuring a new CLI interface and support to skip the introductory Peach & Lakitu cutscenes, useful for development tests. - +# sm64pc OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64). Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. @@ -13,6 +10,7 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * Variable aspect ratio and resolution. The game can now correctly render at basically any window size. * Native xinput controller support. On Linux, DualShock 4 has been confirmed to work plug-and-play. * Analog camera control and mouse look. (Activate with `make BETTERCAMERA=1`.) + * Option to skip the Peach/Lakitu new file intro. ## Building For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki). From ab23b8907bfe0dce0b04ea992f6bca624e02e15f Mon Sep 17 00:00:00 2001 From: uncletrunks Date: Thu, 14 May 2020 21:50:10 -0500 Subject: [PATCH 25/73] putting out fires --- data/behavior_data.c | 1 - src/engine/math_util.c | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/behavior_data.c b/data/behavior_data.c index 8fc3d518..3b4af5a0 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -3183,7 +3183,6 @@ const BehaviorScript bhvFloorTrapInCastle[] = { const BehaviorScript bhvTree[] = { BEGIN(OBJ_LIST_POLELIKE), - BILLBOARD(), CYLBOARD(), OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE), SET_INT(oInteractType, INTERACT_POLE), diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 8ce410d6..3f027ed5 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -383,6 +383,11 @@ void mtxf_cylboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) { //straight dest[0][2] = 0; dest[0][3] = 0; + dest[1][0] = mtx[1][0]; + dest[1][1] = mtx[1][1]; + dest[1][2] = mtx[1][2]; + dest[1][3] = 0; + dest[2][0] = 0; dest[2][1] = 0; dest[2][2] = 1; From 12b605aa6ddba18a8095fbbca6a62ffd1565a8ee Mon Sep 17 00:00:00 2001 From: Leon422 Date: Fri, 15 May 2020 03:56:25 +0100 Subject: [PATCH 26/73] Create translated README.md (README_es_ES.md) Create a Spanish-Spain translation of the README file. --- README_es_ES.md | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 README_es_ES.md diff --git a/README_es_ES.md b/README_es_ES.md new file mode 100644 index 00000000..8ebb06a7 --- /dev/null +++ b/README_es_ES.md @@ -0,0 +1,201 @@ +# sm64pc +Adaptación a OpenGL de [n64decomp/sm64](https://github.com/n64decomp/sm64). + +No dudes en contribuir o reportar bugs, pero recuerda **no se debe subir nada con copyright**. +Ejecuta `./extract-assets.py --clean && make clean` o `make distclean` para borrar todo el contenido proveniente de la ROM. Este port es posible gracias a [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) creado por [Emill](https://github.com/Emill). + +## Funcionalidades + + * Renderizado nativo. Podrás jugar a Super Mario 64 sin necesidad de un emulador. + * Resolución y relación de aspecto variables. Puedes jugar a Super Mario 64 a básicamente cualquier resolución o tamaño de ventana. + * Soporte nativo para mandos XInput. En Linux, se ha confirmado que el DualShock 4 funciona sin más. + * Cámara analógica y cámara controlada con el ratón. (Se activa con `make BETTERCAMERA=1`.) + * Opción para desactivar el límite de distancia de renderizado. (Se activa con `make NODRAWINGDISTANCE=1`.) + * Configurar los controles desde el juego, actualmente solo en la rama `testing`. + * Posibilidad de saltarte la intro con la opción de línea de comandos `--skip-intro`, actualmente solo en las ramas `testing` y `skip-intro`. + +# Compilar en Windows +**No intentes compilar ejecutables para Windows bajo Linux usando `WINDOWS_BUILD=1`. No va a funcionar. Sigue la guía.** +## 1. Instalación y configuración de MSYS2. + +1. Descarga [msys2-x86_64-latest.exe](http://repo.msys2.org/distrib/msys2-x86_64-latest.exe) y ejecútalo. Si tu sistema operativo es de 32 bits (¿por qué?) descarga [msys2-i686-latest.exe](http://repo.msys2.org/distrib/msys2-i686-latest.exe) en su lugar. Asegúrate de que lo instalas en `C:\dev\msys64` (o `C:\dev\msys32` para 32 bits...). Ejecuta MSYS2. + +2. En la ventana de comandos de MSYS2, ejecuta el siguiente comando: + ``` + pacman -Syuu + ``` +3. Abre "MSYS2 MinGW 64-Bit". Ejecuta este comando __repetidamente__ hasta que MSYS diga que ya no hay más actualizaciones. Es posible que tengas que volver a cerrar y abrir MSYS2. + + ``` + pacman -Syuu + ``` + +5. Ejecuta este comando y cuando te pida confirmación pulsa intro: + + ``` + pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain \ + git subversion mercurial \ + mingw-w64-i686-cmake mingw-w64-x86_64-cmake + ``` +6. Listo. +## Instala las dependencias +``` +pacman -S mingw-w64-i686-glew mingw-w64-x86_64-glew mingw-w64-i686-SDL2 mingw-w64-x86_64-SDL2 python3 +``` +## Crea el directorio en el que preparar todo +Desde el explorador de Windows, navega a `C:\msys64\home\(nombre de usuario)\` y crea una carpeta con el nombre que te apetezca. Aquí es donde vamos a preparar todo. +## Clona el repositorio +En MSYS2, introduce el siguiente comando: +``` +git clone https://github.com/sm64pc/sm64pc/ +``` +(Si no funciona, prueba a escribirlo manualmente, en lugar de copiar y pegar) +## Copia la ROM base al directorio correspondiente +El paso anterior tiene que haber creado una carpeta llamada sm64pc. Dentro de esa carpeta, y para cada version de la ROM (jp/us/eu) de la cual quieras compilar un ejecutable, coloca la ROM con el nombre `baserom..z64` para extraer sus assets. Por ejemplo, `baserom.us.z64` para la versión americana, o `baserom.eu.z64` para la versión europea. + +## En MSYS2, vamos a navegar a la carpeta `./tools/audiofile-0.3.6/` y ejecutar el `autoreconf-i`. Introduce los siguientes comandos, en orden, uno a uno: +``` +cd sm64pc/tools/audiofile-0.3.6/ +autoreconf -i +``` +No te vayas de este directorio hasta el paso 9. + +## Ejecuta el script `configure` +``` +PATH=/mingw64/bin:/mingw32/bin:$PATH LIBS=-lstdc++ ./configure --disable-docs +``` +## Ejecuta el script `make` +``` +PATH=/mingw64/bin:/mingw32/bin:$PATH make +``` +## Crea un directorio `lib` en `tools/` +``` +mkdir ../lib +``` + +## Acabas de compilar `libaudiofile`. Ahora cópialo a `tools/lib/` +``` +cp libaudiofile/.libs/libaudiofile.a ../lib/ +cp libaudiofile/.libs/libaudiofile.la ../lib/ +``` +## Ahora toca hacer algo desde Windows. +En el explorador de Windows, ve a sm64pc\tools y edita el archivo Makefile desde un editor de texto (es recomdable usar uno como Notepad++ o Sublime Text. Busca la línea que contiene esto: + +```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile``` + +Y añade ` -lstdc++` al final, de manera que quede así (¡no olvides el espacio!) + +```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile -lstdc++``` + +Guarda el archivo. +## Vuelve a la carpeta tools y ejecuta `make` con los siguientes comandos. +``` +cd .. +PATH=/mingw64/bin:/mingw32/bin:$PATH make +``` +## Vuelve al directorio sm64pc +``` +cd .. +``` +## Finalmente, ejecuta ```make``` de nuevo. + +(Ten en cuenta que mingw32 y mingw64 han sido intercambiados. Esto es para que puedas compilar la versión de 32 bits si quieres.) + +Aquí pones las opciones que quieras según la versión que quieras compilar. Por ejemplo, si quieres activar la cámara analógica, añade al final -BETTERCAMERA=1. Si quieres la opción de distancia de renderizado ilimitada, añade -NODRAWINGDISTANCE=1. + +Por ejemplo: +``` +PATH=/mingw32/bin:/mingw64/bin:$PATH make -BETTERCAMERA=1 -NODRAWINGDISTANCE=1 +``` +Listo. El .exe estará en sm64pc\build\. Disfruta. +# Compilar en Linux +## Nota para usuarios de Windows +No intentes compilar un ejecutable para Windows desde Linux. No funciona. Sigue la guía para Windows. + +## Copia la(s) ROM(s) base para la extracción de assets. + +Por cada versión de la cual quieras compilar un ejecutable, copia la ROM en `./baserom..z64` para extraer los assets. + +## Instala las dependencias. + +Para compilar necesitas las sigueintes dependencias. + * python3 >= 3.6 + * libsdl2-dev + * [audiofile](https://audiofile.68k.org/) + * libglew-dev + * git + +Puedes instalarlas con este comando: + +### Debian / Ubuntu - (compilando para 32 bits) +``` +sudo apt install build-essential git python3 libaudiofile-dev libglew-dev:i386 libsdl2-dev:i386 +``` +### Debian / Ubuntu - (compilando para 64 bits) +``` +sudo apt install build-essential git python3 libaudiofile-dev libglew-dev libsdl2-dev +``` +### Arch Linux +Hay un paquete AUR (cortesía de @narukeh) disponible bajo el nombre [sm64pc-git](https://aur.archlinux.org/packages/sm64pc-git/). Instálalo con tu gestor de AURs preferido. + +Si quieres compilarlo por tu cuenta: +``` +sudo pacman -S base-devel python audiofile sdl2 glew +``` + +### Void Linux - (compilando para 64 bits) +``` +sudo xbps-install -S base-devel python3 audiofile-devel SDL2-devel glew-devel +``` + +### Void Linux - (compilando para 32 bits) +``` +sudo xbps-install -S base-devel python3 audiofile-devel-32bit SDL2-devel-32bit glew-devel-32bit +``` + +## Compila el ejecutable. + +Ejecuta `make` para compilar (por defecto `VERSION=us`) + +``` +make VERSION=jp -j6 # Compila la versión (J) usando 6 hilos +make VERSION=us MARCH=i686 TARGET_BITS=32 # Compila un ejecutable de la versión (U) de 32 bits +make TARGET_RPI=1 # Compila un ejecutable para Raspberry Pi +``` +# Compilar para la web +Puedes compilar el juego para navegadores que admitan WebGL usando [Emscripten](https://github.com/emscripten-core). Para hacerlo, instala [emsdk](https://github.com/emscripten-core/emsdk) y ejecuta `make TARGET_WEB=1`. +# Script para compilar para Raspberry Pi +[Hyenadae](https://github.com/Hyenadae/) ha creado un script que ayuda a compilar el juego para Raspberry Pi. Estos son los pasos que hace el script: + + * Instala las dependencias; + * Cambia VC4_DRM en la RPi de 0 a 3; + * Cambia ajustes en la memoria de las RPis 0 y 1 para que se pueda completar la compilación; + * Permite la instalación de un SDL2 con KMS, lo que elimina la necesidad de usar X11 y garantiza el máximo rendimiento de cualquier RPi que ejecute VC4; + * Clona sm64pc si no encuentra los archivos necesarios; + * Comprueba si existen los assets y la ROM base necesaria (baserom.*.z64); + * Compila sm64pc. + +El script está incluído en la rama master, pero también puede descargarse [aquí](https://raw.githubusercontent.com/sm64pc/sm64pc/master/pisetup.sh). +# Problemas conocidos +### Problemas ya conocidos: + * La versión EU tiene bugs en los textos y no tiene audio. + * Hazy Maze Cave se cuelga en pantalla completa (#57) + * El movimiento analógico horizontal de la cámara vuelve al estilo antiguo en el nivel Bowser in the Dark World (#72) + * La cámara con el ratón falla cuando disparas a Mario hacia un árbol o un tubo. (#71) + * "make: Nothing to be done for 'default'" al compilar para web. (#67) + * La pantalla de título no tiene el cursor para manipular a Mario en pantalla completa. (#28) + +### Estos problemas están marcados como solucionados. Por favor, contacta si sigues teniendo estos problemas. + * El soporte de la versión EU es aún experimental. + * Los controles de la cámara tienen problemas para algunas personas. +# Parches +En la carpeta `./enhancements` hay varios archivos `patch`, que pueden aplicarse de la siguiente manera: + +``` + git apply fps.patch --ignore-whitespace --reject +``` +Si ocurre un rechazo, puedes buscarlo con el comando `find | grep .rej`. +Intenta resolver los rechazos a través de [wiggle](https://github.com/neilbrown/wiggle). +``` +wiggle rejection.rej --replace +``` From d2afc056b31c5b0075c7d12e9474fa10f8a00f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Fri, 15 May 2020 00:05:50 -0300 Subject: [PATCH 27/73] Add a link to the es_ES README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a633108..214260cf 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64). Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. -Run `./extract-assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible thanks to [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) by [Emill](https://github.com/Emill). +Run `./extract-assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer. + +*Read this in other languages: [Español](README_es_ES.md).* ## Features From 4d1c229e6db661a361ee25b68309afed50298698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Fri, 15 May 2020 00:21:46 -0300 Subject: [PATCH 28/73] Formatting and some other small stuff --- README_es_ES.md | 69 ++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/README_es_ES.md b/README_es_ES.md index 8ebb06a7..b6b8779b 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -14,9 +14,9 @@ Ejecuta `./extract-assets.py --clean && make clean` o `make distclean` para borr * Configurar los controles desde el juego, actualmente solo en la rama `testing`. * Posibilidad de saltarte la intro con la opción de línea de comandos `--skip-intro`, actualmente solo en las ramas `testing` y `skip-intro`. -# Compilar en Windows +## Compilar en Windows **No intentes compilar ejecutables para Windows bajo Linux usando `WINDOWS_BUILD=1`. No va a funcionar. Sigue la guía.** -## 1. Instalación y configuración de MSYS2. +#### 1. Instalación y configuración de MSYS2. 1. Descarga [msys2-x86_64-latest.exe](http://repo.msys2.org/distrib/msys2-x86_64-latest.exe) y ejecútalo. Si tu sistema operativo es de 32 bits (¿por qué?) descarga [msys2-i686-latest.exe](http://repo.msys2.org/distrib/msys2-i686-latest.exe) en su lugar. Asegúrate de que lo instalas en `C:\dev\msys64` (o `C:\dev\msys32` para 32 bits...). Ejecuta MSYS2. @@ -38,47 +38,47 @@ Ejecuta `./extract-assets.py --clean && make clean` o `make distclean` para borr mingw-w64-i686-cmake mingw-w64-x86_64-cmake ``` 6. Listo. -## Instala las dependencias +#### Instala las dependencias ``` pacman -S mingw-w64-i686-glew mingw-w64-x86_64-glew mingw-w64-i686-SDL2 mingw-w64-x86_64-SDL2 python3 ``` -## Crea el directorio en el que preparar todo +### Crea el directorio en el que preparar todo Desde el explorador de Windows, navega a `C:\msys64\home\(nombre de usuario)\` y crea una carpeta con el nombre que te apetezca. Aquí es donde vamos a preparar todo. -## Clona el repositorio +### Clona el repositorio En MSYS2, introduce el siguiente comando: ``` git clone https://github.com/sm64pc/sm64pc/ ``` (Si no funciona, prueba a escribirlo manualmente, en lugar de copiar y pegar) -## Copia la ROM base al directorio correspondiente +#### Copia la ROM base al directorio correspondiente El paso anterior tiene que haber creado una carpeta llamada sm64pc. Dentro de esa carpeta, y para cada version de la ROM (jp/us/eu) de la cual quieras compilar un ejecutable, coloca la ROM con el nombre `baserom..z64` para extraer sus assets. Por ejemplo, `baserom.us.z64` para la versión americana, o `baserom.eu.z64` para la versión europea. -## En MSYS2, vamos a navegar a la carpeta `./tools/audiofile-0.3.6/` y ejecutar el `autoreconf-i`. Introduce los siguientes comandos, en orden, uno a uno: +#### En MSYS2, vamos a navegar a la carpeta `./tools/audiofile-0.3.6/` y ejecutar el `autoreconf-i`. Introduce los siguientes comandos, en orden, uno a uno: ``` cd sm64pc/tools/audiofile-0.3.6/ autoreconf -i ``` No te vayas de este directorio hasta el paso 9. -## Ejecuta el script `configure` +#### Ejecuta el script `configure` ``` PATH=/mingw64/bin:/mingw32/bin:$PATH LIBS=-lstdc++ ./configure --disable-docs ``` -## Ejecuta el script `make` +#### Ejecuta el script `make` ``` PATH=/mingw64/bin:/mingw32/bin:$PATH make ``` -## Crea un directorio `lib` en `tools/` +#### Crea un directorio `lib` en `tools/` ``` mkdir ../lib ``` -## Acabas de compilar `libaudiofile`. Ahora cópialo a `tools/lib/` +#### Acabas de compilar `libaudiofile`. Ahora cópialo a `tools/lib/` ``` cp libaudiofile/.libs/libaudiofile.a ../lib/ cp libaudiofile/.libs/libaudiofile.la ../lib/ ``` -## Ahora toca hacer algo desde Windows. +#### Ahora toca hacer algo desde Windows. En el explorador de Windows, ve a sm64pc\tools y edita el archivo Makefile desde un editor de texto (es recomdable usar uno como Notepad++ o Sublime Text. Busca la línea que contiene esto: ```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile``` @@ -88,16 +88,16 @@ Y añade ` -lstdc++` al final, de manera que quede así (¡no olvides el espacio ```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile -lstdc++``` Guarda el archivo. -## Vuelve a la carpeta tools y ejecuta `make` con los siguientes comandos. +#### Vuelve a la carpeta tools y ejecuta `make` con los siguientes comandos. ``` cd .. PATH=/mingw64/bin:/mingw32/bin:$PATH make ``` -## Vuelve al directorio sm64pc +#### Vuelve al directorio sm64pc ``` cd .. ``` -## Finalmente, ejecuta ```make``` de nuevo. +#### Finalmente, ejecuta ```make``` de nuevo. (Ten en cuenta que mingw32 y mingw64 han sido intercambiados. Esto es para que puedas compilar la versión de 32 bits si quieres.) @@ -108,15 +108,16 @@ Por ejemplo: PATH=/mingw32/bin:/mingw64/bin:$PATH make -BETTERCAMERA=1 -NODRAWINGDISTANCE=1 ``` Listo. El .exe estará en sm64pc\build\. Disfruta. -# Compilar en Linux -## Nota para usuarios de Windows -No intentes compilar un ejecutable para Windows desde Linux. No funciona. Sigue la guía para Windows. +## Compilar en Linux -## Copia la(s) ROM(s) base para la extracción de assets. +### Nota para usuarios de Windows +No intentes compilar un ejecutable para Windows desde Linux o WSL. No funciona. Sigue la guía para Windows. + +#### Copia la(s) ROM(s) base para la extracción de assets. Por cada versión de la cual quieras compilar un ejecutable, copia la ROM en `./baserom..z64` para extraer los assets. -## Instala las dependencias. +#### Instala las dependencias. Para compilar necesitas las sigueintes dependencias. * python3 >= 3.6 @@ -127,15 +128,15 @@ Para compilar necesitas las sigueintes dependencias. Puedes instalarlas con este comando: -### Debian / Ubuntu - (compilando para 32 bits) +##### Debian / Ubuntu - (compilando para 32 bits) ``` sudo apt install build-essential git python3 libaudiofile-dev libglew-dev:i386 libsdl2-dev:i386 ``` -### Debian / Ubuntu - (compilando para 64 bits) +##### Debian / Ubuntu - (compilando para 64 bits) ``` sudo apt install build-essential git python3 libaudiofile-dev libglew-dev libsdl2-dev ``` -### Arch Linux +##### Arch Linux Hay un paquete AUR (cortesía de @narukeh) disponible bajo el nombre [sm64pc-git](https://aur.archlinux.org/packages/sm64pc-git/). Instálalo con tu gestor de AURs preferido. Si quieres compilarlo por tu cuenta: @@ -143,17 +144,17 @@ Si quieres compilarlo por tu cuenta: sudo pacman -S base-devel python audiofile sdl2 glew ``` -### Void Linux - (compilando para 64 bits) +##### Void Linux - (compilando para 64 bits) ``` sudo xbps-install -S base-devel python3 audiofile-devel SDL2-devel glew-devel ``` -### Void Linux - (compilando para 32 bits) +##### Void Linux - (compilando para 32 bits) ``` sudo xbps-install -S base-devel python3 audiofile-devel-32bit SDL2-devel-32bit glew-devel-32bit ``` -## Compila el ejecutable. +#### Compila el ejecutable. Ejecuta `make` para compilar (por defecto `VERSION=us`) @@ -162,9 +163,11 @@ make VERSION=jp -j6 # Compila la versión (J) usando 6 make VERSION=us MARCH=i686 TARGET_BITS=32 # Compila un ejecutable de la versión (U) de 32 bits make TARGET_RPI=1 # Compila un ejecutable para Raspberry Pi ``` -# Compilar para la web +## Compilar para la web Puedes compilar el juego para navegadores que admitan WebGL usando [Emscripten](https://github.com/emscripten-core). Para hacerlo, instala [emsdk](https://github.com/emscripten-core/emsdk) y ejecuta `make TARGET_WEB=1`. -# Script para compilar para Raspberry Pi + +## Script para compilar para Raspberry Pi + [Hyenadae](https://github.com/Hyenadae/) ha creado un script que ayuda a compilar el juego para Raspberry Pi. Estos son los pasos que hace el script: * Instala las dependencias; @@ -179,16 +182,16 @@ El script está incluído en la rama master, pero también puede descargarse [aq # Problemas conocidos ### Problemas ya conocidos: * La versión EU tiene bugs en los textos y no tiene audio. - * Hazy Maze Cave se cuelga en pantalla completa (#57) * El movimiento analógico horizontal de la cámara vuelve al estilo antiguo en el nivel Bowser in the Dark World (#72) * La cámara con el ratón falla cuando disparas a Mario hacia un árbol o un tubo. (#71) * "make: Nothing to be done for 'default'" al compilar para web. (#67) - * La pantalla de título no tiene el cursor para manipular a Mario en pantalla completa. (#28) ### Estos problemas están marcados como solucionados. Por favor, contacta si sigues teniendo estos problemas. - * El soporte de la versión EU es aún experimental. - * Los controles de la cámara tienen problemas para algunas personas. -# Parches + * El juego se llena de flags aleatorias en las builds de 64 bits para Windows + * Hazy Maze Cave se cuelga en pantalla completa (#57) + * La pantalla de título no tiene el cursor para manipular a Mario en pantalla completa. (#28) + +## Parches En la carpeta `./enhancements` hay varios archivos `patch`, que pueden aplicarse de la siguiente manera: ``` From 339735392fa749e9508926c7016f8deb38d6d8f6 Mon Sep 17 00:00:00 2001 From: Heaven Volkoff Date: Fri, 15 May 2020 01:09:28 -0300 Subject: [PATCH 29/73] Fix incorrect cursor position calculation on Mario head screen (related to #28) --- src/goddard/renderer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/goddard/renderer.c b/src/goddard/renderer.c index 06928dc7..d2f45acd 100644 --- a/src/goddard/renderer.c +++ b/src/goddard/renderer.c @@ -2986,9 +2986,9 @@ void update_cursor(void) { reset_dlnum_indices(sHandShape->gdDls[gGdFrameBuf]); if (gGdCtrl.btnApressed) { - gd_put_sprite((u16 *) gd_texture_hand_closed, GFX_DIMENSIONS_FROM_LEFT_EDGE(sHandView->upperLeft.x), sHandView->upperLeft.y, 0x20, 0x20); + gd_put_sprite((u16 *) gd_texture_hand_closed, sHandView->upperLeft.x, sHandView->upperLeft.y, 32, 32); } else { - gd_put_sprite((u16 *) gd_texture_hand_open, GFX_DIMENSIONS_FROM_LEFT_EDGE(sHandView->upperLeft.x), sHandView->upperLeft.y, 0x20, 0x20); + gd_put_sprite((u16 *) gd_texture_hand_open, sHandView->upperLeft.x, sHandView->upperLeft.y, 32, 32); } gd_enddlsplist_parent(); @@ -3444,7 +3444,8 @@ void Unknown801A5FF8(struct ObjGroup *arg0) { void gd_put_sprite(u16 *sprite, s32 x, s32 y, s32 wx, s32 wy) { s32 c; // 5c s32 r; // 58 - f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO * 0.75; + // Must be game screen aspect ratio, not GFX window aspect ratio + f32 aspect = ((float) SCREEN_WIDTH) / ((float) SCREEN_HEIGHT ) * 0.75; x *= aspect; gSPDisplayList(next_gfx(), osVirtualToPhysical(gd_dl_sprite_start_tex_block)); From 9c7f1103294e3edf851090e447971367f3a649bb Mon Sep 17 00:00:00 2001 From: yksoft1 Date: Fri, 15 May 2020 12:30:26 +0800 Subject: [PATCH 30/73] Add Simplified Chinese translation of README.md. --- README_zh_CN.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 README_zh_CN.md diff --git a/README_zh_CN.md b/README_zh_CN.md new file mode 100644 index 00000000..ba9bf58a --- /dev/null +++ b/README_zh_CN.md @@ -0,0 +1,21 @@ +# sm64pc +本项目是 [n64decomp/sm64](https://github.com/n64decomp/sm64) 的 OpenGL 移植版本。 + +我们欢迎贡献代码与 bug 报告,但请切记,不得上传**任何被版权保护(来自 ROM 文件)的资源**。 +提交前请运行 `./extract-assets.py --clean && make clean` 或 `make distclean` 来清除所有从 ROM 文件中提取的内容。 +本移植是基于 [Emill](https://github.com/Emill) 的工作 [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) 而得以实现的。 + +## 主要功能 + + * 原生渲染。现在不用任何模拟器就可以运行 马力欧64 了。 + * 长宽比和分辨率可以自由改变。本游戏目前可以在几乎任何窗口尺寸下正确渲染。 + * 原生 xinput 手柄支持。在 Linux 下,已经确认 PS4 手柄可以即插即用。 + * 模拟视点控制和鼠标视点。(请使用 `make BETTERCAMERA=1` 编译) + * 可选择取消可视距离限制。(请使用 `make NODRAWINGDISTANCE=1` 编译) + * 游戏内操作设定,目前在 `testing` 分支下可用。 + * 使用 `--skip-intro` 命令行选项跳过碧奇公主与 Lakitu 的片头剧情。目前在 `testing` 及 `skip-intro` 分支下可用。 + +## Building +关于如何编译,请参考 [wiki](https://github.com/sm64pc/sm64pc/wiki)。 + +**请勿在 Linux 或者 WSL 下使用 `WINDOWS_BUILD=1` 参数尝试编译 Windows 版本,这样无法编译成功。请参考 Wiki。 From 15122920556bf5a3c50258ce1b7c49eae418a9eb Mon Sep 17 00:00:00 2001 From: yksoft1 Date: Fri, 15 May 2020 12:32:28 +0800 Subject: [PATCH 31/73] Add link to Simplified Chinese readme.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 214260cf..09139308 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64). Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. Run `./extract-assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer. -*Read this in other languages: [Español](README_es_ES.md).* +*Read this in other languages: [Español](README_es_ES.md) [简体中文](README_zh_CN.md).* ## Features From db92b7d5635b3c72a92e3a2d48f43bde16a6d95b Mon Sep 17 00:00:00 2001 From: yksoft1 Date: Fri, 15 May 2020 12:35:47 +0800 Subject: [PATCH 32/73] Fixes to zh_CN content. --- README_zh_CN.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README_zh_CN.md b/README_zh_CN.md index ba9bf58a..9bcc5891 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -1,21 +1,21 @@ # sm64pc 本项目是 [n64decomp/sm64](https://github.com/n64decomp/sm64) 的 OpenGL 移植版本。 -我们欢迎贡献代码与 bug 报告,但请切记,不得上传**任何被版权保护(来自 ROM 文件)的资源**。 +我们欢迎贡献代码与 bug 报告,但请切记,**不得上传任何被版权保护(来自 ROM 文件)的资源**。 提交前请运行 `./extract-assets.py --clean && make clean` 或 `make distclean` 来清除所有从 ROM 文件中提取的内容。 -本移植是基于 [Emill](https://github.com/Emill) 的工作 [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) 而得以实现的。 +本移植是基于 [Emill](https://github.com/Emill) 的工作 [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) 才得以实现的。 ## 主要功能 * 原生渲染。现在不用任何模拟器就可以运行 马力欧64 了。 * 长宽比和分辨率可以自由改变。本游戏目前可以在几乎任何窗口尺寸下正确渲染。 * 原生 xinput 手柄支持。在 Linux 下,已经确认 PS4 手柄可以即插即用。 - * 模拟视点控制和鼠标视点。(请使用 `make BETTERCAMERA=1` 编译) - * 可选择取消可视距离限制。(请使用 `make NODRAWINGDISTANCE=1` 编译) - * 游戏内操作设定,目前在 `testing` 分支下可用。 + * 支持模拟量视点控制、鼠标控制视点。(请使用 `make BETTERCAMERA=1` 编译) + * 可取消可视距离限制。(请使用 `make NODRAWINGDISTANCE=1` 编译) + * 游戏内操作设定功能,目前在 `testing` 分支下可用。 * 使用 `--skip-intro` 命令行选项跳过碧奇公主与 Lakitu 的片头剧情。目前在 `testing` 及 `skip-intro` 分支下可用。 -## Building +## 编译方法 关于如何编译,请参考 [wiki](https://github.com/sm64pc/sm64pc/wiki)。 **请勿在 Linux 或者 WSL 下使用 `WINDOWS_BUILD=1` 参数尝试编译 Windows 版本,这样无法编译成功。请参考 Wiki。 From 595b18bebd5149caf16bc9656f6d5ba67adb7cad Mon Sep 17 00:00:00 2001 From: Leon422 Date: Fri, 15 May 2020 13:15:52 +0100 Subject: [PATCH 33/73] Update README_es_ES.md Fixed some typos, added some more details --- README_es_ES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_es_ES.md b/README_es_ES.md index b6b8779b..575a36be 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -1,7 +1,7 @@ # sm64pc Adaptación a OpenGL de [n64decomp/sm64](https://github.com/n64decomp/sm64). -No dudes en contribuir o reportar bugs, pero recuerda **no se debe subir nada con copyright**. +No dudes en contribuir o reportar bugs, pero recuerda: **no se debe subir nada con copyright**. Ejecuta `./extract-assets.py --clean && make clean` o `make distclean` para borrar todo el contenido proveniente de la ROM. Este port es posible gracias a [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) creado por [Emill](https://github.com/Emill). ## Funcionalidades @@ -79,7 +79,7 @@ cp libaudiofile/.libs/libaudiofile.a ../lib/ cp libaudiofile/.libs/libaudiofile.la ../lib/ ``` #### Ahora toca hacer algo desde Windows. -En el explorador de Windows, ve a sm64pc\tools y edita el archivo Makefile desde un editor de texto (es recomdable usar uno como Notepad++ o Sublime Text. Busca la línea que contiene esto: +En el explorador de Windows, ve a sm64pc\tools y edita el archivo Makefile desde un editor de texto (es recomendable usar un editor decente como Notepad++ o Sublime Text, en lugar del bloc de notas, para asegurarte de que no rompes el formato del texto) Busca la línea que contiene esto: ```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile``` From fd74e20373b0b471724433e88c07d647376efcc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Fri, 15 May 2020 12:51:06 -0300 Subject: [PATCH 34/73] Add a `--fullscreen` CLI option --- src/pc/cliopts.c | 6 +++++- src/pc/cliopts.h | 3 ++- src/pc/gfx/gfx_sdl2.c | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index cd77ef12..602de098 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -6,7 +6,8 @@ struct PCCLIOptions gCLIOpts; void parse_cli_opts(int argc, char* argv[]) { // Initialize options with false values. - gCLIOpts.SkipIntro = 0; + gCLIOpts.SkipIntro = 0; + gCLIOpts.FullScreen = 0; // Scan arguments for options if (argc > 1) @@ -16,6 +17,9 @@ void parse_cli_opts(int argc, char* argv[]) { if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro gCLIOpts.SkipIntro = 1; + + if (strcmp(argv[i], "--fullscreen") == 0) // Open game in fullscreen + gCLIOpts.FullScreen = 1; } } } \ No newline at end of file diff --git a/src/pc/cliopts.h b/src/pc/cliopts.h index 2f08cc4e..b4a0b613 100644 --- a/src/pc/cliopts.h +++ b/src/pc/cliopts.h @@ -3,8 +3,9 @@ struct PCCLIOptions { u8 SkipIntro; + u8 FullScreen; }; extern struct PCCLIOptions gCLIOpts; -void parse_cli_opts(int argc, char* argv[]); \ No newline at end of file +void parse_cli_opts(int argc, char* argv[]); diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index a794c6d3..561ac95b 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -19,6 +19,7 @@ #include "gfx_window_manager_api.h" #include "gfx_screen_config.h" #include "../configfile.h" +#include "../cliopts.h" #include "src/pc/controller/controller_keyboard.h" @@ -113,6 +114,10 @@ static void gfx_sdl_init(void) { window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; + if (gCLIOpts.FullScreen) { + configFullscreen = true; + } + if (configFullscreen) { window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } From d407db037737a4fdb5fa35dac558dca105e2cf03 Mon Sep 17 00:00:00 2001 From: Leon422 Date: Fri, 15 May 2020 18:12:56 +0100 Subject: [PATCH 35/73] Update README_es_ES.md Fixed a very stupid mistake --- README_es_ES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_es_ES.md b/README_es_ES.md index 575a36be..86a3373e 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -101,11 +101,11 @@ cd .. (Ten en cuenta que mingw32 y mingw64 han sido intercambiados. Esto es para que puedas compilar la versión de 32 bits si quieres.) -Aquí pones las opciones que quieras según la versión que quieras compilar. Por ejemplo, si quieres activar la cámara analógica, añade al final -BETTERCAMERA=1. Si quieres la opción de distancia de renderizado ilimitada, añade -NODRAWINGDISTANCE=1. +Aquí pones las opciones que quieras según la versión que quieras compilar. Por ejemplo, si quieres activar la cámara analógica, añade al final BETTERCAMERA=1. Si quieres la opción de distancia de renderizado ilimitada, añade NODRAWINGDISTANCE=1. Por ejemplo: ``` -PATH=/mingw32/bin:/mingw64/bin:$PATH make -BETTERCAMERA=1 -NODRAWINGDISTANCE=1 +PATH=/mingw32/bin:/mingw64/bin:$PATH make BETTERCAMERA=1 NODRAWINGDISTANCE=1 ``` Listo. El .exe estará en sm64pc\build\. Disfruta. ## Compilar en Linux From e25b06b60e85e055c2ef254deb08f29bd9b9858e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20D=C3=ADez=20Garc=C3=ADa?= <64872225+diezgvi@users.noreply.github.com> Date: Fri, 15 May 2020 20:33:00 +0200 Subject: [PATCH 36/73] Correct texture format for burn smoke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All credits to zoinknoise, I found this at Romhacking: http://www.romhacking.net/hacks/5008/ "Thanks to the recent decompilation efforts, it’s now known that this texture is displayed in the wrong format by the game, resulting in black garbage pixels. Since video game smoke of this era was often depicted with black garbage pixels, the mistake went unnoticed for over two decades. This patch corrects the error by displaying the texture correctly as proper transparent smoke. It does not add any new art; the texture has been inside the ROM all along. At build time, this will compile the texture into IA16 format (correct) instead of RGBA16 (incorrect)." --- actors/burn_smoke/model.inc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actors/burn_smoke/model.inc.c b/actors/burn_smoke/model.inc.c index a0f65578..3d1adef4 100644 --- a/actors/burn_smoke/model.inc.c +++ b/actors/burn_smoke/model.inc.c @@ -44,7 +44,7 @@ const Gfx burn_smoke_seg4_dl_04022048[] = { // 0x04022070 - 0x040220C8 const Gfx burn_smoke_seg4_dl_04022070[] = { gsSPDisplayList(burn_smoke_seg4_dl_04022000), - gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_RGBA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), + gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_IA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), gsSPDisplayList(burn_smoke_seg4_dl_04022028), gsSPDisplayList(burn_smoke_seg4_dl_04022048), gsSPEndDisplayList(), From 4a13fd3380e7a286a6636ef97c26b607618f37aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Fri, 15 May 2020 15:38:35 -0300 Subject: [PATCH 37/73] Add in-game control binding menu Originally on the testing branch --- Makefile | 6 +- include/text_strings.h.in | 47 +- src/game/bettercamera.h | 5 - src/game/bettercamera.inc.h | 249 +---------- src/game/ingame_menu.c | 20 +- src/game/level_update.c | 4 +- src/game/options_menu.c | 463 ++++++++++++++++++++ src/game/options_menu.h | 11 + src/pc/configfile.c | 107 +++-- src/pc/configfile.h | 41 +- src/pc/controller/controller_api.h | 16 +- src/pc/controller/controller_entry_point.c | 15 + src/pc/controller/controller_keyboard.c | 71 ++- src/pc/controller/controller_keyboard.h | 2 + src/pc/controller/controller_recorded_tas.c | 9 +- src/pc/controller/controller_sdl.c | 108 ++++- src/pc/controller/controller_sdl.h | 2 + 17 files changed, 770 insertions(+), 406 deletions(-) create mode 100644 src/game/options_menu.c create mode 100644 src/game/options_menu.h diff --git a/Makefile b/Makefile index 7f519d81..8a52418f 100644 --- a/Makefile +++ b/Makefile @@ -448,8 +448,8 @@ endif # Check for better camera option ifeq ($(BETTERCAMERA),1) -CC_CHECK += -DBETTERCAMERA -CFLAGS += -DBETTERCAMERA +CC_CHECK += -DBETTERCAMERA -DEXT_OPTIONS_MENU +CFLAGS += -DBETTERCAMERA -DEXT_OPTIONS_MENU endif # Check for no drawing distance option @@ -588,11 +588,13 @@ ifeq ($(VERSION),eu) $(BUILD_DIR)/src/menu/file_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o $(BUILD_DIR)/src/menu/star_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o $(BUILD_DIR)/src/game/ingame_menu.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o +$(BUILD_DIR)/src/game/options_menu.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o O_FILES += $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o else $(BUILD_DIR)/src/menu/file_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/src/menu/star_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/src/game/ingame_menu.o: $(BUILD_DIR)/include/text_strings.h +$(BUILD_DIR)/src/game/options_menu.o: $(BUILD_DIR)/include/text_strings.h endif ################################################################ diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 030f3959..88fe2f7c 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -3,20 +3,39 @@ #include "text_menu_strings.h" -#define NC_CAMX _("Camera X Sensitivity") -#define NC_CAMY _("Camera Y Sensitivity") -#define NC_INVERTX _("Invert X Axis") -#define NC_INVERTY _("Invert Y Axis") -#define NC_CAMC _("Camera Centre Aggression") -#define NC_CAMP _("Camera Pan Level") -#define NC_ENABLED _("Enabled") -#define NC_DISABLED _("Disabled") -#define NC_BUTTON _("[R]: Options") -#define NC_BUTTON2 _("[R]: Return") -#define NC_OPTION _("OPTIONS") -#define NC_HIGHLIGHT _("O") -#define NC_ANALOGUE _("Analogue Camera") -#define NC_MOUSE _("Mouse Look") +#define TEXT_OPT_CAMX _("Camera X Sensitivity") +#define TEXT_OPT_CAMY _("Camera Y Sensitivity") +#define TEXT_OPT_INVERTX _("Invert X Axis") +#define TEXT_OPT_INVERTY _("Invert Y Axis") +#define TEXT_OPT_CAMC _("Camera Centre Aggression") +#define TEXT_OPT_CAMP _("Camera Pan Level") +#define TEXT_OPT_ENABLED _("Enabled") +#define TEXT_OPT_DISABLED _("Disabled") +#define TEXT_OPT_BUTTON1 _("[R]: Options") +#define TEXT_OPT_BUTTON2 _("[R]: Return") +#define TEXT_OPT_OPTIONS _("OPTIONS") +#define TEXT_OPT_CAMERA _("CAMERA") +#define TEXT_OPT_CONTROLS _("CONTROLS") +#define TEXT_OPT_HIGHLIGHT _("O") +#define TEXT_OPT_ANALOGUE _("Analogue Camera") +#define TEXT_OPT_MOUSE _("Mouse Look") + +#define TEXT_OPT_UNBOUND _("NONE") +#define TEXT_OPT_PRESSKEY _("...") +#define TEXT_BIND_A _("A Button") +#define TEXT_BIND_B _("B Button") +#define TEXT_BIND_START _("Start Button") +#define TEXT_BIND_L _("L Trigger") +#define TEXT_BIND_R _("R Trigger") +#define TEXT_BIND_Z _("Z Trigger") +#define TEXT_BIND_C_UP _("C-Up") +#define TEXT_BIND_C_DOWN _("C-Down") +#define TEXT_BIND_C_LEFT _("C-Left") +#define TEXT_BIND_C_RIGHT _("C-Right") +#define TEXT_BIND_UP _("Stick Up") +#define TEXT_BIND_DOWN _("Stick Down") +#define TEXT_BIND_LEFT _("Stick Left") +#define TEXT_BIND_RIGHT _("Stick Right") /** * Global Symbols diff --git a/src/game/bettercamera.h b/src/game/bettercamera.h index b3355ef6..ea814dd7 100644 --- a/src/game/bettercamera.h +++ b/src/game/bettercamera.h @@ -26,14 +26,9 @@ enum newcam_flagvalues }; -extern void newcam_display_options(void); -extern void newcam_check_pause_buttons(void); extern void newcam_init_settings(void); -extern void newcam_save_settings(void); -extern void newcam_render_option_text(void); extern void newcam_diagnostics(void); -extern u8 newcam_option_open; extern u8 newcam_sensitivityX; //How quick the camera works. extern u8 newcam_sensitivityY; diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index 6c9592b8..a4ffa7fe 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -105,17 +105,6 @@ u16 newcam_mode; u16 newcam_intendedmode = 0; // which camera mode the camera's going to try to be in when not forced into another. u16 newcam_modeflags; -u8 newcam_option_open = 0; -s8 newcam_option_selection = 0; -f32 newcam_option_timer = 0; -u8 newcam_option_index = 0; -u8 newcam_option_scroll = 0; -u8 newcam_option_scroll_last = 0; -u8 newcam_total = 8; //How many options there are in newcam_uptions. - -u8 newcam_options[][64] = {{NC_ANALOGUE}, {NC_MOUSE}, {NC_CAMX}, {NC_CAMY}, {NC_INVERTX}, {NC_INVERTY}, {NC_CAMC}, {NC_CAMP}}; -u8 newcam_flags[][64] = {{NC_DISABLED}, {NC_ENABLED}}; -u8 newcam_strings[][64] = {{NC_BUTTON}, {NC_BUTTON2}, {NC_OPTION}, {NC_HIGHLIGHT}}; extern int mouse_x; extern int mouse_y; @@ -168,18 +157,6 @@ void newcam_init_settings(void) newcam_analogue = (u8)configEnableCamera; } -void newcam_save_settings(void) -{ - configCameraXSens = newcam_sensitivityX; - configCameraYSens = newcam_sensitivityY; - configCameraAggr = newcam_aggression; - configCameraPan = newcam_panlevel; - configCameraInvertX = newcam_invertX != 0; - configCameraInvertY = newcam_invertY != 0; - configEnableCamera = newcam_analogue != 0; - configCameraMouse = newcam_mouse != 0; -} - /** Mathematic calculations. This stuffs so basic even *I* understand it lol Basically, it just returns a position based on angle */ static s16 lengthdir_x(f32 length, s16 dir) @@ -670,234 +647,10 @@ void newcam_loop(struct Camera *c) newcam_position_cam(); newcam_find_fixed(); if (gMarioObject) - newcam_apply_values(c); + newcam_apply_values(c); //Just some visual information on the values of the camera. utilises ifdef because it's better at runtime. #ifdef NEWCAM_DEBUG newcam_diagnostics(); #endif // NEWCAM_DEBUG } - - - -//Displays a box. -void newcam_display_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b) -{ - gDPPipeSync(gDisplayListHead++); - gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2); - gDPSetCycleType(gDisplayListHead++, G_CYC_FILL); - gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(r, g, b, 255)); - gDPFillRectangle(gDisplayListHead++, x1, y1, x2 - 1, y2 - 1); - gDPPipeSync(gDisplayListHead++); - gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE); -} - -//I actually took the time to redo this, properly. Lmao. Please don't bully me over this anymore :( -void newcam_change_setting(u8 toggle) -{ - switch (newcam_option_selection) - { - case 0: - newcam_analogue ^= 1; - break; - case 1: - newcam_mouse ^= 1; - break; - case 2: - newcam_sensitivityX = newcam_clamp(newcam_sensitivityX + toggle, 10, 250); - break; - case 3: - newcam_sensitivityY = newcam_clamp(newcam_sensitivityY + toggle, 10, 250); - break; - case 4: - newcam_invertX ^= 1; - break; - case 5: - newcam_invertY ^= 1; - break; - case 6: - newcam_aggression = newcam_clamp(newcam_aggression + toggle, 0, 100); - break; - case 7: - newcam_panlevel = newcam_clamp(newcam_panlevel + toggle, 0, 100); - break; - } -} - -void newcam_text(s16 x, s16 y, u8 str[], u8 col) -{ - u8 textX; - textX = get_str_x_pos_from_center(x,str,10.0f); - gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255); - print_generic_string(textX+1,y-1,str); - if (col != 0) - { - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - } - else - { - gDPSetEnvColor(gDisplayListHead++, 255, 32, 32, 255); - } - print_generic_string(textX,y,str); -} - -//Options menu -void newcam_display_options() -{ - u8 i = 0; - u8 newstring[32]; - s16 scroll; - s16 scrollpos; - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - print_hud_lut_string(HUD_LUT_GLOBAL, 118, 40, newcam_strings[2]); - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); - - if (newcam_total>4) - { - newcam_display_box(272,90,280,208,0x80,0x80,0x80); - scrollpos = (54)*((f32)newcam_option_scroll/(newcam_total-4)); - newcam_display_box(272,90+scrollpos,280,154+scrollpos,0xFF,0xFF,0xFF); - } - - - gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); - gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 80, SCREEN_WIDTH, SCREEN_HEIGHT); - for (i = 0; i < newcam_total; i++) - { - scroll = 140-(32*i)+(newcam_option_scroll*32); - if (scroll <= 140 && scroll > 32) - { - newcam_text(160,scroll,newcam_options[i],newcam_option_selection-i); - switch (i) - { - case 0: - newcam_text(160,scroll-12,newcam_flags[newcam_analogue],newcam_option_selection-i); - break; - case 1: - newcam_text(160,scroll-12,newcam_flags[newcam_mouse],newcam_option_selection-i); - break; - case 2: - int_to_str(newcam_sensitivityX,newstring); - newcam_text(160,scroll-12,newstring,newcam_option_selection-i); - break; - case 3: - int_to_str(newcam_sensitivityY,newstring); - newcam_text(160,scroll-12,newstring,newcam_option_selection-i); - break; - case 4: - newcam_text(160,scroll-12,newcam_flags[newcam_invertX],newcam_option_selection-i); - break; - case 5: - newcam_text(160,scroll-12,newcam_flags[newcam_invertY],newcam_option_selection-i); - break; - case 6: - int_to_str(newcam_aggression,newstring); - newcam_text(160,scroll-12,newstring,newcam_option_selection-i); - break; - case 7: - int_to_str(newcam_panlevel,newstring); - newcam_text(160,scroll-12,newstring,newcam_option_selection-i); - break; - } - } - } - gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - gSPDisplayList(gDisplayListHead++, dl_ia_text_end); - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); - print_hud_lut_string(HUD_LUT_GLOBAL, 80, 90+(32*(newcam_option_selection-newcam_option_scroll)), newcam_strings[3]); - print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90+(32*(newcam_option_selection-newcam_option_scroll)), newcam_strings[3]); - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); -} - -//This has been separated for interesting reasons. Don't question it. -void newcam_render_option_text(void) -{ - gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); - newcam_text(278,212,newcam_strings[newcam_option_open],1); - gSPDisplayList(gDisplayListHead++, dl_ia_text_end); -} - -void newcam_check_pause_buttons() -{ - if (gPlayer1Controller->buttonPressed & R_TRIG) - { - if (newcam_option_open == 0) - { - #ifndef nosound - play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); - #endif - newcam_option_open = 1; - } - else - { - #ifndef nosound - play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs); - #endif - newcam_option_open = 0; - newcam_save_settings(); - } - } - - if (newcam_option_open) - { - if (ABS(gPlayer1Controller->stickY) > 60) - { - newcam_option_timer -= 1; - if (newcam_option_timer <= 0) - { - switch (newcam_option_index) - { - case 0: newcam_option_index++; newcam_option_timer += 10; break; - default: newcam_option_timer += 3; break; - } - #ifndef nosound - play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); - #endif - if (gPlayer1Controller->stickY >= 60) - { - newcam_option_selection--; - if (newcam_option_selection < 0) - newcam_option_selection = newcam_total-1; - } - else - { - newcam_option_selection++; - if (newcam_option_selection >= newcam_total) - newcam_option_selection = 0; - } - } - } - else - if (ABS(gPlayer1Controller->stickX) > 60) - { - newcam_option_timer -= 1; - if (newcam_option_timer <= 0) - { - switch (newcam_option_index) - { - case 0: newcam_option_index++; newcam_option_timer += 10; break; - default: newcam_option_timer += 3; break; - } - #ifndef nosound - play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); - #endif - if (gPlayer1Controller->stickX >= 60) - newcam_change_setting(1); - else - newcam_change_setting(-1); - } - } - else - { - newcam_option_timer = 0; - newcam_option_index = 0; - } - - while (newcam_option_scroll - newcam_option_selection < -3 && newcam_option_selection > newcam_option_scroll) - newcam_option_scroll +=1; - while (newcam_option_scroll + newcam_option_selection > 0 && newcam_option_selection < newcam_option_scroll) - newcam_option_scroll -=1; - } -} diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index bfcbf42b..55ab55b3 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -22,6 +22,9 @@ #ifdef BETTERCAMERA #include "bettercamera.h" #endif +#ifdef EXT_OPTIONS_MENU +#include "options_menu.h" +#endif extern Gfx *gDisplayListHead; extern s16 gCurrCourseNum; @@ -2629,9 +2632,8 @@ s16 render_pause_courses_and_castle(void) { #ifdef VERSION_EU gInGameLanguage = eu_get_language(); #endif -#ifdef BETTERCAMERA - if (newcam_option_open == 0) - { +#ifdef EXT_OPTIONS_MENU + if (optmenu_open == 0) { #endif switch (gDialogBoxState) { case DIALOG_STATE_OPENING: @@ -2708,15 +2710,13 @@ s16 render_pause_courses_and_castle(void) { if (gDialogTextAlpha < 250) { gDialogTextAlpha += 25; } -#ifdef BETTERCAMERA - } - else - { +#ifdef EXT_OPTIONS_MENU + } else { shade_screen(); - newcam_display_options(); + optmenu_draw(); } - newcam_check_pause_buttons(); - newcam_render_option_text(); + optmenu_check_buttons(); + optmenu_draw_prompt(); #endif return 0; diff --git a/src/game/level_update.c b/src/game/level_update.c index 13246ad5..cdff8853 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -179,7 +179,7 @@ u8 unused3[4]; u8 unused4[2]; // For configfile intro skipping -extern unsigned int configSkipIntro; +//extern unsigned int configSkipIntro; void basic_update(s16 *arg); @@ -1217,7 +1217,7 @@ s32 init_level(void) { if (gMarioState->action != ACT_UNINITIALIZED) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) { + } else if (gCLIOpts.SkipIntro == 0) { set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); val4 = 1; } diff --git a/src/game/options_menu.c b/src/game/options_menu.c new file mode 100644 index 00000000..9e2b7e86 --- /dev/null +++ b/src/game/options_menu.c @@ -0,0 +1,463 @@ +#ifdef EXT_OPTIONS_MENU + +#include "sm64.h" +#include "include/text_strings.h" +#include "engine/math_util.h" +#include "audio/external.h" +#include "game/camera.h" +#include "game/level_update.h" +#include "game/print.h" +#include "game/segment2.h" +#include "game/save_file.h" +#include "game/bettercamera.h" +#include "game/mario_misc.h" +#include "game/game_init.h" +#include "game/ingame_menu.h" +#include "game/options_menu.h" +#include "pc/configfile.h" +#include "pc/controller/controller_api.h" + +#include + +u8 optmenu_open = 0; + +static u8 optmenu_binding = 0; +static u8 optmenu_bind_idx = 0; + +// How to add stuff: +// strings: add them to include/text_strings.h.in +// and to menuStr[] / opts*Str[] +// options: add them to the relevant options list +// menus: add a new submenu definition and a new +// option to the optsMain list + +static const u8 toggleStr[][64] = { + { TEXT_OPT_DISABLED }, + { TEXT_OPT_ENABLED }, +}; + +static const u8 menuStr[][64] = { + { TEXT_OPT_HIGHLIGHT }, + { TEXT_OPT_BUTTON1 }, + { TEXT_OPT_BUTTON2 }, + { TEXT_OPT_OPTIONS }, + { TEXT_OPT_CAMERA }, + { TEXT_OPT_CONTROLS }, +}; + +static const u8 optsCameraStr[][64] = { + { TEXT_OPT_CAMX }, + { TEXT_OPT_CAMY }, + { TEXT_OPT_INVERTX }, + { TEXT_OPT_INVERTY }, + { TEXT_OPT_CAMC }, + { TEXT_OPT_CAMP }, + { TEXT_OPT_ANALOGUE }, + { TEXT_OPT_MOUSE }, +}; + +static const u8 bindStr[][64] = { + { TEXT_OPT_UNBOUND }, + { TEXT_OPT_PRESSKEY }, + { TEXT_BIND_A }, + { TEXT_BIND_B }, + { TEXT_BIND_START }, + { TEXT_BIND_L }, + { TEXT_BIND_R }, + { TEXT_BIND_Z }, + { TEXT_BIND_C_UP }, + { TEXT_BIND_C_DOWN }, + { TEXT_BIND_C_LEFT }, + { TEXT_BIND_C_RIGHT }, + { TEXT_BIND_UP }, + { TEXT_BIND_DOWN }, + { TEXT_BIND_LEFT }, + { TEXT_BIND_RIGHT }, +}; + +enum OptType { + OPT_INVALID = 0, + OPT_TOGGLE, + OPT_CHOICE, + OPT_SCROLL, + OPT_SUBMENU, + OPT_BIND, +}; + +struct SubMenu; + +struct Option { + enum OptType type; + const u8 *label; + union { + u32 *uval; + bool *bval; + }; + union { + struct { + const u8 **choices; + u32 numChoices; + }; + struct { + u32 scrMin; + u32 scrMax; + u32 scrStep; + }; + struct SubMenu *nextMenu; + }; +}; + +struct SubMenu { + struct SubMenu *prev; // this is set at runtime to avoid needless complication + const u8 *label; + struct Option *opts; + s32 numOpts; + s32 select; + s32 scroll; +}; + +/* submenu option lists */ + +static struct Option optsCamera[] = { + { .type = OPT_TOGGLE, .label = optsCameraStr[6], .bval = &configEnableCamera, }, + { .type = OPT_TOGGLE, .label = optsCameraStr[7], .bval = &configCameraMouse, }, + { .type = OPT_TOGGLE, .label = optsCameraStr[2], .bval = &configCameraInvertX, }, + { .type = OPT_TOGGLE, .label = optsCameraStr[3], .bval = &configCameraInvertY, }, + { .type = OPT_SCROLL, .label = optsCameraStr[0], .uval = &configCameraXSens, .scrMin = 10, .scrMax = 250, .scrStep = 1 }, + { .type = OPT_SCROLL, .label = optsCameraStr[1], .uval = &configCameraYSens, .scrMin = 10, .scrMax = 250, .scrStep = 1 }, + { .type = OPT_SCROLL, .label = optsCameraStr[4], .uval = &configCameraAggr, .scrMin = 0, .scrMax = 100, .scrStep = 1 }, + { .type = OPT_SCROLL, .label = optsCameraStr[5], .uval = &configCameraPan, .scrMin = 0, .scrMax = 100, .scrStep = 1 }, +}; + +static struct Option optsControls[] = { + { .type = OPT_BIND, .label = bindStr[2], .uval = configKeyA, }, + { .type = OPT_BIND, .label = bindStr[3], .uval = configKeyB, }, + { .type = OPT_BIND, .label = bindStr[4], .uval = configKeyStart, }, + { .type = OPT_BIND, .label = bindStr[5], .uval = configKeyL, }, + { .type = OPT_BIND, .label = bindStr[6], .uval = configKeyR, }, + { .type = OPT_BIND, .label = bindStr[7], .uval = configKeyZ, }, + { .type = OPT_BIND, .label = bindStr[8], .uval = configKeyCUp, }, + { .type = OPT_BIND, .label = bindStr[9], .uval = configKeyCDown, }, + { .type = OPT_BIND, .label = bindStr[10], .uval = configKeyCLeft, }, + { .type = OPT_BIND, .label = bindStr[11], .uval = configKeyCRight, }, + { .type = OPT_BIND, .label = bindStr[12], .uval = configKeyStickUp, }, + { .type = OPT_BIND, .label = bindStr[13], .uval = configKeyStickDown, }, + { .type = OPT_BIND, .label = bindStr[14], .uval = configKeyStickLeft, }, + { .type = OPT_BIND, .label = bindStr[15], .uval = configKeyStickRight, }, +}; + +/* submenu definitions */ + +static struct SubMenu menuCamera = { + .label = menuStr[4], + .opts = optsCamera, + .numOpts = sizeof(optsCamera) / sizeof(optsCamera[0]), +}; + +static struct SubMenu menuControls = { + .label = menuStr[5], + .opts = optsControls, + .numOpts = sizeof(optsControls) / sizeof(optsControls[0]), +}; + +/* main options menu definition */ + +static struct Option optsMain[] = { + { .type = OPT_SUBMENU, .label = menuStr[4], .nextMenu = &menuCamera, }, + { .type = OPT_SUBMENU, .label = menuStr[5], .nextMenu = &menuControls, }, +}; + +static struct SubMenu menuMain = { + .label = menuStr[3], + .opts = optsMain, + .numOpts = sizeof(optsMain) / sizeof(optsMain[0]), +}; + +/* implementation */ + +static s32 optmenu_option_timer = 0; +static u8 optmenu_hold_count = 0; + +static struct SubMenu *currentMenu = &menuMain; + +static inline s32 wrap_add(s32 a, const s32 b, const s32 min, const s32 max) { + a += b; + if (a < min) a = max - (min - a) + 1; + else if (a > max) a = min + (a - max) - 1; + return a; +} + +static void uint_to_hex(u32 num, u8 *dst) { + u8 places = 4; + while (places--) { + const u32 digit = num & 0xF; + dst[places] = digit; + num >>= 4; + } + dst[4] = DIALOG_CHAR_TERMINATOR; +} + +//Displays a box. +static void optmenu_draw_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b) { + gDPPipeSync(gDisplayListHead++); + gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2); + gDPSetCycleType(gDisplayListHead++, G_CYC_FILL); + gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(r, g, b, 255)); + gDPFillRectangle(gDisplayListHead++, x1, y1, x2 - 1, y2 - 1); + gDPPipeSync(gDisplayListHead++); + gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE); +} + +static void optmenu_draw_text(s16 x, s16 y, const u8 *str, u8 col) { + const u8 textX = get_str_x_pos_from_center(x, (u8*)str, 10.0f); + gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255); + print_generic_string(textX+1, y-1, str); + if (col == 0) { + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); + } else { + gDPSetEnvColor(gDisplayListHead++, 255, 32, 32, 255); + } + print_generic_string(textX, y, str); +} + +static void optmenu_draw_opt(const struct Option *opt, s16 x, s16 y, u8 sel) { + u8 buf[32] = { 0 }; + + if (opt->type == OPT_SUBMENU) + y -= 6; + + optmenu_draw_text(x, y, opt->label, sel); + + switch (opt->type) { + case OPT_TOGGLE: + optmenu_draw_text(x, y-13, toggleStr[(int)*opt->bval], sel); + break; + + case OPT_CHOICE: + optmenu_draw_text(x, y-13, opt->choices[*opt->uval], sel); + break; + + case OPT_SCROLL: + int_to_str(*opt->uval, buf); + optmenu_draw_text(x, y-13, buf, sel); + break; + + case OPT_BIND: + x = 112; + for (u8 i = 0; i < MAX_BINDS; ++i, x += 48) { + const u8 white = (sel && (optmenu_bind_idx == i)); + // TODO: button names + if (opt->uval[i] == VK_INVALID) { + if (optmenu_binding && white) + optmenu_draw_text(x, y-13, bindStr[1], 1); + else + optmenu_draw_text(x, y-13, bindStr[0], white); + } else { + uint_to_hex(opt->uval[i], buf); + optmenu_draw_text(x, y-13, buf, white); + } + } + break; + + default: break; + }; +} + +static void optmenu_opt_change(struct Option *opt, s32 val) { + switch (opt->type) { + case OPT_TOGGLE: + *opt->bval = !*opt->bval; + break; + + case OPT_CHOICE: + *opt->uval = wrap_add(*opt->uval, val, 0, opt->numChoices - 1); + break; + + case OPT_SCROLL: + *opt->uval = wrap_add(*opt->uval, val, opt->scrMin, opt->scrMax); + break; + + case OPT_SUBMENU: + opt->nextMenu->prev = currentMenu; + currentMenu = opt->nextMenu; + break; + + case OPT_BIND: + if (val == 0xFF) { + // clear the bind + opt->uval[optmenu_bind_idx] = VK_INVALID; + } else if (val == 0) { + opt->uval[optmenu_bind_idx] = VK_INVALID; + optmenu_binding = 1; + controller_get_raw_key(); // clear the last key, which is probably A + } else { + optmenu_bind_idx = wrap_add(optmenu_bind_idx, val, 0, MAX_BINDS - 1); + } + break; + + default: break; + }; +} + +static inline s16 get_hudstr_centered_x(const s16 sx, const u8 *str) { + const u8 *chr = str; + s16 len = 0; + while (*chr != GLOBAR_CHAR_TERMINATOR) ++chr, ++len; + return sx - len * 6; // stride is 12 +} + +//Options menu +void optmenu_draw(void) { + s16 scroll; + s16 scrollpos; + + const s16 labelX = get_hudstr_centered_x(160, currentMenu->label); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); + print_hud_lut_string(HUD_LUT_GLOBAL, labelX, 40, currentMenu->label); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); + + if (currentMenu->numOpts > 4) { + optmenu_draw_box(272, 90, 280, 208, 0x80, 0x80, 0x80); + scrollpos = 54 * ((f32)currentMenu->scroll / (currentMenu->numOpts-4)); + optmenu_draw_box(272, 90+scrollpos, 280, 154+scrollpos, 0xFF, 0xFF, 0xFF); + } + + gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); + gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 80, SCREEN_WIDTH, SCREEN_HEIGHT); + for (u8 i = 0; i < currentMenu->numOpts; i++) { + scroll = 140 - 32 * i + currentMenu->scroll * 32; + // FIXME: just start from the first visible option bruh + if (scroll <= 140 && scroll > 32) + optmenu_draw_opt(¤tMenu->opts[i], 160, scroll, (currentMenu->select == i)); + } + + gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + gSPDisplayList(gDisplayListHead++, dl_ia_text_end); + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); + print_hud_lut_string(HUD_LUT_GLOBAL, 80, 90 + (32 * (currentMenu->select - currentMenu->scroll)), menuStr[0]); + print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90 + (32 * (currentMenu->select - currentMenu->scroll)), menuStr[0]); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); +} + +//This has been separated for interesting reasons. Don't question it. +void optmenu_draw_prompt(void) { + gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); + optmenu_draw_text(278, 212, menuStr[1 + optmenu_open], 0); + gSPDisplayList(gDisplayListHead++, dl_ia_text_end); +} + +void optmenu_toggle(void) { + if (optmenu_open == 0) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + currentMenu = &menuMain; + optmenu_open = 1; + } else { + #ifndef nosound + play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs); + #endif + optmenu_open = 0; + newcam_init_settings(); // load bettercam settings from config vars + controller_reconfigure(); // rebind using new config values + configfile_save(CONFIG_FILE); + } +} + +void optmenu_check_buttons(void) { + if (optmenu_binding) { + u32 key = controller_get_raw_key(); + if (key != VK_INVALID) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + currentMenu->opts[currentMenu->select].uval[optmenu_bind_idx] = key; + optmenu_binding = 0; + optmenu_option_timer = 12; + } + return; + } + + if (gPlayer1Controller->buttonPressed & R_TRIG) + optmenu_toggle(); + + if (!optmenu_open) return; + + u8 allowInput = 0; + + optmenu_option_timer--; + if (optmenu_option_timer <= 0) { + if (optmenu_hold_count == 0) { + optmenu_hold_count++; + optmenu_option_timer = 10; + } else { + optmenu_option_timer = 3; + } + allowInput = 1; + } + + if (ABS(gPlayer1Controller->stickY) > 60) { + if (allowInput) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + + if (gPlayer1Controller->stickY >= 60) { + currentMenu->select--; + if (currentMenu->select < 0) + currentMenu->select = currentMenu->numOpts-1; + } else { + currentMenu->select++; + if (currentMenu->select >= currentMenu->numOpts) + currentMenu->select = 0; + } + + if (currentMenu->select < currentMenu->scroll) + currentMenu->scroll = currentMenu->select; + else if (currentMenu->select > currentMenu->scroll + 3) + currentMenu->scroll = currentMenu->select - 3; + } + } else if (ABS(gPlayer1Controller->stickX) > 60) { + if (allowInput) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + if (gPlayer1Controller->stickX >= 60) + optmenu_opt_change(¤tMenu->opts[currentMenu->select], 1); + else + optmenu_opt_change(¤tMenu->opts[currentMenu->select], -1); + } + } else if (gPlayer1Controller->buttonPressed & A_BUTTON) { + if (allowInput) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + optmenu_opt_change(¤tMenu->opts[currentMenu->select], 0); + } + } else if (gPlayer1Controller->buttonPressed & B_BUTTON) { + if (allowInput) { + if (currentMenu->prev) { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + currentMenu = currentMenu->prev; + } else { + // can't go back, exit the menu altogether + optmenu_toggle(); + } + } + } else if (gPlayer1Controller->buttonPressed & Z_TRIG) { + // HACK: clear binds with Z + if (allowInput && currentMenu->opts[currentMenu->select].type == OPT_BIND) + optmenu_opt_change(¤tMenu->opts[currentMenu->select], 0xFF); + } else if (gPlayer1Controller->buttonPressed & START_BUTTON) { + if (allowInput) optmenu_toggle(); + } else { + optmenu_hold_count = 0; + optmenu_option_timer = 0; + } +} + +#endif // EXT_OPTIONS_MENU diff --git a/src/game/options_menu.h b/src/game/options_menu.h new file mode 100644 index 00000000..4828ae9d --- /dev/null +++ b/src/game/options_menu.h @@ -0,0 +1,11 @@ +#ifndef OPTIONS_MENU_H +#define OPTIONS_MENU_H + +void optmenu_toggle(void); +void optmenu_draw(void); +void optmenu_draw_prompt(void); +void optmenu_check_buttons(void); + +extern u8 optmenu_open; + +#endif // OPTIONS_MENU_H diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 6b1e83b0..cee4dfdb 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -7,6 +7,7 @@ #include #include "configfile.h" +#include "controller/controller_api.h" #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) @@ -14,6 +15,7 @@ enum ConfigOptionType { CONFIG_TYPE_BOOL, CONFIG_TYPE_UINT, CONFIG_TYPE_FLOAT, + CONFIG_TYPE_BIND, }; struct ConfigOption { @@ -29,35 +31,24 @@ struct ConfigOption { /* *Config options and default values */ -bool configFullscreen = false; -// Keyboard mappings (scancode values) -unsigned int configKeyA = 0x26; -unsigned int configKeyB = 0x33; -unsigned int configKeyStart = 0x39; -unsigned int configKeyL = 0x34; -unsigned int configKeyR = 0x36; -unsigned int configKeyZ = 0x25; -unsigned int configKeyCUp = 0x148; -unsigned int configKeyCDown = 0x150; -unsigned int configKeyCLeft = 0x14B; -unsigned int configKeyCRight = 0x14D; -unsigned int configKeyStickUp = 0x11; -unsigned int configKeyStickDown = 0x1F; -unsigned int configKeyStickLeft = 0x1E; -unsigned int configKeyStickRight = 0x20; -// Gamepad mappings (SDL_GameControllerButton values) -unsigned int configJoyA = 0; -unsigned int configJoyB = 2; -unsigned int configJoyStart = 6; -unsigned int configJoyL = 7; -unsigned int configJoyR = 10; -unsigned int configJoyZ = 9; -// Mouse button mappings (0 for none, 1 for left, 2 for middle, 3 for right) -unsigned int configMouseA = 3; -unsigned int configMouseB = 1; -unsigned int configMouseL = 4; -unsigned int configMouseR = 5; -unsigned int configMouseZ = 2; + +bool configFullscreen = false; +// Keyboard mappings (VK_ values, by default keyboard/gamepad/mouse) +unsigned int configKeyA[MAX_BINDS] = { 0x0026, 0x1000, 0x1103 }; +unsigned int configKeyB[MAX_BINDS] = { 0x0033, 0x1002, 0x1101 }; +unsigned int configKeyStart[MAX_BINDS] = { 0x0039, 0x1006, VK_INVALID }; +unsigned int configKeyL[MAX_BINDS] = { 0x0034, 0x1007, 0x1104 }; +unsigned int configKeyR[MAX_BINDS] = { 0x0036, 0x100A, 0x1105 }; +unsigned int configKeyZ[MAX_BINDS] = { 0x0025, 0x1009, 0x1102 }; +unsigned int configKeyCUp[MAX_BINDS] = { 0x0148, VK_INVALID, VK_INVALID }; +unsigned int configKeyCDown[MAX_BINDS] = { 0x0150, VK_INVALID, VK_INVALID }; +unsigned int configKeyCLeft[MAX_BINDS] = { 0x014B, VK_INVALID, VK_INVALID }; +unsigned int configKeyCRight[MAX_BINDS] = { 0x014D, VK_INVALID, VK_INVALID }; +unsigned int configKeyStickUp[MAX_BINDS] = { 0x0011, VK_INVALID, VK_INVALID }; +unsigned int configKeyStickDown[MAX_BINDS] = { 0x001F, VK_INVALID, VK_INVALID }; +unsigned int configKeyStickLeft[MAX_BINDS] = { 0x001E, VK_INVALID, VK_INVALID }; +unsigned int configKeyStickRight[MAX_BINDS] = { 0x0020, VK_INVALID, VK_INVALID }; + #ifdef BETTERCAMERA // BetterCamera settings unsigned int configCameraXSens = 50; @@ -69,35 +60,23 @@ bool configCameraInvertY = false; bool configEnableCamera = false; bool configCameraMouse = false; #endif -unsigned int configSkipIntro = 0; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen}, - {.name = "key_a", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyA}, - {.name = "key_b", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyB}, - {.name = "key_start", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStart}, - {.name = "key_l", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyL}, - {.name = "key_r", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyR}, - {.name = "key_z", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyZ}, - {.name = "key_cup", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCUp}, - {.name = "key_cdown", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCDown}, - {.name = "key_cleft", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCLeft}, - {.name = "key_cright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCRight}, - {.name = "key_stickup", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickUp}, - {.name = "key_stickdown", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickDown}, - {.name = "key_stickleft", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickLeft}, - {.name = "key_stickright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickRight}, - {.name = "joy_a", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyA}, - {.name = "joy_b", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyB}, - {.name = "joy_start", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyStart}, - {.name = "joy_l", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyL}, - {.name = "joy_r", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyR}, - {.name = "joy_z", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyZ}, - {.name = "mouse_a", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseA}, - {.name = "mouse_b", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseB}, - {.name = "mouse_l", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseL}, - {.name = "mouse_r", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseR}, - {.name = "mouse_z", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseZ}, + {.name = "key_a", .type = CONFIG_TYPE_BIND, .uintValue = configKeyA}, + {.name = "key_b", .type = CONFIG_TYPE_BIND, .uintValue = configKeyB}, + {.name = "key_start", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStart}, + {.name = "key_l", .type = CONFIG_TYPE_BIND, .uintValue = configKeyL}, + {.name = "key_r", .type = CONFIG_TYPE_BIND, .uintValue = configKeyR}, + {.name = "key_z", .type = CONFIG_TYPE_BIND, .uintValue = configKeyZ}, + {.name = "key_cup", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCUp}, + {.name = "key_cdown", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCDown}, + {.name = "key_cleft", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCLeft}, + {.name = "key_cright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCRight}, + {.name = "key_stickup", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickUp}, + {.name = "key_stickdown", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickDown}, + {.name = "key_stickleft", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickLeft}, + {.name = "key_stickright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickRight}, #ifdef BETTERCAMERA {.name = "bettercam_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configEnableCamera}, {.name = "bettercam_mouse_look", .type = CONFIG_TYPE_BOOL, .boolValue = &configCameraMouse}, @@ -108,7 +87,7 @@ static const struct ConfigOption options[] = { {.name = "bettercam_aggression", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraAggr}, {.name = "bettercam_pan_level", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraPan}, #endif - {.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, + //{.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, // Add this back! }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string @@ -209,9 +188,13 @@ void configfile_load(const char *filename) { while (isspace(*p)) p++; + + if (!*p || *p == '#') // comment or empty line + continue; + numTokens = tokenize_string(p, 2, tokens); if (numTokens != 0) { - if (numTokens == 2) { + if (numTokens >= 2) { const struct ConfigOption *option = NULL; for (unsigned int i = 0; i < ARRAY_LEN(options); i++) { @@ -233,6 +216,10 @@ void configfile_load(const char *filename) { case CONFIG_TYPE_UINT: sscanf(tokens[1], "%u", option->uintValue); break; + case CONFIG_TYPE_BIND: + for (int i = 0; i < MAX_BINDS && i < numTokens - 1; ++i) + sscanf(tokens[i + 1], "%x", option->uintValue + i); + break; case CONFIG_TYPE_FLOAT: sscanf(tokens[1], "%f", option->floatValue); break; @@ -275,6 +262,12 @@ void configfile_save(const char *filename) { case CONFIG_TYPE_FLOAT: fprintf(file, "%s %f\n", option->name, *option->floatValue); break; + case CONFIG_TYPE_BIND: + fprintf(file, "%s ", option->name); + for (int i = 0; i < MAX_BINDS; ++i) + fprintf(file, "%04x ", option->uintValue[i]); + fprintf(file, "\n"); + break; default: assert(0); // unknown type } diff --git a/src/pc/configfile.h b/src/pc/configfile.h index a2044dd7..c53d6991 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -4,34 +4,23 @@ #include #define CONFIG_FILE "sm64config.txt" +#define MAX_BINDS 3 extern bool configFullscreen; -extern unsigned int configKeyA; -extern unsigned int configKeyB; -extern unsigned int configKeyStart; -extern unsigned int configKeyL; -extern unsigned int configKeyR; -extern unsigned int configKeyZ; -extern unsigned int configKeyCUp; -extern unsigned int configKeyCDown; -extern unsigned int configKeyCLeft; -extern unsigned int configKeyCRight; -extern unsigned int configKeyStickUp; -extern unsigned int configKeyStickDown; -extern unsigned int configKeyStickLeft; -extern unsigned int configKeyStickRight; -extern unsigned int configJoyA; -extern unsigned int configJoyB; -extern unsigned int configJoyStart; -extern unsigned int configJoyL; -extern unsigned int configJoyR; -extern unsigned int configJoyZ; -extern unsigned int configMouseA; -extern unsigned int configMouseB; -extern unsigned int configMouseStart; -extern unsigned int configMouseL; -extern unsigned int configMouseR; -extern unsigned int configMouseZ; +extern unsigned int configKeyA[]; +extern unsigned int configKeyB[]; +extern unsigned int configKeyStart[]; +extern unsigned int configKeyL[]; +extern unsigned int configKeyR[]; +extern unsigned int configKeyZ[]; +extern unsigned int configKeyCUp[]; +extern unsigned int configKeyCDown[]; +extern unsigned int configKeyCLeft[]; +extern unsigned int configKeyCRight[]; +extern unsigned int configKeyStickUp[]; +extern unsigned int configKeyStickDown[]; +extern unsigned int configKeyStickLeft[]; +extern unsigned int configKeyStickRight[]; #ifdef BETTERCAMERA extern unsigned int configCameraXSens; extern unsigned int configCameraYSens; diff --git a/src/pc/controller/controller_api.h b/src/pc/controller/controller_api.h index e040551a..fdd6e503 100644 --- a/src/pc/controller/controller_api.h +++ b/src/pc/controller/controller_api.h @@ -2,15 +2,21 @@ #define CONTROLLER_API #define DEADZONE 4960 - -// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors -// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera +#define VK_INVALID 0xFFFF +#define VK_SIZE 0x1000 #include struct ControllerAPI { - void (*init)(void); - void (*read)(OSContPad *pad); + const u32 vkbase; // base number in the virtual keyspace (e.g. keyboard is 0x0000-0x1000) + void (*init)(void); // call once, also calls reconfig() + void (*read)(OSContPad *pad); // read controller and update N64 pad values + u32 (*rawkey)(void); // returns last pressed virtual key or VK_INVALID if none + void (*reconfig)(void); // (optional) call when bindings have changed }; +// used for binding keys +u32 controller_get_raw_key(void); +void controller_reconfigure(void); + #endif diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index 9f3630a0..536b0798 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -56,3 +56,18 @@ void osContGetReadData(OSContPad *pad) { controller_implementations[i]->read(pad); } } + +u32 controller_get_raw_key(void) { + for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) { + u32 vk = controller_implementations[i]->rawkey(); + if (vk != VK_INVALID) return vk + controller_implementations[i]->vkbase; + } + return VK_INVALID; +} + +void controller_reconfigure(void) { + for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) { + if (controller_implementations[i]->reconfig) + controller_implementations[i]->reconfig(); + } +} diff --git a/src/pc/controller/controller_keyboard.c b/src/pc/controller/controller_keyboard.c index 87eaee0d..c9421a24 100644 --- a/src/pc/controller/controller_keyboard.c +++ b/src/pc/controller/controller_keyboard.c @@ -8,14 +8,19 @@ #endif #include "../configfile.h" +#include "controller_keyboard.h" static int keyboard_buttons_down; -static int keyboard_mapping[14][2]; +#define MAX_KEYBINDS 64 +static int keyboard_mapping[MAX_KEYBINDS][2]; +static int num_keybinds = 0; + +static u32 keyboard_lastkey = VK_INVALID; static int keyboard_map_scancode(int scancode) { int ret = 0; - for (size_t i = 0; i < sizeof(keyboard_mapping) / sizeof(keyboard_mapping[0]); i++) { + for (int i = 0; i < num_keybinds; i++) { if (keyboard_mapping[i][0] == scancode) { ret |= keyboard_mapping[i][1]; } @@ -26,12 +31,15 @@ static int keyboard_map_scancode(int scancode) { bool keyboard_on_key_down(int scancode) { int mapped = keyboard_map_scancode(scancode); keyboard_buttons_down |= mapped; + keyboard_lastkey = scancode; return mapped != 0; } bool keyboard_on_key_up(int scancode) { int mapped = keyboard_map_scancode(scancode); keyboard_buttons_down &= ~mapped; + if (keyboard_lastkey == (u32) scancode) + keyboard_lastkey = VK_INVALID; return mapped != 0; } @@ -39,28 +47,38 @@ void keyboard_on_all_keys_up(void) { keyboard_buttons_down = 0; } -static void set_keyboard_mapping(int index, int mask, int scancode) { - keyboard_mapping[index][0] = scancode; - keyboard_mapping[index][1] = mask; +static void keyboard_add_binds(int mask, unsigned int *scancode) { + for (int i = 0; i < MAX_BINDS && num_keybinds < MAX_KEYBINDS; ++i) { + if (scancode[i] < VK_BASE_KEYBOARD + VK_SIZE) { + keyboard_mapping[num_keybinds][0] = scancode[i]; + keyboard_mapping[num_keybinds][1] = mask; + num_keybinds++; + } + } +} + +static void keyboard_bindkeys(void) { + bzero(keyboard_mapping, sizeof(keyboard_mapping)); + num_keybinds = 0; + + keyboard_add_binds(0x80000, configKeyStickUp); + keyboard_add_binds(0x10000, configKeyStickLeft); + keyboard_add_binds(0x40000, configKeyStickDown); + keyboard_add_binds(0x20000, configKeyStickRight); + keyboard_add_binds(A_BUTTON, configKeyA); + keyboard_add_binds(B_BUTTON, configKeyB); + keyboard_add_binds(Z_TRIG, configKeyZ); + keyboard_add_binds(U_CBUTTONS, configKeyCUp); + keyboard_add_binds(L_CBUTTONS, configKeyCLeft); + keyboard_add_binds(D_CBUTTONS, configKeyCDown); + keyboard_add_binds(R_CBUTTONS, configKeyCRight); + keyboard_add_binds(L_TRIG, configKeyL); + keyboard_add_binds(R_TRIG, configKeyR); + keyboard_add_binds(START_BUTTON, configKeyStart); } static void keyboard_init(void) { - int i = 0; - - set_keyboard_mapping(i++, 0x80000, configKeyStickUp); - set_keyboard_mapping(i++, 0x10000, configKeyStickLeft); - set_keyboard_mapping(i++, 0x40000, configKeyStickDown); - set_keyboard_mapping(i++, 0x20000, configKeyStickRight); - set_keyboard_mapping(i++, A_BUTTON, configKeyA); - set_keyboard_mapping(i++, B_BUTTON, configKeyB); - set_keyboard_mapping(i++, Z_TRIG, configKeyZ); - set_keyboard_mapping(i++, U_CBUTTONS, configKeyCUp); - set_keyboard_mapping(i++, L_CBUTTONS, configKeyCLeft); - set_keyboard_mapping(i++, D_CBUTTONS, configKeyCDown); - set_keyboard_mapping(i++, R_CBUTTONS, configKeyCRight); - set_keyboard_mapping(i++, L_TRIG, configKeyL); - set_keyboard_mapping(i++, R_TRIG, configKeyR); - set_keyboard_mapping(i++, START_BUTTON, configKeyStart); + keyboard_bindkeys(); #ifdef TARGET_WEB controller_emscripten_keyboard_init(); @@ -83,7 +101,16 @@ static void keyboard_read(OSContPad *pad) { } } +static u32 keyboard_rawkey(void) { + const u32 ret = keyboard_lastkey; + keyboard_lastkey = VK_INVALID; + return ret; +} + struct ControllerAPI controller_keyboard = { + VK_BASE_KEYBOARD, keyboard_init, - keyboard_read + keyboard_read, + keyboard_rawkey, + keyboard_bindkeys, }; diff --git a/src/pc/controller/controller_keyboard.h b/src/pc/controller/controller_keyboard.h index e2c08586..028d2e85 100644 --- a/src/pc/controller/controller_keyboard.h +++ b/src/pc/controller/controller_keyboard.h @@ -4,6 +4,8 @@ #include #include "controller_api.h" +# define VK_BASE_KEYBOARD 0x0000 + #ifdef __cplusplus extern "C" { #endif diff --git a/src/pc/controller/controller_recorded_tas.c b/src/pc/controller/controller_recorded_tas.c index 4f5c1bb0..f05c0558 100644 --- a/src/pc/controller/controller_recorded_tas.c +++ b/src/pc/controller/controller_recorded_tas.c @@ -23,7 +23,14 @@ static void tas_read(OSContPad *pad) { } } +static u32 tas_rawkey(void) { + return VK_INVALID; +} + struct ControllerAPI controller_recorded_tas = { + VK_INVALID, tas_init, - tas_read + tas_read, + tas_rawkey, + NULL, // no rebinding }; diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 48120231..171a31f4 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -11,9 +11,15 @@ #include #include "controller_api.h" - +#include "controller_sdl.h" #include "../configfile.h" +// mouse buttons are also in the controller namespace (why), just offset 0x100 +#define VK_OFS_SDL_MOUSE 0x0100 +#define VK_BASE_SDL_MOUSE (VK_BASE_SDL_GAMEPAD + VK_OFS_SDL_MOUSE) +#define MAX_JOYBINDS 32 +#define MAX_MOUSEBUTTONS 8 // arbitrary + extern int16_t rightx; extern int16_t righty; @@ -27,6 +33,51 @@ extern u8 newcam_mouse; static bool init_ok; static SDL_GameController *sdl_cntrl; + +static u32 num_joy_binds = 0; +static u32 num_mouse_binds = 0; +static u32 joy_binds[MAX_JOYBINDS][2]; +static u32 mouse_binds[MAX_JOYBINDS][2]; + +static bool joy_buttons[SDL_CONTROLLER_BUTTON_MAX ] = { false }; +static u32 mouse_buttons = 0; +static u32 last_mouse = VK_INVALID; +static u32 last_joybutton = VK_INVALID; + +static inline void controller_add_binds(const u32 mask, const u32 *btns) { + for (u32 i = 0; i < MAX_BINDS; ++i) { + if (btns[i] >= VK_BASE_SDL_GAMEPAD && btns[i] <= VK_BASE_SDL_GAMEPAD + VK_SIZE) { + if (btns[i] >= VK_BASE_SDL_MOUSE && num_joy_binds < MAX_JOYBINDS) { + mouse_binds[num_mouse_binds][0] = btns[i] - VK_BASE_SDL_MOUSE; + mouse_binds[num_mouse_binds][1] = mask; + ++num_mouse_binds; + } else if (num_mouse_binds < MAX_JOYBINDS) { + joy_binds[num_joy_binds][0] = btns[i] - VK_BASE_SDL_GAMEPAD; + joy_binds[num_joy_binds][1] = mask; + ++num_joy_binds; + } + } + } +} + +static void controller_sdl_bind(void) { + bzero(joy_binds, sizeof(joy_binds)); + bzero(mouse_binds, sizeof(mouse_binds)); + num_joy_binds = 0; + num_mouse_binds = 0; + + controller_add_binds(A_BUTTON, configKeyA); + controller_add_binds(B_BUTTON, configKeyB); + controller_add_binds(Z_TRIG, configKeyZ); + controller_add_binds(U_CBUTTONS, configKeyCUp); + controller_add_binds(L_CBUTTONS, configKeyCLeft); + controller_add_binds(D_CBUTTONS, configKeyCDown); + controller_add_binds(R_CBUTTONS, configKeyCRight); + controller_add_binds(L_TRIG, configKeyL); + controller_add_binds(R_TRIG, configKeyR); + controller_add_binds(START_BUTTON, configKeyStart); +} + static void controller_sdl_init(void) { if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) { fprintf(stderr, "SDL init error: %s\n", SDL_GetError()); @@ -39,6 +90,8 @@ static void controller_sdl_init(void) { SDL_GetRelativeMouseState(&mouse_x, &mouse_y); #endif + controller_sdl_bind(); + init_ok = true; } @@ -53,13 +106,16 @@ static void controller_sdl_read(OSContPad *pad) { else SDL_SetRelativeMouseMode(SDL_FALSE); - const u32 mbuttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + u32 mouse = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + + for (u32 i = 0; i < num_mouse_binds; ++i) + if (mouse & SDL_BUTTON(mouse_binds[i][0])) + pad->button |= mouse_binds[i][1]; + + // remember buttons that changed from 0 to 1 + last_mouse = (mouse_buttons ^ mouse) & mouse; + mouse_buttons = mouse; - if (configMouseA && (mbuttons & SDL_BUTTON(configMouseA))) pad->button |= A_BUTTON; - if (configMouseB && (mbuttons & SDL_BUTTON(configMouseB))) pad->button |= B_BUTTON; - if (configMouseL && (mbuttons & SDL_BUTTON(configMouseL))) pad->button |= L_TRIG; - if (configMouseR && (mbuttons & SDL_BUTTON(configMouseR))) pad->button |= R_TRIG; - if (configMouseZ && (mbuttons & SDL_BUTTON(configMouseZ))) pad->button |= Z_TRIG; #endif SDL_GameControllerUpdate(); @@ -82,12 +138,16 @@ static void controller_sdl_read(OSContPad *pad) { } } - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyStart)) pad->button |= START_BUTTON; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyZ)) pad->button |= Z_TRIG; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyL)) pad->button |= L_TRIG; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyR)) pad->button |= R_TRIG; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyA)) pad->button |= A_BUTTON; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyB)) pad->button |= B_BUTTON; + for (u32 i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { + const bool new = SDL_GameControllerGetButton(sdl_cntrl, i); + const bool pressed = !joy_buttons[i] && new; + joy_buttons[i] = new; + if (pressed) last_joybutton = i; + } + + for (u32 i = 0; i < num_joy_binds; ++i) + if (joy_buttons[joy_binds[i][0]]) + pad->button |= joy_binds[i][1]; int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); @@ -127,7 +187,27 @@ static void controller_sdl_read(OSContPad *pad) { } } +static u32 controller_sdl_rawkey(void) { + if (last_joybutton != VK_INVALID) { + const u32 ret = last_joybutton; + last_joybutton = VK_INVALID; + return ret; + } + + for (int i = 0; i < MAX_MOUSEBUTTONS; ++i) { + if (last_mouse & SDL_BUTTON(i)) { + const u32 ret = VK_OFS_SDL_MOUSE + i; + last_mouse = 0; + return ret; + } + } + return VK_INVALID; +} + struct ControllerAPI controller_sdl = { + VK_BASE_SDL_GAMEPAD, controller_sdl_init, - controller_sdl_read + controller_sdl_read, + controller_sdl_rawkey, + controller_sdl_bind, }; diff --git a/src/pc/controller/controller_sdl.h b/src/pc/controller/controller_sdl.h index 02aec8d9..bbe8a62c 100644 --- a/src/pc/controller/controller_sdl.h +++ b/src/pc/controller/controller_sdl.h @@ -3,6 +3,8 @@ #include "controller_api.h" +#define VK_BASE_SDL_GAMEPAD 0x1000 + extern struct ControllerAPI controller_sdl; #endif From e96bbef6504f5438e59ddb85fa04fd062417f6e9 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Fri, 15 May 2020 16:47:04 -0300 Subject: [PATCH 38/73] Fix configfile skip_intro option --- src/game/level_update.c | 4 ++-- src/pc/configfile.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/game/level_update.c b/src/game/level_update.c index cdff8853..13246ad5 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -179,7 +179,7 @@ u8 unused3[4]; u8 unused4[2]; // For configfile intro skipping -//extern unsigned int configSkipIntro; +extern unsigned int configSkipIntro; void basic_update(s16 *arg); @@ -1217,7 +1217,7 @@ s32 init_level(void) { if (gMarioState->action != ACT_UNINITIALIZED) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else if (gCLIOpts.SkipIntro == 0) { + } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) { set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); val4 = 1; } diff --git a/src/pc/configfile.c b/src/pc/configfile.c index cee4dfdb..e4a88691 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -60,6 +60,7 @@ bool configCameraInvertY = false; bool configEnableCamera = false; bool configCameraMouse = false; #endif +unsigned int configSkipIntro = 0; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen}, @@ -87,7 +88,7 @@ static const struct ConfigOption options[] = { {.name = "bettercam_aggression", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraAggr}, {.name = "bettercam_pan_level", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraPan}, #endif - //{.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, // Add this back! + {.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, // Add this back! }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string From 2b098781b81b336ec25d6c1e0461035ceffe0e10 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Fri, 15 May 2020 17:09:02 -0300 Subject: [PATCH 39/73] skip_intro now skips Lakitu and Bowser intros --- src/game/level_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/level_update.c b/src/game/level_update.c index 13246ad5..3fa795f9 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1287,7 +1287,7 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) { #endif sWarpDest.type = WARP_TYPE_NOT_WARPING; sDelayedWarpOp = WARP_OP_NONE; - gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1); + gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1) && gCLIOpts.SkipIntro == 0 && configSkipIntro == 0; gCurrLevelNum = levelNum; gCurrCourseNum = COURSE_NONE; From 59a33aa60440c6cf521a0427f21319d2181d38c2 Mon Sep 17 00:00:00 2001 From: uncletrunks <51267277+uncletrunks@users.noreply.github.com> Date: Fri, 15 May 2020 19:26:44 -0500 Subject: [PATCH 40/73] Rebind camera centering to left trigger. --- src/game/bettercamera.inc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index a4ffa7fe..3ef627a8 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -378,8 +378,8 @@ static void newcam_zoom_button(void) newcam_distance = newcam_distance_target; } - //When you press L and R together, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time. - if (gPlayer1Controller->buttonDown & L_TRIG && gPlayer1Controller->buttonDown & R_TRIG && newcam_modeflags & NC_FLAG_ZOOM) + //When you press L, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time. + if (gPlayer1Controller->buttonDown & L_TRIG && newcam_modeflags & NC_FLAG_ZOOM) { newcam_yaw_target = -gMarioState->faceAngle[1]-0x4000; newcam_centering = 1; From 45dc30e741b23adddd3af9ae4b4355bee80db9c7 Mon Sep 17 00:00:00 2001 From: Armando Arredondo Soto <32519217+arredondos@users.noreply.github.com> Date: Sat, 16 May 2020 03:00:33 +0200 Subject: [PATCH 41/73] add two scripts to extract and embed 3d models c2obj.py extracts the 3d models from the hard-coded C code found in the `model.in.c` files and generates a standard .obj file obj2c.py converts back the geometry in an .obj file to compatible C code --- c2obj.py | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ obj2c.py | 107 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 c2obj.py create mode 100644 obj2c.py diff --git a/c2obj.py b/c2obj.py new file mode 100644 index 00000000..ca4faaa9 --- /dev/null +++ b/c2obj.py @@ -0,0 +1,141 @@ +""" +This module attempts to parse the ``model.inc.c`` files and extract the +3D models within as standard Wavefront OBJ files. + +Example: + Specify the path to the ``.inc.c`` file and a directory where to save + the extracted ``.obj`` files. + + $ python c2obj.py ./actors/mario/model.inc.c ./actors/mario/obj/ + +This is a work in progress and it currently has some serious limitations: + * It only extracts geometry information, so no textures or any other info + * It makes assumptions about the layout of the code in the C source + * It hasn't been properly tested. + +""" + +def parse(filename, output_directory): + from os import path, mkdir + + if not path.isdir(output_directory): + try: + mkdir(output_directory) + except OSError: + print(f'Could not use output directory {output_directory}.') + + vtx_def = 'static const Vtx ' + vtx_data = {} + reading_vtx = False + current_vtx_name = '' + current_vtx_data = [] + current_vtx_vertices = 0 + + gfx_def = 'const Gfx ' + reading_gfx = False + current_gfx_vertices = 0 + current_gfx_faces = 0 + insert_vert_call = 'gsSPVertex(' + insert_1tri_call = 'gsSP1Triangle(' + insert_2tri_call = 'gsSP2Triangles(' + gfx_count = 0 + + end_of_block = '};' + + with open(filename, 'r') as f: + for line in f: + line = line.strip() + + if line.startswith(vtx_def): + vtx_name = line.split(' ')[3][:-2] + current_vtx_name = vtx_name + current_vtx_data = [] + reading_vtx = True + continue + + if line.startswith(gfx_def): + from datetime import datetime + + current_gfx_name = line.split(' ')[2][:-2] + current_gfx_file = open(path.join(output_directory, current_gfx_name + '.obj'), 'w') + current_gfx_file.write("# Armando Arredondo's SM64 Wavefront OBJ Geometry Converter\n") + current_gfx_file.write('# File Created: {}\n\n'.format(datetime.now())) + reading_gfx = True + continue + + if line == end_of_block: + if reading_vtx: + vtx_data[current_vtx_name] = current_vtx_data + reading_vtx = False + + elif reading_gfx: + current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') + current_gfx_file.close() + current_gfx_vertices = 0 + reading_gfx = False + gfx_count += 1 + + continue + + if reading_vtx: + line = line.replace('{', '[').replace('}', ']') + tri = eval(line[:-1])[0] + current_vtx_data.append(tri) + continue + + if reading_gfx: + if line.startswith(insert_vert_call): + args = line[len(insert_vert_call):].split(',') + current_vtx_name = args[0] + + if current_gfx_vertices > 0: + current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') + + current_gfx_faces = 0 + current_vtx_vertices = len(vtx_data[current_vtx_name]) + current_gfx_vertices += current_vtx_vertices + + current_gfx_file.write(f'#\n# object {current_vtx_name}\n#\n\n') + current_vtx_data = vtx_data[current_vtx_name] + for tri in current_vtx_data: + v = tri[0] + current_gfx_file.write('v {:.3f} {:.3f} {:.3f}\n'.format(*v)) + current_gfx_file.write(f'# {current_vtx_vertices} vertices\n\n') + + for tri in current_vtx_data: + n = [_decode_normal(u) for u in tri[3][:3]] + current_gfx_file.write('vn {:.3f} {:.3f} {:.3f}\n'.format(*n)) + current_gfx_file.write(f'# {current_vtx_vertices} vertex normals\n\n') + + current_gfx_file.write(f'g {current_vtx_name}\n\n') + + elif line.startswith(insert_2tri_call): + args = line[len(insert_2tri_call):].split(',') + correction = current_gfx_vertices - current_vtx_vertices + 1 + indexes = [eval(args[i]) + correction for i in [0, 1, 2, 4, 5, 6]] + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[:3])) + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[3:])) + current_gfx_faces += 2 + + elif line.startswith(insert_1tri_call): + args = line[len(insert_1tri_call):].split(',') + correction = current_gfx_vertices - current_vtx_vertices + 1 + indexes = [eval(args[i]) + correction for i in [0, 1, 2]] + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes)) + current_gfx_faces += 1 + + continue + + print(f'{gfx_count} models extracted.') + +def _decode_normal(x): + y = x if x <= 127 else x - 255 + return y / 127 + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('filename', help = 'filename of the .inc.c source file') + parser.add_argument('output_directory', help = 'directory where to put the extracted .obj files') + args = parser.parse_args() + parse(args.filename, args.output_directory) \ No newline at end of file diff --git a/obj2c.py b/obj2c.py new file mode 100644 index 00000000..8e84c806 --- /dev/null +++ b/obj2c.py @@ -0,0 +1,107 @@ +""" +This module generates a fragment of C code, in the style of that found in +the ``model.inc.c`` files, that encodes the geometry of the model specified +by the Wavefront OBJ file. + +Example: + Specify the path to the ``.obj`` file and pipe the output of the script + into the desired destination ``.c`` file. + + $ python obj2c.py left_hand_closed.obj > left_hand_closed.inc.c + +This is a work in progress and it currently has some serious limitations: + * It only encodes the geometry information of the OBJ file, so no + texture mapping or any other info. + * The generated fragment of C code has to be manually pasted into the + desired source file. Make sure that the name of the Gfx structure + you're pasting matches the one you're replacing. + * It hasn't been properly tested. + +""" + +def parse(filename): + from os.path import basename, splitext + from re import sub + + # WARNIGN! + # `gfx_name` is just a guess. You have to manually check that the name + # of the Gfx structure you're pasting matches the one you're replacing. + clean = lambda fn: sub('\W|^(?=\d)','_', fn) + gfx_name = clean(splitext(basename(filename))[0]) + gfx_vertices = [] + gfx_normals = [] + vertex_to_normal = {} + gfx_v_count = 0 + + vtx_name = '' + vtx_faces = [] + vtx_v_count = 0 + + output_upper = [] + output_lower = [f'const Gfx {gfx_name}[] = {{'] + + with open(filename, 'r') as obj: + for line in obj: + line = line.strip() + + if line.startswith('v '): + coordinates = [eval(x) for x in line.split()[1:4]] + gfx_vertices.append(coordinates) + vtx_v_count += 1 + gfx_v_count += 1 + + if line.startswith('vn '): + coordinates = [eval(x) for x in line.split()[1:4]] + gfx_normals.append([_encode_normal(x) for x in coordinates]) + + if line.startswith('g '): + vtx_name = line.split()[1] + + if line.startswith('f '): + pairs = [pair.split('//') for pair in line.split()[1:4]] + vtx_faces.append([int(pair[0]) for pair in pairs]) + for (x, y) in pairs: + vertex_to_normal[int(x) - 1] = int(y) - 1 + + if line.startswith('# ') and line.endswith('faces'): + output_upper.append(f'static const Vtx {vtx_name}[] = {{') + for i in range(gfx_v_count - vtx_v_count, gfx_v_count): + v_string = '[{}, {}, {}]'.format(*gfx_vertices[i]) + n_string = '[{}, {}, {}, 0x00]'.format(*gfx_normals[vertex_to_normal[i]]) + combined = f' [[{v_string}, 0, [0, 0], {n_string}]],' + output_upper.append(combined.replace('[', '{').replace(']', '}')) + + output_upper.append('};\n') + output_lower.append(f' gsSPVertex({vtx_name}, {vtx_v_count}, 0),') + + n = len(vtx_faces) + correction = vtx_v_count - gfx_v_count - 1 + for i in range(int(n / 2)): + f1 = [vtx_faces[2 * i][j] + correction for j in range(3)] + f2 = [vtx_faces[2 * i + 1][j] + correction for j in range(3)] + output_lower.append(' gsSP2Triangles({}, {}, {}, 0x0, {}, {}, {}, 0x0),'.format(*f1, *f2)) + + if n % 2 != 0: + f3 = [vtx_faces[-1][j] + correction for j in range(3)] + output_lower.append(' gsSP1Triangle({}, {}, {}, 0x0),'.format(*f3)) + + vtx_v_count = 0 + vtx_faces = [] + + output_lower.append(' gsSPEndDisplayList(),') + output_lower.append('};') + + for line in output_upper + output_lower: + print(line) + +def _encode_normal(x): + x *= 127 + if x <= 0: x += 255 + return hex(int(x)) + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('filename', help = 'filename of the .obj file to parse') + args = parser.parse_args() + parse(args.filename) \ No newline at end of file From 8b71a1a734edcbf3d70b4cc73973474e572d075b Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 07:36:28 +0300 Subject: [PATCH 42/73] correct line endings --- c2obj.py | 280 +++++++++++++++++++++++++++---------------------------- obj2c.py | 212 ++++++++++++++++++++--------------------- 2 files changed, 246 insertions(+), 246 deletions(-) diff --git a/c2obj.py b/c2obj.py index ca4faaa9..508a51ec 100644 --- a/c2obj.py +++ b/c2obj.py @@ -1,141 +1,141 @@ -""" -This module attempts to parse the ``model.inc.c`` files and extract the -3D models within as standard Wavefront OBJ files. - -Example: - Specify the path to the ``.inc.c`` file and a directory where to save - the extracted ``.obj`` files. - - $ python c2obj.py ./actors/mario/model.inc.c ./actors/mario/obj/ - -This is a work in progress and it currently has some serious limitations: - * It only extracts geometry information, so no textures or any other info - * It makes assumptions about the layout of the code in the C source - * It hasn't been properly tested. - -""" - -def parse(filename, output_directory): - from os import path, mkdir - - if not path.isdir(output_directory): - try: - mkdir(output_directory) - except OSError: - print(f'Could not use output directory {output_directory}.') - - vtx_def = 'static const Vtx ' - vtx_data = {} - reading_vtx = False - current_vtx_name = '' - current_vtx_data = [] - current_vtx_vertices = 0 - - gfx_def = 'const Gfx ' - reading_gfx = False - current_gfx_vertices = 0 - current_gfx_faces = 0 - insert_vert_call = 'gsSPVertex(' - insert_1tri_call = 'gsSP1Triangle(' - insert_2tri_call = 'gsSP2Triangles(' - gfx_count = 0 - - end_of_block = '};' - - with open(filename, 'r') as f: - for line in f: - line = line.strip() - - if line.startswith(vtx_def): - vtx_name = line.split(' ')[3][:-2] - current_vtx_name = vtx_name - current_vtx_data = [] - reading_vtx = True - continue - - if line.startswith(gfx_def): - from datetime import datetime - - current_gfx_name = line.split(' ')[2][:-2] - current_gfx_file = open(path.join(output_directory, current_gfx_name + '.obj'), 'w') - current_gfx_file.write("# Armando Arredondo's SM64 Wavefront OBJ Geometry Converter\n") - current_gfx_file.write('# File Created: {}\n\n'.format(datetime.now())) - reading_gfx = True - continue - - if line == end_of_block: - if reading_vtx: - vtx_data[current_vtx_name] = current_vtx_data - reading_vtx = False - - elif reading_gfx: - current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') - current_gfx_file.close() - current_gfx_vertices = 0 - reading_gfx = False - gfx_count += 1 - - continue - - if reading_vtx: - line = line.replace('{', '[').replace('}', ']') - tri = eval(line[:-1])[0] - current_vtx_data.append(tri) - continue - - if reading_gfx: - if line.startswith(insert_vert_call): - args = line[len(insert_vert_call):].split(',') - current_vtx_name = args[0] - - if current_gfx_vertices > 0: - current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') - - current_gfx_faces = 0 - current_vtx_vertices = len(vtx_data[current_vtx_name]) - current_gfx_vertices += current_vtx_vertices - - current_gfx_file.write(f'#\n# object {current_vtx_name}\n#\n\n') - current_vtx_data = vtx_data[current_vtx_name] - for tri in current_vtx_data: - v = tri[0] - current_gfx_file.write('v {:.3f} {:.3f} {:.3f}\n'.format(*v)) - current_gfx_file.write(f'# {current_vtx_vertices} vertices\n\n') - - for tri in current_vtx_data: - n = [_decode_normal(u) for u in tri[3][:3]] - current_gfx_file.write('vn {:.3f} {:.3f} {:.3f}\n'.format(*n)) - current_gfx_file.write(f'# {current_vtx_vertices} vertex normals\n\n') - - current_gfx_file.write(f'g {current_vtx_name}\n\n') - - elif line.startswith(insert_2tri_call): - args = line[len(insert_2tri_call):].split(',') - correction = current_gfx_vertices - current_vtx_vertices + 1 - indexes = [eval(args[i]) + correction for i in [0, 1, 2, 4, 5, 6]] - current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[:3])) - current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[3:])) - current_gfx_faces += 2 - - elif line.startswith(insert_1tri_call): - args = line[len(insert_1tri_call):].split(',') - correction = current_gfx_vertices - current_vtx_vertices + 1 - indexes = [eval(args[i]) + correction for i in [0, 1, 2]] - current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes)) - current_gfx_faces += 1 - - continue - - print(f'{gfx_count} models extracted.') - -def _decode_normal(x): - y = x if x <= 127 else x - 255 - return y / 127 - -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('filename', help = 'filename of the .inc.c source file') - parser.add_argument('output_directory', help = 'directory where to put the extracted .obj files') - args = parser.parse_args() +""" +This module attempts to parse the ``model.inc.c`` files and extract the +3D models within as standard Wavefront OBJ files. + +Example: + Specify the path to the ``.inc.c`` file and a directory where to save + the extracted ``.obj`` files. + + $ python c2obj.py ./actors/mario/model.inc.c ./actors/mario/obj/ + +This is a work in progress and it currently has some serious limitations: + * It only extracts geometry information, so no textures or any other info + * It makes assumptions about the layout of the code in the C source + * It hasn't been properly tested. + +""" + +def parse(filename, output_directory): + from os import path, mkdir + + if not path.isdir(output_directory): + try: + mkdir(output_directory) + except OSError: + print(f'Could not use output directory {output_directory}.') + + vtx_def = 'static const Vtx ' + vtx_data = {} + reading_vtx = False + current_vtx_name = '' + current_vtx_data = [] + current_vtx_vertices = 0 + + gfx_def = 'const Gfx ' + reading_gfx = False + current_gfx_vertices = 0 + current_gfx_faces = 0 + insert_vert_call = 'gsSPVertex(' + insert_1tri_call = 'gsSP1Triangle(' + insert_2tri_call = 'gsSP2Triangles(' + gfx_count = 0 + + end_of_block = '};' + + with open(filename, 'r') as f: + for line in f: + line = line.strip() + + if line.startswith(vtx_def): + vtx_name = line.split(' ')[3][:-2] + current_vtx_name = vtx_name + current_vtx_data = [] + reading_vtx = True + continue + + if line.startswith(gfx_def): + from datetime import datetime + + current_gfx_name = line.split(' ')[2][:-2] + current_gfx_file = open(path.join(output_directory, current_gfx_name + '.obj'), 'w') + current_gfx_file.write("# Armando Arredondo's SM64 Wavefront OBJ Geometry Converter\n") + current_gfx_file.write('# File Created: {}\n\n'.format(datetime.now())) + reading_gfx = True + continue + + if line == end_of_block: + if reading_vtx: + vtx_data[current_vtx_name] = current_vtx_data + reading_vtx = False + + elif reading_gfx: + current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') + current_gfx_file.close() + current_gfx_vertices = 0 + reading_gfx = False + gfx_count += 1 + + continue + + if reading_vtx: + line = line.replace('{', '[').replace('}', ']') + tri = eval(line[:-1])[0] + current_vtx_data.append(tri) + continue + + if reading_gfx: + if line.startswith(insert_vert_call): + args = line[len(insert_vert_call):].split(',') + current_vtx_name = args[0] + + if current_gfx_vertices > 0: + current_gfx_file.write(f'# {current_gfx_faces} faces\n\n') + + current_gfx_faces = 0 + current_vtx_vertices = len(vtx_data[current_vtx_name]) + current_gfx_vertices += current_vtx_vertices + + current_gfx_file.write(f'#\n# object {current_vtx_name}\n#\n\n') + current_vtx_data = vtx_data[current_vtx_name] + for tri in current_vtx_data: + v = tri[0] + current_gfx_file.write('v {:.3f} {:.3f} {:.3f}\n'.format(*v)) + current_gfx_file.write(f'# {current_vtx_vertices} vertices\n\n') + + for tri in current_vtx_data: + n = [_decode_normal(u) for u in tri[3][:3]] + current_gfx_file.write('vn {:.3f} {:.3f} {:.3f}\n'.format(*n)) + current_gfx_file.write(f'# {current_vtx_vertices} vertex normals\n\n') + + current_gfx_file.write(f'g {current_vtx_name}\n\n') + + elif line.startswith(insert_2tri_call): + args = line[len(insert_2tri_call):].split(',') + correction = current_gfx_vertices - current_vtx_vertices + 1 + indexes = [eval(args[i]) + correction for i in [0, 1, 2, 4, 5, 6]] + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[:3])) + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[3:])) + current_gfx_faces += 2 + + elif line.startswith(insert_1tri_call): + args = line[len(insert_1tri_call):].split(',') + correction = current_gfx_vertices - current_vtx_vertices + 1 + indexes = [eval(args[i]) + correction for i in [0, 1, 2]] + current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes)) + current_gfx_faces += 1 + + continue + + print(f'{gfx_count} models extracted.') + +def _decode_normal(x): + y = x if x <= 127 else x - 255 + return y / 127 + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('filename', help = 'filename of the .inc.c source file') + parser.add_argument('output_directory', help = 'directory where to put the extracted .obj files') + args = parser.parse_args() parse(args.filename, args.output_directory) \ No newline at end of file diff --git a/obj2c.py b/obj2c.py index 8e84c806..015aa628 100644 --- a/obj2c.py +++ b/obj2c.py @@ -1,107 +1,107 @@ -""" -This module generates a fragment of C code, in the style of that found in -the ``model.inc.c`` files, that encodes the geometry of the model specified -by the Wavefront OBJ file. - -Example: - Specify the path to the ``.obj`` file and pipe the output of the script - into the desired destination ``.c`` file. - - $ python obj2c.py left_hand_closed.obj > left_hand_closed.inc.c - -This is a work in progress and it currently has some serious limitations: - * It only encodes the geometry information of the OBJ file, so no - texture mapping or any other info. - * The generated fragment of C code has to be manually pasted into the - desired source file. Make sure that the name of the Gfx structure - you're pasting matches the one you're replacing. - * It hasn't been properly tested. - -""" - -def parse(filename): - from os.path import basename, splitext - from re import sub - - # WARNIGN! - # `gfx_name` is just a guess. You have to manually check that the name - # of the Gfx structure you're pasting matches the one you're replacing. - clean = lambda fn: sub('\W|^(?=\d)','_', fn) - gfx_name = clean(splitext(basename(filename))[0]) - gfx_vertices = [] - gfx_normals = [] - vertex_to_normal = {} - gfx_v_count = 0 - - vtx_name = '' - vtx_faces = [] - vtx_v_count = 0 - - output_upper = [] - output_lower = [f'const Gfx {gfx_name}[] = {{'] - - with open(filename, 'r') as obj: - for line in obj: - line = line.strip() - - if line.startswith('v '): - coordinates = [eval(x) for x in line.split()[1:4]] - gfx_vertices.append(coordinates) - vtx_v_count += 1 - gfx_v_count += 1 - - if line.startswith('vn '): - coordinates = [eval(x) for x in line.split()[1:4]] - gfx_normals.append([_encode_normal(x) for x in coordinates]) - - if line.startswith('g '): - vtx_name = line.split()[1] - - if line.startswith('f '): - pairs = [pair.split('//') for pair in line.split()[1:4]] - vtx_faces.append([int(pair[0]) for pair in pairs]) - for (x, y) in pairs: - vertex_to_normal[int(x) - 1] = int(y) - 1 - - if line.startswith('# ') and line.endswith('faces'): - output_upper.append(f'static const Vtx {vtx_name}[] = {{') - for i in range(gfx_v_count - vtx_v_count, gfx_v_count): - v_string = '[{}, {}, {}]'.format(*gfx_vertices[i]) - n_string = '[{}, {}, {}, 0x00]'.format(*gfx_normals[vertex_to_normal[i]]) - combined = f' [[{v_string}, 0, [0, 0], {n_string}]],' - output_upper.append(combined.replace('[', '{').replace(']', '}')) - - output_upper.append('};\n') - output_lower.append(f' gsSPVertex({vtx_name}, {vtx_v_count}, 0),') - - n = len(vtx_faces) - correction = vtx_v_count - gfx_v_count - 1 - for i in range(int(n / 2)): - f1 = [vtx_faces[2 * i][j] + correction for j in range(3)] - f2 = [vtx_faces[2 * i + 1][j] + correction for j in range(3)] - output_lower.append(' gsSP2Triangles({}, {}, {}, 0x0, {}, {}, {}, 0x0),'.format(*f1, *f2)) - - if n % 2 != 0: - f3 = [vtx_faces[-1][j] + correction for j in range(3)] - output_lower.append(' gsSP1Triangle({}, {}, {}, 0x0),'.format(*f3)) - - vtx_v_count = 0 - vtx_faces = [] - - output_lower.append(' gsSPEndDisplayList(),') - output_lower.append('};') - - for line in output_upper + output_lower: - print(line) - -def _encode_normal(x): - x *= 127 - if x <= 0: x += 255 - return hex(int(x)) - -if __name__ == "__main__": - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('filename', help = 'filename of the .obj file to parse') - args = parser.parse_args() +""" +This module generates a fragment of C code, in the style of that found in +the ``model.inc.c`` files, that encodes the geometry of the model specified +by the Wavefront OBJ file. + +Example: + Specify the path to the ``.obj`` file and pipe the output of the script + into the desired destination ``.c`` file. + + $ python obj2c.py left_hand_closed.obj > left_hand_closed.inc.c + +This is a work in progress and it currently has some serious limitations: + * It only encodes the geometry information of the OBJ file, so no + texture mapping or any other info. + * The generated fragment of C code has to be manually pasted into the + desired source file. Make sure that the name of the Gfx structure + you're pasting matches the one you're replacing. + * It hasn't been properly tested. + +""" + +def parse(filename): + from os.path import basename, splitext + from re import sub + + # WARNIGN! + # `gfx_name` is just a guess. You have to manually check that the name + # of the Gfx structure you're pasting matches the one you're replacing. + clean = lambda fn: sub('\W|^(?=\d)','_', fn) + gfx_name = clean(splitext(basename(filename))[0]) + gfx_vertices = [] + gfx_normals = [] + vertex_to_normal = {} + gfx_v_count = 0 + + vtx_name = '' + vtx_faces = [] + vtx_v_count = 0 + + output_upper = [] + output_lower = [f'const Gfx {gfx_name}[] = {{'] + + with open(filename, 'r') as obj: + for line in obj: + line = line.strip() + + if line.startswith('v '): + coordinates = [eval(x) for x in line.split()[1:4]] + gfx_vertices.append(coordinates) + vtx_v_count += 1 + gfx_v_count += 1 + + if line.startswith('vn '): + coordinates = [eval(x) for x in line.split()[1:4]] + gfx_normals.append([_encode_normal(x) for x in coordinates]) + + if line.startswith('g '): + vtx_name = line.split()[1] + + if line.startswith('f '): + pairs = [pair.split('//') for pair in line.split()[1:4]] + vtx_faces.append([int(pair[0]) for pair in pairs]) + for (x, y) in pairs: + vertex_to_normal[int(x) - 1] = int(y) - 1 + + if line.startswith('# ') and line.endswith('faces'): + output_upper.append(f'static const Vtx {vtx_name}[] = {{') + for i in range(gfx_v_count - vtx_v_count, gfx_v_count): + v_string = '[{}, {}, {}]'.format(*gfx_vertices[i]) + n_string = '[{}, {}, {}, 0x00]'.format(*gfx_normals[vertex_to_normal[i]]) + combined = f' [[{v_string}, 0, [0, 0], {n_string}]],' + output_upper.append(combined.replace('[', '{').replace(']', '}')) + + output_upper.append('};\n') + output_lower.append(f' gsSPVertex({vtx_name}, {vtx_v_count}, 0),') + + n = len(vtx_faces) + correction = vtx_v_count - gfx_v_count - 1 + for i in range(int(n / 2)): + f1 = [vtx_faces[2 * i][j] + correction for j in range(3)] + f2 = [vtx_faces[2 * i + 1][j] + correction for j in range(3)] + output_lower.append(' gsSP2Triangles({}, {}, {}, 0x0, {}, {}, {}, 0x0),'.format(*f1, *f2)) + + if n % 2 != 0: + f3 = [vtx_faces[-1][j] + correction for j in range(3)] + output_lower.append(' gsSP1Triangle({}, {}, {}, 0x0),'.format(*f3)) + + vtx_v_count = 0 + vtx_faces = [] + + output_lower.append(' gsSPEndDisplayList(),') + output_lower.append('};') + + for line in output_upper + output_lower: + print(line) + +def _encode_normal(x): + x *= 127 + if x <= 0: x += 255 + return hex(int(x)) + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('filename', help = 'filename of the .obj file to parse') + args = parser.parse_args() parse(args.filename) \ No newline at end of file From ed594815600d5227b8fe126118690f7511aaf3eb Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 08:02:07 +0300 Subject: [PATCH 43/73] add OPT_BUTTON option type; move Exit Game button from pause to options menu --- src/game/ingame_menu.c | 24 ++++++------------------ src/game/options_menu.c | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 55ab55b3..6ecee5b9 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -2391,12 +2391,6 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) { { TEXT_EXIT_COURSE_DE } }; - u8 textExitGame[][22] ={ - { TEXT_EXIT_GAME }, - { TEXT_EXIT_GAME_FR }, - { TEXT_EXIT_GAME_DE } - }; - u8 textCameraAngleR[][24] = { { TEXT_CAMERA_ANGLE_R }, { TEXT_CAMERA_ANGLE_R_FR }, @@ -2404,27 +2398,23 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) { }; #define textContinue textContinue[gInGameLanguage] #define textExitCourse textExitCourse[gInGameLanguage] -#define textExitGame textExitGame[gInGameLanguage] #define textCameraAngleR textCameraAngleR[gInGameLanguage] #else u8 textContinue[] = { TEXT_CONTINUE }; u8 textExitCourse[] = { TEXT_EXIT_COURSE }; - u8 textExitGame[] = { TEXT_EXIT_GAME }; u8 textCameraAngleR[] = { TEXT_CAMERA_ANGLE_R }; #endif - handle_menu_scrolling(MENU_SCROLL_VERTICAL, index, 1, 4); // Index max raised to 4 from 3 + handle_menu_scrolling(MENU_SCROLL_VERTICAL, index, 1, 3); gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); print_generic_string(x + 10, y - 2, textContinue); print_generic_string(x + 10, y - 17, textExitCourse); - print_generic_string(x + 10, y - 33, textExitGame); - - if (index[0] != 4) { - print_generic_string(x + 10, y - 48, textCameraAngleR); + if (index[0] != 3) { + print_generic_string(x + 10, y - 33, textCameraAngleR); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); create_dl_translation_matrix(MENU_MTX_PUSH, x - X_VAL8, (y - ((index[0] - 1) * yIndex)) - Y_VAL8, 0); @@ -2432,10 +2422,8 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) { gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); gSPDisplayList(gDisplayListHead++, dl_draw_triangle); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - } - - if (index[0] == 4) { - render_pause_camera_options(x - 42, y - 57, &gDialogCameraAngleIndex, 110); + } else { + render_pause_camera_options(x - 42, y - 42, &gDialogCameraAngleIndex, 110); } } @@ -2675,7 +2663,7 @@ s16 render_pause_courses_and_castle(void) { gDialogBoxState = DIALOG_STATE_OPENING; gMenuMode = -1; - if (gDialogLineNum == 2 || gDialogLineNum == 3) { + if (gDialogLineNum == 2) { num = gDialogLineNum; } else { num = 1; diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 9e2b7e86..f9426b41 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -18,6 +18,7 @@ #include "pc/controller/controller_api.h" #include +#include u8 optmenu_open = 0; @@ -43,6 +44,7 @@ static const u8 menuStr[][64] = { { TEXT_OPT_OPTIONS }, { TEXT_OPT_CAMERA }, { TEXT_OPT_CONTROLS }, + { TEXT_EXIT_GAME }, }; static const u8 optsCameraStr[][64] = { @@ -82,6 +84,7 @@ enum OptType { OPT_SCROLL, OPT_SUBMENU, OPT_BIND, + OPT_BUTTON, }; struct SubMenu; @@ -104,6 +107,7 @@ struct Option { u32 scrStep; }; struct SubMenu *nextMenu; + void (*actionFn)(struct Option *, s32); }; }; @@ -116,6 +120,12 @@ struct SubMenu { s32 scroll; }; +/* button action functions */ + +static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) { + if (!arg) exit(0); // only exit on A press and not directions +} + /* submenu option lists */ static struct Option optsCamera[] = { @@ -165,6 +175,7 @@ static struct SubMenu menuControls = { static struct Option optsMain[] = { { .type = OPT_SUBMENU, .label = menuStr[4], .nextMenu = &menuCamera, }, { .type = OPT_SUBMENU, .label = menuStr[5], .nextMenu = &menuControls, }, + { .type = OPT_BUTTON, .label = menuStr[6], .actionFn = optmenu_act_exit, }, }; static struct SubMenu menuMain = { @@ -223,7 +234,7 @@ static void optmenu_draw_text(s16 x, s16 y, const u8 *str, u8 col) { static void optmenu_draw_opt(const struct Option *opt, s16 x, s16 y, u8 sel) { u8 buf[32] = { 0 }; - if (opt->type == OPT_SUBMENU) + if (opt->type == OPT_SUBMENU || opt->type == OPT_BUTTON) y -= 6; optmenu_draw_text(x, y, opt->label, sel); @@ -282,6 +293,11 @@ static void optmenu_opt_change(struct Option *opt, s32 val) { currentMenu = opt->nextMenu; break; + case OPT_BUTTON: + if (opt->actionFn) + opt->actionFn(opt, val); + break; + case OPT_BIND: if (val == 0xFF) { // clear the bind From de49bf1ac205c01d7813f692a5d2e7e422b50bb6 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 08:11:24 +0300 Subject: [PATCH 44/73] fix build on all toolchains except mine --- src/game/options_menu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index f9426b41..a92c800e 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -18,7 +18,6 @@ #include "pc/controller/controller_api.h" #include -#include u8 optmenu_open = 0; From aba9a57e148ad550100f0ef827e1b17b0cc92492 Mon Sep 17 00:00:00 2001 From: Heaven Volkoff Date: Sat, 16 May 2020 02:59:29 -0300 Subject: [PATCH 45/73] Fix Whomp and PiranhaPlant not appearing from a distance in WF --- src/game/behaviors/piranha_plant.inc.c | 2 ++ src/game/behaviors/whomp.inc.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/game/behaviors/piranha_plant.inc.c b/src/game/behaviors/piranha_plant.inc.c index e8abe089..7677e3c9 100644 --- a/src/game/behaviors/piranha_plant.inc.c +++ b/src/game/behaviors/piranha_plant.inc.c @@ -329,6 +329,7 @@ void (*TablePiranhaPlantActions[])(void) = { void bhv_piranha_plant_loop(void) { cur_obj_call_action_function(TablePiranhaPlantActions); + #ifndef NODRAWINGDISTANCE // In WF, hide all Piranha Plants once high enough up. if (gCurrLevelNum == LEVEL_WF) { if (gMarioObject->oPosY > 3400.0f) @@ -336,5 +337,6 @@ void bhv_piranha_plant_loop(void) { else cur_obj_unhide(); } + #endif o->oInteractStatus = 0; } diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index c9ebca0a..28f1c4c8 100644 --- a/src/game/behaviors/whomp.inc.c +++ b/src/game/behaviors/whomp.inc.c @@ -246,10 +246,14 @@ void bhv_whomp_loop(void) { cur_obj_call_action_function(sWhompActions); cur_obj_move_standard(-20); if (o->oAction != 9) { + #ifndef NODRAWINGDISTANCE + // o->oBehParams2ndByte here seems to be a flag + // indicating whether this is a normal or king whomp if (o->oBehParams2ndByte != 0) cur_obj_hide_if_mario_far_away_y(2000.0f); else cur_obj_hide_if_mario_far_away_y(1000.0f); + #endif load_object_collision_model(); } } From 1a3034898cda792c65e628da38bcd902003f8d30 Mon Sep 17 00:00:00 2001 From: Heaven Volkoff Date: Sat, 16 May 2020 04:48:11 -0300 Subject: [PATCH 46/73] Consider second color column of Light_t when calculating vertex colors --- src/pc/gfx/gfx_pc.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index d674a4d6..8d03cffa 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -569,10 +569,16 @@ static void gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *verti calculate_normal_dir(&lookat_y, rsp.current_lookat_coeffs[1]); rsp.lights_changed = false; } - - int r = rsp.current_lights[rsp.current_num_lights - 1].col[0]; - int g = rsp.current_lights[rsp.current_num_lights - 1].col[1]; - int b = rsp.current_lights[rsp.current_num_lights - 1].col[2]; + + // Inspired by: + // https://github.com/gonetz/GLideN64/commit/c8cbafff71a81bee5112aaafe6e21d6648ff8125#diff-69d8715ec7f9fd627ec4f5516edd003dL484 + const bool useFirstColor = (dest_index & 1) == 0; + const unsigned char* col = useFirstColor + ? rsp.current_lights[rsp.current_num_lights - 1].col + : rsp.current_lights[rsp.current_num_lights - 1].colc; + int r = col[0]; + int g = col[1]; + int b = col[2]; for (int i = 0; i < rsp.current_num_lights - 1; i++) { float intensity = 0; @@ -581,9 +587,14 @@ static void gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *verti intensity += vn->n[2] * rsp.current_lights_coeffs[i][2]; intensity /= 127.0f; if (intensity > 0.0f) { - r += intensity * rsp.current_lights[i].col[0]; - g += intensity * rsp.current_lights[i].col[1]; - b += intensity * rsp.current_lights[i].col[2]; + // Inspired by: + // https://github.com/gonetz/GLideN64/commit/c8cbafff71a81bee5112aaafe6e21d6648ff8125#diff-69d8715ec7f9fd627ec4f5516edd003dL492 + col = useFirstColor + ? rsp.current_lights[i].col + : rsp.current_lights[i].colc; + r += intensity * col[0]; + g += intensity * col[1]; + b += intensity * col[2]; } } From 6ebd074c5d7cebc23ded22d89c36764b66b08495 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 09:36:06 -0300 Subject: [PATCH 47/73] Set compile-time flag for texture fixes This should allow for quashing the debate surrounding some minor texture fix PRs. --- actors/burn_smoke/model.inc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/actors/burn_smoke/model.inc.c b/actors/burn_smoke/model.inc.c index 3d1adef4..bcf4fd6f 100644 --- a/actors/burn_smoke/model.inc.c +++ b/actors/burn_smoke/model.inc.c @@ -11,6 +11,9 @@ static const Vtx burn_smoke_seg4_vertex_040217C0[] = { // //! Wrong texture format. Called as rgba16, which makes the burn smoke appear // as a transparent black burn smoke. Probably meant to show up as white-ish // burn smoke, but mistakened for being intended as black smoke. +// Due to debate in the Koopa shorts PR surrounding the fix to a similar bug, +// said fix is on a compile-time variable. Use TEXTURE_FIX=1 at compile time +// to fix this. // 0x04021800 ALIGNED8 static const u8 burn_smoke_seg4_texture_04021800[] = { #include "actors/burn_smoke/burn_smoke.ia16.inc.c" @@ -44,7 +47,11 @@ const Gfx burn_smoke_seg4_dl_04022048[] = { // 0x04022070 - 0x040220C8 const Gfx burn_smoke_seg4_dl_04022070[] = { gsSPDisplayList(burn_smoke_seg4_dl_04022000), + #ifdef TEXTURE_FIX gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_IA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), + #else + gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_RGBA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), + #endif gsSPDisplayList(burn_smoke_seg4_dl_04022028), gsSPDisplayList(burn_smoke_seg4_dl_04022048), gsSPEndDisplayList(), From 03b129c5bf4a82041fc8ed370cbef155e5646857 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 09:40:33 -0300 Subject: [PATCH 48/73] Added compile-time optional Koopa shorts fix --- actors/koopa/model.inc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/actors/koopa/model.inc.c b/actors/koopa/model.inc.c index 04a43a8a..6bf24187 100644 --- a/actors/koopa/model.inc.c +++ b/actors/koopa/model.inc.c @@ -54,6 +54,8 @@ static const Lights1 koopa_seg6_lights_06002630 = gdSPDefLights1( // beneath its shell, despite the fact it was intended to be white like // the rest of its body. This is evident because once the mistake is corrected // it turns back to being white like the other polygons. +// Due to debate in the PR surrounding the fix to this, said fix is on +// a compile-time variable. Use TEXTURE_FIX=1 at compile time to fix this. // 0x06002648 ALIGNED8 static const u8 koopa_seg6_texture_06002648[] = { #include "actors/koopa/koopa_shell_front.rgba16.inc.c" @@ -2077,8 +2079,13 @@ const Gfx koopa_seg6_dl_0600C498[] = { gsSPVertex(koopa_seg6_vertex_0600B560, 9, 0), gsSP2Triangles( 0, 1, 2, 0x0, 3, 4, 5, 0x0), gsSP1Triangle( 6, 7, 8, 0x0), + #ifdef TEXTURE_FIX + gsSPLight(&koopa_seg6_lights_06002630.l, 1), + gsSPLight(&koopa_seg6_lights_06002630.a, 2), + #else gsSPLight(koopa_seg6_texture_06002648 + 0x20, 1), // this malformed light results in a gsSPLight(koopa_seg6_texture_06002648 + 0x18, 2), // koopa appearing to wear pink shorts. + #endif gsSPVertex(koopa_seg6_vertex_0600B5F0, 15, 0), gsSP2Triangles( 0, 1, 2, 0x0, 3, 4, 5, 0x0), gsSP2Triangles( 6, 7, 0, 0x0, 8, 5, 9, 0x0), From a83fa35c4df17dfa20d27d9c02e8424eb91c81d8 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 09:41:57 -0300 Subject: [PATCH 49/73] Add compile-time texture fixes to Makefile Add compile-time texture fixes as a Makefile build flag, set when `TEXTURE_FIX=1`. --- Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile b/Makefile index 8a52418f..89452c95 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,8 @@ COMPILER ?= ido BETTERCAMERA ?= 0 # Disable no drawing distance by default NODRAWINGDISTANCE ?= 0 +# Disable texture fixes by default (helps with them purists) +TEXTURE_FIX ?= 0 # Build for Emscripten/WebGL TARGET_WEB ?= 0 @@ -458,6 +460,12 @@ CC_CHECK += -DNODRAWINGDISTANCE CFLAGS += -DNODRAWINGDISTANCE endif +# Check for texture fix option +ifeq ($(TEXTURE_FIX),1) +CC_CHECK += -DTEXTURE_FIX +CFLAGS += -DTEXTURE_FIX +endif + ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) ifeq ($(TARGET_WEB),1) From dbca0c413d8a2a07d48e50c128cccb54cd426504 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 13:56:12 +0300 Subject: [PATCH 50/73] add fullscreen and filtering settings to options filtering only applies to newly loaded textures --- include/text_strings.h.in | 5 +++++ src/game/options_menu.c | 37 +++++++++++++++++++++++++++++++------ src/pc/configfile.c | 4 +++- src/pc/configfile.h | 1 + src/pc/gfx/gfx_opengl.c | 6 ++++-- src/pc/gfx/gfx_sdl2.c | 28 +++++++++++++--------------- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 88fe2f7c..ee4508b7 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -16,9 +16,14 @@ #define TEXT_OPT_OPTIONS _("OPTIONS") #define TEXT_OPT_CAMERA _("CAMERA") #define TEXT_OPT_CONTROLS _("CONTROLS") +#define TEXT_OPT_VIDEO _("DISPLAY") #define TEXT_OPT_HIGHLIGHT _("O") #define TEXT_OPT_ANALOGUE _("Analogue Camera") #define TEXT_OPT_MOUSE _("Mouse Look") +#define TEXT_OPT_TEXFILTER _("Texture Filtering") +#define TEXT_OPT_FSCREEN _("Fullscreen") +#define TEXT_OPT_NEAREST _("Nearest") +#define TEXT_OPT_LINEAR _("Linear") #define TEXT_OPT_UNBOUND _("NONE") #define TEXT_OPT_PRESSKEY _("...") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index a92c800e..093c839e 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -31,22 +31,23 @@ static u8 optmenu_bind_idx = 0; // menus: add a new submenu definition and a new // option to the optsMain list -static const u8 toggleStr[][64] = { +static const u8 toggleStr[][16] = { { TEXT_OPT_DISABLED }, { TEXT_OPT_ENABLED }, }; -static const u8 menuStr[][64] = { +static const u8 menuStr[][32] = { { TEXT_OPT_HIGHLIGHT }, { TEXT_OPT_BUTTON1 }, { TEXT_OPT_BUTTON2 }, { TEXT_OPT_OPTIONS }, { TEXT_OPT_CAMERA }, { TEXT_OPT_CONTROLS }, + { TEXT_OPT_VIDEO }, { TEXT_EXIT_GAME }, }; -static const u8 optsCameraStr[][64] = { +static const u8 optsCameraStr[][32] = { { TEXT_OPT_CAMX }, { TEXT_OPT_CAMY }, { TEXT_OPT_INVERTX }, @@ -57,7 +58,14 @@ static const u8 optsCameraStr[][64] = { { TEXT_OPT_MOUSE }, }; -static const u8 bindStr[][64] = { +static const u8 optsVideoStr[][32] = { + { TEXT_OPT_FSCREEN }, + { TEXT_OPT_TEXFILTER }, + { TEXT_OPT_NEAREST }, + { TEXT_OPT_LINEAR }, +}; + +static const u8 bindStr[][32] = { { TEXT_OPT_UNBOUND }, { TEXT_OPT_PRESSKEY }, { TEXT_BIND_A }, @@ -76,6 +84,11 @@ static const u8 bindStr[][64] = { { TEXT_BIND_RIGHT }, }; +static const u8 *filterChoices[] = { + optsVideoStr[2], + optsVideoStr[3], +}; + enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -155,6 +168,11 @@ static struct Option optsControls[] = { { .type = OPT_BIND, .label = bindStr[15], .uval = configKeyStickRight, }, }; +static struct Option optsVideo[] = { + { .type = OPT_TOGGLE, .label = optsVideoStr[0], .bval = &configFullscreen, }, + { .type = OPT_CHOICE, .label = optsVideoStr[1], .uval = &configFiltering, .choices = filterChoices, .numChoices = 2 }, +}; + /* submenu definitions */ static struct SubMenu menuCamera = { @@ -169,12 +187,19 @@ static struct SubMenu menuControls = { .numOpts = sizeof(optsControls) / sizeof(optsControls[0]), }; +static struct SubMenu menuVideo = { + .label = menuStr[6], + .opts = optsVideo, + .numOpts = sizeof(optsVideo) / sizeof(optsVideo[0]), +}; + /* main options menu definition */ static struct Option optsMain[] = { { .type = OPT_SUBMENU, .label = menuStr[4], .nextMenu = &menuCamera, }, { .type = OPT_SUBMENU, .label = menuStr[5], .nextMenu = &menuControls, }, - { .type = OPT_BUTTON, .label = menuStr[6], .actionFn = optmenu_act_exit, }, + { .type = OPT_SUBMENU, .label = menuStr[6], .nextMenu = &menuVideo, }, + { .type = OPT_BUTTON, .label = menuStr[7], .actionFn = optmenu_act_exit, }, }; static struct SubMenu menuMain = { @@ -311,7 +336,7 @@ static void optmenu_opt_change(struct Option *opt, s32 val) { break; default: break; - }; + } } static inline s16 get_hudstr_centered_x(const s16 sx, const u8 *str) { diff --git a/src/pc/configfile.c b/src/pc/configfile.c index e4a88691..67308815 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -32,7 +32,8 @@ struct ConfigOption { *Config options and default values */ -bool configFullscreen = false; +bool configFullscreen = false; +unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point // Keyboard mappings (VK_ values, by default keyboard/gamepad/mouse) unsigned int configKeyA[MAX_BINDS] = { 0x0026, 0x1000, 0x1103 }; unsigned int configKeyB[MAX_BINDS] = { 0x0033, 0x1002, 0x1101 }; @@ -64,6 +65,7 @@ unsigned int configSkipIntro = 0; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen}, + {.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering}, {.name = "key_a", .type = CONFIG_TYPE_BIND, .uintValue = configKeyA}, {.name = "key_b", .type = CONFIG_TYPE_BIND, .uintValue = configKeyB}, {.name = "key_start", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStart}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index c53d6991..de277fba 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -7,6 +7,7 @@ #define MAX_BINDS 3 extern bool configFullscreen; +extern unsigned int configFiltering; extern unsigned int configKeyA[]; extern unsigned int configKeyB[]; extern unsigned int configKeyStart[]; diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index 65b3099e..b73462e1 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -26,6 +26,7 @@ #include "gfx_cc.h" #include "gfx_rendering_api.h" +#include "../configfile.h" struct ShaderProgram { uint32_t shader_id; @@ -408,9 +409,10 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) { } static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { + const GLenum filter = (linear_filter && (configFiltering == 1)) ? GL_LINEAR : GL_NEAREST; glActiveTexture(GL_TEXTURE0 + tile); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt)); } diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 561ac95b..e7018476 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -26,7 +26,8 @@ static SDL_Window *wnd; static int inverted_scancode_table[512]; -extern bool configFullscreen; +static bool cur_fullscreen; +static uint32_t cur_width, cur_height; const SDL_Scancode windows_scancode_table[] = { @@ -79,20 +80,18 @@ const SDL_Scancode scancode_rmapping_nonextended[][2] = { {SDL_SCANCODE_KP_MULTIPLY, SDL_SCANCODE_PRINTSCREEN} }; -static void gfx_sdl_set_fullscreen(bool fullscreen) -{ - if (fullscreen) - { +static void gfx_sdl_set_fullscreen(bool fullscreen) { + if (fullscreen == cur_fullscreen) return; + + if (fullscreen) { SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_ShowCursor(SDL_DISABLE); - } - else - { + } else { SDL_SetWindowFullscreen(wnd, 0); SDL_ShowCursor(SDL_ENABLE); } - configFullscreen = fullscreen; + cur_fullscreen = fullscreen; } static void gfx_sdl_init(void) { @@ -190,13 +189,9 @@ static void gfx_sdl_onkeydown(int scancode) { const Uint8 *state = SDL_GetKeyboardState(NULL); if (state[SDL_SCANCODE_LALT] && state[SDL_SCANCODE_RETURN]) - { - gfx_sdl_set_fullscreen(!configFullscreen); - } + configFullscreen = !configFullscreen; else if (state[SDL_SCANCODE_ESCAPE] && configFullscreen) - { - gfx_sdl_set_fullscreen(false); - } + configFullscreen = false; } static void gfx_sdl_onkeyup(int scancode) { @@ -220,6 +215,9 @@ static void gfx_sdl_handle_events(void) { exit(0); } } + // just check if the fullscreen value has changed and toggle fullscreen if it has + if (configFullscreen != cur_fullscreen) + gfx_sdl_set_fullscreen(configFullscreen); } static bool gfx_sdl_start_frame(void) { From 92c75fb21b751f8fb0b342d1756668150b94ba0d Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 15:00:35 +0300 Subject: [PATCH 51/73] simplify options menu definitions --- src/game/options_menu.c | 99 ++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 093c839e..4184dbab 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -132,6 +132,23 @@ struct SubMenu { s32 scroll; }; +/* helper macros */ + +#define DEF_OPT_TOGGLE(lbl, bv) \ + { .type = OPT_TOGGLE, .label = lbl, .bval = bv } +#define DEF_OPT_SCROLL(lbl, uv, min, max, st) \ + { .type = OPT_SCROLL, .label = lbl, .uval = uv, .scrMin = min, .scrMax = max, .scrStep = st } +#define DEF_OPT_CHOICE(lbl, uv, ch) \ + { .type = OPT_CHOICE, .label = lbl, .uval = uv, .choices = ch, .numChoices = sizeof(ch) / sizeof(ch[0]) } +#define DEF_OPT_SUBMENU(lbl, nm) \ + { .type = OPT_SUBMENU, .label = lbl, .nextMenu = nm } +#define DEF_OPT_BIND(lbl, uv) \ + { .type = OPT_BIND, .label = lbl, .uval = uv } +#define DEF_OPT_BUTTON(lbl, act) \ + { .type = OPT_BUTTON, .label = lbl, .actionFn = act } +#define DEF_SUBMENU(lbl, opt) \ + { .label = lbl, .opts = opt, .numOpts = sizeof(opt) / sizeof(opt[0]) } + /* button action functions */ static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) { @@ -141,72 +158,54 @@ static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) { /* submenu option lists */ static struct Option optsCamera[] = { - { .type = OPT_TOGGLE, .label = optsCameraStr[6], .bval = &configEnableCamera, }, - { .type = OPT_TOGGLE, .label = optsCameraStr[7], .bval = &configCameraMouse, }, - { .type = OPT_TOGGLE, .label = optsCameraStr[2], .bval = &configCameraInvertX, }, - { .type = OPT_TOGGLE, .label = optsCameraStr[3], .bval = &configCameraInvertY, }, - { .type = OPT_SCROLL, .label = optsCameraStr[0], .uval = &configCameraXSens, .scrMin = 10, .scrMax = 250, .scrStep = 1 }, - { .type = OPT_SCROLL, .label = optsCameraStr[1], .uval = &configCameraYSens, .scrMin = 10, .scrMax = 250, .scrStep = 1 }, - { .type = OPT_SCROLL, .label = optsCameraStr[4], .uval = &configCameraAggr, .scrMin = 0, .scrMax = 100, .scrStep = 1 }, - { .type = OPT_SCROLL, .label = optsCameraStr[5], .uval = &configCameraPan, .scrMin = 0, .scrMax = 100, .scrStep = 1 }, + DEF_OPT_TOGGLE( optsCameraStr[6], &configEnableCamera ), + DEF_OPT_TOGGLE( optsCameraStr[7], &configCameraMouse ), + DEF_OPT_TOGGLE( optsCameraStr[2], &configCameraInvertX ), + DEF_OPT_TOGGLE( optsCameraStr[3], &configCameraInvertY ), + DEF_OPT_SCROLL( optsCameraStr[0], &configCameraXSens, 10, 250, 1 ), + DEF_OPT_SCROLL( optsCameraStr[1], &configCameraYSens, 10, 250, 1 ), + DEF_OPT_SCROLL( optsCameraStr[4], &configCameraAggr, 0, 100, 1 ), + DEF_OPT_SCROLL( optsCameraStr[5], &configCameraPan, 0, 100, 1 ), }; static struct Option optsControls[] = { - { .type = OPT_BIND, .label = bindStr[2], .uval = configKeyA, }, - { .type = OPT_BIND, .label = bindStr[3], .uval = configKeyB, }, - { .type = OPT_BIND, .label = bindStr[4], .uval = configKeyStart, }, - { .type = OPT_BIND, .label = bindStr[5], .uval = configKeyL, }, - { .type = OPT_BIND, .label = bindStr[6], .uval = configKeyR, }, - { .type = OPT_BIND, .label = bindStr[7], .uval = configKeyZ, }, - { .type = OPT_BIND, .label = bindStr[8], .uval = configKeyCUp, }, - { .type = OPT_BIND, .label = bindStr[9], .uval = configKeyCDown, }, - { .type = OPT_BIND, .label = bindStr[10], .uval = configKeyCLeft, }, - { .type = OPT_BIND, .label = bindStr[11], .uval = configKeyCRight, }, - { .type = OPT_BIND, .label = bindStr[12], .uval = configKeyStickUp, }, - { .type = OPT_BIND, .label = bindStr[13], .uval = configKeyStickDown, }, - { .type = OPT_BIND, .label = bindStr[14], .uval = configKeyStickLeft, }, - { .type = OPT_BIND, .label = bindStr[15], .uval = configKeyStickRight, }, + DEF_OPT_BIND( bindStr[ 2], configKeyA ), + DEF_OPT_BIND( bindStr[ 3], configKeyB ), + DEF_OPT_BIND( bindStr[ 4], configKeyStart ), + DEF_OPT_BIND( bindStr[ 5], configKeyL ), + DEF_OPT_BIND( bindStr[ 6], configKeyR ), + DEF_OPT_BIND( bindStr[ 7], configKeyZ ), + DEF_OPT_BIND( bindStr[ 8], configKeyCUp ), + DEF_OPT_BIND( bindStr[ 9], configKeyCDown ), + DEF_OPT_BIND( bindStr[10], configKeyCLeft ), + DEF_OPT_BIND( bindStr[11], configKeyCRight ), + DEF_OPT_BIND( bindStr[12], configKeyStickUp ), + DEF_OPT_BIND( bindStr[13], configKeyStickDown ), + DEF_OPT_BIND( bindStr[14], configKeyStickLeft ), + DEF_OPT_BIND( bindStr[15], configKeyStickRight ), }; static struct Option optsVideo[] = { - { .type = OPT_TOGGLE, .label = optsVideoStr[0], .bval = &configFullscreen, }, - { .type = OPT_CHOICE, .label = optsVideoStr[1], .uval = &configFiltering, .choices = filterChoices, .numChoices = 2 }, + DEF_OPT_TOGGLE( optsVideoStr[0], &configFullscreen ), + DEF_OPT_CHOICE( optsVideoStr[1], &configFiltering, filterChoices ), }; /* submenu definitions */ -static struct SubMenu menuCamera = { - .label = menuStr[4], - .opts = optsCamera, - .numOpts = sizeof(optsCamera) / sizeof(optsCamera[0]), -}; - -static struct SubMenu menuControls = { - .label = menuStr[5], - .opts = optsControls, - .numOpts = sizeof(optsControls) / sizeof(optsControls[0]), -}; - -static struct SubMenu menuVideo = { - .label = menuStr[6], - .opts = optsVideo, - .numOpts = sizeof(optsVideo) / sizeof(optsVideo[0]), -}; +static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); +static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); +static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); /* main options menu definition */ static struct Option optsMain[] = { - { .type = OPT_SUBMENU, .label = menuStr[4], .nextMenu = &menuCamera, }, - { .type = OPT_SUBMENU, .label = menuStr[5], .nextMenu = &menuControls, }, - { .type = OPT_SUBMENU, .label = menuStr[6], .nextMenu = &menuVideo, }, - { .type = OPT_BUTTON, .label = menuStr[7], .actionFn = optmenu_act_exit, }, + DEF_OPT_SUBMENU( menuStr[4], &menuCamera ), + DEF_OPT_SUBMENU( menuStr[5], &menuControls ), + DEF_OPT_SUBMENU( menuStr[6], &menuVideo ), + DEF_OPT_BUTTON ( menuStr[7], optmenu_act_exit ), }; -static struct SubMenu menuMain = { - .label = menuStr[3], - .opts = optsMain, - .numOpts = sizeof(optsMain) / sizeof(optsMain[0]), -}; +static struct SubMenu menuMain = DEF_SUBMENU( menuStr[3], optsMain ); /* implementation */ From a259cd15a1a32393463fa239036c7b3913e8dcd2 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 16:09:27 +0300 Subject: [PATCH 52/73] add dumb master volume control --- include/text_strings.h.in | 2 ++ src/game/options_menu.c | 19 +++++++++++++++---- src/pc/configfile.c | 8 ++++++-- src/pc/configfile.h | 6 +++++- src/pc/pc_main.c | 8 +++++++- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index ee4508b7..a577a161 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -17,6 +17,7 @@ #define TEXT_OPT_CAMERA _("CAMERA") #define TEXT_OPT_CONTROLS _("CONTROLS") #define TEXT_OPT_VIDEO _("DISPLAY") +#define TEXT_OPT_AUDIO _("SOUND") #define TEXT_OPT_HIGHLIGHT _("O") #define TEXT_OPT_ANALOGUE _("Analogue Camera") #define TEXT_OPT_MOUSE _("Mouse Look") @@ -24,6 +25,7 @@ #define TEXT_OPT_FSCREEN _("Fullscreen") #define TEXT_OPT_NEAREST _("Nearest") #define TEXT_OPT_LINEAR _("Linear") +#define TEXT_OPT_MVOLUME _("Master Volume") #define TEXT_OPT_UNBOUND _("NONE") #define TEXT_OPT_PRESSKEY _("...") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 4184dbab..c9feeb39 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -44,6 +44,7 @@ static const u8 menuStr[][32] = { { TEXT_OPT_CAMERA }, { TEXT_OPT_CONTROLS }, { TEXT_OPT_VIDEO }, + { TEXT_OPT_AUDIO }, { TEXT_EXIT_GAME }, }; @@ -65,6 +66,10 @@ static const u8 optsVideoStr[][32] = { { TEXT_OPT_LINEAR }, }; +static const u8 optsAudioStr[][32] = { + { TEXT_OPT_MVOLUME }, +}; + static const u8 bindStr[][32] = { { TEXT_OPT_UNBOUND }, { TEXT_OPT_PRESSKEY }, @@ -190,11 +195,16 @@ static struct Option optsVideo[] = { DEF_OPT_CHOICE( optsVideoStr[1], &configFiltering, filterChoices ), }; +static struct Option optsAudio[] = { + DEF_OPT_SCROLL( optsAudioStr[0], &configMasterVolume, 0, MAX_VOLUME, 1 ), +}; + /* submenu definitions */ -static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); +static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); -static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); +static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); +static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); /* main options menu definition */ @@ -202,7 +212,8 @@ static struct Option optsMain[] = { DEF_OPT_SUBMENU( menuStr[4], &menuCamera ), DEF_OPT_SUBMENU( menuStr[5], &menuControls ), DEF_OPT_SUBMENU( menuStr[6], &menuVideo ), - DEF_OPT_BUTTON ( menuStr[7], optmenu_act_exit ), + DEF_OPT_SUBMENU( menuStr[7], &menuAudio ), + DEF_OPT_BUTTON ( menuStr[8], optmenu_act_exit ), }; static struct SubMenu menuMain = DEF_SUBMENU( menuStr[3], optsMain ); @@ -308,7 +319,7 @@ static void optmenu_opt_change(struct Option *opt, s32 val) { break; case OPT_SCROLL: - *opt->uval = wrap_add(*opt->uval, val, opt->scrMin, opt->scrMax); + *opt->uval = wrap_add(*opt->uval, opt->scrStep * val, opt->scrMin, opt->scrMax); break; case OPT_SUBMENU: diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 67308815..df05b1d5 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -32,8 +32,11 @@ struct ConfigOption { *Config options and default values */ -bool configFullscreen = false; -unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point +// Video/audio stuff +bool configFullscreen = false; +unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point +unsigned int configMasterVolume = MAX_VOLUME; // 0 - MAX_VOLUME + // Keyboard mappings (VK_ values, by default keyboard/gamepad/mouse) unsigned int configKeyA[MAX_BINDS] = { 0x0026, 0x1000, 0x1103 }; unsigned int configKeyB[MAX_BINDS] = { 0x0033, 0x1002, 0x1101 }; @@ -66,6 +69,7 @@ unsigned int configSkipIntro = 0; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen}, {.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering}, + {.name = "master_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMasterVolume}, {.name = "key_a", .type = CONFIG_TYPE_BIND, .uintValue = configKeyA}, {.name = "key_b", .type = CONFIG_TYPE_BIND, .uintValue = configKeyB}, {.name = "key_start", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStart}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index de277fba..39a020e8 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -4,10 +4,14 @@ #include #define CONFIG_FILE "sm64config.txt" -#define MAX_BINDS 3 + +#define MAX_BINDS 3 +#define MAX_VOLUME 127 +#define VOLUME_SHIFT 7 extern bool configFullscreen; extern unsigned int configFiltering; +extern unsigned int configMasterVolume; extern unsigned int configKeyA[]; extern unsigned int configKeyB[]; extern unsigned int configKeyStart[]; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index ca7adf51..52d8339b 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -73,7 +73,13 @@ void produce_one_frame(void) { create_next_audio_buffer(audio_buffer + i * (num_audio_samples * 2), num_audio_samples); } //printf("Audio samples before submitting: %d\n", audio_api->buffered()); - audio_api->play(audio_buffer, 2 * num_audio_samples * 4); + + // scale by master volume (0-127) + const s32 mod = (s32)configMasterVolume; + for (u32 i = 0; i < num_audio_samples * 4; ++i) + audio_buffer[i] = ((s32)audio_buffer[i] * mod) >> VOLUME_SHIFT; + + audio_api->play((u8*)audio_buffer, 2 * num_audio_samples * 4); gfx_end_frame(); } From 9ae444d2b568ca8b27cc55c795ebc32ddb0b64f3 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 16:13:54 +0300 Subject: [PATCH 53/73] move filtering check to gfx_pc.c for those sweet realtime updates --- src/pc/gfx/gfx_opengl.c | 3 +-- src/pc/gfx/gfx_pc.c | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index b73462e1..b7067e91 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -26,7 +26,6 @@ #include "gfx_cc.h" #include "gfx_rendering_api.h" -#include "../configfile.h" struct ShaderProgram { uint32_t shader_id; @@ -409,7 +408,7 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) { } static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { - const GLenum filter = (linear_filter && (configFiltering == 1)) ? GL_LINEAR : GL_NEAREST; + const GLenum filter = linear_filter ? GL_LINEAR : GL_NEAREST; glActiveTexture(GL_TEXTURE0 + tile); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index d674a4d6..7052ad60 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -18,6 +18,8 @@ #include "gfx_rendering_api.h" #include "gfx_screen_config.h" +#include "../configfile.h" + #define SUPPORT_CHECK(x) assert(x) // SCALE_M_N: upscale/downscale M-bit integer to N-bit @@ -763,7 +765,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) { import_texture(i); rdp.textures_changed[i] = false; } - bool linear_filter = (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT; + bool linear_filter = configFiltering && ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT); if (linear_filter != rendering_state.textures[i]->linear_filter || rdp.texture_tile.cms != rendering_state.textures[i]->cms || rdp.texture_tile.cmt != rendering_state.textures[i]->cmt) { gfx_flush(); gfx_rapi->set_sampler_parameters(i, linear_filter, rdp.texture_tile.cms, rdp.texture_tile.cmt); From fd9909269d8c99f452e683d3e9f5c5558a6dcd4d Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 10:19:58 -0300 Subject: [PATCH 54/73] Remove newline in nodrawdistance define --- src/game/behaviors/piranha_plant.inc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/behaviors/piranha_plant.inc.c b/src/game/behaviors/piranha_plant.inc.c index 7677e3c9..328f4518 100644 --- a/src/game/behaviors/piranha_plant.inc.c +++ b/src/game/behaviors/piranha_plant.inc.c @@ -328,7 +328,6 @@ void (*TablePiranhaPlantActions[])(void) = { */ void bhv_piranha_plant_loop(void) { cur_obj_call_action_function(TablePiranhaPlantActions); - #ifndef NODRAWINGDISTANCE // In WF, hide all Piranha Plants once high enough up. if (gCurrLevelNum == LEVEL_WF) { From 6736bd7e9ceeb260d4530c2c962160574a076821 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 10:23:32 -0300 Subject: [PATCH 55/73] Fix SL walking penguin for nodrawdistance --- src/game/behaviors/sl_walking_penguin.inc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/behaviors/sl_walking_penguin.inc.c b/src/game/behaviors/sl_walking_penguin.inc.c index f5b60a8a..59428acb 100644 --- a/src/game/behaviors/sl_walking_penguin.inc.c +++ b/src/game/behaviors/sl_walking_penguin.inc.c @@ -97,7 +97,9 @@ void bhv_sl_walking_penguin_loop(void) { } cur_obj_move_standard(-78); - if (!cur_obj_hide_if_mario_far_away_y(1000.0f)) +#ifndef NODRAWINGDISTANCE + if (!cur_obj_hide_if_mario_far_away_y(1000.0f)) +#endif play_penguin_walking_sound(PENGUIN_WALK_BIG); // Adjust the position to get a point better lined up with the visual model, for stopping the wind. From 07aa2cd2341c487547a48aaf20f955e93e0378a8 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 12:21:16 -0300 Subject: [PATCH 56/73] Fix compilation for MXE on Linux and WSL Even though this isn't usually an option on the wiki, this will allow for cross-compilation of sm64pc through MXE on both Linux and WSL, making Wine testing much easier. --- Makefile | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 89452c95..71379025 100644 --- a/Makefile +++ b/Makefile @@ -428,9 +428,17 @@ else LD := $(CC) endif -CPP := $(CROSS)cpp -P +ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL + CPP := cpp -P +else + CPP := $(CROSS)cpp -P +endif OBJDUMP := $(CROSS)objdump -OBJCOPY := $(CROSS)objcopy +ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL + OBJCOPY := $(CROSS)objcopy +else + OBJCOPY := $(CROSS)objcopy +endif PYTHON := python3 SDLCONFIG := $(CROSS)sdl2-config @@ -473,9 +481,22 @@ LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base ht else ifeq ($(WINDOWS_BUILD),1) -LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static -ifeq ($(WINDOWS_CONSOLE),1) -LDFLAGS += -mconsole + ifeq ($(CROSS),i686-w64-mingw32.static-) + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static + ifeq ($(WINDOWS_CONSOLE),1) + LDFLAGS += -mconsole + endif + else ifeq ($(CROSS),x86_64-w64-mingw32.static-) + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static + ifeq ($(WINDOWS_CONSOLE),1) + LDFLAGS += -mconsole + endif + else + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static + ifeq ($(WINDOWS_CONSOLE),1) + LDFLAGS += -mconsole + endif + endif endif else From 0f688c80d00492f31ee4e3dac7c9927cd1d54c34 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 12:26:06 -0300 Subject: [PATCH 57/73] removing a pesky endif --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 71379025..11aa77ca 100644 --- a/Makefile +++ b/Makefile @@ -495,7 +495,6 @@ ifeq ($(WINDOWS_BUILD),1) LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static ifeq ($(WINDOWS_CONSOLE),1) LDFLAGS += -mconsole - endif endif endif else From b4cb8a7f65f5fb7f6be5006000e6d7d94ae73439 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 12:30:25 -0300 Subject: [PATCH 58/73] remove needless ifeq --- Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 11aa77ca..4eae2ca8 100644 --- a/Makefile +++ b/Makefile @@ -434,11 +434,7 @@ else CPP := $(CROSS)cpp -P endif OBJDUMP := $(CROSS)objdump -ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL - OBJCOPY := $(CROSS)objcopy -else - OBJCOPY := $(CROSS)objcopy -endif +OBJCOPY := $(CROSS)objcopy PYTHON := python3 SDLCONFIG := $(CROSS)sdl2-config From 17695a7b4f8bf6633e065f4a85e01c52deb0e235 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 12:56:58 -0300 Subject: [PATCH 59/73] fix objcopy on MXE builds --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4eae2ca8..41617d6c 100644 --- a/Makefile +++ b/Makefile @@ -434,7 +434,11 @@ else CPP := $(CROSS)cpp -P endif OBJDUMP := $(CROSS)objdump -OBJCOPY := $(CROSS)objcopy +ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL + OBJCOPY := objcopy +else + OBJCOPY := $(CROSS)objcopy +endif PYTHON := python3 SDLCONFIG := $(CROSS)sdl2-config From 74058cf32f97abeead9f9cdfe62eb3e0c0d16e67 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 13:01:23 -0300 Subject: [PATCH 60/73] Simplify MXE fixes --- Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 41617d6c..fe45680c 100644 --- a/Makefile +++ b/Makefile @@ -430,15 +430,12 @@ endif ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL CPP := cpp -P -else - CPP := $(CROSS)cpp -P -endif -OBJDUMP := $(CROSS)objdump -ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL OBJCOPY := objcopy else + CPP := $(CROSS)cpp -P OBJCOPY := $(CROSS)objcopy endif +OBJDUMP := $(CROSS)objdump PYTHON := python3 SDLCONFIG := $(CROSS)sdl2-config From 31c91c6968c900667335854aa3b01214a5f585c5 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 13:46:18 -0300 Subject: [PATCH 61/73] Nah dude, that's possible under WINDOWS_BUILD=1 --- Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile b/Makefile index fe45680c..63fb19d5 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,6 @@ else endif # Automatic settings for PC port(s) -# WINDOWS_BUILD IS NOT FOR COMPILING A WINDOWS EXECUTABLE UNDER LINUX OR WSL! -# USE THE WIKI GUIDE WITH MSYS2 FOR COMPILING A WINDOWS EXECUTABLE! NON_MATCHING := 1 GRUCODE := f3dex2e From 0446b244ebd0757ea743699240dc9c80fb2f5b4f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 14 May 2020 00:33:12 +0300 Subject: [PATCH 62/73] separate EXT_OPTIONS_MENU into its own option --- Makefile | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 89452c95..0eefab09 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,8 @@ BETTERCAMERA ?= 0 NODRAWINGDISTANCE ?= 0 # Disable texture fixes by default (helps with them purists) TEXTURE_FIX ?= 0 +# Enable extended options menu by default +EXT_OPTIONS_MENU ?= 1 # Build for Emscripten/WebGL TARGET_WEB ?= 0 @@ -448,22 +450,31 @@ CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -W CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` endif -# Check for better camera option +# Check for enhancement options + +# Check for Puppycam option ifeq ($(BETTERCAMERA),1) -CC_CHECK += -DBETTERCAMERA -DEXT_OPTIONS_MENU -CFLAGS += -DBETTERCAMERA -DEXT_OPTIONS_MENU + CC_CHECK += -DBETTERCAMERA + CFLAGS += -DBETTERCAMERA + EXT_OPTIONS_MENU := 1 endif # Check for no drawing distance option ifeq ($(NODRAWINGDISTANCE),1) -CC_CHECK += -DNODRAWINGDISTANCE -CFLAGS += -DNODRAWINGDISTANCE + CC_CHECK += -DNODRAWINGDISTANCE + CFLAGS += -DNODRAWINGDISTANCE endif # Check for texture fix option ifeq ($(TEXTURE_FIX),1) -CC_CHECK += -DTEXTURE_FIX -CFLAGS += -DTEXTURE_FIX + CC_CHECK += -DTEXTURE_FIX + CFLAGS += -DTEXTURE_FIX +endif + +# Check for extended options menu option +ifeq ($(EXT_OPTIONS_MENU),1) + CC_CHECK += -DEXT_OPTIONS_MENU + CFLAGS += -DEXT_OPTIONS_MENU endif ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) From 1d557e4c4dda0bd120eeececd97c25029f5a1e05 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 19:59:59 +0300 Subject: [PATCH 63/73] only include camera options if BETTERCAM==1 --- src/game/options_menu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index c9feeb39..81c56c0f 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -9,7 +9,9 @@ #include "game/print.h" #include "game/segment2.h" #include "game/save_file.h" +#ifdef BETTERCAMERA #include "game/bettercamera.h" +#endif #include "game/mario_misc.h" #include "game/game_init.h" #include "game/ingame_menu.h" @@ -162,6 +164,7 @@ static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) { /* submenu option lists */ +#ifdef BETTERCAMERA static struct Option optsCamera[] = { DEF_OPT_TOGGLE( optsCameraStr[6], &configEnableCamera ), DEF_OPT_TOGGLE( optsCameraStr[7], &configCameraMouse ), @@ -172,6 +175,7 @@ static struct Option optsCamera[] = { DEF_OPT_SCROLL( optsCameraStr[4], &configCameraAggr, 0, 100, 1 ), DEF_OPT_SCROLL( optsCameraStr[5], &configCameraPan, 0, 100, 1 ), }; +#endif static struct Option optsControls[] = { DEF_OPT_BIND( bindStr[ 2], configKeyA ), @@ -201,7 +205,9 @@ static struct Option optsAudio[] = { /* submenu definitions */ +#ifdef BETTERCAMERA static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); +#endif static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); @@ -209,7 +215,9 @@ static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); /* main options menu definition */ static struct Option optsMain[] = { +#ifdef BETTERCAMERA DEF_OPT_SUBMENU( menuStr[4], &menuCamera ), +#endif DEF_OPT_SUBMENU( menuStr[5], &menuControls ), DEF_OPT_SUBMENU( menuStr[6], &menuVideo ), DEF_OPT_SUBMENU( menuStr[7], &menuAudio ), @@ -410,7 +418,9 @@ void optmenu_toggle(void) { play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs); #endif optmenu_open = 0; + #ifdef BETTERCAMERA newcam_init_settings(); // load bettercam settings from config vars + #endif controller_reconfigure(); // rebind using new config values configfile_save(CONFIG_FILE); } From 93cfab086a37bc0518adbf7fa025c49fff5d872f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 20:28:36 +0300 Subject: [PATCH 64/73] bettercam: add adjustable camera deceleration --- include/text_strings.h.in | 1 + src/game/bettercamera.inc.h | 12 ++++++------ src/game/options_menu.c | 2 ++ src/pc/configfile.c | 2 ++ src/pc/configfile.h | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index a577a161..3246699e 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -9,6 +9,7 @@ #define TEXT_OPT_INVERTY _("Invert Y Axis") #define TEXT_OPT_CAMC _("Camera Centre Aggression") #define TEXT_OPT_CAMP _("Camera Pan Level") +#define TEXT_OPT_CAMD _("Camera Deceleration") #define TEXT_OPT_ENABLED _("Enabled") #define TEXT_OPT_DISABLED _("Disabled") #define TEXT_OPT_BUTTON1 _("[R]: Options") diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index 3ef627a8..0f58b2e8 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -28,8 +28,6 @@ NC_MODE_NOTURN: Disables horizontal and vertical control of the camera. //#define NEWCAM_DEBUG //Some print values for puppycam. Not useful anymore, but never hurts to keep em around. //#define nosound //If for some reason you hate the concept of audio, you can disable it. //#define noaccel //Disables smooth movement of the camera with the C buttons. -#define DEGRADE 0.1f //What percent of the remaining camera movement is degraded. Default is 10% - //!Hardcoded camera angle stuff. They're essentially area boxes that when Mario is inside, will trigger some view changes. ///Don't touch this btw, unless you know what you're doing, this has to be above for religious reasons. @@ -88,6 +86,7 @@ s16 newcam_yaw_target; // The yaw value the camera tries to set itself to when t f32 newcam_turnwait; // The amount of time to wait after landing before allowing the camera to turn again f32 newcam_pan_x; f32 newcam_pan_z; +f32 newcam_degrade = 0.1f; //What percent of the remaining camera movement is degraded. Default is 10% u8 newcam_cstick_down = 0; //Just a value that triggers true when the player 2 stick is moved in 8 direction move to prevent holding it down. u8 newcam_target; @@ -155,6 +154,7 @@ void newcam_init_settings(void) newcam_invertY = (u8)configCameraInvertY; newcam_mouse = (u8)configCameraMouse; newcam_analogue = (u8)configEnableCamera; + newcam_degrade = (f32)configCameraDegrade / 100.0f; } /** Mathematic calculations. This stuffs so basic even *I* understand it lol @@ -268,7 +268,7 @@ static void newcam_rotate_button(void) #ifdef noaccel newcam_yaw_acc = 0; #else - newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE)); + newcam_yaw_acc -= (newcam_yaw_acc*newcam_degrade); #endif } @@ -280,7 +280,7 @@ static void newcam_rotate_button(void) #ifdef noaccel newcam_tilt_acc = 0; #else - newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE)); + newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade); #endif newcam_framessincec[0] += 1; @@ -346,13 +346,13 @@ static void newcam_rotate_button(void) else { newcam_cstick_down = 0; - newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE)); + newcam_yaw_acc -= (newcam_yaw_acc*newcam_degrade); } if (ABS(gPlayer2Controller->stickY) > 20 && newcam_modeflags & NC_FLAG_YTURN) newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,(-gPlayer2Controller->stickY/4)); else - newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE)); + newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade); } if (newcam_mouse == 1) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 81c56c0f..37bce584 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -59,6 +59,7 @@ static const u8 optsCameraStr[][32] = { { TEXT_OPT_CAMP }, { TEXT_OPT_ANALOGUE }, { TEXT_OPT_MOUSE }, + { TEXT_OPT_CAMD }, }; static const u8 optsVideoStr[][32] = { @@ -174,6 +175,7 @@ static struct Option optsCamera[] = { DEF_OPT_SCROLL( optsCameraStr[1], &configCameraYSens, 10, 250, 1 ), DEF_OPT_SCROLL( optsCameraStr[4], &configCameraAggr, 0, 100, 1 ), DEF_OPT_SCROLL( optsCameraStr[5], &configCameraPan, 0, 100, 1 ), + DEF_OPT_SCROLL( optsCameraStr[8], &configCameraDegrade, 0, 100, 1 ), }; #endif diff --git a/src/pc/configfile.c b/src/pc/configfile.c index df05b1d5..3c2735c2 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -59,6 +59,7 @@ unsigned int configCameraXSens = 50; unsigned int configCameraYSens = 50; unsigned int configCameraAggr = 0; unsigned int configCameraPan = 0; +unsigned int configCameraDegrade = 10; // 0 - 100% bool configCameraInvertX = false; bool configCameraInvertY = false; bool configEnableCamera = false; @@ -93,6 +94,7 @@ static const struct ConfigOption options[] = { {.name = "bettercam_ysens", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraYSens}, {.name = "bettercam_aggression", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraAggr}, {.name = "bettercam_pan_level", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraPan}, + {.name = "bettercam_degrade", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraDegrade}, #endif {.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, // Add this back! }; diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 39a020e8..8dc69e27 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -31,6 +31,7 @@ extern unsigned int configCameraXSens; extern unsigned int configCameraYSens; extern unsigned int configCameraAggr; extern unsigned int configCameraPan; +extern unsigned int configCameraDegrade; extern bool configCameraInvertX; extern bool configCameraInvertY; extern bool configEnableCamera; From 0a6ea9e9d42bdcf5f25619984b385a3ef11b4a81 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 14:35:56 -0300 Subject: [PATCH 65/73] Clean up the makefile fixes a bit --- Makefile | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 63fb19d5..7ef38cdd 100644 --- a/Makefile +++ b/Makefile @@ -477,18 +477,13 @@ else ifeq ($(WINDOWS_BUILD),1) ifeq ($(CROSS),i686-w64-mingw32.static-) - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static - ifeq ($(WINDOWS_CONSOLE),1) - LDFLAGS += -mconsole - endif + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static else ifeq ($(CROSS),x86_64-w64-mingw32.static-) - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static - ifeq ($(WINDOWS_CONSOLE),1) - LDFLAGS += -mconsole - endif + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static else - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static - ifeq ($(WINDOWS_CONSOLE),1) + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static + endif + ifeq ($(WINDOWS_CONSOLE),1) LDFLAGS += -mconsole endif endif From 50af1393c3b0af1d00fe7a8c1d4098b2f202ea22 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 14:38:47 -0300 Subject: [PATCH 66/73] Further clean up the makefile fixes --- Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 7ef38cdd..4cc4db1e 100644 --- a/Makefile +++ b/Makefile @@ -476,12 +476,11 @@ LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base ht else ifeq ($(WINDOWS_BUILD),1) - ifeq ($(CROSS),i686-w64-mingw32.static-) - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static - else ifeq ($(CROSS),x86_64-w64-mingw32.static-) - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static - else - LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static + LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static + ifneq ($(CROSS),i686-w64-mingw32.static-) + ifneq ($(CROSS),x86_64-w64-mingw32.static-) + LDFLAGS += -no-pie + endif endif ifeq ($(WINDOWS_CONSOLE),1) LDFLAGS += -mconsole From 3c6bf53dea58c9e38fe285291b3e5d07ce82951c Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 14:59:27 -0300 Subject: [PATCH 67/73] even further cleanup of the makefile --- Makefile | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 4cc4db1e..b285ddba 100644 --- a/Makefile +++ b/Makefile @@ -473,9 +473,7 @@ ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) ifeq ($(TARGET_WEB),1) LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base http://localhost:8080/ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']" -else - -ifeq ($(WINDOWS_BUILD),1) +else ifeq ($(WINDOWS_BUILD),1) LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static ifneq ($(CROSS),i686-w64-mingw32.static-) ifneq ($(CROSS),x86_64-w64-mingw32.static-) @@ -485,17 +483,12 @@ ifeq ($(WINDOWS_BUILD),1) ifeq ($(WINDOWS_CONSOLE),1) LDFLAGS += -mconsole endif -endif -else - +else ifeq ($(TARGET_RPI),1) # Linux / Other builds below -ifeq ($(TARGET_RPI),1) LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(SDLCONFIG) --libs` -no-pie else LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm -lGL `$(SDLCONFIG) --libs` -no-pie -lpthread endif -endif -endif #Added for Pi ifeq # Prevent a crash with -sopt From a5d4b22606e16f9656541e5d0c8834af97fdf1a5 Mon Sep 17 00:00:00 2001 From: wabberz <22555393+wabberz@users.noreply.github.com> Date: Sat, 16 May 2020 20:33:41 +0200 Subject: [PATCH 68/73] Update whomp.inc.c --- src/game/behaviors/whomp.inc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index 28f1c4c8..c7c39241 100644 --- a/src/game/behaviors/whomp.inc.c +++ b/src/game/behaviors/whomp.inc.c @@ -246,14 +246,14 @@ void bhv_whomp_loop(void) { cur_obj_call_action_function(sWhompActions); cur_obj_move_standard(-20); if (o->oAction != 9) { - #ifndef NODRAWINGDISTANCE +#ifndef NODRAWINGDISTANCE // o->oBehParams2ndByte here seems to be a flag // indicating whether this is a normal or king whomp if (o->oBehParams2ndByte != 0) cur_obj_hide_if_mario_far_away_y(2000.0f); else cur_obj_hide_if_mario_far_away_y(1000.0f); - #endif +#endif load_object_collision_model(); } } From 4bbbc5b7e0ea7d34f24d624321e23b5767a1f528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Sat, 16 May 2020 15:42:59 -0300 Subject: [PATCH 69/73] Typo in extract_assets.py Closes #131 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05eba070..b1cc3121 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64). Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. -Run `./extract-assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer. +Run `./extract_assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer. *Read this in other languages: [Español](README_es_ES.md) [简体中文](README_zh_CN.md).* From 249a2d476320352dad3ab61e1d5f8a7f9f70f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Sat, 16 May 2020 15:44:55 -0300 Subject: [PATCH 70/73] Typo in extract_assets.py --- README_zh_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_zh_CN.md b/README_zh_CN.md index 9bcc5891..b3e90f92 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -2,7 +2,7 @@ 本项目是 [n64decomp/sm64](https://github.com/n64decomp/sm64) 的 OpenGL 移植版本。 我们欢迎贡献代码与 bug 报告,但请切记,**不得上传任何被版权保护(来自 ROM 文件)的资源**。 -提交前请运行 `./extract-assets.py --clean && make clean` 或 `make distclean` 来清除所有从 ROM 文件中提取的内容。 +提交前请运行 `./extract_assets.py --clean && make clean` 或 `make distclean` 来清除所有从 ROM 文件中提取的内容。 本移植是基于 [Emill](https://github.com/Emill) 的工作 [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) 才得以实现的。 ## 主要功能 From 8722b09bb4998afd190fab02f65459f7b87abc8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= <36349314+vrmiguel@users.noreply.github.com> Date: Sat, 16 May 2020 15:45:40 -0300 Subject: [PATCH 71/73] Typo in "extract_assets.py" --- README_es_ES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_es_ES.md b/README_es_ES.md index 86a3373e..7426486c 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -2,7 +2,7 @@ Adaptación a OpenGL de [n64decomp/sm64](https://github.com/n64decomp/sm64). No dudes en contribuir o reportar bugs, pero recuerda: **no se debe subir nada con copyright**. -Ejecuta `./extract-assets.py --clean && make clean` o `make distclean` para borrar todo el contenido proveniente de la ROM. Este port es posible gracias a [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) creado por [Emill](https://github.com/Emill). +Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para borrar todo el contenido proveniente de la ROM. Este port es posible gracias a [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) creado por [Emill](https://github.com/Emill). ## Funcionalidades From 9e8290773b29a2cf515f65b2f4997d0e79d57bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Sat, 16 May 2020 16:23:23 -0300 Subject: [PATCH 72/73] Shutdown subsystems on exit Porting from testing, originally by @fgsfdsfgs --- src/pc/audio/audio_api.h | 1 + src/pc/audio/audio_null.c | 8 ++++++-- src/pc/audio/audio_sdl.c | 14 +++++++++++++- src/pc/controller/controller_api.h | 4 ++++ src/pc/controller/controller_entry_point.c | 7 +++++++ src/pc/controller/controller_keyboard.c | 4 ++++ src/pc/controller/controller_recorded_tas.c | 8 ++++++++ src/pc/controller/controller_sdl.c | 12 ++++++++++++ src/pc/gfx/gfx_opengl.c | 6 +++++- src/pc/gfx/gfx_pc.c | 11 +++++++++++ src/pc/gfx/gfx_pc.h | 1 + src/pc/gfx/gfx_rendering_api.h | 1 + src/pc/gfx/gfx_sdl2.c | 13 ++++++++++++- src/pc/gfx/gfx_window_manager_api.h | 1 + src/pc/pc_main.c | 20 +++++++++++++++----- 15 files changed, 101 insertions(+), 10 deletions(-) diff --git a/src/pc/audio/audio_api.h b/src/pc/audio/audio_api.h index 26794dd6..b40130e0 100644 --- a/src/pc/audio/audio_api.h +++ b/src/pc/audio/audio_api.h @@ -10,6 +10,7 @@ struct AudioAPI { int (*buffered)(void); int (*get_desired_buffered)(void); void (*play)(const uint8_t *buf, size_t len); + void (*shutdown)(void); }; #endif diff --git a/src/pc/audio/audio_null.c b/src/pc/audio/audio_null.c index 8a244e4b..4d0dd923 100644 --- a/src/pc/audio/audio_null.c +++ b/src/pc/audio/audio_null.c @@ -15,9 +15,13 @@ static int audio_null_get_desired_buffered(void) { static void audio_null_play(const uint8_t *buf, size_t len) { } +static void audio_null_shutdown(void) { +} + struct AudioAPI audio_null = { audio_null_init, audio_null_buffered, audio_null_get_desired_buffered, - audio_null_play -}; + audio_null_play, + audio_null_shutdown +}; \ No newline at end of file diff --git a/src/pc/audio/audio_sdl.c b/src/pc/audio/audio_sdl.c index 2f13ccde..beb5a1e6 100644 --- a/src/pc/audio/audio_sdl.c +++ b/src/pc/audio/audio_sdl.c @@ -40,9 +40,21 @@ static void audio_sdl_play(const uint8_t *buf, size_t len) { } } +static void audio_sdl_shutdown(void) +{ + if (SDL_WasInit(SDL_INIT_AUDIO)) { + if (dev != 0) { + SDL_CloseAudioDevice(dev); + dev = 0; + } + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } +} + struct AudioAPI audio_sdl = { audio_sdl_init, audio_sdl_buffered, audio_sdl_get_desired_buffered, - audio_sdl_play + audio_sdl_play, + audio_sdl_shutdown }; \ No newline at end of file diff --git a/src/pc/controller/controller_api.h b/src/pc/controller/controller_api.h index fdd6e503..2f9c1d16 100644 --- a/src/pc/controller/controller_api.h +++ b/src/pc/controller/controller_api.h @@ -13,10 +13,14 @@ struct ControllerAPI { void (*read)(OSContPad *pad); // read controller and update N64 pad values u32 (*rawkey)(void); // returns last pressed virtual key or VK_INVALID if none void (*reconfig)(void); // (optional) call when bindings have changed + void (*shutdown)(void); // (optional) call in osContReset }; // used for binding keys u32 controller_get_raw_key(void); void controller_reconfigure(void); +// calls the shutdown() function of all controller subsystems +void controller_shutdown(void); + #endif diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index 536b0798..90c10c1d 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -65,6 +65,13 @@ u32 controller_get_raw_key(void) { return VK_INVALID; } +void controller_shutdown(void) { + for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) { + if (controller_implementations[i]->shutdown) + controller_implementations[i]->shutdown(); + } +} + void controller_reconfigure(void) { for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) { if (controller_implementations[i]->reconfig) diff --git a/src/pc/controller/controller_keyboard.c b/src/pc/controller/controller_keyboard.c index c9421a24..9fb4b635 100644 --- a/src/pc/controller/controller_keyboard.c +++ b/src/pc/controller/controller_keyboard.c @@ -107,10 +107,14 @@ static u32 keyboard_rawkey(void) { return ret; } +static void keyboard_shutdown(void) { +} + struct ControllerAPI controller_keyboard = { VK_BASE_KEYBOARD, keyboard_init, keyboard_read, keyboard_rawkey, keyboard_bindkeys, + keyboard_shutdown }; diff --git a/src/pc/controller/controller_recorded_tas.c b/src/pc/controller/controller_recorded_tas.c index f05c0558..2fcd5b54 100644 --- a/src/pc/controller/controller_recorded_tas.c +++ b/src/pc/controller/controller_recorded_tas.c @@ -23,6 +23,13 @@ static void tas_read(OSContPad *pad) { } } +static void tas_shutdown(void) { + if (fp != NULL) { + fclose(fp); + fp = NULL; + } +} + static u32 tas_rawkey(void) { return VK_INVALID; } @@ -33,4 +40,5 @@ struct ControllerAPI controller_recorded_tas = { tas_read, tas_rawkey, NULL, // no rebinding + tas_shutdown }; diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 171a31f4..62aa2acf 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -204,10 +204,22 @@ static u32 controller_sdl_rawkey(void) { return VK_INVALID; } +static void controller_sdl_shutdown(void) { + if (SDL_WasInit(SDL_INIT_GAMECONTROLLER)) { + if (sdl_cntrl) { + SDL_GameControllerClose(sdl_cntrl); + sdl_cntrl = NULL; + } + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + } + init_ok = false; +} + struct ControllerAPI controller_sdl = { VK_BASE_SDL_GAMEPAD, controller_sdl_init, controller_sdl_read, controller_sdl_rawkey, controller_sdl_bind, + controller_sdl_shutdown }; diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index b7067e91..b283b7e2 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -481,6 +481,9 @@ static void gfx_opengl_start_frame(void) { glEnable(GL_SCISSOR_TEST); } +static void gfx_opengl_shutdown(void) { +} + struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_z_is_from_0_to_1, gfx_opengl_unload_shader, @@ -500,5 +503,6 @@ struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_set_use_alpha, gfx_opengl_draw_triangles, gfx_opengl_init, - gfx_opengl_start_frame + gfx_opengl_start_frame, + gfx_opengl_shutdown }; diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 7052ad60..67c45ecb 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -1547,3 +1547,14 @@ void gfx_end_frame(void) { gfx_wapi->swap_buffers_end(); } } + +void gfx_shutdown(void) { + if (gfx_rapi) { + if (gfx_rapi->shutdown) gfx_rapi->shutdown(); + gfx_rapi = NULL; + } + if (gfx_wapi) { + if (gfx_wapi->shutdown) gfx_wapi->shutdown(); + gfx_wapi = NULL; + } +} \ No newline at end of file diff --git a/src/pc/gfx/gfx_pc.h b/src/pc/gfx/gfx_pc.h index 6903597c..8d62e2b7 100644 --- a/src/pc/gfx/gfx_pc.h +++ b/src/pc/gfx/gfx_pc.h @@ -15,5 +15,6 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi); void gfx_start_frame(void); void gfx_run(Gfx *commands); void gfx_end_frame(void); +void gfx_shutdown(void); #endif diff --git a/src/pc/gfx/gfx_rendering_api.h b/src/pc/gfx/gfx_rendering_api.h index 58d79435..75aedef9 100644 --- a/src/pc/gfx/gfx_rendering_api.h +++ b/src/pc/gfx/gfx_rendering_api.h @@ -27,6 +27,7 @@ struct GfxRenderingAPI { void (*draw_triangles)(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris); void (*init)(void); void (*start_frame)(void); + void (*shutdown)(void); }; #endif diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index e7018476..57ff486d 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -24,6 +24,7 @@ #include "src/pc/controller/controller_keyboard.h" static SDL_Window *wnd; +static SDL_GLContext ctx = NULL; static int inverted_scancode_table[512]; static bool cur_fullscreen; @@ -235,6 +236,15 @@ static double gfx_sdl_get_time(void) { return 0.0; } + +static void gfx_sdl_shutdown(void) { + if (SDL_WasInit(0)) { + if (ctx) { SDL_GL_DeleteContext(ctx); ctx = NULL; } + if (wnd) { SDL_DestroyWindow(wnd); wnd = NULL; } + SDL_Quit(); + } +} + struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_init, gfx_sdl_main_loop, @@ -243,5 +253,6 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_start_frame, gfx_sdl_swap_buffers_begin, gfx_sdl_swap_buffers_end, - gfx_sdl_get_time + gfx_sdl_get_time, + gfx_sdl_shutdown }; diff --git a/src/pc/gfx/gfx_window_manager_api.h b/src/pc/gfx/gfx_window_manager_api.h index 9c68cd10..45826711 100644 --- a/src/pc/gfx/gfx_window_manager_api.h +++ b/src/pc/gfx/gfx_window_manager_api.h @@ -13,6 +13,7 @@ struct GfxWindowManagerAPI { void (*swap_buffers_begin)(void); void (*swap_buffers_end)(void); double (*get_time)(void); // For debug + void (*shutdown)(void); }; #endif diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 52d8339b..93774fe2 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -84,6 +84,20 @@ void produce_one_frame(void) { gfx_end_frame(); } +void audio_shutdown(void) { + if (audio_api) { + if (audio_api->shutdown) audio_api->shutdown(); + audio_api = NULL; + } +} + +void game_shutdown(void) { + configfile_save(CONFIG_FILE); + controller_shutdown(); + audio_shutdown(); + gfx_shutdown(); +} + #ifdef TARGET_WEB static void em_main_loop(void) { } @@ -117,17 +131,13 @@ static void on_anim_frame(double time) { } #endif -static void save_config(void) { - configfile_save(CONFIG_FILE); -} - void main_func(void) { static u64 pool[0x165000/8 / 4 * sizeof(void *)]; main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0])); gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT); configfile_load(CONFIG_FILE); - atexit(save_config); + atexit(game_shutdown); #ifdef TARGET_WEB emscripten_set_main_loop(em_main_loop, 0, 0); From f6642e9a9d32836cc52071ba12e953c4023018c5 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 22:39:37 +0300 Subject: [PATCH 73/73] tabs begone --- src/pc/gfx/gfx_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 67d8e1ec..3b11a46c 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -575,7 +575,7 @@ static void gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *verti // Inspired by: // https://github.com/gonetz/GLideN64/commit/c8cbafff71a81bee5112aaafe6e21d6648ff8125#diff-69d8715ec7f9fd627ec4f5516edd003dL484 const bool useFirstColor = (dest_index & 1) == 0; - const unsigned char* col = useFirstColor + const unsigned char* col = useFirstColor ? rsp.current_lights[rsp.current_num_lights - 1].col : rsp.current_lights[rsp.current_num_lights - 1].colc; int r = col[0];