mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-23 15:52:41 +02:00
Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-debugger
This commit is contained in:
commit
9633e7eac6
22 files changed
+1109
-70
No files matched your search
@@ -282,7 +282,7 @@ jobs:
|
||||
bundle: io.github.fgsfdsfgs.perfect_dark.flatpak
|
||||
manifest-path: dist/linux/io.github.fgsfdsfgs.perfect_dark.yaml
|
||||
cache-key: flatpak-builder-${{ github.sha }}
|
||||
upload-artifact: true
|
||||
upload-artifact: false
|
||||
|
||||
# - name: Build Flatpak bundle
|
||||
# run: |
|
||||
|
||||
@@ -31,7 +31,7 @@ There are minor graphics- and gameplay-related issues, and possibly occasional c
|
||||
* basic mod support, currently enough to load a few custom levels;
|
||||
* slightly expanded memory heap size;
|
||||
* experimental high framerate support (up to 240 FPS):
|
||||
* set `Game.TickRateDivisor` to `0` in `pd.ini` to activate;
|
||||
* enable `Uncap Tickrate` in `Extended Video Options` to activate;
|
||||
* in practice the game will have issues running faster than ~165 FPS, so use VSync or `Video.FramerateLimit` to cap it.
|
||||
* emulate the Transfer Pak functionality the game has on the Nintendo 64 to unlock some cheats automatically.
|
||||
|
||||
|
||||
+118
-7
@@ -30,10 +30,30 @@ static uint64_t qpc_freq;
|
||||
#define FRAME_INTERVAL_US_NUMERATOR 1000000
|
||||
#define FRAME_INTERVAL_US_DENOMINATOR (target_fps)
|
||||
|
||||
static void set_fullscreen(bool on, bool call_callback) {
|
||||
if (fullscreen_state == on) {
|
||||
return;
|
||||
static int32_t gfx_sdl_get_maximized_state(void) {
|
||||
return (int32_t)maximized_state;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_fullscreen_state(void) {
|
||||
return (int32_t)fullscreen_state;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_fullscreen_flag_mode(void) {
|
||||
return fullscreen_flag == SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : 1;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_fullscreen_flag(int32_t mode) {
|
||||
switch (mode) {
|
||||
case 0: {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
} break;
|
||||
case 1: {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_fullscreen(bool on, bool call_callback) {
|
||||
fullscreen_state = on;
|
||||
SDL_SetWindowFullscreen(wnd, on ? fullscreen_flag : 0);
|
||||
if (call_callback && on_fullscreen_changed_callback) {
|
||||
@@ -42,9 +62,6 @@ static void set_fullscreen(bool on, bool call_callback) {
|
||||
}
|
||||
|
||||
static void set_maximize_window(bool on) {
|
||||
if (maximized_state == on) {
|
||||
return;
|
||||
}
|
||||
maximized_state = on;
|
||||
if (on) {
|
||||
SDL_MaximizeWindow(wnd);
|
||||
@@ -95,6 +112,13 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
||||
posY = 100;
|
||||
}
|
||||
|
||||
if (set->centered) {
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetCurrentDisplayMode(0, &mode);
|
||||
posX = mode.w / 2 - window_width / 2;
|
||||
posY = mode.h / 2 - window_height / 2;
|
||||
}
|
||||
|
||||
if (set->fullscreen_is_exclusive) {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
@@ -222,6 +246,43 @@ static void gfx_sdl_set_cursor_visibility(bool visible) {
|
||||
}
|
||||
}
|
||||
|
||||
static void get_centered_positions_native(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetDesktopDisplayMode(disp_idx, &mode);
|
||||
*posX = mode.w / 2 - width / 2;
|
||||
*posY = mode.h / 2 - height / 2;
|
||||
}
|
||||
|
||||
static void gfx_sdl_get_centered_positions(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetCurrentDisplayMode(disp_idx, &mode);
|
||||
*posX = mode.w / 2 - width / 2;
|
||||
*posY = mode.h / 2 - height / 2;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_closest_resolution(int32_t width, int32_t height, bool should_center) {
|
||||
const SDL_DisplayMode mode = {.w = width, .h = height};
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode closest = {};
|
||||
if (SDL_GetClosestDisplayMode(disp_idx, &mode, &closest)) {
|
||||
SDL_SetWindowDisplayMode(wnd, &closest);
|
||||
SDL_SetWindowSize(wnd, closest.w, closest.h);
|
||||
if (should_center) {
|
||||
int32_t posX = 0;
|
||||
int32_t posY = 0;
|
||||
get_centered_positions_native(closest.w, closest.h, &posX, &posY);
|
||||
SDL_SetWindowPosition(wnd, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_dimensions(uint32_t width, uint32_t height, int32_t posX, int32_t posY) {
|
||||
SDL_SetWindowSize(wnd, width, height);
|
||||
SDL_SetWindowPosition(wnd, posX, posY);
|
||||
}
|
||||
|
||||
static void gfx_sdl_get_dimensions(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY) {
|
||||
SDL_GL_GetDrawableSize(wnd, static_cast<int*>((void*)width), static_cast<int*>((void*)height));
|
||||
SDL_GetWindowPosition(wnd, static_cast<int*>(posX), static_cast<int*>(posY));
|
||||
@@ -240,6 +301,9 @@ static void gfx_sdl_handle_events(void) {
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
|
||||
if (!fullscreen_state) {
|
||||
maximized_state = SDL_GetWindowFlags(wnd) & SDL_WINDOW_MAXIMIZED ? true : false;
|
||||
}
|
||||
} else if (event.window.event == SDL_WINDOWEVENT_CLOSE &&
|
||||
event.window.windowID == SDL_GetWindowID(wnd)) {
|
||||
// We listen specifically for main window close because closing main window
|
||||
@@ -304,6 +368,10 @@ static double gfx_sdl_get_time(void) {
|
||||
return SDL_GetPerformanceCounter() / (double)qpc_freq;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_target_fps(void) {
|
||||
return target_fps;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_target_fps(int fps) {
|
||||
target_fps = fps;
|
||||
}
|
||||
@@ -320,6 +388,10 @@ static void gfx_sdl_set_window_title(const char *title) {
|
||||
SDL_SetWindowTitle(wnd, title);
|
||||
}
|
||||
|
||||
static int gfx_sdl_get_swap_interval(void) {
|
||||
return SDL_GL_GetSwapInterval();
|
||||
}
|
||||
|
||||
static bool gfx_sdl_set_swap_interval(int interval) {
|
||||
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
|
||||
vsync_enabled = success && (interval != 0);
|
||||
@@ -329,24 +401,63 @@ static bool gfx_sdl_set_swap_interval(int interval) {
|
||||
return success;
|
||||
}
|
||||
|
||||
struct GfxWindowManagerAPI gfx_sdl = {
|
||||
int gfx_sdl_get_display_mode(int modenum, int *out_w, int *out_h) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode sdlmode;
|
||||
if (SDL_GetDisplayMode(display_in_use, modenum, &sdlmode) == 0) {
|
||||
*out_w = sdlmode.w;
|
||||
*out_h = sdlmode.h;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gfx_sdl_get_current_display_mode(int *out_w, int *out_h) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode sdlmode;
|
||||
if (SDL_GetCurrentDisplayMode(display_in_use, &sdlmode) == 0) {
|
||||
*out_w = sdlmode.w;
|
||||
*out_h = sdlmode.h;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gfx_sdl_get_num_display_modes(void) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
return SDL_GetNumDisplayModes(display_in_use);
|
||||
}
|
||||
|
||||
struct GfxWindowManagerAPI gfx_sdl = {
|
||||
gfx_sdl_init,
|
||||
gfx_sdl_close,
|
||||
gfx_sdl_get_display_mode,
|
||||
gfx_sdl_get_current_display_mode,
|
||||
gfx_sdl_get_num_display_modes,
|
||||
gfx_sdl_get_fullscreen_state,
|
||||
gfx_sdl_set_fullscreen_changed_callback,
|
||||
gfx_sdl_set_fullscreen,
|
||||
gfx_sdl_set_fullscreen_exclusive,
|
||||
gfx_sdl_set_fullscreen_flag,
|
||||
gfx_sdl_get_fullscreen_flag_mode,
|
||||
gfx_sdl_get_maximized_state,
|
||||
gfx_sdl_set_maximize_window,
|
||||
gfx_sdl_get_active_window_refresh_rate,
|
||||
gfx_sdl_set_cursor_visibility,
|
||||
gfx_sdl_set_closest_resolution,
|
||||
gfx_sdl_set_dimensions,
|
||||
gfx_sdl_get_dimensions,
|
||||
gfx_sdl_get_centered_positions,
|
||||
gfx_sdl_handle_events,
|
||||
gfx_sdl_start_frame,
|
||||
gfx_sdl_swap_buffers_begin,
|
||||
gfx_sdl_swap_buffers_end,
|
||||
gfx_sdl_get_time,
|
||||
gfx_sdl_get_target_fps,
|
||||
gfx_sdl_set_target_fps,
|
||||
gfx_sdl_can_disable_vsync,
|
||||
gfx_sdl_get_window_handle,
|
||||
gfx_sdl_set_window_title,
|
||||
gfx_sdl_get_swap_interval,
|
||||
gfx_sdl_set_swap_interval,
|
||||
};
|
||||
@@ -13,28 +13,41 @@ struct GfxWindowInitSettings {
|
||||
bool fullscreen;
|
||||
bool fullscreen_is_exclusive;
|
||||
bool maximized;
|
||||
bool centered;
|
||||
bool allow_hidpi;
|
||||
};
|
||||
|
||||
struct GfxWindowManagerAPI {
|
||||
void (*init)(const struct GfxWindowInitSettings *settings);
|
||||
void (*close)(void);
|
||||
int (*get_display_mode)(int modenum, int *out_w, int *out_h);
|
||||
int (*get_current_display_mode)(int *out_w, int *out_h);
|
||||
int (*get_num_display_modes)(void);
|
||||
int32_t (*get_fullscreen_state)(void);
|
||||
void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen));
|
||||
void (*set_fullscreen)(bool enable);
|
||||
void (*set_fullscreen_exclusive)(bool exc);
|
||||
void (*set_fullscreen_flag)(int32_t mode);
|
||||
int32_t (*get_fullscreen_flag_mode)(void);
|
||||
int32_t (*get_maximized_state)(void);
|
||||
void (*set_maximize)(bool enable);
|
||||
void (*get_active_window_refresh_rate)(uint32_t* refresh_rate);
|
||||
void (*set_cursor_visibility)(bool visible);
|
||||
void (*set_closest_resolution)(int32_t width, int32_t height, bool should_center);
|
||||
void (*set_dimensions)(uint32_t width, uint32_t height, int32_t posX, int32_t posY);
|
||||
void (*get_dimensions)(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY);
|
||||
void (*get_centered_positions)(int32_t width, int32_t height, int32_t *posX, int32_t *posY);
|
||||
void (*handle_events)(void);
|
||||
bool (*start_frame)(void);
|
||||
void (*swap_buffers_begin)(void);
|
||||
void (*swap_buffers_end)(void);
|
||||
double (*get_time)(void); // For debug
|
||||
int32_t (*get_target_fps)(void);
|
||||
void (*set_target_fps)(int fps);
|
||||
bool (*can_disable_vsync)(void);
|
||||
void *(*get_window_handle)(void);
|
||||
void (*set_window_title)(const char *);
|
||||
int (*get_swap_interval)(void);
|
||||
bool (*set_swap_interval)(int);
|
||||
};
|
||||
|
||||
|
||||
@@ -142,6 +142,10 @@ void inputControllerSetSticksSwapped(s32 cidx, s32 swapped);
|
||||
s32 inputControllerGetDualAnalog(s32 cidx);
|
||||
void inputControllerSetDualAnalog(s32 cidx, s32 enable);
|
||||
|
||||
// get/set Input.Player%d.CancelCButtons
|
||||
s32 inputControllerGetCancelCButtons(s32 cidx);
|
||||
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel);
|
||||
|
||||
// get/set sensitivity for a given player
|
||||
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis);
|
||||
void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value);
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
#define VIDEO_MAX_FPS 240
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
s32 width;
|
||||
s32 height;
|
||||
} displaymode;
|
||||
|
||||
s32 videoInit(void);
|
||||
void videoStartFrame(void);
|
||||
void videoSubmitCommands(Gfx *cmds);
|
||||
@@ -27,17 +32,36 @@ s32 videoGetWidth(void);
|
||||
s32 videoGetHeight(void);
|
||||
f32 videoGetAspect(void);
|
||||
s32 videoGetFullscreen(void);
|
||||
s32 videoGetFullscreenMode(void);
|
||||
s32 videoGetMaximizeWindow(void);
|
||||
void videoSetMaximizeWindow(s32 fs);
|
||||
s32 videoGetCenterWindow(void);
|
||||
void videoSetCenterWindow(s32 center);
|
||||
u32 videoGetTextureFilter(void);
|
||||
s32 videoGetTextureFilter2D(void);
|
||||
s32 videoGetDetailTextures(void);
|
||||
s32 videoGetDisplayModeIndex(void);
|
||||
s32 videoGetDisplayMode(displaymode *out, const s32 index);
|
||||
s32 videoGetNumDisplayModes(void);
|
||||
s32 videoGetVsync(void);
|
||||
s32 videoGetFramerateLimit(void);
|
||||
s32 videoGetDisplayFPS(void);
|
||||
s32 videoGetMSAA(void);
|
||||
|
||||
f32 videoGetAverageFPS(void);
|
||||
f64 videoGetLastRenderTime(void);
|
||||
|
||||
void videoSetWindowOffset(s32 x, s32 y);
|
||||
void videoSetFullscreen(s32 fs);
|
||||
void videoSetFullscreenMode(s32 mode);
|
||||
void videoSetTextureFilter(u32 filter);
|
||||
void videoSetTextureFilter2D(s32 filter);
|
||||
void videoSetDetailTextures(s32 detail);
|
||||
void videoSetDisplayMode(const s32 index);
|
||||
void videoSetVsync(const s32 vsync);
|
||||
void videoSetFramerateLimit(const s32 limit);
|
||||
void videoSetDisplayFPS(const s32 displayfps);
|
||||
void videoSetMSAA(const s32 msaa);
|
||||
|
||||
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
|
||||
void videoSetFramebuffer(s32 target);
|
||||
@@ -49,4 +73,6 @@ s32 videoFramebuffersSupported(void);
|
||||
void videoResetTextureCache(void);
|
||||
void videoFreeCachedTexture(const void *texptr);
|
||||
|
||||
void videoShutdown(void);
|
||||
|
||||
#endif
|
||||
+7
-2
@@ -10,7 +10,7 @@
|
||||
|
||||
#define CONFIG_MAX_SECNAME 128
|
||||
#define CONFIG_MAX_KEYNAME 256
|
||||
#define CONFIG_MAX_SETTINGS 256
|
||||
#define CONFIG_MAX_SETTINGS 300
|
||||
|
||||
typedef enum {
|
||||
CFG_NONE,
|
||||
@@ -34,6 +34,7 @@ struct configentry {
|
||||
} settings[CONFIG_MAX_SETTINGS];
|
||||
|
||||
static s32 numSettings = 0;
|
||||
static u8 configMaxWarningLogged = 0;
|
||||
|
||||
static inline s32 configClampInt(s32 val, s32 min, s32 max)
|
||||
{
|
||||
@@ -64,11 +65,15 @@ static inline struct configentry *configAddEntry(const char *key)
|
||||
{
|
||||
if (numSettings < CONFIG_MAX_SETTINGS) {
|
||||
struct configentry *cfg = &settings[numSettings++];
|
||||
strncpy(cfg->key, key, CONFIG_MAX_KEYNAME);
|
||||
snprintf(cfg->key, CONFIG_MAX_KEYNAME, "%s", key);
|
||||
const char *delim = strrchr(cfg->key, '.');
|
||||
cfg->seclen = delim ? (delim - cfg->key) : 0;
|
||||
return cfg;
|
||||
}
|
||||
if (!configMaxWarningLogged) {
|
||||
sysLogPrintf(LOG_WARNING, "Maximum number of configuration entries exceeded: %d", CONFIG_MAX_SETTINGS);
|
||||
configMaxWarningLogged = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+26
-3
@@ -45,7 +45,8 @@ static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
|
||||
.deadzone = { DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE_RY }, \
|
||||
.stickCButtons = 0, \
|
||||
.swapSticks = 1, \
|
||||
.deviceIndex = -1 \
|
||||
.deviceIndex = -1, \
|
||||
.cancelCButtons = 0, \
|
||||
}
|
||||
|
||||
static struct controllercfg {
|
||||
@@ -57,6 +58,7 @@ static struct controllercfg {
|
||||
s32 stickCButtons;
|
||||
s32 swapSticks;
|
||||
s32 deviceIndex;
|
||||
s32 cancelCButtons;
|
||||
} padsCfg[INPUT_MAX_CONTROLLERS] = {
|
||||
CONTROLLERCFG_DEFAULT,
|
||||
CONTROLLERCFG_DEFAULT,
|
||||
@@ -771,12 +773,22 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
||||
npad->stick_x = xdiff < 0 ? -0x80 : (xdiff > 0 ? 0x7F : 0);
|
||||
npad->stick_y = ydiff < 0 ? -0x80 : (ydiff > 0 ? 0x7F : 0);
|
||||
|
||||
const struct controllercfg *cfg = &padsCfg[idx];
|
||||
|
||||
if (cfg->cancelCButtons) {
|
||||
// opposite C buttons cancel each other out
|
||||
if ((npad->button & (L_CBUTTONS | R_CBUTTONS)) == (L_CBUTTONS | R_CBUTTONS)) {
|
||||
npad->button &= ~(L_CBUTTONS | R_CBUTTONS);
|
||||
}
|
||||
if ((npad->button & (U_CBUTTONS | D_CBUTTONS)) == (U_CBUTTONS | D_CBUTTONS)) {
|
||||
npad->button &= ~(U_CBUTTONS | D_CBUTTONS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pads[idx]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct controllercfg *cfg = &padsCfg[idx];
|
||||
|
||||
s32 leftX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][0]);
|
||||
s32 leftY = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][1]);
|
||||
s32 rightX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[1][0]);
|
||||
@@ -965,6 +977,16 @@ void inputControllerSetDualAnalog(s32 cidx, s32 enable)
|
||||
padsCfg[cidx].stickCButtons = !enable;
|
||||
}
|
||||
|
||||
s32 inputControllerGetCancelCButtons(s32 cidx)
|
||||
{
|
||||
return padsCfg[cidx].cancelCButtons;
|
||||
}
|
||||
|
||||
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel)
|
||||
{
|
||||
padsCfg[cidx].cancelCButtons = cancel;
|
||||
}
|
||||
|
||||
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis)
|
||||
{
|
||||
return padsCfg[cidx].sens[stick * 2 + axis];
|
||||
@@ -1490,6 +1512,7 @@ PD_CONSTRUCTOR static void inputConfigInit(void)
|
||||
configRegisterFloat(strFmt("%s.RStickScaleX", secname), &padsCfg[c].sens[2], -10.f, 10.f);
|
||||
configRegisterFloat(strFmt("%s.RStickScaleY", secname), &padsCfg[c].sens[3], -10.f, 10.f);
|
||||
configRegisterInt(strFmt("%s.StickCButtons", secname), &padsCfg[c].stickCButtons, 0, 1);
|
||||
configRegisterInt(strFmt("%s.CancelCButtons", secname), &padsCfg[c].cancelCButtons, 0, 1);
|
||||
configRegisterInt(strFmt("%s.SwapSticks", secname), &padsCfg[c].swapSticks, 0, 1);
|
||||
configRegisterInt(strFmt("%s.ControllerIndex", secname), &padsCfg[c].deviceIndex, -1, 0x7FFFFFFF);
|
||||
secname[13] = '.';
|
||||
|
||||
@@ -89,6 +89,7 @@ static void cleanup(void)
|
||||
sysLogPrintf(LOG_NOTE, "shutdown");
|
||||
inputSaveBinds();
|
||||
configSave(CONFIG_PATH);
|
||||
videoShutdown();
|
||||
crashShutdown();
|
||||
// TODO: actually shut down all subsystems
|
||||
}
|
||||
@@ -184,5 +185,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
|
||||
configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF);
|
||||
configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4);
|
||||
configRegisterInt(strFmt("Game.Player%d.CrosshairHealth", i), &g_PlayerExtCfg[j].crosshairhealth, 0, CROSSHAIR_HEALTH_ON_WHITE);
|
||||
configRegisterInt(strFmt("Game.Player%d.UseKeyReloads", i), &g_PlayerExtCfg[j].usereloads, 0, false);
|
||||
}
|
||||
}
|
||||
+284
-10
@@ -698,19 +698,164 @@ static MenuItemHandlerResult menuhandlerFullScreen(s32 operation, struct menuite
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerMaximizeWindow(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
static MenuItemHandlerResult menuhandlerFullScreenMode(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
"Borderless",
|
||||
"Exclusive"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
videoSetFullscreenMode(data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetFullscreenMode();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCenterWindow(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return videoGetMaximizeWindow();
|
||||
return videoGetCenterWindow();
|
||||
case MENUOP_SET:
|
||||
videoSetMaximizeWindow(data->checkbox.value);
|
||||
videoSetCenterWindow(data->checkbox.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerVsync(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const s32 numOpts = 10;
|
||||
static const char *constOpts[] = {
|
||||
"Adaptive",
|
||||
"Off",
|
||||
"On"
|
||||
};
|
||||
static char dynOpt[20];
|
||||
s32 vblanks;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = numOpts;
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
if (data->dropdown.value < ARRAYCOUNT(constOpts))
|
||||
return (intptr_t)constOpts[data->dropdown.value];
|
||||
vblanks = (s32)data->dropdown.value - 1;
|
||||
snprintf(dynOpt, sizeof(dynOpt), "On (%d frames)", vblanks);
|
||||
return (intptr_t)dynOpt;
|
||||
case MENUOP_SET:
|
||||
videoSetVsync(data->dropdown.value - 1);
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetVsync() + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerFramerateLimit(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetFramerateLimit();
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
videoSetFramerateLimit(data->slider.value);
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
// NOTE: data->slider.label length must not exceed 15.
|
||||
if (data->slider.value == 0) {
|
||||
strcpy(data->slider.label, "Off");
|
||||
} else {
|
||||
sprintf(data->slider.label, "%d FPS", data->slider.value);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerMSAA(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
s32 msaa;
|
||||
static const char *opts[] = {
|
||||
"Off",
|
||||
"2x (MSAA)",
|
||||
"4x (MSAA)",
|
||||
"8x (MSAA)",
|
||||
"16x (MSAA)"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
videoSetMSAA(1 << data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
msaa = videoGetMSAA();
|
||||
if (msaa < 2) {
|
||||
data->dropdown.value = 0;
|
||||
} else if (msaa < 4) {
|
||||
data->dropdown.value = 1;
|
||||
} else if (msaa < 8) {
|
||||
data->dropdown.value = 2;
|
||||
} else if (msaa < 16) {
|
||||
data->dropdown.value = 3;
|
||||
} else {
|
||||
data->dropdown.value = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static char resstring[32];
|
||||
static const char *rescustom = "Custom";
|
||||
displaymode mode;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_CHECKDISABLED:
|
||||
if (videoGetFullscreen() && videoGetFullscreenMode() == 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = videoGetNumDisplayModes();
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
videoGetDisplayMode(&mode, data->dropdown.value);
|
||||
if (mode.width == 0 && mode.height == 0) {
|
||||
return (intptr_t)rescustom;
|
||||
} else {
|
||||
snprintf(resstring, sizeof(resstring), "%dx%d", mode.width, mode.height);
|
||||
}
|
||||
return (intptr_t)resstring;
|
||||
case MENUOP_SET:
|
||||
videoSetDisplayMode(data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetDisplayModeIndex();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
@@ -755,12 +900,25 @@ static MenuItemHandlerResult menuhandlerTexFilter2D(s32 operation, struct menuit
|
||||
return videoGetTextureFilter2D();
|
||||
case MENUOP_SET:
|
||||
videoSetTextureFilter2D(data->checkbox.value);
|
||||
g_TexFilter2D = videoGetTextureFilter2D() ? G_TF_BILERP : G_TF_POINT;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerDisplayFPS(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return videoGetDisplayFPS();
|
||||
case MENUOP_SET:
|
||||
videoSetDisplayFPS(data->checkbox.value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
@@ -774,6 +932,19 @@ static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct me
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerUncapTickrate(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return (g_TickRateDiv == 0);
|
||||
case MENUOP_SET:
|
||||
g_TickRateDiv = !data->checkbox.value;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
@@ -832,20 +1003,84 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
menuhandlerFullScreen,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Maximize Window",
|
||||
(uintptr_t)"Full Screen Mode",
|
||||
0,
|
||||
menuhandlerMaximizeWindow,
|
||||
menuhandlerFullScreenMode,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Resolution",
|
||||
0,
|
||||
menuhandlerResolution,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Detail Textures",
|
||||
(uintptr_t)"Center Window",
|
||||
0,
|
||||
menuhandlerTexDetail,
|
||||
menuhandlerCenterWindow,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Anti-aliasing",
|
||||
0,
|
||||
menuhandlerMSAA,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Vsync",
|
||||
0,
|
||||
menuhandlerVsync,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE | MENUITEMFLAG_SLIDER_DEFERRED,
|
||||
(uintptr_t)"Framerate Limit",
|
||||
VIDEO_MAX_FPS,
|
||||
menuhandlerFramerateLimit,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Uncap Tickrate",
|
||||
0,
|
||||
menuhandlerUncapTickrate,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Display FPS",
|
||||
0,
|
||||
menuhandlerDisplayFPS,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
@@ -867,9 +1102,17 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"GE64-style Muzzle Flashes",
|
||||
(uintptr_t)"Detail Textures",
|
||||
0,
|
||||
menuhandlerGeMuzzleFlashes,
|
||||
menuhandlerTexDetail,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
@@ -879,6 +1122,14 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
0,
|
||||
menuhandlerCenterHUD,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"GE64-style Muzzle Flashes",
|
||||
0,
|
||||
menuhandlerGeMuzzleFlashes,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
@@ -965,6 +1216,21 @@ struct menudialogdef g_ExtendedAudioMenuDialog = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static MenuItemHandlerResult menuhandlerUseKeyReloads(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_CHECKDISABLED:
|
||||
return !g_PlayerExtCfg[g_ExtMenuPlayer].extcontrols;
|
||||
case MENUOP_GET:
|
||||
return g_PlayerExtCfg[g_ExtMenuPlayer].usereloads;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].usereloads = data->checkbox.value;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCrouchMode(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
@@ -1269,6 +1535,14 @@ struct menuitem g_ExtendedGameMenuItems[] = {
|
||||
0,
|
||||
menuhandlerCrosshairHealth,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Use Key Reloads",
|
||||
0,
|
||||
menuhandlerUseKeyReloads,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
|
||||
+254
-18
@@ -6,6 +6,7 @@
|
||||
#include <PR/gbi.h>
|
||||
#include "platform.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "../fast3d/gfx_api.h"
|
||||
@@ -35,19 +36,33 @@ static s32 vidFramebuffers = true;
|
||||
static s32 vidFullscreen = DEFAULT_VID_FULLSCREEN;
|
||||
static s32 vidFullscreenExclusive = DEFAULT_VID_FULLSCREEN_EXCLUSIVE;
|
||||
static s32 vidMaximize = false;
|
||||
static s32 vidCenter = false;
|
||||
static s32 vidAllowHiDpi = false;
|
||||
static s32 vidVsync = 1;
|
||||
static s32 vidMSAA = 1;
|
||||
static s32 vidFramerateLimit = 0;
|
||||
|
||||
static s32 vidDisplayFPS = 0;
|
||||
static f32 vidDisplayFPSInterval = 1.f;
|
||||
static f32 vidAvgFPS = 0;
|
||||
static f64 vidLastRenderTime;
|
||||
|
||||
static s32 vidNumModes = 1;
|
||||
static displaymode vidModeDefault;
|
||||
static displaymode *vidModes = &vidModeDefault;
|
||||
|
||||
static s32 texFilter = FILTER_LINEAR;
|
||||
static s32 texFilter2D = true;
|
||||
static s32 texDetail = true;
|
||||
static s32 texDetail = false;
|
||||
|
||||
static u32 dlcount = 0;
|
||||
static u32 frames = 0;
|
||||
static u32 framesPerSec = 0;
|
||||
static f64 startTime, endTime, fpsTime;
|
||||
static f64 startTime, endTime;
|
||||
static f64 accumDelta = 0.0;
|
||||
static f64 fpsTime = 0.0;
|
||||
static s32 fpsNumFrames = 0;
|
||||
|
||||
static s32 videoInitDisplayModes(void);
|
||||
|
||||
s32 videoInit(void)
|
||||
{
|
||||
@@ -73,22 +88,17 @@ s32 videoInit(void)
|
||||
.fullscreen = vidFullscreen,
|
||||
.fullscreen_is_exclusive = vidFullscreenExclusive,
|
||||
.maximized = vidMaximize,
|
||||
.centered = vidCenter,
|
||||
.allow_hidpi = vidAllowHiDpi
|
||||
}
|
||||
};
|
||||
|
||||
gfx_init(&set);
|
||||
|
||||
if (!wmAPI->set_swap_interval(vidVsync)) {
|
||||
vidVsync = 0;
|
||||
}
|
||||
videoInitDisplayModes();
|
||||
videoSetVsync(vidVsync);
|
||||
videoSetFramerateLimit(vidFramerateLimit);
|
||||
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
vidFramerateLimit = VIDEO_MAX_FPS;
|
||||
}
|
||||
|
||||
wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on
|
||||
gfx_set_texture_filter((enum FilteringMode)texFilter);
|
||||
|
||||
initDone = true;
|
||||
@@ -101,6 +111,10 @@ void videoStartFrame(void)
|
||||
startTime = wmAPI->get_time();
|
||||
gfx_start_frame();
|
||||
}
|
||||
|
||||
// Synchronize with their backend counterparts.
|
||||
vidFullscreen = videoGetFullscreen();
|
||||
vidMaximize = videoGetMaximizeWindow();
|
||||
}
|
||||
|
||||
void videoSubmitCommands(Gfx *cmds)
|
||||
@@ -119,20 +133,35 @@ void videoEndFrame(void)
|
||||
|
||||
gfx_end_frame();
|
||||
|
||||
endTime = wmAPI->get_time();
|
||||
|
||||
++frames;
|
||||
++framesPerSec;
|
||||
++fpsNumFrames;
|
||||
|
||||
const f64 flipTime = wmAPI->get_time();
|
||||
accumDelta += flipTime - endTime;
|
||||
endTime = flipTime;
|
||||
vidLastRenderTime = endTime - startTime;
|
||||
|
||||
if (endTime >= fpsTime) {
|
||||
char tmp[128];
|
||||
snprintf(tmp, sizeof(tmp), "fps %3u frt %lf frm %u", framesPerSec, endTime - startTime, frames);
|
||||
vidAvgFPS = fpsNumFrames ? ((f64)fpsNumFrames / accumDelta) : 0.f;
|
||||
fpsNumFrames = 0;
|
||||
accumDelta = 0.0;
|
||||
snprintf(tmp, sizeof(tmp), "fps %4.1f frt %lf frm %u", vidAvgFPS, vidLastRenderTime, frames);
|
||||
wmAPI->set_window_title(tmp);
|
||||
framesPerSec = 0;
|
||||
fpsTime = endTime + 1.0;
|
||||
fpsTime = endTime + vidDisplayFPSInterval;
|
||||
}
|
||||
}
|
||||
|
||||
f64 videoGetLastRenderTime(void)
|
||||
{
|
||||
return vidLastRenderTime;
|
||||
}
|
||||
|
||||
f32 videoGetAverageFPS(void)
|
||||
{
|
||||
return vidAvgFPS;
|
||||
}
|
||||
|
||||
void videoClearScreen(void)
|
||||
{
|
||||
videoStartFrame();
|
||||
@@ -177,19 +206,159 @@ s32 videoGetHeight(void)
|
||||
|
||||
s32 videoGetFullscreen(void)
|
||||
{
|
||||
vidFullscreen = wmAPI->get_fullscreen_state();
|
||||
return vidFullscreen;
|
||||
}
|
||||
|
||||
s32 videoGetFullscreenMode(void)
|
||||
{
|
||||
vidFullscreenExclusive = wmAPI->get_fullscreen_flag_mode();
|
||||
return vidFullscreenExclusive;
|
||||
}
|
||||
|
||||
s32 videoGetMaximizeWindow(void)
|
||||
{
|
||||
vidMaximize = wmAPI->get_maximized_state();
|
||||
return vidMaximize;
|
||||
}
|
||||
|
||||
s32 videoGetCenterWindow(void)
|
||||
{
|
||||
return vidCenter;
|
||||
}
|
||||
|
||||
f32 videoGetAspect(void)
|
||||
{
|
||||
return gfx_current_dimensions.aspect_ratio;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayModeIndex(void)
|
||||
{
|
||||
for (s32 i = 1; i < vidNumModes; ++i) {
|
||||
if (vidModes[i].width == gfx_current_dimensions.width &&
|
||||
vidModes[i].height == gfx_current_dimensions.height) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// Current dimensions don't match any known mode, so return index 0, "Custom".
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 videoGetMSAA(void)
|
||||
{
|
||||
vidMSAA = (s32)gfx_msaa_level;
|
||||
return vidMSAA;
|
||||
}
|
||||
|
||||
s32 videoGetVsync(void)
|
||||
{
|
||||
vidVsync = wmAPI->get_swap_interval();
|
||||
return vidVsync;
|
||||
}
|
||||
|
||||
s32 videoGetFramerateLimit(void)
|
||||
{
|
||||
vidFramerateLimit = wmAPI->get_target_fps();
|
||||
return vidFramerateLimit;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayFPS(void)
|
||||
{
|
||||
return vidDisplayFPS;
|
||||
}
|
||||
|
||||
static s32 videoInitDisplayModes(void)
|
||||
{
|
||||
if (!wmAPI->get_current_display_mode(&vidModeDefault.width, &vidModeDefault.height)) {
|
||||
vidModeDefault.width = 640;
|
||||
vidModeDefault.height = 480;
|
||||
return false;
|
||||
}
|
||||
|
||||
const s32 numBaseModes = wmAPI->get_num_display_modes();
|
||||
if (!numBaseModes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const s32 numCustomModes = 1;
|
||||
displaymode *modeList = sysMemZeroAlloc((numBaseModes + numCustomModes) * sizeof(displaymode));
|
||||
if (!modeList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modeList[0].width = 0;
|
||||
modeList[0].height = 0;
|
||||
|
||||
s32 numModes = 1;
|
||||
s32 w = -1, h = w, neww = w, newh = w;
|
||||
|
||||
// SDL modes are guaranteed to be sorted high to low
|
||||
for (s32 i = 0; i < numBaseModes; ++i) {
|
||||
wmAPI->get_display_mode(i, &neww, &newh);
|
||||
|
||||
if (neww != w || newh != h) {
|
||||
w = neww;
|
||||
h = newh;
|
||||
modeList[numModes].width = w;
|
||||
modeList[numModes].height = h;
|
||||
++numModes;
|
||||
}
|
||||
}
|
||||
|
||||
modeList = sysMemRealloc(modeList, numModes * sizeof(displaymode));
|
||||
if (!modeList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vidModes = modeList;
|
||||
vidNumModes = numModes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayMode(displaymode *out, const s32 index)
|
||||
{
|
||||
if (index >= 0 && index < vidNumModes) {
|
||||
*out = vidModes[index];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 videoGetNumDisplayModes(void)
|
||||
{
|
||||
return vidNumModes;
|
||||
}
|
||||
|
||||
void videoSetDisplayMode(const s32 index)
|
||||
{
|
||||
const displaymode dm = vidModes[index];
|
||||
|
||||
if (index == 0) {
|
||||
// "Custom" video mode.
|
||||
return;
|
||||
}
|
||||
|
||||
vidWidth = dm.width;
|
||||
vidHeight = dm.height;
|
||||
|
||||
s32 posX = 100;
|
||||
s32 posY = 100;
|
||||
if (vidCenter) {
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
}
|
||||
|
||||
if (vidFullscreen) {
|
||||
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
|
||||
} else {
|
||||
if (vidMaximize) {
|
||||
videoSetMaximizeWindow(false);
|
||||
} else {
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 videoGetTextureFilter2D(void)
|
||||
{
|
||||
return texFilter2D;
|
||||
@@ -215,7 +384,22 @@ void videoSetFullscreen(s32 fs)
|
||||
{
|
||||
if (fs != vidFullscreen) {
|
||||
vidFullscreen = !!fs;
|
||||
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
|
||||
wmAPI->set_fullscreen(vidFullscreen);
|
||||
if (!vidFullscreen && vidMaximize) {
|
||||
wmAPI->set_maximize(false);
|
||||
wmAPI->set_maximize(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetFullscreenMode(s32 mode)
|
||||
{
|
||||
vidFullscreenExclusive = mode;
|
||||
wmAPI->set_fullscreen_flag(mode);
|
||||
if (vidFullscreen) {
|
||||
wmAPI->set_fullscreen(false);
|
||||
wmAPI->set_fullscreen(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +408,23 @@ void videoSetMaximizeWindow(s32 fs)
|
||||
if (fs != vidMaximize) {
|
||||
vidMaximize = !!fs;
|
||||
wmAPI->set_maximize(vidMaximize);
|
||||
if (vidCenter && !vidMaximize) {
|
||||
s32 posX = 0;
|
||||
s32 posY = 0;
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetCenterWindow(s32 center)
|
||||
{
|
||||
vidCenter = center;
|
||||
if (vidCenter && !vidMaximize) {
|
||||
s32 posX = 0;
|
||||
s32 posY = 0;
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +452,33 @@ s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
|
||||
return gfx_create_framebuffer(w, h, upscale, autoresize);
|
||||
}
|
||||
|
||||
void videoSetMSAA(const s32 msaa)
|
||||
{
|
||||
vidMSAA = msaa;
|
||||
gfx_msaa_level = (u32)vidMSAA;
|
||||
}
|
||||
|
||||
void videoSetVsync(const s32 vsync)
|
||||
{
|
||||
vidVsync = wmAPI->set_swap_interval(vsync) ? vsync : 0;
|
||||
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
videoSetFramerateLimit(VIDEO_MAX_FPS);
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetFramerateLimit(const s32 limit)
|
||||
{
|
||||
vidFramerateLimit = (vidVsync == 0 && limit == 0) ? VIDEO_MAX_FPS : limit;
|
||||
wmAPI->set_target_fps(vidFramerateLimit);
|
||||
}
|
||||
|
||||
void videoSetDisplayFPS(const s32 displayfps)
|
||||
{
|
||||
vidDisplayFPS = displayfps;
|
||||
}
|
||||
|
||||
void videoSetFramebuffer(s32 target)
|
||||
{
|
||||
return gfx_set_framebuffer(target, 1.f);
|
||||
@@ -287,6 +515,11 @@ void videoFreeCachedTexture(const void *texptr)
|
||||
gfx_texture_cache_delete(texptr);
|
||||
}
|
||||
|
||||
void videoShutdown(void)
|
||||
{
|
||||
free(vidModes);
|
||||
}
|
||||
|
||||
PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
{
|
||||
configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1);
|
||||
@@ -294,10 +527,13 @@ PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767);
|
||||
configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767);
|
||||
configRegisterInt("Video.ExclusiveFullscreen", &vidFullscreenExclusive, 0, 1);
|
||||
configRegisterInt("Video.CenterWindow", &vidCenter, 0, 1);
|
||||
configRegisterInt("Video.AllowHiDpi", &vidAllowHiDpi, 0, 1);
|
||||
configRegisterInt("Video.VSync", &vidVsync, -1, 10);
|
||||
configRegisterInt("Video.FramebufferEffects", &vidFramebuffers, 0, 1);
|
||||
configRegisterInt("Video.FramerateLimit", &vidFramerateLimit, 0, VIDEO_MAX_FPS);
|
||||
configRegisterInt("Video.DisplayFPS", &vidDisplayFPS, 0, 1);
|
||||
configRegisterFloat("Video.DisplayFPSInterval", &vidDisplayFPSInterval, 0.01f, 32.f);
|
||||
configRegisterInt("Video.MSAA", &vidMSAA, 1, 16);
|
||||
configRegisterInt("Video.TextureFilter", &texFilter, 0, 2);
|
||||
configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1);
|
||||
|
||||
+3
-1
@@ -1810,7 +1810,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
|
||||
g_Vars.currentplayer->bondactivateorreload = 0;
|
||||
|
||||
s32 usereloads = (controlmode != CONTROLMODE_PC);
|
||||
#ifndef PLATFORM_N64
|
||||
usereloads = usereloads || PLAYER_EXTCFG().usereloads;
|
||||
if (controlmode == CONTROLMODE_PC && movedata.alt1tapcount) {
|
||||
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_RELOAD;
|
||||
}
|
||||
@@ -1818,7 +1820,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
if (movedata.btapcount) {
|
||||
g_Vars.currentplayer->activatetimelast = g_Vars.currentplayer->activatetimethis;
|
||||
g_Vars.currentplayer->activatetimethis = g_Vars.lvframe60;
|
||||
if (controlmode == CONTROLMODE_PC) {
|
||||
if (!usereloads) {
|
||||
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_ACTIVATE;
|
||||
} else {
|
||||
g_Vars.currentplayer->bondactivateorreload = movedata.btapcount ?
|
||||
|
||||
@@ -687,6 +687,12 @@ void challengeApply(void)
|
||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
||||
g_PlayerConfigsArray[i].base.team = 0;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// Enable Friendly Fire option
|
||||
g_MpSetup.options |= MPOPTION_FRIENDLYFIRE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
s32 challengeRemovePlayerLock(void)
|
||||
|
||||
+47
-1
@@ -98,6 +98,7 @@
|
||||
#include "types.h"
|
||||
#ifndef PLATFORM_N64
|
||||
#include "debugger.h"
|
||||
#include "video.h"
|
||||
#endif
|
||||
|
||||
struct sndstate *g_MiscSfxAudioHandles[3];
|
||||
@@ -956,6 +957,45 @@ void lvFindThreats(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
Gfx *lvRenderFPS(Gfx *gdl)
|
||||
{
|
||||
const f32 fps = videoGetAverageFPS();
|
||||
const u8 a = 160;
|
||||
s32 x = 27, y = 13;
|
||||
u32 color;
|
||||
char buffer[16];
|
||||
|
||||
if (fps <= 30.f) {
|
||||
// red -> yellow
|
||||
color = 0xff000000 | a | ((u32)((fps / 30.f) * 255.f) << 16);
|
||||
} else if (fps <= 60.f) {
|
||||
// yellow -> green
|
||||
color = 0x00ff0000 | a | ((u32)((1.f - (fps - 30.f) / 30.f) * 255.f) << 24);
|
||||
} else if (fps <= 90.f) {
|
||||
// green -> cyan
|
||||
color = 0x00ff0000 | a | ((u32)(((fps - 60.f) / 30.f) * 255.f) << 8);
|
||||
} else {
|
||||
// cyan
|
||||
color = 0x00ffff00 | a;
|
||||
}
|
||||
|
||||
if (g_CharsNumeric && g_FontNumeric) {
|
||||
snprintf(buffer, sizeof buffer, "%.2f", fps);
|
||||
|
||||
gSPSetExtraGeometryModeEXT(gdl++, g_HudAlignModeL);
|
||||
|
||||
gdl = text0f153628(gdl);
|
||||
gdl = textRender(gdl, &x, &y, buffer, g_CharsNumeric, g_FontNumeric, color, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0);
|
||||
gdl = text0f153780(gdl);
|
||||
|
||||
gSPClearExtraGeometryModeEXT(gdl++, g_HudAlignModeL);
|
||||
}
|
||||
|
||||
return gdl;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Renders a complete frame for all players, and also does some other game logic
|
||||
* that really doesn't belong here.
|
||||
@@ -1309,7 +1349,7 @@ Gfx *lvRender(Gfx *gdl)
|
||||
if (!currentPlayerInteract(false)) {
|
||||
#ifndef PLATFORM_N64
|
||||
// n64 behavior: interact sucessful, cancel reload
|
||||
if (!PLAYER_EXTCFG().extcontrols) {
|
||||
if (!PLAYER_EXTCFG().extcontrols || PLAYER_EXTCFG().usereloads) {
|
||||
g_Vars.currentplayer->bondactivateorreload = (g_Vars.currentplayer->bondactivateorreload & ~JO_ACTION_RELOAD);
|
||||
}
|
||||
#endif
|
||||
@@ -1751,6 +1791,12 @@ Gfx *lvRender(Gfx *gdl)
|
||||
|
||||
gDPSetScissor(gdl++, G_SC_NON_INTERLACE, 0, 0, viGetWidth(), viGetHeight());
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (videoGetDisplayFPS()) {
|
||||
gdl = lvRenderFPS(gdl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VERSION < VERSION_NTSC_1_0
|
||||
if ((uintptr_t)gdl < (uintptr_t)g_GfxBuffers[g_GfxActiveBufferIndex]
|
||||
|| (uintptr_t)gdl > (uintptr_t)g_GfxBuffers[g_GfxActiveBufferIndex + 1]) {
|
||||
|
||||
+19
-1
@@ -142,6 +142,9 @@ s32 g_MpPlayerNum = 0;
|
||||
s32 g_MenuMouseControl = true;
|
||||
s32 g_MenuUsingMouse = false;
|
||||
s32 g_MenuKeyboardPlayer = -1;
|
||||
s32 g_AllowMouseHeld = true;
|
||||
s32 g_MouseDimmedMode = false;
|
||||
s32 g_MouseEndDeferredSlider = false;
|
||||
#endif
|
||||
|
||||
void menuPlaySound(s32 menusound)
|
||||
@@ -1512,6 +1515,12 @@ void menuOpenDialog(struct menudialogdef *dialogdef, struct menudialog *dialog,
|
||||
|
||||
void menuPushDialog(struct menudialogdef *dialogdef)
|
||||
{
|
||||
#ifndef PLATFORM_N64
|
||||
// Prevent the mouse from immediately changing a slider's value, as was
|
||||
// happening while entering the Audio menu.
|
||||
g_AllowMouseHeld = false;
|
||||
#endif
|
||||
|
||||
if (dialogdef) {
|
||||
menuUnsetModel(&g_Menus[g_MpPlayerNum].menumodel);
|
||||
|
||||
@@ -4700,6 +4709,7 @@ void menuProcessInput(void)
|
||||
inputs.back2 = 0;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
inputs.mouseheld = false;
|
||||
inputs.mousemoved = false;
|
||||
inputs.mousescroll = 0;
|
||||
inputs.mousex = 0;
|
||||
@@ -4709,8 +4719,16 @@ void menuProcessInput(void)
|
||||
// ESC always acts as back
|
||||
inputs.back = inputKeyJustPressed(VK_ESCAPE);
|
||||
if (inputMouseIsEnabled() && !inputMouseIsLocked() && g_MenuMouseControl) {
|
||||
inputs.mousemoved = inputMouseGetPosition(&inputs.mousex, &inputs.mousey);
|
||||
inputs.mouseheld = inputKeyPressed(VK_MOUSE_LEFT);
|
||||
if (!inputs.mouseheld) {
|
||||
g_AllowMouseHeld = true;
|
||||
if (g_MouseDimmedMode) {
|
||||
g_MouseDimmedMode = false;
|
||||
g_MouseEndDeferredSlider = true;
|
||||
}
|
||||
}
|
||||
inputs.mousescroll = inputKeyPressed(VK_MOUSE_WHEEL_DN) - inputKeyPressed(VK_MOUSE_WHEEL_UP);
|
||||
inputs.mousemoved = inputMouseGetPosition(&inputs.mousex, &inputs.mousey) || inputs.mousescroll;
|
||||
// aspect correct the X
|
||||
const f32 cx = ((f32)inputs.mousex - (f32)(SCREEN_WIDTH_LO / 2)) * (videoGetAspect() / SCREEN_ASPECT);
|
||||
inputs.mousex = (f32)(SCREEN_WIDTH_LO / 2) + cx;
|
||||
|
||||
+70
-22
@@ -50,6 +50,8 @@ u8 g_KeyboardKeys[5][10] = {
|
||||
{ '1','2','1','2','1','2','3','1','2','3' },
|
||||
};
|
||||
|
||||
static s32 deferredindex = -1;
|
||||
|
||||
s32 func0f0e5ce0(s32 value)
|
||||
{
|
||||
if (value < var800711a4) {
|
||||
@@ -2266,7 +2268,7 @@ Gfx* menuitemColorBoxRender(Gfx *gdl, struct menurendercontext *context)
|
||||
return gdl;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Gfx *menuitemSelectableRender(Gfx *gdl, struct menurendercontext *context)
|
||||
{
|
||||
@@ -2427,8 +2429,15 @@ Gfx *menuitemSliderRender(Gfx *gdl, struct menurendercontext *context)
|
||||
extray = 0;
|
||||
|
||||
if (context->item->handler != NULL) {
|
||||
context->item->handler(MENUOP_GETSLIDER, context->item, &data);
|
||||
slidervalue = (s16) data.slider.value;
|
||||
if ((context->item->flags & MENUITEMFLAG_SLIDER_DEFERRED) &&
|
||||
deferredindex != -1 &&
|
||||
context->dialog->dimmed &&
|
||||
context->focused) {
|
||||
slidervalue = (s16) deferredindex;
|
||||
} else {
|
||||
context->item->handler(MENUOP_GETSLIDER, context->item, &data);
|
||||
slidervalue = (s16) data.slider.value;
|
||||
}
|
||||
} else {
|
||||
slidervalue = 0;
|
||||
}
|
||||
@@ -2550,7 +2559,7 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
|
||||
if ((tickflags & MENUTICKFLAG_ITEMISFOCUSED)) {
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MenuUsingMouse && inputs->select) {
|
||||
if (g_AllowMouseHeld && g_MenuUsingMouse && (inputs->select || inputs->mouseheld)) {
|
||||
// handle mouse
|
||||
struct menudialog *dialog = g_Menus[g_MpPlayerNum].curdialog;
|
||||
if (dialog) {
|
||||
@@ -2559,19 +2568,27 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
const s32 size = right - left;
|
||||
const s32 delta = inputs->mousex - left;
|
||||
if (delta >= -8 && delta <= size + 8) {
|
||||
index = (delta / (f32)size) * item->param3;
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
if ((tickflags & MENUTICKFLAG_DIALOGISDIMMED) == 0) {
|
||||
g_MouseDimmedMode = true;
|
||||
} else {
|
||||
index = (delta / (f32)size) * item->param3;
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
}
|
||||
if (index > item->param3) {
|
||||
index = item->param3;
|
||||
}
|
||||
if (item->handler) {
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
deferredindex = index;
|
||||
} else {
|
||||
item->handler(MENUOP_GET, item, &handlerdata);
|
||||
handlerdata.slider.value = index;
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (index > item->param3) {
|
||||
index = item->param3;
|
||||
}
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_GET, item, &handlerdata);
|
||||
handlerdata.slider.value = index;
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2579,12 +2596,32 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
|
||||
if (tickflags & MENUTICKFLAG_DIALOGISDIMMED) {
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
index = (s16) handlerdata.slider.value;
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
if (deferredindex == -1) {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
deferredindex = (s16) handlerdata.slider.value;
|
||||
}
|
||||
index = deferredindex;
|
||||
} else {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
index = (s16) handlerdata.slider.value;
|
||||
}
|
||||
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MenuUsingMouse && inputs->mousescroll) {
|
||||
if ((item->flags & MENUITEMFLAG_SLIDER_FAST) == 0) {
|
||||
index += -inputs->mousescroll;
|
||||
} else {
|
||||
s32 mult = item->param3 / 40;
|
||||
index += -inputs->mousescroll * (mult ? mult : 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((item->flags & MENUITEMFLAG_SLIDER_FAST) == 0
|
||||
&& g_Menus[g_MpPlayerNum].xrepeatmode == MENUREPEATMODE_SLOW) {
|
||||
index = index + inputs->leftright;
|
||||
@@ -2660,11 +2697,22 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
inputs->leftright = 0;
|
||||
handlerdata.slider.value = index;
|
||||
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
deferredindex = index;
|
||||
} else {
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
}
|
||||
|
||||
if (inputs->select) {
|
||||
if (inputs->select || g_MouseEndDeferredSlider) {
|
||||
g_MouseEndDeferredSlider = false;
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
deferredindex = -1;
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
}
|
||||
dialog->dimmed = false;
|
||||
}
|
||||
} else {
|
||||
@@ -2704,7 +2752,7 @@ Gfx *menuitemCarouselRender(Gfx *gdl, struct menurendercontext *context)
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
s16 chevronOffset = 0;
|
||||
#else
|
||||
#else
|
||||
s16 chevronOffset = 3;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@ struct modeldef *var800acc28[18];
|
||||
struct mpweaponset g_MpWeaponSets[12];
|
||||
s32 g_MpWeaponSetNum;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
u8 g_MpWeaponSetRandomFilters[NUM_MPWEAPONS];
|
||||
s32 g_MpWeaponRandomFilterNum;
|
||||
#endif
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
const char var7f1b8a00[] = "||||||||||||| Starting game... players %d\n";
|
||||
#endif
|
||||
@@ -130,6 +135,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = {
|
||||
.crosshaircolour = 0x00ff0028, \
|
||||
.crosshairsize = 2, \
|
||||
.crosshairhealth = CROSSHAIR_HEALTH_OFF, \
|
||||
.usereloads = false, \
|
||||
}
|
||||
|
||||
struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = {
|
||||
@@ -507,6 +513,12 @@ void mpPlayerSetDefaults(s32 playernum, bool autonames)
|
||||
for (i = 0; i < ARRAYCOUNT(g_PlayerConfigsArray); i++) {
|
||||
g_PlayerConfigsArray[playernum].gunfuncs[i] = 0;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void func0f1881d4(s32 index)
|
||||
@@ -1157,10 +1169,40 @@ void func0f18913c(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
void mpSetRandomWeapons(u8 weapons[])
|
||||
{
|
||||
s32 lockcount = 0;
|
||||
s32 index = 0;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < NUM_MPWEAPONS; i++) {
|
||||
if (challengeIsFeatureUnlocked(g_MpWeapons[i].unlockfeature)) {
|
||||
if (g_MpWeaponSetRandomFilters[i] == 1) {
|
||||
weapons[index] = i - lockcount;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
lockcount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
weapons[0] = 0; // optionindex (shifted by unlocked weapons, but usually 0 is "Nothing")
|
||||
g_MpWeaponRandomFilterNum = 1;
|
||||
} else {
|
||||
g_MpWeaponRandomFilterNum = index;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mpApplyWeaponSet(void)
|
||||
{
|
||||
s32 i;
|
||||
u8 *ptr;
|
||||
#ifndef PLATFORM_N64
|
||||
u8 randomweapons[NUM_MPWEAPONS];
|
||||
#endif
|
||||
|
||||
if (g_MpWeaponSetNum >= 0 && g_MpWeaponSetNum < ARRAYCOUNT(g_MpWeaponSets)) {
|
||||
if (challengeIsFeatureUnlocked(g_MpWeaponSets[g_MpWeaponSetNum].requirefeatures[0])
|
||||
@@ -1198,17 +1240,31 @@ void mpApplyWeaponSet(void)
|
||||
}
|
||||
}
|
||||
} else if (g_MpWeaponSetNum == WEAPONSET_RANDOM) {
|
||||
#ifdef PLATFORM_N64
|
||||
s32 numoptions = mpGetNumWeaponOptions();
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpSetup.weapons); i++) {
|
||||
mpSetWeaponSlot(i, rngRandom() % numoptions);
|
||||
}
|
||||
#else
|
||||
mpSetRandomWeapons(randomweapons);
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpSetup.weapons); i++) {
|
||||
mpSetWeaponSlot(i, randomweapons[rngRandom() % g_MpWeaponRandomFilterNum]);
|
||||
}
|
||||
#endif
|
||||
} else if (g_MpWeaponSetNum == WEAPONSET_RANDOMFIVE) {
|
||||
#ifdef PLATFORM_N64
|
||||
s32 numoptions = mpGetNumWeaponOptions() - 2;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
mpSetWeaponSlot(i, rngRandom() % numoptions + 1);
|
||||
}
|
||||
#else
|
||||
mpSetRandomWeapons(randomweapons);
|
||||
for (i = 0; i < 5; i++) {
|
||||
mpSetWeaponSlot(i, randomweapons[rngRandom() % g_MpWeaponRandomFilterNum]);
|
||||
}
|
||||
#endif
|
||||
|
||||
mpSetWeaponSlot(i, mpGetNumWeaponOptions() - 1);
|
||||
}
|
||||
|
||||
@@ -1165,6 +1165,155 @@ struct menudialogdef g_MpSaveSetupExistsMenuDialog = {
|
||||
};
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
MenuItemHandlerResult mpSelectRandomWeaponListHandler(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *labels[] = {
|
||||
"Select Dark",
|
||||
"Select Classic",
|
||||
"Select All",
|
||||
"Select None",
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->list.value = mpGetNumWeaponOptions() + 4;
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
{
|
||||
s32 numweapons = mpGetNumWeaponOptions();
|
||||
|
||||
if (data->list.value < numweapons) {
|
||||
return (uintptr_t) mpGetWeaponLabel(data->list.value);
|
||||
} else {
|
||||
return (intptr_t)labels[data->list.value - numweapons];
|
||||
}
|
||||
}
|
||||
case MENUOP_SET:
|
||||
{
|
||||
s32 numweapons = mpGetNumWeaponOptions();
|
||||
s32 mpweaponnum = data->list.value;
|
||||
s32 optionindex = mpweaponnum;
|
||||
s32 i;
|
||||
|
||||
if (data->list.value < numweapons) {
|
||||
if (data->list.unk04 == 0) {
|
||||
for (i = 0; i <= mpweaponnum; i++) {
|
||||
if (challengeIsFeatureUnlocked(g_MpWeapons[i].unlockfeature) == 0) {
|
||||
mpweaponnum++;
|
||||
}
|
||||
|
||||
optionindex = mpweaponnum;
|
||||
}
|
||||
|
||||
g_MpWeaponSetRandomFilters[optionindex] = 1 - g_MpWeaponSetRandomFilters[optionindex];
|
||||
}
|
||||
} else {
|
||||
s32 index = data->list.value - numweapons;
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
// Select Dark
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
if ((i >= MPWEAPON_NONE && i <= MPWEAPON_COMBATBOOST) || i >= MPWEAPON_SHIELD) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
} else {
|
||||
g_MpWeaponSetRandomFilters[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// Select Classic
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
if (i >= MPWEAPON_PP9I && i <= MPWEAPON_RCP45) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
} else {
|
||||
g_MpWeaponSetRandomFilters[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Select All
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Select None
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
g_MpWeaponSetRandomFilters[i] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->list.value = 0x000fffff;
|
||||
break;
|
||||
case MENUOP_GETLISTITEMCHECKBOX:
|
||||
{
|
||||
s32 numweapons = mpGetNumWeaponOptions();
|
||||
s32 mpweaponnum = data->list.value;
|
||||
s32 optionindex = mpweaponnum;
|
||||
s32 i;
|
||||
|
||||
if (data->list.value < numweapons) {
|
||||
|
||||
for (i = 0; i <= mpweaponnum; i++) {
|
||||
if (challengeIsFeatureUnlocked(g_MpWeapons[i].unlockfeature) == 0) {
|
||||
mpweaponnum++;
|
||||
}
|
||||
|
||||
optionindex = mpweaponnum;
|
||||
}
|
||||
|
||||
data->list.unk04 = g_MpWeaponSetRandomFilters[optionindex];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_MpSelectRandomWeaponsMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LIST,
|
||||
0,
|
||||
MENUITEMFLAG_LOCKABLEMINOR,
|
||||
0x00000078,
|
||||
0x0000004d,
|
||||
mpSelectRandomWeaponListHandler,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_MpSelectRandomWeaponsMenuDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Select Weapons",
|
||||
g_MpSelectRandomWeaponsMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
MenuItemHandlerResult menuhandlerMpSelectRandomWeapons(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_CHECKDISABLED:
|
||||
case MENUOP_CHECKHIDDEN:
|
||||
if (g_MpWeaponSetNum == WEAPONSET_RANDOM
|
||||
|| g_MpWeaponSetNum == WEAPONSET_RANDOMFIVE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case MENUOP_SET:
|
||||
menuPushDialog(&g_MpSelectRandomWeaponsMenuDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MenuItemHandlerResult menuhandlerMpAutoRandomWeapon(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *labels[] = {
|
||||
@@ -1220,6 +1369,14 @@ struct menuitem g_MpWeaponsMenuItems[] = {
|
||||
menuhandlerMpWeaponSetDropdown,
|
||||
},
|
||||
#ifndef PLATFORM_N64
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Select Weapons\n",
|
||||
0,
|
||||
menuhandlerMpSelectRandomWeapons,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
|
||||
@@ -1666,6 +1666,7 @@
|
||||
#define MENUITEMFLAG_CAROUSEL_04000000 0x04000000
|
||||
#define MENUITEMFLAG_LITERAL_TEXT 0x08000000
|
||||
#define MENUITEMFLAG_SLIDER_WIDE 0x10000000
|
||||
#define MENUITEMFLAG_SLIDER_DEFERRED 0x20000000
|
||||
|
||||
#define MENUITEMTYPE_LABEL 0x01
|
||||
#define MENUITEMTYPE_LIST 0x02
|
||||
@@ -1696,7 +1697,7 @@
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
#define MENUITEMTYPE_COLORBOX 0x1b
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MENUMODELFLAG_HASSCALE 0x01
|
||||
#define MENUMODELFLAG_HASPOSITION 0x02
|
||||
|
||||
@@ -539,6 +539,9 @@ extern const struct weathercfg *g_CurWeatherConfig;
|
||||
|
||||
extern s32 g_MenuUsingMouse;
|
||||
extern s32 g_MenuKeyboardPlayer;
|
||||
extern s32 g_AllowMouseHeld;
|
||||
extern s32 g_MouseDimmedMode;
|
||||
extern s32 g_MouseEndDeferredSlider;
|
||||
|
||||
extern f32 g_ViShakeIntensityMult;
|
||||
extern u32 g_TexFilter2D;
|
||||
@@ -556,6 +559,9 @@ extern s32 g_MusicDisableMpDeath;
|
||||
extern s32 g_BgunGeMuzzleFlashes;
|
||||
extern s32 g_FileAutoSelect;
|
||||
|
||||
extern u8 g_MpWeaponSetRandomFilters[NUM_MPWEAPONS];
|
||||
extern s32 g_MpWeaponRandomFilterNum;
|
||||
|
||||
#define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3]
|
||||
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ s32 func0f189058(bool full);
|
||||
s32 func0f189088(void);
|
||||
char *mpGetWeaponSetName(s32 arg0);
|
||||
void func0f18913c(void);
|
||||
#ifndef PLATFORM_N64
|
||||
void mpSetRandomWeapons(u8 weapons[]);
|
||||
#endif
|
||||
void mpApplyWeaponSet(void);
|
||||
void mpSetWeaponSet(s32 weaponsetnum);
|
||||
void func0f1895e8(void);
|
||||
|
||||
+4
-2
@@ -4996,8 +4996,9 @@ struct menuinputs {
|
||||
/*0x10*/ s32 unk10;
|
||||
/*0x14*/ u8 unk14;
|
||||
#ifndef PLATFORM_N64
|
||||
/*0x15*/ u8 mousemoved;
|
||||
/*0x16*/ s8 mousescroll;
|
||||
/*0x15*/ u8 mouseheld;
|
||||
/*0x16*/ u8 mousemoved;
|
||||
/*0x17*/ s8 mousescroll;
|
||||
/*0x18*/ s32 mousex;
|
||||
/*0x1c*/ s32 mousey;
|
||||
#endif
|
||||
@@ -6152,6 +6153,7 @@ struct extplayerconfig {
|
||||
u32 crosshaircolour;
|
||||
u32 crosshairsize;
|
||||
s32 crosshairhealth;
|
||||
s32 usereloads;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user