From be340547c47b94e76696cc7bd1ddbe31a802cb07 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Fri, 8 May 2020 03:24:42 +0200 Subject: [PATCH 01/39] port analog camera code to the master codebase --- Makefile | 10 + include/segments.h | 11 + include/text_strings.h.in | 14 + src/engine/math_util.c | 31 +- src/engine/math_util.h | 6 + src/engine/surface_collision.c | 165 ++++ src/engine/surface_collision.h | 2 +- src/game/bettercamera.h | 48 ++ src/game/bettercamera.inc.h | 885 +++++++++++++++++++++ src/game/camera.c | 102 ++- src/game/camera.h | 3 + src/game/game_init.c | 49 +- src/game/ingame_menu.c | 20 +- src/game/mario.c | 12 +- src/game/mario_actions_airborne.c | 99 ++- src/game/save_file.c | 47 ++ src/game/save_file.h | 27 +- src/pc/controller/controller_api.h | 5 + src/pc/controller/controller_entry_point.c | 18 + src/pc/controller/controller_sdl.c | 10 +- 20 files changed, 1542 insertions(+), 22 deletions(-) create mode 100644 src/game/bettercamera.h create mode 100644 src/game/bettercamera.inc.h diff --git a/Makefile b/Makefile index aa36bc0a..86234be5 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,8 @@ TARGET_RPI ?= 0 # Compiler to use (ido or gcc) COMPILER ?= ido +BETTERCAMERA ?= 1 + ifeq ($(COMPILER),gcc) NON_MATCHING := 1 endif @@ -508,6 +510,11 @@ 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 `$(CROSS)sdl2-config --cflags` endif +ifeq ($(BETTERCAMERA),1) +CC_CHECK += -DBETTERCAMERA +CFLAGS += -DBETTERCAMERA +endif + ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) ifeq ($(TARGET_WEB),1) @@ -599,6 +606,9 @@ asm/boot.s: $(BUILD_DIR)/lib/bin/ipl3_font.bin $(BUILD_DIR)/lib/bin/ipl3_font.bin: lib/ipl3_font.png $(IPLFONTUTIL) e $< $@ + +#Required so the compiler doesn't complain about this not existing. +$(BUILD_DIR)/src/game/camera.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/include/text_strings.h: include/text_strings.h.in $(TEXTCONV) charmap.txt $< $@ diff --git a/include/segments.h b/include/segments.h index c98040a8..b03463ae 100644 --- a/include/segments.h +++ b/include/segments.h @@ -1,6 +1,10 @@ #ifndef _SEGMENTS_H #define _SEGMENTS_H +#ifdef BETTERCAMERA +#define USE_EXT_RAM +#endif + /* * Memory addresses for segments. Ideally, this header file would not be * needed, and the addresses would be defined in sm64.ld and linker-inserted @@ -44,10 +48,17 @@ */ #define SEG_BUFFERS 0x8005C000 // 0x0085000 in size +#ifdef BETTERCAMERA +#define SEG_MAIN 0x800F1000 // 0x1328000 in size +#define SEG_ENGINE 0x80223800 // 0x0017000 in size +#define SEG_FRAMEBUFFERS 0x8023A800 // 0x0070800 in size +#define SEG_POOL_START 0x802AB000 // 0x0165000 in size +#else #define SEG_MAIN 0x800E1000 // 0x1328000 in size #define SEG_ENGINE 0x80213800 // 0x0017000 in size #define SEG_FRAMEBUFFERS 0x8022A800 // 0x0070800 in size #define SEG_POOL_START 0x8029B000 // 0x0165000 in size +#endif #define SEG_POOL_END 0x80800000 #define SEG_POOL_END_4MB 0x80400000 // For the error message screen enhancement. #define SEG_GODDARD SEG_POOL_START + 0x113000 diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 4e36eb96..db15cd6c 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -3,6 +3,20 @@ #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") + /** * Global Symbols */ diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 61a095d1..8643f5e0 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -49,6 +49,15 @@ void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) { return &dest; //! warning: function returns address of local variable } +/// Multiply vector 'dest' by a +void *vec3f_mul(Vec3f dest, f32 a) +{ + dest[0] *= a; + dest[1] *= a; + dest[2] *= a; + return &dest; //! warning: function returns address of local variable +} + /// Copy vector src to dest void *vec3s_copy(Vec3s dest, Vec3s src) { dest[0] = src[0]; @@ -81,11 +90,11 @@ void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) { return &dest; //! warning: function returns address of local variable } -/// Subtract vector a from 'dest' -void *vec3s_sub(Vec3s dest, Vec3s a) { - dest[0] -= a[0]; - dest[1] -= a[1]; - dest[2] -= a[2]; +/// Make 'dest' the difference of vectors a and b. +void *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; return &dest; //! warning: function returns address of local variable } @@ -140,6 +149,18 @@ void *vec3f_normalize(Vec3f dest) { return &dest; //! warning: function returns address of local variable } +/// Get length of vector 'a' +f32 vec3f_length(Vec3f a) +{ + return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); +} + +/// Get dot product of vectors 'a' and 'b' +f32 vec3f_dot(Vec3f a, Vec3f b) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + #pragma GCC diagnostic pop /// Copy matrix 'src' to 'dest' diff --git a/src/engine/math_util.h b/src/engine/math_util.h index b36498c7..650fe973 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -29,10 +29,14 @@ extern f32 gCosineTable[]; #define sqr(x) ((x) * (x)) +#define abs(x) ((x) < 0 ? -(x) : (x)) + void *vec3f_copy(Vec3f dest, Vec3f src); void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z); void *vec3f_add(Vec3f dest, Vec3f a); void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b); +void *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b); +void *vec3f_mul(Vec3f dest, f32 a); void *vec3s_copy(Vec3s dest, Vec3s src); void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z); void *vec3s_add(Vec3s dest, Vec3s a); @@ -43,6 +47,8 @@ void *vec3f_to_vec3s(Vec3s dest, Vec3f a); void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c); void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b); void *vec3f_normalize(Vec3f dest); +f32 vec3f_length(Vec3f a); +f32 vec3f_dot(Vec3f a, Vec3f b); void mtxf_copy(f32 dest[4][4], f32 src[4][4]); void mtxf_identity(f32 mtx[4][4]); void mtxf_translate(f32 a[4][4], Vec3f b); diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 7672187d..5eee60ed 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -9,6 +9,7 @@ #include "surface_collision.h" #include "surface_load.h" #include "game/object_list_processor.h" +#include "math_util.h" /************************************************** * WALLS * @@ -779,3 +780,167 @@ s32 unused_resolve_floor_or_ceil_collisions(s32 checkCeil, f32 *px, f32 *py, f32 return 0; } + +/** + * Raycast functions + */ +s32 ray_surface_intersect(Vec3f orig, Vec3f dir, f32 dir_length, struct Surface *surface, Vec3f hit_pos, f32 *length) +{ + Vec3f v0, v1, v2, e1, e2, h, s, q; + f32 a, f, u, v; + Vec3f add_dir; + + // Get surface normal and some other stuff + vec3s_to_vec3f(v0, surface->vertex1); + vec3s_to_vec3f(v1, surface->vertex2); + vec3s_to_vec3f(v2, surface->vertex3); + + vec3f_dif(e1, v1, v0); + vec3f_dif(e2, v2, v0); + + vec3f_cross(h, dir, e2); + + // Check if we're perpendicular from the surface + a = vec3f_dot(e1, h); + if (a > -0.00001f && a < 0.00001f) + return FALSE; + + // Check if we're making contact with the surface + f = 1.0f / a; + + vec3f_dif(s, orig, v0); + u = f * vec3f_dot(s, h); + if (u < 0.0f || u > 1.0f) + return FALSE; + + vec3f_cross(q, s, e1); + v = f * vec3f_dot(dir, q); + if (v < 0.0f || u + v > 1.0f) + return FALSE; + + // Get the length between our origin and the surface contact point + *length = f * vec3f_dot(e2, q); + if (*length <= 0.00001 || *length > dir_length) + return FALSE; + + // Successful contact + vec3f_copy(add_dir, dir); + vec3f_mul(add_dir, *length); + vec3f_sum(hit_pos, orig, add_dir); + return TRUE; +} + +void find_surface_on_ray_list(struct SurfaceNode *list, Vec3f orig, Vec3f dir, f32 dir_length, struct Surface **hit_surface, Vec3f hit_pos, f32 *max_length) +{ + s32 hit; + f32 length; + Vec3f chk_hit_pos; + f32 top, bottom; + + // Get upper and lower bounds of ray + if (dir[1] >= 0.0f) + { + top = orig[1] + dir[1] * dir_length; + bottom = orig[1]; + } + else + { + top = orig[1]; + bottom = orig[1] + dir[1] * dir_length; + } + + // Iterate through every surface of the list + for (; list != NULL; list = list->next) + { + // Reject surface if out of vertical bounds + if (list->surface->lowerY > top || list->surface->upperY < bottom) + continue; + + // Check intersection between the ray and this surface + if ((hit = ray_surface_intersect(orig, dir, dir_length, list->surface, chk_hit_pos, &length)) != 0) + { + if (length <= *max_length) + { + *hit_surface = list->surface; + vec3f_copy(hit_pos, chk_hit_pos); + *max_length = length; + } + } + } +} + + +void find_surface_on_ray_cell(s16 cellX, s16 cellZ, Vec3f orig, Vec3f normalized_dir, f32 dir_length, struct Surface **hit_surface, Vec3f hit_pos, f32 *max_length) +{ + // Skip if OOB + if (cellX >= 0 && cellX <= 0xF && cellZ >= 0 && cellZ <= 0xF) + { + // Iterate through each surface in this partition + if (normalized_dir[1] > -0.99f) + { + find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + } + if (normalized_dir[1] < 0.99f) + { + find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + } + find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + } +} + +void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos) +{ + f32 max_length; + s16 cellZ, cellX; + f32 fCellZ, fCellX; + f32 dir_length; + Vec3f normalized_dir; + f32 step, dx, dz; + u32 i; + + // Set that no surface has been hit + *hit_surface = NULL; + vec3f_sum(hit_pos, orig, dir); + + // Get normalized direction + dir_length = vec3f_length(dir); + max_length = dir_length; + vec3f_copy(normalized_dir, dir); + vec3f_normalize(normalized_dir); + + // Get our cell coordinate + fCellX = (orig[0] + LEVEL_BOUNDARY_MAX) / CELL_SIZE; + fCellZ = (orig[2] + LEVEL_BOUNDARY_MAX) / CELL_SIZE; + cellX = (s16)fCellX; + cellZ = (s16)fCellZ; + + // Don't do DDA if straight down + if (normalized_dir[1] >= 1.0f || normalized_dir[1] <= -1.0f) + { + find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length); + return; + } + + // Get cells we cross using DDA + if (abs(dir[0]) >= abs(dir[2])) + step = abs(dir[0]) / CELL_SIZE; + else + step = abs(dir[2]) / CELL_SIZE; + + dx = dir[0] / step / CELL_SIZE; + dz = dir[2] / step / CELL_SIZE; + + for (i = 0; i < step && *hit_surface == NULL; i++) + { + find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length); + + // Move cell coordinate + fCellX += dx; + fCellZ += dz; + cellX = (s16)fCellX; + cellZ = (s16)fCellZ; + } +} diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index 82ba8624..6e79dca5 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -32,6 +32,6 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor); f32 find_water_level(f32 x, f32 z); f32 find_poison_gas_level(f32 x, f32 z); void debug_surface_list_info(f32 xPos, f32 zPos); - +void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos); #endif /* _SURFACE_COLLISION_H */ diff --git a/src/game/bettercamera.h b/src/game/bettercamera.h new file mode 100644 index 00000000..2896103d --- /dev/null +++ b/src/game/bettercamera.h @@ -0,0 +1,48 @@ +enum newcam_flagvalues +{ + NC_FLAG_XTURN = 0x0001,//If this flag is set, the camera's yaw can be moved by the player. + NC_FLAG_YTURN = 0x0002, //If this flag is set, the camera's pitch can be moved by the player. + NC_FLAG_ZOOM = 0x0004, //If this flag is set, the camera's distance can be set by the player. + NC_FLAG_8D = 0x0008, //If this flag is set, the camera will snap to an 8 directional axis + NC_FLAG_4D = 0x0010, //If this flag is set, the camera will snap to a 4 directional axis + NC_FLAG_2D = 0x0020, //If this flag is set, the camera will stick to 2D. + NC_FLAG_FOCUSX = 0x0040, //If this flag is set, the camera will point towards its focus on the X axis. + NC_FLAG_FOCUSY = 0x0080, //If this flag is set, the camera will point towards its focus on the Y axis. + NC_FLAG_FOCUSZ = 0x0100, //If this flag is set, the camera will point towards its focus on the Z axis. + NC_FLAG_POSX = 0x0200, //If this flag is set, the camera will move along the X axis. + NC_FLAG_POSY = 0x0400, //If this flag is set, the camera will move along the Y axis. + NC_FLAG_POSZ = 0x0800, //If this flag is set, the camera will move along the Z axis. + NC_FLAG_COLLISION = 0x1000, //If this flag is set, the camera will collide and correct itself with terrain. + NC_FLAG_SLIDECORRECT = 0x2000, //If this flag is set, the camera will attempt to centre itself behind Mario whenever he's sliding. + + NC_MODE_NORMAL = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, + NC_MODE_SLIDE = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION | NC_FLAG_SLIDECORRECT, + NC_MODE_FIXED = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ, + NC_MODE_2D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, + NC_MODE_8D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_8D | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, + NC_MODE_FIXED_NOMOVE = 0x0000, + NC_MODE_NOTURN = NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, + NC_MODE_NOROTATE = NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION + +}; + +extern void newcam_display_options(void); +extern void newcam_check_pause_buttons(void); +extern void newcam_init_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; +extern u8 newcam_invertX; +extern u8 newcam_invertY; +extern u8 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking. +extern u8 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement. +extern u8 newcam_active; // basically the thing that governs if newcam is on. +extern u8 newcam_analogue; +extern u16 newcam_intendedmode; + +extern u16 newcam_mode; +extern s16 newcam_yaw; diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h new file mode 100644 index 00000000..b04d8122 --- /dev/null +++ b/src/game/bettercamera.inc.h @@ -0,0 +1,885 @@ +#include "sm64.h" +#include "game/camera.h" +#include "game/level_update.h" +#include "game/print.h" +#include "engine/math_util.h" +#include "game/segment2.h" +#include "game/save_file.h" +#include "bettercamera.h" +#include "include/text_strings.h" +#include "engine/surface_collision.h" +#include + + + +/** +Quick explanation of the camera modes + +NC_MODE_NORMAL: Standard mode, allows dualaxial movement and free control of the camera. +NC_MODE_FIXED: Disables control of camera, and the actual position of the camera doesn't update. +NC_MODE_2D: Disables horizontal control of the camera and locks Mario's direction to the X axis. NYI though. +NC_MODE_8D: 8 directional movement. Similar to standard, except the camera direction snaps to 8 directions. +NC_MODE_FIXED_NOMOVE: Disables control and movement of the camera. +NC_MODE_NOTURN: Disables horizontal and vertical control of the camera. +**/ + +//!A bunch of developer intended options, to cover every base, really. +//#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. +struct newcam_hardpos +{ + u8 newcam_hard_levelID; + u8 newcam_hard_areaID; + u8 newcam_hard_permaswap; + u16 newcam_hard_modeset; + s16 newcam_hard_X1; + s16 newcam_hard_Y1; + s16 newcam_hard_Z1; + s16 newcam_hard_X2; + s16 newcam_hard_Y2; + s16 newcam_hard_Z2; + s16 newcam_hard_camX; + s16 newcam_hard_camY; + s16 newcam_hard_camZ; + s16 newcam_hard_lookX; + s16 newcam_hard_lookY; + s16 newcam_hard_lookZ; +}; + +///This is the bit that defines where the angles happen. They're basically environment boxes that dictate camera behaviour. +//Permaswap is a boolean that simply determines wether or not when the camera changes at this point it stays changed. 0 means it resets when you leave, and 1 means it stays changed. +//The camera position fields accept "32767" as an ignore flag. +struct newcam_hardpos newcam_fixedcam[] = +{ +{/*Level ID*/ 16,/*Area ID*/ 1,/*Permaswap*/ 0,/*Mode*/ NC_MODE_FIXED_NOMOVE, //Standard params. +/*X begin*/ -540,/*Y begin*/ 800,/*Z begin*/ -3500, //Where the activation box begins +/*X end*/ 540,/*Y end*/ 2000,/*Z end*/ -1500, //Where the activation box ends. +/*Cam X*/ 0,/*Cam Y*/ 1500,/*Cam Z*/ -1000, //The position the camera gets placed for NC_MODE_FIXED and NC_MODE_FIXED_NOMOVE +/*Look X*/ 0,/*Look Y*/ 800,/*Look Z*/ -2500}, //The position the camera looks at for NC_MODE_FIXED_NOMOVE +}; + + +#ifdef noaccel + u8 accel = 255; + #else + u8 accel = 10; +#endif // noaccel + +s16 newcam_yaw; //Z axis rotation +s8 newcam_yaw_acc; +s16 newcam_tilt = 1500; //Y axis rotation +s8 newcam_tilt_acc; +u16 newcam_distance = 750; //The distance the camera stays from the player +u16 newcam_distance_target = 750; //The distance the player camera tries to reach. +f32 newcam_pos_target[3]; //The position the camera is basing calculations off. *usually* Mario. +f32 newcam_pos[3]; //Position the camera is in the world +f32 newcam_lookat[3]; //Position the camera is looking at +f32 newcam_framessincec[2]; +f32 newcam_extheight = 125; +u8 newcam_centering = 0; // The flag that depicts wether the camera's goin gto try centering. +s16 newcam_yaw_target; // The yaw value the camera tries to set itself to when the centre flag is active. Is set to Mario's face angle. +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; +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; + +u8 newcam_sensitivityX; //How quick the camera works. +u8 newcam_sensitivityY; +u8 newcam_invertX; //Reverses movement of the camera axis. +u8 newcam_invertY; +u8 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking. +u8 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement. +u8 newcam_analogue; //Wether to accept inputs from a player 2 joystick, and then disables C button input. +s16 newcam_distance_values[] = {750,1250,2000}; +u8 newcam_active = 1; // basically the thing that governs if newcam is on. +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 = 7; //How many options there are in newcam_uptions. + +u8 newcam_options[][64] = {{NC_ANALOGUE}, {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}}; + +///This is called at every level initialisation. +void newcam_init(struct Camera *c, u8 dv) +{ + newcam_tilt = 1500; + newcam_distance_target = newcam_distance_values[dv]; + newcam_yaw = -c->yaw+0x4000; //Mario and the camera's yaw have this offset between them. + newcam_mode = NC_MODE_NORMAL; + ///This here will dictate what modes the camera will start in at the beginning of a level. Below are some examples. + switch (gCurrLevelNum) + { + case LEVEL_BITDW: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break; + case LEVEL_BITFS: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break; + case LEVEL_BITS: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break; + case LEVEL_WF: newcam_yaw = 0x4000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[1]; break; + case LEVEL_RR: newcam_yaw = 0x6000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[2]; break; + case LEVEL_CCM: if (gCurrAreaIndex == 1) {newcam_yaw = -0x4000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[1];} else newcam_mode = NC_MODE_SLIDE; break; + case LEVEL_WDW: newcam_yaw = 0x2000; newcam_tilt = 3000; newcam_distance_target = newcam_distance_values[1]; break; + case 27: newcam_mode = NC_MODE_SLIDE; break; + case LEVEL_THI: if (gCurrAreaIndex == 2) newcam_mode = NC_MODE_SLIDE; break; + } + + newcam_distance = newcam_distance_target; + newcam_intendedmode = newcam_mode; + newcam_modeflags = newcam_mode; +} +static f32 newcam_clamp(f32 value, f32 max, f32 min) +{ + if (value > max) + value = max; + if (value < min) + value = min; + return value; +} +///These are the default settings for Puppycam. You may change them to change how they'll be set for first timers. +void newcam_init_settings() +{ + if (save_check_firsttime()) + { + save_file_get_setting(); + newcam_clamp(newcam_sensitivityX, 10, 250); + newcam_clamp(newcam_sensitivityY, 10, 250); + newcam_clamp(newcam_aggression, 0, 100); + newcam_clamp(newcam_panlevel, 0, 100); + newcam_clamp(newcam_invertX, 0, 1); + newcam_clamp(newcam_invertY, 0, 1); + } + else + { + newcam_sensitivityX = 75; + newcam_sensitivityY = 75; + newcam_aggression = 0; + newcam_panlevel = 75; + newcam_invertX = 0; + newcam_invertY = 0; + save_set_firsttime(); + } +} + +/** 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) +{ + return (s16) (length * coss(dir)); +} +static s16 lengthdir_y(f32 length, s16 dir) +{ + return (s16) (length * sins(dir)); +} + +void newcam_diagnostics(void) +{ + print_text_fmt_int(32,192,"Lv %d",gCurrLevelNum); + print_text_fmt_int(32,176,"Area %d",gCurrAreaIndex); + print_text_fmt_int(32,160,"X %d",gMarioState->pos[0]); + print_text_fmt_int(32,144,"Y %d",gMarioState->pos[1]); + print_text_fmt_int(32,128,"Z %d",gMarioState->pos[2]); + print_text_fmt_int(32,112,"FLAGS %d",newcam_modeflags); + print_text_fmt_int(180,112,"INTM %d",newcam_intendedmode); + print_text_fmt_int(32,96,"TILT UP %d",newcam_tilt_acc); + print_text_fmt_int(32,80,"YAW UP %d",newcam_yaw_acc); + print_text_fmt_int(32,64,"YAW %d",newcam_yaw); + print_text_fmt_int(32,48,"TILT %d",newcam_tilt); + print_text_fmt_int(32,32,"DISTANCE %d",newcam_distance); +} + +static s16 newcam_adjust_value(s16 var, s16 val) +{ + var += val; + if (var > 100) + var = 100; + if (var < -100) + var = -100; + + return var; +} + +static f32 newcam_approach_float(f32 var, f32 val, f32 inc) +{ + if (var < val) + return min(var + inc, val); + else + return max(var - inc, val); +} + +static s16 newcam_approach_s16(s16 var, s16 val, s16 inc) +{ + if (var < val) + return max(var + inc, val); + else + return min(var - inc, val); +} + +static u8 ivrt(u8 axis) +{ + if (axis == 0) + { + if (newcam_invertX == 0) + return 1; + else + return -1; + } + else + { + if (newcam_invertY == 0) + return 1; + else + return -1; + } +} + +static void newcam_rotate_button(void) +{ + if ((newcam_modeflags & NC_FLAG_8D || newcam_modeflags & NC_FLAG_4D) && newcam_modeflags & NC_FLAG_XTURN) //8 directional camera rotation input for buttons. + { + if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_analogue == 0) + { + #ifndef nosound + play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); + #endif + if (newcam_modeflags & NC_FLAG_8D) + newcam_yaw_target = newcam_yaw_target+0x2000; + else + newcam_yaw_target = newcam_yaw_target+0x4000; + newcam_centering = 1; + } + else + if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_analogue == 0) + { + #ifndef nosound + play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); + #endif + if (newcam_modeflags & NC_FLAG_8D) + newcam_yaw_target = newcam_yaw_target-0x2000; + else + newcam_yaw_target = newcam_yaw_target-0x4000; + newcam_centering = 1; + } + } + else //Standard camera movement + if (newcam_modeflags & NC_FLAG_XTURN) + { + if ((gPlayer1Controller->buttonDown & L_CBUTTONS) && newcam_analogue == 0) + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,accel); + else if ((gPlayer1Controller->buttonDown & R_CBUTTONS) && newcam_analogue == 0) + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,-accel); + else + #ifdef noaccel + newcam_yaw_acc = 0; + #else + newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE)); + #endif + } + + if (gPlayer1Controller->buttonDown & U_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) + newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,accel); + else if (gPlayer1Controller->buttonDown & D_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) + newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,-accel); + else + #ifdef noaccel + newcam_tilt_acc = 0; + #else + newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE)); + #endif + + newcam_framessincec[0] += 1; + newcam_framessincec[1] += 1; + if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0) + { + if (newcam_framessincec[0] < 6) + { + newcam_yaw_target = newcam_yaw+0x3000; + newcam_centering = 1; + #ifndef nosound + play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); + #endif + } + newcam_framessincec[0] = 0; + } + if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0) + { + if (newcam_framessincec[1] < 6) + { + newcam_yaw_target = newcam_yaw-0x3000; + newcam_centering = 1; + #ifndef nosound + play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); + #endif + } + newcam_framessincec[1] = 0; + } + + + if (newcam_analogue == 1) //There's not much point in keeping this behind a check, but it wouldn't hurt, just incase any 2player shenanigans ever happen, it makes it easy to disable. + { //The joystick values cap at 80, so divide by 8 to get the same net result at maximum turn as the button + if (ABS(gPlayer2Controller->stickX) > 20 && newcam_modeflags & NC_FLAG_XTURN) + { + if (newcam_modeflags & NC_FLAG_8D) + { + if (newcam_cstick_down == 0) + { + newcam_cstick_down = 1; + newcam_centering = 1; + #ifndef nosound + play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); + #endif + if (gPlayer2Controller->stickX > 20) + { + if (newcam_modeflags & NC_FLAG_8D) + newcam_yaw_target = newcam_yaw_target+0x2000; + else + newcam_yaw_target = newcam_yaw_target+0x4000; + } + else + { + if (newcam_modeflags & NC_FLAG_8D) + newcam_yaw_target = newcam_yaw_target-0x2000; + else + newcam_yaw_target = newcam_yaw_target-0x4000; + } + } + } + else + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,(-gPlayer2Controller->stickX/4)); + } + else + { + newcam_cstick_down = 0; + newcam_yaw_acc -= (newcam_yaw_acc*(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)); + } +} + +static void newcam_zoom_button(void) +{ + //Smoothly move the camera to the new spot. + if (newcam_distance > newcam_distance_target) + { + newcam_distance -= 250; + if (newcam_distance < newcam_distance_target) + newcam_distance = newcam_distance_target; + } + if (newcam_distance < newcam_distance_target) + { + newcam_distance += 250; + if (newcam_distance > newcam_distance_target) + 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) + { + newcam_yaw_target = -gMarioState->faceAngle[1]-0x4000; + newcam_centering = 1; + } + else //Each time the player presses R, but NOT L the camera zooms out more, until it hits the limit and resets back to close view. + if (gPlayer1Controller->buttonPressed & R_TRIG && newcam_modeflags & NC_FLAG_XTURN) + { + #ifndef nosound + play_sound(SOUND_MENU_CLICK_CHANGE_VIEW, gDefaultSoundArgs); + #endif + + if (newcam_distance_target == newcam_distance_values[0]) + newcam_distance_target = newcam_distance_values[1]; + else + if (newcam_distance_target == newcam_distance_values[1]) + newcam_distance_target = newcam_distance_values[2]; + else + newcam_distance_target = newcam_distance_values[0]; + + } + if (newcam_centering && newcam_modeflags & NC_FLAG_XTURN) + { + newcam_yaw = approach_s16_symmetric(newcam_yaw,newcam_yaw_target,0x800); + if (newcam_yaw = newcam_yaw_target) + newcam_centering = 0; + } + else + newcam_yaw_target = newcam_yaw; +} + +static void newcam_update_values(void) +{//For tilt, this just limits it so it doesn't go further than 90 degrees either way. 90 degrees is actually 16384, but can sometimes lead to issues, so I just leave it shy of 90. + u8 waterflag = 0; + newcam_sensitivityX = 75; + newcam_sensitivityY = 75; + if (newcam_modeflags & NC_FLAG_XTURN) + newcam_yaw += (ivrt(0)*(newcam_yaw_acc*(newcam_sensitivityX/10))); + if (((newcam_tilt < 12000 && newcam_tilt_acc*ivrt(1) > 0) || (newcam_tilt > -12000 && newcam_tilt_acc*ivrt(1) < 0)) && newcam_modeflags & NC_FLAG_YTURN) + newcam_tilt += (ivrt(1)*(newcam_tilt_acc*(newcam_sensitivityY/10))); + else + { + if (newcam_tilt > 12000) + newcam_tilt = 12000; + if (newcam_tilt < -12000) + newcam_tilt = -12000; + } + + if (newcam_turnwait > 0 && gMarioState->vel[1] == 0) + { + newcam_turnwait -= 1; + if (newcam_turnwait < 0) + newcam_turnwait = 0; + } + else + { + if (gMarioState->intendedMag > 0 && gMarioState->vel[1] == 0 && newcam_modeflags & NC_FLAG_XTURN) + newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioState->faceAngle[1]-0x4000,((newcam_aggression*(ABS(gPlayer1Controller->stickX/10)))*(gMarioState->forwardVel/32)))); + else + newcam_turnwait = 10; + } + + if (newcam_modeflags & NC_FLAG_SLIDECORRECT) + { + switch (gMarioState->action) + { + case ACT_BUTT_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break; + case ACT_STOMACH_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break; + case ACT_HOLD_BUTT_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break; + case ACT_HOLD_STOMACH_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break; + } + } + switch (gMarioState->action) + { + case ACT_SHOT_FROM_CANNON: waterflag = 1; break; + case ACT_FLYING: waterflag = 1; break; + } + + if (gMarioState->action & ACT_FLAG_SWIMMING) + { + if (gMarioState->forwardVel > 2) + waterflag = 1; + } + + if (waterflag && newcam_modeflags & NC_FLAG_XTURN) + { + newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioState->faceAngle[1]-0x4000,(gMarioState->forwardVel*128))); + if ((signed)gMarioState->forwardVel > 1) + newcam_tilt = (approach_s16_symmetric(newcam_tilt,(-gMarioState->faceAngle[0]*0.8)+3000,(gMarioState->forwardVel*32))); + else + newcam_tilt = (approach_s16_symmetric(newcam_tilt,3000,32)); + } +} + +static void newcam_collision(void) +{ + struct Surface *surf; + Vec3f camdir; + Vec3f hitpos; + + camdir[0] = newcam_pos[0]-newcam_lookat[0]; + camdir[1] = newcam_pos[1]-newcam_lookat[1]; + camdir[2] = newcam_pos[2]-newcam_lookat[2]; + + + + find_surface_on_ray(newcam_pos_target, camdir, &surf, &hitpos); + + if (surf) + { + newcam_pos[0] = hitpos[0]; + newcam_pos[1] = approach_f32(hitpos[1],newcam_pos[1],25,-25); + newcam_pos[2] = hitpos[2]; + newcam_pan_x = 0; + newcam_pan_z = 0; + } +} + +static void newcam_set_pan(void) +{ + //Apply panning values based on Mario's direction. + if (gMarioState->action != ACT_HOLDING_BOWSER && gMarioState->action != ACT_SLEEPING && gMarioState->action != ACT_START_SLEEPING) + { + approach_f32_asymptotic_bool(&newcam_pan_x, lengthdir_x((160*newcam_panlevel)/100, -gMarioState->faceAngle[1]-0x4000), 0.05); + approach_f32_asymptotic_bool(&newcam_pan_z, lengthdir_y((160*newcam_panlevel)/100, -gMarioState->faceAngle[1]-0x4000), 0.05); + } + else + { + approach_f32_asymptotic_bool(&newcam_pan_x, 0, 0.05); + approach_f32_asymptotic_bool(&newcam_pan_z, 0, 0.05); + } + + newcam_pan_x = newcam_pan_x*(min(newcam_distance/newcam_distance_target,1)); + newcam_pan_z = newcam_pan_z*(min(newcam_distance/newcam_distance_target,1)); +} + +static void newcam_position_cam(void) +{ + f32 floorY = 0; + f32 floorY2 = 0; + s16 shakeX; + s16 shakeY; + + if (!(gMarioState->action & ACT_FLAG_SWIMMING)) + calc_y_to_curr_floor(&floorY, 1.f, 200.f, &floorY2, 0.9f, 200.f); + + newcam_update_values(); + shakeX = gLakituState.shakeMagnitude[1]; + shakeY = gLakituState.shakeMagnitude[0]; + //Fetch Mario's current position. Not hardcoded just for the sake of flexibility, though this specific bit is temp, because it won't always want to be focusing on Mario. + newcam_pos_target[0] = gMarioState->pos[0]; + newcam_pos_target[1] = gMarioState->pos[1]+newcam_extheight; + newcam_pos_target[2] = gMarioState->pos[2]; + //These will set the position of the camera to where Mario is supposed to be, minus adjustments for where the camera should be, on top of. + if (newcam_modeflags & NC_FLAG_POSX) + newcam_pos[0] = newcam_pos_target[0]+lengthdir_x(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY); + if (newcam_modeflags & NC_FLAG_POSY) + newcam_pos[2] = newcam_pos_target[2]+lengthdir_y(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY); + if (newcam_modeflags & NC_FLAG_POSZ) + newcam_pos[1] = newcam_pos_target[1]+lengthdir_y(newcam_distance,newcam_tilt+gLakituState.shakeMagnitude[0])+floorY; + if ((newcam_modeflags & NC_FLAG_FOCUSX) && (newcam_modeflags & NC_FLAG_FOCUSY) && (newcam_modeflags & NC_FLAG_FOCUSZ)) + newcam_set_pan(); + //Set where the camera wants to be looking at. This is almost always the place it's based off, too. + if (newcam_modeflags & NC_FLAG_FOCUSX) + newcam_lookat[0] = newcam_pos_target[0]-newcam_pan_x; + if (newcam_modeflags & NC_FLAG_FOCUSY) + newcam_lookat[1] = newcam_pos_target[1]+floorY2; + if (newcam_modeflags & NC_FLAG_FOCUSZ) + newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z; + + if (newcam_modeflags & NC_FLAG_COLLISION) + newcam_collision(); + +} + +//Nested if's baybeeeee +static void newcam_find_fixed(void) +{ + u8 i = 0; + newcam_mode = newcam_intendedmode; + newcam_modeflags = newcam_mode; + for (i = 0; i < sizeof(newcam_fixedcam); i++) + { + if (newcam_fixedcam[i].newcam_hard_levelID == gCurrLevelNum && newcam_fixedcam[i].newcam_hard_areaID == gCurrAreaIndex) + {//I didn't wanna just obliterate the horizontal plane of the IDE with a beefy if statement, besides, I think this runs slightly better anyway? + if (newcam_pos_target[0] > newcam_fixedcam[i].newcam_hard_X1) + if (newcam_pos_target[0] < newcam_fixedcam[i].newcam_hard_X2) + if (newcam_pos_target[1] > newcam_fixedcam[i].newcam_hard_Y1) + if (newcam_pos_target[1] < newcam_fixedcam[i].newcam_hard_Y2) + if (newcam_pos_target[2] > newcam_fixedcam[i].newcam_hard_Z1) + if (newcam_pos_target[2] < newcam_fixedcam[i].newcam_hard_Z2) + { + if (newcam_fixedcam[i].newcam_hard_permaswap) + newcam_intendedmode = newcam_fixedcam[i].newcam_hard_modeset; + newcam_mode = newcam_fixedcam[i].newcam_hard_modeset; + newcam_modeflags = newcam_mode; + + if (newcam_fixedcam[i].newcam_hard_camX != 32767 && !(newcam_modeflags & NC_FLAG_POSX)) + newcam_pos[0] = newcam_fixedcam[i].newcam_hard_camX; + if (newcam_fixedcam[i].newcam_hard_camY != 32767 && !(newcam_modeflags & NC_FLAG_POSY)) + newcam_pos[1] = newcam_fixedcam[i].newcam_hard_camY; + if (newcam_fixedcam[i].newcam_hard_camZ != 32767 && !(newcam_modeflags & NC_FLAG_POSZ)) + newcam_pos[2] = newcam_fixedcam[i].newcam_hard_camZ; + + if (newcam_fixedcam[i].newcam_hard_lookX != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSX)) + newcam_lookat[0] = newcam_fixedcam[i].newcam_hard_lookX; + if (newcam_fixedcam[i].newcam_hard_lookY != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSY)) + newcam_lookat[1] = newcam_fixedcam[i].newcam_hard_lookY; + if (newcam_fixedcam[i].newcam_hard_lookZ != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSZ)) + newcam_lookat[2] = newcam_fixedcam[i].newcam_hard_lookZ; + + newcam_yaw = atan2s(newcam_pos[0]-newcam_pos_target[0],newcam_pos[2]-newcam_pos_target[2]); + } + } + } +} + +static void newcam_apply_values(struct Camera *c) +{ + + c->pos[0] = newcam_pos[0]; + c->pos[1] = newcam_pos[1]; + c->pos[2] = newcam_pos[2]; + + c->focus[0] = newcam_lookat[0]; + c->focus[1] = newcam_lookat[1]; + c->focus[2] = newcam_lookat[2]; + + gLakituState.pos[0] = newcam_pos[0]; + gLakituState.pos[1] = newcam_pos[1]; + gLakituState.pos[2] = newcam_pos[2]; + + gLakituState.focus[0] = newcam_lookat[0]; + gLakituState.focus[1] = newcam_lookat[1]; + gLakituState.focus[2] = newcam_lookat[2]; + + c->yaw = -newcam_yaw+0x4000; + gLakituState.yaw = -newcam_yaw+0x4000; + + //Adds support for wing mario tower + if (gMarioState->floor->type == SURFACE_LOOK_UP_WARP) { + if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 0x18) >= 10) { + if (newcam_tilt < -8000 && gMarioState->forwardVel == 0) { + level_trigger_warp(gMarioState, 1); + } + } + } + +} + +//The ingame cutscene system is such a spaghetti mess I actually have to resort to something as stupid as this to cover every base. +void newcam_apply_outside_values(struct Camera *c, u8 bit) +{ + if (newcam_modeflags == NC_FLAG_XTURN) + { + if (bit) + newcam_yaw = -gMarioState->faceAngle[1]-0x4000; + else + newcam_yaw = -c->yaw+0x4000; + } +} + +//Main loop. +void newcam_loop(struct Camera *c) +{ + newcam_rotate_button(); + newcam_zoom_button(); + newcam_position_cam(); + newcam_find_fixed(); + if (gMarioObject) + 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: + if (newcam_sensitivityX > 10 && newcam_sensitivityX < 250) + newcam_sensitivityX += toggle; + break; + case 2: + if (newcam_sensitivityY > 10 && newcam_sensitivityY < 250) + newcam_sensitivityY += toggle; + break; + case 3: + newcam_invertX ^= 1; + break; + case 4: + newcam_invertY ^= 1; + break; + case 5: + if (newcam_aggression > 0 && newcam_aggression < 100) + newcam_aggression += toggle; + break; + case 6: + if (newcam_panlevel > 0 && newcam_panlevel < 100) + newcam_panlevel += toggle; + 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: + int_to_str(newcam_sensitivityX,newstring); + newcam_text(160,scroll-12,newstring,newcam_option_selection-i); + break; + case 2: + int_to_str(newcam_sensitivityY,newstring); + newcam_text(160,scroll-12,newstring,newcam_option_selection-i); + break; + case 3: + newcam_text(160,scroll-12,newcam_flags[newcam_invertX],newcam_option_selection-i); + break; + case 4: + newcam_text(160,scroll-12,newcam_flags[newcam_invertY],newcam_option_selection-i); + break; + case 5: + int_to_str(newcam_aggression,newstring); + newcam_text(160,scroll-12,newstring,newcam_option_selection-i); + break; + case 6: + 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) + { + #ifndef nosound + play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs); + #endif + if (newcam_option_open == 0) + newcam_option_open = 1; + else + { + newcam_option_open = 0; + save_file_set_setting(); + } + } + + 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 += 5; 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 += 5; 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/camera.c b/src/game/camera.c index e0bf05f4..deddc6d5 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -701,6 +701,10 @@ f32 calc_y_to_curr_floor(f32 *posOff, f32 posMul, f32 posBound, f32 *focOff, f32 *focOff = -focBound; } } +//Compiler gets mad if I put this any further above. thanks refresh 7 +#ifdef BETTERCAMERA +#include "bettercamera.inc.h" +#endif void focus_on_mario(Vec3f focus, Vec3f pos, f32 posYOff, f32 focYOff, f32 dist, s16 pitch, s16 yaw) { Vec3f marioPos; @@ -2853,6 +2857,10 @@ void set_camera_mode(struct Camera *c, s16 mode, s16 frames) { struct LinearTransitionPoint *start = &sModeInfo.transitionStart; struct LinearTransitionPoint *end = &sModeInfo.transitionEnd; +#ifdef BETTERCAMERA + if (mode != CAMERA_MODE_NEWCAM && gLakituState.mode != CAMERA_MODE_NEWCAM) + { +#endif if (mode == CAMERA_MODE_WATER_SURFACE && gCurrLevelArea == AREA_TTM_OUTSIDE) { } else { // Clear movement flags that would affect the transition @@ -2896,6 +2904,9 @@ void set_camera_mode(struct Camera *c, s16 mode, s16 frames) { vec3f_get_dist_and_angle(start->focus, start->pos, &start->dist, &start->pitch, &start->yaw); vec3f_get_dist_and_angle(end->focus, end->pos, &end->dist, &end->pitch, &end->yaw); } +#ifdef BETTERCAMERA + } +#endif } /** @@ -2980,7 +2991,12 @@ void update_lakitu(struct Camera *c) { gLakituState.roll += sHandheldShakeRoll; gLakituState.roll += gLakituState.keyDanceRoll; - if (c->mode != CAMERA_MODE_C_UP && c->cutscene == 0) { + if (c->mode != CAMERA_MODE_C_UP && c->cutscene == 0 +#ifdef BETTERCAMERA + && c->mode != CAMERA_MODE_NEWCAM +#endif + ) + { gCheckingSurfaceCollisionsForCamera = TRUE; distToFloor = find_floor(gLakituState.pos[0], gLakituState.pos[1] + 20.0f, @@ -3013,7 +3029,11 @@ void update_camera(struct Camera *c) { update_camera_hud_status(c); if (c->cutscene == 0) { // Only process R_TRIG if 'fixed' is not selected in the menu - if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) { + if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO +#ifdef BETTERCAMERA + && c->mode != CAMERA_MODE_NEWCAM +#endif + ) { if (gPlayer1Controller->buttonPressed & R_TRIG) { if (set_cam_angle(0) == CAM_ANGLE_LAKITU) { set_cam_angle(CAM_ANGLE_MARIO); @@ -3051,10 +3071,16 @@ void update_camera(struct Camera *c) { c->mode = gLakituState.mode; c->defMode = gLakituState.defMode; +#ifdef BETTERCAMERA + if (c->mode != CAMERA_MODE_NEWCAM) + { +#endif camera_course_processing(c); stub_camera_3(c); - sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed, - gPlayer1Controller->buttonDown); + sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed,gPlayer1Controller->buttonDown); +#ifdef BETTERCAMERA + } +#endif if (c->cutscene != 0) { sYawSpeed = 0; @@ -3092,6 +3118,12 @@ void update_camera(struct Camera *c) { mode_cannon_camera(c); break; +#ifdef BETTERCAMERA + case CAMERA_MODE_NEWCAM: + newcam_loop(c); + break; +#endif + default: mode_mario_camera(c); } @@ -3151,6 +3183,12 @@ void update_camera(struct Camera *c) { case CAMERA_MODE_SPIRAL_STAIRS: mode_spiral_stairs_camera(c); break; + +#ifdef BETTERCAMERA + case CAMERA_MODE_NEWCAM: + newcam_loop(c); + break; +#endif } } } @@ -3426,6 +3464,15 @@ void init_camera(struct Camera *c) { gLakituState.nextYaw = gLakituState.yaw; c->yaw = gLakituState.yaw; c->nextYaw = gLakituState.yaw; + +#ifdef BETTERCAMERA + if (newcam_active == 1) + { + gLakituState.mode = CAMERA_MODE_NEWCAM; + gLakituState.defMode = CAMERA_MODE_NEWCAM; + newcam_init(c, 0); + } +#endif } /** @@ -5514,6 +5561,10 @@ void set_camera_mode_8_directions(struct Camera *c) { s8DirModeBaseYaw = 0; s8DirModeYawOffset = 0; } +#ifdef BETTERCAMERA + if (newcam_active == 1) + c->mode = CAMERA_MODE_NEWCAM; +#endif } /** @@ -5532,6 +5583,10 @@ void set_camera_mode_close_cam(u8 *mode) { sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT; *mode = CAMERA_MODE_CLOSE; } +#ifdef BETTERCAMERA + if (newcam_active == 1) + *mode = CAMERA_MODE_NEWCAM; +#endif } /** @@ -5556,6 +5611,10 @@ void set_camera_mode_radial(struct Camera *c, s16 transitionTime) { } sModeOffsetYaw = 0; } +#ifdef BETTERCAMERA + if (newcam_active == 1) + c->mode = CAMERA_MODE_NEWCAM; +#endif } /** @@ -6934,6 +6993,9 @@ s16 cutscene_object(u8 cutscene, struct Object *o) { void update_camera_yaw(struct Camera *c) { c->nextYaw = calculate_yaw(c->focus, c->pos); c->yaw = c->nextYaw; +#ifdef BETTERCAMERA + newcam_apply_outside_values(c,0); +#endif } void cutscene_reset_spline(void) { @@ -9202,7 +9264,14 @@ BAD_RETURN(s32) cutscene_non_painting_end(struct Camera *c) { if (c->defMode == CAMERA_MODE_CLOSE) { c->mode = CAMERA_MODE_CLOSE; - } else { + } else +#ifdef BETTERCAMERA + if (c->defMode == CAMERA_MODE_NEWCAM) { + c->mode = CAMERA_MODE_NEWCAM; + } + else +#endif + { c->mode = CAMERA_MODE_FREE_ROAM; } @@ -9958,6 +10027,9 @@ BAD_RETURN(s32) cutscene_sliding_doors_follow_mario(struct Camera *c) { BAD_RETURN(s32) cutscene_sliding_doors_open(struct Camera *c) { UNUSED u32 pad[2]; +#ifdef BETTERCAMERA + newcam_apply_outside_values(c,1); +#endif reset_pan_distance(c); cutscene_event(cutscene_sliding_doors_open_start, c, 0, 8); cutscene_event(cutscene_sliding_doors_open_set_cvars, c, 8, 8); @@ -10154,7 +10226,12 @@ BAD_RETURN(s32) cutscene_unused_exit_focus_mario(struct Camera *c) { * Give control back to the player. */ BAD_RETURN(s32) cutscene_exit_painting_end(struct Camera *c) { - c->mode = CAMERA_MODE_CLOSE; +#ifdef BETTERCAMERA + if (newcam_active == 1) + c->mode = CAMERA_MODE_NEWCAM; + else +#endif + c->mode = CAMERA_MODE_CLOSE; c->cutscene = 0; gCutsceneTimer = CUTSCENE_STOP; sStatusFlags |= CAM_FLAG_SMOOTH_MOVEMENT; @@ -10314,11 +10391,24 @@ BAD_RETURN(s32) cutscene_door_follow_mario(struct Camera *c) { * Ends the door cutscene. Sets the camera mode to close mode unless the default is free roam. */ BAD_RETURN(s32) cutscene_door_end(struct Camera *c) { +#ifndef BETTERCAMERA if (c->defMode == CAMERA_MODE_FREE_ROAM) { c->mode = CAMERA_MODE_FREE_ROAM; } else { c->mode = CAMERA_MODE_CLOSE; } +#else + if (c->defMode == CAMERA_MODE_CLOSE) { + c->mode = CAMERA_MODE_CLOSE; + } else + if (c->defMode == CAMERA_MODE_NEWCAM) { + c->mode = CAMERA_MODE_NEWCAM; + } + else + { + c->mode = CAMERA_MODE_FREE_ROAM; + } +#endif c->cutscene = 0; gCutsceneTimer = CUTSCENE_STOP; diff --git a/src/game/camera.h b/src/game/camera.h index b9aecbec..42d78515 100644 --- a/src/game/camera.h +++ b/src/game/camera.h @@ -110,6 +110,9 @@ #define CAMERA_MODE_8_DIRECTIONS 0x0E // AKA Parallel Camera, Bowser Courses & Rainbow Road #define CAMERA_MODE_FREE_ROAM 0x10 #define CAMERA_MODE_SPIRAL_STAIRS 0x11 +#ifdef BETTERCAMERA +#define CAMERA_MODE_NEWCAM 0x12 +#endif #define CAM_MOVE_RETURN_TO_MIDDLE 0x0001 #define CAM_MOVE_ZOOMED_OUT 0x0002 diff --git a/src/game/game_init.c b/src/game/game_init.c index 4603acc4..75471ff7 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -19,6 +19,9 @@ #include "main_entry.h" #include "thread6.h" #include +#ifdef BETTERCAMERA +#include "bettercamera.h" +#endif // FIXME: I'm not sure all of these variables belong in this file, but I don't // know of a good way to split them @@ -58,6 +61,8 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence u16 gDemoInputListID = 0; struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check +extern int c_rightx; +extern int c_righty; /** * Initializes the Reality Display Processor (RDP). * This function initializes settings such as texture filtering mode, @@ -225,7 +230,7 @@ void create_task_structure(void) { gGfxSPTask->task.t.dram_stack_size = SP_DRAM_STACK_SIZE8; #ifdef VERSION_EU // terrible hack - gGfxSPTask->task.t.output_buff = + gGfxSPTask->task.t.output_buff = (u64 *)((u8 *) gGfxSPTaskOutputBuffer - 0x670 + 0x280); gGfxSPTask->task.t.output_buff_size = (u64 *)((u8 *) gGfxSPTaskOutputBuffer+ 0x280 + 0x17790); @@ -490,6 +495,7 @@ void read_controller_inputs(void) { for (i = 0; i < 2; i++) { struct Controller *controller = &gControllers[i]; +#ifndef BETTERCAMERA // if we're receiving inputs, update the controller struct // with the new button info. @@ -511,6 +517,47 @@ void read_controller_inputs(void) { controller->stickY = 0; controller->stickMag = 0; } +#else + if (i==1) // This is related to the analog camera control, using a P2 controller hack. P2 will no longer be correctly available for multiplayer. + { + if (c_rightx != 0 || c_righty !=0) + { + controller->rawStickX = c_rightx; + controller->rawStickY = c_righty; + controller->stickX = c_rightx; + controller->stickY = c_righty; + //printf("P2 = {%d, %d}\n", controller->rawStickX, controller->rawStickY); + continue; + } else + { + controller->rawStickX = 0; + controller->rawStickY = 0; + } + } + else + { + // if we're receiving inputs, update the controller struct + // with the new button info. + if (controller->controllerData != NULL) { + controller->rawStickX = controller->controllerData->stick_x; + controller->rawStickY = controller->controllerData->stick_y; + controller->buttonPressed = controller->controllerData->button + & (controller->controllerData->button ^ controller->buttonDown); + // 0.5x A presses are a good meme + controller->buttonDown = controller->controllerData->button; + adjust_analog_stick(controller); + } else // otherwise, if the controllerData is NULL, 0 out all of the inputs. + { + controller->rawStickX = 0; + controller->rawStickY = 0; + controller->buttonPressed = 0; + controller->buttonDown = 0; + controller->stickX = 0; + controller->stickY = 0; + controller->stickMag = 0; + } + } +#endif } // For some reason, player 1's inputs are copied to player 3's port. This diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index e05eff41..227062c1 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -19,6 +19,9 @@ #include "print.h" #include "engine/math_util.h" #include "course_table.h" +#ifdef BETTERCAMERA +#include "bettercamera.h" +#endif extern Gfx *gDisplayListHead; extern s16 gCurrCourseNum; @@ -693,7 +696,7 @@ void print_credits_string(s16 x, s16 y, const u8 *str) { gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD); gDPTileSync(gDisplayListHead++); - gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 2, 0, G_TX_RENDERTILE, 0, + gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 2, 0, G_TX_RENDERTILE, 0, G_TX_CLAMP, 3, G_TX_NOLOD, G_TX_CLAMP, 3, G_TX_NOLOD); gDPSetTileSize(gDisplayListHead++, G_TX_RENDERTILE, 0, 0, (8 - 1) << G_TEXTURE_IMAGE_FRAC, (8 - 1) << G_TEXTURE_IMAGE_FRAC); @@ -2615,7 +2618,10 @@ s16 render_pause_courses_and_castle(void) { #ifdef VERSION_EU gInGameLanguage = eu_get_language(); #endif - +#ifdef BETTERCAMERA + if (newcam_option_open == 0) + { +#endif switch (gDialogBoxState) { case DIALOG_STATE_OPENING: gDialogLineNum = 1; @@ -2691,6 +2697,16 @@ s16 render_pause_courses_and_castle(void) { if (gDialogTextAlpha < 250) { gDialogTextAlpha += 25; } +#ifdef BETTERCAMERA + } + else + { + shade_screen(); + newcam_display_options(); + } + newcam_check_pause_buttons(); + newcam_render_option_text(); +#endif return 0; } diff --git a/src/game/mario.c b/src/game/mario.c index aace34f6..164f92f5 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -31,6 +31,9 @@ #include "engine/surface_collision.h" #include "level_table.h" #include "thread6.h" +#ifdef BETTERCAMERA +#include "bettercamera.h" +#endif u32 unused80339F10; s8 filler80339F1C[20]; @@ -350,7 +353,7 @@ void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits) { void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) { if (actionSound == SOUND_ACTION_TERRAIN_JUMP) { play_mario_action_sound( - m, (m->flags & MARIO_METAL_CAP) ? (s32)SOUND_ACTION_METAL_JUMP + m, (m->flags & MARIO_METAL_CAP) ? (s32)SOUND_ACTION_METAL_JUMP : (s32)SOUND_ACTION_TERRAIN_JUMP, 1); } else { play_sound_if_no_flag(m, actionSound, MARIO_ACTION_SOUND_PLAYED); @@ -1306,7 +1309,14 @@ void update_mario_joystick_inputs(struct MarioState *m) { } if (m->intendedMag > 0.0f) { +#ifndef BETTERCAMERA m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + m->area->camera->yaw; +#else + if (gLakituState.mode != CAMERA_MODE_NEWCAM) + m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + m->area->camera->yaw; + else + m->intendedYaw = atan2s(-controller->stickY, controller->stickX)-newcam_yaw+0x4000; +#endif m->input |= INPUT_NONZERO_ANALOG; } else { m->intendedYaw = m->faceAngle[1]; diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 92e5dab1..451035ae 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -13,6 +13,9 @@ #include "audio/external.h" #include "engine/graph_node.h" #include "thread6.h" +#ifdef BETTERCAMERA +#include "bettercamera.h" +#endif void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3) { s32 animFrame = m->marioObj->header.gfx.unk38.animFrame; @@ -455,8 +458,8 @@ s32 act_jump(struct MarioState *m) { } s32 act_double_jump(struct MarioState *m) { - s32 animation = (m->vel[1] >= 0.0f) - ? MARIO_ANIM_DOUBLE_JUMP_RISE + s32 animation = (m->vel[1] >= 0.0f) + ? MARIO_ANIM_DOUBLE_JUMP_RISE : MARIO_ANIM_DOUBLE_JUMP_FALL; if (check_kick_or_dive_in_air(m)) { @@ -1676,7 +1679,17 @@ s32 act_shot_from_cannon(struct MarioState *m) { case AIR_STEP_LANDED: set_mario_action(m, ACT_DIVE_SLIDE, 0); m->faceAngle[0] = 0; +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif #ifdef VERSION_SH queue_rumble_data(5, 80); #endif @@ -1692,7 +1705,17 @@ s32 act_shot_from_cannon(struct MarioState *m) { m->particleFlags |= PARTICLE_VERTICAL_STAR; set_mario_action(m, ACT_BACKWARD_AIR_KB, 0); +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif break; case AIR_STEP_HIT_LAVA_WALL: @@ -1722,20 +1745,50 @@ s32 act_flying(struct MarioState *m) { if (m->input & INPUT_Z_PRESSED) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } return set_mario_action(m, ACT_GROUND_POUND, 1); } if (!(m->flags & MARIO_WING_CAP)) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } return set_mario_action(m, ACT_FREEFALL, 0); } if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } if (m->actionState == 0) { @@ -1775,7 +1828,17 @@ s32 act_flying(struct MarioState *m) { set_anim_to_frame(m, 7); m->faceAngle[0] = 0; +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif #ifdef VERSION_SH queue_rumble_data(5, 80); #endif @@ -1796,7 +1859,17 @@ s32 act_flying(struct MarioState *m) { m->particleFlags |= PARTICLE_VERTICAL_STAR; set_mario_action(m, ACT_BACKWARD_AIR_KB, 0); +#ifndef BETTERCAMERA + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } else { if (m->actionTimer++ == 0) { play_sound(SOUND_ACTION_HIT, m->marioObj->header.gfx.cameraToObject); @@ -1877,7 +1950,17 @@ s32 act_flying_triple_jump(struct MarioState *m) { #ifndef VERSION_JP if (m->input & (INPUT_B_PRESSED | INPUT_Z_PRESSED)) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, m->area->camera->defMode, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } if (m->input & INPUT_B_PRESSED) { return set_mario_action(m, ACT_DIVE, 0); @@ -1918,7 +2001,17 @@ s32 act_flying_triple_jump(struct MarioState *m) { if (m->vel[1] < 4.0f) { if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { +#ifndef BETTERCAMERA set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); +#else + if (newcam_active == 0) + set_camera_mode(m->area->camera, m->area->camera->defMode, 1); + else + { + m->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } +#endif } if (m->forwardVel < 32.0f) { @@ -1928,9 +2021,11 @@ s32 act_flying_triple_jump(struct MarioState *m) { set_mario_action(m, ACT_FLYING, 1); } +#ifndef BETTERCAMERA if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); } +#endif update_air_without_turn(m); diff --git a/src/game/save_file.c b/src/game/save_file.c index 6803fb69..6f429730 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -11,6 +11,9 @@ #include "level_table.h" #include "course_table.h" #include "thread6.h" +#ifdef BETTERCAMERA +#include "bettercamera.h" +#endif #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 @@ -565,6 +568,50 @@ u16 save_file_get_sound_mode(void) { return gSaveBuffer.menuData[0].soundMode; } +#ifdef BETTERCAMERA +void save_file_set_setting(void) { + + gSaveBuffer.menuData[0].camx = newcam_sensitivityX; + gSaveBuffer.menuData[0].camy = newcam_sensitivityY; + gSaveBuffer.menuData[0].invertx = newcam_invertX; + gSaveBuffer.menuData[0].inverty = newcam_invertY; + gSaveBuffer.menuData[0].camc = newcam_aggression; + gSaveBuffer.menuData[0].camp = newcam_panlevel; + gSaveBuffer.menuData[0].analogue = newcam_analogue; + + gSaveBuffer.menuData[0].firsttime = 1; + + + gMainMenuDataModified = TRUE; + save_main_menu_data(); +} + +void save_file_get_setting(void) { + newcam_sensitivityX = gSaveBuffer.menuData[0].camx; + newcam_sensitivityY = gSaveBuffer.menuData[0].camy; + newcam_invertX = gSaveBuffer.menuData[0].invertx; + newcam_invertY = gSaveBuffer.menuData[0].inverty; + newcam_aggression = gSaveBuffer.menuData[0].camc; + newcam_panlevel = gSaveBuffer.menuData[0].camp; + newcam_analogue = gSaveBuffer.menuData[0].analogue; + +} + +u8 save_check_firsttime(void) +{ + return gSaveBuffer.menuData[0].firsttime; +} + + +void save_set_firsttime(void) +{ + gSaveBuffer.menuData[0].firsttime = 1; + + gMainMenuDataModified = TRUE; + save_main_menu_data(); +} +#endif + void save_file_move_cap_to_default_location(void) { if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) { switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) { diff --git a/src/game/save_file.h b/src/game/save_file.h index 198748de..dca6dc72 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -6,7 +6,11 @@ #include "course_table.h" +#ifndef BETTERCAMERA #define EEPROM_SIZE 0x200 +#else +#define EEPROM_SIZE 0x800 +#endif #define NUM_SAVE_FILES 4 struct SaveBlockSignature @@ -50,7 +54,16 @@ struct MainMenuSaveData // on the high score screen. u32 coinScoreAges[NUM_SAVE_FILES]; u16 soundMode; - +#ifdef BETTERCAMERA + u8 camx; + u8 camy; + u8 analogue; + u8 invertx; + u8 inverty; + u8 camc; + u8 camp; + u8 firsttime; +#endif #ifdef VERSION_EU u16 language; #define SUBTRAHEND 8 @@ -58,8 +71,11 @@ struct MainMenuSaveData #define SUBTRAHEND 6 #endif + // Pad to match the EEPROM size of 0x200 (10 bytes on JP/US, 8 bytes on EU) + #ifndef BETTERCAMERA u8 filler[EEPROM_SIZE / 2 - SUBTRAHEND - NUM_SAVE_FILES * (4 + sizeof(struct SaveFile))]; + #endif struct SaveBlockSignature signature; }; @@ -70,6 +86,9 @@ struct SaveBuffer struct SaveFile files[NUM_SAVE_FILES][2]; // The main menu data has two copies. If one is bad, the other is used as a backup. struct MainMenuSaveData menuData[2]; + #ifdef BETTERCAMERA + u8 filler[1535]; //!I still haven't done an algorithm for this yet lol + #endif }; struct WarpNode; @@ -144,6 +163,12 @@ s32 save_file_get_cap_pos(Vec3s capPos); void save_file_set_sound_mode(u16 mode); u16 save_file_get_sound_mode(void); void save_file_move_cap_to_default_location(void); +#ifdef BETTERCAMERA +void save_set_firsttime(void); +u8 save_check_firsttime(void); +void save_file_get_setting(void); +void save_file_set_setting(void); +#endif void disable_warp_checkpoint(void); void check_if_should_set_warp_checkpoint(struct WarpNode *a); diff --git a/src/pc/controller/controller_api.h b/src/pc/controller/controller_api.h index dd318a8a..e040551a 100644 --- a/src/pc/controller/controller_api.h +++ b/src/pc/controller/controller_api.h @@ -1,6 +1,11 @@ #ifndef CONTROLLER_API #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 + #include struct ControllerAPI { diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index faf91f5f..920fa815 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -6,6 +6,14 @@ #include "controller_sdl.h" +// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors +// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera + +int16_t rightx; +int16_t righty; +int c_rightx; +int c_righty; + static struct ControllerAPI *controller_implementations[] = { &controller_recorded_tas, &controller_sdl, @@ -30,6 +38,16 @@ void osContGetReadData(OSContPad *pad) { pad->stick_y = 0; pad->errnum = 0; +#ifdef BETTERCAMERA + uint32_t magnitude_sq = (uint32_t)(rightx * rightx) + (uint32_t)(righty * righty); + if (magnitude_sq > (uint32_t)(DEADZONE * DEADZONE)) { + c_rightx = rightx / 0x100; + int stick_y = -righty / 0x100; + c_righty = stick_y == 128 ? 127 : stick_y; + } +#endif + + for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) { controller_implementations[i]->read(pad); } diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 68a50f5c..cae57020 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -5,11 +5,15 @@ #include +// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors +// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera + #include #include "controller_api.h" -#define DEADZONE 4960 +extern int16_t rightx; +extern int16_t righty; static bool init_ok; static SDL_GameController *sdl_cntrl; @@ -56,8 +60,8 @@ static void controller_sdl_read(OSContPad *pad) { int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); - int16_t rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX); - int16_t righty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTY); + rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX); + righty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTY); int16_t ltrig = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_TRIGGERLEFT); int16_t rtrig = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); From c4707eb36f7334f7c509ee7e186a38306b104d3d Mon Sep 17 00:00:00 2001 From: HengiFettlich Date: Fri, 8 May 2020 14:35:38 +0200 Subject: [PATCH 02/39] refactor fullscreen into own static function --- src/pc/gfx/gfx_sdl2.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 5a782f5d..ba6044f0 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -78,6 +78,22 @@ const SDL_Scancode scancode_rmapping_nonextended[][2] = { {SDL_SCANCODE_KP_MULTIPLY, SDL_SCANCODE_PRINTSCREEN} }; +static void gfx_sdl_set_fullscreen(bool fullscreen) +{ + if (fullscreen) + { + SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_ShowCursor(SDL_DISABLE); + } + else + { + SDL_SetWindowFullscreen(wnd, 0); + SDL_ShowCursor(SDL_ENABLE); + } + + configFullscreen = fullscreen; +} + static void gfx_sdl_init(void) { SDL_Init(SDL_INIT_VIDEO); @@ -101,11 +117,7 @@ static void gfx_sdl_init(void) { DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); #endif - if (configFullscreen) - { - SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowCursor(SDL_DISABLE); - } + gfx_sdl_set_fullscreen(configFullscreen); SDL_GL_CreateContext(wnd); SDL_GL_SetSwapInterval(2); // TODO 0, 1 or 2 or remove this line @@ -156,24 +168,11 @@ static void gfx_sdl_onkeydown(int scancode) { if (state[SDL_SCANCODE_LALT] && state[SDL_SCANCODE_RETURN]) { - if (!configFullscreen) - { - SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowCursor(SDL_DISABLE); - } - else - { - SDL_SetWindowFullscreen(wnd, 0); - SDL_ShowCursor(SDL_ENABLE); - } - - configFullscreen = !configFullscreen; + gfx_sdl_set_fullscreen(!configFullscreen); } else if (state[SDL_SCANCODE_ESCAPE] && configFullscreen) { - SDL_SetWindowFullscreen(wnd, 0); - SDL_ShowCursor(SDL_ENABLE); - configFullscreen = false; + gfx_sdl_set_fullscreen(false); } } From b0404194d232175ba2153e807018b46f1ba348cd Mon Sep 17 00:00:00 2001 From: vanfanel Date: Fri, 8 May 2020 16:47:17 +0200 Subject: [PATCH 03/39] Pass the correct CFLAGs for Rpi3 and Rpi4 when both models run a system with aarch64 kernel and libs. --- Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index aa36bc0a..1c5a5e6f 100644 --- a/Makefile +++ b/Makefile @@ -265,7 +265,7 @@ ifeq ($(TARGET_RPI),1) OPT_FLAGS := -march=armv6zk+fp -mfpu=vfp -Ofast endif -# Raspberry Pi 2 and 3 +# Raspberry Pi 2 and 3 in ARM 32bit mode ifneq (,$(findstring armv7l,$(machine))) model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') @@ -276,9 +276,15 @@ ifeq ($(TARGET_RPI),1) endif endif -# RPi4 / ARM A64 NEEDS TESTING 32BIT. +# RPi3 or RPi4, in ARM64 (aarch64) mode. NEEDS TESTING 32BIT. +# DO NOT pass -mfpu stuff here, thats for 32bit ARM only and will fail for 64bit ARM. ifneq (,$(findstring aarch64,$(machine))) - OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -O3 + model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') + ifneq (,$(findstring 3,$(model))) + OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -O3 + else ifneq (,$(findstring 4,$(model))) + OPT_FLAGS := -march=armv8-a+crc+simd -mtune=cortex-a72 -O3 + endif endif endif From ab52a3cbf56b1c77363eac359cbf7e5e82680089 Mon Sep 17 00:00:00 2001 From: vanfanel Date: Fri, 8 May 2020 17:06:23 +0200 Subject: [PATCH 04/39] Pass -DUSE_GLES to sdl2 GL init context instead of -DTARGET_RPI, since there are more GLES platforms out there that this engine will run on. --- Makefile | 3 ++- src/pc/gfx/gfx_sdl2.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 1c5a5e6f..1b0898cf 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,8 @@ endif ifeq ($(NON_MATCHING),1) VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints - VERSION_CFLAGS += -DTARGET_RPI + # Other platforms will use GLES2 eventually, not only RPis. + VERSION_CFLAGS += -DUSE_GLES endif VERSION_ASFLAGS := --defsym AVOID_UB=1 COMPARE := 0 diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index ba6044f0..309c19a2 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -100,7 +100,7 @@ static void gfx_sdl_init(void) { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - #ifdef TARGET_RPI + #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_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); @@ -109,18 +109,18 @@ static void gfx_sdl_init(void) { //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - #ifndef TARGET_RPI - wnd = SDL_CreateWindow("Super Mario 64 PC-Port", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + #ifndef USE_GLES + wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); #else - wnd = SDL_CreateWindow("Super Mario 64 RPi (GLES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL_ES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); #endif gfx_sdl_set_fullscreen(configFullscreen); SDL_GL_CreateContext(wnd); - SDL_GL_SetSwapInterval(2); // TODO 0, 1 or 2 or remove this line + 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; From bdfdb176845094ca1d0f96c9610cb5ca030dce5b 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, 8 May 2020 13:29:35 -0300 Subject: [PATCH 05/39] Added a new Windows guide. --- README.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 32cd8b64..ce833e2b 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,62 @@ make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable ### On Windows -A full guide is to be written. You can use [mxe](https://mxe.cc/) and MinGW. +#### 1. Set up MSYS2, following [this guide](https://github.com/orlp/dev-on-windows/wiki/Installing-GCC--&-MSYS2). + +#### 2. Install dependencies +``` +pacman -S mingw-w64-i686-glew mingw-w64-x86_64-glew mingw-w64-i686-SDL2 mingw-w64-x86_64-SDL2 python3 +``` +#### 3. Copy baserom(s) for asset extraction + +For each version (jp/us/eu) that you want to build an executable for, put an existing ROM at +`./baserom..z64` for asset extraction. + +#### 4. On MSYS2, navigate to the sm64pc folder and then enter `./tools/audiofile-0.3.6/`. Inside this directory, run +``` +autoreconf -i +``` + +Only leave this directory on step 9. + +#### 5. Run the `configure` script +``` +PATH=/mingw64/bin:/mingw32/bin:$PATH LIBS=-lstdc++ ./configure --disable-docs +``` +#### 6. Run the `make` script +``` +PATH=/mingw64/bin:/mingw32/bin:$PATH make +``` +#### 7. Create a lib directory in `tools/` +``` +mkdir ../lib +``` + +#### 8. Copy the compiled libaudiofile to `tools/lib/` +``` +cp libaudiofile/.libs/libaudiofile.a ../lib/ +cp libaudiofile/.libs/libaudiofile.la ../lib/ +``` + +#### 9. Navigate back to `tools/`, then alter the `Makefile` and add `-lstdc++` on the following line +``` +tabledesign_CFLAGS := -Wno-uninitialized -laudiofile -lstdc++ +``` + +#### 10. Run `make` +``` +PATH=/mingw64/bin:/mingw32/bin:$PATH make +``` + +#### 11. Navigate back to the sm64pc root directory. + +#### 12. Finally, run `make` once more. (Note that mingw32 and mingw64 have been swapped. This is so you can build the 32bit application successfully.) +``` +PATH=/mingw32/bin:/mingw64/bin:$PATH make +``` + +This guide is a courtesy of [XNBlank](https://github.com/XNBlank). + ### For the web From 65c297dcf04a9c8c77994589673c4ac1113126f8 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, 8 May 2020 13:32:31 -0300 Subject: [PATCH 06/39] Mention Raspberry Pi building and formatting fix. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ce833e2b..7f87181c 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Run `make` to build (defaults to `VERSION=us`) ``` make VERSION=jp -j6 # build (J) version with 6 jobs make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable +make TARGET_RPI=1 # targets an executable for a Raspberry Pi ``` ### On Windows @@ -114,7 +115,10 @@ PATH=/mingw64/bin:/mingw32/bin:$PATH make #### 11. Navigate back to the sm64pc root directory. -#### 12. Finally, run `make` once more. (Note that mingw32 and mingw64 have been swapped. This is so you can build the 32bit application successfully.) +#### 12. Finally, run `make` once more. + +(Note that mingw32 and mingw64 have been swapped. This is so you can build the 32bit application successfully.) + ``` PATH=/mingw32/bin:/mingw64/bin:$PATH make ``` From 0690451684937273dcd8a77acafba61ce461ba43 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, 8 May 2020 14:55:25 -0300 Subject: [PATCH 07/39] Update .gitignore to remove patch/wiggle residue `git patch` makes a .rej file for every rejection, and wiggle makes a .porig for every rejection fixed. This can add up to a lot of junk. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 06cc0022..2f56cebf 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ *.ilk *.exp +# Patch and wiggle related residdue +*.rej +*.porig + # Precompiled Headers *.gch *.pch From 0859a0cfefb7521c7204172fe79e97cf045b37fb 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, 8 May 2020 16:16:53 -0300 Subject: [PATCH 08/39] Nothing to see here --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 7f87181c..180f12f4 100644 --- a/README.md +++ b/README.md @@ -123,9 +123,6 @@ PATH=/mingw64/bin:/mingw32/bin:$PATH make PATH=/mingw32/bin:/mingw64/bin:$PATH make ``` -This guide is a courtesy of [XNBlank](https://github.com/XNBlank). - - ### For the web The game can be compiled for web browsers that support WebGL using [Emscripten](https://github.com/emscripten-core). To do so, install [emsdk](https://github.com/emscripten-core/emsdk) and run `make TARGET_WEB=1`. From aaa26021f6c500ceed65522352313dbc2a91031f Mon Sep 17 00:00:00 2001 From: albertw <3dsgitasw@gmail.com> Date: Fri, 8 May 2020 19:11:59 -0700 Subject: [PATCH 09/39] Add libSDL and emsdk to support building linux and web in container --- Dockerfile | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index dbc31e2a..a4344f26 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,11 +5,14 @@ RUN apt-get update && \ binutils-mips-linux-gnu \ bsdmainutils \ build-essential \ + git \ libaudiofile-dev \ + libsdl2-dev \ pkg-config \ python3 \ wget \ - zlib1g-dev + zlib1g-dev && \ + rm -rf /var/lib/apt/lists/* RUN wget \ https://github.com/n64decomp/qemu-irix/releases/download/v2.11-deb/qemu-irix-2.11.0-2169-g32ab296eef_amd64.deb \ @@ -18,9 +21,16 @@ RUN wget \ dpkg -i qemu.deb && \ rm qemu.deb +RUN cd /tmp && \ + git clone https://github.com/emscripten-core/emsdk.git && \ + cd emsdk && \ + ./emsdk install latest && \ + cd .. && \ + rm -rf emsdk + RUN mkdir /sm64 WORKDIR /sm64 -ENV PATH="/sm64/tools:${PATH}" +ENV PATH="/sm64/tools:/emsdk:${PATH}" CMD echo 'usage: docker run --rm --mount type=bind,source="$(pwd)",destination=/sm64 sm64 make VERSION=${VERSION:-us} -j4\n' \ 'see https://github.com/n64decomp/sm64/blob/master/README.md for advanced usage' From 3ff6d4d38e86f67cb2798fcef456974921b04c22 Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Sat, 9 May 2020 03:29:10 +0100 Subject: [PATCH 10/39] Strip out N64 ROM building from Makefile --- Makefile | 317 +++++++++++++++---------------------------------------- 1 file changed, 87 insertions(+), 230 deletions(-) diff --git a/Makefile b/Makefile index c862063a..7640d351 100644 --- a/Makefile +++ b/Makefile @@ -16,17 +16,15 @@ GRUCODE ?= f3d_old # If COMPARE is 1, check the output sha1sum when building 'all' COMPARE ?= 1 # If NON_MATCHING is 1, define the NON_MATCHING and AVOID_UB macros when building (recommended) -NON_MATCHING ?= 0 -# Build for the N64 (turn this off for ports) +NON_MATCHING ?= 1 +# Sane default until N64 build scripts rm'd TARGET_N64 ?= 0 + # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 # Compiler to use (ido or gcc) COMPILER ?= ido -ifeq ($(COMPILER),gcc) - NON_MATCHING := 1 -endif # Build for Emscripten/WebGL TARGET_WEB ?= 0 # Specify the target you are building for, 0 means native @@ -39,18 +37,18 @@ else BITS := endif -# Automatic settings only for ports -ifeq ($(TARGET_N64),0) - NON_MATCHING := 1 - GRUCODE := f3dex2e - WINDOWS_BUILD := 0 - ifeq ($(TARGET_WEB),0) - ifeq ($(OS),Windows_NT) - WINDOWS_BUILD := 1 - endif - endif +# Automatic settings for PC port(s) -# Release +NON_MATCHING := 1 +GRUCODE := f3dex2e +WINDOWS_BUILD := 0 + +ifeq ($(TARGET_WEB),0) +ifeq ($(OS),Windows_NT) +WINDOWS_BUILD := 1 +endif + +# Release (version) flag defs ifeq ($(VERSION),jp) VERSION_CFLAGS := -DVERSION_JP @@ -103,7 +101,7 @@ ifeq ($(GRUCODE), f3dex2) # Fast3DEX2 TARGET := $(TARGET).f3dex2 COMPARE := 0 else -ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (for PC) +ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (PC default) GRUCODE_CFLAGS := -DF3DEX_GBI_2E TARGET := $(TARGET).f3dex2e COMPARE := 0 @@ -126,18 +124,15 @@ endif endif endif -ifeq ($(TARGET_N64),0) - NON_MATCHING := 1 +# Default build is for PC now +VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB + +ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints + VERSION_CFLAGS += -DUSE_GLES endif -ifeq ($(NON_MATCHING),1) - VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB - ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints - VERSION_CFLAGS += -DTARGET_RPI - endif - VERSION_ASFLAGS := --defsym AVOID_UB=1 - COMPARE := 0 -endif +VERSION_ASFLAGS := --defsym AVOID_UB=1 +COMPARE := 0 ifeq ($(TARGET_WEB),1) VERSION_CFLAGS := $(VERSION_CFLAGS) -DTARGET_WEB @@ -174,34 +169,30 @@ endif # BUILD_DIR is location where all build artifacts are placed BUILD_DIR_BASE := build -ifeq ($(TARGET_N64),1) - BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION) -else + ifeq ($(TARGET_WEB),1) BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_web else BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_pc endif -endif LIBULTRA := $(BUILD_DIR)/libultra.a + ifeq ($(TARGET_WEB),1) EXE := $(BUILD_DIR)/$(TARGET).html -else -ifeq ($(WINDOWS_BUILD),1) -EXE := $(BUILD_DIR)/$(TARGET).exe + else + ifeq ($(WINDOWS_BUILD),1) + EXE := $(BUILD_DIR)/$(TARGET).exe -else #Linux builds here -ifeq ($(TARGET_RPI),1) -EXE := $(BUILD_DIR)/$(TARGET).arm -else -EXE := $(BUILD_DIR)/$(TARGET) -endif + else # Linux builds/binary namer + ifeq ($(TARGET_RPI),1) + EXE := $(BUILD_DIR)/$(TARGET).arm + else + EXE := $(BUILD_DIR)/$(TARGET) + endif + endif endif -endif - -ROM := $(BUILD_DIR)/$(TARGET).z64 ELF := $(BUILD_DIR)/$(TARGET).elf LD_SCRIPT := sm64.ld MIO0_DIR := $(BUILD_DIR)/bin @@ -211,14 +202,11 @@ ACTOR_DIR := actors LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h))) # Directories containing source files -SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets -ASM_DIRS := lib -ifeq ($(TARGET_N64),1) - ASM_DIRS := asm $(ASM_DIRS) -else - SRC_DIRS := $(SRC_DIRS) src/pc src/pc/gfx src/pc/audio src/pc/controller - ASM_DIRS := -endif + +# Hi, I'm a PC +SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller +ASM_DIRS := + BIN_DIRS := bin bin/$(VERSION) ULTRA_SRC_DIRS := lib/src lib/src/math @@ -244,28 +232,27 @@ else endif endif -ifeq ($(TARGET_N64),0) - OPT_FLAGS += $(BITS) -endif +# Set BITS (32/64) to compile for +OPT_FLAGS += $(BITS) ifeq ($(TARGET_WEB),1) OPT_FLAGS := -O2 -g4 --source-map-base http://localhost:8080/ endif endif -# Use a default opt flag for gcc -ifeq ($(NON_MATCHING),1) - OPT_FLAGS := -O2 +# Use a default opt flag for gcc, then override if RPi +ifeq ($(COMPILER),gcc) +OPT_FLAGS := -O2 # Breaks sound on x86? endif ifeq ($(TARGET_RPI),1) - machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') + machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') # Raspberry Pi B+, Zero, etc - ifneq (,$(findstring armv6l,$(machine))) + ifneq (,$(findstring armv6l,$(machine))) OPT_FLAGS := -march=armv6zk+fp -mfpu=vfp -Ofast endif -# Raspberry Pi 2 and 3 +# Raspberry Pi 2 and 3 in ARM 32bit mode ifneq (,$(findstring armv7l,$(machine))) model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') @@ -276,9 +263,19 @@ ifeq ($(TARGET_RPI),1) endif endif -# RPi4 / ARM A64 NEEDS TESTING 32BIT. - ifneq (,$(findstring aarch64,$(machine))) - OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -O3 + +# RPi3 or RPi4, in ARM64 (aarch64) mode. NEEDS TESTING 32BIT. +# DO NOT pass -mfpu stuff here, thats for 32bit ARM only and will fail for 64bit ARM. + + ifneq (,$(findstring aarch64,$(machine))) + model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') + + ifneq (,$(findstring 3,$(model))) + OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -O3 + else ifneq (,$(findstring 4,$(model))) + OPT_FLAGS := -march=armv8-a+crc+simd -mtune=cortex-a72 -O3 + endif + endif endif @@ -292,9 +289,7 @@ CXX_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp)) S_FILES := $(foreach dir,$(ASM_DIRS),$(wildcard $(dir)/*.s)) ULTRA_C_FILES := $(foreach dir,$(ULTRA_SRC_DIRS),$(wildcard $(dir)/*.c)) GODDARD_C_FILES := $(foreach dir,$(GODDARD_SRC_DIRS),$(wildcard $(dir)/*.c)) -ifeq ($(TARGET_N64),1) - ULTRA_S_FILES := $(foreach dir,$(ULTRA_ASM_DIRS),$(wildcard $(dir)/*.s)) -endif + GENERATED_C_FILES := $(BUILD_DIR)/assets/mario_anim_data.c $(BUILD_DIR)/assets/demo_data.c \ $(addprefix $(BUILD_DIR)/bin/,$(addsuffix _skybox.c,$(notdir $(basename $(wildcard textures/skyboxes/*.png))))) @@ -302,7 +297,9 @@ ifeq ($(WINDOWS_BUILD),0) CXX_FILES := endif -ifneq ($(TARGET_N64),1) +# We need to keep this for now +# If we're not N64 use below + ULTRA_C_FILES_SKIP := \ sqrtf.c \ string.c \ @@ -361,7 +358,8 @@ ifneq ($(TARGET_N64),1) C_FILES := $(filter-out src/game/main.c,$(C_FILES)) ULTRA_C_FILES := $(filter-out $(addprefix lib/src/,$(ULTRA_C_FILES_SKIP)),$(ULTRA_C_FILES)) -endif + +# "If we're not N64, use the above" ifeq ($(VERSION),sh) SOUND_BANK_FILES := $(wildcard sound/sound_banks/*.json) @@ -386,7 +384,6 @@ SOUND_OBJ_FILES := $(SOUND_BIN_DIR)/sound_data.ctl.o \ $(SOUND_BIN_DIR)/sequences.bin.o \ $(SOUND_BIN_DIR)/bank_sets.o - # Object files O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \ $(foreach file,$(CXX_FILES),$(BUILD_DIR)/$(file:.cpp=.o)) \ @@ -401,13 +398,6 @@ GODDARD_O_FILES := $(foreach file,$(GODDARD_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) # Automatic dependency files DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(BUILD_DIR)/$(LD_SCRIPT).d -# Files with GLOBAL_ASM blocks -ifneq ($(NON_MATCHING),1) -GLOBAL_ASM_C_FILES != grep -rl 'GLOBAL_ASM(' $(wildcard src/**/*.c) -GLOBAL_ASM_O_FILES = $(foreach file,$(GLOBAL_ASM_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) -GLOBAL_ASM_DEP = $(BUILD_DIR)/src/audio/non_matching_dep -endif - # Segment elf files SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES) @@ -415,82 +405,23 @@ SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES) INCLUDE_CFLAGS := -I include -I $(BUILD_DIR) -I $(BUILD_DIR)/include -I src -I . ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth -ifeq ($(TARGET_N64),1) -IRIX_ROOT := tools/ido5.3_compiler - -ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips-linux-gnu- -else ifeq ($(shell type mips64-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips64-linux-gnu- -else ifeq ($(shell type mips64-elf-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips64-elf- -endif - -# check that either QEMU_IRIX is set or qemu-irix package installed -ifndef QEMU_IRIX - QEMU_IRIX := $(shell which qemu-irix) - ifeq (, $(QEMU_IRIX)) - $(error Please install qemu-irix package or set QEMU_IRIX env var to the full qemu-irix binary path) - endif -endif - -AS := $(CROSS)as -CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc -CPP := cpp -P -Wno-trigraphs -LD := $(CROSS)ld -AR := $(CROSS)ar -OBJDUMP := $(CROSS)objdump -OBJCOPY := $(CROSS)objcopy -PYTHON := python3 - -# change the compiler to gcc, to use the default, install the gcc-mips-linux-gnu package -ifeq ($(COMPILER),gcc) - CC := $(CROSS)gcc -endif - -ifeq ($(TARGET_N64),1) - TARGET_CFLAGS := -nostdinc -I include/libc -DTARGET_N64 - CC_CFLAGS := -fno-builtin -endif - -# Check code syntax with host compiler -CC_CHECK := gcc -fsyntax-only -fsigned-char $(CC_CFLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) -std=gnu90 -Wall -Wextra -Wno-format-security -Wno-main -DNON_MATCHING -DAVOID_UB $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) - -COMMON_CFLAGS = $(OPT_FLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(MIPSISET) $(GRUCODE_CFLAGS) - -ASFLAGS := -march=vr4300 -mabi=32 -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) $(GRUCODE_ASFLAGS) -CFLAGS = -Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -Xfullwarn -signed $(COMMON_CFLAGS) $(MIPSBIT) -OBJCOPYFLAGS := --pad-to=0x800000 --gap-fill=0xFF -SYMBOL_LINKING_FLAGS := $(addprefix -R ,$(SEG_FILES)) -LDFLAGS := -T undefined_syms.txt -T $(BUILD_DIR)/$(LD_SCRIPT) -Map $(BUILD_DIR)/sm64.$(VERSION).map --no-check-sections $(SYMBOL_LINKING_FLAGS) -ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth - -ifeq ($(COMPILER),gcc) - CFLAGS := -march=vr4300 -mfix4300 -mno-shared -G 0 -mhard-float -fno-stack-protector -fno-common -I include -I src/ -I $(BUILD_DIR)/include -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra $(COMMON_CFLAGS) -endif - -ifeq ($(shell getconf LONG_BIT), 32) - # Work around memory allocation bug in QEMU - export QEMU_GUEST_BASE := 1 -else - # Ensure that gcc treats the code as 32-bit - CC_CHECK += $(BITS) -endif - -else # TARGET_N64 +# Huge deleted N64 section was here AS := as -ifneq ($(TARGET_WEB),1) + +ifneq ($(TARGET_WEB),1) # As in, not-web PC port CC := $(CROSS)gcc CXX := $(CROSS)g++ else CC := emcc endif + ifeq ($(WINDOWS_BUILD),1) LD := $(CXX) else LD := $(CC) endif + CPP := cpp -P OBJDUMP := objdump OBJCOPY := objcopy @@ -499,9 +430,11 @@ PYTHON := python3 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` + 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 CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv -s USE_SDL=2 + # 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` @@ -513,9 +446,11 @@ 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) 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 else + # Linux / Other builds below ifeq ($(TARGET_RPI),1) LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(CROSS)sdl2-config --libs` -no-pie @@ -525,14 +460,13 @@ endif endif endif #Added for Pi ifeq -endif # Prevent a crash with -sopt export LANG := C ####################### Other Tools ######################### -# N64 tools +# N64 conversion tools TOOLS_DIR = tools MIO0TOOL = $(TOOLS_DIR)/mio0 N64CKSUM = $(TOOLS_DIR)/n64cksum @@ -550,32 +484,13 @@ LOADER = loader64 LOADER_FLAGS = -vwf SHA1SUM = sha1sum -# Use Objcopy instead of extract_data_for_mio -ifeq ($(COMPILER),gcc) -EXTRACT_DATA_FOR_MIO := $(OBJCOPY) -O binary --only-section=.data -endif - ###################### Dependency Check ##################### -ifeq ($(TARGET_N64),1) -BINUTILS_VER_MAJOR := $(shell $(LD) --version | grep ^GNU | sed 's/^.* //; s/\..*//g') -BINUTILS_VER_MINOR := $(shell $(LD) --version | grep ^GNU | sed 's/^[^.]*\.//; s/\..*//g') -BINUTILS_DEPEND := $(shell expr $(BINUTILS_VER_MAJOR) \>= 2 \& $(BINUTILS_VER_MINOR) \>= 27) -ifeq ($(BINUTILS_DEPEND),0) -$(error binutils version 2.27 required, version $(BINUTILS_VER_MAJOR).$(BINUTILS_VER_MINOR) detected) -endif -endif +# Stubbed ######################## Targets ############################# -ifeq ($(TARGET_N64),1) -all: $(ROM) -ifeq ($(COMPARE),1) - @$(SHA1SUM) -c $(TARGET).sha1 || (echo 'The build succeeded, but did not match the official ROM. This is expected if you are making changes to the game.\nTo silence this message, use "make COMPARE=0"'. && false) -endif -else all: $(EXE) -endif clean: $(RM) -r $(BUILD_DIR_BASE) @@ -606,10 +521,6 @@ $(BUILD_DIR)/include/text_strings.h: include/text_strings.h.in $(BUILD_DIR)/include/text_menu_strings.h: include/text_menu_strings.h.in $(TEXTCONV) charmap_menu.txt $< $@ -ifeq ($(COMPILER),gcc) -$(BUILD_DIR)/lib/src/math/%.o: CFLAGS += -fno-builtin -endif - ifeq ($(VERSION),eu) TEXT_DIRS := text/de text/us text/fr @@ -635,7 +546,6 @@ $(BUILD_DIR)/bin/segment2.o: $(BUILD_DIR)/text/$(VERSION)/define_text.inc.c endif endif - $(BUILD_DIR)/text/%/define_courses.inc.c: text/define_courses.inc.c text/%/courses.h $(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/ $(TEXTCONV) charmap.txt $@ $@ @@ -644,7 +554,6 @@ $(BUILD_DIR)/text/%/define_text.inc.c: text/define_text.inc.c text/%/courses.h t $(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/ $(TEXTCONV) charmap.txt $@ $@ -O_FILES += $(wildcard $(BUILD_DIR)/bin/$(VERSION)/*.o) ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GODDARD_SRC_DIRS) $(ULTRA_SRC_DIRS) $(ULTRA_ASM_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) include) $(MIO0_DIR) $(addprefix $(MIO0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) @@ -652,9 +561,17 @@ ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GOD DUMMY != mkdir -p $(ALL_DIRS) $(BUILD_DIR)/include/text_strings.h: $(BUILD_DIR)/include/text_menu_strings.h + +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 +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 +endif ################################################################ # TEXTURE GENERATION # @@ -680,38 +597,7 @@ $(BUILD_DIR)/%.ci4: %.ci4.png # compressed segment generation -ifeq ($(TARGET_N64),1) -# TODO: ideally this would be `-Trodata-segment=0x07000000` but that doesn't set the address - -$(BUILD_DIR)/bin/%.elf: $(BUILD_DIR)/bin/%.o - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $< -$(BUILD_DIR)/actors/%.elf: $(BUILD_DIR)/actors/%.o - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $< - -# Override for level.elf, which otherwise matches the above pattern -.SECONDEXPANSION: -$(BUILD_DIR)/levels/%/leveldata.elf: $(BUILD_DIR)/levels/%/leveldata.o $(BUILD_DIR)/bin/$$(TEXTURE_BIN).elf - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map --just-symbols=$(BUILD_DIR)/bin/$(TEXTURE_BIN).elf -o $@ $< - -$(BUILD_DIR)/bin/%.bin: $(BUILD_DIR)/bin/%.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/actors/%.bin: $(BUILD_DIR)/actors/%.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/levels/%/leveldata.bin: $(BUILD_DIR)/levels/%/leveldata.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/%.mio0: $(BUILD_DIR)/%.bin - $(MIO0TOOL) $< $@ - -$(BUILD_DIR)/%.mio0.o: $(BUILD_DIR)/%.mio0.s - $(AS) $(ASFLAGS) -o $@ $< - -$(BUILD_DIR)/%.mio0.s: $(BUILD_DIR)/%.mio0 - printf ".section .data\n\n.incbin \"$<\"\n" > $@ -endif - +# PC Area $(BUILD_DIR)/%.table: %.aiff $(AIFF_EXTRACT_CODEBOOK) $< >$@ @@ -748,10 +634,7 @@ $(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o $(SOUND_BIN_DIR)/%.o: $(SOUND_BIN_DIR)/%.s $(AS) $(ASFLAGS) -o $@ $< -ifeq ($(TARGET_N64),1) -$(SOUND_BIN_DIR)/%.s: $(SOUND_BIN_DIR)/% - printf ".section .data\n\n.incbin \"$<\"\n" > $@ -else + $(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl echo "unsigned char gSoundDataADSR[] = {" > $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@ @@ -771,7 +654,6 @@ $(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets echo "unsigned char gBankSetsData[] = {" > $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@ echo "};" >> $@ -endif $(BUILD_DIR)/levels/scripts.o: $(BUILD_DIR)/include/level_headers.h @@ -828,9 +710,6 @@ $(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp endif endif -ifeq ($(NON_MATCHING),0) -$(GLOBAL_ASM_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) -- -endif # Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes. $(GLOBAL_ASM_O_FILES): $(GLOBAL_ASM_DEP).$(NON_MATCHING) @@ -854,32 +733,10 @@ $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c $(BUILD_DIR)/%.o: %.s $(AS) $(ASFLAGS) -MD $(BUILD_DIR)/$*.d -o $@ $< -ifeq ($(TARGET_N64),1) -$(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) - $(CPP) $(VERSION_CFLAGS) -MMD -MP -MT $@ -MF $@.d -I include/ -I . -DBUILD_DIR=$(BUILD_DIR) -o $@ $< -$(BUILD_DIR)/libultra.a: $(ULTRA_O_FILES) - $(AR) rcs -o $@ $(ULTRA_O_FILES) - tools/patch_libultra_math $@ -$(BUILD_DIR)/libgoddard.a: $(GODDARD_O_FILES) - $(AR) rcs -o $@ $(GODDARD_O_FILES) - -$(ELF): $(O_FILES) $(MIO0_OBJ_FILES) $(SOUND_OBJ_FILES) $(SEG_FILES) $(BUILD_DIR)/$(LD_SCRIPT) undefined_syms.txt $(BUILD_DIR)/libultra.a $(BUILD_DIR)/libgoddard.a - $(LD) -L $(BUILD_DIR) $(LDFLAGS) -o $@ $(O_FILES)$(LIBS) -lultra -lgoddard - -$(ROM): $(ELF) - $(OBJCOPY) $(OBJCOPYFLAGS) $< $(@:.z64=.bin) -O binary - $(N64CKSUM) $(@:.z64=.bin) $@ - -$(BUILD_DIR)/$(TARGET).objdump: $(ELF) - $(OBJDUMP) -D $< > $@ - -else $(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS) -endif - .PHONY: all clean distclean default diff test load libultra .PRECIOUS: $(BUILD_DIR)/bin/%.elf $(SOUND_BIN_DIR)/%.ctl $(SOUND_BIN_DIR)/%.tbl $(SOUND_SAMPLE_TABLES) $(SOUND_BIN_DIR)/%.s $(BUILD_DIR)/% From 2b188036cbd2ee730b3e66564a15db611e60c6a6 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sat, 9 May 2020 01:17:42 -0300 Subject: [PATCH 11/39] Slight Makefile update Change TARGET_N64 ?= to TARGET_N64 = --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 625384a1..9b829f36 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ COMPARE ?= 1 # If NON_MATCHING is 1, define the NON_MATCHING and AVOID_UB macros when building (recommended) NON_MATCHING ?= 1 # Sane default until N64 build scripts rm'd -TARGET_N64 ?= 0 +TARGET_N64 = 0 # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 From ef2cd47343c07edd95db76b4f3748eebd45c8507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20R=2E=20Miguel?= Date: Sat, 9 May 2020 01:19:13 -0300 Subject: [PATCH 12/39] True analog camera control has been added. --- src/game/game_init.c | 74 ++++++++++------------ src/pc/controller/controller_entry_point.c | 4 ++ 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/game/game_init.c b/src/game/game_init.c index 75471ff7..0a2c0cab 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -487,52 +487,20 @@ void read_controller_inputs(void) { if (gControllerBits) { osRecvMesg(&gSIEventMesgQueue, &D_80339BEC, OS_MESG_BLOCK); osContGetReadData(&gControllerPads[0]); -#ifdef VERSION_SH - release_rumble_pak_control(); -#endif } run_demo_inputs(); - for (i = 0; i < 2; i++) { + #ifdef BETTERCAMERA + for (i = 0; i < 2; i++) + { struct Controller *controller = &gControllers[i]; -#ifndef BETTERCAMERA - // if we're receiving inputs, update the controller struct - // with the new button info. - if (controller->controllerData != NULL) { - controller->rawStickX = controller->controllerData->stick_x; - controller->rawStickY = controller->controllerData->stick_y; - controller->buttonPressed = controller->controllerData->button - & (controller->controllerData->button ^ controller->buttonDown); - // 0.5x A presses are a good meme - controller->buttonDown = controller->controllerData->button; - adjust_analog_stick(controller); - } else // otherwise, if the controllerData is NULL, 0 out all of the inputs. - { - controller->rawStickX = 0; - controller->rawStickY = 0; - controller->buttonPressed = 0; - controller->buttonDown = 0; - controller->stickX = 0; - controller->stickY = 0; - controller->stickMag = 0; - } -#else if (i==1) // This is related to the analog camera control, using a P2 controller hack. P2 will no longer be correctly available for multiplayer. { - if (c_rightx != 0 || c_righty !=0) - { - controller->rawStickX = c_rightx; - controller->rawStickY = c_righty; - controller->stickX = c_rightx; - controller->stickY = c_righty; - //printf("P2 = {%d, %d}\n", controller->rawStickX, controller->rawStickY); - continue; - } else - { - controller->rawStickX = 0; - controller->rawStickY = 0; - } + controller->rawStickX = c_rightx; + controller->rawStickY = c_righty; + controller->stickX = c_rightx; + controller->stickY = c_righty; } else { @@ -557,8 +525,34 @@ void read_controller_inputs(void) { controller->stickMag = 0; } } -#endif + } + #else + for (i = 0; i < 2; i++) { + struct Controller *controller = &gControllers[i]; + + // if we're receiving inputs, update the controller struct + // with the new button info. + if (controller->controllerData != NULL) { + controller->rawStickX = controller->controllerData->stick_x; + controller->rawStickY = controller->controllerData->stick_y; + controller->buttonPressed = controller->controllerData->button + & (controller->controllerData->button ^ controller->buttonDown); + // 0.5x A presses are a good meme + controller->buttonDown = controller->controllerData->button; + adjust_analog_stick(controller); + } else // otherwise, if the controllerData is NULL, 0 out all of the inputs. + { + controller->rawStickX = 0; + controller->rawStickY = 0; + controller->buttonPressed = 0; + controller->buttonDown = 0; + controller->stickX = 0; + controller->stickY = 0; + controller->stickMag = 0; + } + } + #endif // For some reason, player 1's inputs are copied to player 3's port. This // potentially may have been a way the developers "recorded" the inputs diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index 920fa815..9f3630a0 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -44,6 +44,10 @@ void osContGetReadData(OSContPad *pad) { c_rightx = rightx / 0x100; int stick_y = -righty / 0x100; c_righty = stick_y == 128 ? 127 : stick_y; + } else + { + c_rightx = 0; + c_righty = 0; } #endif From 3ebfc225ca84537b5fcfe5c9b0dd20c37104f72c Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sat, 9 May 2020 02:10:56 -0300 Subject: [PATCH 13/39] Mouse Look ported to camera_rebase With check for settings SDL_SetRelativeMouseMode only if Mouse Look is enabled. We always send regards to Fastblitters. --- include/text_strings.h.in | 1 + src/game/bettercamera.inc.h | 40 +++++++++++++++++++++--------- src/pc/controller/controller_sdl.c | 18 +++++++++++++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index db15cd6c..63a8e77e 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -16,6 +16,7 @@ #define NC_OPTION _("OPTIONS") #define NC_HIGHLIGHT _("O") #define NC_ANALOGUE _("Analogue Camera") +#define NC_MOUSE _("Mouse Look") /** * Global Symbols diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index b04d8122..92a54029 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -97,6 +97,7 @@ u8 newcam_invertY; u8 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking. u8 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement. u8 newcam_analogue; //Wether to accept inputs from a player 2 joystick, and then disables C button input. +u8 newcam_mouse; // Whether to accept mouse input s16 newcam_distance_values[] = {750,1250,2000}; u8 newcam_active = 1; // basically the thing that governs if newcam is on. u16 newcam_mode; @@ -109,12 +110,15 @@ f32 newcam_option_timer = 0; u8 newcam_option_index = 0; u8 newcam_option_scroll = 0; u8 newcam_option_scroll_last = 0; -u8 newcam_total = 7; //How many options there are in newcam_uptions. +u8 newcam_total = 8; //How many options there are in newcam_uptions. -u8 newcam_options[][64] = {{NC_ANALOGUE}, {NC_CAMX}, {NC_CAMY}, {NC_INVERTX}, {NC_INVERTY}, {NC_CAMC}, {NC_CAMP}}; +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; + ///This is called at every level initialisation. void newcam_init(struct Camera *c, u8 dv) { @@ -370,6 +374,12 @@ static void newcam_rotate_button(void) else newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE)); } + + if (newcam_mouse == 1) + { + newcam_yaw += mouse_x * 16; + newcam_tilt += mouse_y * 16; + } } static void newcam_zoom_button(void) @@ -690,24 +700,27 @@ void newcam_change_setting(u8 toggle) newcam_analogue ^= 1; break; case 1: + newcam_mouse ^= 1; + break; + case 2: if (newcam_sensitivityX > 10 && newcam_sensitivityX < 250) newcam_sensitivityX += toggle; break; - case 2: + case 3: if (newcam_sensitivityY > 10 && newcam_sensitivityY < 250) newcam_sensitivityY += toggle; break; - case 3: + case 4: newcam_invertX ^= 1; break; - case 4: + case 5: newcam_invertY ^= 1; break; - case 5: + case 6: if (newcam_aggression > 0 && newcam_aggression < 100) newcam_aggression += toggle; break; - case 6: + case 7: if (newcam_panlevel > 0 && newcam_panlevel < 100) newcam_panlevel += toggle; break; @@ -765,24 +778,27 @@ void newcam_display_options() 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 2: + case 3: int_to_str(newcam_sensitivityY,newstring); newcam_text(160,scroll-12,newstring,newcam_option_selection-i); break; - case 3: + case 4: newcam_text(160,scroll-12,newcam_flags[newcam_invertX],newcam_option_selection-i); break; - case 4: + case 5: newcam_text(160,scroll-12,newcam_flags[newcam_invertY],newcam_option_selection-i); break; - case 5: + case 6: int_to_str(newcam_aggression,newstring); newcam_text(160,scroll-12,newstring,newcam_option_selection-i); break; - case 6: + case 7: int_to_str(newcam_panlevel,newstring); newcam_text(160,scroll-12,newstring,newcam_option_selection-i); break; diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index cae57020..1a148bcb 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -14,16 +14,24 @@ extern int16_t rightx; extern int16_t righty; +int mouse_x; +int mouse_y; + +extern u8 newcam_mouse; static bool init_ok; static SDL_GameController *sdl_cntrl; static void controller_sdl_init(void) { - if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) { + if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) { fprintf(stderr, "SDL init error: %s\n", SDL_GetError()); return; } + if (newcam_mouse == 1) + SDL_SetRelativeMouseMode(SDL_TRUE); + SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + init_ok = true; } @@ -32,7 +40,15 @@ static void controller_sdl_read(OSContPad *pad) { return; } + if (newcam_mouse == 1) + SDL_SetRelativeMouseMode(SDL_TRUE); + else + SDL_SetRelativeMouseMode(SDL_FALSE); + + + SDL_GameControllerUpdate(); + SDL_GetRelativeMouseState(&mouse_x, &mouse_y); if (sdl_cntrl != NULL && !SDL_GameControllerGetAttached(sdl_cntrl)) { SDL_GameControllerClose(sdl_cntrl); From 89cd99608e40c60d9d4a0b8c9e8830f8686846e0 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sat, 9 May 2020 02:30:14 -0300 Subject: [PATCH 14/39] Fix goddard/sfx.h header --- src/goddard/sfx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goddard/sfx.h b/src/goddard/sfx.h index 0ba48c0a..d0b6f6fd 100644 --- a/src/goddard/sfx.h +++ b/src/goddard/sfx.h @@ -20,6 +20,6 @@ enum GdSfx { extern void gd_reset_sfx(void); extern u32 gd_new_sfx_to_play(void); extern void gd_sfx_played(void); -extern void gd_play_sfx(u32); +extern void gd_play_sfx(enum GdSfx sfx); #endif /* GD_MARIO_HEAD_SFX_H */ From 75aeb9d6869aaa1d4ee165b1d2c19a6e49eebad8 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sat, 9 May 2020 02:32:57 -0300 Subject: [PATCH 15/39] Fix goddard/sfx.h header --- src/goddard/sfx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goddard/sfx.h b/src/goddard/sfx.h index 0ba48c0a..d0b6f6fd 100644 --- a/src/goddard/sfx.h +++ b/src/goddard/sfx.h @@ -20,6 +20,6 @@ enum GdSfx { extern void gd_reset_sfx(void); extern u32 gd_new_sfx_to_play(void); extern void gd_sfx_played(void); -extern void gd_play_sfx(u32); +extern void gd_play_sfx(enum GdSfx sfx); #endif /* GD_MARIO_HEAD_SFX_H */ From f43c06303fabf2c8246efe2596b7e6cf0902d59b Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Sat, 9 May 2020 09:28:19 +0100 Subject: [PATCH 16/39] L (Trigger) is real. Keyboard only for now. --- src/pc/configfile.c | 2 ++ src/pc/controller/controller_keyboard.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 10ff1e68..8bcc24db 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -34,6 +34,7 @@ bool configFullscreen = false; unsigned int configKeyA = 0x26; unsigned int configKeyB = 0x33; unsigned int configKeyStart = 0x39; +unsigned int configKeyL = 0x35; unsigned int configKeyR = 0x36; unsigned int configKeyZ = 0x25; unsigned int configKeyCUp = 0x148; @@ -51,6 +52,7 @@ static const struct ConfigOption options[] = { {.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}, diff --git a/src/pc/controller/controller_keyboard.c b/src/pc/controller/controller_keyboard.c index a49b86a8..87eaee0d 100644 --- a/src/pc/controller/controller_keyboard.c +++ b/src/pc/controller/controller_keyboard.c @@ -11,7 +11,7 @@ static int keyboard_buttons_down; -static int keyboard_mapping[13][2]; +static int keyboard_mapping[14][2]; static int keyboard_map_scancode(int scancode) { int ret = 0; @@ -58,6 +58,7 @@ static void keyboard_init(void) { 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); From 0413703a6023123e0263951865fb16b90938d1cb Mon Sep 17 00:00:00 2001 From: Hyenadae Date: Sat, 9 May 2020 09:31:15 +0100 Subject: [PATCH 17/39] L (Trigger) is real. Keyboard only for now. --- src/pc/configfile.c | 2 +- src/pc/configfile.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 8bcc24db..a2de665e 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -34,7 +34,7 @@ bool configFullscreen = false; unsigned int configKeyA = 0x26; unsigned int configKeyB = 0x33; unsigned int configKeyStart = 0x39; -unsigned int configKeyL = 0x35; +unsigned int configKeyL = 0x34; unsigned int configKeyR = 0x36; unsigned int configKeyZ = 0x25; unsigned int configKeyCUp = 0x148; diff --git a/src/pc/configfile.h b/src/pc/configfile.h index ae9070b7..7128aaab 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -5,6 +5,7 @@ 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; From 76783f2ab01f29ca4eee9de251a90dc088ad0f55 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, 9 May 2020 12:18:30 -0300 Subject: [PATCH 18/39] Add optional support for L-trigger on controllers. --- enhancements/L-trigger-mapping/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 enhancements/L-trigger-mapping/README.md diff --git a/enhancements/L-trigger-mapping/README.md b/enhancements/L-trigger-mapping/README.md new file mode 100644 index 00000000..0538f094 --- /dev/null +++ b/enhancements/L-trigger-mapping/README.md @@ -0,0 +1,12 @@ +# L-trigger mapping + +Some parts of the code might require the pressing of the L-trigger for testing reasons. + +If you need that, alter `controller_sdl.c`. +In the following line: +``` + if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pad->button |= Z_TRIG; +``` +Replace `Z_TRIG` with `L_TRIG`, save and rebuild. + +On a DS4, this now means that Z-trigger will be mapped to L2 and the L-trigger to L1. From 7a81769abc4702a52e8b9e129f220e84c4b4155b 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, 9 May 2020 18:20:20 -0300 Subject: [PATCH 19/39] Delete fps.patch --- enhancements/fps.patch | 60 ------------------------------------------ 1 file changed, 60 deletions(-) delete mode 100644 enhancements/fps.patch diff --git a/enhancements/fps.patch b/enhancements/fps.patch deleted file mode 100644 index 9e28d22a..00000000 --- a/enhancements/fps.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --git a/src/game/game_init.c b/src/game/game_init.c -index 0852a141..18c5e8fe 100644 ---- a/src/game/game_init.c -+++ b/src/game/game_init.c -@@ -56,6 +56,47 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence - u16 gDemoInputListID = 0; - struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check - -+// SDK states that 1 cycle takes about 21.33 nanoseconds -+#define SECONDS_PER_CYCLE 0.00000002133f -+ -+#define FPS_COUNTER_X_POS 24 -+#define FPS_COUNTER_Y_POS 190 -+ -+static OSTime gLastOSTime = 0; -+static float gFrameTime = 0.0f; -+static u16 gFrames = 0; -+static u16 gFPS = 0; -+static u8 gRenderFPS = FALSE; -+ -+static void calculate_frameTime_from_OSTime(OSTime diff) { -+ gFrameTime += diff * SECONDS_PER_CYCLE; -+ gFrames++; -+} -+ -+static void render_fps(void) { -+ // Toggle rendering framerate with the L button. -+ if (gPlayer1Controller->buttonPressed & L_TRIG) { -+ gRenderFPS ^= 1; -+ } -+ -+ if (gRenderFPS) { -+ OSTime newTime = osGetTime(); -+ -+ calculate_frameTime_from_OSTime(newTime - gLastOSTime); -+ -+ // If frame time is longer or equal to a second, update FPS counter. -+ if (gFrameTime >= 1.0f) { -+ gFPS = gFrames; -+ gFrames = 0; -+ gFrameTime -= 1.0f; -+ } -+ -+ print_text_fmt_int(FPS_COUNTER_X_POS, FPS_COUNTER_Y_POS, "FPS %d", gFPS); -+ -+ gLastOSTime = newTime; -+ } -+} -+ - /** - * Initializes the Reality Display Processor (RDP). - * This function initializes settings such as texture filtering mode, -@@ -614,5 +655,7 @@ void thread5_game_loop(UNUSED void *arg) { - // amount of free space remaining. - print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead); - } -+ -+ render_fps(); - } - } From 5024cdece36e1ea1a47c5e7d3be17e41acfc5346 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, 9 May 2020 18:21:44 -0300 Subject: [PATCH 20/39] Delete fps.patch --- enhancements/fps.patch | 60 ------------------------------------------ 1 file changed, 60 deletions(-) delete mode 100644 enhancements/fps.patch diff --git a/enhancements/fps.patch b/enhancements/fps.patch deleted file mode 100644 index 9e28d22a..00000000 --- a/enhancements/fps.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff --git a/src/game/game_init.c b/src/game/game_init.c -index 0852a141..18c5e8fe 100644 ---- a/src/game/game_init.c -+++ b/src/game/game_init.c -@@ -56,6 +56,47 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence - u16 gDemoInputListID = 0; - struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check - -+// SDK states that 1 cycle takes about 21.33 nanoseconds -+#define SECONDS_PER_CYCLE 0.00000002133f -+ -+#define FPS_COUNTER_X_POS 24 -+#define FPS_COUNTER_Y_POS 190 -+ -+static OSTime gLastOSTime = 0; -+static float gFrameTime = 0.0f; -+static u16 gFrames = 0; -+static u16 gFPS = 0; -+static u8 gRenderFPS = FALSE; -+ -+static void calculate_frameTime_from_OSTime(OSTime diff) { -+ gFrameTime += diff * SECONDS_PER_CYCLE; -+ gFrames++; -+} -+ -+static void render_fps(void) { -+ // Toggle rendering framerate with the L button. -+ if (gPlayer1Controller->buttonPressed & L_TRIG) { -+ gRenderFPS ^= 1; -+ } -+ -+ if (gRenderFPS) { -+ OSTime newTime = osGetTime(); -+ -+ calculate_frameTime_from_OSTime(newTime - gLastOSTime); -+ -+ // If frame time is longer or equal to a second, update FPS counter. -+ if (gFrameTime >= 1.0f) { -+ gFPS = gFrames; -+ gFrames = 0; -+ gFrameTime -= 1.0f; -+ } -+ -+ print_text_fmt_int(FPS_COUNTER_X_POS, FPS_COUNTER_Y_POS, "FPS %d", gFPS); -+ -+ gLastOSTime = newTime; -+ } -+} -+ - /** - * Initializes the Reality Display Processor (RDP). - * This function initializes settings such as texture filtering mode, -@@ -614,5 +655,7 @@ void thread5_game_loop(UNUSED void *arg) { - // amount of free space remaining. - print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead); - } -+ -+ render_fps(); - } - } From 1c86dca5816afddcb266adc013977b9348650a55 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sat, 9 May 2020 21:13:57 -0300 Subject: [PATCH 21/39] Fix save corruption in some 64-bit builds --- src/game/game_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/game_init.c b/src/game/game_init.c index 4603acc4..511bae2c 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -306,7 +306,7 @@ void rendering_init(void) { } void config_gfx_pool(void) { - gGfxPool = &gGfxPools[gGlobalTimer % 2]; + gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS]; set_segment_base_addr(1, gGfxPool->buffer); gGfxSPTask = &gGfxPool->spTask; gDisplayListHead = gGfxPool->buffer; From 3f9236a23345981e8511961811abea44cec5c541 Mon Sep 17 00:00:00 2001 From: Zero-Shift Date: Sat, 9 May 2020 20:32:50 -0500 Subject: [PATCH 22/39] Update script.c Changed amount of sleep frames when transitioning from main menu and exiting a stage to fix TAS sync issues --- levels/menu/script.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/levels/menu/script.c b/levels/menu/script.c index 46cd0668..5a9d3e44 100644 --- a/levels/menu/script.c +++ b/levels/menu/script.c @@ -50,7 +50,7 @@ const LevelScript level_main_menu_entry_1[] = { GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_SAVE_FILE_NUM), STOP_MUSIC(/*fadeOutTime*/ 0x00BE), TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF), - SLEEP(/*frames*/ 24), + SLEEP(/*frames*/ 16), CLEAR_LEVEL(), SLEEP_BEFORE_EXIT(/*frames*/ 1), SET_REG(/*value*/ LEVEL_CASTLE_GROUNDS), @@ -89,7 +89,7 @@ const LevelScript level_main_menu_entry_2[] = { /*35*/ GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_ACT_NUM), /*36*/ STOP_MUSIC(/*fadeOutTime*/ 0x00BE), /*37*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF), - /*39*/ SLEEP(/*frames*/ 24), + /*39*/ SLEEP(/*frames*/ 16), /*40*/ CLEAR_LEVEL(), /*41*/ SLEEP_BEFORE_EXIT(/*frames*/ 1), // L1: From 8e2e2f49f0e9cb0def8b34bd43a0c1c2ff41ccba Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sun, 10 May 2020 00:03:14 -0300 Subject: [PATCH 23/39] Port fixes from fdsfgsfds' fork see https://github.com/fgsfdsfgs/sm64pc/commit/63bed21d26cfa2aad7fd5b9339a1770f7b293978 for details --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9b829f36..6102eab7 100644 --- a/Makefile +++ b/Makefile @@ -647,7 +647,7 @@ $(SOUND_BIN_DIR)/sequences.bin.c: $(SOUND_BIN_DIR)/sequences.bin echo "};" >> $@ $(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets - echo "unsigned char gBankSetsData[] = {" > $@ + echo "unsigned char gBankSetsData[0x100] = {" > $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@ echo "};" >> $@ From ad89f663f3fd3c19bf373c6a312f3caadea49843 Mon Sep 17 00:00:00 2001 From: "Colton G. Rushton" Date: Sun, 10 May 2020 00:05:33 -0300 Subject: [PATCH 24/39] More fixes ported from fdsfgsfds' fork --- src/pc/gfx/gfx_sdl2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 309c19a2..fb7f6a07 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -131,8 +131,8 @@ static void gfx_sdl_init(void) { } for (size_t i = 0; i < sizeof(scancode_rmapping_nonextended) / sizeof(scancode_rmapping_nonextended[0]); i++) { - inverted_scancode_table[scancode_rmapping_extended[i][0]] = inverted_scancode_table[scancode_rmapping_extended[i][1]]; - inverted_scancode_table[scancode_rmapping_extended[i][1]] += 0x100; + inverted_scancode_table[scancode_rmapping_nonextended[i][0]] = inverted_scancode_table[scancode_rmapping_nonextended[i][1]]; + inverted_scancode_table[scancode_rmapping_nonextended[i][1]] += 0x100; } } From 88b063d7a187b5058fc371492846d8af12bdb70f Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sun, 10 May 2020 05:11:27 -0300 Subject: [PATCH 25/39] New Makefile and fgsfdsfgs fixes New Makefile based on master branch Makefile. Ported fdsfgsfds' OOB memory access and save buffer corruption fixes. --- Makefile | 310 +++++++++++------------------------------- src/game/game_init.c | 2 +- src/pc/gfx/gfx_sdl2.c | 4 +- 3 files changed, 83 insertions(+), 233 deletions(-) diff --git a/Makefile b/Makefile index 86234be5..a28d0930 100644 --- a/Makefile +++ b/Makefile @@ -16,19 +16,18 @@ GRUCODE ?= f3d_old # If COMPARE is 1, check the output sha1sum when building 'all' COMPARE ?= 1 # If NON_MATCHING is 1, define the NON_MATCHING and AVOID_UB macros when building (recommended) -NON_MATCHING ?= 0 -# Build for the N64 (turn this off for ports) -TARGET_N64 ?= 0 +NON_MATCHING ?= 1 +# Sane default until N64 build scripts rm'd +TARGET_N64 = 0 + # Build and optimize for Raspberry Pi(s) TARGET_RPI ?= 0 # Compiler to use (ido or gcc) COMPILER ?= ido +# Enable better camera by default BETTERCAMERA ?= 1 -ifeq ($(COMPILER),gcc) - NON_MATCHING := 1 -endif # Build for Emscripten/WebGL TARGET_WEB ?= 0 # Specify the target you are building for, 0 means native @@ -41,18 +40,18 @@ else BITS := endif -# Automatic settings only for ports -ifeq ($(TARGET_N64),0) - NON_MATCHING := 1 - GRUCODE := f3dex2e - WINDOWS_BUILD := 0 - ifeq ($(TARGET_WEB),0) - ifeq ($(OS),Windows_NT) - WINDOWS_BUILD := 1 - endif - endif +# Automatic settings for PC port(s) -# Release +NON_MATCHING := 1 +GRUCODE := f3dex2e +WINDOWS_BUILD := 0 + +ifeq ($(TARGET_WEB),0) +ifeq ($(OS),Windows_NT) +WINDOWS_BUILD := 1 +endif + +# Release (version) flag defs ifeq ($(VERSION),jp) VERSION_CFLAGS := -DVERSION_JP @@ -105,7 +104,7 @@ ifeq ($(GRUCODE), f3dex2) # Fast3DEX2 TARGET := $(TARGET).f3dex2 COMPARE := 0 else -ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (for PC) +ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (PC default) GRUCODE_CFLAGS := -DF3DEX_GBI_2E TARGET := $(TARGET).f3dex2e COMPARE := 0 @@ -128,18 +127,15 @@ endif endif endif -ifeq ($(TARGET_N64),0) - NON_MATCHING := 1 +# Default build is for PC now +VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB + +ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints + VERSION_CFLAGS += -DUSE_GLES endif -ifeq ($(NON_MATCHING),1) - VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB - ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints - VERSION_CFLAGS += -DTARGET_RPI - endif - VERSION_ASFLAGS := --defsym AVOID_UB=1 - COMPARE := 0 -endif +VERSION_ASFLAGS := --defsym AVOID_UB=1 +COMPARE := 0 ifeq ($(TARGET_WEB),1) VERSION_CFLAGS := $(VERSION_CFLAGS) -DTARGET_WEB @@ -176,34 +172,30 @@ endif # BUILD_DIR is location where all build artifacts are placed BUILD_DIR_BASE := build -ifeq ($(TARGET_N64),1) - BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION) -else + ifeq ($(TARGET_WEB),1) BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_web else BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_pc endif -endif LIBULTRA := $(BUILD_DIR)/libultra.a + ifeq ($(TARGET_WEB),1) EXE := $(BUILD_DIR)/$(TARGET).html -else -ifeq ($(WINDOWS_BUILD),1) -EXE := $(BUILD_DIR)/$(TARGET).exe + else + ifeq ($(WINDOWS_BUILD),1) + EXE := $(BUILD_DIR)/$(TARGET).exe -else #Linux builds here -ifeq ($(TARGET_RPI),1) -EXE := $(BUILD_DIR)/$(TARGET).arm -else -EXE := $(BUILD_DIR)/$(TARGET) -endif + else # Linux builds/binary namer + ifeq ($(TARGET_RPI),1) + EXE := $(BUILD_DIR)/$(TARGET).arm + else + EXE := $(BUILD_DIR)/$(TARGET) + endif + endif endif -endif - -ROM := $(BUILD_DIR)/$(TARGET).z64 ELF := $(BUILD_DIR)/$(TARGET).elf LD_SCRIPT := sm64.ld MIO0_DIR := $(BUILD_DIR)/bin @@ -213,14 +205,11 @@ ACTOR_DIR := actors LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h))) # Directories containing source files -SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets -ASM_DIRS := lib -ifeq ($(TARGET_N64),1) - ASM_DIRS := asm $(ASM_DIRS) -else - SRC_DIRS := $(SRC_DIRS) src/pc src/pc/gfx src/pc/audio src/pc/controller - ASM_DIRS := -endif + +# Hi, I'm a PC +SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller +ASM_DIRS := + BIN_DIRS := bin bin/$(VERSION) ULTRA_SRC_DIRS := lib/src lib/src/math @@ -246,28 +235,27 @@ else endif endif -ifeq ($(TARGET_N64),0) - OPT_FLAGS += $(BITS) -endif +# Set BITS (32/64) to compile for +OPT_FLAGS += $(BITS) ifeq ($(TARGET_WEB),1) OPT_FLAGS := -O2 -g4 --source-map-base http://localhost:8080/ endif endif -# Use a default opt flag for gcc +# Use a default opt flag for gcc, then override if RPi ifeq ($(COMPILER),gcc) - OPT_FLAGS := -O2 +OPT_FLAGS := -O2 # Breaks sound on x86? endif ifeq ($(TARGET_RPI),1) - machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') + machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown') # Raspberry Pi B+, Zero, etc - ifneq (,$(findstring armv6l,$(machine))) + ifneq (,$(findstring armv6l,$(machine))) OPT_FLAGS := -march=armv6zk+fp -mfpu=vfp -Ofast endif -# Raspberry Pi 2 and 3 +# Raspberry Pi 2 and 3 in ARM 32bit mode ifneq (,$(findstring armv7l,$(machine))) model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') @@ -278,9 +266,16 @@ ifeq ($(TARGET_RPI),1) endif endif -# RPi4 / ARM A64 NEEDS TESTING 32BIT. +# RPi3 or RPi4, in ARM64 (aarch64) mode. NEEDS TESTING 32BIT. +# DO NOT pass -mfpu stuff here, thats for 32bit ARM only and will fail for 64bit ARM. ifneq (,$(findstring aarch64,$(machine))) - OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -O3 + model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown') + ifneq (,$(findstring 3,$(model))) + OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -O3 + else ifneq (,$(findstring 4,$(model))) + OPT_FLAGS := -march=armv8-a+crc+simd -mtune=cortex-a72 -O3 + endif + endif endif @@ -294,9 +289,7 @@ CXX_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp)) S_FILES := $(foreach dir,$(ASM_DIRS),$(wildcard $(dir)/*.s)) ULTRA_C_FILES := $(foreach dir,$(ULTRA_SRC_DIRS),$(wildcard $(dir)/*.c)) GODDARD_C_FILES := $(foreach dir,$(GODDARD_SRC_DIRS),$(wildcard $(dir)/*.c)) -ifeq ($(TARGET_N64),1) - ULTRA_S_FILES := $(foreach dir,$(ULTRA_ASM_DIRS),$(wildcard $(dir)/*.s)) -endif + GENERATED_C_FILES := $(BUILD_DIR)/assets/mario_anim_data.c $(BUILD_DIR)/assets/demo_data.c \ $(addprefix $(BUILD_DIR)/bin/,$(addsuffix _skybox.c,$(notdir $(basename $(wildcard textures/skyboxes/*.png))))) @@ -304,7 +297,9 @@ ifeq ($(WINDOWS_BUILD),0) CXX_FILES := endif -ifneq ($(TARGET_N64),1) +# We need to keep this for now +# If we're not N64 use below + ULTRA_C_FILES_SKIP := \ sqrtf.c \ string.c \ @@ -363,7 +358,8 @@ ifneq ($(TARGET_N64),1) C_FILES := $(filter-out src/game/main.c,$(C_FILES)) ULTRA_C_FILES := $(filter-out $(addprefix lib/src/,$(ULTRA_C_FILES_SKIP)),$(ULTRA_C_FILES)) -endif + +# "If we're not N64, use the above" ifeq ($(VERSION),sh) SOUND_BANK_FILES := $(wildcard sound/sound_banks/*.json) @@ -388,7 +384,6 @@ SOUND_OBJ_FILES := $(SOUND_BIN_DIR)/sound_data.ctl.o \ $(SOUND_BIN_DIR)/sequences.bin.o \ $(SOUND_BIN_DIR)/bank_sets.o - # Object files O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \ $(foreach file,$(CXX_FILES),$(BUILD_DIR)/$(file:.cpp=.o)) \ @@ -403,13 +398,6 @@ GODDARD_O_FILES := $(foreach file,$(GODDARD_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) # Automatic dependency files DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(BUILD_DIR)/$(LD_SCRIPT).d -# Files with GLOBAL_ASM blocks -ifneq ($(NON_MATCHING),1) -GLOBAL_ASM_C_FILES != grep -rl 'GLOBAL_ASM(' $(wildcard src/**/*.c) -GLOBAL_ASM_O_FILES = $(foreach file,$(GLOBAL_ASM_C_FILES),$(BUILD_DIR)/$(file:.c=.o)) -GLOBAL_ASM_DEP = $(BUILD_DIR)/src/audio/non_matching_dep -endif - # Segment elf files SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES) @@ -417,82 +405,23 @@ SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES) INCLUDE_CFLAGS := -I include -I $(BUILD_DIR) -I $(BUILD_DIR)/include -I src -I . ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth -ifeq ($(TARGET_N64),1) -IRIX_ROOT := tools/ido5.3_compiler - -ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips-linux-gnu- -else ifeq ($(shell type mips64-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips64-linux-gnu- -else ifeq ($(shell type mips64-elf-ld >/dev/null 2>/dev/null; echo $$?), 0) - CROSS := mips64-elf- -endif - -# check that either QEMU_IRIX is set or qemu-irix package installed -ifndef QEMU_IRIX - QEMU_IRIX := $(shell which qemu-irix) - ifeq (, $(QEMU_IRIX)) - $(error Please install qemu-irix package or set QEMU_IRIX env var to the full qemu-irix binary path) - endif -endif - -AS := $(CROSS)as -CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc -CPP := cpp -P -Wno-trigraphs -LD := $(CROSS)ld -AR := $(CROSS)ar -OBJDUMP := $(CROSS)objdump -OBJCOPY := $(CROSS)objcopy -PYTHON := python3 - -# change the compiler to gcc, to use the default, install the gcc-mips-linux-gnu package -ifeq ($(COMPILER),gcc) - CC := $(CROSS)gcc -endif - -ifeq ($(TARGET_N64),1) - TARGET_CFLAGS := -nostdinc -I include/libc -DTARGET_N64 - CC_CFLAGS := -fno-builtin -endif - -# Check code syntax with host compiler -CC_CHECK := gcc -fsyntax-only -fsigned-char $(CC_CFLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) -std=gnu90 -Wall -Wextra -Wno-format-security -Wno-main -DNON_MATCHING -DAVOID_UB $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) - -COMMON_CFLAGS = $(OPT_FLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(MIPSISET) $(GRUCODE_CFLAGS) - -ASFLAGS := -march=vr4300 -mabi=32 -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) $(GRUCODE_ASFLAGS) -CFLAGS = -Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -Xfullwarn -signed $(COMMON_CFLAGS) $(MIPSBIT) -OBJCOPYFLAGS := --pad-to=0x800000 --gap-fill=0xFF -SYMBOL_LINKING_FLAGS := $(addprefix -R ,$(SEG_FILES)) -LDFLAGS := -T undefined_syms.txt -T $(BUILD_DIR)/$(LD_SCRIPT) -Map $(BUILD_DIR)/sm64.$(VERSION).map --no-check-sections $(SYMBOL_LINKING_FLAGS) -ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth - -ifeq ($(COMPILER),gcc) - CFLAGS := -march=vr4300 -mfix4300 -mno-shared -G 0 -mhard-float -fno-stack-protector -fno-common -I include -I src/ -I $(BUILD_DIR)/include -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra $(COMMON_CFLAGS) -endif - -ifeq ($(shell getconf LONG_BIT), 32) - # Work around memory allocation bug in QEMU - export QEMU_GUEST_BASE := 1 -else - # Ensure that gcc treats the code as 32-bit - CC_CHECK += $(BITS) -endif - -else # TARGET_N64 +# Huge deleted N64 section was here AS := as -ifneq ($(TARGET_WEB),1) + +ifneq ($(TARGET_WEB),1) # As in, not-web PC port CC := $(CROSS)gcc CXX := $(CROSS)g++ else CC := emcc endif + ifeq ($(WINDOWS_BUILD),1) LD := $(CXX) else LD := $(CC) endif + CPP := cpp -P OBJDUMP := objdump OBJCOPY := objcopy @@ -501,15 +430,18 @@ PYTHON := python3 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` + 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 CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv -s USE_SDL=2 + # 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` endif +# Check for better camera option ifeq ($(BETTERCAMERA),1) CC_CHECK += -DBETTERCAMERA CFLAGS += -DBETTERCAMERA @@ -520,9 +452,11 @@ 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) 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 else + # Linux / Other builds below ifeq ($(TARGET_RPI),1) LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(CROSS)sdl2-config --libs` -no-pie @@ -532,14 +466,13 @@ endif endif endif #Added for Pi ifeq -endif # Prevent a crash with -sopt export LANG := C ####################### Other Tools ######################### -# N64 tools +# N64 conversion tools TOOLS_DIR = tools MIO0TOOL = $(TOOLS_DIR)/mio0 N64CKSUM = $(TOOLS_DIR)/n64cksum @@ -557,32 +490,13 @@ LOADER = loader64 LOADER_FLAGS = -vwf SHA1SUM = sha1sum -# Use Objcopy instead of extract_data_for_mio -ifeq ($(COMPILER),gcc) -EXTRACT_DATA_FOR_MIO := $(OBJCOPY) -O binary --only-section=.data -endif - ###################### Dependency Check ##################### -ifeq ($(TARGET_N64),1) -BINUTILS_VER_MAJOR := $(shell $(LD) --version | grep ^GNU | sed 's/^.* //; s/\..*//g') -BINUTILS_VER_MINOR := $(shell $(LD) --version | grep ^GNU | sed 's/^[^.]*\.//; s/\..*//g') -BINUTILS_DEPEND := $(shell expr $(BINUTILS_VER_MAJOR) \>= 2 \& $(BINUTILS_VER_MINOR) \>= 27) -ifeq ($(BINUTILS_DEPEND),0) -$(error binutils version 2.27 required, version $(BINUTILS_VER_MAJOR).$(BINUTILS_VER_MINOR) detected) -endif -endif +# Stubbed ######################## Targets ############################# -ifeq ($(TARGET_N64),1) -all: $(ROM) -ifeq ($(COMPARE),1) - @$(SHA1SUM) -c $(TARGET).sha1 || (echo 'The build succeeded, but did not match the official ROM. This is expected if you are making changes to the game.\nTo silence this message, use "make COMPARE=0"'. && false) -endif -else all: $(EXE) -endif clean: $(RM) -r $(BUILD_DIR_BASE) @@ -606,7 +520,7 @@ asm/boot.s: $(BUILD_DIR)/lib/bin/ipl3_font.bin $(BUILD_DIR)/lib/bin/ipl3_font.bin: lib/ipl3_font.png $(IPLFONTUTIL) e $< $@ - + #Required so the compiler doesn't complain about this not existing. $(BUILD_DIR)/src/game/camera.o: $(BUILD_DIR)/include/text_strings.h @@ -616,10 +530,6 @@ $(BUILD_DIR)/include/text_strings.h: include/text_strings.h.in $(BUILD_DIR)/include/text_menu_strings.h: include/text_menu_strings.h.in $(TEXTCONV) charmap_menu.txt $< $@ -ifeq ($(COMPILER),gcc) -$(BUILD_DIR)/lib/src/math/%.o: CFLAGS += -fno-builtin -endif - ifeq ($(VERSION),eu) TEXT_DIRS := text/de text/us text/fr @@ -645,7 +555,6 @@ $(BUILD_DIR)/bin/segment2.o: $(BUILD_DIR)/text/$(VERSION)/define_text.inc.c endif endif - $(BUILD_DIR)/text/%/define_courses.inc.c: text/define_courses.inc.c text/%/courses.h $(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/ $(TEXTCONV) charmap.txt $@ $@ @@ -660,6 +569,7 @@ ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GOD DUMMY != mkdir -p $(ALL_DIRS) $(BUILD_DIR)/include/text_strings.h: $(BUILD_DIR)/include/text_menu_strings.h + 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 @@ -695,38 +605,7 @@ $(BUILD_DIR)/%.ci4: %.ci4.png # compressed segment generation -ifeq ($(TARGET_N64),1) -# TODO: ideally this would be `-Trodata-segment=0x07000000` but that doesn't set the address - -$(BUILD_DIR)/bin/%.elf: $(BUILD_DIR)/bin/%.o - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $< -$(BUILD_DIR)/actors/%.elf: $(BUILD_DIR)/actors/%.o - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $< - -# Override for level.elf, which otherwise matches the above pattern -.SECONDEXPANSION: -$(BUILD_DIR)/levels/%/leveldata.elf: $(BUILD_DIR)/levels/%/leveldata.o $(BUILD_DIR)/bin/$$(TEXTURE_BIN).elf - $(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map --just-symbols=$(BUILD_DIR)/bin/$(TEXTURE_BIN).elf -o $@ $< - -$(BUILD_DIR)/bin/%.bin: $(BUILD_DIR)/bin/%.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/actors/%.bin: $(BUILD_DIR)/actors/%.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/levels/%/leveldata.bin: $(BUILD_DIR)/levels/%/leveldata.elf - $(EXTRACT_DATA_FOR_MIO) $< $@ - -$(BUILD_DIR)/%.mio0: $(BUILD_DIR)/%.bin - $(MIO0TOOL) $< $@ - -$(BUILD_DIR)/%.mio0.o: $(BUILD_DIR)/%.mio0.s - $(AS) $(ASFLAGS) -o $@ $< - -$(BUILD_DIR)/%.mio0.s: $(BUILD_DIR)/%.mio0 - printf ".section .data\n\n.incbin \"$<\"\n" > $@ -endif - +# PC Area $(BUILD_DIR)/%.table: %.aiff $(AIFF_EXTRACT_CODEBOOK) $< >$@ @@ -763,10 +642,7 @@ $(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o $(SOUND_BIN_DIR)/%.o: $(SOUND_BIN_DIR)/%.s $(AS) $(ASFLAGS) -o $@ $< -ifeq ($(TARGET_N64),1) -$(SOUND_BIN_DIR)/%.s: $(SOUND_BIN_DIR)/% - printf ".section .data\n\n.incbin \"$<\"\n" > $@ -else + $(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl echo "unsigned char gSoundDataADSR[] = {" > $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@ @@ -783,10 +659,9 @@ $(SOUND_BIN_DIR)/sequences.bin.c: $(SOUND_BIN_DIR)/sequences.bin echo "};" >> $@ $(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets - echo "unsigned char gBankSetsData[] = {" > $@ + echo "unsigned char gBankSetsData[0x100] = {" > $@ hexdump -v -e '1/1 "0x%X,"' $< >> $@ echo "};" >> $@ -endif $(BUILD_DIR)/levels/scripts.o: $(BUILD_DIR)/include/level_headers.h @@ -843,9 +718,6 @@ $(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp endif endif -ifeq ($(NON_MATCHING),0) -$(GLOBAL_ASM_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) -- -endif # Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes. $(GLOBAL_ASM_O_FILES): $(GLOBAL_ASM_DEP).$(NON_MATCHING) @@ -869,32 +741,10 @@ $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c $(BUILD_DIR)/%.o: %.s $(AS) $(ASFLAGS) -MD $(BUILD_DIR)/$*.d -o $@ $< -ifeq ($(TARGET_N64),1) -$(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) - $(CPP) $(VERSION_CFLAGS) -MMD -MP -MT $@ -MF $@.d -I include/ -I . -DBUILD_DIR=$(BUILD_DIR) -o $@ $< -$(BUILD_DIR)/libultra.a: $(ULTRA_O_FILES) - $(AR) rcs -o $@ $(ULTRA_O_FILES) - tools/patch_libultra_math $@ -$(BUILD_DIR)/libgoddard.a: $(GODDARD_O_FILES) - $(AR) rcs -o $@ $(GODDARD_O_FILES) - -$(ELF): $(O_FILES) $(MIO0_OBJ_FILES) $(SOUND_OBJ_FILES) $(SEG_FILES) $(BUILD_DIR)/$(LD_SCRIPT) undefined_syms.txt $(BUILD_DIR)/libultra.a $(BUILD_DIR)/libgoddard.a - $(LD) -L $(BUILD_DIR) $(LDFLAGS) -o $@ $(O_FILES)$(LIBS) -lultra -lgoddard - -$(ROM): $(ELF) - $(OBJCOPY) $(OBJCOPYFLAGS) $< $(@:.z64=.bin) -O binary - $(N64CKSUM) $(@:.z64=.bin) $@ - -$(BUILD_DIR)/$(TARGET).objdump: $(ELF) - $(OBJDUMP) -D $< > $@ - -else $(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS) -endif - .PHONY: all clean distclean default diff test load libultra .PRECIOUS: $(BUILD_DIR)/bin/%.elf $(SOUND_BIN_DIR)/%.ctl $(SOUND_BIN_DIR)/%.tbl $(SOUND_SAMPLE_TABLES) $(SOUND_BIN_DIR)/%.s $(BUILD_DIR)/% diff --git a/src/game/game_init.c b/src/game/game_init.c index 0a2c0cab..cbf712cf 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -311,7 +311,7 @@ void rendering_init(void) { } void config_gfx_pool(void) { - gGfxPool = &gGfxPools[gGlobalTimer % 2]; + gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS]; set_segment_base_addr(1, gGfxPool->buffer); gGfxSPTask = &gGfxPool->spTask; gDisplayListHead = gGfxPool->buffer; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 5a782f5d..034d4269 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -119,8 +119,8 @@ static void gfx_sdl_init(void) { } for (size_t i = 0; i < sizeof(scancode_rmapping_nonextended) / sizeof(scancode_rmapping_nonextended[0]); i++) { - inverted_scancode_table[scancode_rmapping_extended[i][0]] = inverted_scancode_table[scancode_rmapping_extended[i][1]]; - inverted_scancode_table[scancode_rmapping_extended[i][1]] += 0x100; + inverted_scancode_table[scancode_rmapping_nonextended[i][0]] = inverted_scancode_table[scancode_rmapping_nonextended[i][1]]; + inverted_scancode_table[scancode_rmapping_nonextended[i][1]] += 0x100; } } From e3a2613328e988b38c0bd38cb8aa4137389e6abc Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sun, 10 May 2020 05:47:38 -0300 Subject: [PATCH 26/39] Fix build without new camera, add example to README This fixes an oversight of mine that broke building with BETTERCAMERA=0 and adds an example to the README of how to build with the new camera disabled. --- README.md | 3 ++- src/pc/controller/controller_sdl.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 180f12f4..e315ac61 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ Run `make` to build (defaults to `VERSION=us`) ``` make VERSION=jp -j6 # build (J) version with 6 jobs -make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable +make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable (under Windows, compiling for Windows under Linux is not supported) +make BETTERCAMERA=0 # builds an executable with the original SM64 camera (no analog/mouse support) make TARGET_RPI=1 # targets an executable for a Raspberry Pi ``` diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 1a148bcb..9e1b7a4e 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -14,10 +14,13 @@ extern int16_t rightx; extern int16_t righty; + +#ifdef BETTERCAMERA int mouse_x; int mouse_y; extern u8 newcam_mouse; +#endif static bool init_ok; static SDL_GameController *sdl_cntrl; @@ -28,9 +31,11 @@ static void controller_sdl_init(void) { return; } +#ifdef BETTERCAMERA if (newcam_mouse == 1) SDL_SetRelativeMouseMode(SDL_TRUE); SDL_GetRelativeMouseState(&mouse_x, &mouse_y); +#endif init_ok = true; } @@ -40,15 +45,16 @@ static void controller_sdl_read(OSContPad *pad) { return; } +#ifdef BETTERCAMERA if (newcam_mouse == 1) SDL_SetRelativeMouseMode(SDL_TRUE); else SDL_SetRelativeMouseMode(SDL_FALSE); - + SDL_GetRelativeMouseState(&mouse_x, &mouse_y); +#endif SDL_GameControllerUpdate(); - SDL_GetRelativeMouseState(&mouse_x, &mouse_y); if (sdl_cntrl != NULL && !SDL_GameControllerGetAttached(sdl_cntrl)) { SDL_GameControllerClose(sdl_cntrl); From f70ebeb2b3a1a6f2654020d3d2ca29ccfd0f1d97 Mon Sep 17 00:00:00 2001 From: vanfanel Date: Sun, 10 May 2020 15:41:46 +0200 Subject: [PATCH 27/39] Use the system video mode in GLES platforms instead of setting a new one. --- src/pc/gfx/gfx_sdl2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index fb7f6a07..e85412f1 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -113,8 +113,10 @@ static void gfx_sdl_init(void) { wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); #else + /* GLES platforms generally run without a window server like Xorg. Just use the system video mode, + instead of trying to set a new video mode, which does not make any sense in modern displays. */ wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL_ES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP); #endif gfx_sdl_set_fullscreen(configFullscreen); From d54d625a4f052ce7892a9aec14df4933ef3dabd1 Mon Sep 17 00:00:00 2001 From: rai Date: Sun, 10 May 2020 16:02:02 +0200 Subject: [PATCH 28/39] Update README.md Remove most of the infromation from the readme that has been moved to the wiki. --- README.md | 134 +----------------------------------------------------- 1 file changed, 1 insertion(+), 133 deletions(-) diff --git a/README.md b/README.md index 180f12f4..13f24242 100644 --- a/README.md +++ b/README.md @@ -12,136 +12,4 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * True analog camera control is now available on our [testing branch](https://github.com/sm64pc/sm64pc/tree/testing). ## Building - -### On Linux - -#### 1. Copy baserom(s) for asset extraction - -For each version (jp/us/eu) that you want to build an executable for, put an existing ROM at -`./baserom..z64` for asset extraction. - -#### 2. Install build dependencies - -The build system has the following package requirements: - * python3 >= 3.6 - * libsdl2-dev - * [audiofile](https://audiofile.68k.org/) - * libglew-dev - * git - - -__Debian / Ubuntu - targeting 32 bits__ -``` -sudo apt install build-essential git python3 libaudiofile-dev libglew-dev:i386 libsdl2-dev:i386 -``` -__Debian / Ubuntu - targeting 64 bits__ -``` -sudo apt install build-essential git python3 libaudiofile-dev libglew-dev libsdl2-dev -``` - -__Arch Linux__ -``` -sudo pacman -S base-devel python audiofile sdl2 glew -``` - -__Void Linux - targeting 64 bits__ -``` -sudo xbps-install -S base-devel python3 audiofile-devel SDL2-devel glew-devel -``` - -__Void Linux - targeting 32 bits__ -``` -sudo xbps-install -S base-devel python3 audiofile-devel-32bit SDL2-devel-32bit glew-devel-32bit -``` - -#### 3. Build the executable. - -Run `make` to build (defaults to `VERSION=us`) - -``` -make VERSION=jp -j6 # build (J) version with 6 jobs -make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable -make TARGET_RPI=1 # targets an executable for a Raspberry Pi -``` - -### On Windows - -#### 1. Set up MSYS2, following [this guide](https://github.com/orlp/dev-on-windows/wiki/Installing-GCC--&-MSYS2). - -#### 2. Install dependencies -``` -pacman -S mingw-w64-i686-glew mingw-w64-x86_64-glew mingw-w64-i686-SDL2 mingw-w64-x86_64-SDL2 python3 -``` -#### 3. Copy baserom(s) for asset extraction - -For each version (jp/us/eu) that you want to build an executable for, put an existing ROM at -`./baserom..z64` for asset extraction. - -#### 4. On MSYS2, navigate to the sm64pc folder and then enter `./tools/audiofile-0.3.6/`. Inside this directory, run -``` -autoreconf -i -``` - -Only leave this directory on step 9. - -#### 5. Run the `configure` script -``` -PATH=/mingw64/bin:/mingw32/bin:$PATH LIBS=-lstdc++ ./configure --disable-docs -``` -#### 6. Run the `make` script -``` -PATH=/mingw64/bin:/mingw32/bin:$PATH make -``` -#### 7. Create a lib directory in `tools/` -``` -mkdir ../lib -``` - -#### 8. Copy the compiled libaudiofile to `tools/lib/` -``` -cp libaudiofile/.libs/libaudiofile.a ../lib/ -cp libaudiofile/.libs/libaudiofile.la ../lib/ -``` - -#### 9. Navigate back to `tools/`, then alter the `Makefile` and add `-lstdc++` on the following line -``` -tabledesign_CFLAGS := -Wno-uninitialized -laudiofile -lstdc++ -``` - -#### 10. Run `make` -``` -PATH=/mingw64/bin:/mingw32/bin:$PATH make -``` - -#### 11. Navigate back to the sm64pc root directory. - -#### 12. Finally, run `make` once more. - -(Note that mingw32 and mingw64 have been swapped. This is so you can build the 32bit application successfully.) - -``` -PATH=/mingw32/bin:/mingw64/bin:$PATH make -``` - -### For the web - -The game can be compiled for web browsers that support WebGL using [Emscripten](https://github.com/emscripten-core). To do so, install [emsdk](https://github.com/emscripten-core/emsdk) and run `make TARGET_WEB=1`. - -## Optional enhancements - -On the `./enhancements` folder, you'll find several .patch files, which can be applied in the following manner: - -``` - git apply fps.patch --ignore-whitespace --reject -``` -If any rejections occur, you can search for them with `find | grep .rej`. -Try to solve rejections through [wiggle](https://github.com/neilbrown/wiggle). -``` -wiggle rejection.rej --replace -``` - -### Current issues - - * Support for the EU version is still experimental. - * There seems to be savedata-related problems on some 64-bits builds. - * Camera controls are also bugged for some. +For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki) From 65bb12f7a402d4bc2f20262b6032eadce2f42bd3 Mon Sep 17 00:00:00 2001 From: rai Date: Sun, 10 May 2020 16:03:43 +0200 Subject: [PATCH 29/39] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13f24242..a9b06d03 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,4 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO * True analog camera control is now available on our [testing branch](https://github.com/sm64pc/sm64pc/tree/testing). ## Building -For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki) +For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki). From e427aaa89434a60fa91942541016d9b301dfb4e2 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 10 May 2020 18:41:46 +0300 Subject: [PATCH 30/39] make use of mouse buttons --- src/pc/controller/controller_sdl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 9e1b7a4e..3284446f 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -51,7 +51,11 @@ static void controller_sdl_read(OSContPad *pad) { else SDL_SetRelativeMouseMode(SDL_FALSE); - SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + const u32 mbuttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + + if (mbuttons & SDL_BUTTON_LMASK) pad->button |= B_BUTTON; + if (mbuttons & SDL_BUTTON_RMASK) pad->button |= A_BUTTON; + if (mbuttons & SDL_BUTTON_MMASK) pad->button |= Z_TRIG; #endif SDL_GameControllerUpdate(); From a0068c747b7f336f59a292ed3dd9a47305ffb868 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sun, 10 May 2020 12:45:46 -0300 Subject: [PATCH 31/39] Fix Web build. The ifeq($(TARGET_WEB),0) check on line 49 wasn't being endif'ed properly, which caused the rest of the code up until 244 (where an incorrect endif was placed) to be ignored. This commit fixes that issue and allows web builds to work normally. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a28d0930..a40dfb29 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ ifeq ($(TARGET_WEB),0) ifeq ($(OS),Windows_NT) WINDOWS_BUILD := 1 endif +endif # Release (version) flag defs @@ -241,7 +242,6 @@ OPT_FLAGS += $(BITS) ifeq ($(TARGET_WEB),1) OPT_FLAGS := -O2 -g4 --source-map-base http://localhost:8080/ endif -endif # Use a default opt flag for gcc, then override if RPi ifeq ($(COMPILER),gcc) From fd02d88b5938a83075ed38f60c458917d3838e05 Mon Sep 17 00:00:00 2001 From: vanfanel Date: Sun, 10 May 2020 17:52:01 +0200 Subject: [PATCH 32/39] Fix for GLES on windowed rendering contexts (X11) --- src/pc/gfx/gfx_sdl2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index e85412f1..824c20a4 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -115,8 +115,10 @@ static void gfx_sdl_init(void) { #else /* GLES platforms generally run without a window server like Xorg. Just use the system video mode, instead of trying to set a new video mode, which does not make any sense in modern displays. */ + SDL_DisplayMode sdl_displaymode; + SDL_GetCurrentDisplayMode(0, &sdl_displaymode); wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL_ES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - 0, 0, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP); + sdl_displaymode.w, sdl_displaymode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP); #endif gfx_sdl_set_fullscreen(configFullscreen); From 690283da13a948cfe2d2d1d7695c6a1d96f5c942 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 10 May 2020 19:05:54 +0300 Subject: [PATCH 33/39] allow rebinding of joystick and mouse buttons --- src/pc/configfile.c | 24 ++++++++++++++++++++++++ src/pc/configfile.h | 12 ++++++++++++ src/pc/controller/controller_sdl.c | 20 ++++++++++++-------- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/pc/configfile.c b/src/pc/configfile.c index a2de665e..8f304ab6 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -45,6 +45,19 @@ 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 = 9; +unsigned int configJoyR = 10; +unsigned int configJoyZ = 7; +// 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; static const struct ConfigOption options[] = { @@ -63,6 +76,17 @@ static const struct ConfigOption options[] = { {.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}, }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 7128aaab..17968166 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -16,6 +16,18 @@ 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; void configfile_load(const char *filename); void configfile_save(const char *filename); diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 3284446f..77e37d4d 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -12,6 +12,8 @@ #include "controller_api.h" +#include "../configfile.h" + extern int16_t rightx; extern int16_t righty; @@ -53,9 +55,11 @@ static void controller_sdl_read(OSContPad *pad) { const u32 mbuttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); - if (mbuttons & SDL_BUTTON_LMASK) pad->button |= B_BUTTON; - if (mbuttons & SDL_BUTTON_RMASK) pad->button |= A_BUTTON; - if (mbuttons & SDL_BUTTON_MMASK) pad->button |= Z_TRIG; + 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(); @@ -78,11 +82,11 @@ static void controller_sdl_read(OSContPad *pad) { } } - if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_START)) pad->button |= START_BUTTON; - if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pad->button |= Z_TRIG; - if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) pad->button |= R_TRIG; - if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_A)) pad->button |= A_BUTTON; - if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_X)) pad->button |= B_BUTTON; + if (SDL_GameControllerGetButton(sdl_cntrl, configJoyStart)) pad->button |= START_BUTTON; + if (SDL_GameControllerGetButton(sdl_cntrl, configJoyL)) pad->button |= Z_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; int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); From 16a4495bf2e054a7038066f837c8847b546ef988 Mon Sep 17 00:00:00 2001 From: vanfanel Date: Sun, 10 May 2020 18:07:26 +0200 Subject: [PATCH 34/39] Do not call gfx_sdl_set_fullscreen() just after creating the game window: create window fullscreen or not directly. --- src/pc/gfx/gfx_sdl2.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 824c20a4..3f75ed2f 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -95,6 +95,8 @@ static void gfx_sdl_set_fullscreen(bool fullscreen) } static void gfx_sdl_init(void) { + Uint32 window_flags = 0; + SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); @@ -108,21 +110,27 @@ static void gfx_sdl_init(void) { //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - + + window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; + + if (configFullscreen) { + window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + + #ifndef USE_GLES wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, window_flags); #else /* GLES platforms generally run without a window server like Xorg. Just use the system video mode, instead of trying to set a new video mode, which does not make any sense in modern displays. */ SDL_DisplayMode sdl_displaymode; SDL_GetCurrentDisplayMode(0, &sdl_displaymode); + wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL_ES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - sdl_displaymode.w, sdl_displaymode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP); + sdl_displaymode.w, sdl_displaymode.h, window_flags); #endif - gfx_sdl_set_fullscreen(configFullscreen); - SDL_GL_CreateContext(wnd); SDL_GL_SetSwapInterval(1); // We have a double buffered GL context, it makes no sense to want tearing. From d6820f6073e8fd6bd5bac2e92980e520a7d18ea8 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 10 May 2020 19:09:43 +0300 Subject: [PATCH 35/39] whoops, this is supposed to be the Z button --- src/pc/controller/controller_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index 77e37d4d..f7c8b81c 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -83,7 +83,7 @@ static void controller_sdl_read(OSContPad *pad) { } if (SDL_GameControllerGetButton(sdl_cntrl, configJoyStart)) pad->button |= START_BUTTON; - if (SDL_GameControllerGetButton(sdl_cntrl, configJoyL)) pad->button |= Z_TRIG; + if (SDL_GameControllerGetButton(sdl_cntrl, configJoyZ)) pad->button |= Z_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; From 6c7df61480080d80e8e8462b7f1ff69eb97778a9 Mon Sep 17 00:00:00 2001 From: IvanDSM Date: Sun, 10 May 2020 13:13:15 -0300 Subject: [PATCH 36/39] Add warning about WINDOWS_BUILD --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index a40dfb29..ada27ecb 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ else endif # Automatic settings for PC port(s) +# WINDOWS_BUILD IS NOT FOR COMPILING A WINDOWS EXECUTABLE UNDER LINUX! NON_MATCHING := 1 GRUCODE := f3dex2e From 2234e28625f785fcfc71fab3529e76f42274f0d3 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 10 May 2020 19:14:59 +0300 Subject: [PATCH 37/39] rebind Z trigger back to L --- src/pc/configfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 8f304ab6..57b9a4f2 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -49,9 +49,9 @@ unsigned int configKeyStickRight = 0x20; unsigned int configJoyA = 0; unsigned int configJoyB = 2; unsigned int configJoyStart = 6; -unsigned int configJoyL = 9; +unsigned int configJoyL = 7; unsigned int configJoyR = 10; -unsigned int configJoyZ = 7; +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; From d0b85785fe8956069fbda113816dc196b2606701 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 10 May 2020 19:15:13 +0300 Subject: [PATCH 38/39] might as well check for L while we're at it --- src/pc/controller/controller_sdl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pc/controller/controller_sdl.c b/src/pc/controller/controller_sdl.c index f7c8b81c..48120231 100644 --- a/src/pc/controller/controller_sdl.c +++ b/src/pc/controller/controller_sdl.c @@ -84,6 +84,7 @@ 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; From f24d44c9c73adb8361d1a7f74981adf84f64cfd7 Mon Sep 17 00:00:00 2001 From: vanfanel Date: Sun, 10 May 2020 18:23:34 +0200 Subject: [PATCH 39/39] Remove redundant code. Make GLES and GL modes respect DESIRED_WIDTH and DESIRED_HEIGHT in windowed mode, but in fullscreen mode just use the system video mode. --- src/pc/gfx/gfx_sdl2.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 3f75ed2f..80a539a0 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -117,19 +117,23 @@ static void gfx_sdl_init(void) { window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } - - #ifndef USE_GLES - wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, window_flags); - #else - /* GLES platforms generally run without a window server like Xorg. Just use the system video mode, - instead of trying to set a new video mode, which does not make any sense in modern displays. */ SDL_DisplayMode sdl_displaymode; SDL_GetCurrentDisplayMode(0, &sdl_displaymode); - wnd = SDL_CreateWindow("Super Mario 64 PC port (OpenGL_ES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - sdl_displaymode.w, sdl_displaymode.h, window_flags); + const char* window_title = + #ifndef USE_GLES + "Super Mario 64 PC port (OpenGL)"; + #else + "Super Mario 64 PC port (OpenGL_ES2)"; #endif + + if (configFullscreen) { + wnd = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + sdl_displaymode.w, sdl_displaymode.h, window_flags); + } else { + wnd = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, window_flags); + } SDL_GL_CreateContext(wnd); SDL_GL_SetSwapInterval(1); // We have a double buffered GL context, it makes no sense to want tearing.