From 4cbe3af070ee8415217e7fe502874fda93eb2be1 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Mon, 11 May 2020 02:42:22 -0300 Subject: [PATCH 01/86] 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/86] 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/86] 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/86] 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 bea82c00bcce52afb02cbc72a0f8d8163ad3a321 Mon Sep 17 00:00:00 2001 From: uwabami Date: Wed, 13 May 2020 09:25:45 +0200 Subject: [PATCH 05/86] 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 31f0d68ca2e7c9d52f31efa4628d8fefca0caeed Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Wed, 13 May 2020 07:57:25 -0400 Subject: [PATCH 06/86] Removed majority of TARGET_N64 logic from code --- bin/segment2.c | 26 +----- include/PR/gbi.h | 22 ----- include/PR/ultratypes.h | 9 +- include/config.h | 9 +- include/gfx_dimensions.h | 8 -- include/macros.h | 11 --- include/make_const_nonconst.h | 7 -- include/platform_info.h | 5 -- include/segment_symbols.h | 10 --- levels/menu/script.c | 7 +- lib/src/guMtxF2L.c | 49 +---------- src/audio/external.c | 110 +------------------------ src/audio/heap.c | 7 +- src/audio/internal.h | 3 - src/audio/port_eu.c | 101 ----------------------- src/audio/synthesis.c | 3 - src/buffers/buffers.h | 5 +- src/engine/level_script.c | 15 ++-- src/engine/surface_load.c | 3 - src/engine/surface_load.h | 4 +- src/game/display.h | 2 +- src/game/game_init.c | 67 +++------------ src/game/game_init.h | 4 +- src/game/geo_misc.c | 5 +- src/game/geo_misc.h | 6 -- src/game/ingame_menu.c | 29 ++----- src/game/macro_special_objects.c | 3 +- src/game/macro_special_objects.h | 2 - src/game/memory.c | 136 +------------------------------ src/game/memory.h | 8 -- src/game/print.c | 26 ------ src/game/rendering_graph_node.c | 6 -- src/game/screen_transition.c | 13 +-- src/game/skybox.c | 2 - src/goddard/renderer.c | 106 +----------------------- src/goddard/skin.c | 26 ++---- 36 files changed, 58 insertions(+), 797 deletions(-) diff --git a/bin/segment2.c b/bin/segment2.c index d4199d9c..d7e807fd 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -2499,41 +2499,23 @@ static const Lights1 segment2_lights_unused = gdSPDefLights1( // 0x02014470 - 0x020144B0 static const Mtx matrix_identity = { -#ifdef TARGET_N64 - {{0x00010000, 0x00000000, - 0x00000001, 0x00000000}, - {0x00000000, 0x00010000, - 0x00000000, 0x00000001}, - {0x00000000, 0x00000000, - 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, - 0x00000000, 0x00000000}} -#else + {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}} -#endif + }; // 0x020144B0 - 0x020144F0 static const Mtx matrix_fullscreen = { -#if TARGET_N64 - {{0x00000000, 0x00000000, - 0x00000000, 0x00000000}, - {0x00000000, 0xffff0000, - 0xffffffff, 0xffff0001}, - {((65536 * 2 / SCREEN_WIDTH) << 16) | 0, 0x00000000, - (0 << 16) | (65536 * 2 / SCREEN_HEIGHT), 0x00000000}, - {0x00000000, 0x00000000, - 0x00000000, 0x00000000}} -#else + {{2.0f / SCREEN_WIDTH, 0.0f, 0.0f, 0.0f}, {0.0f, 2.0f / SCREEN_HEIGHT, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, -1.0f, 1.0f}} -#endif + }; diff --git a/include/PR/gbi.h b/include/PR/gbi.h index 4a7a5de0..0f63e04f 100644 --- a/include/PR/gbi.h +++ b/include/PR/gbi.h @@ -1109,11 +1109,7 @@ * Vertex (set up for use with colors) */ typedef struct { -#ifdef TARGET_N64 - short ob[3]; /* x, y, z */ -#else float ob[3]; /* x, y, z */ -#endif unsigned short flag; short tc[2]; /* texture coord */ unsigned char cn[4]; /* color & alpha */ @@ -1123,11 +1119,7 @@ typedef struct { * Vertex (set up for use with normals) */ typedef struct { -#ifdef TARGET_N64 - short ob[3]; /* x, y, z */ -#else float ob[3]; /* x, y, z */ -#endif unsigned short flag; short tc[2]; /* texture coord */ signed char n[3]; /* normal */ @@ -1176,23 +1168,9 @@ typedef struct { unsigned char v[3]; } Tri; -#ifdef TARGET_N64 -/* - * 4x4 matrix, fixed point s15.16 format. - * First 8 words are integer portion of the 4x4 matrix - * Last 8 words are the fraction portion of the 4x4 matrix - */ -typedef s32 Mtx_t[4][4]; - -typedef union { - Mtx_t m; - long long int force_structure_alignment; -} Mtx; -#else typedef struct { float m[4][4]; } Mtx; -#endif /* * Viewport diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h index 8a00490a..e2a3e771 100644 --- a/include/PR/ultratypes.h +++ b/include/PR/ultratypes.h @@ -29,16 +29,9 @@ typedef volatile s64 vs64; typedef float f32; typedef double f64; -#ifdef TARGET_N64 -typedef u32 size_t; -typedef s32 ssize_t; -typedef u32 uintptr_t; -typedef s32 intptr_t; -typedef s32 ptrdiff_t; -#else #include #include typedef ptrdiff_t ssize_t; -#endif + #endif diff --git a/include/config.h b/include/config.h index df5cc54e..db50b1cc 100644 --- a/include/config.h +++ b/include/config.h @@ -1,4 +1,5 @@ #ifndef CONFIG_H + #define CONFIG_H /** @@ -28,15 +29,11 @@ #define SCREEN_HEIGHT 240 // Border Height Define for NTSC Versions -#ifdef TARGET_N64 -#ifndef VERSION_EU -#define BORDER_HEIGHT 8 -#else + #define BORDER_HEIGHT 1 -#endif + #else // What's the point of having a border? #define BORDER_HEIGHT 0 -#endif #endif diff --git a/include/gfx_dimensions.h b/include/gfx_dimensions.h index dfc0394d..cae20701 100644 --- a/include/gfx_dimensions.h +++ b/include/gfx_dimensions.h @@ -1,7 +1,6 @@ #ifndef GFX_DIMENSIONS_H #define GFX_DIMENSIONS_H -#ifndef TARGET_N64 #include #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)) @@ -9,12 +8,5 @@ #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_ASPECT_RATIO (gfx_current_dimensions.aspect_ratio) -#else -#define GFX_DIMENSIONS_FROM_LEFT_EDGE(v) (v) -#define GFX_DIMENSIONS_FROM_RIGHT_EDGE(v) (SCREEN_WIDTH - (v)) -#define GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(v) (v) -#define GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(v) (SCREEN_WIDTH - (v)) -#define GFX_DIMENSIONS_ASPECT_RATIO (4.0f / 3.0f) -#endif #endif diff --git a/include/macros.h b/include/macros.h index 8d6182c9..bcace7fb 100644 --- a/include/macros.h +++ b/include/macros.h @@ -46,20 +46,9 @@ #define ALIGNED16 #endif -#ifdef TARGET_N64 -// convert a virtual address to physical. -#define VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr) & 0x1FFFFFFF) - -// convert a physical address to virtual. -#define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr) | 0x80000000) - -// another way of converting virtual to physical -#define VIRTUAL_TO_PHYSICAL2(addr) ((u8 *)(addr) - 0x80000000U) -#else // no conversion for pc port other than cast #define VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr)) #define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr)) #define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr)) -#endif #endif diff --git a/include/make_const_nonconst.h b/include/make_const_nonconst.h index 6336ec34..249f73ae 100644 --- a/include/make_const_nonconst.h +++ b/include/make_const_nonconst.h @@ -1,11 +1,4 @@ #ifndef MAKE_CONST_NONCONST_H #define MAKE_CONST_NONCONST_H -#ifdef TARGET_N64 -// IDO sometimes puts const variables in .rodata and sometimes in .data, which breaks ordering. -// This makes sure all variables are put into the same section (.data). We need to do this for -// both IDO and gcc for TARGET_N64. -#define const -#endif - #endif diff --git a/include/platform_info.h b/include/platform_info.h index ee35d4f0..2197833a 100644 --- a/include/platform_info.h +++ b/include/platform_info.h @@ -1,14 +1,9 @@ #ifndef PLATFORM_INFO_H #define PLATFORM_INFO_H -#ifdef TARGET_N64 -#define IS_64_BIT 0 -#define IS_BIG_ENDIAN 1 -#else #include #define IS_64_BIT (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFU) #define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#endif #define DOUBLE_SIZE_ON_64_BIT(size) ((size) * (sizeof(void *) / 4)) diff --git a/include/segment_symbols.h b/include/segment_symbols.h index 77adc158..26d65cde 100644 --- a/include/segment_symbols.h +++ b/include/segment_symbols.h @@ -1,15 +1,9 @@ #ifndef SEGMENT_SYMBOLS_H #define SEGMENT_SYMBOLS_H -#ifdef TARGET_N64 -#define DECLARE_SEGMENT(name) \ - extern u8 _##name##SegmentRomStart[]; \ - extern u8 _##name##SegmentRomEnd[]; -#else #define DECLARE_SEGMENT(name) \ static u8 _##name##SegmentRomStart[1]; \ static u8 _##name##SegmentRomEnd[1]; -#endif #define DECLARE_ACTOR_SEGMENT(name) \ DECLARE_SEGMENT(name##_mio0) \ @@ -43,11 +37,7 @@ DECLARE_ACTOR_SEGMENT(group17) DECLARE_SEGMENT(behavior) DECLARE_SEGMENT(scripts) DECLARE_SEGMENT(goddard) -#ifdef TARGET_N64 -extern u8 _goddardSegmentStart[]; -#else static u8 _goddardSegmentStart[1]; -#endif DECLARE_LEVEL_SEGMENT(menu) DECLARE_LEVEL_SEGMENT(intro) diff --git a/levels/menu/script.c b/levels/menu/script.c index 5a9d3e44..4e955c12 100644 --- a/levels/menu/script.c +++ b/levels/menu/script.c @@ -72,19 +72,16 @@ const LevelScript level_main_menu_entry_2[] = { /*25*/ FREE_LEVEL_POOL(), /*26*/ LOAD_AREA(/*area*/ 2), -#ifndef TARGET_N64 + // sVisibleStars is set to 0 during FIXED_LOAD above on N64, but not on PC-port. // lvl_init_act_selector_values_and_stars must be called here otherwise the // previous value is retained and causes incorrect drawing during the 16 transition // frames. CALL(/*arg*/ 0, /*func*/ lvl_init_act_selector_values_and_stars), -#endif + /*27*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_FROM_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF), /*29*/ SLEEP(/*frames*/ 16), /*30*/ SET_MENU_MUSIC(/*seq*/ 0x000D), -#ifdef TARGET_N64 - /*31*/ CALL(/*arg*/ 0, /*func*/ lvl_init_act_selector_values_and_stars), -#endif /*33*/ CALL_LOOP(/*arg*/ 0, /*func*/ lvl_update_obj_and_load_act_button_actions), /*35*/ GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_ACT_NUM), /*36*/ STOP_MUSIC(/*fadeOutTime*/ 0x00BE), diff --git a/lib/src/guMtxF2L.c b/lib/src/guMtxF2L.c index e08528ec..9cd7359c 100644 --- a/lib/src/guMtxF2L.c +++ b/lib/src/guMtxF2L.c @@ -1,49 +1,9 @@ #include "libultra_internal.h" -#ifndef TARGET_N64 #include -#endif -#ifdef TARGET_N64 -void guMtxF2L(float mf[4][4], Mtx *m) { - int r, c; - s32 tmp1; - s32 tmp2; - s32 *m1 = &m->m[0][0]; - s32 *m2 = &m->m[2][0]; - for (r = 0; r < 4; r++) { - for (c = 0; c < 2; c++) { - tmp1 = mf[r][2 * c] * 65536.0f; - tmp2 = mf[r][2 * c + 1] * 65536.0f; - *m1++ = (tmp1 & 0xffff0000) | ((tmp2 >> 0x10) & 0xffff); - *m2++ = ((tmp1 << 0x10) & 0xffff0000) | (tmp2 & 0xffff); - } - } -} -void guMtxL2F(float mf[4][4], Mtx *m) { - int r, c; - u32 tmp1; - u32 tmp2; - u32 *m1; - u32 *m2; - s32 stmp1, stmp2; - m1 = (u32 *) &m->m[0][0]; - m2 = (u32 *) &m->m[2][0]; - for (r = 0; r < 4; r++) { - for (c = 0; c < 2; c++) { - tmp1 = (*m1 & 0xffff0000) | ((*m2 >> 0x10) & 0xffff); - tmp2 = ((*m1++ << 0x10) & 0xffff0000) | (*m2++ & 0xffff); - stmp1 = *(s32 *) &tmp1; - stmp2 = *(s32 *) &tmp2; - mf[r][c * 2 + 0] = stmp1 / 65536.0f; - mf[r][c * 2 + 1] = stmp2 / 65536.0f; - } - } -} -#else void guMtxF2L(float mf[4][4], Mtx *m) { memcpy(m, mf, sizeof(Mtx)); } -#endif void guMtxIdentF(float mf[4][4]) { int r, c; @@ -58,11 +18,8 @@ void guMtxIdentF(float mf[4][4]) { } } void guMtxIdent(Mtx *m) { -#ifdef TARGET_N64 - float mf[4][4]; - guMtxIdentF(mf); - guMtxF2L(mf, m); -#else + guMtxIdentF(m->m); -#endif + } + diff --git a/src/audio/external.c b/src/audio/external.c index 32431a53..a059c0b5 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -738,6 +738,7 @@ void func_8031D838(s32 player, FadeT fadeInTime, u8 targetVolume) { } seqPlayer->fadeVelocity = (((f32)(FLOAT_CAST(targetVolume) / EU_FLOAT(127.0)) - seqPlayer->fadeVolume) / (f32) fadeInTime); + #ifdef VERSION_EU seqPlayer->state = 0; #else @@ -764,117 +765,15 @@ void func_eu_802e9bec(s32 player, s32 channel, s32 arg2) { } #else - -#ifdef TARGET_N64 -struct SPTask *create_next_audio_frame_task(void) { - u32 samplesRemainingInAI; - s32 writtenCmds; - s32 index; - OSTask_t *task; - s32 oldDmaCount; - s32 flags; - - gAudioFrameCount++; - if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) { - stubbed_printf("DAC:Lost 1 Frame.\n"); - return NULL; - } - - gAudioTaskIndex ^= 1; - gCurrAiBufferIndex++; - gCurrAiBufferIndex %= NUMAIBUFFERS; - index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS; - samplesRemainingInAI = osAiGetLength() / 4; - - // Audio is triple buffered; the audio interface reads from two buffers - // while the third is being written by the RSP. More precisely, the - // lifecycle is: - // - this function computes an audio command list - // - wait for vblank - // - the command list is sent to the RSP (we could have sent it to the - // RSP before the vblank, but that gives the RSP less time to finish) - // - wait for vblank - // - the RSP is now expected to be finished, and we can send its output - // on to the AI - // Here we thus send to the AI the sound that was generated two frames ago. - if (gAiBufferLengths[index] != 0) { - osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4); - } - - oldDmaCount = gCurrAudioFrameDmaCount; - // There has to be some sort of no-op if here, but it's not exactly clear - // how it should look... It's also very unclear why gCurrAudioFrameDmaQueue - // isn't read from here, despite gCurrAudioFrameDmaCount being reset. - if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) { - stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount); - } - gCurrAudioFrameDmaCount = 0; - - gAudioTask = &gAudioTasks[gAudioTaskIndex]; - gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex]; - - index = gCurrAiBufferIndex; - gCurrAiBuffer = gAiBuffers[index]; - gAiBufferLengths[index] = ((gSamplesPerFrameTarget - samplesRemainingInAI + - EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE; - if (gAiBufferLengths[index] < gMinAiBufferLength) { - gAiBufferLengths[index] = gMinAiBufferLength; - } - if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) { - gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE; - } - - if (sGameLoopTicked != 0) { - update_game_sound(); - sGameLoopTicked = 0; - } - - // For the function to match we have to preserve some arbitrary variable - // across this function call. - flags = 0; - gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]); - gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount); - - index = gAudioTaskIndex; - gAudioTask->msgqueue = NULL; - gAudioTask->msg = NULL; - - task = &gAudioTask->task.t; - task->type = M_AUDTASK; - task->flags = flags; - task->ucode_boot = rspF3DBootStart; - task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart; - task->ucode = rspAspMainStart; - task->ucode_size = 0x800; // (this size is ignored) - task->ucode_data = rspAspMainDataStart; - task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64); - task->dram_stack = NULL; - task->dram_stack_size = 0; - task->output_buff = NULL; - task->output_buff_size = NULL; - task->data_ptr = gAudioCmdBuffers[index]; - task->data_size = writtenCmds * sizeof(u64); - - // The audio task never yields, so having a yield buffer is pointless. - // This wastefulness was fixed in US. -#ifdef VERSION_JP - task->yield_data_ptr = (u64 *) gAudioSPTaskYieldBuffer; - task->yield_data_size = OS_YIELD_AUDIO_SIZE; -#else - task->yield_data_ptr = NULL; - task->yield_data_size = 0; +// Stubbed N64-US/JP audio code +// continue; #endif - decrease_sample_dma_ttls(); - return gAudioTask; -} -#endif -#endif -#ifndef TARGET_N64 struct SPTask *create_next_audio_frame_task(void) { return NULL; } + void create_next_audio_buffer(s16 *samples, u32 num_samples) { gAudioFrameCount++; if (sGameLoopTicked != 0) { @@ -886,7 +785,6 @@ void create_next_audio_buffer(s16 *samples, u32 num_samples) { gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount); decrease_sample_dma_ttls(); } -#endif void play_sound(s32 soundBits, f32 *pos) { sSoundRequests[sSoundRequestCount].soundBits = soundBits; diff --git a/src/audio/heap.c b/src/audio/heap.c index 32b8103c..d1d69417 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -651,12 +651,7 @@ s32 audio_shut_down_and_reset_step(void) { */ void wait_for_audio_frames(s32 frames) { gAudioFrameCount = 0; -#ifdef TARGET_N64 - // Sound thread will update gAudioFrameCount - while (gAudioFrameCount < frames) { - // spin - } -#endif + } #endif diff --git a/src/audio/internal.h b/src/audio/internal.h index f681afae..fa44c8be 100644 --- a/src/audio/internal.h +++ b/src/audio/internal.h @@ -507,9 +507,6 @@ struct Note /* U/J, EU */ /*0xA4, 0x00*/ struct AudioListItem listItem; /* 0x10*/ struct NoteSynthesisState synthesisState; -#ifdef TARGET_N64 - u8 pad0[12]; -#endif /*0x04, 0x30*/ u8 priority; /* 0x31*/ u8 waveId; /* 0x32*/ u8 sampleCountIndex; diff --git a/src/audio/port_eu.c b/src/audio/port_eu.c index f90fc2bf..b0d0650e 100644 --- a/src/audio/port_eu.c +++ b/src/audio/port_eu.c @@ -34,107 +34,6 @@ void decrease_sample_dma_ttls(void); s32 audio_shut_down_and_reset_step(void); void func_802ad7ec(u32); -#ifdef TARGET_N64 -struct SPTask *create_next_audio_frame_task(void) { - u32 samplesRemainingInAI; - s32 writtenCmds; - s32 index; - OSTask_t *task; - s32 flags; - u16 *currAiBuffer; - s32 oldDmaCount; - OSMesg sp30; - OSMesg sp2C; - - gAudioFrameCount++; - if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) { - stubbed_printf("DAC:Lost 1 Frame.\n"); - return NULL; - } - - osSendMesg(OSMesgQueues[0], (OSMesg) gAudioFrameCount, 0); - - gAudioTaskIndex ^= 1; - gCurrAiBufferIndex++; - gCurrAiBufferIndex %= NUMAIBUFFERS; - index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS; - samplesRemainingInAI = osAiGetLength() / 4; - - if (gAiBufferLengths[index] != 0) { - osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4); - } - - oldDmaCount = gCurrAudioFrameDmaCount; - if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) { - stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount); - } - gCurrAudioFrameDmaCount = 0; - - decrease_sample_dma_ttls(); - if (osRecvMesg(OSMesgQueues[2], &sp30, 0) != -1) { - gAudioResetPresetIdToLoad = (u8) (s32) sp30; - gAudioResetStatus = 5; - } - - if (gAudioResetStatus != 0) { - if (audio_shut_down_and_reset_step() == 0) { - if (gAudioResetStatus == 0) { - osSendMesg(OSMesgQueues[3], (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK); - } - return NULL; - } - } - - gAudioTask = &gAudioTasks[gAudioTaskIndex]; - gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex]; - index = gCurrAiBufferIndex; - currAiBuffer = gAiBuffers[index]; - - gAiBufferLengths[index] = ((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI + - EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE; - if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) { - gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength; - } - if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) { - gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength; - } - - if (osRecvMesg(OSMesgQueues[1], &sp2C, OS_MESG_NOBLOCK) != -1) { - func_802ad7ec((u32) sp2C); - } - - flags = 0; - gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]); - gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount); - gAudioRandom = gAudioRandom + writtenCmds / 8; - - index = gAudioTaskIndex; - gAudioTask->msgqueue = NULL; - gAudioTask->msg = NULL; - - task = &gAudioTask->task.t; - task->type = M_AUDTASK; - task->flags = flags; -#if TARGET_N64 - task->ucode_boot = rspF3DBootStart; - task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart; - task->ucode = rspAspMainStart; - task->ucode_data = rspAspMainDataStart; - task->ucode_size = 0x800; // (this size is ignored) - task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64); -#endif - task->dram_stack = NULL; - task->dram_stack_size = 0; - task->output_buff = NULL; - task->output_buff_size = NULL; - task->data_ptr = gAudioCmdBuffers[index]; - task->data_size = writtenCmds * sizeof(u64); - task->yield_data_ptr = NULL; - task->yield_data_size = 0; - return gAudioTask; -} -#endif - void eu_process_audio_cmd(struct EuAudioCmd *cmd) { s32 i; diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index 370728ba..b332c9f0 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -8,10 +8,7 @@ #include "seqplayer.h" #include "external.h" - -#ifndef TARGET_N64 #include "../pc/mixer.h" -#endif #define DMEM_ADDR_TEMP 0x0 #define DMEM_ADDR_UNCOMPRESSED_NOTE 0x180 diff --git a/src/buffers/buffers.h b/src/buffers/buffers.h index aa834618..3d8b6c64 100644 --- a/src/buffers/buffers.h +++ b/src/buffers/buffers.h @@ -27,11 +27,8 @@ extern struct SaveBuffer gSaveBuffer; extern u8 gGfxSPTaskStack[]; -#ifdef TARGET_N64 -#define GFX_NUM_POOLS 2 -#else #define GFX_NUM_POOLS 1 -#endif + extern struct GfxPool gGfxPools[GFX_NUM_POOLS]; #endif diff --git a/src/engine/level_script.c b/src/engine/level_script.c index d0534038..64e4d46e 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -1,7 +1,6 @@ #include -#ifndef TARGET_N64 #include -#endif + #include "sm64.h" #include "audio/external.h" @@ -605,9 +604,7 @@ static void level_cmd_set_gamma(void) { static void level_cmd_set_terrain_data(void) { if (sCurrAreaIndex != -1) { -#ifdef TARGET_N64 - gAreas[sCurrAreaIndex].terrainData = segmented_to_virtual(CMD_GET(void *, 4)); -#else + Collision *data; u32 size; @@ -615,7 +612,7 @@ static void level_cmd_set_terrain_data(void) { size = get_area_terrain_size(data) * sizeof(Collision); gAreas[sCurrAreaIndex].terrainData = alloc_only_pool_alloc(sLevelPool, size); memcpy(gAreas[sCurrAreaIndex].terrainData, data, size); -#endif + } sCurrentCmd = CMD_NEXT; } @@ -629,9 +626,7 @@ static void level_cmd_set_rooms(void) { static void level_cmd_set_macro_objects(void) { if (sCurrAreaIndex != -1) { -#ifdef TARGET_N64 - gAreas[sCurrAreaIndex].macroObjects = segmented_to_virtual(CMD_GET(void *, 4)); -#else + MacroObject *data = segmented_to_virtual(CMD_GET(void *, 4)); s32 len = 0; while (data[len++] != 0x001E) { @@ -639,7 +634,7 @@ static void level_cmd_set_macro_objects(void) { } gAreas[sCurrAreaIndex].macroObjects = alloc_only_pool_alloc(sLevelPool, len * sizeof(MacroObject)); memcpy(gAreas[sCurrAreaIndex].macroObjects, data, len * sizeof(MacroObject)); -#endif + } sCurrentCmd = CMD_NEXT; } diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 363f9afb..da354352 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -533,7 +533,6 @@ void alloc_surface_pools(void) { reset_red_coins_collected(); } -#ifndef TARGET_N64 /** * Get the size of the terrain data, to get the correct size when copying later. */ @@ -581,8 +580,6 @@ u32 get_area_terrain_size(s16 *data) { return data - startPos; } -#endif - /** * Process the level file, loading in vertices, surfaces, some objects, and environmental diff --git a/src/engine/surface_load.h b/src/engine/surface_load.h index 943317c9..b8637be4 100644 --- a/src/engine/surface_load.h +++ b/src/engine/surface_load.h @@ -28,9 +28,9 @@ extern struct Surface *sSurfacePool; extern s16 sSurfacePoolSize; void alloc_surface_pools(void); -#ifndef TARGET_N64 + u32 get_area_terrain_size(s16 *data); -#endif + void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects); void clear_dynamic_surfaces(void); void load_object_collision_model(void); 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.c b/src/game/game_init.c index 939383a2..8834fc8b 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -217,13 +217,7 @@ void create_task_structure(void) { gGfxSPTask->msgqueue = &D_80339CB8; gGfxSPTask->msg = (OSMesg) 2; gGfxSPTask->task.t.type = M_GFXTASK; -#if TARGET_N64 - gGfxSPTask->task.t.ucode_boot = rspF3DBootStart; - gGfxSPTask->task.t.ucode_boot_size = ((u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart); - gGfxSPTask->task.t.flags = 0; - gGfxSPTask->task.t.ucode = rspF3DStart; - gGfxSPTask->task.t.ucode_data = rspF3DDataStart; -#endif + gGfxSPTask->task.t.ucode_size = SP_UCODE_SIZE; // (this size is ignored) gGfxSPTask->task.t.ucode_data_size = SP_UCODE_DATA_SIZE; gGfxSPTask->task.t.dram_stack = (u64 *) gGfxSPTaskStack; @@ -267,33 +261,9 @@ void end_master_display_list(void) { create_task_structure(); } -void draw_reset_bars(void) { - s32 sp24; - s32 sp20; - s32 fbNum; - u64 *sp18; - - if (gResetTimer != 0 && D_8032C648 < 15) { - if (sCurrFBNum == 0) { - fbNum = 2; - } else { - fbNum = sCurrFBNum - 1; - } - - sp18 = (u64 *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[fbNum]); - sp18 += D_8032C648++ * (SCREEN_WIDTH / 4); - - for (sp24 = 0; sp24 < ((SCREEN_HEIGHT / 16) + 1); sp24++) { - // Must be on one line to match -O2 - for (sp20 = 0; sp20 < (SCREEN_WIDTH / 4); sp20++) *sp18++ = 0; - sp18 += ((SCREEN_WIDTH / 4) * 14); - } - } - - osWritebackDCacheAll(); - osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK); - osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK); -} +//void draw_reset_bars(void) { // TARGET_64 only +// Stubbed. Only N64 target uses this +// } void rendering_init(void) { gGfxPool = &gGfxPools[0]; @@ -626,16 +596,12 @@ void setup_game_memory(void) { load_segment_decompress(2, _segment2_mio0SegmentRomStart, _segment2_mio0SegmentRomEnd); } -#ifndef TARGET_N64 + static struct LevelCommand *levelCommandAddr; -#endif // main game loop thread. runs forever as long as the game // continues. void thread5_game_loop(UNUSED void *arg) { -#ifdef TARGET_N64 - struct LevelCommand *levelCommandAddr; -#endif setup_game_memory(); #ifdef VERSION_SH @@ -655,32 +621,21 @@ void thread5_game_loop(UNUSED void *arg) { play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); set_sound_mode(save_file_get_sound_mode()); -#ifdef TARGET_N64 - func_80247ED8(); - rendering_init(); - - while (1) { -#else gGlobalTimer++; } void game_loop_one_iteration(void) { -#endif // if the reset timer is active, run the process to reset the game. - if (gResetTimer) { + //if (gResetTimer) { +// draw_reset_bars(); (N64 target only?) +//} -#ifdef TARGET_N64 - draw_reset_bars(); - continue; -#else - return; -#endif - } profiler_log_thread5_time(THREAD5_START); // if any controllers are plugged in, start read the data for when // read_controller_inputs is called later. if (gControllerBits) { + #ifdef VERSION_SH block_until_rumble_pak_free(); #endif @@ -699,7 +654,5 @@ void game_loop_one_iteration(void) { // amount of free space remaining. print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead); } -#ifdef TARGET_N64 - } -#endif +// } was here for ifdef targ 64 } diff --git a/src/game/game_init.h b/src/game/game_init.h index 68db7426..10dd2f86 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]; @@ -71,7 +71,7 @@ extern void clear_viewport(Vp *, s32); void make_viewport_clip_rect(Vp *viewport); extern void init_render_image(void); extern void end_master_display_list(void); -extern void draw_reset_bars(void); +//extern void draw_reset_bars(void); Target_64 only. Not used extern void rendering_init(void); extern void config_gfx_pool(void); extern void display_and_vsync(void); diff --git a/src/game/geo_misc.c b/src/game/geo_misc.c index af0cfa6f..afd5e289 100644 --- a/src/game/geo_misc.c +++ b/src/game/geo_misc.c @@ -46,11 +46,8 @@ s8 gFlyingCarpetState; * * Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5. */ -#ifdef TARGET_N64 -void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) { -#else void make_vertex(Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) { -#endif + vtx[n].v.ob[0] = x; vtx[n].v.ob[1] = y; vtx[n].v.ob[2] = z; diff --git a/src/game/geo_misc.h b/src/game/geo_misc.h index 5646568d..fde7095e 100644 --- a/src/game/geo_misc.h +++ b/src/game/geo_misc.h @@ -12,15 +12,9 @@ enum FlyingCarpetState extern s8 gFlyingCarpetState; -#ifdef TARGET_N64 -extern void make_vertex( - Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a -); -#else extern void make_vertex( Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a ); -#endif extern s16 round_float(f32); extern Gfx *geo_exec_inside_castle_light(s32 callContext, struct GraphNode *node, f32 mtx[4][4]); extern Gfx *geo_exec_flying_carpet_timer_update(s32 callContext, struct GraphNode *node, diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index bfcbf42b..f1336559 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -131,14 +131,7 @@ void create_dl_identity_matrix(void) { return; } -#ifdef TARGET_N64 - matrix->m[0][0] = 0x00010000; matrix->m[1][0] = 0x00000000; matrix->m[2][0] = 0x00000000; matrix->m[3][0] = 0x00000000; - matrix->m[0][1] = 0x00000000; matrix->m[1][1] = 0x00010000; matrix->m[2][1] = 0x00000000; matrix->m[3][1] = 0x00000000; - matrix->m[0][2] = 0x00000001; matrix->m[1][2] = 0x00000000; matrix->m[2][2] = 0x00000000; matrix->m[3][2] = 0x00000000; - matrix->m[0][3] = 0x00000000; matrix->m[1][3] = 0x00000001; matrix->m[2][3] = 0x00000000; matrix->m[3][3] = 0x00000000; -#else guMtxIdent(matrix); -#endif gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); @@ -1802,25 +1795,18 @@ void render_dialog_entries(void) { render_dialog_box_type(dialog, dialog->linesPerBox); gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, -#ifdef TARGET_N64 - ensure_nonnegative(dialog->leftOffset), -#else + 0, -#endif ensure_nonnegative(DIAG_VAL2 - dialog->width), #ifdef VERSION_EU -#ifdef TARGET_N64 - ensure_nonnegative(dialog->leftOffset + DIAG_VAL3 / gDialogBoxScale), -#else + SCREEN_WIDTH, -#endif + ensure_nonnegative((240 - dialog->width) + ((dialog->linesPerBox * 80) / DIAG_VAL4) / gDialogBoxScale)); #else -#ifdef TARGET_N64 - ensure_nonnegative(DIAG_VAL3 + dialog->leftOffset), -#else + SCREEN_WIDTH, -#endif + ensure_nonnegative(240 + ((dialog->linesPerBox * 80) / DIAG_VAL4) - dialog->width)); #endif #if defined(VERSION_JP) || defined(VERSION_SH) @@ -2133,12 +2119,9 @@ void shade_screen(void) { // This is a bit weird. It reuses the dialog text box (width 130, height -80), // so scale to at least fit the screen. -#ifdef TARGET_N64 - create_dl_scale_matrix(MENU_MTX_NOPUSH, 2.6f, 3.4f, 1.0f); -#else + create_dl_scale_matrix(MENU_MTX_NOPUSH, GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT / 130.0f, 3.0f, 1.0f); -#endif gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 110); gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box); diff --git a/src/game/macro_special_objects.c b/src/game/macro_special_objects.c index 63c63d3b..d9318971 100644 --- a/src/game/macro_special_objects.c +++ b/src/game/macro_special_objects.c @@ -328,7 +328,7 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) { } } -#ifndef TARGET_N64 +// PC Port, so always use below u32 get_special_objects_size(s16 *data) { s16 *startPos = data; s32 numOfSpecialObjects; @@ -372,4 +372,3 @@ u32 get_special_objects_size(s16 *data) { return data - startPos; } -#endif diff --git a/src/game/macro_special_objects.h b/src/game/macro_special_objects.h index 33fee18c..37851cc9 100644 --- a/src/game/macro_special_objects.h +++ b/src/game/macro_special_objects.h @@ -16,8 +16,6 @@ extern void spawn_macro_abs_special(u32 model, const BehaviorScript *behavior, s extern void spawn_macro_objects(s16 areaIndex, s16 * macroObjList); extern void spawn_macro_objects_hardcoded(s16 areaIndex, s16 * macroObjList); extern void spawn_special_objects(s16 areaIndex, s16 ** specialObjList); -#ifndef TARGET_N64 extern u32 get_special_objects_size(s16 *data); -#endif #endif /* MACRO_SPECIAL_OBJECTS_H */ diff --git a/src/game/memory.c b/src/game/memory.c index da4107fc..14c332cc 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -1,7 +1,5 @@ #include -#ifndef TARGET_N64 #include -#endif #include "sm64.h" @@ -78,27 +76,6 @@ void *get_segment_base_addr(s32 segment) { return (void *) (sSegmentTable[segment] | 0x80000000); } -#ifdef TARGET_N64 -void *segmented_to_virtual(const void *addr) { - size_t segment = (uintptr_t) addr >> 24; - size_t offset = (uintptr_t) addr & 0x00FFFFFF; - - return (void *) ((sSegmentTable[segment] + offset) | 0x80000000); -} - -void *virtual_to_segmented(u32 segment, const void *addr) { - size_t offset = ((uintptr_t) addr & 0x1FFFFFFF) - sSegmentTable[segment]; - - return (void *) ((segment << 24) + offset); -} - -void move_segment_table_to_dmem(void) { - s32 i; - - for (i = 0; i < 16; i++) - gSPSegment(gDisplayListHead++, i, sSegmentTable[i]); -} -#else void *segmented_to_virtual(const void *addr) { return (void *) addr; } @@ -109,7 +86,7 @@ void *virtual_to_segmented(u32 segment, const void *addr) { void move_segment_table_to_dmem(void) { } -#endif + /** * Initialize the main memory pool. This pool is conceptually a pair of stacks @@ -248,22 +225,8 @@ u32 main_pool_pop_state(void) { */ static void dma_read(u8 *dest, u8 *srcStart, u8 *srcEnd) { u32 size = ALIGN16(srcEnd - srcStart); -#ifdef TARGET_N64 - osInvalDCache(dest, size); - while (size != 0) { - u32 copySize = (size >= 0x1000) ? 0x1000 : size; - osPiStartDma(&gDmaIoMesg, OS_MESG_PRI_NORMAL, OS_READ, (uintptr_t) srcStart, dest, copySize, - &gDmaMesgQueue); - osRecvMesg(&gDmaMesgQueue, &D_80339BEC, OS_MESG_BLOCK); - - dest += copySize; - srcStart += copySize; - size -= copySize; - } -#else memcpy(dest, srcStart, srcEnd - srcStart); -#endif } /** @@ -281,103 +244,6 @@ static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) { return dest; } -#ifdef TARGET_N64 -/** - * Load data from ROM into a newly allocated block, and set the segment base - * address to this block. - */ -void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side) { - void *addr = dynamic_dma_read(srcStart, srcEnd, side); - - if (addr != NULL) { - set_segment_base_addr(segment, addr); - } - return addr; -} - -/* - * Allocate a block of memory starting at destAddr and ending at the righthand - * end of the memory pool. Then copy srcStart through srcEnd from ROM to this - * block. - * If this block is not large enough to hold the ROM data, or that portion - * of the pool is already allocated, return NULL. - */ -void *load_to_fixed_pool_addr(u8 *destAddr, u8 *srcStart, u8 *srcEnd) { - void *dest = NULL; - u32 srcSize = ALIGN16(srcEnd - srcStart); - u32 destSize = ALIGN16((u8 *) sPoolListHeadR - destAddr); - - if (srcSize <= destSize) { - dest = main_pool_alloc(destSize, MEMORY_POOL_RIGHT); - if (dest != NULL) { - bzero(dest, destSize); - osWritebackDCacheAll(); - dma_read(dest, srcStart, srcEnd); - osInvalICache(dest, destSize); - osInvalDCache(dest, destSize); - } - } else { - } - return dest; -} - -/** - * Decompress the block of ROM data from srcStart to srcEnd and return a - * pointer to an allocated buffer holding the decompressed data. Set the - * base address of segment to this address. - */ -void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd) { - void *dest = NULL; - - u32 compSize = ALIGN16(srcEnd - srcStart); - u8 *compressed = main_pool_alloc(compSize, MEMORY_POOL_RIGHT); - - // Decompressed size from mio0 header - u32 *size = (u32 *) (compressed + 4); - - if (compressed != NULL) { - dma_read(compressed, srcStart, srcEnd); - dest = main_pool_alloc(*size, MEMORY_POOL_LEFT); - if (dest != NULL) { - decompress(compressed, dest); - set_segment_base_addr(segment, dest); - main_pool_free(compressed); - } else { - } - } else { - } - return dest; -} - -void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd) { - UNUSED void *dest = NULL; - u32 compSize = ALIGN16(srcEnd - srcStart); - u8 *compressed = main_pool_alloc(compSize, MEMORY_POOL_RIGHT); - UNUSED u32 *pUncSize = (u32 *) (compressed + 4); - - if (compressed != NULL) { - dma_read(compressed, srcStart, srcEnd); - decompress(compressed, gDecompressionHeap); - set_segment_base_addr(segment, gDecompressionHeap); - main_pool_free(compressed); - } else { - } - return gDecompressionHeap; -} - -void load_engine_code_segment(void) { - void *startAddr = (void *) SEG_ENGINE; - u32 totalSize = SEG_FRAMEBUFFERS - SEG_ENGINE; - UNUSED u32 alignedSize = ALIGN16(_engineSegmentRomEnd - _engineSegmentRomStart); - - bzero(startAddr, totalSize); - osWritebackDCacheAll(); - dma_read(startAddr, _engineSegmentRomStart, _engineSegmentRomEnd); - osInvalICache(startAddr, totalSize); - osInvalDCache(startAddr, totalSize); -} -#endif - /** * Allocate an allocation-only pool from the main pool. This pool doesn't * support freeing allocated memory. diff --git a/src/game/memory.h b/src/game/memory.h index b392728e..0639ccef 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -37,19 +37,11 @@ u32 main_pool_available(void); u32 main_pool_push_state(void); u32 main_pool_pop_state(void); -#ifdef TARGET_N64 -void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side); -void *load_to_fixed_pool_addr(u8 *destAddr, u8 *srcStart, u8 *srcEnd); -void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd); -void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd); -void load_engine_code_segment(void); -#else #define load_segment(...) #define load_to_fixed_pool_addr(...) #define load_segment_decompress(...) #define load_segment_decompress_heap(...) #define load_engine_code_segment(...) -#endif struct AllocOnlyPool *alloc_only_pool_init(u32 size, u32 side); void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size); diff --git a/src/game/print.c b/src/game/print.c index 42395b5f..56ab66d3 100644 --- a/src/game/print.c +++ b/src/game/print.c @@ -366,29 +366,6 @@ void add_glyph_texture(s8 glyphIndex) { gSPDisplayList(gDisplayListHead++, dl_hud_img_load_tex_block); } -#ifdef TARGET_N64 -/** - * Clips textrect into the boundaries defined. - */ -void clip_to_bounds(s32 *x, s32 *y) { - if (*x < TEXRECT_MIN_X) { - *x = TEXRECT_MIN_X; - } - - if (*x > TEXRECT_MAX_X) { - *x = TEXRECT_MAX_X; - } - - if (*y < TEXRECT_MIN_Y) { - *y = TEXRECT_MIN_Y; - } - - if (*y > TEXRECT_MAX_Y) { - *y = TEXRECT_MAX_Y; - } -} -#endif - /** * Renders the glyph that's set at the given position. */ @@ -398,9 +375,6 @@ void render_textrect(s32 x, s32 y, s32 pos) { s32 rectX; s32 rectY; -#ifdef TARGET_N64 - clip_to_bounds(&rectBaseX, &rectBaseY); -#endif rectX = rectBaseX; rectY = rectBaseY; gSPTextureRectangle(gDisplayListHead++, rectX << 2, rectY << 2, (rectX + 15) << 2, diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 93a9a8a3..d83616d5 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -506,11 +506,7 @@ static void geo_process_background(struct GraphNodeBackground *node) { if (list != 0) { geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(list), node->fnNode.node.flags >> 8); } else if (gCurGraphNodeMasterList != NULL) { -#ifdef TARGET_N64 - Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 7); -#else Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 8); -#endif Gfx *gfx = gfxStart; gDPPipeSync(gfx++); @@ -757,9 +753,7 @@ static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) { // the amount of units between the center of the screen and the horizontal edge // given the distance from the object to the camera. -#ifndef TARGET_N64 hScreenEdge *= GFX_DIMENSIONS_ASPECT_RATIO; -#endif if (geo != NULL && geo->type == GRAPH_NODE_TYPE_CULLING_RADIUS) { cullingRadius = diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c index b0c14776..c009abea 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c @@ -241,13 +241,10 @@ int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct Wa } Gfx *render_cannon_circle_base(void) { -#ifdef TARGET_N64 - Vtx *verts = alloc_display_list(4 * sizeof(*verts)); - Gfx *dlist = alloc_display_list(16 * sizeof(*dlist)); -#else + Vtx *verts = alloc_display_list(8 * sizeof(*verts)); Gfx *dlist = alloc_display_list(20 * sizeof(*dlist)); -#endif + Gfx *g = dlist; if (verts != NULL && dlist != NULL) { @@ -256,12 +253,10 @@ Gfx *render_cannon_circle_base(void) { make_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192, 0, 0, 0, 255); make_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192, 0, 0, 0, 255); -#ifndef TARGET_N64 make_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); make_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); make_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); make_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); -#endif gSPDisplayList(g++, dl_proj_mtx_fullscreen); gDPSetCombineMode(g++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); @@ -272,12 +267,12 @@ Gfx *render_cannon_circle_base(void) { gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); gSPDisplayList(g++, dl_draw_quad_verts_0123); gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); -#ifndef TARGET_N64 + gDPSetCombineMode(g++, G_CC_SHADE, G_CC_SHADE); gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts + 4), 4, 4); gSP2Triangles(g++, 4, 0, 3, 0, 4, 3, 7, 0); gSP2Triangles(g++, 1, 5, 6, 0, 1, 6, 2, 0); -#endif + gSPDisplayList(g++, dl_screen_transition_end); gSPEndDisplayList(g); } else { diff --git a/src/game/skybox.c b/src/game/skybox.c index 76f93201..d1f49908 100644 --- a/src/game/skybox.c +++ b/src/game/skybox.c @@ -242,7 +242,6 @@ void *create_skybox_ortho_matrix(s8 player) { f32 top = sSkyBoxInfo[player].scaledY; Mtx *mtx = alloc_display_list(sizeof(*mtx)); -#ifndef TARGET_N64 f32 half_width = (4.0f / 3.0f) / GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_WIDTH / 2; f32 center = (sSkyBoxInfo[player].scaledX + SCREEN_WIDTH / 2); if (half_width < SCREEN_WIDTH / 2) { @@ -250,7 +249,6 @@ void *create_skybox_ortho_matrix(s8 player) { left = center - half_width; right = center + half_width; } -#endif if (mtx != NULL) { guOrtho(mtx, left, right, bottom, top, 0.0f, 3.0f, 1.0f); diff --git a/src/goddard/renderer.c b/src/goddard/renderer.c index b5b7fafb..6264bb66 100644 --- a/src/goddard/renderer.c +++ b/src/goddard/renderer.c @@ -27,15 +27,9 @@ #define MAX_GD_DLS 1000 #define OS_MESG_SI_COMPLETE 0x33333333 -#ifdef TARGET_N64 -#define GD_VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr) &0x0FFFFFFF) -#define GD_LOWER_24(addr) ((uintptr_t)(addr) &0x00FFFFFF) -#define GD_LOWER_29(addr) (((uintptr_t)(addr)) & 0x1FFFFFFF) -#else #define GD_VIRTUAL_TO_PHYSICAL(addr) (addr) #define GD_LOWER_24(addr) ((uintptr_t)(addr)) #define GD_LOWER_29(addr) (((uintptr_t)(addr))) -#endif #define MTX_INTPART_PACK(w1, w2) (((w1) &0xFFFF0000) | (((w2) >> 16) & 0xFFFF)) #define MTX_FRACPART_PACK(w1, w2) ((((w1) << 16) & 0xFFFF0000) | ((w2) &0xFFFF)) @@ -1691,27 +1685,9 @@ u32 Unknown8019EC88(Gfx *dl, UNUSED s32 arg1) { /* 24D4C4 -> 24D63C; orig name: func_8019ECF4 */ void mat4_to_mtx(const Mat4f *src, Mtx *dst) { -#ifdef TARGET_N64 - s32 i; // 14 - s32 j; // 10 - s32 w1; - s32 w2; - s32 *mtxInt = (s32 *) dst->m[0]; // s32 part - s32 *mtxFrc = (s32 *) dst->m[2]; // frac part - for (i = 0; i < 4; i++) { - for (j = 0; j < 2; j++) { - w1 = (s32)((*src)[i][j * 2] * 65536.0f); - w2 = (s32)((*src)[i][j * 2 + 1] * 65536.0f); - *mtxInt = MTX_INTPART_PACK(w1, w2); - mtxInt++; - *mtxFrc = MTX_FRACPART_PACK(w1, w2); - mtxFrc++; - } - } -#else guMtxF2L(src, dst); -#endif + } /* 24D63C -> 24D6E4; orig name: func_8019EE6C */ @@ -3632,89 +3608,9 @@ void Unknown801A6E30(UNUSED u32 a0) { void Unknown801A6E44(UNUSED u32 a0) { } -#ifdef TARGET_N64 -/* 255628 -> 255704; orig name: func_801A6E58 */ -void gd_block_dma(u32 devAddr, void *vAddr, s32 size) { - s32 transfer; // 2c - - do { - if ((transfer = size) > 0x1000) { - transfer = 0x1000; - } - - osPiStartDma(&D_801BE980, OS_MESG_PRI_NORMAL, OS_READ, devAddr, vAddr, transfer, &sGdDMAQueue); - osRecvMesg(&sGdDMAQueue, &D_801BE97C, OS_MESG_BLOCK); - devAddr += transfer; - vAddr = (void *) ((uintptr_t) vAddr + transfer); - size -= 0x1000; - } while (size > 0); -} - -/* 255704 -> 255988 */ -struct GdObj *load_dynlist(struct DynList *dynlist) { - u32 segSize; // 4c - u8 *allocSegSpace; // 48 - void *allocPtr; // 44 - uintptr_t dynlistSegStart; // 40 - uintptr_t dynlistSegEnd; // 3c - s32 i; // 38 - s32 sp34; // tlbPage - struct GdObj *loadedList; // 30 - - i = -1; - - while (sDynLists[++i].list != NULL) { - if (sDynLists[i].list == dynlist) { - break; - } - } - - if (sDynLists[i].list == NULL) { - fatal_printf("load_dynlist() ptr not found in any banks"); - } - - switch (sDynLists[i].flag) { - case STD_LIST_BANK: - dynlistSegStart = (uintptr_t) _gd_dynlistsSegmentRomStart; - dynlistSegEnd = (uintptr_t) _gd_dynlistsSegmentRomEnd; - break; - default: - fatal_printf("load_dynlist() unkown bank"); - } - - segSize = dynlistSegEnd - dynlistSegStart; - allocSegSpace = gd_malloc_temp(segSize + 0x10000); - - if ((allocPtr = (void *) allocSegSpace) == NULL) { - fatal_printf("Not enough DRAM for DATA segment \n"); - } - - allocSegSpace = (u8 *) (((uintptr_t) allocSegSpace + 0x10000) & 0xFFFF0000); - gd_block_dma(dynlistSegStart, (void *) allocSegSpace, segSize); - osUnmapTLBAll(); - - sp34 = (segSize / 0x10000) / 2 + 1; //? has to be written this way - if (sp34 >= 31) { - fatal_printf("load_dynlist() too many TLBs"); - } - - for (i = 0; i < sp34; i++) { - osMapTLB(i, OS_PM_64K, (void *) (uintptr_t) (0x04000000 + (i * 2 * 0x10000)), - GD_LOWER_24(((uintptr_t) allocSegSpace) + (i * 2 * 0x10000)), - GD_LOWER_24(((uintptr_t) allocSegSpace) + (i * 2 * 0x10000) + 0x10000), -1); - } - - loadedList = proc_dynlist(dynlist); - gd_free(allocPtr); - osUnmapTLBAll(); - - return loadedList; -} -#else struct GdObj *load_dynlist(struct DynList *dynlist) { return proc_dynlist(dynlist); } -#endif /* 255988 -> 25599C */ void stub_801A71B8(UNUSED u32 a0) { diff --git a/src/goddard/skin.c b/src/goddard/skin.c index 5223c246..59779177 100644 --- a/src/goddard/skin.c +++ b/src/goddard/skin.c @@ -303,9 +303,7 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) { u8 nx, ny, nz; // 24, 25, 26 UNUSED u32 pad20; register struct VtxLink *vtxlink; // a1 -#ifdef TARGET_N64 - register s16 *vnPos; // a2 -#endif + register s16 x; // a3 register s16 y; // t0 register s16 z; // t1 @@ -325,18 +323,12 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) { nz = (u8)(vtx->normal.z * 255.0f); for (vtxlink = vtx->gbiVerts; vtxlink != NULL; vtxlink = vtxlink->prev) { -#ifdef TARGET_N64 - vnPos = vtxlink->data->n.ob; - vn = vtxlink->data; - *vnPos++ = x; - *vnPos++ = y; - *vnPos++ = z; -#else + vn = vtxlink->data; vn->n.ob[0] = x; vn->n.ob[1] = y; vn->n.ob[2] = z; -#endif + vn->n.n[0] = nx; vn->n.n[1] = ny; vn->n.n[2] = nz; @@ -348,9 +340,7 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) { void convert_gd_verts_to_Vtx(struct ObjGroup *grp) { UNUSED u32 pad24[6]; register struct VtxLink *vtxlink; // a1 -#ifdef TARGET_N64 - register s16 *vtxcoords; // a2 -#endif + register s16 x; // a3 register s16 y; // t0 register s16 z; // t1 @@ -366,16 +356,10 @@ void convert_gd_verts_to_Vtx(struct ObjGroup *grp) { z = (s16) vtx->pos.z; for (vtxlink = vtx->gbiVerts; vtxlink != NULL; vtxlink = vtxlink->prev) { -#ifdef TARGET_N64 - vtxcoords = vtxlink->data->v.ob; - vtxcoords[0] = x; - vtxcoords[1] = y; - vtxcoords[2] = z; -#else + vtxlink->data->v.ob[0] = x; vtxlink->data->v.ob[1] = y; vtxlink->data->v.ob[2] = z; -#endif } } } From 829c1f29a8a7b5626a343ba26bcd499e51b56c94 Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Thu, 14 May 2020 05:18:12 -0400 Subject: [PATCH 07/86] Fixed more border-related code and fixes to N64 build removal --- Makefile | 38 ++++++++++++++++++-------------------- include/config.h | 9 ++------- include/gfx_dimensions.h | 4 ++-- src/game/game_init.c | 8 +++++--- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index d4bd2846..b3bafd9a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ + # Makefile to rebuild SM64 split image ### Default target ### @@ -23,7 +24,7 @@ TARGET_N64 = 0 # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 # Compiler to use (ido or gcc) -COMPILER ?= ido +# COMPILER ?= ido // Old Default # Disable better camera by default BETTERCAMERA ?= 0 @@ -224,10 +225,6 @@ GODDARD_SRC_DIRS := src/goddard src/goddard/dynlists MIPSISET := -mips2 MIPSBIT := -32 -ifeq ($(COMPILER),gcc) - MIPSISET := -mips3 -endif - ifeq ($(VERSION),eu) OPT_FLAGS := -O2 else @@ -246,9 +243,8 @@ ifeq ($(TARGET_WEB),1) endif # Use a default opt flag for gcc, then override if RPi -ifeq ($(COMPILER),gcc) -OPT_FLAGS := -O2 # Breaks sound on x86? -endif + +# OPT_FLAGS := -O2 # "Whole-compile optimization flag" Breaks sound on x86. ifeq ($(TARGET_RPI),1) machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') @@ -424,14 +420,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 +436,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 +453,17 @@ 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 +ifeq ($(WINDOWS_CONSOLE),1) +LDFLAGS += -mconsole +endif 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 @@ -676,7 +676,6 @@ $(BUILD_DIR)/assets/mario_anim_data.c: $(wildcard assets/anims/*.inc.c) $(BUILD_DIR)/assets/demo_data.c: assets/demo_data.json $(wildcard assets/demos/*.bin) $(PYTHON) tools/demo_data_converter.py assets/demo_data.json $(VERSION_CFLAGS) > $@ -ifeq ($(COMPILER),ido) # Source code $(BUILD_DIR)/levels/%/leveldata.o: OPT_FLAGS := -g $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -g @@ -718,7 +717,6 @@ $(BUILD_DIR)/src/audio/%.acpp: src/audio/%.c $(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/lib/copt -signed -I=$< -CMP=$@ -cp=i -scalaroptimize=1 endif -endif # Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes. diff --git a/include/config.h b/include/config.h index db50b1cc..23a317e8 100644 --- a/include/config.h +++ b/include/config.h @@ -28,12 +28,7 @@ #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 -// Border Height Define for NTSC Versions - -#define BORDER_HEIGHT 1 - -#else -// What's the point of having a border? -#define BORDER_HEIGHT 0 +// What's the point of having a border if we're not an N64? +#define BORDER_HEIGHT 0 // Never use a border as not-N64 #endif diff --git a/include/gfx_dimensions.h b/include/gfx_dimensions.h index cae20701..f3a5ee23 100644 --- a/include/gfx_dimensions.h +++ b/include/gfx_dimensions.h @@ -5,8 +5,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) #endif diff --git a/src/game/game_init.c b/src/game/game_init.c index 8834fc8b..ffcf7a18 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -3,6 +3,7 @@ #include "sm64.h" #include "audio/external.h" #include "buffers/buffers.h" +#include "gfx_dimensions.h" #include "buffers/gfx_output_buffer.h" #include "buffers/framebuffers.h" #include "buffers/zbuffer.h" @@ -152,8 +153,9 @@ void clear_frame_buffer(s32 a) { gDPSetCycleType(gDisplayListHead++, G_CYC_FILL); gDPSetFillColor(gDisplayListHead++, a); - gDPFillRectangle(gDisplayListHead++, 0, BORDER_HEIGHT, SCREEN_WIDTH - 1, - SCREEN_HEIGHT - 1 - BORDER_HEIGHT); + + // Ratio-correct borderfill + gDPFillRectangle(gDisplayListHead++, GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), BORDER_HEIGHT, GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - BORDER_HEIGHT - 1); gDPPipeSync(gDisplayListHead++); @@ -495,7 +497,7 @@ void read_controller_inputs(void) { controller->stickMag = 0; } } - + } #else for (i = 0; i < 2; i++) { From 87dac5d916bddb50f5193d96db09f1ddbd0b61ab Mon Sep 17 00:00:00 2001 From: uwabami Date: Thu, 14 May 2020 16:11:59 +0200 Subject: [PATCH 08/86] 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 09/86] 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 10/86] 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 11/86] 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 12/86] 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 13/86] 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 14/86] 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 15/86] 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 16/86] 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 17/86] 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 18/86] 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 19/86] 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 20/86] 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 21/86] 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 22/86] 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 23/86] 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 24/86] 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 25/86] 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 26/86] 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 27/86] 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 28/86] 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 29/86] 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 30/86] 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 31/86] 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 32/86] 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 33/86] 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 34/86] 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 35/86] 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 36/86] 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 37/86] 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 38/86] 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 39/86] 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 40/86] 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 41/86] 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 42/86] 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 43/86] 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 44/86] 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 45/86] 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 46/86] 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 47/86] 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 48/86] 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 49/86] 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 50/86] 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 51/86] 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 52/86] 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 53/86] 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 54/86] 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 55/86] 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 56/86] 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 57/86] 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 58/86] 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 59/86] 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 60/86] 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 61/86] 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 62/86] 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 63/86] 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 64/86] 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 65/86] 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 66/86] 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 67/86] 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 68/86] 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 f4a3757145a508fa9338562b6524f488b0a0c492 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 16:16:44 -0300 Subject: [PATCH 69/86] Further fixes to MXE compilation Adds on the work of PR #130. --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 91049539..a0dd34c5 100644 --- a/Makefile +++ b/Makefile @@ -423,7 +423,13 @@ else endif ifeq ($(WINDOWS_BUILD),1) - LD := $(CXX) + ifeq ($(CROSS),i686-w64-mingw32.static-) # fixes compilation in MXE on Linux and WSL + LD := $(CC) + else ifeq ($(CROSS),x86_64-w64-mingw32.static-) + LD := $(CC) + else + LD := $(CXX) + endif else LD := $(CC) endif 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 70/86] 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 5dd43ad674da23a86067f6b484d9467d15573b5b Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Sat, 16 May 2020 15:30:27 -0400 Subject: [PATCH 71/86] OSX_BUILD cleaned commit --- Makefile | 42 +++++++++++++------- include/PR/os_libc.h | 5 +++ lib/src/ldiv.c | 2 + lib/src/math/cosf.c | 3 ++ src/pc/gfx/gfx_opengl.c | 30 +++++++++++--- src/pc/gfx/gfx_sdl2.c | 24 ++++++----- tools/Makefile | 9 ++++- tools/n64graphics_ci_dir/exoquant/exoquant.c | 6 ++- 8 files changed, 89 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 91049539..19f42e56 100644 --- a/Makefile +++ b/Makefile @@ -22,8 +22,9 @@ TARGET_N64 = 0 # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 -# Compiler to use (ido or gcc) -COMPILER ?= ido + +# Makeflag to enable OSX fixes +OSX_BUILD ?= 0 # Disable better camera by default BETTERCAMERA ?= 0 @@ -141,6 +142,10 @@ ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints VERSION_CFLAGS += -DUSE_GLES endif +ifeq ($(OSX_BUILD),1) # Modify GFX & SDL2 for OSX GL + VERSION_CFLAGS += -DOSX_BUILD +endif + VERSION_ASFLAGS := --defsym AVOID_UB=1 COMPARE := 0 @@ -167,7 +172,7 @@ endif endif # Make tools if out of date -DUMMY != make -s -C tools >&2 || echo FAIL +DUMMY != make -C tools >&2 || echo FAIL ifeq ($(DUMMY),FAIL) $(error Failed to build tools) endif @@ -228,10 +233,6 @@ GODDARD_SRC_DIRS := src/goddard src/goddard/dynlists MIPSISET := -mips2 MIPSBIT := -32 -ifeq ($(COMPILER),gcc) - MIPSISET := -mips3 -endif - ifeq ($(VERSION),eu) OPT_FLAGS := -O2 else @@ -250,9 +251,8 @@ ifeq ($(TARGET_WEB),1) endif # Use a default opt flag for gcc, then override if RPi -ifeq ($(COMPILER),gcc) -OPT_FLAGS := -O2 # Breaks sound on x86? -endif +# OPT_FLAGS := -O2 # -O2 opt breaks sound on x86? + ifeq ($(TARGET_RPI),1) machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') @@ -415,6 +415,10 @@ ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth AS := as +ifeq ($(OSX_BUILD),1) +AS := i686-w64-mingw32-as +endif + ifneq ($(TARGET_WEB),1) # As in, not-web PC port CC := $(CROSS)gcc CXX := $(CROSS)g++ @@ -431,11 +435,19 @@ endif ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL CPP := cpp -P OBJCOPY := objcopy + OBJDUMP := $(CROSS)objdump else +ifeq ($(OSX_BUILD),1) + CPP := cpp-9 -P + OBJDUMP := i686-w64-mingw32-objdump + OBJCOPY := i686-w64-mingw32-objcopy +else # Linux & other builds CPP := $(CROSS)cpp -P OBJCOPY := $(CROSS)objcopy + OBJDUMP := $(CROSS)objdump endif -OBJDUMP := $(CROSS)objdump +endif + PYTHON := python3 SDLCONFIG := $(CROSS)sdl2-config @@ -498,9 +510,12 @@ else ifeq ($(TARGET_RPI),1) # Linux / Other builds below LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(SDLCONFIG) --libs` -no-pie else +ifeq ($(OSX_BUILD),1) +LDFLAGS := -lm -framework OpenGL `$(SDLCONFIG) --libs` -no-pie -lpthread `pkg-config --libs libusb-1.0 glfw3 glew` +else LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm -lGL `$(SDLCONFIG) --libs` -no-pie -lpthread endif - +endif # End of LDFLAGS # Prevent a crash with -sopt export LANG := C @@ -711,7 +726,6 @@ $(BUILD_DIR)/assets/mario_anim_data.c: $(wildcard assets/anims/*.inc.c) $(BUILD_DIR)/assets/demo_data.c: assets/demo_data.json $(wildcard assets/demos/*.bin) $(PYTHON) tools/demo_data_converter.py assets/demo_data.json $(VERSION_CFLAGS) > $@ -ifeq ($(COMPILER),ido) # Source code $(BUILD_DIR)/levels/%/leveldata.o: OPT_FLAGS := -g $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -g @@ -753,8 +767,6 @@ $(BUILD_DIR)/src/audio/%.acpp: src/audio/%.c $(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/lib/copt -signed -I=$< -CMP=$@ -cp=i -scalaroptimize=1 endif -endif - # Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes. $(GLOBAL_ASM_O_FILES): $(GLOBAL_ASM_DEP).$(NON_MATCHING) diff --git a/include/PR/os_libc.h b/include/PR/os_libc.h index 94111c0b..987abefe 100644 --- a/include/PR/os_libc.h +++ b/include/PR/os_libc.h @@ -3,8 +3,13 @@ #include "ultratypes.h" +#ifdef OSX_BUILD +#include // OSX doesn't like it not being included? +#else + // Old deprecated functions from strings.h, replaced by memcpy/memset. extern void bcopy(const void *, void *, size_t); extern void bzero(void *, size_t); +#endif #endif /* !_OS_LIBC_H_ */ diff --git a/lib/src/ldiv.c b/lib/src/ldiv.c index 01b04be2..b7c28efa 100644 --- a/lib/src/ldiv.c +++ b/lib/src/ldiv.c @@ -1,6 +1,7 @@ #include "libultra_internal.h" #include +#ifndef OSX_BUILD lldiv_t lldiv(long long num, long long denom) { lldiv_t ret; @@ -13,6 +14,7 @@ lldiv_t lldiv(long long num, long long denom) { return ret; } +#endif // OSX_BUILD cannot use this ldiv_t ldiv(long num, long denom) { ldiv_t ret; diff --git a/lib/src/math/cosf.c b/lib/src/math/cosf.c index 2b01c12a..f1130b44 100644 --- a/lib/src/math/cosf.c +++ b/lib/src/math/cosf.c @@ -33,6 +33,7 @@ static const du pilo = { static const fu zero = {0.0}; extern const fu NAN; +#ifndef OSX_BUILD float cosf(float x) { double dx; // double x @@ -92,3 +93,5 @@ float cosf(float x) return zero.f; } +#endif // OSX_BUILD cannot use this + diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index b7067e91..1e323a1a 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -18,12 +18,19 @@ #include #define GL_GLEXT_PROTOTYPES 1 #include + #else #include #define GL_GLEXT_PROTOTYPES 1 + +#ifdef OSX_BUILD +#include +#else #include #endif +#endif + #include "gfx_cc.h" #include "gfx_rendering_api.h" @@ -49,7 +56,7 @@ static bool gfx_opengl_z_is_from_0_to_1(void) { static void gfx_opengl_vertex_array_set_attribs(struct ShaderProgram *prg) { size_t num_floats = prg->num_floats; size_t pos = 0; - + for (int i = 0; i < prg->num_attribs; i++) { glEnableVertexAttribArray(prg->attrib_locations[i]); glVertexAttribPointer(prg->attrib_locations[i], prg->attrib_sizes[i], GL_FLOAT, GL_FALSE, num_floats * sizeof(float), (void *)(pos * sizeof(float))); @@ -179,15 +186,19 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad bool do_multiply[2] = {c[0][1] == 0 && c[0][3] == 0, c[1][1] == 0 && c[1][3] == 0}; bool do_mix[2] = {c[0][1] == c[0][3], c[1][1] == c[1][3]}; bool color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff); - + char vs_buf[1024]; char fs_buf[1024]; size_t vs_len = 0; size_t fs_len = 0; size_t num_floats = 4; - + // Vertex shader +#ifdef OSX_BUILD + append_line(vs_buf, &vs_len, ""); +#else append_line(vs_buf, &vs_len, "#version 100"); +#endif append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;"); if (used_textures[0] || used_textures[1]) { append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;"); @@ -216,10 +227,15 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad } append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;"); append_line(vs_buf, &vs_len, "}"); - + // Fragment shader +#ifdef OSX_BUILD + append_line(fs_buf, &fs_len, ""); +#else append_line(fs_buf, &fs_len, "#version 100"); append_line(fs_buf, &fs_len, "precision mediump float;"); +#endif + if (used_textures[0] || used_textures[1]) { append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;"); } @@ -464,7 +480,11 @@ static void gfx_opengl_init(void) { #if FOR_WINDOWS glewInit(); #endif - + +#ifdef OSX_BUILD + glewInit(); +#endif + glGenBuffers(1, &opengl_vbo); glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo); diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index e7018476..309de78b 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -13,9 +13,15 @@ #else #include #define GL_GLEXT_PROTOTYPES 1 + +#ifdef OSX_BUILD +#include +#else #include #endif +#endif // End of OS-Specific GL defines + #include "gfx_window_manager_api.h" #include "gfx_screen_config.h" #include "../configfile.h" @@ -30,7 +36,7 @@ static bool cur_fullscreen; static uint32_t cur_width, cur_height; const SDL_Scancode windows_scancode_table[] = -{ +{ /* 0 1 2 3 4 5 6 7 */ /* 8 9 A B C D E F */ SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6, /* 0 */ @@ -53,7 +59,7 @@ const SDL_Scancode windows_scancode_table[] = SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_F16, /* 6 */ SDL_SCANCODE_F17, SDL_SCANCODE_F18, SDL_SCANCODE_F19, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 6 */ - + SDL_SCANCODE_INTERNATIONAL2, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL1, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, /* 7 */ SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL4, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL5, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL3, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN /* 7 */ }; @@ -98,16 +104,16 @@ static void gfx_sdl_init(void) { Uint32 window_flags = 0; SDL_Init(SDL_INIT_VIDEO); - + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); #ifdef USE_GLES SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // These attributes allow for hardware acceleration on RPis. - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #endif - + //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); @@ -122,9 +128,9 @@ static void gfx_sdl_init(void) { } SDL_DisplayMode sdl_displaymode; - SDL_GetCurrentDisplayMode(0, &sdl_displaymode); + SDL_GetCurrentDisplayMode(0, &sdl_displaymode); - const char* window_title = + const char* window_title = #ifndef USE_GLES "Super Mario 64 PC port (OpenGL)"; #else @@ -140,10 +146,10 @@ static void gfx_sdl_init(void) { DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, window_flags); SDL_ShowCursor(SDL_ENABLE); } - + SDL_GL_CreateContext(wnd); SDL_GL_SetSwapInterval(1); // We have a double buffered GL context, it makes no sense to want tearing. - + for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) { inverted_scancode_table[windows_scancode_table[i]] = i; } diff --git a/tools/Makefile b/tools/Makefile index 467b8d4c..1809ab92 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,5 +1,10 @@ +UNAME := $(shell uname) +ifeq ($(UNAME),Darwin) + OSX_BUILD := -DOSX_BUILD +endif + CC := gcc -CFLAGS := -Llib -Iinclude -I . -Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 -O3 -s +CFLAGS := -Llib -Iinclude -I . -Wall -Wextra -Wno-unused-parameter $(OSX_BUILD) -pedantic -std=c99 -O3 -s PROGRAMS := n64graphics n64graphics_ci mio0 n64cksum textconv patch_libultra_math iplfontutil aifc_decode aiff_extract_codebook vadpcm_enc tabledesign extract_data_for_mio skyconv n64graphics_SOURCES := n64graphics.c utils.c @@ -43,7 +48,7 @@ clean: define COMPILE $(1): $($1_SOURCES) - $(CC) $(CFLAGS) $$^ -lm -o $$@ $($1_CFLAGS) + $(CC) $(CFLAGS) $(OSX_BUILD) $$^ -lm -o $$@ $($1_CFLAGS) endef $(foreach p,$(PROGRAMS),$(eval $(call COMPILE,$(p)))) diff --git a/tools/n64graphics_ci_dir/exoquant/exoquant.c b/tools/n64graphics_ci_dir/exoquant/exoquant.c index 9f33c066..a70bc038 100644 --- a/tools/n64graphics_ci_dir/exoquant/exoquant.c +++ b/tools/n64graphics_ci_dir/exoquant/exoquant.c @@ -23,7 +23,11 @@ SOFTWARE. */ #include "exoquant.h" + +#ifndef OSX_BUILD // OSX build cannot have malloc defined #include +#endif + #include #include #include @@ -705,4 +709,4 @@ exq_float exq_sort_by_dir(const exq_histogram *pHist) pHist->color.g * exq_sort_dir.g + pHist->color.b * exq_sort_dir.b + pHist->color.a * exq_sort_dir.a; -} \ No newline at end of file +} From f6642e9a9d32836cc52071ba12e953c4023018c5 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 May 2020 22:39:37 +0300 Subject: [PATCH 72/86] 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]; From 3d7bdc300cd5c818ee7c677d4ef9718ddfe0402d Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 17:12:56 -0300 Subject: [PATCH 73/86] Add NO_BZERO for MXE --- Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile b/Makefile index a0dd34c5..ece07b95 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,8 @@ TARGET_N64 = 0 # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 +# No BZERO (for building under MXE) +NO_BZERO ?= 0 # Compiler to use (ido or gcc) COMPILER ?= ido @@ -461,6 +463,12 @@ endif # Check for enhancement options +# Check for no bzero option +ifeq ($(NO_BZERO),1) +CC_CHECK += -DNO_BZERO +CFLAGS += -DNO_BZERO +endif + # Check for Puppycam option ifeq ($(BETTERCAMERA),1) CC_CHECK += -DBETTERCAMERA From e42e1587b24c7042de03cf00a715f6fcbd4a8fb4 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 17:14:10 -0300 Subject: [PATCH 74/86] MXE fix for os_libc.h --- include/PR/os_libc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/PR/os_libc.h b/include/PR/os_libc.h index 94111c0b..13ec2124 100644 --- a/include/PR/os_libc.h +++ b/include/PR/os_libc.h @@ -4,7 +4,13 @@ #include "ultratypes.h" // Old deprecated functions from strings.h, replaced by memcpy/memset. +#ifdef NO_BZERO +#include +#define bzero(buf, size) memset(buf, 0, size) +#define bcopy(src, dst, size) memcpy(dst, src, size) +#else extern void bcopy(const void *, void *, size_t); extern void bzero(void *, size_t); +#endif #endif /* !_OS_LIBC_H_ */ From 8736776545859a9dd6bb33fd4022d1bc598c8dbb Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 17:20:33 -0300 Subject: [PATCH 75/86] Another fix to MXE --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index ece07b95..5903e52f 100644 --- a/Makefile +++ b/Makefile @@ -450,6 +450,12 @@ 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) `$(SDLCONFIG) --cflags` CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` + ifeq ($(CROSS),i686-w64-mingw32.static-) + ifeq ($(CROSS),x86_64-w64-mingw32.static-) + CC_CHECK += D_NOBZERO + CFLAGS += D_NOBZERO + endif + endif 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 From 385e396feb6d6afd4d71d096ddb9378425206402 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 17:21:59 -0300 Subject: [PATCH 76/86] fix the MXE fix for os_libc.h --- include/PR/os_libc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/PR/os_libc.h b/include/PR/os_libc.h index 13ec2124..4c2fc3e1 100644 --- a/include/PR/os_libc.h +++ b/include/PR/os_libc.h @@ -6,8 +6,8 @@ // Old deprecated functions from strings.h, replaced by memcpy/memset. #ifdef NO_BZERO #include -#define bzero(buf, size) memset(buf, 0, size) -#define bcopy(src, dst, size) memcpy(dst, src, size) +#define bzero(buf, size) memset((buf), 0, (size)) +#define bcopy(src, dst, size) memcpy((dst), (src), (size)) #else extern void bcopy(const void *, void *, size_t); extern void bzero(void *, size_t); From 69ff11e459e237998725b0bda05754908eb0503e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Sat, 16 May 2020 17:57:40 -0300 Subject: [PATCH 77/86] Add support for saves of both endiannesses. Porting from testing. Originally by @fgsfdsfgs. --- src/game/save_file.c | 119 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 8 deletions(-) diff --git a/src/game/save_file.c b/src/game/save_file.c index 6803fb69..b5112eb5 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -15,6 +15,12 @@ #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 +#define BSWAP16(x) \ + ( (((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00) ) +#define BSWAP32(x) \ + ( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \ + (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) ) + STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match"); extern struct SaveBuffer gSaveBuffer; @@ -50,6 +56,38 @@ static void stub_save_file_1(void) { UNUSED s32 pad; } +/** + * Byteswap all multibyte fields in a SaveBlockSignature. + */ +static inline void bswap_signature(struct SaveBlockSignature *data) { + data->magic = BSWAP16(data->magic); + data->chksum = BSWAP16(data->chksum); // valid as long as the checksum is a literal sum +} + +/** + * Byteswap all multibyte fields in a MainMenuSaveData. + */ +static inline void bswap_menudata(struct MainMenuSaveData *data) { + for (int i = 0; i < NUM_SAVE_FILES; ++i) + data->coinScoreAges[i] = BSWAP32(data->coinScoreAges[i]); + data->soundMode = BSWAP16(data->soundMode); +#ifdef VERSION_EU + data->language = BSWAP16(data->language); +#endif + bswap_signature(&data->signature); +} + +/** + * Byteswap all multibyte fields in a SaveFile. + */ +static inline void bswap_savefile(struct SaveFile *data) { + data->capPos[0] = BSWAP16(data->capPos[0]); + data->capPos[1] = BSWAP16(data->capPos[1]); + data->capPos[2] = BSWAP16(data->capPos[2]); + data->flags = BSWAP32(data->flags); + bswap_signature(&data->signature); +} + /** * Read from EEPROM to a given address. * The EEPROM address is computed using the offset of the destination address from gSaveBuffer. @@ -80,16 +118,16 @@ static s32 read_eeprom_data(void *buffer, s32 size) { /** * Write data to EEPROM. - * The EEPROM address is computed using the offset of the source address from gSaveBuffer. + * The EEPROM address was originally computed using the offset of the source address from gSaveBuffer. * Try at most 4 times, and return 0 on success. On failure, return the status returned from * osEepromLongWrite. Unlike read_eeprom_data, return 1 if EEPROM isn't loaded. */ -static s32 write_eeprom_data(void *buffer, s32 size) { +static s32 write_eeprom_data(void *buffer, s32 size, const uintptr_t baseofs) { s32 status = 1; if (gEepromProbe != 0) { s32 triesLeft = 4; - u32 offset = (u32)((u8 *) buffer - (u8 *) &gSaveBuffer) >> 3; + u32 offset = (u32)baseofs >> 3; do { #ifdef VERSION_SH @@ -106,6 +144,41 @@ static s32 write_eeprom_data(void *buffer, s32 size) { return status; } +/** + * Wrappers that byteswap the data on LE platforms before writing it to 'EEPROM' + */ + +static inline s32 write_eeprom_savefile(const u32 file, const u32 slot, const u32 num) { + // calculate the EEPROM address using the file number and slot + const uintptr_t ofs = (u8*)&gSaveBuffer.files[file][slot] - (u8*)&gSaveBuffer; + +#if IS_BIG_ENDIAN + return write_eeprom_data(&gSaveBuffer.files[file][slot], num * sizeof(struct SaveFile), ofs); +#else + // byteswap the data and then write it + struct SaveFile sf[num]; + bcopy(&gSaveBuffer.files[file][slot], sf, num * sizeof(sf[0])); + for (u32 i = 0; i < num; ++i) bswap_savefile(&sf[i]); + return write_eeprom_data(&sf, sizeof(sf), ofs); +#endif +} + +static inline s32 write_eeprom_menudata(const u32 slot, const u32 num) { + // calculate the EEPROM address using the slot + const uintptr_t ofs = (u8*)&gSaveBuffer.menuData[slot] - (u8*)&gSaveBuffer; + +#if IS_BIG_ENDIAN + return write_eeprom_data(&gSaveBuffer.menuData[slot], num * sizeof(struct MainMenuSaveData), ofs); +#else + // byteswap the data and then write it + struct MainMenuSaveData md[num]; + bcopy(&gSaveBuffer.menuData[slot], md, num * sizeof(md[0])); + for (u32 i = 0; i < num; ++i) bswap_menudata(&md[i]); + return write_eeprom_data(&md, sizeof(md), ofs); +#endif +} + + /** * Sum the bytes in data to data + size - 2. The last two bytes are ignored * because that is where the checksum is stored. @@ -157,7 +230,7 @@ static void restore_main_menu_data(s32 srcSlot) { bcopy(&gSaveBuffer.menuData[srcSlot], &gSaveBuffer.menuData[destSlot], sizeof(gSaveBuffer.menuData[destSlot])); // Write destination data to EEPROM - write_eeprom_data(&gSaveBuffer.menuData[destSlot], sizeof(gSaveBuffer.menuData[destSlot])); + write_eeprom_menudata(destSlot, 1); } static void save_main_menu_data(void) { @@ -169,7 +242,7 @@ static void save_main_menu_data(void) { bcopy(&gSaveBuffer.menuData[0], &gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1])); // Write to EEPROM - write_eeprom_data(gSaveBuffer.menuData, sizeof(gSaveBuffer.menuData)); + write_eeprom_menudata(0, 2); gMainMenuDataModified = FALSE; } @@ -245,8 +318,35 @@ static void restore_save_file_data(s32 fileIndex, s32 srcSlot) { sizeof(gSaveBuffer.files[fileIndex][destSlot])); // Write destination data to EEPROM - write_eeprom_data(&gSaveBuffer.files[fileIndex][destSlot], - sizeof(gSaveBuffer.files[fileIndex][destSlot])); + write_eeprom_savefile(fileIndex, destSlot, 1); +} + +/** + * Check if the 'EEPROM' save has different endianness (e.g. it's from an actual N64). + */ +static u8 save_file_need_bswap(const struct SaveBuffer *buf) { + // check all signatures just in case + for (int i = 0; i < 2; ++i) { + if (buf->menuData[i].signature.magic == BSWAP16(MENU_DATA_MAGIC)) + return TRUE; + for (int j = 0; j < NUM_SAVE_FILES; ++j) { + if (buf->files[j][i].signature.magic == BSWAP16(SAVE_FILE_MAGIC)) + return TRUE; + } + } + return FALSE; +} + +/** + * Byteswap all multibyte fields in a SaveBuffer. + */ +static void save_file_bswap(struct SaveBuffer *buf) { + bswap_menudata(buf->menuData + 0); + bswap_menudata(buf->menuData + 1); + for (int i = 0; i < NUM_SAVE_FILES; ++i) { + bswap_savefile(buf->files[i] + 0); + bswap_savefile(buf->files[i] + 1); + } } void save_file_do_save(s32 fileIndex) { @@ -260,7 +360,7 @@ void save_file_do_save(s32 fileIndex) { sizeof(gSaveBuffer.files[fileIndex][1])); // Write to EEPROM - write_eeprom_data(gSaveBuffer.files[fileIndex], sizeof(gSaveBuffer.files[fileIndex])); + write_eeprom_savefile(fileIndex, 0, 2); gSaveFileModified = FALSE; } @@ -298,6 +398,9 @@ void save_file_load_all(void) { bzero(&gSaveBuffer, sizeof(gSaveBuffer)); read_eeprom_data(&gSaveBuffer, sizeof(gSaveBuffer)); + if (save_file_need_bswap(&gSaveBuffer)) + save_file_bswap(&gSaveBuffer); + // Verify the main menu data and create a backup copy if only one of the slots is valid. validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC); validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1; From 7bf7b34c57f8b1ca06d2d54e3deff59fb38da26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Sat, 16 May 2020 18:07:14 -0300 Subject: [PATCH 78/86] Add a `--configfile` CLI option Usage: `--configfile yahoo.ini` will load up a file named yahoo.ini as the configuration file. --- src/game/options_menu.c | 3 ++- src/pc/cliopts.c | 16 ++++++++++++++++ src/pc/configfile.h | 2 -- src/pc/pc_main.c | 4 ++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 37bce584..59dfc23e 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -16,6 +16,7 @@ #include "game/game_init.h" #include "game/ingame_menu.h" #include "game/options_menu.h" +#include "pc/cliopts.h" #include "pc/configfile.h" #include "pc/controller/controller_api.h" @@ -424,7 +425,7 @@ void optmenu_toggle(void) { newcam_init_settings(); // load bettercam settings from config vars #endif controller_reconfigure(); // rebind using new config values - configfile_save(CONFIG_FILE); + configfile_save(gCLIOpts.ConfigFile); } } diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 602de098..0baf9fdd 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -1,5 +1,6 @@ #include "cliopts.h" #include +#include struct PCCLIOptions gCLIOpts; @@ -8,6 +9,8 @@ void parse_cli_opts(int argc, char* argv[]) // Initialize options with false values. gCLIOpts.SkipIntro = 0; gCLIOpts.FullScreen = 0; + gCLIOpts.ConfigFile = malloc(31); + strncpy(gCLIOpts.ConfigFile, "sm64config.txt", strlen("sm64config.txt")); // Scan arguments for options if (argc > 1) @@ -20,6 +23,19 @@ void parse_cli_opts(int argc, char* argv[]) if (strcmp(argv[i], "--fullscreen") == 0) // Open game in fullscreen gCLIOpts.FullScreen = 1; + + if (strncmp(argv[i], "--configfile", strlen("--configfile")) == 0) + { + if (i+1 < argc) + { + if (strlen(argv[i]) > 30) { + fprintf(stderr, "Configuration file supplied has a name too long.\n"); + } else { + memset(gCLIOpts.ConfigFile, 0, 30); + strncpy(gCLIOpts.ConfigFile, argv[i+1], strlen(argv[i+1])); + } + } + } } } } \ No newline at end of file diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 8dc69e27..49b48b93 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -3,8 +3,6 @@ #include -#define CONFIG_FILE "sm64config.txt" - #define MAX_BINDS 3 #define MAX_VOLUME 127 #define VOLUME_SHIFT 7 diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 93774fe2..f0c0a08b 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -92,7 +92,7 @@ void audio_shutdown(void) { } void game_shutdown(void) { - configfile_save(CONFIG_FILE); + configfile_save(gCLIOpts.ConfigFile);; controller_shutdown(); audio_shutdown(); gfx_shutdown(); @@ -136,7 +136,7 @@ void main_func(void) { main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0])); gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT); - configfile_load(CONFIG_FILE); + configfile_load(gCLIOpts.ConfigFile); atexit(game_shutdown); #ifdef TARGET_WEB From e67a5443b70ecf597843572ab3a1680e54ed9437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Sat, 16 May 2020 18:14:43 -0300 Subject: [PATCH 79/86] Fixed some stuff --- src/pc/cliopts.c | 1 + src/pc/cliopts.h | 1 + src/pc/pc_main.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 0baf9fdd..1e3b29c8 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -1,6 +1,7 @@ #include "cliopts.h" #include #include +#include struct PCCLIOptions gCLIOpts; diff --git a/src/pc/cliopts.h b/src/pc/cliopts.h index b4a0b613..1844c44c 100644 --- a/src/pc/cliopts.h +++ b/src/pc/cliopts.h @@ -4,6 +4,7 @@ struct PCCLIOptions { u8 SkipIntro; u8 FullScreen; + char * ConfigFile; }; extern struct PCCLIOptions gCLIOpts; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index f0c0a08b..c198f210 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -20,6 +20,7 @@ #include "cliopts.h" #include "configfile.h" +#include "controller/controller_api.h" OSMesg D_80339BEC; OSMesgQueue gSIEventMesgQueue; From 9fd43118cb6129521956741a3d5f01cb00e701bb 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 18:37:08 -0300 Subject: [PATCH 80/86] Added nightly notice. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b1cc3121..c9fabe58 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,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 mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer. + +Please contribute **first** to the [nightly branch](https://github.com/sm64pc/sm64pc/tree/nightly/). New functionality will be merged to master once they're considered to be well-tested. + *Read this in other languages: [Español](README_es_ES.md) [简体中文](README_zh_CN.md).* ## Features From 0402ad463b84fe5049bd491c9a8ff951342755c7 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 19:18:50 -0300 Subject: [PATCH 81/86] fixed MXE once and for all thanks to @fgsfdsfgs, this is the final thing needed for MXE support --- include/PR/os_libc.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/include/PR/os_libc.h b/include/PR/os_libc.h index 4c2fc3e1..e7567516 100644 --- a/include/PR/os_libc.h +++ b/include/PR/os_libc.h @@ -3,14 +3,28 @@ #include "ultratypes.h" -// Old deprecated functions from strings.h, replaced by memcpy/memset. -#ifdef NO_BZERO +// old bstring functions that aren't present on some platforms + +#if defined(__APPLE__) + +// macOS libc has them +#include + +#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) + +// there's no way that shit's defined, use memcpy/memset #include -#define bzero(buf, size) memset((buf), 0, (size)) -#define bcopy(src, dst, size) memcpy((dst), (src), (size)) +#undef bzero +#undef bcopy +#define bzero(buf, len) memset((buf), 0, (len)) +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) + #else + +// hope for the best extern void bcopy(const void *, void *, size_t); extern void bzero(void *, size_t); + #endif #endif /* !_OS_LIBC_H_ */ From 5c9e3c60a7b14ccc387ea1e7bcdb98585ba8446e Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 19:20:45 -0300 Subject: [PATCH 82/86] strip out now-needless NOBZERO flag --- Makefile | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Makefile b/Makefile index 5903e52f..a0dd34c5 100644 --- a/Makefile +++ b/Makefile @@ -22,8 +22,6 @@ TARGET_N64 = 0 # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 -# No BZERO (for building under MXE) -NO_BZERO ?= 0 # Compiler to use (ido or gcc) COMPILER ?= ido @@ -450,12 +448,6 @@ 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) `$(SDLCONFIG) --cflags` CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags` - ifeq ($(CROSS),i686-w64-mingw32.static-) - ifeq ($(CROSS),x86_64-w64-mingw32.static-) - CC_CHECK += D_NOBZERO - CFLAGS += D_NOBZERO - endif - endif 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 @@ -469,12 +461,6 @@ endif # Check for enhancement options -# Check for no bzero option -ifeq ($(NO_BZERO),1) -CC_CHECK += -DNO_BZERO -CFLAGS += -DNO_BZERO -endif - # Check for Puppycam option ifeq ($(BETTERCAMERA),1) CC_CHECK += -DBETTERCAMERA From bd4187c92bd14288b15a023f06e1a96bcdb290ef Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 21:04:55 -0300 Subject: [PATCH 83/86] Make MXE easier to compile in Specifying the target arch MXE expects in the makefile makes it easier for MXE users to compile the game. --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 7091f336..80213c10 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,17 @@ EXT_OPTIONS_MENU ?= 1 TARGET_WEB ?= 0 # Specify the target you are building for, 0 means native TARGET_ARCH ?= native + +ifeq ($(CROSS),i686-w64-mingw32.static-) + ifeq ($(CROSS),x86_64-w64-mingw32.static-) + TARGET_ARCH = i386pe + else + TARGET_ARCH = i386pe + endif +else + TARGET_ARCH = native +endif + TARGET_BITS ?= 0 ifneq ($(TARGET_BITS),0) From 410090a84c5d5d10dabf0893309c792c3c460ec6 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 21:24:29 -0300 Subject: [PATCH 84/86] Fix a few minor bugs with MXE compilation --- Makefile | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 80213c10..fe9add23 100644 --- a/Makefile +++ b/Makefile @@ -42,11 +42,9 @@ TARGET_WEB ?= 0 TARGET_ARCH ?= native ifeq ($(CROSS),i686-w64-mingw32.static-) - ifeq ($(CROSS),x86_64-w64-mingw32.static-) - TARGET_ARCH = i386pe - else - TARGET_ARCH = i386pe - endif + TARGET_ARCH = i386pe +else ifeq ($(CROSS),x86_64-w64-mingw32.static-) + TARGET_ARCH = i386pe else TARGET_ARCH = native endif @@ -517,9 +515,9 @@ 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 -static ifneq ($(CROSS),i686-w64-mingw32.static-) - ifneq ($(CROSS),x86_64-w64-mingw32.static-) - LDFLAGS += -no-pie - endif + LDFLAGS += -no-pie + else ifneq ($(CROSS),x86_64-w64-mingw32.static-) + LDFLAGS += -no-pie endif ifeq ($(WINDOWS_CONSOLE),1) LDFLAGS += -mconsole From 5d800819df0caa8a01ffd8be2aecba27494f7f01 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 22:54:03 -0300 Subject: [PATCH 85/86] fix small bug with MXE compilation the no-pie command line option was being sent to MXE when it shouldn't have been, breaking MXE compilation. Urgent fix. --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index fe9add23..6767bf89 100644 --- a/Makefile +++ b/Makefile @@ -514,9 +514,7 @@ 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) 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-) - LDFLAGS += -no-pie - else ifneq ($(CROSS),x86_64-w64-mingw32.static-) + ifeq ($(CROSS),) LDFLAGS += -no-pie endif ifeq ($(WINDOWS_CONSOLE),1) From a40892a1bf695da78b23bd560b95f4f8ad735c51 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 16 May 2020 23:05:24 -0300 Subject: [PATCH 86/86] Update readme for MXE compilation support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9fabe58..1ba69773 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,4 @@ Please contribute **first** to the [nightly branch](https://github.com/sm64pc/sm ## Building For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki). -**Do NOT attempt to compile Windows executables with `WINDOWS_BUILD=1` under Linux or WSL. It will NOT work. Follow the guide on the wiki.** +**Make sure you have MXE first before attempting to compile for Windows on Linux and WSL. Follow the guide on the wiki.**