mirror of
https://github.com/izzy2lost/sm64-izzys-port-android.git
synced 2026-07-05 15:19:31 -07:00
Merge remote-tracking branch 'sm64ex/nightly' into ex/nightly
This commit is contained in:
@@ -30,6 +30,9 @@ TARGET_WEB ?= 0
|
||||
# Makeflag to enable OSX fixes
|
||||
OSX_BUILD ?= 0
|
||||
|
||||
# Enable -no-pie linker option
|
||||
NO_PIE ?= 1
|
||||
|
||||
# Specify the target you are building for, TARGET_BITS=0 means native
|
||||
TARGET_ARCH ?= native
|
||||
TARGET_BITS ?= 0
|
||||
@@ -59,11 +62,11 @@ NO_LDIV ?= 0
|
||||
|
||||
# Renderers: GL, GL_LEGACY, D3D11, D3D12
|
||||
RENDER_API ?= GL
|
||||
# Window managers: SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API)
|
||||
# Window managers: SDL1, SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API)
|
||||
WINDOW_API ?= SDL2
|
||||
# Audio backends: SDL2
|
||||
# Audio backends: SDL1, SDL2
|
||||
AUDIO_API ?= SDL2
|
||||
# Controller backends (can have multiple, space separated): SDL2
|
||||
# Controller backends (can have multiple, space separated): SDL2, SDL1
|
||||
CONTROLLER_API ?= SDL2
|
||||
|
||||
# Misc settings for EXTERNAL_DATA
|
||||
@@ -501,7 +504,9 @@ SDLCONFIG := $(CROSS)sdl2-config
|
||||
BACKEND_CFLAGS := -DRAPI_$(RENDER_API)=1 -DWAPI_$(WINDOW_API)=1 -DAAPI_$(AUDIO_API)=1
|
||||
# can have multiple controller APIs
|
||||
BACKEND_CFLAGS += $(foreach capi,$(CONTROLLER_API),-DCAPI_$(capi)=1)
|
||||
BACKEND_LDFLAGS :=
|
||||
BACKEND_LDFLAG0S :=
|
||||
|
||||
SDL1_USED := 0
|
||||
SDL2_USED := 0
|
||||
|
||||
# for now, it's either SDL+GL or DXGI+DirectX, so choose based on WAPI
|
||||
@@ -512,7 +517,7 @@ ifeq ($(WINDOW_API),DXGI)
|
||||
endif
|
||||
BACKEND_LDFLAGS += -ld3dcompiler -ldxgi -ldxguid
|
||||
BACKEND_LDFLAGS += -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -static
|
||||
else ifeq ($(WINDOW_API),SDL2)
|
||||
else ifeq ($(findstring SDL,$(WINDOW_API)),SDL)
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
BACKEND_LDFLAGS += -lglew32 -lglu32 -lopengl32
|
||||
else ifeq ($(TARGET_ANDROID),1)
|
||||
@@ -524,24 +529,35 @@ else ifeq ($(WINDOW_API),SDL2)
|
||||
else
|
||||
BACKEND_LDFLAGS += -lGL
|
||||
endif
|
||||
SDL_USED := 2
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_API),SDL2)
|
||||
SDL_USED := 2
|
||||
ifneq (,$(findstring SDL2,$(AUDIO_API)$(WINDOW_API)$(CONTROLLER_API)))
|
||||
SDL2_USED := 1
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring SDL,$(CONTROLLER_API)))
|
||||
SDL_USED := 2
|
||||
ifneq (,$(findstring SDL1,$(AUDIO_API)$(WINDOW_API)$(CONTROLLER_API)))
|
||||
SDL1_USED := 1
|
||||
endif
|
||||
|
||||
ifeq ($(SDL1_USED)$(SDL2_USED),11)
|
||||
$(error Cannot link both SDL1 and SDL2 at the same time)
|
||||
endif
|
||||
|
||||
# SDL can be used by different systems, so we consolidate all of that shit into this
|
||||
ifeq ($(SDL_USED),2)
|
||||
|
||||
ifeq ($(SDL2_USED),1)
|
||||
SDLCONFIG := $(CROSS)sdl2-config
|
||||
BACKEND_CFLAGS += -DHAVE_SDL2=1
|
||||
else ifeq ($(SDL1_USED),1)
|
||||
SDLCONFIG := $(CROSS)sdl-config
|
||||
BACKEND_CFLAGS += -DHAVE_SDL1=1
|
||||
endif
|
||||
|
||||
ifneq ($(SDL1_USED)$(SDL2_USED),00)
|
||||
ifeq ($(TARGET_ANDROID),1)
|
||||
BACKEND_CFLAGS += -DHAVE_SDL2=1
|
||||
BACKEND_LDFLAGS += -lhidapi -lSDL2
|
||||
else
|
||||
BACKEND_CFLAGS += -DHAVE_SDL2=1 `$(SDLCONFIG) --cflags`
|
||||
BACKEND_CFLAGS += `$(SDLCONFIG) --cflags`
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
BACKEND_LDFLAGS += `$(SDLCONFIG) --static-libs` -lsetupapi -luser32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion
|
||||
else
|
||||
@@ -637,7 +653,7 @@ endif
|
||||
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']"
|
||||
LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=64MB -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 $(BACKEND_LDFLAGS) -static
|
||||
@@ -668,9 +684,13 @@ else ifeq ($(OSX_BUILD),1)
|
||||
LDFLAGS := -lm $(BACKEND_LDFLAGS) -no-pie -lpthread
|
||||
|
||||
else
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm $(BACKEND_LDFLAGS) -no-pie -lpthread
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm $(BACKEND_LDFLAGS) -lpthread -ldl
|
||||
ifeq ($(NO_PIE), 1)
|
||||
LDFLAGS += -no-pie
|
||||
endif
|
||||
|
||||
ifeq ($(DISCORDRPC),1)
|
||||
LDFLAGS += -ldl -Wl,-rpath .
|
||||
LDFLAGS += -Wl,-rpath .
|
||||
endif
|
||||
|
||||
endif # End of LDFLAGS
|
||||
|
||||
+15
-15
@@ -112,7 +112,7 @@ index 802d97a..1b0d677 100644
|
||||
|
||||
/** A node that allows an object to specify a different culling radius than the
|
||||
diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c
|
||||
index 5b6775f..2c11e25 100644
|
||||
index 1da535b..49a5c03 100644
|
||||
--- a/src/engine/surface_collision.c
|
||||
+++ b/src/engine/surface_collision.c
|
||||
@@ -8,6 +8,7 @@
|
||||
@@ -1890,19 +1890,10 @@ index 0467495..fa4eb33 100644
|
||||
|
||||
using namespace Microsoft::WRL; // For ComPtr
|
||||
diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c
|
||||
index 5f4c690..de96bbd 100644
|
||||
index 42b8541..388e137 100644
|
||||
--- a/src/pc/gfx/gfx_sdl2.c
|
||||
+++ b/src/pc/gfx/gfx_sdl2.c
|
||||
@@ -61,7 +61,7 @@ static void (*touch_up_callback)(void* event);
|
||||
// whether to use timer for frame control
|
||||
static bool use_timer = true;
|
||||
// time between consequtive game frames
|
||||
-static const int frame_time = 1000 / FRAMERATE;
|
||||
+static const int frame_time = 1000 / (2 * FRAMERATE);
|
||||
|
||||
const SDL_Scancode windows_scancode_table[] = {
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
@@ -153,11 +153,11 @@ int test_vsync(void) {
|
||||
@@ -161,11 +161,11 @@ static int test_vsync(void) {
|
||||
* On SGI models, turning vsync off will help with framerate, but the best is 60fps patch.
|
||||
* The actual solution would be to render or copy the buffer to a texture
|
||||
* and then render that to the screen.*/
|
||||
@@ -1916,11 +1907,11 @@ index 5f4c690..de96bbd 100644
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -165,7 +165,11 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
|
||||
@@ -173,7 +173,11 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
|
||||
if (enabled) {
|
||||
// try to detect refresh rate
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
- const int vblanks = test_vsync();
|
||||
- const int vblanks = gCLIOpts.SyncFrames ? (int)gCLIOpts.SyncFrames : test_vsync();
|
||||
+ int vblanks = test_vsync();
|
||||
+ if (vblanks & 1)
|
||||
+ vblanks = 0; // not divisible by 60, fuck that
|
||||
@@ -1929,8 +1920,17 @@ index 5f4c690..de96bbd 100644
|
||||
if (vblanks) {
|
||||
printf("determined swap interval: %d\n", vblanks);
|
||||
SDL_GL_SetSwapInterval(vblanks);
|
||||
@@ -258,7 +262,7 @@ static void gfx_sdl_init(const char *window_title) {
|
||||
gfx_sdl_set_fullscreen();
|
||||
|
||||
perf_freq = SDL_GetPerformanceFrequency();
|
||||
- frame_time = perf_freq / FRAMERATE;
|
||||
+ frame_time = perf_freq / (2 * FRAMERATE);
|
||||
|
||||
for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) {
|
||||
inverted_scancode_table[windows_scancode_table[i]] = i;
|
||||
diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c
|
||||
index a3c9817..8c61830 100644
|
||||
index 5fda297..35d50db 100644
|
||||
--- a/src/pc/pc_main.c
|
||||
+++ b/src/pc/pc_main.c
|
||||
@@ -84,6 +84,25 @@ void send_display_list(struct SPTask *spTask) {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
// Markers
|
||||
|
||||
#define TEXT_OPT_HIGHLIGHT _("O")
|
||||
#define TEXT_OPT_L_HIGHLIGHT _(">")
|
||||
#define TEXT_OPT_R_HIGHLIGHT _("<")
|
||||
#define TEXT_OPT_UNBOUND _("NONE")
|
||||
|
||||
// Language specific strings
|
||||
|
||||
@@ -851,7 +851,11 @@ void find_surface_on_ray_list(struct SurfaceNode *list, Vec3f orig, Vec3f dir, f
|
||||
// Reject surface if out of vertical bounds
|
||||
if (list->surface->lowerY > top || list->surface->upperY < bottom)
|
||||
continue;
|
||||
|
||||
|
||||
// Reject no-cam collision surfaces
|
||||
if (gCheckingSurfaceCollisionsForCamera && (list->surface->flags & SURFACE_FLAG_NO_CAM_COLLISION))
|
||||
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)
|
||||
{
|
||||
@@ -919,13 +923,16 @@ void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Ve
|
||||
find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// increase collision checking precision (normally 1)
|
||||
f32 precision = gCheckingSurfaceCollisionsForCamera ? 3 : 1;
|
||||
|
||||
// Get cells we cross using DDA
|
||||
if (absx(dir[0]) >= absx(dir[2]))
|
||||
step = absx(dir[0]) / CELL_SIZE;
|
||||
step = precision * absx(dir[0]) / CELL_SIZE;
|
||||
else
|
||||
step = absx(dir[2]) / CELL_SIZE;
|
||||
|
||||
step = precision * absx(dir[2]) / CELL_SIZE;
|
||||
|
||||
dx = dir[0] / step / CELL_SIZE;
|
||||
dz = dir[2] / step / CELL_SIZE;
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@ struct Struct8032F754 D_8032F754[] = { { 145, { 0.7f, 1.5f, 0.7f }, 7.0f },
|
||||
{ 235, { 1.2f, 2.0f, 1.2f }, 11.6f } };
|
||||
|
||||
void bhv_checkerboard_elevator_group_init(void) {
|
||||
// Added to prevent a crash in the vanish cap stage
|
||||
cur_obj_hide();
|
||||
// Here's the theory: Since it is only valid for a few frames, I believe
|
||||
// the model gets deallocated after removal. Since changing the camera
|
||||
// precision makes the camera end up in a slightly different spot, it
|
||||
// could be trying to render the object when `precision` is set to 3 but
|
||||
// not to 1.
|
||||
|
||||
s32 sp3C;
|
||||
s32 sp38;
|
||||
s32 sp34;
|
||||
|
||||
@@ -181,10 +181,9 @@ void bhv_snufit_balls_loop(void) {
|
||||
// If far from Mario or in a different room, despawn.
|
||||
if ((o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
|| (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)) {
|
||||
#else
|
||||
|| (o->oTimer != 0)) {
|
||||
|| (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)
|
||||
#endif
|
||||
){
|
||||
obj_mark_for_deletion(o);
|
||||
}
|
||||
|
||||
|
||||
+71
-15
@@ -10,12 +10,16 @@
|
||||
#include "engine/surface_collision.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/controller/controller_mouse.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
//quick and dirty fix for some older MinGW.org mingwrt
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define NEW_CAM_BOUNDING_BOX_RAYS 4
|
||||
#define NEW_CAM_BOUNDING_BOX_HRADIUS 250
|
||||
#define NEW_CAM_BOUNDING_BOX_VRADIUS 100
|
||||
|
||||
/**
|
||||
Quick explanation of the camera modes
|
||||
@@ -269,18 +273,18 @@ static void newcam_rotate_button(void) {
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(newcam_invertX)*0x2000);
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x2000);
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(newcam_invertX)*0x4000);
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(0)*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-(ivrt(newcam_invertX)*0x2000);
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x2000);
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(newcam_invertX)*0x4000);
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x4000);
|
||||
newcam_centering = 1;
|
||||
}
|
||||
} else if (newcam_modeflags & NC_FLAG_XTURN) {
|
||||
@@ -314,7 +318,7 @@ static void newcam_rotate_button(void) {
|
||||
newcam_framessincec[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+(ivrt(newcam_invertX)*0x3000);
|
||||
newcam_yaw_target = newcam_yaw+(ivrt(0)*0x3000);
|
||||
newcam_centering = 1;
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
@@ -324,7 +328,7 @@ static void newcam_rotate_button(void) {
|
||||
}
|
||||
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-(ivrt(newcam_invertX)*0x3000);
|
||||
newcam_yaw_target = newcam_yaw-(ivrt(0)*0x3000);
|
||||
newcam_centering = 1;
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
@@ -350,14 +354,14 @@ static void newcam_rotate_button(void) {
|
||||
#endif
|
||||
if (newcam_stick2[0] > 20) {
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(newcam_invertX)*0x2000);
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x2000);
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(newcam_invertX)*0x4000);
|
||||
newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x4000);
|
||||
} else {
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(newcam_invertX)*0x2000);
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x2000);
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(newcam_invertX)*0x4000);
|
||||
newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x4000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -425,9 +429,9 @@ static void newcam_update_values(void) {
|
||||
u8 waterflag = 0;
|
||||
|
||||
if (newcam_modeflags & NC_FLAG_XTURN)
|
||||
newcam_yaw -= ((newcam_yaw_acc*(newcam_sensitivityX/10))*ivrt(newcam_invertX));
|
||||
newcam_yaw -= ((newcam_yaw_acc*(newcam_sensitivityX/10))*ivrt(0));
|
||||
if (((newcam_tilt <= 12000) && (newcam_tilt >= -12000)) && newcam_modeflags & NC_FLAG_YTURN)
|
||||
newcam_tilt += ((newcam_tilt_acc*ivrt(newcam_invertY))*(newcam_sensitivityY/10));
|
||||
newcam_tilt += ((newcam_tilt_acc*ivrt(1))*(newcam_sensitivityY/10));
|
||||
|
||||
if (newcam_tilt > 12000)
|
||||
newcam_tilt = 12000;
|
||||
@@ -473,6 +477,47 @@ static void newcam_update_values(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_bounding_box(void) {
|
||||
Vec3f camdirs[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 };
|
||||
Vec3f raypos[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 };
|
||||
s16 antiYaw = newcam_yaw - 0x4000;
|
||||
|
||||
// sideways ray 1
|
||||
camdirs[0][0] = coss(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
camdirs[0][2] = sins(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
|
||||
// sideways ray 2
|
||||
camdirs[1][0] = -coss(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
camdirs[1][2] = -sins(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
|
||||
// vertical rays
|
||||
camdirs[2][1] = -NEW_CAM_BOUNDING_BOX_VRADIUS;
|
||||
camdirs[3][1] = NEW_CAM_BOUNDING_BOX_VRADIUS;
|
||||
|
||||
for (int i = 0; i < NEW_CAM_BOUNDING_BOX_RAYS; i++) {
|
||||
struct Surface* surf;
|
||||
Vec3f offset = { 0 };
|
||||
|
||||
Vec3f startpos = { 0 };
|
||||
vec3f_copy(startpos, newcam_pos);
|
||||
vec3f_add(startpos, offset);
|
||||
|
||||
find_surface_on_ray(startpos, camdirs[i], &surf, raypos[i]);
|
||||
if (!surf) {
|
||||
vec3f_copy(raypos[i], startpos);
|
||||
vec3f_add(raypos[i], camdirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f avg = { 0 };
|
||||
for (int i = 0; i < NEW_CAM_BOUNDING_BOX_RAYS; i++) {
|
||||
vec3f_add(avg, raypos[i]);
|
||||
}
|
||||
vec3f_mul(avg, 1.0f / ((f32)NEW_CAM_BOUNDING_BOX_RAYS));
|
||||
|
||||
vec3f_copy(newcam_pos, avg);
|
||||
}
|
||||
|
||||
static void newcam_collision(void) {
|
||||
struct Surface *surf;
|
||||
Vec3f camdir;
|
||||
@@ -483,11 +528,20 @@ static void newcam_collision(void) {
|
||||
camdir[2] = newcam_pos[2]-newcam_lookat[2];
|
||||
|
||||
find_surface_on_ray(newcam_pos_target, camdir, &surf, hitpos);
|
||||
|
||||
newcam_coldist = sqrtf((newcam_pos_target[0] - hitpos[0]) * (newcam_pos_target[0] - hitpos[0]) + (newcam_pos_target[1] - hitpos[1]) * (newcam_pos_target[1] - hitpos[1]) + (newcam_pos_target[2] - hitpos[2]) * (newcam_pos_target[2] - hitpos[2]));
|
||||
|
||||
if (surf) {
|
||||
// offset the hit pos by the hit normal
|
||||
Vec3f offset = { 0 };
|
||||
offset[0] = surf->normal.x;
|
||||
offset[1] = surf->normal.y;
|
||||
offset[2] = surf->normal.z;
|
||||
vec3f_mul(offset, 5.0f);
|
||||
vec3f_add(hitpos, offset);
|
||||
|
||||
newcam_pos[0] = hitpos[0];
|
||||
newcam_pos[1] = approach_f32(hitpos[1],newcam_pos[1],25,-25);
|
||||
newcam_pos[1] = hitpos[1];
|
||||
newcam_pos[2] = hitpos[2];
|
||||
newcam_pan_x = 0;
|
||||
newcam_pan_z = 0;
|
||||
@@ -541,8 +595,10 @@ static void newcam_position_cam(void) {
|
||||
if (newcam_modeflags & NC_FLAG_FOCUSZ)
|
||||
newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z;
|
||||
|
||||
if (newcam_modeflags & NC_FLAG_COLLISION)
|
||||
newcam_collision();
|
||||
if (newcam_modeflags & NC_FLAG_COLLISION) {
|
||||
newcam_collision();
|
||||
newcam_bounding_box();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1754,7 +1754,7 @@ s32 act_flying(struct MarioState *m) {
|
||||
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);
|
||||
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define MEMORY_POOL_RIGHT 1
|
||||
|
||||
#define GFX_POOL_SIZE (512 * 1024)
|
||||
#define DEFAULT_POOL_SIZE (0x165000 * 8)
|
||||
|
||||
struct AllocOnlyPool
|
||||
{
|
||||
|
||||
+26
-25
@@ -1,7 +1,7 @@
|
||||
#ifdef EXT_OPTIONS_MENU
|
||||
|
||||
#include "sm64.h"
|
||||
#include "include/text_strings.h"
|
||||
#include "text_strings.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "audio/external.h"
|
||||
#include "game/camera.h"
|
||||
@@ -45,10 +45,14 @@ static const u8 toggleStr[][16] = {
|
||||
{ TEXT_OPT_ENABLED },
|
||||
};
|
||||
|
||||
static const u8 menuStr[][32] = {
|
||||
{ TEXT_OPT_HIGHLIGHT },
|
||||
static const u8 optSmallStr[][32] = {
|
||||
{ TEXT_OPT_BUTTON1 },
|
||||
{ TEXT_OPT_BUTTON2 },
|
||||
{ TEXT_OPT_L_HIGHLIGHT },
|
||||
{ TEXT_OPT_R_HIGHLIGHT },
|
||||
};
|
||||
|
||||
static const u8 menuStr[][32] = {
|
||||
{ TEXT_OPT_OPTIONS },
|
||||
{ TEXT_OPT_CAMERA },
|
||||
{ TEXT_OPT_CONTROLS },
|
||||
@@ -56,7 +60,6 @@ static const u8 menuStr[][32] = {
|
||||
{ TEXT_OPT_AUDIO },
|
||||
{ TEXT_EXIT_GAME },
|
||||
{ TEXT_OPT_CHEATS },
|
||||
|
||||
};
|
||||
|
||||
static const u8 optsCameraStr[][32] = {
|
||||
@@ -122,7 +125,7 @@ static const u8 bindStr[][32] = {
|
||||
{ TEXT_BIND_LEFT },
|
||||
{ TEXT_BIND_RIGHT },
|
||||
{ TEXT_OPT_DEADZONE },
|
||||
{ TEXT_OPT_RUMBLE }
|
||||
{ TEXT_OPT_RUMBLE },
|
||||
};
|
||||
|
||||
static const u8 *filterChoices[] = {
|
||||
@@ -285,28 +288,28 @@ static struct Option optsCheats[] = {
|
||||
/* submenu definitions */
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera );
|
||||
static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[1], optsCamera );
|
||||
#endif
|
||||
static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls );
|
||||
static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo );
|
||||
static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio );
|
||||
static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats );
|
||||
static struct SubMenu menuControls = DEF_SUBMENU( menuStr[2], optsControls );
|
||||
static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[3], optsVideo );
|
||||
static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[4], optsAudio );
|
||||
static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[6], optsCheats );
|
||||
|
||||
/* main options menu definition */
|
||||
|
||||
static struct Option optsMain[] = {
|
||||
#ifdef BETTERCAMERA
|
||||
DEF_OPT_SUBMENU( menuStr[4], &menuCamera ),
|
||||
DEF_OPT_SUBMENU( menuStr[1], &menuCamera ),
|
||||
#endif
|
||||
DEF_OPT_SUBMENU( menuStr[5], &menuControls ),
|
||||
DEF_OPT_SUBMENU( menuStr[6], &menuVideo ),
|
||||
DEF_OPT_SUBMENU( menuStr[7], &menuAudio ),
|
||||
DEF_OPT_BUTTON ( menuStr[8], optmenu_act_exit ),
|
||||
DEF_OPT_SUBMENU( menuStr[2], &menuControls ),
|
||||
DEF_OPT_SUBMENU( menuStr[3], &menuVideo ),
|
||||
DEF_OPT_SUBMENU( menuStr[4], &menuAudio ),
|
||||
DEF_OPT_BUTTON ( menuStr[5], optmenu_act_exit ),
|
||||
// NOTE: always keep cheats the last option here because of the half-assed way I toggle them
|
||||
DEF_OPT_SUBMENU( menuStr[9], &menuCheats )
|
||||
DEF_OPT_SUBMENU( menuStr[6], &menuCheats )
|
||||
};
|
||||
|
||||
static struct SubMenu menuMain = DEF_SUBMENU( menuStr[3], optsMain );
|
||||
static struct SubMenu menuMain = DEF_SUBMENU( menuStr[0], optsMain );
|
||||
|
||||
/* implementation */
|
||||
|
||||
@@ -465,6 +468,7 @@ void optmenu_draw(void) {
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 80, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
for (u8 i = 0; i < currentMenu->numOpts; i++) {
|
||||
scroll = 140 - 32 * i + currentMenu->scroll * 32;
|
||||
// FIXME: just start from the first visible option bruh
|
||||
@@ -473,18 +477,16 @@ void optmenu_draw(void) {
|
||||
}
|
||||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 80, 90 + (32 * (currentMenu->select - currentMenu->scroll)), menuStr[0]);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90 + (32 * (currentMenu->select - currentMenu->scroll)), menuStr[0]);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||
print_generic_string(72, 132 - (32 * (currentMenu->select - currentMenu->scroll)), optSmallStr[2]);
|
||||
print_generic_string(232, 132 - (32 * (currentMenu->select - currentMenu->scroll)), optSmallStr[3]);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
}
|
||||
|
||||
//This has been separated for interesting reasons. Don't question it.
|
||||
void optmenu_draw_prompt(void) {
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
optmenu_draw_text(264, 212, menuStr[1 + optmenu_open], 0);
|
||||
optmenu_draw_text(264, 212, optSmallStr[optmenu_open], 0);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
}
|
||||
|
||||
@@ -506,7 +508,6 @@ void optmenu_toggle(void) {
|
||||
|
||||
currentMenu = &menuMain;
|
||||
optmenu_open = 1;
|
||||
|
||||
/* Resets l_counter to 0 every time the options menu is open */
|
||||
l_counter = 0;
|
||||
} else {
|
||||
@@ -538,7 +539,7 @@ void optmenu_check_buttons(void) {
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG)
|
||||
optmenu_toggle();
|
||||
|
||||
|
||||
/* Enables cheats if the user press the L trigger 3 times while in the options menu. Also plays a sound. */
|
||||
|
||||
if ((gPlayer1Controller->buttonPressed & L_TRIG) && !Cheats.EnableCheats) {
|
||||
|
||||
@@ -615,6 +615,12 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) {
|
||||
|
||||
return starFlags;
|
||||
}
|
||||
u32 save_file_get_cannon_flags(s32 fileIndex, s32 courseIndex) {
|
||||
|
||||
if (gSaveBuffer.files[fileIndex][0].courseStars[courseIndex+1] & 0x80){return 1;}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the bitset of obtained stars in the specified course.
|
||||
|
||||
@@ -135,6 +135,7 @@ void save_file_set_flags(u32 flags);
|
||||
void save_file_clear_flags(u32 flags);
|
||||
u32 save_file_get_flags(void);
|
||||
u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex);
|
||||
u32 save_file_get_cannon_flags(s32 fileIndex, s32 courseIndex);
|
||||
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags);
|
||||
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex);
|
||||
s32 save_file_is_cannon_unlocked(void);
|
||||
|
||||
@@ -81,7 +81,7 @@ static s32 write_text_save(s32 fileIndex) {
|
||||
struct MainMenuSaveData *menudata;
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
char value[64];
|
||||
u32 i, bit, flags, coins, stars, starFlags;
|
||||
u32 i, bit, flags, coins, stars, starFlags, cannonFlag;
|
||||
|
||||
if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, fs_writepath, fileIndex) < 0)
|
||||
return -1;
|
||||
@@ -133,9 +133,10 @@ static s32 write_text_save(s32 fileIndex) {
|
||||
for (i = 0; i < NUM_COURSES; i++) {
|
||||
stars = save_file_get_star_flags(fileIndex, i);
|
||||
coins = save_file_get_course_coin_score(fileIndex, i);
|
||||
cannonFlag = save_file_get_cannon_flags(fileIndex, i);
|
||||
starFlags = int_to_bin(stars); // 63 -> 111111
|
||||
|
||||
fprintf(file, "%s = \"%d, %07d\"\n", sav_courses[i], coins, starFlags);
|
||||
fprintf(file, "%s = \"%d, %07d, %d\"\n", sav_courses[i], coins, starFlags,cannonFlag);
|
||||
}
|
||||
|
||||
fprintf(file, "\n[bonus]\n");
|
||||
@@ -208,7 +209,7 @@ static s32 read_text_save(s32 fileIndex) {
|
||||
const char *value;
|
||||
ini_t *savedata;
|
||||
|
||||
u32 i, flag, coins, stars, starFlags;
|
||||
u32 i, flag, coins, stars, starFlags, cannonFlag;
|
||||
u32 capArea;
|
||||
|
||||
if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, fs_writepath, fileIndex) < 0)
|
||||
@@ -255,9 +256,10 @@ static s32 read_text_save(s32 fileIndex) {
|
||||
for (i = 0; i < NUM_COURSES; i++) {
|
||||
value = ini_get(savedata, "courses", sav_courses[i]);
|
||||
if (value) {
|
||||
sscanf(value, "%d, %d", &coins, &stars);
|
||||
sscanf(value, "%d, %d, %d", &coins, &stars, &cannonFlag);
|
||||
starFlags = bin_to_int(stars); // 111111 -> 63
|
||||
|
||||
cannonFlag <<= 7; //Shifts the bit to the most significant bit.
|
||||
save_file_set_star_flags(fileIndex, i+1, cannonFlag); //
|
||||
save_file_set_star_flags(fileIndex, i, starFlags);
|
||||
gSaveBuffer.files[fileIndex][0].courseCoinScores[i] = coins;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
#ifdef AAPI_SDL1
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "audio_api.h"
|
||||
|
||||
#define SNDPACKETLEN (8 * 1024)
|
||||
|
||||
// this is basically SDL_dataqueue but slightly less generic
|
||||
|
||||
typedef struct sndpacket {
|
||||
size_t datalen; /* bytes currently in use in this packet. */
|
||||
size_t startpos; /* bytes currently consumed in this packet. */
|
||||
struct sndpacket *next; /* next item in linked list. */
|
||||
Uint8 data[]; /* packet data */
|
||||
} sndpacket_t;
|
||||
|
||||
static sndpacket_t *qhead;
|
||||
static sndpacket_t *qtail;
|
||||
static sndpacket_t *qpool;
|
||||
static size_t queued;
|
||||
|
||||
static SDL_AudioSpec aspec;
|
||||
static int was_init = 0;
|
||||
|
||||
static void sndqueue_init(const size_t bufsize) {
|
||||
const size_t wantpackets = (bufsize + (SNDPACKETLEN - 1)) / SNDPACKETLEN;
|
||||
for (size_t i = 0; i < wantpackets; ++i) {
|
||||
sndpacket_t *packet = malloc(sizeof(sndpacket_t) + SNDPACKETLEN);
|
||||
if (packet) {
|
||||
packet->datalen = 0;
|
||||
packet->startpos = 0;
|
||||
packet->next = qpool;
|
||||
qpool = packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t sndqueue_read(void *buf, size_t len) {
|
||||
sndpacket_t *packet;
|
||||
Uint8 *ptr = buf;
|
||||
|
||||
while ((len > 0) && ((packet = qhead) != NULL)) {
|
||||
const size_t avail = packet->datalen - packet->startpos;
|
||||
const size_t tx = (len < avail) ? len : avail;
|
||||
|
||||
memcpy(ptr, packet->data + packet->startpos, tx);
|
||||
packet->startpos += tx;
|
||||
ptr += tx;
|
||||
queued -= tx;
|
||||
len -= tx;
|
||||
|
||||
if (packet->startpos == packet->datalen) {
|
||||
qhead = packet->next;
|
||||
packet->next = qpool;
|
||||
qpool = packet;
|
||||
}
|
||||
}
|
||||
|
||||
if (qhead == NULL)
|
||||
qtail = NULL;
|
||||
|
||||
return (size_t)(ptr - (Uint8*)buf);
|
||||
}
|
||||
|
||||
static inline sndpacket_t *alloc_sndpacket(void) {
|
||||
sndpacket_t *packet = qpool;
|
||||
|
||||
if (packet) {
|
||||
qpool = packet->next;
|
||||
} else {
|
||||
packet = malloc(sizeof(sndpacket_t) + SNDPACKETLEN);
|
||||
if (!packet) return NULL;
|
||||
}
|
||||
|
||||
packet->datalen = 0;
|
||||
packet->startpos = 0;
|
||||
packet->next = NULL;
|
||||
|
||||
if (qtail == NULL)
|
||||
qhead = packet;
|
||||
else
|
||||
qtail->next = packet;
|
||||
qtail = packet;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
static int sndqueue_push(const void *data, size_t len) {
|
||||
sndpacket_t *orighead = qhead;
|
||||
sndpacket_t *origtail = qtail;
|
||||
size_t origlen = origtail ? origtail->datalen : 0;
|
||||
Uint8 *ptr = data;
|
||||
|
||||
while (len > 0) {
|
||||
sndpacket_t *packet = qtail;
|
||||
if (!packet || (packet->datalen >= SNDPACKETLEN)) {
|
||||
packet = alloc_sndpacket();
|
||||
if (!packet) {
|
||||
// out of memory, fuck everything
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t room = SNDPACKETLEN - packet->datalen;
|
||||
const size_t datalen = (len < room) ? len : room;
|
||||
memcpy(packet->data + packet->datalen, ptr, datalen);
|
||||
ptr += datalen;
|
||||
len -= datalen;
|
||||
packet->datalen += datalen;
|
||||
queued += datalen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audio_drain(void *user, Uint8 *buf, int len) {
|
||||
const size_t tx = sndqueue_read(buf, len);
|
||||
buf += tx;
|
||||
len -= (int)tx;
|
||||
if (len > 0) memset(buf, aspec.silence, len);
|
||||
}
|
||||
|
||||
static bool audio_sdl_init(void) {
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_AudioSpec want, have;
|
||||
memset(&want, 0, sizeof(want));
|
||||
want.freq = 32000;
|
||||
want.format = AUDIO_S16SYS;
|
||||
want.channels = 2;
|
||||
want.samples = 512;
|
||||
want.callback = audio_drain;
|
||||
if (SDL_OpenAudio(&want, &have) == -1) {
|
||||
fprintf(stderr, "SDL_OpenAudio error: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
aspec = have;
|
||||
|
||||
was_init = 1;
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int audio_sdl_buffered(void) {
|
||||
SDL_LockAudio();
|
||||
int len = queued / 4;
|
||||
SDL_UnlockAudio();
|
||||
return len;
|
||||
}
|
||||
|
||||
static int audio_sdl_get_desired_buffered(void) {
|
||||
return 1100;
|
||||
}
|
||||
|
||||
static void audio_sdl_play(const uint8_t *buf, size_t len) {
|
||||
SDL_LockAudio();
|
||||
// Don't fill the audio buffer too much in case this happens
|
||||
if (queued / 4 < 6000)
|
||||
sndqueue_push(buf, len);
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
|
||||
static void audio_sdl_shutdown(void) {
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
if (was_init) {
|
||||
SDL_CloseAudio();
|
||||
was_init = 0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
struct AudioAPI audio_sdl = {
|
||||
audio_sdl_init,
|
||||
audio_sdl_buffered,
|
||||
audio_sdl_get_desired_buffered,
|
||||
audio_sdl_play,
|
||||
audio_sdl_shutdown
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,10 +11,11 @@ static bool audio_sdl_init(void) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_AudioSpec want, have;
|
||||
SDL_zero(want);
|
||||
want.freq = 32000;
|
||||
want.format = AUDIO_S16;
|
||||
want.format = AUDIO_S16SYS;
|
||||
want.channels = 2;
|
||||
want.samples = 512;
|
||||
want.callback = NULL;
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "cheats.h"
|
||||
#include "pc_main.h"
|
||||
#include "platform.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
@@ -34,6 +35,12 @@ static inline int arg_string(const char *name, const char *value, char *target)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int arg_uint(UNUSED const char *name, const char *value, unsigned int *target) {
|
||||
const unsigned long int v = strtoul(value, NULL, 0);
|
||||
*target = v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[]) {
|
||||
// Initialize options with false values.
|
||||
memset(&gCLIOpts, 0, sizeof(gCLIOpts));
|
||||
@@ -51,6 +58,12 @@ void parse_cli_opts(int argc, char* argv[]) {
|
||||
else if (strcmp(argv[i], "--cheats") == 0) // Enable cheats menu
|
||||
Cheats.EnableCheats = true;
|
||||
|
||||
else if (strcmp(argv[i], "--poolsize") == 0) // Main pool size
|
||||
arg_uint("--poolsize", argv[++i], &gCLIOpts.PoolSize);
|
||||
|
||||
else if (strcmp(argv[i], "--syncframes") == 0) // VBlanks to wait
|
||||
arg_uint("--syncframes", argv[++i], &gCLIOpts.SyncFrames);
|
||||
|
||||
else if (strcmp(argv[i], "--configfile") == 0 && (i + 1) < argc)
|
||||
arg_string("--configfile", argv[++i], gCLIOpts.ConfigFile);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
struct PCCLIOptions {
|
||||
unsigned int SkipIntro;
|
||||
unsigned int FullScreen;
|
||||
unsigned int PoolSize;
|
||||
unsigned int SyncFrames;
|
||||
char ConfigFile[SYS_MAX_PATH];
|
||||
char SavePath[SYS_MAX_PATH];
|
||||
char GameDir[SYS_MAX_PATH];
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
static struct ControllerAPI *controller_implementations[] = {
|
||||
&controller_recorded_tas,
|
||||
#if defined(CAPI_SDL2) || defined(CAPI_SDL1)
|
||||
&controller_sdl,
|
||||
#endif
|
||||
&controller_keyboard,
|
||||
#ifdef TOUCH_CONTROLS
|
||||
&controller_touchscreen,
|
||||
@@ -22,9 +24,8 @@ static struct ControllerAPI *controller_implementations[] = {
|
||||
};
|
||||
|
||||
s32 osContInit(UNUSED OSMesgQueue *mq, u8 *controllerBits, UNUSED OSContStatus *status) {
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++)
|
||||
controller_implementations[i]->init();
|
||||
}
|
||||
*controllerBits = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -32,12 +33,14 @@ s32 osContInit(UNUSED OSMesgQueue *mq, u8 *controllerBits, UNUSED OSContStatus *
|
||||
s32 osMotorStart(UNUSED void *pfs) {
|
||||
// Since rumble stops by osMotorStop, its duration is not nessecary.
|
||||
// Set it to 5 seconds and hope osMotorStop() is called in time.
|
||||
controller_rumble_play(configRumbleStrength / 100.0f, 5.0f);
|
||||
if (configRumbleStrength)
|
||||
controller_rumble_play(configRumbleStrength / 100.0f, 5.0f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 osMotorStop(UNUSED void *pfs) {
|
||||
controller_rumble_stop();
|
||||
if (configRumbleStrength)
|
||||
controller_rumble_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
#ifdef CAPI_SDL1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <SDL/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
|
||||
|
||||
#include <ultra64.h>
|
||||
|
||||
#include "controller_api.h"
|
||||
#include "controller_sdl.h"
|
||||
#include "../configfile.h"
|
||||
#include "../platform.h"
|
||||
#include "../fs/fs.h"
|
||||
|
||||
#include "game/level_update.h"
|
||||
|
||||
// mouse buttons are also in the controller namespace (why), just offset 0x100
|
||||
#define VK_OFS_SDL_MOUSE 0x0100
|
||||
#define VK_BASE_SDL_MOUSE (VK_BASE_SDL_GAMEPAD + VK_OFS_SDL_MOUSE)
|
||||
#define MAX_JOYBINDS 32
|
||||
#define MAX_MOUSEBUTTONS 8 // arbitrary
|
||||
#define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers
|
||||
#define AXIS_THRESHOLD (30 * 256)
|
||||
|
||||
enum {
|
||||
JOY_AXIS_LEFTX,
|
||||
JOY_AXIS_LEFTY,
|
||||
JOY_AXIS_RIGHTX,
|
||||
JOY_AXIS_RIGHTY,
|
||||
JOY_AXIS_LTRIG,
|
||||
JOY_AXIS_RTRIG,
|
||||
MAX_AXES,
|
||||
};
|
||||
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
extern u8 newcam_mouse;
|
||||
#endif
|
||||
|
||||
static bool init_ok;
|
||||
static SDL_Joystick *sdl_joy;
|
||||
|
||||
static u32 num_joy_binds = 0;
|
||||
static u32 num_mouse_binds = 0;
|
||||
static u32 joy_binds[MAX_JOYBINDS][2];
|
||||
static u32 mouse_binds[MAX_JOYBINDS][2];
|
||||
static int joy_axis_binds[MAX_AXES] = { 0, 1, 2, 3, 4, 5 };
|
||||
|
||||
static bool joy_buttons[MAX_JOYBUTTONS] = { false };
|
||||
static u32 mouse_buttons = 0;
|
||||
static u32 last_mouse = VK_INVALID;
|
||||
static u32 last_joybutton = VK_INVALID;
|
||||
|
||||
static int num_joy_axes = 0;
|
||||
static int num_joy_buttons = 0;
|
||||
static int num_joy_hats = 0;
|
||||
|
||||
static inline void controller_add_binds(const u32 mask, const u32 *btns) {
|
||||
for (u32 i = 0; i < MAX_BINDS; ++i) {
|
||||
if (btns[i] >= VK_BASE_SDL_GAMEPAD && btns[i] <= VK_BASE_SDL_GAMEPAD + VK_SIZE) {
|
||||
if (btns[i] >= VK_BASE_SDL_MOUSE && num_joy_binds < MAX_JOYBINDS) {
|
||||
mouse_binds[num_mouse_binds][0] = btns[i] - VK_BASE_SDL_MOUSE;
|
||||
mouse_binds[num_mouse_binds][1] = mask;
|
||||
++num_mouse_binds;
|
||||
} else if (num_mouse_binds < MAX_JOYBINDS) {
|
||||
joy_binds[num_joy_binds][0] = btns[i] - VK_BASE_SDL_GAMEPAD;
|
||||
joy_binds[num_joy_binds][1] = mask;
|
||||
++num_joy_binds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_sdl_bind(void) {
|
||||
bzero(joy_binds, sizeof(joy_binds));
|
||||
bzero(mouse_binds, sizeof(mouse_binds));
|
||||
num_joy_binds = 0;
|
||||
num_mouse_binds = 0;
|
||||
|
||||
controller_add_binds(A_BUTTON, configKeyA);
|
||||
controller_add_binds(B_BUTTON, configKeyB);
|
||||
controller_add_binds(Z_TRIG, configKeyZ);
|
||||
controller_add_binds(STICK_UP, configKeyStickUp);
|
||||
controller_add_binds(STICK_LEFT, configKeyStickLeft);
|
||||
controller_add_binds(STICK_DOWN, configKeyStickDown);
|
||||
controller_add_binds(STICK_RIGHT, configKeyStickRight);
|
||||
controller_add_binds(U_CBUTTONS, configKeyCUp);
|
||||
controller_add_binds(L_CBUTTONS, configKeyCLeft);
|
||||
controller_add_binds(D_CBUTTONS, configKeyCDown);
|
||||
controller_add_binds(R_CBUTTONS, configKeyCRight);
|
||||
controller_add_binds(L_TRIG, configKeyL);
|
||||
controller_add_binds(R_TRIG, configKeyR);
|
||||
controller_add_binds(START_BUTTON, configKeyStart);
|
||||
}
|
||||
|
||||
static void controller_sdl_init(void) {
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_NumJoysticks() > 0)
|
||||
sdl_joy = SDL_JoystickOpen(0);
|
||||
|
||||
if (sdl_joy) {
|
||||
num_joy_axes = SDL_JoystickNumAxes(sdl_joy);
|
||||
num_joy_buttons = SDL_JoystickNumButtons(sdl_joy);
|
||||
num_joy_hats = SDL_JoystickNumHats(sdl_joy);
|
||||
|
||||
for (int i = 0; i < MAX_AXES; ++i)
|
||||
if (i >= num_joy_axes)
|
||||
joy_axis_binds[i] = -1;
|
||||
}
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_mouse == 1)
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
#endif
|
||||
|
||||
controller_sdl_bind();
|
||||
|
||||
init_ok = true;
|
||||
}
|
||||
|
||||
static inline void update_button(const int i, const bool new) {
|
||||
const bool pressed = !joy_buttons[i] && new;
|
||||
joy_buttons[i] = new;
|
||||
if (pressed) last_joybutton = i;
|
||||
}
|
||||
|
||||
static inline int16_t get_axis(const int i) {
|
||||
if (joy_axis_binds[i] >= 0)
|
||||
return SDL_JoystickGetAxis(sdl_joy, i);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void controller_sdl_read(OSContPad *pad) {
|
||||
if (!init_ok) return;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_mouse == 1 && sCurrPlayMode != 2)
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
else
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
|
||||
u32 mouse = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
|
||||
for (u32 i = 0; i < num_mouse_binds; ++i)
|
||||
if (mouse & SDL_BUTTON(mouse_binds[i][0]))
|
||||
pad->button |= mouse_binds[i][1];
|
||||
|
||||
// remember buttons that changed from 0 to 1
|
||||
last_mouse = (mouse_buttons ^ mouse) & mouse;
|
||||
mouse_buttons = mouse;
|
||||
#endif
|
||||
|
||||
if (!sdl_joy) return;
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
int16_t leftx = get_axis(JOY_AXIS_LEFTX);
|
||||
int16_t lefty = get_axis(JOY_AXIS_LEFTY);
|
||||
int16_t rightx = get_axis(JOY_AXIS_RIGHTX);
|
||||
int16_t righty = get_axis(JOY_AXIS_RIGHTY);
|
||||
|
||||
int16_t ltrig = get_axis(JOY_AXIS_LTRIG);
|
||||
int16_t rtrig = get_axis(JOY_AXIS_RTRIG);
|
||||
|
||||
#ifdef TARGET_WEB
|
||||
// Firefox has a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1606562
|
||||
// It sets down y to 32768.0f / 32767.0f, which is greater than the allowed 1.0f,
|
||||
// which SDL then converts to a int16_t by multiplying by 32767.0f, which overflows into -32768.
|
||||
// Maximum up will hence never become -32768 with the current version of SDL2,
|
||||
// so this workaround should be safe in compliant browsers.
|
||||
if (lefty == -32768) {
|
||||
lefty = 32767;
|
||||
}
|
||||
if (righty == -32768) {
|
||||
righty = 32767;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < num_joy_buttons; ++i) {
|
||||
const bool new = SDL_JoystickGetButton(sdl_joy, i);
|
||||
update_button(i, new);
|
||||
}
|
||||
|
||||
update_button(VK_LTRIGGER - VK_BASE_SDL_GAMEPAD, ltrig > AXIS_THRESHOLD);
|
||||
update_button(VK_RTRIGGER - VK_BASE_SDL_GAMEPAD, rtrig > AXIS_THRESHOLD);
|
||||
|
||||
u32 buttons_down = 0;
|
||||
for (u32 i = 0; i < num_joy_binds; ++i)
|
||||
if (joy_buttons[joy_binds[i][0]])
|
||||
buttons_down |= joy_binds[i][1];
|
||||
|
||||
pad->button |= buttons_down;
|
||||
|
||||
const u32 xstick = buttons_down & STICK_XMASK;
|
||||
const u32 ystick = buttons_down & STICK_YMASK;
|
||||
if (xstick == STICK_LEFT)
|
||||
pad->stick_x = -128;
|
||||
else if (xstick == STICK_RIGHT)
|
||||
pad->stick_x = 127;
|
||||
if (ystick == STICK_DOWN)
|
||||
pad->stick_y = -128;
|
||||
else if (ystick == STICK_UP)
|
||||
pad->stick_y = 127;
|
||||
|
||||
if (rightx < -0x4000) pad->button |= L_CBUTTONS;
|
||||
if (rightx > 0x4000) pad->button |= R_CBUTTONS;
|
||||
if (righty < -0x4000) pad->button |= U_CBUTTONS;
|
||||
if (righty > 0x4000) pad->button |= D_CBUTTONS;
|
||||
|
||||
uint32_t magnitude_sq = (uint32_t)(leftx * leftx) + (uint32_t)(lefty * lefty);
|
||||
uint32_t stickDeadzoneActual = configStickDeadzone * DEADZONE_STEP;
|
||||
if (magnitude_sq > (uint32_t)(stickDeadzoneActual * stickDeadzoneActual)) {
|
||||
pad->stick_x = leftx / 0x100;
|
||||
int stick_y = -lefty / 0x100;
|
||||
pad->stick_y = stick_y == 128 ? 127 : stick_y;
|
||||
}
|
||||
|
||||
magnitude_sq = (uint32_t)(rightx * rightx) + (uint32_t)(righty * righty);
|
||||
stickDeadzoneActual = configStickDeadzone * DEADZONE_STEP;
|
||||
if (magnitude_sq > (uint32_t)(stickDeadzoneActual * stickDeadzoneActual)) {
|
||||
pad->ext_stick_x = rightx / 0x100;
|
||||
int stick_y = -righty / 0x100;
|
||||
pad->ext_stick_y = stick_y == 128 ? 127 : stick_y;
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_sdl_rumble_play(f32 strength, f32 length) { }
|
||||
|
||||
static void controller_sdl_rumble_stop(void) { }
|
||||
|
||||
static u32 controller_sdl_rawkey(void) {
|
||||
if (last_joybutton != VK_INVALID) {
|
||||
const u32 ret = last_joybutton;
|
||||
last_joybutton = VK_INVALID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_MOUSEBUTTONS; ++i) {
|
||||
if (last_mouse & SDL_BUTTON(i)) {
|
||||
const u32 ret = VK_OFS_SDL_MOUSE + i;
|
||||
last_mouse = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return VK_INVALID;
|
||||
}
|
||||
|
||||
static void controller_sdl_shutdown(void) {
|
||||
if (SDL_WasInit(SDL_INIT_JOYSTICK)) {
|
||||
if (sdl_joy) {
|
||||
SDL_JoystickClose(sdl_joy);
|
||||
sdl_joy = NULL;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
}
|
||||
|
||||
init_ok = false;
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_sdl = {
|
||||
VK_BASE_SDL_GAMEPAD,
|
||||
controller_sdl_init,
|
||||
controller_sdl_read,
|
||||
controller_sdl_rawkey,
|
||||
controller_sdl_rumble_play,
|
||||
controller_sdl_rumble_stop,
|
||||
controller_sdl_bind,
|
||||
controller_sdl_shutdown
|
||||
};
|
||||
|
||||
#endif // CAPI_SDL1
|
||||
@@ -89,13 +89,6 @@ static void controller_sdl_bind(void) {
|
||||
}
|
||||
|
||||
static void controller_sdl_init(void) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
haptics_enabled = (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
// try loading an external gamecontroller mapping file
|
||||
uint64_t gcsize = 0;
|
||||
void *gcdata = fs_load_file("gamecontrollerdb.txt", &gcsize);
|
||||
@@ -109,6 +102,13 @@ static void controller_sdl_init(void) {
|
||||
free(gcdata);
|
||||
}
|
||||
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
haptics_enabled = (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0);
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_mouse == 1)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user