[WIP] Added switch support and QOL Changes to the UI

This commit is contained in:
Alex 2021-01-05 06:23:06 -06:00
parent a3cdec8307
commit 1c53bee114
24 changed files with 416 additions and 32 deletions

View File

@ -22,6 +22,10 @@ NON_MATCHING ?= 1
TARGET_RPI ?= 0
# Build for Emscripten/WebGL
TARGET_WEB ?= 0
# Build for Nintendo Switch
TARGET_SWITCH ?= 0
# Makeflag to enable OSX fixes
OSX_BUILD ?= 0
# Specify the target you are building for, TARGET_BITS=0 means native
@ -75,7 +79,7 @@ else
endif
endif
ifeq ($(TARGET_WEB),0)
ifeq ($(TARGET_WEB)$(TARGET_RPI)$(TARGET_SWITCH),000)
ifeq ($(HOST_OS),Windows)
WINDOWS_BUILD := 1
endif
@ -133,6 +137,7 @@ VERSION_ASFLAGS := --defsym $(VERSION_DEF)=1
# Stuff for showing the git hash in the title bar
GIT_HASH := $(shell git rev-parse --short HEAD)
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
VERSION_CFLAGS += -DGIT_HASH="\"$(GIT_HASH)\""
ifeq ($(shell git rev-parse --abbrev-ref HEAD),nightly)
@ -152,6 +157,9 @@ ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints
VERSION_CFLAGS += -DUSE_GLES
endif
ifeq ($(TARGET_SWITCH),1)
VERSION_CFLAGS += -DUSE_GLES -DTARGET_SWITCH
endif
ifeq ($(OSX_BUILD),1) # Modify GFX & SDL2 for OSX GL
VERSION_CFLAGS += -DOSX_BUILD
endif
@ -214,6 +222,8 @@ BUILD_DIR_BASE := build
ifeq ($(TARGET_WEB),1)
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_web
else ifeq ($(TARGET_SWITCH),1)
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_nx
else
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_pc
endif
@ -246,9 +256,12 @@ LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h)))
# Directories containing source files
# Hi, I'm a PC
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/text src/text/libs src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/text src/text/libs src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/nx
ifeq ($(DISCORDRPC),1)
ifneq ($(TARGET_SWITCH)$(TARGET_WEB)$(TARGET_RPI),000)
$(error Discord RPC does not work on this target)
endif
SRC_DIRS += src/pc/discord
endif
@ -381,6 +394,30 @@ ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
# Huge deleted N64 section was here
ifeq ($(TARGET_SWITCH),1)
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
export PATH := $(DEVKITPRO)/devkitA64/bin:$(PATH)
PORTLIBS ?= $(DEVKITPRO)/portlibs/switch
LIBNX ?= $(DEVKITPRO)/libnx
CROSS ?= aarch64-none-elf-
SDLCROSS :=
CC := $(CROSS)gcc
CXX := $(CROSS)g++
STRIP := $(CROSS)strip
NXARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
APP_TITLE := Render96ex
APP_AUTHOR := Nintendo, n64decomp team, Render96 team
APP_VERSION := $(GIT_BRANCH) - $(GIT_HASH)
APP_ICON := $(CURDIR)/textures/logo/r96-logo.jpg
INCLUDE_CFLAGS += -isystem$(LIBNX)/include -I$(PORTLIBS)/include
OPT_FLAGS := -O2
endif
# for some reason sdl-config in dka64 is not prefixed, while pkg-config is
SDLCROSS ?= $(CROSS)
AS := $(CROSS)as
ifeq ($(OSX_BUILD),1)
@ -423,7 +460,7 @@ else # Linux & other builds
endif
PYTHON := python3
SDLCONFIG := $(CROSS)sdl2-config
SDLCONFIG := $(SDLCROSS)sdl2-config
# configure backend flags
@ -444,7 +481,7 @@ ifeq ($(WINDOW_API),DXGI)
else ifeq ($(WINDOW_API),SDL2)
ifeq ($(WINDOWS_BUILD),1)
BACKEND_LDFLAGS += -lglew32 -lglu32 -lopengl32
else ifeq ($(TARGET_RPI),1)
else ifneq ($(TARGET_RPI)$(TARGET_SWITCH),00)
BACKEND_LDFLAGS += -lGLESv2
else ifeq ($(OSX_BUILD),1)
BACKEND_LDFLAGS += -framework OpenGL $(shell pkg-config --libs glew)
@ -480,6 +517,10 @@ else ifeq ($(TARGET_WEB),1)
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(BACKEND_CFLAGS) $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -s USE_SDL=2
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(BACKEND_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv -s USE_SDL=2
else ifeq ($(TARGET_SWITCH),1)
CC_CHECK := $(CC) $(NXARCH) -fsyntax-only -fsigned-char $(BACKEND_CFLAGS) $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -D__SWITCH__=1
CFLAGS := $(NXARCH) $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(BACKEND_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -ftls-model=local-exec -fPIC -fwrapv -D__SWITCH__=1
# Linux / Other builds below
else
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(BACKEND_CFLAGS) $(PLATFORM_CFLAGS) $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS)
@ -564,6 +605,9 @@ else ifeq ($(TARGET_RPI),1)
else ifeq ($(OSX_BUILD),1)
LDFLAGS := -lm $(PLATFORM_LDFLAGS) $(BACKEND_LDFLAGS) -lpthread
else ifeq ($(TARGET_SWITCH),1)
LDFLAGS := -specs=$(LIBNX)/switch.specs $(NXARCH) $(OPT_FLAGS) -no-pie -L$(LIBNX)/lib $(BACKEND_LDFLAGS) -lstdc++ -lnx -lm
else
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm $(BACKEND_LDFLAGS) -no-pie -lpthread
ifeq ($(DISCORDRPC),1)
@ -590,6 +634,9 @@ ZEROTERM = $(PYTHON) $(TOOLS_DIR)/zeroterm.py
#################################### Targets ###################################
all: $(EXE)
ifeq ($(TARGET_SWITCH),1)
all: $(EXE).nro
endif
BASEPACK_PATH := $(BUILD_DIR)/$(BASEDIR)/
BASEPACK_LST := $(BUILD_DIR)/basepack.lst
@ -746,6 +793,24 @@ $(BUILD_DIR)/%.o: %.s
$(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(BUILD_DIR)/$(RPC_LIBS)
$(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS)
ifeq ($(TARGET_SWITCH), 1)
# add `--icon=$(APP_ICON)` to this when we get a suitable icon
%.nro: %.stripped %.nacp
@elf2nro $< $@ --nacp=$*.nacp --icon=$(APP_ICON)
@echo built ... $(notdir $@)
@echo $(APP_ICON)
%.nacp:
@nacptool --create "$(APP_TITLE)" "$(APP_AUTHOR)" "$(APP_VERSION)" $@ $(NACPFLAGS)
@echo built ... $(notdir $@)
%.stripped: %
@$(STRIP) -o $@ $<
@echo stripped ... $(notdir $<)
endif
.PHONY: all clean distclean default diff libultra res
.PRECIOUS: $(BUILD_DIR)/bin/%.elf $(SOUND_BIN_DIR)/%.ctl $(SOUND_BIN_DIR)/%.tbl $(SOUND_SAMPLE_TABLES) $(SOUND_BIN_DIR)/%.s $(BUILD_DIR)/%
.DELETE_ON_ERROR:

View File

@ -16,6 +16,12 @@
#include "print.h"
#include "pc/configfile.h"
#ifdef TARGET_SWITCH
#define AVOID_UTYPES
#include "nx/m_nx.h"
#include "nx/m_controller.h"
#endif
/* @file hud.c
* This file implements HUD rendering and power meter animations.
* That includes stars, lives, coins, camera status, power meter, timer
@ -59,6 +65,15 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE };
void render_hud_rectangle(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);
}
/**
* Renders a rgba16 16x16 glyph texture from a table list.
*/
@ -88,6 +103,20 @@ void render_hud_small_tex_lut(s32 x, s32 y, u8 *texture) {
0, 0, 4 << 10, 1 << 10);
}
void render_hud_texture(s32 x, s32 y, u32 w, u32 h, u8 *texture) {
gSPDisplayList(gDisplayListHead++, dl_hud_img_begin);
gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0, 0, G_TX_LOADTILE, 0, G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD);
gDPTileSync(gDisplayListHead++);
gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_32b, 2, 0, G_TX_RENDERTILE, 0, G_TX_NOMIRROR, 3, G_TX_NOLOD, G_TX_NOMIRROR, 3, G_TX_NOLOD);
gDPSetTileSize(gDisplayListHead++, G_TX_RENDERTILE, 0, 0, w << G_TEXTURE_IMAGE_FRAC, h << G_TEXTURE_IMAGE_FRAC);
gDPPipeSync(gDisplayListHead++);
gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_32b, 1, texture);
gDPLoadSync(gDisplayListHead++);
gDPLoadBlock(gDisplayListHead++, G_TX_LOADTILE, 0, 0, w * h - 1, CALC_DXT(w, G_IM_SIZ_32b_BYTES));
gSPTextureRectangle(gDisplayListHead++, x << 2, y << 2, (x + w) << 2, (y + h) << 2, G_TX_RENDERTILE, 0, 0, 4 << 10, 1 << 10);
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
/**
* Renders power meter health segment texture using a table list.
*/
@ -416,6 +445,32 @@ void render_hud_camera_status(void) {
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
#ifdef TARGET_SWITCH
void render_nx_hud(void){
s16 x = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(40);
s16 y = 212;
s16 w = x + 14;
s16 h = y + 6;
render_hud_rectangle(x - 1, y - 1, w + 1, h + 1, 57, 57, 57);
render_hud_rectangle(w, y + 1, w + 2, y + 6, 57, 57, 57);
render_hud_rectangle(x, y, w, h, 194, 194, 194);
render_hud_rectangle(x, y, x + (s16)(14 * getBatteryPercentage()), h, 76, 235, 52);
x = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(20);
y = 207;
struct NXController controller;
get_controller_nx(&controller);
gSPDisplayList(gDisplayListHead++, dl_hud_img_begin);
render_hud_tex_lut(x, y, controller.icon);
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
#endif
/**
* Render HUD strings using hudDisplayFlags with it's render functions,
* excluding the cannon reticle which detects a camera preset for it.
@ -465,10 +520,6 @@ void render_hud(void) {
render_hud_stars();
}
if (hudDisplayFlags & HUD_DISPLAY_FLAG_KEYS && configHUD) {
render_hud_keys();
}
if (hudDisplayFlags & HUD_DISPLAY_FLAG_CAMERA_AND_POWER && configHUD) {
render_hud_power_meter();
render_hud_camera_status();
@ -477,5 +528,14 @@ void render_hud(void) {
if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER && configHUD) {
render_hud_timer();
}
if( configHUD ) {
#ifdef TARGET_SWITCH
if ( configSwitchHud )
render_nx_hud();
#endif
}
}
}

View File

@ -24,5 +24,6 @@ enum CameraHUDLut {
// Functions
void set_hud_camera_status(s16 status);
void render_hud(void);
void render_hud_rectangle(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b);
#endif // HUD_H

View File

@ -8,6 +8,7 @@
#include "game/print.h"
#include "game/segment2.h"
#include "game/save_file.h"
#include "game/hud.h"
#ifdef BETTERCAMERA
#include "game/bettercamera.h"
#endif
@ -73,11 +74,10 @@ static const u8 optsCameraStr[][32] = {
"TEXT_OPT_CAMON"
};
// TODO: Get dynamic languages
// This is only for testing
static const u8 optsGameStr[][32] = {
"TEXT_OPT_LANGUAGE"
"TEXT_OPT_LANGUAGE",
"TEXT_OPT_PRECACHE",
"TEXT_OPT_SWITCH_HUD"
};
static const u8 optsVideoStr[][32] = {
@ -262,16 +262,24 @@ static struct Option optsControls[] = {
};
static struct Option optsVideo[] = {
#ifndef TARGET_SWITCH
DEF_OPT_TOGGLE( optsVideoStr[0], &configWindow.fullscreen ),
DEF_OPT_TOGGLE( optsVideoStr[5], &configWindow.vsync ),
#endif
DEF_OPT_CHOICE( optsVideoStr[1], &configFiltering, filterChoices ),
DEF_OPT_TOGGLE( optsVideoStr[7], &configHUD ),
#ifndef TARGET_SWITCH
DEF_OPT_BUTTON( optsVideoStr[4], optvideo_reset_window ),
DEF_OPT_BUTTON( optsVideoStr[9], optvideo_apply ),
#endif
};
static struct Option optsGame[] = {
DEF_OPT_CHOICE( optsGameStr[0], &configLanguage, NULL ),
DEF_OPT_CHOICE( optsGameStr[0], &configLanguage, NULL ),
DEF_OPT_TOGGLE( optsGameStr[1], &configPrecacheRes ),
#ifdef TARGET_SWITCH
DEF_OPT_TOGGLE( optsGameStr[2], &configSwitchHud ),
#endif
};
static struct Option optsAudio[] = {
@ -378,6 +386,11 @@ static void optmenu_draw_opt(const struct Option *opt, s16 x, s16 y, u8 sel) {
optmenu_draw_text(x, y, get_key_string(opt->label), sel);
s16 sx = 0;
s16 sy = 0;
s16 sw = 0;
s16 sh = 0;
switch (opt->type) {
case OPT_TOGGLE:
optmenu_draw_text(x, y-13, get_key_string(toggleStr[(int)*opt->bval]), sel);
@ -395,8 +408,13 @@ static void optmenu_draw_opt(const struct Option *opt, s16 x, s16 y, u8 sel) {
break;
case OPT_SCROLL:
int_to_str(*opt->uval, buf);
optmenu_draw_text(x, y-13, buf, sel);
sx = x - 127 / 2;
sy = 209 - (y - 35);
sw = sx + (127.0 * (((*opt->uval * 1.0) + __FLT_MIN__) / (opt->scrMax * 1.0)));
sh = sy + 7;
render_hud_rectangle(sx - 1, sy - 1, (sx + 126), sh + 1, 180, 180, 180);
render_hud_rectangle(sx, sy, sw - 2, sh, 255, 255, 255);
break;
case OPT_BIND:
@ -500,10 +518,10 @@ 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)), get_key_string(menuStr[0]));
print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90 + (32 * (currentMenu->select - currentMenu->scroll)), get_key_string(menuStr[0]));
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
// gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
// print_hud_lut_string(HUD_LUT_GLOBAL, 80, 90 + (32 * (currentMenu->select - currentMenu->scroll)), get_key_string(menuStr[0]));
// print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90 + (32 * (currentMenu->select - currentMenu->scroll)), get_key_string(menuStr[0]));
// gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
}
//This has been separated for interesting reasons. Don't question it.

82
src/nx/m_controller.c Normal file
View File

@ -0,0 +1,82 @@
#ifdef TARGET_SWITCH
#include "m_controller.h"
#include <switch.h>
PadState pad;
u32 target_device = -1;
HidVibrationValue VibrationValue;
HidVibrationValue VibrationValue_stop;
HidVibrationValue VibrationValues[2];
HidVibrationDeviceHandle VibrationDeviceHandles[2][2];
u32 last = 0;
u32 vlength = 0;
void controller_nx_init(){
padInitializeDefault(&pad);
hidInitializeVibrationDevices(VibrationDeviceHandles[0], 2, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
hidInitializeVibrationDevices(VibrationDeviceHandles[1], 2, HidNpadIdType_No1, HidNpadStyleTag_NpadJoyDual);
}
void get_controller_nx(struct NXController* controller){
u32 tagStyle = padGetStyleSet(&pad);
if (tagStyle & HidNpadStyleTag_NpadFullKey) {
controller->name = "Pro Controller";
controller->type = PRO_CONTROLLER;
controller->icon = "textures/icons/pro_controller";
}
else if (tagStyle & HidNpadStyleTag_NpadHandheld) {
controller->name = "Nintendo Switch";
controller->type = HANDHELD;
controller->icon = "textures/icons/joycons";
} else {
controller->name = "Dual Joy-Con";
controller->type = DUAL_JOYCON;
controller->icon = "textures/icons/joycons";
}
}
void controller_nx_rumble_play(f32 strength, f32 length) {
memset(VibrationValues, 0, sizeof(VibrationValues));
VibrationValue.freq_low = 160.0f;
VibrationValue.freq_high = 320.0f;
VibrationValue.amp_low = strength;
VibrationValue.amp_high = strength;
memcpy(&VibrationValues[0], &VibrationValue, sizeof(HidVibrationValue));
memcpy(&VibrationValues[1], &VibrationValue, sizeof(HidVibrationValue));
last = 0;
vlength = (length / 1000);
}
void controller_nx_rumble_stop(void) {
memset(&VibrationValue_stop, 0, sizeof(HidVibrationValue));
VibrationValue_stop.freq_low = 160.0f;
VibrationValue_stop.freq_high = 320.0f;
memcpy(&VibrationValues[0], &VibrationValue_stop, sizeof(HidVibrationValue));
memcpy(&VibrationValues[1], &VibrationValue_stop, sizeof(HidVibrationValue));
hidSendVibrationValues(VibrationDeviceHandles[target_device], VibrationValues, 2);
hidSendVibrationValues(VibrationDeviceHandles[1-target_device], VibrationValues, 2);
vlength = -1;
}
void controller_nx_rumble_loop(void){
padUpdate(&pad);
target_device = padIsHandheld(&pad) ? 0 : 1;
if(vlength != -1 && last <= vlength){
hidSendVibrationValues(VibrationDeviceHandles[target_device], VibrationValues, 2);
last++;
} else vlength = -1;
}
#endif

32
src/nx/m_controller.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef VIBRATION_MODULE
#define VIBRATION_MODULE
#ifndef AVOID_UTYPES
typedef float f32;
typedef double f64;
typedef char bool;
#endif
enum ControllerType {
PRO_CONTROLLER,
DUAL_JOYCON,
HANDHELD,
};
struct NXController {
char* name;
char* icon;
enum ControllerType type;
};
// Controller
void controller_nx_init();
void get_controller_nx(struct NXController* controller);
// Rumble
void controller_nx_rumble_play(f32 strength, f32 length);
void controller_nx_rumble_stop(void);
void controller_nx_rumble_loop(void);
#endif

28
src/nx/m_nx.c Normal file
View File

@ -0,0 +1,28 @@
#ifdef TARGET_SWITCH
#include <switch.h>
#include "m_nx.h"
void initNX(){
appletInitializeGamePlayRecording();
socketInitializeDefault();
nxlinkStdio();
appletSetGamePlayRecordingState(1);
Result rc = psmInitialize();
if (R_FAILED(rc)) psmExit();
}
void exitNX(){
socketExit();
appletSetGamePlayRecordingState(0);
}
float getBatteryPercentage(){
u32 charge;
psmGetBatteryChargePercentage(&charge);
return (charge / 100.0f);
}
#endif

8
src/nx/m_nx.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef NX_MODULE
#define NX_MODULE
void initNX();
void exitNX();
float getBatteryPercentage();
#endif

View File

@ -51,6 +51,12 @@ ConfigWindow configWindow = {
};
unsigned int configLanguage = 0;
#ifdef TARGET_SWITCH
bool configSwitchHud = true;
bool configPrecacheRes = false;
#else
bool configPrecacheRes = true;
#endif
unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point
unsigned int configMasterVolume = MAX_VOLUME; // 0 - MAX_VOLUME
@ -75,7 +81,6 @@ unsigned int configKeyStickLeft[MAX_BINDS] = { 0x001E, VK_INVALID, VK_INVALID
unsigned int configKeyStickRight[MAX_BINDS] = { 0x0020, VK_INVALID, VK_INVALID };
unsigned int configStickDeadzone = 16; // 16*DEADZONE_STEP=4960 (the original default deadzone)
unsigned int configRumbleStrength = 50;
bool configPrecacheRes = true;
#ifdef BETTERCAMERA
// BetterCamera settings
unsigned int configCameraXSens = 50;
@ -125,6 +130,9 @@ static const struct ConfigOption options[] = {
{.name = "rumble_strength", .type = CONFIG_TYPE_UINT, .uintValue = &configRumbleStrength},
{.name = "precache", .type = CONFIG_TYPE_BOOL, .boolValue = &configPrecacheRes},
{.name = "language", .type = CONFIG_TYPE_UINT, .boolValue = &configLanguage},
#ifdef TARGET_SWITCH
{.name = "nx_hud", .type = CONFIG_TYPE_BOOL, .boolValue = &configSwitchHud},
#endif
#ifdef BETTERCAMERA
{.name = "bettercam_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configEnableCamera},
{.name = "bettercam_analog", .type = CONFIG_TYPE_BOOL, .boolValue = &configCameraAnalog},

View File

@ -19,6 +19,9 @@ typedef struct {
extern ConfigWindow configWindow;
extern unsigned int configLanguage;
#ifdef TARGET_SWITCH
extern bool configSwitchHud;
#endif
extern unsigned int configFiltering;
extern unsigned int configMasterVolume;
extern unsigned int configMusicVolume;

View File

@ -18,6 +18,9 @@
#include "../platform.h"
#include "../fs/fs.h"
#define AVOID_UTYPES
#include "nx/m_controller.h"
#include "game/level_update.h"
// mouse buttons are also in the controller namespace (why), just offset 0x100
@ -96,6 +99,7 @@ static void controller_sdl_init(void) {
haptics_enabled = (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0);
#ifndef TARGET_SWITCH
// try loading an external gamecontroller mapping file
uint64_t gcsize = 0;
void *gcdata = fs_load_file("db/gamecontrollerdb.txt", &gcsize);
@ -108,7 +112,8 @@ static void controller_sdl_init(void) {
}
free(gcdata);
}
#endif
#ifdef BETTERCAMERA
if (newcam_mouse == 1)
SDL_SetRelativeMouseMode(SDL_TRUE);
@ -118,11 +123,17 @@ static void controller_sdl_init(void) {
controller_sdl_bind();
init_ok = true;
#ifdef TARGET_SWITCH
haptics_enabled = true;
#endif
}
static SDL_Haptic *controller_sdl_init_haptics(const int joy) {
if (!haptics_enabled) return NULL;
#ifndef TARGET_SWITCH
SDL_Haptic *hap = SDL_HapticOpen(joy);
if (!hap) return NULL;
@ -138,6 +149,11 @@ static SDL_Haptic *controller_sdl_init_haptics(const int joy) {
printf("controller %s has haptics support, rumble enabled\n", SDL_JoystickNameForIndex(joy));
return hap;
#else
controller_nx_init();
printf("switch controller has haptics support, rumble enabled\n");
return NULL;
#endif
}
static inline void update_button(const int i, const bool new) {
@ -176,7 +192,7 @@ static void controller_sdl_read(OSContPad *pad) {
sdl_cntrl = NULL;
sdl_haptic = NULL;
}
if (sdl_cntrl == NULL) {
for (int i = 0; i < SDL_NumJoysticks(); i++) {
if (SDL_IsGameController(i)) {
@ -263,13 +279,21 @@ static void controller_sdl_read(OSContPad *pad) {
}
static void controller_sdl_rumble_play(f32 strength, f32 length) {
#ifndef TARGET_SWITCH
if (sdl_haptic)
SDL_HapticRumblePlay(sdl_haptic, strength, (u32)(length * 1000.0f));
#else
controller_nx_rumble_play(strength, length);
#endif
}
static void controller_sdl_rumble_stop(void) {
#ifndef TARGET_SWITCH
if (sdl_haptic)
SDL_HapticRumbleStop(sdl_haptic);
#else
controller_nx_rumble_stop();
#endif
}
static u32 controller_sdl_rawkey(void) {

View File

@ -35,6 +35,12 @@
#include "src/pc/controller/controller_keyboard.h"
#ifdef TARGET_SWITCH
// can't include <switch.h> or even <switch/services/applet.h> because
// the basic libnx types have the same names as some of the types in this
extern int appletGetOperationMode(void);
#endif
// TODO: figure out if this shit even works
#ifdef VERSION_EU
# define FRAMERATE 25
@ -139,6 +145,10 @@ int test_vsync(void) {
}
static inline void gfx_sdl_set_vsync(const bool enabled) {
#ifdef TARGET_SWITCH
SDL_GL_SetSwapInterval(2);
use_timer = false;
#else
if (enabled) {
// try to detect refresh rate
SDL_GL_SetSwapInterval(1);
@ -155,6 +165,7 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
use_timer = true;
SDL_GL_SetSwapInterval(0);
#endif
}
static void gfx_sdl_set_fullscreen(void) {
@ -210,8 +221,21 @@ static void gfx_sdl_init(const char *window_title) {
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
#ifdef TARGET_SWITCH
configWindow.fullscreen = false;
if (appletGetOperationMode() == 1) {
configWindow.w = 1920;
configWindow.h = 1080;
} else {
configWindow.w = 1280;
configWindow.h = 720;
}
int xpos = 0;
int ypos = 0;
#else
int xpos = (configWindow.x == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.x;
int ypos = (configWindow.y == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.y;
#endif
wnd = SDL_CreateWindow(
window_title,

View File

@ -39,6 +39,10 @@
#include "pc/discord/discordrpc.h"
#endif
#ifdef TARGET_SWITCH
#include "nx/m_nx.h"
#endif
#include "text/text-loader.h"
OSMesg D_80339BEC;
@ -95,6 +99,9 @@ void produce_one_frame(void) {
game_loop_one_iteration();
thread6_rumble_loop(NULL);
#ifdef TARGET_SWITCH
controller_nx_rumble_loop();
#endif
int samples_left = audio_api->buffered();
u32 num_audio_samples = samples_left < audio_api->get_desired_buffered() ? SAMPLES_HIGH : SAMPLES_LOW;
@ -266,7 +273,13 @@ void main_func(char *argv[]) {
}
int main(int argc, char *argv[]) {
#ifdef TARGET_SWITCH
initNX();
#endif
parse_cli_opts(argc, argv);
main_func(argv);
#ifdef TARGET_SWITCH
exitNX();
#endif
return 0;
}

View File

@ -14,7 +14,7 @@
const char *sys_ropaths[] = {
".", // working directory
"!", // executable directory
#if defined(__linux__) || defined(__unix__)
#if (defined(__linux__) || defined(__unix__)) && !defined(TARGET_SWITCH)
// some common UNIX directories for read only stuff
"/usr/local/share/sm64pc",
"/usr/share/sm64pc",

View File

@ -3345,7 +3345,9 @@
"TEXT_OPT_CHEAT8": "Huge Mario",
"TEXT_OPT_CHEAT9": "Tiny Mario",
"TEXT_OPT_GAME": "GAME",
"TEXT_OPT_LANGUAGE": "Current Language"
"TEXT_OPT_LANGUAGE": "Current Language",
"TEXT_OPT_PRECACHE": "Precache Textures",
"TEXT_OPT_SWITCH_HUD": "Switch HUD"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3530,7 +3530,9 @@
"TEXT_OPT_CHEAT8": "Mario gigante",
"TEXT_OPT_CHEAT9": "Mario enano",
"TEXT_OPT_GAME": "JUEGO",
"TEXT_OPT_LANGUAGE": "Idioma actual"
"TEXT_OPT_LANGUAGE": "Idioma actual",
"TEXT_OPT_PRECACHE": "Precargar texturas",
"TEXT_OPT_SWITCH_HUD": "Interfaz de la switch"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3397,7 +3397,9 @@
"TEXT_OPT_CHEAT8": "Mario Gigante",
"TEXT_OPT_CHEAT9": "Mario Pequeño",
"TEXT_OPT_GAME": "JUEGO",
"TEXT_OPT_LANGUAGE": "Idioma actual"
"TEXT_OPT_LANGUAGE": "Idioma actual",
"TEXT_OPT_PRECACHE": "Precargar texturas",
"TEXT_OPT_SWITCH_HUD": "Interfaz de la switch"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3345,7 +3345,9 @@
"TEXT_OPT_CHEAT8": "Huge Mario",
"TEXT_OPT_CHEAT9": "Tiny Mario",
"TEXT_OPT_GAME": "JOGO",
"TEXT_OPT_LANGUAGE": "Idioma Atual"
"TEXT_OPT_LANGUAGE": "Idioma Atual",
"TEXT_OPT_PRECACHE": "Texturas pré-carregadas",
"TEXT_OPT_SWITCH_HUD": "Interface de switch"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3345,7 +3345,9 @@
"TEXT_OPT_CHEAT8": "Huge Mario",
"TEXT_OPT_CHEAT9": "Tiny Mario",
"TEXT_OPT_GAME": "GAME",
"TEXT_OPT_LANGUAGE": "Current Language"
"TEXT_OPT_LANGUAGE": "Current Language",
"TEXT_OPT_PRECACHE": "Precache Textures",
"TEXT_OPT_SWITCH_HUD": "Switch HUD"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3530,7 +3530,9 @@
"TEXT_OPT_CHEAT8": "Mario gigante",
"TEXT_OPT_CHEAT9": "Mario enano",
"TEXT_OPT_GAME": "JUEGO",
"TEXT_OPT_LANGUAGE": "Idioma actual"
"TEXT_OPT_LANGUAGE": "Idioma actual",
"TEXT_OPT_PRECACHE": "Precargar texturas",
"TEXT_OPT_SWITCH_HUD": "Interfaz de la switch"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3397,7 +3397,9 @@
"TEXT_OPT_CHEAT8": "Mario Gigante",
"TEXT_OPT_CHEAT9": "Mario Peque{00241}o",
"TEXT_OPT_GAME": "JUEGO",
"TEXT_OPT_LANGUAGE": "Idioma actual"
"TEXT_OPT_LANGUAGE": "Idioma actual",
"TEXT_OPT_PRECACHE": "Precargar texturas",
"TEXT_OPT_SWITCH_HUD": "Interfaz de la switch"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3388,7 +3388,9 @@
"TEXT_OPT_CHEAT8": "Huge Mario",
"TEXT_OPT_CHEAT9": "Tiny Mario",
"TEXT_OPT_GAME": "GRA",
"TEXT_OPT_LANGUAGE": "Jezyk"
"TEXT_OPT_LANGUAGE": "Jezyk",
"TEXT_OPT_PRECACHE": "Precache Textures",
"TEXT_OPT_SWITCH_HUD": "Switch HUD"
},
"strings": {
"TEXT_ZERO": "0",

View File

@ -3345,7 +3345,9 @@
"TEXT_OPT_CHEAT8": "Huge Mario",
"TEXT_OPT_CHEAT9": "Tiny Mario",
"TEXT_OPT_GAME": "JOGO",
"TEXT_OPT_LANGUAGE": "Idioma Atual"
"TEXT_OPT_LANGUAGE": "Idioma Atual",
"TEXT_OPT_PRECACHE": "Texturas pr{00233}-carregadas",
"TEXT_OPT_SWITCH_HUD": "Interface de switch"
},
"strings": {
"TEXT_ZERO": "0",

BIN
textures/logo/r96-logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB