Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-debugger

This commit is contained in:
fgsfds committed 2023-11-12 15:07:13 +01:00
commit df2ba8ec7d
36 files changed
+2049 -455

No files matched your search

+58 -27
View File
@@ -2,22 +2,39 @@
This repository contains a work-in-progress port of the [Perfect Dark decompilation](https://github.com/n64decomp/perfect_dark) to modern platforms.
To run the port, you must already have a Perfect Dark ROM, specifically the ntsc-final/revision 1 version
(md5 `e03b088b6ac9e0080440efed07c1e40f`).
To run the port, you must already have a Perfect Dark ROM, specifically one of the following:
* `ntsc-final`/`US V1.1`/`US Rev 1` (md5 `e03b088b6ac9e0080440efed07c1e40f`).
**This is the recommended version to use**.
Called `NTSC version 8.7 final` on the boot screen.
* `ntsc-1.0`/`US V1.0` (md5 `7f4171b0c8d17815be37913f535e4e93`).
Technically supported, but not recommended.
Called `NTSC version 8.7 final` on the boot screen as well.
* `jpn-final` (md5 `538d2b75945eae069b29c46193e74790`).
Technically supported, but requires a separate custom-built executable.
Called `JPN version 8.9 final` on the boot screen.
* `pal-final` (md5 `d9b5cd305d228424891ce38e71bc9213`).
Technically supported, but requires a separate custom-built executable.
Called `PAL 8.7 final` on the boot screen.
## Status
Currently only 32-bit platforms are supported, namely x86 Windows and Linux.
The game is in a mostly functional state, with both singleplayer and split-screen multiplayer modes fully working.
There are minor graphics- and gameplay-related issues, and possibly occasional crashes.
**The following extra features are implemented:**
* mouselook;
* dual analog controller support;
* widescreen resolution support;
* configurable field of view;
* 60 FPS support, including fixes for some framerate-related issues;
* fixes for a couple original bugs and crashes;
* basic mod support, currently enough to load a few custom levels;
* slightly expanded memory heap size.
Currently only 32-bit platforms are supported, namely x86 Windows and Linux.
Note that 32-bit binaries will still work on 64-bit versions of those platforms,
though you might have to install some additional libraries.
The game is in a somewhat functional but probably unstable state.
There are major graphical issues, minor audio issues and possibly other issues.
There are currently no "extra features" implemented
except for janky mouselook, arbitrary resolution support (with partial widescreen support), some extra controls
and somewhat expanded heap size.
## Download
Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) for supported platforms:
@@ -26,12 +43,16 @@ Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) for
## Running
You must already have a Perfect Dark ROM to run the game, as specified above.
You must already have a Perfect Dark ROM to run the game, as specified above.
1. Create a directory named `data` next to `pd.exe`.
2. Put your Perfect Dark ROM named `pd.ntsc-final.z64` into it.
3. Run `pd.exe`.
Additional information can be found in the [wiki](https://github.com/fgsfdsfgs/perfect_dark/wiki).
A GPU supporting OpenGL 3.0 or above is required to run the port.
## Controls
1964GEPD-style and Xbox-style bindings are implemented.
@@ -40,23 +61,26 @@ N64 pad buttons X and Y (or `X_BUTTON`, `Y_BUTTON` in the code) refer to the res
Support for one controller, two-stick configurations are enabled for 1.2.
Note that the mouse only controls player 1.
| Action | Keyboard and mouse | Xbox pad | N64 pad |
| - | - | - | - |
| Fire / Accept | LMB/Space | RT | Z Trigger |
| Aim mode | RMB/Z | LT | R Trigger |
| Use / Cancel | E | N/A | B |
| Use / Accept | N/A | A | A |
| Crouch cycle | N/A | L3 | `0x80000000` (Extra) |
| Half-Crouch | Shift | N/A | `0x40000000` (Extra) |
| Full-Crouch | Control | N/A | `0x20000000` (Extra) |
| Reload | R | X | X `(0x40)` |
| Previous weapon | Mousewheel forward | B | D-Left |
| Next weapon | Mousewheel back | Y | Y `(0x80)` |
| Radial menu | Q | LB | D-Down |
| Alt fire mode | F | RB | L Trigger |
| Alt-fire oneshot | F + LMB or E + LMB | A + RT or RB + RT | A + Z, L + Z |
| Quick-detonate | E + Q | A + B | A + D-Left |
Controls can be rebound in `pd.ini`. Default control scheme is as follows:
| Action | Keyboard and mouse | Xbox pad | N64 pad |
| - | - | - | - |
| Fire / Accept | LMB/Space | RT | Z Trigger |
| Aim mode | RMB/Z | LT | R Trigger |
| Use / Cancel | E | N/A | B |
| Use / Accept | N/A | A | A |
| Crouch cycle | N/A | L3 | `0x80000000` (Extra) |
| Half-Crouch | Shift | N/A | `0x40000000` (Extra) |
| Full-Crouch | Control | N/A | `0x20000000` (Extra) |
| Reload | R | X | X `(0x40)` |
| Previous weapon | Mousewheel forward | B | D-Left |
| Next weapon | Mousewheel back | Y | Y `(0x80)` |
| Radial menu | Q | LB | D-Down |
| Alt fire mode | F | RB | L Trigger |
| Alt-fire oneshot | `F + LMB` or `E + LMB` | `A + RT` or `RB + RT` | `A + Z` or `L + Z` |
| Quick-detonate | `E + Q` or `E + R` | `A + B` or `A + X` | `A + D-Left`or `A + X` |
## Building
@@ -80,6 +104,11 @@ Support for one controller, two-stick configurations are enabled for 1.2.
Currently only `i686-linux` and `i686-windows` are supported, using `gcc -m32` and `i686-w64-mingw32-gcc` as compilers, respectively.
Alternate compilers can be specified by passing `TOOLCHAIN=i686-whatever-` as a command line argument.
You can build an executable with PAL or JPN ROM support by adding `ROMID=pal-final` or `ROMID=jpn-final` to the `make` command.
You will need to provide a `jpn-final` or `pal-final` ROM for those, named `pd.jpn-final.z64` or `pd.pal-final.z64`.
It might be possible to build a 32-bit ARM executable, but this has not been tested.
## Credits
* the original [decompilation project](https://github.com/n64decomp/perfect_dark) authors;
@@ -87,4 +116,6 @@ Alternate compilers can be specified by passing `TOOLCHAIN=i686-whatever-` as a
* [sm64-port](https://github.com/sm64-port/sm64-port) authors for the audio mixer and some other changes;
* [Ship of Harkinian team](https://github.com/Kenix3/libultraship/tree/main/src/graphic/Fast3D), Emill and MaikelChan for the libultraship version of fast3d that this port uses;
* lieff for [minimp3](https://github.com/lieff/minimp3);
* Mouse Injector and 1964GEPD authors for some of the 60FPS- and mouselook-related fixes;
* everyone who has submitted pull requests and issues to this repository and tested the port;
* probably more I'm forgetting.
+5 -15
View File
@@ -13,18 +13,8 @@ s32 configLoad(const char *fname);
// saves config to file (path extensions such as ! apply)
s32 configSave(const char *fname);
// get value of a config variable or create a new one with specified default
// key is a string of the form "SECTION.KEY"
s32 configGetInt(const char *key, s32 defval);
f32 configGetFloat(const char *key, f32 defval);
const char *configGetString(const char *key, const char *defval);
// get value as above and clamp it in between minval, maxval
s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval);
f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval);
// set value of a config variable, will create it if it doesn't exist
// key is a string of the form "SECTION.KEY"
void configSetInt(const char *key, s32 val);
void configSetFloat(const char *key, f32 val);
void configSetString(const char *key, const char *val);
// registers a variable in the config file
// this should be done before configInit() is called, preferably in a module constructor
void configRegisterInt(const char *key, s32 *var, s32 min, s32 max);
void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max);
void configRegisterString(const char *key, char *var, u32 maxstr);
+34 -1
View File
@@ -6,6 +6,7 @@
#define INPUT_MAX_CONTROLLERS MAXCONTROLLERS
#define INPUT_MAX_CONTROLLER_BUTTONS 32
#define INPUT_MAX_BINDS 4
#define CONT_STICK_XNEG 0x10000
#define CONT_STICK_XPOS 0x20000
@@ -19,6 +20,7 @@ enum virtkey {
VK_KEYBOARD_BEGIN = 0,
VK_RETURN = 40,
VK_ESCAPE = 41,
VK_DELETE = 76,
/* same order as SDL mouse buttons */
VK_MOUSE_BEGIN = 512,
@@ -93,6 +95,18 @@ s32 inputControllerConnected(s32 idx);
// returns bitmask of connected controllers
s32 inputControllerMask(void);
s32 inputControllerGetSticksSwapped(s32 cidx);
void inputControllerSetSticksSwapped(s32 cidx, s32 swapped);
s32 inputControllerGetDualAnalog(s32 cidx);
void inputControllerSetDualAnalog(s32 cidx, s32 enable);
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis);
void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value);
f32 inputControllerGetAxisDeadzone(s32 cidx, s32 stick, s32 axis);
void inputControllerSetAxisDeadzone(s32 cidx, s32 stick, s32 axis, f32 value);
// vk is a value from the virtkey enum above
s32 inputKeyPressed(u32 vk);
@@ -103,6 +117,8 @@ s32 inputButtonPressed(s32 idx, u32 contbtn);
// if bind is -1, picks a bind slot automatically
void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk);
const u32 *inputKeyGetBinds(s32 idx, u32 ck);
// get VK_ value from human-readable name
s32 inputGetKeyByName(const char *name);
@@ -118,6 +134,9 @@ const char *inputGetContKeyName(u32 ck);
// strength is 0 .. 1; 0 strength turns it off
void inputRumble(s32 idx, f32 strength, f32 time);
f32 inputRumbleGetStrength(s32 cidx);
void inputRumbleSetStrength(s32 cidx, f32 val);
// locks the mouse cursor in the window and makes it invisible if argument is true
void inputLockMouse(s32 lock);
@@ -138,10 +157,24 @@ void inputMouseGetScaledDelta(f32 *dx, f32 *dy);
// returns 0, 0 when the mouse is not locked into the window
void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy);
void inputMouseGetSpeed(f32 *x, f32 *y);
void inputMouseSetSpeed(f32 x, f32 y);
s32 inputMouseIsEnabled(void);
void inputMouseEnable(s32 enabled);
// call this every frame
void inputUpdate(void);
// call this before configSave()
void inputSaveConfig(void);
void inputSaveBinds(void);
void inputSetDefaultKeyBinds(void);
void inputClearLastKey(void);
s32 inputGetLastKey(void);
s32 inputGetMouseDefaultLocked(void);
void inputSetMouseDefaultLocked(s32 defaultLocked);
#endif
+5
View File
@@ -19,9 +19,14 @@ s32 videoGetNativeHeight(void);
s32 videoGetWidth(void);
s32 videoGetHeight(void);
f32 videoGetAspect(void);
s32 videoGetFullscreen(void);
u32 videoGetTextureFilter(void);
u32 videoGetTextureFilter2D(void);
void videoSetWindowOffset(s32 x, s32 y);
void videoSetFullscreen(s32 fs);
void videoSetTextureFilter(u32 filter);
void videoSetTextureFilter2D(u32 filter);
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
void videoSetFramebuffer(s32 target);
+11 -4
View File
@@ -1,6 +1,7 @@
#include <PR/ultratypes.h>
#include <stdio.h>
#include <SDL.h>
#include "platform.h"
#include "config.h"
#include "audio.h"
#include "system.h"
@@ -8,7 +9,9 @@
static SDL_AudioDeviceID dev;
static const s16 *nextBuf;
static u32 nextSize = 0;
static u32 queueLimit = 8192;
static s32 bufferSize = 512;
static s32 queueLimit = 8192;
s32 audioInit(void)
{
@@ -22,7 +25,7 @@ s32 audioInit(void)
want.freq = 22020; // TODO: this might cause trouble for some platforms
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = configGetInt("Audio.BufferSize", 512);
want.samples = bufferSize;
want.callback = NULL;
nextBuf = NULL;
@@ -33,8 +36,6 @@ s32 audioInit(void)
return -1;
}
queueLimit = configGetInt("Audio.QueueLimit", 8192);
SDL_PauseAudioDevice(dev, 0);
return 0;
@@ -66,3 +67,9 @@ void audioEndFrame(void)
nextSize = 0;
}
}
PD_CONSTRUCTOR static void audioConfigInit(void)
{
configRegisterInt("Audio.BufferSize", &bufferSize, 0, 1 * 1024 * 1024);
configRegisterInt("Audio.QueueLimit", &queueLimit, 0, 1 * 1024 * 1024);
}
+85 -92
View File
@@ -8,20 +8,42 @@
#include "system.h"
#include "utils.h"
#define CONFIG_MAX_STR 512
#define CONFIG_MAX_SECNAME 128
#define CONFIG_MAX_KEYNAME 256
#define CONFIG_MAX_SETTINGS 256
typedef enum {
CFG_NONE,
CFG_S32,
CFG_F32,
CFG_STR
} configtype;
struct configentry {
char key[CONFIG_MAX_KEYNAME + 1];
char strval[CONFIG_MAX_STR + 1];
s32 s32val;
f32 f32val;
s32 seclen;
} settings[CONFIG_MAX_SETTINGS + 1];
configtype type;
void *ptr;
union {
struct { f32 min_f32, max_f32; };
struct { s32 min_s32, max_s32; };
u32 max_str;
};
} settings[CONFIG_MAX_SETTINGS];
static s32 numSettings = 0;
static inline s32 configClampInt(s32 val, s32 min, s32 max)
{
return (val < min) ? min : ((val > max) ? max : val);
}
static inline f32 configClampFloat(f32 val, f32 min, f32 max)
{
return (val < min) ? min : ((val > max) ? max : val);
}
static inline struct configentry *configFindEntry(const char *key)
{
for (s32 i = 0; i < numSettings; ++i) {
@@ -68,115 +90,89 @@ static inline const char *configGetSection(char *sec, const struct configentry *
return sec;
}
void configSetInt(const char *key, s32 val)
void configRegisterInt(const char *key, s32 *var, s32 min, s32 max)
{
struct configentry *cfg = configFindOrAddEntry(key);
if (cfg) {
cfg->s32val = val;
snprintf(cfg->strval, CONFIG_MAX_STR, "%d", val);
cfg->type = CFG_S32;
cfg->ptr = var;
cfg->min_s32 = min;
cfg->max_s32 = max;
}
}
void configSetFloat(const char *key, f32 val)
void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max)
{
struct configentry *cfg = configFindOrAddEntry(key);
if (cfg) {
cfg->f32val = val;
snprintf(cfg->strval, CONFIG_MAX_STR, "%f", val);
cfg->type = CFG_F32;
cfg->ptr = var;
cfg->min_f32 = min;
cfg->max_f32 = max;
}
}
void configSetString(const char *key, const char *val)
void configRegisterString(const char *key, char *var, u32 maxstr)
{
struct configentry *cfg = configFindOrAddEntry(key);
if (cfg) {
strncpy(cfg->strval, val, CONFIG_MAX_STR);
cfg->type = CFG_STR;
cfg->ptr = var;
cfg->max_str = maxstr;
}
}
void configSetFromString(const char *key, const char *val)
{
struct configentry *cfg = configFindOrAddEntry(key);
if (cfg) {
strncpy(cfg->strval, val, CONFIG_MAX_STR);
cfg->f32val = atof(val);
cfg->s32val = atoi(val);
}
}
s32 configGetInt(const char *key, s32 defval)
static void configSetFromString(const char *key, const char *val)
{
struct configentry *cfg = configFindEntry(key);
if (cfg) {
return cfg->s32val;
}
if (!cfg) return;
cfg = configAddEntry(key);
if (cfg) {
cfg->s32val = defval;
snprintf(cfg->strval, CONFIG_MAX_STR, "%d", defval);
s32 tmp_s32;
f32 tmp_f32;
switch (cfg->type) {
case CFG_S32:
tmp_s32 = atoi(val);
if (cfg->min_s32 < cfg->max_s32) {
tmp_f32 = configClampInt(tmp_s32, cfg->min_s32, cfg->max_s32);
}
*(s32 *)cfg->ptr = tmp_s32;
break;
case CFG_F32:
tmp_f32 = atof(val);
if (cfg->min_f32 < cfg->max_f32) {
tmp_f32 = configClampFloat(tmp_f32, cfg->min_f32, cfg->max_f32);
}
*(f32 *)cfg->ptr = tmp_f32;
break;
case CFG_STR:
strncpy(cfg->ptr, val, cfg->max_str ? cfg->max_str - 1 : 4096);
break;
default:
break;
}
return defval;
}
f32 configGetFloat(const char *key, f32 defval)
static void configSaveEntry(struct configentry *cfg, FILE *f)
{
struct configentry *cfg = configFindEntry(key);
if (cfg) {
return cfg->f32val;
switch (cfg->type) {
case CFG_S32:
if (cfg->min_s32 < cfg->max_s32) {
*(s32 *)cfg->ptr = configClampInt(*(s32 *)cfg->ptr, cfg->min_s32, cfg->max_s32);
}
fprintf(f, "%s=%d\n", cfg->key + cfg->seclen + 1, *(s32 *)cfg->ptr);
break;
case CFG_F32:
if (cfg->min_f32 < cfg->max_f32) {
*(f32 *)cfg->ptr = configClampFloat(*(f32 *)cfg->ptr, cfg->min_f32, cfg->max_f32);
}
fprintf(f, "%s=%f\n", cfg->key + cfg->seclen + 1, *(f32 *)cfg->ptr);
break;
case CFG_STR:
fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, (char *)cfg->ptr);
break;
default:
break;
}
cfg = configAddEntry(key);
if (cfg) {
cfg->f32val = defval;
snprintf(cfg->strval, CONFIG_MAX_STR, "%f", defval);
}
return defval;
}
const char *configGetString(const char *key, const char *defval)
{
struct configentry *cfg = configFindEntry(key);
if (cfg) {
return cfg->strval;
}
cfg = configAddEntry(key);
if (cfg) {
strncpy(cfg->strval, defval, CONFIG_MAX_STR);
}
return defval;
}
s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval)
{
const s32 ret = configGetInt(key, defval);
return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret);
}
f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval)
{
const f32 ret = configGetFloat(key, defval);
return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret);
}
static s32 configCmp(const struct configentry *a, const struct configentry *b) {
char tmpa[CONFIG_MAX_SECNAME + 1];
char tmpb[CONFIG_MAX_SECNAME + 1];
configGetSection(tmpa, a);
configGetSection(tmpb, b);
// compare section names first
const s32 seccmp = strncmp(tmpa, tmpb, CONFIG_MAX_SECNAME);
if (seccmp) {
return seccmp;
}
// same section; sort keys by first letter
return a->key[a->seclen + 1] - b->key[b->seclen + 1];
}
s32 configSave(const char *fname)
@@ -186,9 +182,6 @@ s32 configSave(const char *fname)
return 0;
}
// sort the config so that the sections appear in order
qsort(settings, numSettings, sizeof(*settings), (void *)configCmp);
char tmpSec[CONFIG_MAX_SECNAME + 1] = { 0 };
char curSec[CONFIG_MAX_SECNAME + 1] = { 0 };
configGetSection(curSec, &settings[0]);
@@ -201,7 +194,7 @@ s32 configSave(const char *fname)
fprintf(f, "\n[%s]\n", tmpSec);
strncpy(curSec, tmpSec, CONFIG_MAX_SECNAME);
}
fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, cfg->strval);
configSaveEntry(cfg, f);
}
fsFileClose(f);
+292 -111
View File
@@ -8,10 +8,12 @@
#include "input.h"
#include "video.h"
#include "config.h"
#include "utils.h"
#include "system.h"
#include "debugger.h"
#define MAX_BINDS 4
#define MAX_BIND_STR 256
#define TRIG_THRESHOLD (30 * 256)
#define DEFAULT_DEADZONE 4096
#define DEFAULT_DEADZONE_RY 6144
@@ -20,14 +22,45 @@
#define WHEEL_DN_MASK SDL_BUTTON(VK_MOUSE_WHEEL_DN - VK_MOUSE_BEGIN + 1)
static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
static s32 rumbleSupported[INPUT_MAX_CONTROLLERS];
static u32 binds[MAXCONTROLLERS][CK_TOTAL_COUNT][MAX_BINDS]; // [i][CK_][b] = [VK_]
#define CONTROLLERCFG_DEFAULT { \
.rumbleOn = 0, \
.rumbleScale = 0.5f, \
.axisMap = { \
{ SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY }, \
{ SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY }, \
}, \
.sens = { 1.f, 1.f, 1.f, 1.f }, \
.deadzone = { DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE_RY }, \
.stickCButtons = 0, \
.swapSticks = 1 \
}
static struct controllercfg {
s32 rumbleOn;
f32 rumbleScale;
u32 axisMap[2][2];
f32 sens[4];
s32 deadzone[4];
s32 stickCButtons;
s32 swapSticks;
} padsCfg[INPUT_MAX_CONTROLLERS] = {
CONTROLLERCFG_DEFAULT,
CONTROLLERCFG_DEFAULT,
CONTROLLERCFG_DEFAULT,
CONTROLLERCFG_DEFAULT
};
static u32 binds[MAXCONTROLLERS][CK_TOTAL_COUNT][INPUT_MAX_BINDS];
static char bindStrs[MAXCONTROLLERS][CK_TOTAL_COUNT][MAX_BIND_STR];
static s32 fakeControllers = 0;
static s32 firstController = 0;
static s32 connectedMask = 0;
static s32 mouseEnabled = 1;
static s32 mouseLocked = 0;
static s32 mouseDefaultLocked = 0;
static s32 mouseX, mouseY;
static s32 mouseDX, mouseDY;
static u32 mouseButtons;
@@ -36,26 +69,7 @@ static s32 mouseWheel = 0;
static f32 mouseSensX = 1.5f;
static f32 mouseSensY = 1.5f;
static f32 rumbleScale = 0.5f;
// NOTE: by default this gets inverted for 1.2: "right stick" here means left stick on your controller
static u32 axisMap[2][2] = {
{ SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY },
{ SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY },
};
static f32 stickSens[4] = {
// index == SDL_CONTROLLER_AXIS_*
1.f, 1.f, 1.f, 1.f
};
static s32 deadzone[4] = {
// index == SDL_CONTROLLER_AXIS_*
DEFAULT_DEADZONE, DEFAULT_DEADZONE,
DEFAULT_DEADZONE, DEFAULT_DEADZONE_RY,
};
static s32 stickCButtons = 1;
static s32 lastKey = 0;
static const char *ckNames[CK_TOTAL_COUNT] = {
"R_CBUTTONS",
@@ -182,10 +196,13 @@ void inputSetDefaultKeyBinds(void)
{ CK_START, SDL_CONTROLLER_BUTTON_START },
{ CK_C_D, SDL_CONTROLLER_BUTTON_DPAD_DOWN },
{ CK_C_U, SDL_CONTROLLER_BUTTON_DPAD_UP },
{ CK_8000, SDL_CONTROLLER_BUTTON_LEFTSTICK },
{ CK_C_R, SDL_CONTROLLER_BUTTON_DPAD_RIGHT },
{ CK_C_L, SDL_CONTROLLER_BUTTON_DPAD_LEFT },
{ CK_8000, SDL_CONTROLLER_BUTTON_LEFTSTICK },
};
memset(binds, 0, sizeof(binds));
for (u32 i = 0; i < sizeof(kbbinds) / sizeof(kbbinds[0]); ++i) {
for (s32 j = 1; j < 3; ++j) {
if (kbbinds[i][j]) {
@@ -205,15 +222,15 @@ static inline void inputInitController(const s32 cidx)
{
#if SDL_VERSION_ATLEAST(2, 0, 18)
// SDL_GameControllerHasRumble() appeared in 2.0.18 even though SDL_GameControllerRumble() is in 2.0.9
rumbleSupported[cidx] = SDL_GameControllerHasRumble(pads[cidx]);
padsCfg[cidx].rumbleOn = SDL_GameControllerHasRumble(pads[cidx]);
#else
// assume that all joysticks with haptic feedback support will support rumble
rumbleSupported[cidx] = SDL_JoystickIsHaptic(SDL_GameControllerGetJoystick(pads[cidx]));
if (!rumbleSupported[cidx]) {
padsCfg[cidx].rumbleOn = SDL_JoystickIsHaptic(SDL_GameControllerGetJoystick(pads[cidx]));
if (!padsCfg[cidx].rumbleOn) {
// at least on Windows some controllers will report no haptics, but rumble will still function
// just assume it's supported if the controller is of known type
const SDL_GameControllerType ctype = SDL_GameControllerGetType(pads[cidx]);
rumbleSupported[cidx] = ctype && (ctype != SDL_CONTROLLER_TYPE_VIRTUAL);
padsCfg[cidx].rumbleOn = ctype && (ctype != SDL_CONTROLLER_TYPE_VIRTUAL);
}
#endif
@@ -227,17 +244,29 @@ static inline void inputCloseController(const s32 cidx)
{
SDL_GameControllerClose(pads[cidx]);
pads[cidx] = NULL;
rumbleSupported[cidx] = 0;
padsCfg[cidx].rumbleOn = 0;
if (cidx) {
connectedMask &= ~(1 << cidx);
}
}
static inline s32 inputControllerGetIndex(SDL_GameController *ctrl) {
if (ctrl) {
for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) {
if (pads[i] == ctrl) {
return i;
}
}
}
return -1;
}
static int inputEventFilter(void *data, SDL_Event *event)
{
switch (event->type) {
case SDL_CONTROLLERDEVICEADDED:
for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) {
for (s32 i = firstController; i < INPUT_MAX_CONTROLLERS; ++i) {
if (!pads[i]) {
pads[i] = SDL_GameControllerOpen(event->cdevice.which);
if (pads[i]) {
@@ -250,19 +279,54 @@ static int inputEventFilter(void *data, SDL_Event *event)
case SDL_CONTROLLERDEVICEREMOVED: {
SDL_GameController *ctrl = SDL_GameControllerFromInstanceID(event->cdevice.which);
if (ctrl) {
for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) {
if (pads[i] == ctrl) {
inputCloseController(i);
break;
}
}
const s32 idx = inputControllerGetIndex(ctrl);
if (idx >= 0) {
inputCloseController(idx);
}
break;
}
case SDL_MOUSEWHEEL:
mouseWheel = event->wheel.y;
if (!lastKey && mouseWheel) {
lastKey = (mouseWheel < 0) + VK_MOUSE_WHEEL_UP;
}
break;
case SDL_MOUSEBUTTONDOWN:
if (!lastKey) {
lastKey = VK_MOUSE_BEGIN - 1 + event->button.button;
}
break;
case SDL_KEYDOWN:
if (!lastKey) {
lastKey = VK_KEYBOARD_BEGIN + event->key.keysym.scancode;
}
break;
case SDL_CONTROLLERBUTTONDOWN:
if (!lastKey) {
lastKey = VK_JOY1_BEGIN + event->cbutton.button;
SDL_GameController *ctrl = SDL_GameControllerFromInstanceID(event->cdevice.which);
const s32 idx = inputControllerGetIndex(ctrl);
if (idx >= 0) {
lastKey += idx * INPUT_MAX_CONTROLLER_BUTTONS;
}
}
break;
case SDL_CONTROLLERAXISMOTION:
if (!lastKey) {
if (event->caxis.axis >= SDL_CONTROLLER_AXIS_TRIGGERLEFT && event->caxis.value > TRIG_THRESHOLD) {
lastKey = VK_JOY1_LTRIG + (event->caxis.axis - SDL_CONTROLLER_AXIS_TRIGGERLEFT);
SDL_GameController *ctrl = SDL_GameControllerFromInstanceID(event->cdevice.which);
const s32 idx = inputControllerGetIndex(ctrl);
if (idx >= 0) {
lastKey += idx * INPUT_MAX_CONTROLLER_BUTTONS;
}
}
}
break;
default:
@@ -338,34 +402,36 @@ static inline void inputInitKeyNames(void)
}
}
static inline void inputSaveBinds(void)
void inputSaveBinds(void)
{
char bindstr[256];
char keyname[256];
char secname[] = "Input.Player1.Binds";
bindstr[sizeof(bindstr) - 1] = '\0';
char *bindstr;
for (s32 i = 0; i < MAXCONTROLLERS; ++i) {
secname[12] = '1' + i;
for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) {
snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck));
bindstr = bindStrs[i][ck];
bindstr[0] = '\0';
for (s32 b = 0; b < MAX_BINDS; ++b) {
for (s32 b = 0; b < INPUT_MAX_BINDS; ++b) {
if (binds[i][ck][b]) {
if (b) {
strncat(bindstr, ", ", sizeof(bindstr) - 1);
strncat(bindstr, ", ", MAX_BIND_STR - 1);
}
strncat(bindstr, inputGetKeyName(binds[i][ck][b]), sizeof(bindstr) - 1);
strncat(bindstr, inputGetKeyName(binds[i][ck][b]), MAX_BIND_STR - 1);
}
}
configSetString(keyname, bindstr[0] ? bindstr : "NONE");
if (!bindstr[0]) {
strcpy(bindstr, "NONE");
}
}
}
}
static inline void inputParseBindString(const s32 ctrl, const u32 ck, char *bindstr)
{
if (!bindstr[0]) {
// empty string, keep defaults
return;
}
// unbind all first
memset(binds[ctrl][ck], 0, sizeof(binds[ctrl][ck]));
@@ -388,29 +454,13 @@ static inline void inputParseBindString(const s32 ctrl, const u32 ck, char *bind
static inline void inputLoadBinds(void)
{
char secname[] = "Input.Player1.Binds";
char keyname[256];
char bindstr[256];
for (s32 i = 0; i < MAXCONTROLLERS; ++i) {
secname[12] = '1' + i;
for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) {
snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck));
const char *cfgstr = configGetString(keyname, "");
if (cfgstr[0]) {
strncpy(bindstr, cfgstr, sizeof(bindstr) - 1);
bindstr[sizeof(bindstr) - 1] = '\0';
inputParseBindString(i, ck, bindstr);
}
inputParseBindString(i, ck, bindStrs[i][ck]);
}
}
}
void inputSaveConfig(void)
{
inputSaveBinds();
}
s32 inputInit(void)
{
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
@@ -423,11 +473,9 @@ s32 inputInit(void)
connectedMask = 1; // always report first controller as connected
// if this is set to 1, keyboard will count as a separate controller on its own,
// if firstController is set to 1, keyboard will count as a separate controller on its own,
// so the first connected gamepad will go to player 2 instead of player 1
const s32 cstart = configGetInt("Input.FirstGamepadNum", 0);
for (s32 jidx = 0, cidx = cstart; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) {
for (s32 jidx = 0, cidx = firstController; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) {
if (SDL_IsGameController(jidx)) {
pads[cidx] = SDL_GameControllerOpen(jidx);
if (pads[cidx]) {
@@ -444,33 +492,15 @@ s32 inputInit(void)
inputSetDefaultKeyBinds();
mouseEnabled = configGetInt("Input.MouseEnabled", 1);
mouseSensX = configGetFloat("Input.MouseSpeedX", 1.5f);
mouseSensY = configGetFloat("Input.MouseSpeedY", 1.5f);
inputLockMouse(mouseDefaultLocked);
rumbleScale = configGetFloat("Input.RumbleScale", 0.5f);
deadzone[0] = configGetInt("Input.LStickDeadzoneX", DEFAULT_DEADZONE);
deadzone[1] = configGetInt("Input.LStickDeadzoneY", DEFAULT_DEADZONE);
deadzone[2] = configGetInt("Input.RStickDeadzoneX", DEFAULT_DEADZONE);
deadzone[3] = configGetInt("Input.RStickDeadzoneY", DEFAULT_DEADZONE_RY);
stickSens[0] = configGetFloat("Input.LStickScaleX", 1.f);
stickSens[1] = configGetFloat("Input.LStickScaleY", 1.f);
stickSens[2] = configGetFloat("Input.RStickScaleX", 1.f);
stickSens[3] = configGetFloat("Input.RStickScaleY", 1.f);
stickCButtons = configGetInt("Input.StickCButtons", 0);
if (configGetInt("Input.SwapSticks", 1)) {
// invert axis map
axisMap[0][0] = SDL_CONTROLLER_AXIS_RIGHTX;
axisMap[0][1] = SDL_CONTROLLER_AXIS_RIGHTY;
axisMap[1][0] = SDL_CONTROLLER_AXIS_LEFTX;
axisMap[1][1] = SDL_CONTROLLER_AXIS_LEFTY;
// update the axis maps
// NOTE: by default sticks get swapped for 1.2: "right stick" here means left stick on your controller
for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) {
inputControllerSetSticksSwapped(i, padsCfg[i].swapSticks);
}
const s32 overrideMask = (1 << configGetInt("Input.FakeGamepads", 0)) - 1;
const s32 overrideMask = (1 << fakeControllers) - 1;
if (overrideMask) {
connectedMask = overrideMask;
}
@@ -482,7 +512,7 @@ s32 inputInit(void)
static inline s32 inputBindPressed(const s32 idx, const u32 ck)
{
for (s32 i = 0; i < MAX_BINDS; ++i) {
for (s32 i = 0; i < INPUT_MAX_BINDS; ++i) {
if (binds[idx][ck][i]) {
if (inputKeyPressed(binds[idx][ck][i])) {
return 1;
@@ -533,15 +563,17 @@ s32 inputReadController(s32 idx, OSContPad *npad)
return 0;
}
s32 leftX = SDL_GameControllerGetAxis(pads[idx], axisMap[0][0]);
s32 leftY = SDL_GameControllerGetAxis(pads[idx], axisMap[0][1]);
s32 rightX = SDL_GameControllerGetAxis(pads[idx], axisMap[1][0]);
s32 rightY = SDL_GameControllerGetAxis(pads[idx], axisMap[1][1]);
const struct controllercfg *cfg = &padsCfg[idx];
leftX = inputAxisScale(leftX, deadzone[axisMap[0][0]], stickSens[axisMap[0][0]]);
leftY = inputAxisScale(leftY, deadzone[axisMap[0][1]], stickSens[axisMap[0][1]]);
rightX = inputAxisScale(rightX, deadzone[axisMap[1][0]], stickSens[axisMap[1][0]]);
rightY = inputAxisScale(rightY, deadzone[axisMap[1][1]], stickSens[axisMap[1][1]]);
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]);
s32 rightY = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[1][1]);
leftX = inputAxisScale(leftX, cfg->deadzone[cfg->axisMap[0][0]], cfg->sens[cfg->axisMap[0][0]]);
leftY = inputAxisScale(leftY, cfg->deadzone[cfg->axisMap[0][1]], cfg->sens[cfg->axisMap[0][1]]);
rightX = inputAxisScale(rightX, cfg->deadzone[cfg->axisMap[1][0]], cfg->sens[cfg->axisMap[1][0]]);
rightY = inputAxisScale(rightY, cfg->deadzone[cfg->axisMap[1][1]], cfg->sens[cfg->axisMap[1][1]]);
if (!npad->stick_x && leftX) {
npad->stick_x = leftX / 0x100;
@@ -552,7 +584,7 @@ s32 inputReadController(s32 idx, OSContPad *npad)
npad->stick_y = (stickY == 128) ? 127 : stickY;
}
if (stickCButtons) {
if (cfg->stickCButtons) {
// rstick emulates C buttons
if (rightX < -0x4000) npad->button |= L_CBUTTONS;
if (rightX > +0x4000) npad->button |= R_CBUTTONS;
@@ -636,7 +668,7 @@ s32 inputRumbleSupported(s32 idx)
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS) {
return 0;
}
return rumbleSupported[idx];
return padsCfg[idx].rumbleOn;
}
void inputRumble(s32 idx, f32 strength, f32 time)
@@ -645,8 +677,8 @@ void inputRumble(s32 idx, f32 strength, f32 time)
return;
}
if (rumbleSupported[idx]) {
strength *= rumbleScale;
if (padsCfg[idx].rumbleOn) {
strength *= padsCfg[idx].rumbleScale;
if (strength <= 0.f) {
strength = 0.f;
time = 0.f;
@@ -658,33 +690,101 @@ void inputRumble(s32 idx, f32 strength, f32 time)
}
}
f32 inputRumbleGetStrength(s32 cidx)
{
return padsCfg[cidx].rumbleScale;
}
void inputRumbleSetStrength(s32 cidx, f32 val)
{
padsCfg[cidx].rumbleScale = val;
}
s32 inputControllerMask(void)
{
return connectedMask;
}
s32 inputControllerGetSticksSwapped(s32 cidx)
{
return padsCfg[cidx].swapSticks;
}
void inputControllerSetSticksSwapped(s32 cidx, s32 swapped)
{
padsCfg[cidx].swapSticks = swapped;
if (swapped) {
padsCfg[cidx].axisMap[0][0] = SDL_CONTROLLER_AXIS_RIGHTX;
padsCfg[cidx].axisMap[0][1] = SDL_CONTROLLER_AXIS_RIGHTY;
padsCfg[cidx].axisMap[1][0] = SDL_CONTROLLER_AXIS_LEFTX;
padsCfg[cidx].axisMap[1][1] = SDL_CONTROLLER_AXIS_LEFTY;
} else {
padsCfg[cidx].axisMap[0][0] = SDL_CONTROLLER_AXIS_LEFTX;
padsCfg[cidx].axisMap[0][1] = SDL_CONTROLLER_AXIS_LEFTY;
padsCfg[cidx].axisMap[1][0] = SDL_CONTROLLER_AXIS_RIGHTX;
padsCfg[cidx].axisMap[1][1] = SDL_CONTROLLER_AXIS_RIGHTY;
}
}
s32 inputControllerGetDualAnalog(s32 cidx)
{
return !padsCfg[cidx].stickCButtons;
}
void inputControllerSetDualAnalog(s32 cidx, s32 enable)
{
padsCfg[cidx].stickCButtons = !enable;
}
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis)
{
return padsCfg[cidx].sens[stick * 2 + axis];
}
void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value)
{
padsCfg[cidx].sens[stick * 2 + axis] = value;
}
f32 inputControllerGetAxisDeadzone(s32 cidx, s32 stick, s32 axis)
{
return (f32)padsCfg[cidx].deadzone[stick * 2 + axis] / 32767.f;
}
void inputControllerSetAxisDeadzone(s32 cidx, s32 stick, s32 axis, f32 value)
{
padsCfg[cidx].deadzone[stick * 2 + axis] = value * 32767.f;
}
void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk)
{
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || bind >= MAX_BINDS || ck >= CK_TOTAL_COUNT) {
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || bind >= INPUT_MAX_BINDS || ck >= CK_TOTAL_COUNT) {
return;
}
if (bind < 0) {
for (s32 i = 0; i < MAX_BINDS; ++i) {
for (s32 i = 0; i < INPUT_MAX_BINDS; ++i) {
if (binds[idx][ck][i] == 0) {
bind = i;
break;
}
}
if (bind < 0) {
bind = MAX_BINDS - 1; // just overwrite last
bind = INPUT_MAX_BINDS - 1; // just overwrite last
}
}
binds[idx][ck][bind] = vk;
}
const u32 *inputKeyGetBinds(s32 idx, u32 ck)
{
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || ck >= CK_TOTAL_COUNT) {
return NULL;
}
return binds[idx][ck];
}
s32 inputKeyPressed(u32 vk)
{
if (vk >= VK_KEYBOARD_BEGIN && vk < VK_MOUSE_BEGIN) {
@@ -778,6 +878,44 @@ void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy)
if (dy) *dy = mdy;
}
void inputMouseGetSpeed(f32 *x, f32 *y)
{
*x = mouseSensX;
*y = mouseSensY;
}
void inputMouseSetSpeed(f32 x, f32 y)
{
mouseSensX = x;
mouseSensY = y;
}
s32 inputMouseIsEnabled(void)
{
return mouseEnabled;
}
void inputMouseEnable(s32 enabled)
{
mouseEnabled = !!enabled;
if (!mouseEnabled && mouseLocked) {
inputLockMouse(0);
}
}
s32 inputGetMouseDefaultLocked(void)
{
return mouseDefaultLocked;
}
void inputSetMouseDefaultLocked(s32 defaultLocked)
{
mouseDefaultLocked = !!defaultLocked;
if (mouseEnabled) {
inputLockMouse(mouseDefaultLocked);
}
}
const char *inputGetContKeyName(u32 ck)
{
if (ck >= CK_TOTAL_COUNT) {
@@ -841,3 +979,46 @@ s32 inputGetKeyByName(const char *name)
return -1;
}
void inputClearLastKey(void)
{
lastKey = 0;
}
s32 inputGetLastKey(void)
{
return lastKey;
}
PD_CONSTRUCTOR static void inputConfigInit(void)
{
configRegisterInt("Input.MouseEnabled", &mouseEnabled, 0, 1);
configRegisterInt("Input.MouseDefaultLocked", &mouseDefaultLocked, 0, 1);
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -10.f, 10.f);
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.f);
configRegisterInt("Input.FakeGamepads", &fakeControllers, 0, 4);
configRegisterInt("Input.FirstGamepadNum", &firstController, 0, 3);
char secname[] = "Input.Player1.Binds";
char keyname[256] = { 0 };
for (s32 c = 0; c < MAXCONTROLLERS; ++c) {
secname[12] = '1' + c;
secname[13] = '\0';
configRegisterFloat(strFmt("%s.RumbleScale", secname), &padsCfg[c].rumbleScale, 0.f, 1.f);
configRegisterInt(strFmt("%s.LStickDeadzoneX", secname), &padsCfg[c].deadzone[0], 0, 32767);
configRegisterInt(strFmt("%s.LStickDeadzoneY", secname), &padsCfg[c].deadzone[1], 0, 32767);
configRegisterInt(strFmt("%s.RStickDeadzoneX", secname), &padsCfg[c].deadzone[2], 0, 32767);
configRegisterInt(strFmt("%s.RStickDeadzoneY", secname), &padsCfg[c].deadzone[3], 0, 32767);
configRegisterFloat(strFmt("%s.LStickScaleX", secname), &padsCfg[c].sens[0], -10.f, 10.f);
configRegisterFloat(strFmt("%s.LStickScaleY", secname), &padsCfg[c].sens[1], -10.f, 10.f);
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.SwapSticks", secname), &padsCfg[c].swapSticks, 0, 1);
secname[13] = '.';
for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) {
snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck));
configRegisterString(keyname, bindStrs[c][ck], MAX_BIND_STR);
}
}
}
+38 -22
View File
@@ -16,8 +16,10 @@
#include "config.h"
#include "mod.h"
#include "system.h"
#include "utils.h"
u32 g_OsMemSize = 0;
s32 g_OsMemSizeMb = 16;
u8 g_Is4Mb = 0;
s8 g_Resetting = false;
OSSched g_Sched;
@@ -56,34 +58,30 @@ void bootCreateSched(void)
}
}
static void cleanup(void)
static void gameInit(void)
{
sysLogPrintf(LOG_NOTE, "shutdown");
inputSaveConfig();
configSave(CONFIG_PATH);
crashShutdown();
// TODO: actually shut down all subsystems
}
osMemSize = g_OsMemSizeMb * 1024 * 1024;
static void gameLoadConfig(void)
{
osMemSize = configGetIntClamped("Game.MemorySize", 16, 4, 2048) * 1024 * 1024;
g_PlayerCrosshairSway = configGetFloatClamped("Game.CrosshairSway", g_PlayerCrosshairSway, 0.f, 10.f);
g_PlayerDefaultFovY = configGetFloatClamped("Game.FovY", g_PlayerDefaultFovY, 5.f, 175.f);
g_PlayerMouseAimMode = configGetIntClamped("Game.MouseAimMode", g_PlayerMouseAimMode, 0, 1);
g_PlayerMouseAimSpeedX = configGetFloatClamped("Game.MouseAimSpeedX", g_PlayerMouseAimSpeedX, 0.f, 10.f);
g_PlayerMouseAimSpeedY = configGetFloatClamped("Game.MouseAimSpeedY", g_PlayerMouseAimSpeedY, 0.f, 10.f);
g_PlayerFovAffectsZoom = configGetIntClamped("Game.FovAffectsZoom", g_PlayerFovAffectsZoom, 0, 1);
g_PlayerFovZoomMultiplier = g_PlayerFovAffectsZoom ? g_PlayerDefaultFovY / 60.0f : 1.0f;
g_PlayerClassicCrouch = configGetIntClamped("Game.ClassicCrouch", 0, 0, 1);
g_ViShakeIntensityMult = configGetFloatClamped("Game.ScreenShakeIntensity", 1.f, 0.f, 100.f);
const s32 center = configGetIntClamped("Game.CenterHUD", 0, 0, 1);
if (center) {
for (s32 i = 0; i < MAX_PLAYERS; ++i) {
struct extplayerconfig *cfg = g_PlayerExtCfg + i;
cfg->fovzoommult = cfg->fovzoom ? cfg->fovy / 60.0f : 1.0f;
}
if (g_HudCenter) {
g_HudAlignModeL = G_ASPECT_CENTER_EXT;
g_HudAlignModeR = G_ASPECT_CENTER_EXT;
}
}
static void cleanup(void)
{
sysLogPrintf(LOG_NOTE, "shutdown");
inputSaveBinds();
configSave(CONFIG_PATH);
crashShutdown();
// TODO: actually shut down all subsystems
}
int main(int argc, const char **argv)
{
sysInitArgs(argc, argv);
@@ -101,7 +99,7 @@ int main(int argc, const char **argv)
romdataInit();
debuggerInit();
gameLoadConfig();
gameInit();
if (fsGetModDir()) {
modConfigLoad(MOD_CONFIG_FNAME);
@@ -132,3 +130,21 @@ int main(int argc, const char **argv)
return 0;
}
PD_CONSTRUCTOR static void gameConfigInit(void)
{
configRegisterInt("Game.MemorySize", &g_OsMemSizeMb, 4, 2048);
configRegisterInt("Game.CenterHUD", &g_HudCenter, 0, 1);
configRegisterFloat("Game.ScreenShakeIntensity", &g_ViShakeIntensityMult, 0.f, 10.f);
for (s32 j = 0; j < MAX_PLAYERS; ++j) {
const s32 i = j + 1;
configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f);
configRegisterInt(strFmt("Game.Player%d.FovAffectsZoom", i), &g_PlayerExtCfg[j].fovzoom, 0, 1);
configRegisterInt(strFmt("Game.Player%d.MouseAimMode", i), &g_PlayerExtCfg[j].mouseaimmode, 0, 1);
configRegisterFloat(strFmt("Game.Player%d.MouseAimSpeedX", i), &g_PlayerExtCfg[j].mouseaimspeedx, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.MouseAimSpeedY", i), &g_PlayerExtCfg[j].mouseaimspeedy, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.RadialMenuSpeed", i), &g_PlayerExtCfg[j].radialmenuspeed, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f);
configRegisterInt(strFmt("Game.Player%d.ClassicCrouch", i), &g_PlayerExtCfg[j].classiccrouch, 0, 1);
}
}
File diff suppressed because it is too large. Load diff
+8 -6
View File
@@ -103,7 +103,8 @@ OSScMsg g_SchedRspMsg = {OS_SC_RSP_MSG};
bool g_SchedIsFirstTask = true;
s32 g_PrevFrameFb = -1;
s32 g_PrevFrameCapTimer = -1;
s32 g_BlurFb = -1;
s32 g_BlurFbCapTimer = -1;
void schedSetCrashEnable1(bool enable)
{
@@ -181,6 +182,7 @@ void osCreateScheduler(OSSched *sc, OSThread *thread, u8 mode, u32 numFields)
schedInitCrashLastRendered();
g_PrevFrameFb = videoCreateFramebuffer(0, 0, false, true);
g_BlurFb = videoCreateFramebuffer(0, 0, false, true);
}
void osScAddClient(OSSched *sc, OSScClient *c, OSMesgQueue *msgQ, bool is30fps)
@@ -391,11 +393,11 @@ void schedConsiderScreenshot(void)
g_MenuData.screenshottimer = 0;
}
if (g_PrevFrameCapTimer == 0) {
videoCopyFramebuffer(g_PrevFrameFb, 0, -1, -1);
g_PrevFrameCapTimer = -1;
} else if (g_PrevFrameCapTimer > 0) {
--g_PrevFrameCapTimer;
if (g_BlurFbCapTimer == 0) {
videoCopyFramebuffer(g_BlurFb, 0, -1, -1);
g_BlurFbCapTimer = -1;
} else if (g_BlurFbCapTimer > 0) {
--g_BlurFbCapTimer;
}
if (g_MenuData.screenshottimer >= 2) {
+15 -1
View File
@@ -1063,7 +1063,21 @@ void preprocessFont(u8 *data, u32 size)
PD_SWAP_VAL(fnt->kerning[i]);
}
for (s32 i = 0; i < ARRAYCOUNT(fnt->chars); ++i) {
s32 numchars = 94;
#if PAL
// PAL has more characters in these fonts
extern u8 *_fonthandelgothicsmSegmentRomStart;
extern u8 *_fonthandelgothicxsSegmentRomStart;
extern u8 *_fonthandelgothicmdSegmentRomStart;
if (data == _fonthandelgothicsmSegmentRomStart
|| data == _fonthandelgothicxsSegmentRomStart
|| data == _fonthandelgothicmdSegmentRomStart) {
numchars = 135;
}
#endif
for (s32 i = 0; i < numchars; ++i) {
PD_SWAP_VAL(fnt->chars[i].kerningindex);
PD_SWAP_PTR(fnt->chars[i].pixeldata);
}
+27 -9
View File
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <PR/ultratypes.h>
@@ -25,21 +26,23 @@
#define ROMDATA_ROM_NAME "pd." VERSION_ROMID ".z64"
#define ROMDATA_ROM_SIZE 33554432
#define ROMDATA_ROM_HASH // TODO
#if VERSION == VERSION_NTSC_FINAL
#define ROMDATA_ROM_TITLE "Perfect Dark"
#define ROMDATA_ROM_ID "NPDE"
#define ROMDATA_ROM_DESC "NTSC v1.1"
#define ROMDATA_FILES_OFS 0x28080
#define ROMDATA_DATA_OFS 0x39850
#elif VERSION == VERSION_PAL_FINAL
#define ROMDATA_ROM_TITLE "Perfect Dark"
#define ROMDATA_ROM_ID "NPDP"
#define ROMDATA_ROM_DESC "PAL"
#define ROMDATA_FILES_OFS 0x28910
#define ROMDATA_DATA_OFS 0x39850
#elif VERSION == VERSION_JPN_FINAL
#define ROMDATA_ROM_TITLE "PERFECT DARK"
#define ROMDATA_ROM_ID "NPDJ"
#define ROMDATA_ROM_DESC "JPN"
#define ROMDATA_FILES_OFS 0x28800
#define ROMDATA_DATA_OFS 0x39850
#else
@@ -151,6 +154,19 @@ static preprocessfunc filePreprocFuncs[] = {
/* LOADTYPE_GUN */ preprocessGunFile,
};
static inline void romdataWrongRomError(const char *fmt, ...)
{
char reason[1024];
reason[0] = '\0';
va_list args;
va_start(args, fmt);
vsnprintf(reason, sizeof(reason), fmt, args);
va_end(args);
sysFatalError("Wrong ROM file.\n%s\nEnsure that you have the correct " ROMDATA_ROM_DESC " ROM in z64 format.", reason);
}
static inline void romdataLoadRom(void)
{
sysLogPrintf(LOG_NOTE, "ROM file: %s", romName);
@@ -161,27 +177,29 @@ static inline void romdataLoadRom(void)
sysFatalError("Could not open ROM file %s.\nEnsure that it is in the %s directory.", romName, fsFullPath(""));
}
// zips are not guaranteed to start with PK, but might as well at least try
if (g_RomFileSize > 2 && (!memcmp(g_RomFile, "PK", 2) || !memcmp(g_RomFile, "Rar", 3) || !memcmp(g_RomFile, "7z", 2))) {
romdataWrongRomError("Your ROM is in an archive file. Please extract it.");
}
if (g_RomFileSize != ROMDATA_ROM_SIZE) {
sysFatalError("Wrong ROM file size.\nExpected: %u\nGot: %u", ROMDATA_ROM_SIZE, g_RomFileSize);
romdataWrongRomError("ROM size does not match: expected: %u, got: %u.", ROMDATA_ROM_SIZE, g_RomFileSize);
}
if (memcmp(g_RomFile + 0x3b, ROMDATA_ROM_ID, 4) || memcmp(g_RomFile + 0x20, ROMDATA_ROM_TITLE, sizeof(ROMDATA_ROM_TITLE) - 1)) {
sysFatalError("Wrong ROM file.\nEnsure that it is the correct NTSC v1.1 ROM in z64 format.");
romdataWrongRomError("ROM header does not match.");
}
// inflate the compressed data segment since that's where some useful stuff is
u8 *zipped = g_RomFile + ROMDATA_DATA_OFS;
if (!zipped) {
sysFatalError("Data segment not found.");
}
if (!rzipIs1173(zipped)) {
sysFatalError("Data segment is not 1173-compressed.");
romdataWrongRomError("Data segment is not 1173-compressed.");
}
const u32 dataSegLen = ((u32)zipped[2] << 16) | ((u32)zipped[3] << 8) | (u32)zipped[4];
if (dataSegLen < ROMDATA_FILES_OFS) {
sysFatalError("Data segment too small (%u), need at least %u.", dataSegLen, ROMDATA_FILES_OFS);
romdataWrongRomError("Data segment too small (%u), need at least %u.", dataSegLen, ROMDATA_FILES_OFS);
}
u8 *dataSeg = sysMemAlloc(dataSegLen);
@@ -291,7 +309,7 @@ static inline void romdataInitFiles(void)
if (!g_RomFile) {
// no ROM; try to load the file name list from disk
if (!romdataLoadExternalFileList()) {
sysFatalError("No ROM or external file for filename table.");
sysFatalError("No ROM file or external filename table found.");
}
return;
}
+62 -21
View File
@@ -4,6 +4,7 @@
#include <string.h>
#include <PR/ultratypes.h>
#include <PR/gbi.h>
#include "platform.h"
#include "config.h"
#include "video.h"
@@ -16,40 +17,37 @@ static struct GfxRenderingAPI *renderingAPI;
static bool initDone = false;
static s32 vidWidth = 640;
static s32 vidHeight = 480;
static s32 vidFramebuffers = true;
static s32 vidFullscreen = false;
static s32 vidVsync = 1;
static s32 vidMSAA = 1;
static s32 vidFramerateLimit = 0;
static s32 texFilter = FILTER_LINEAR;
static s32 texFilter2D = true;
static u32 dlcount = 0;
static u32 frames = 0;
static u32 framesPerSec = 0;
static f64 startTime, endTime, fpsTime;
static u32 texFilter2D = 1;
s32 videoInit(void)
{
wmAPI = &gfx_sdl;
renderingAPI = &gfx_opengl_api;
gfx_current_native_viewport.width = 320;
gfx_current_native_viewport.height = 240;
gfx_framebuffers_enabled = (bool)vidFramebuffers;
gfx_msaa_level = vidMSAA;
const s32 w = configGetInt("Video.DefaultWidth", 640);
const s32 h = configGetInt("Video.DefaultHeight", 480);
const bool fs = configGetInt("Video.DefaultFullscreen", false);
gfx_init(wmAPI, renderingAPI, "PD", vidFullscreen, vidWidth, vidHeight, 100, 100);
gfx_framebuffers_enabled = (bool)configGetIntClamped("Video.FramebufferEffects", 1, 0, 1);
gfx_msaa_level = configGetInt("Video.MSAA", 0);
if (gfx_msaa_level < 1 || gfx_msaa_level > 16) {
gfx_msaa_level = 1;
}
gfx_init(wmAPI, renderingAPI, "PD", fs, w, h, 100, 100);
wmAPI->set_swap_interval(configGetInt("Video.VSync", 1));
wmAPI->set_target_fps(configGetInt("Video.FramerateLimit", 0)); // disabled because vsync is on
u32 filter = configGetInt("Video.TextureFilter", FILTER_LINEAR);
if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT;
renderingAPI->set_texture_filter((enum FilteringMode)filter);
texFilter2D = configGetIntClamped("Video.TextureFilter2D", 1, 0, 1);
wmAPI->set_swap_interval(vidVsync);
wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on
renderingAPI->set_texture_filter((enum FilteringMode)texFilter);
initDone = true;
return 0;
@@ -134,6 +132,11 @@ s32 videoGetHeight(void)
return gfx_current_dimensions.height;
}
s32 videoGetFullscreen(void)
{
return vidFullscreen;
}
f32 videoGetAspect(void)
{
return gfx_current_dimensions.aspect_ratio;
@@ -144,12 +147,37 @@ u32 videoGetTextureFilter2D(void)
return texFilter2D;
}
u32 videoGetTextureFilter(void)
{
return texFilter;
}
void videoSetWindowOffset(s32 x, s32 y)
{
gfx_current_game_window_viewport.x = x;
gfx_current_game_window_viewport.y = y;
}
void videoSetFullscreen(s32 fs)
{
if (fs != vidFullscreen) {
vidFullscreen = !!fs;
wmAPI->set_fullscreen(vidFullscreen);
}
}
void videoSetTextureFilter(u32 filter)
{
if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT;
texFilter = filter;
renderingAPI->set_texture_filter((enum FilteringMode)filter);
}
void videoSetTextureFilter2D(u32 filter)
{
texFilter2D = !!filter;
}
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
{
return gfx_create_framebuffer(w, h, upscale, autoresize);
@@ -190,3 +218,16 @@ void videoFreeCachedTexture(const void *texptr)
{
gfx_texture_cache_delete(texptr);
}
PD_CONSTRUCTOR static void videoConfigInit(void)
{
configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1);
configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767);
configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767);
configRegisterInt("Video.VSync", &vidVsync, -1, 10);
configRegisterInt("Video.FramebufferEffects", &vidFramebuffers, 0, 1);
configRegisterInt("Video.FramerateLimit", &vidFramerateLimit, 0, 10000);
configRegisterInt("Video.MSAA", &vidMSAA, 1, 16);
configRegisterInt("Video.TextureFilter", &texFilter, 0, 2);
configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1);
}
+5 -1
View File
@@ -364,7 +364,11 @@ void amApply(s32 slot)
bgunEquipWeapon2(HAND_RIGHT, weaponnum);
}
if (bgunGetWeaponNum(HAND_LEFT) != WEAPON_NONE) {
// don't unequip detonator
// if we already have it equipped
if (weaponnum == WEAPON_REMOTEMINE) {
bgunEquipWeapon2(HAND_LEFT, weaponnum);
} else if (bgunGetWeaponNum(HAND_LEFT) != WEAPON_NONE) {
bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE);
}
}
+15 -10
View File
@@ -13,6 +13,7 @@
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "game/player.h"
#include "input.h"
#endif
@@ -48,10 +49,14 @@ void amTick(void)
s8 gotonextscreen = false;
s8 cstickx = joyGetStickXOnSample(j, contpadnum);
s8 csticky = joyGetStickYOnSample(j, contpadnum);
s8 crstickx = joyGetRStickXOnSample(j, contpadnum);
s8 crsticky = joyGetRStickYOnSample(j, contpadnum);
#ifdef AVOID_UB
// if cstickx is -128, it will get negated and stored into absstickx, negating it again if it's 8 bit
s32 absstickx;
s32 abssticky;
#else
s8 absstickx;
s8 abssticky;
#endif
u32 buttonsstate = joyGetButtonsOnSample(j, contpadnum, 0xffffffff);
u32 buttonspressed = joyGetButtonsPressedOnSample(j, contpadnum, 0xffffffff);
bool stickpushed = false;
@@ -69,29 +74,29 @@ void amTick(void)
g_AmMenus[g_AmIndex].allbots = false;
#ifndef PLATFORM_N64
s32 newstickx = (s32)cstickx;
s32 newsticky = (s32)csticky;
if (j == 0 && g_Vars.currentplayernum == 0 && inputMouseIsLocked()) {
f32 mdx, mdy;
struct activemenu *am = &g_AmMenus[g_AmIndex];
inputMouseGetAbsScaledDelta(&mdx, &mdy);
if (mdx || mdy) {
am->mousex += mdx * 4.f;
am->mousey += mdy * 4.f;
am->mousex += mdx * PLAYER_EXTCFG().radialmenuspeed;
am->mousey += mdy * PLAYER_EXTCFG().radialmenuspeed;
am->mousex = (am->mousex > 127.f) ? 127.f : (am->mousex < -128.f) ? -128.f : am->mousex;
am->mousey = (am->mousey > 127.f) ? 127.f : (am->mousey < -128.f) ? -128.f : am->mousey;
}
const s32 newstickx = (s32)cstickx + (s32)crstickx + (s32)am->mousex;
const s32 newsticky = (s32)csticky + (s32)crsticky - (s32)am->mousey;
cstickx = (newstickx < -128) ? -128 : (newstickx > 127) ? 127 : newstickx;
csticky = (newsticky < -128) ? -128 : (newsticky > 127) ? 127 : newsticky;
newstickx += (s32)am->mousex;
newsticky -= (s32)am->mousey;
}
cstickx = (newstickx < -128) ? -128 : (newstickx > 127) ? 127 : newstickx;
csticky = (newsticky < -128) ? -128 : (newsticky > 127) ? 127 : newsticky;
#endif
if (g_Vars.currentplayer->activemenumode == AMMODE_EDIT) {
buttonsstate = buttonsstate & D_JPAD;
cstickx = 0;
csticky = 0;
crstickx = 0;
crsticky = 0;
buttonspressed = 0;
}
+10
View File
@@ -3659,7 +3659,17 @@ bool bgTestHitOnObj(struct coord *arg0, struct coord *arg1, struct coord *arg2,
} else if (gdl->dma.cmd == G_VTX) {
ptr = var800a6470;
count = gdl->bytes[GFX_W0_BYTE(1)] & 0xf;
#ifdef PLATFORM_N64
offset = (UNSEGADDR(gdl->words.w1) & 0xffffff);
#else
if (gdl->words.w1 & 1) {
// segmented address
offset = (UNSEGADDR(gdl->words.w1) & 0xffffff);
} else {
// linear address
offset = gdl->words.w1 - (uintptr_t)vertices;
}
#endif
numvertices = (((u32) gdl->bytes[GFX_W0_BYTE(1)] >> 4) & 0xf) + 1;
vtx = (Vtx *)((uintptr_t)vertices + offset);
vtx -= count;
+2 -2
View File
@@ -7516,12 +7516,12 @@ void bgunCreateFx(struct hand *hand, s32 handnum, struct weaponfunc *funcdef, s3
static inline f32 bgunGetFovOffsetZ(void)
{
return (g_PlayerDefaultFovY - 60.f) / 3.f;
return (PLAYER_DEFAULT_FOV - 60.f) / 3.f;
}
static inline f32 bgunGetFovOffsetY(void)
{
return (g_PlayerDefaultFovY - 60.f) / (2.75f * 4.f);
return (PLAYER_DEFAULT_FOV - 60.f) / (2.75f * 4.f);
}
#endif
+3
View File
@@ -7,6 +7,9 @@
#include "lib/memp.h"
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "game/player.h"
#endif
extern u32 g_BgunGunMemBaseSize4Mb2P;
+43 -55
View File
@@ -43,6 +43,23 @@
#include "input.h"
#include "video.h"
static void bgunProcessQuickDetonate(struct movedata *data, u32 c1buttons, u32 c1buttonsthisframe, u32 buttons1, u32 buttons2) {
if ((((c1buttons & (buttons1)) && (c1buttonsthisframe & (buttons2)))
|| ((c1buttons & (buttons2)) && (c1buttonsthisframe & (buttons1))))
&& bgunGetWeaponNum(HAND_RIGHT) == WEAPON_REMOTEMINE) {
data->detonating = true;
data->weaponbackoffset = 0;
data->weaponforwardoffset = 0;
data->btapcount = 0;
// prevent the previous slotnum
// from causing Jo to switch weapons
g_AmMenus[g_AmIndex].slotnum = 4;
amClose();
g_Vars.currentplayer->invdowntime = -2;
g_Vars.currentplayer->usedowntime = -2;
}
}
static void bgunProcessInputAltButton(struct movedata *data, s8 contpad, s32 i)
{
s32 buttons = joyGetButtonsOnSample(i, contpad, 0xffffffff);
@@ -756,7 +773,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
#ifndef PLATFORM_N64
if (allowmlook) {
inputMouseGetScaledDelta(&movedata.freelookdx, &movedata.freelookdy);
allowmcross = (g_PlayerMouseAimMode == MOUSEAIM_CLASSIC) &&
allowmcross = (PLAYER_EXTCFG().mouseaimmode == MOUSEAIM_CLASSIC) &&
(movedata.freelookdx || movedata.freelookdy || g_Vars.currentplayer->swivelpos[0] || g_Vars.currentplayer->swivelpos[1]);
if (movedata.invertpitch) {
movedata.freelookdy = -movedata.freelookdy;
@@ -1198,7 +1215,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
if (!g_Vars.currentplayer->insightaimmode) {
movedata.analogstrafe = c2stickx;
movedata.analogwalk = c2sticky;
movedata.unk14 = 1;
movedata.unk14 = (c2stickx || c2sticky);
} else {
movedata.analogstrafe = 0.f;
movedata.analogwalk = 0.f;
@@ -1256,7 +1273,11 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
movedata.digitalstepforward = !g_Vars.currentplayer->insightaimmode && (c1buttons & (U_CBUTTONS));
movedata.digitalstepback = !g_Vars.currentplayer->insightaimmode && (c1buttons & (D_CBUTTONS));
movedata.canlookahead = !g_Vars.currentplayer->insightaimmode;
#ifdef PLATFORM_N64
movedata.canlookahead = false;
#else
movedata.canlookahead = !g_Vars.currentplayer->insightaimmode && (c2stickx || c2sticky);
#endif
movedata.cannaturalpitch = !g_Vars.currentplayer->insightaimmode;
movedata.speedvertadown = 0;
movedata.speedvertaup = 0;
@@ -1271,7 +1292,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
movedata.analoglean = 0.f;
}
if (g_PlayerMouseAimMode == MOUSEAIM_LOCKED || bgunGetWeaponNum(HAND_RIGHT) == WEAPON_HORIZONSCANNER) {
if (PLAYER_EXTCFG().mouseaimmode == MOUSEAIM_LOCKED || bgunGetWeaponNum(HAND_RIGHT) == WEAPON_HORIZONSCANNER) {
movedata.cannaturalpitch = movedata.cannaturalpitch || (movedata.freelookdy != 0.0f);
movedata.cannaturalturn = movedata.cannaturalturn || (movedata.freelookdx != 0.0f);
}
@@ -1320,7 +1341,11 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
movedata.cannaturalturn = !g_Vars.currentplayer->insightaimmode;
movedata.unk14 = !g_Vars.currentplayer->insightaimmode;
#ifdef PLATFORM_N64
movedata.unk14 = false;
#else
movedata.unk14 = !g_Vars.currentplayer->insightaimmode && (c2stickx || c2sticky);
#endif
if (g_Vars.tickmode == TICKMODE_AUTOWALK) {
movedata.analogstrafe = 0;
@@ -1631,7 +1656,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
#endif
// Handle C-button and analog crouch and uncrouch, if enabled
if (g_PlayerClassicCrouch && allowc1buttons) {
if (PLAYER_EXTCFG().classiccrouch && allowc1buttons) {
for (i = 0; i < numsamples; i++) {
if (!canmanualzoom && aimonhist[i]) {
bool goUp = joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & (U_CBUTTONS));
@@ -1699,9 +1724,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
movedata.farsighttempautoseek = g_Vars.currentplayer->insightaimmode && (c1buttons & (L_CBUTTONS | R_CBUTTONS));
if (g_Vars.currentplayer->insightaimmode) {
movedata.unk14 = 1;
#ifndef PLATFORM_N64
#ifndef PLATFORM_N64
movedata.analogstrafe = c2stickx;
#endif
#endif
}
} else {
movedata.rleanleft = g_Vars.currentplayer->insightaimmode && (c1buttons & (L_CBUTTONS));
@@ -1726,28 +1751,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
g_Vars.currentplayer->usedowntime = -2;
}
#else
if ((((c1buttons & BUTTON_RADIAL) && (c1buttonsthisframe & BUTTON_CANCEL_USE))
|| ((c1buttons & BUTTON_CANCEL_USE) && (c1buttonsthisframe & BUTTON_RADIAL)))
&& weaponnum == WEAPON_REMOTEMINE) {
movedata.detonating = true;
movedata.weaponbackoffset = 0;
movedata.weaponforwardoffset = 0;
movedata.btapcount = 0;
amClose();
g_Vars.currentplayer->invdowntime = -2;
g_Vars.currentplayer->usedowntime = -2;
g_Vars.currentplayer->amdowntime = 0;
}
if ((((c1buttons & BUTTON_WPNBACK) && (c1buttonsthisframe & BUTTON_CANCEL_USE))
|| ((c1buttons & BUTTON_CANCEL_USE) && (c1buttonsthisframe & BUTTON_WPNBACK)))
&& weaponnum == WEAPON_REMOTEMINE) {
movedata.detonating = true;
movedata.weaponbackoffset = 0;
movedata.weaponforwardoffset = 0;
movedata.btapcount = 0;
g_Vars.currentplayer->invdowntime = -2;
g_Vars.currentplayer->usedowntime = -2;
}
bgunProcessQuickDetonate(&movedata, c1buttons, c1buttonsthisframe, (BUTTON_CANCEL_USE | BUTTON_ACCEPT_USE), (BUTTON_WPNBACK | BUTTON_RADIAL | BUTTON_RELOAD));
#endif
}
@@ -1830,11 +1834,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
if (g_Vars.currentplayer->pausemode == PAUSEMODE_UNPAUSED && !g_MainIsEndscreen) {
#ifdef PLATFORM_N64
zoomfov = 60;
#else
zoomfov = g_PlayerDefaultFovY;
#endif
zoomfov = PLAYER_DEFAULT_FOV;
// FarSight in secondary function
if (bgunGetWeaponNum(HAND_RIGHT) == WEAPON_FARSIGHT
@@ -1843,15 +1843,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
&& g_Vars.currentplayer->autoeraserdist > 0) {
eraserfov = cam0f0b49b8(500.0f / g_Vars.currentplayer->autoeraserdist);
#ifdef PLATFORM_N64
if (eraserfov > 60) {
eraserfov = 60;
if (eraserfov > PLAYER_DEFAULT_FOV) {
eraserfov = PLAYER_DEFAULT_FOV;
}
#else
if (eraserfov > g_PlayerDefaultFovY) {
eraserfov = g_PlayerDefaultFovY;
}
#endif
if (eraserfov < ADJUST_ZOOM_FOV(2)) {
eraserfov = ADJUST_ZOOM_FOV(2);
@@ -1885,15 +1879,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
zoomfov = currentPlayerGetGunZoomFov();
}
#ifdef PLATFORM_N64
if (zoomfov <= 0) {
zoomfov = 60;
zoomfov = PLAYER_DEFAULT_FOV;
}
#else
if (zoomfov <= 0) {
zoomfov = g_PlayerDefaultFovY;
}
#endif
playerTweenFovY(zoomfov);
playerUpdateZoom();
@@ -2169,10 +2157,10 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
#else
f32 xscale, yscale;
if (movedata.freelookdx || movedata.freelookdy) {
xscale = g_PlayerCrosshairSway * 0.20f;
yscale = g_PlayerCrosshairSway * 0.30f;
xscale = PLAYER_EXTCFG().crosshairsway * 0.20f;
yscale = PLAYER_EXTCFG().crosshairsway * 0.30f;
} else {
xscale = yscale = g_PlayerCrosshairSway;
xscale = yscale = PLAYER_EXTCFG().crosshairsway;
}
x = g_Vars.currentplayer->speedtheta * 0.3f * xscale + g_Vars.currentplayer->gunextraaimx;
y = -g_Vars.currentplayer->speedverta * 0.1f * yscale + g_Vars.currentplayer->gunextraaimy;
@@ -2187,8 +2175,8 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
#ifndef PLATFORM_N64
if (allowmcross) {
// joystick is inactive, move crosshair using the mouse
const f32 xscale = g_PlayerMouseAimSpeedX * 320.f / (f32)videoGetWidth();
const f32 yscale = g_PlayerMouseAimSpeedY * 240.f / (f32)videoGetHeight();
const f32 xscale = PLAYER_EXTCFG().mouseaimspeedx * 320.f / (f32)videoGetWidth();
const f32 yscale = PLAYER_EXTCFG().mouseaimspeedy * 240.f / (f32)videoGetHeight();
f32 x = g_Vars.currentplayer->swivelpos[0] + movedata.freelookdx * xscale;
f32 y = g_Vars.currentplayer->swivelpos[1] + movedata.freelookdy * yscale;
x = (x < -1.f) ? -1.f : ((x > 1.f) ? 1.f : x);
+5 -4
View File
@@ -21,6 +21,7 @@
#include "types.h"
#include "gbiex.h"
#ifndef PLATFORM_N64
#include "game/player.h"
#include "video.h"
#endif
@@ -306,12 +307,12 @@ Gfx *bviewDrawMotionBlur(Gfx *gdl, u32 colour, u32 alpha)
somefloat += 1.0f / fyyy;
}
#else
gDPSetFramebufferTextureEXT(gdl++, 0, 0, 0, g_PrevFrameFb);
gDPSetFramebufferTextureEXT(gdl++, 0, 0, 0, g_BlurFb);
gSPImageRectangleEXT(gdl++,
viewleft << 2, viewtop << 2, viewleft, viewtop,
(viewleft + viewwidth) << 2, (viewtop + viewheight) << 2, viewleft + viewwidth, viewtop + viewheight,
0, videoGetNativeWidth(), videoGetNativeHeight());
g_PrevFrameCapTimer = 0;
g_BlurFbCapTimer = 0;
#endif
return gdl;
@@ -544,12 +545,12 @@ Gfx *bviewDrawZoomBlur(Gfx *gdl, u32 colour, s32 alpha, f32 arg3, f32 arg4)
const s32 top = ycenter - halfh;
const s32 right = xcenter + halfw;
const s32 bottom = ycenter + halfh;
gDPSetFramebufferTextureEXT(gdl++, 0, 0, 0, g_PrevFrameFb);
gDPSetFramebufferTextureEXT(gdl++, 0, 0, 0, g_BlurFb);
gSPImageRectangleEXT(gdl++,
left << 2, top << 2, viewleft, viewtop,
right << 2, bottom << 2, viewleft + viewwidth, viewtop + viewheight,
0, videoGetNativeWidth(), videoGetNativeHeight());
g_PrevFrameCapTimer = 0;
g_BlurFbCapTimer = 0;
#endif
return gdl;
+3
View File
@@ -26,6 +26,9 @@
#include "lib/collision.h"
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
extern f32 fabsf(f32);
#endif
void bwalkInit(void)
{
+4
View File
@@ -88,6 +88,10 @@ void botReset(struct chrdata *chr, u8 respawning)
chrSetShield(chr, 0);
chr->cmnum = 0;
chr->cmnum2 = 0;
#ifndef PLATFORM_N64
chr->blurdrugamount = 0;
chr->poisoncounter = 0;
#endif
#if VERSION >= VERSION_NTSC_1_0
bgunFreeFireslot(chr->fireslots[0]);
+3 -1
View File
@@ -4811,7 +4811,9 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
chrChoke(chr, choketype);
}
chrFlinchBody(chr);
if (g_Vars.currentplayer->haschrbody) {
chrFlinchBody(chr);
}
}
// Handle player boost
+1
View File
@@ -143,6 +143,7 @@ u32 var8007fbc0 = 0x44444400;
u32 var8007fbc4 = 0xffffff00;
#ifndef PLATFORM_N64
s32 g_HudCenter = false;
u32 g_HudAlignModeL = G_ASPECT_LEFT_EXT;
u32 g_HudAlignModeR = G_ASPECT_RIGHT_EXT;
#endif
+7 -7
View File
@@ -269,11 +269,7 @@ Gfx *hudmsgRenderZoomRange(Gfx *gdl, u32 alpha)
return gdl;
}
} else {
#ifdef PLATFORM_N64
maxzoom = 60.0f / zoomfov;
#else
maxzoom = g_PlayerDefaultFovY / zoomfov;
#endif
maxzoom = PLAYER_DEFAULT_FOV / zoomfov;
curzoom = maxzoom - 1.0f / (zoomfov / zoominfovy) + 1;
}
@@ -1519,7 +1515,9 @@ Gfx *hudmsgsRender(Gfx *gdl)
gdl = hudmsgRenderBox(gdl, x - 3, y - 3, x + msg->width + 2, y + msg->height + 2, 1.0f, bordercolour, spc0);
#endif
gdl = textRenderProjected(gdl, &x, &y, msg->text, msg->font1, msg->font2, textcolour, viGetWidth(), viGetHeight(), 0, 0);
if (spc0 > 0) {
gdl = textRenderProjected(gdl, &x, &y, msg->text, msg->font1, msg->font2, textcolour, viGetWidth(), viGetHeight(), 0, 0);
}
} else {
gdl = text0f153a34(gdl, x, y, x + msg->width, y + msg->height, 0);
@@ -1601,7 +1599,9 @@ Gfx *hudmsgsRender(Gfx *gdl)
gdl = hudmsgRenderBox(gdl, x - 3, y - 3, x + msg->width + 2, y + msg->height + 2, 1.0f, bordercolour, 1.0f - spa8);
#endif
gdl = textRenderProjected(gdl, &x, &y, msg->text, msg->font1, msg->font2, textcolour, viGetWidth(), viGetHeight(), 0, 0);
if (spa8 < 1.0f) {
gdl = textRenderProjected(gdl, &x, &y, msg->text, msg->font1, msg->font2, textcolour, viGetWidth(), viGetHeight(), 0, 0);
}
} else {
gdl = text0f153a34(gdl, x, y, x + msg->width, y + msg->height, 0);
+64 -7
View File
@@ -39,6 +39,9 @@ u8 g_InventoryWeapon;
struct menudialogdef g_2PMissionControlStyleMenuDialog;
struct menudialogdef g_CiControlPlayer2MenuDialog;
struct menudialogdef g_CinemaMenuDialog;
#ifndef PLATFORM_N64
extern struct menudialogdef g_ExtendedMenuDialog;
#endif
char *menuTextCurrentStageName(struct menuitem *item)
{
@@ -3429,15 +3432,23 @@ struct menuitem g_ExitGameMenuItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING,
L_OPTIONS_110, // "Exit"
MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_LESSHEIGHT | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Are you sure you want to exit?\n",
0,
NULL,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0x00000082,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
0,
MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_190, // "Yes"
0,
menuhandlerExitGame,
@@ -3445,7 +3456,7 @@ struct menuitem g_ExitGameMenuItems[] = {
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
L_OPTIONS_191, // "No"
0,
NULL,
@@ -3497,6 +3508,16 @@ struct menuitem g_SoloMissionOptionsMenuItems[] = {
0,
(void *)&g_MissionDisplayOptionsMenuDialog,
},
#ifndef PLATFORM_N64
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Extended",
0,
(void *)&g_ExtendedMenuDialog,
},
#endif
{ MENUITEMTYPE_END },
};
@@ -3533,6 +3554,16 @@ struct menuitem g_2PMissionOptionsHMenuItems[] = {
0,
(void *)&g_MissionDisplayOptionsMenuDialog,
},
#ifndef PLATFORM_N64
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Extended",
0,
(void *)&g_ExtendedMenuDialog,
},
#endif
{
MENUITEMTYPE_SEPARATOR,
0,
@@ -3589,6 +3620,16 @@ struct menuitem g_2PMissionOptionsVMenuItems[] = {
0,
(void *)&g_2PMissionDisplayOptionsVMenuDialog,
},
#ifndef PLATFORM_N64
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Extended",
0,
(void *)&g_ExtendedMenuDialog,
},
#endif
{
MENUITEMTYPE_SEPARATOR,
0,
@@ -3657,6 +3698,16 @@ struct menuitem g_CiOptionsMenuItems[] = {
6,
(void *)&g_CinemaMenuDialog,
},
#ifndef PLATFORM_N64
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Extended",
7,
(void *)&g_ExtendedMenuDialog,
},
#endif
{ MENUITEMTYPE_END },
};
@@ -4253,7 +4304,13 @@ MenuItemHandlerResult menuhandlerInventoryList(s32 operation, struct menuitem *i
bgunEquipWeapon2(HAND_LEFT, weaponnum);
} else {
bgunEquipWeapon2(HAND_RIGHT, weaponnum);
bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE);
// don't unequip detonator
// if we already have it equipped
if (weaponnum == WEAPON_REMOTEMINE) {
bgunEquipWeapon2(HAND_LEFT, weaponnum);
} else {
bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE);
}
}
}
@@ -4886,8 +4943,8 @@ struct menuitem g_MainMenuMenuItems[] = {
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT,
L_OPTIONS_110, // "Exit Game"
MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Exit Game",
0x00000007,
(void *)&g_ExitGameMenuDialog,
},
+18
View File
@@ -488,11 +488,21 @@ char *menuResolveText(uintptr_t thing, void *dialogoritem)
char *menuResolveParam2Text(struct menuitem *item)
{
#ifndef PLATFORM_N64
if (item->flags & MENUITEMFLAG_LITERAL_TEXT) {
return (const char *)item->param2;
}
#endif
return menuResolveText(item->param2, item);
}
char *menuResolveDialogTitle(struct menudialogdef *dialogdef)
{
#ifndef PLATFORM_N64
if (dialogdef->flags & MENUDIALOGFLAG_LITERAL_TEXT) {
return (const char *)dialogdef->title;
}
#endif
return menuResolveText(dialogdef->title, dialogdef);
}
@@ -660,6 +670,9 @@ void menuCalculateItemSize(struct menuitem *item, s16 *width, s16 *height, struc
if (item->flags & MENUITEMFLAG_SLIDER_ALTSIZE) {
*height = 22;
*width = 120;
} else if (item->flags & MENUITEMFLAG_SLIDER_WIDE) {
*width = 200;
*height = VERSION == VERSION_JPN_FINAL ? 14 : 12;
}
break;
case MENUITEMTYPE_CHECKBOX:
@@ -746,6 +759,11 @@ void menuCalculateItemSize(struct menuitem *item, s16 *width, s16 *height, struc
#endif
if ((item->flags & (MENUITEMFLAG_LABEL_HASRIGHTTEXT | MENUITEMFLAG_BIGFONT)) == 0) {
#ifndef PLATFORM_N64
if (item->flags & MENUITEMFLAG_LITERAL_TEXT) {
text = (const char *)item->param3;
} else
#endif
text = menuResolveText(item->param3, item);
// @bug: This is not how you check for an empty string
+23
View File
@@ -109,6 +109,29 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = {
/*0x2e*/ { WEAPON_DISABLED }, // 0x25 on N64
};
#ifndef PLATFORM_N64
#define PLAYER_EXT_CFG_DEFAULT { \
.fovy = 60.f, \
.fovzoommult = 1.f, \
.fovzoom = true, \
.mouseaimmode = MOUSEAIM_CLASSIC, \
.mouseaimspeedx = 0.7f, \
.mouseaimspeedy = 0.7f, \
.radialmenuspeed = 4.f, \
.crosshairsway = 1.f, \
.classiccrouch = true, \
}
struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = {
PLAYER_EXT_CFG_DEFAULT,
PLAYER_EXT_CFG_DEFAULT,
PLAYER_EXT_CFG_DEFAULT,
PLAYER_EXT_CFG_DEFAULT,
};
#endif
/**
* Converts the given value into a float on a curved scale from 0.1 to 10.
*
+11 -34
View File
@@ -203,17 +203,6 @@ s16 g_DeathAnimations[] = {
s32 g_NumDeathAnimations = 0;
#ifndef PLATFORM_N64
f32 g_PlayerDefaultFovY = 60.f;
f32 g_PlayerCrosshairSway = 1.f;
s32 g_PlayerMouseAimMode = MOUSEAIM_CLASSIC;
f32 g_PlayerMouseAimSpeedX = 0.75f;
f32 g_PlayerMouseAimSpeedY = 0.75f;
s32 g_PlayerFovAffectsZoom = 1;
f32 g_PlayerFovZoomMultiplier = 1.0f;
s32 g_PlayerClassicCrouch = true;
#endif
/**
* Choose which location to spawn into from the given pads. Write the position
* and rooms to the dstpos and dstrooms pointers and return the angle that the
@@ -531,6 +520,10 @@ void playerStartNewLife(void)
g_Vars.currentplayer->damagetype = DAMAGETYPE_7;
g_Vars.currentplayer->gunammooff = 0;
g_Vars.currentplayer->gunsightoff = 2;
#ifndef PLATFORM_N64
g_Vars.currentplayer->prop->chr->blurdrugamount = 0;
g_Vars.currentplayer->prop->chr->poisoncounter = 0;
#endif
hudmsgsSetOn(0xffffffff);
@@ -2082,8 +2075,8 @@ void playerTweenFovY(f32 targetfovy)
f32 speed = 15.0f / 30.0f;
#ifndef PLATFORM_N64
if (g_PlayerDefaultFovY > 60.0f) { // adjust zoom speed depending on non-default fov setting (higher fov == faster zoom)
speed /= g_PlayerDefaultFovY / 60.0f;
if (PLAYER_DEFAULT_FOV > 60.0f) { // adjust zoom speed depending on non-default fov setting (higher fov == faster zoom)
speed /= PLAYER_DEFAULT_FOV / 60.0f;
}
#endif
@@ -2708,7 +2701,7 @@ Gfx *playerRenderHealthBar(Gfx *gdl)
#ifdef PLATFORM_N64
mtx00016ae4(&matrix, 0, 370, 0, 0, 0, 0, 0, 0, -1);
#else
f32 fovsc = 60.f / g_PlayerDefaultFovY;
f32 fovsc = 60.f / PLAYER_DEFAULT_FOV;
if (fovsc > 1.01f) {
fovsc *= 1.1f;
}
@@ -3163,22 +3156,14 @@ void playerConfigureVi(void)
var800800f0jf = 0;
#endif
#ifdef PLATFORM_N64
playermgrSetFovY(60);
#else
playermgrSetFovY(g_PlayerDefaultFovY);
#endif
playermgrSetFovY(PLAYER_DEFAULT_FOV);
playermgrSetAspectRatio(ratio);
playermgrSetViewSize(playerGetViewportWidth(), playerGetViewportHeight());
playermgrSetViewPosition(playerGetViewportLeft(), playerGetViewportTop());
viSetMode(g_ViModes[g_ViRes].xscale);
#ifdef PLATFORM_N64
viSetFovAspectAndSize(60, ratio, playerGetViewportWidth(), playerGetViewportHeight());
#else
viSetFovAspectAndSize(g_PlayerDefaultFovY, ratio, playerGetViewportWidth(), playerGetViewportHeight());
#endif
viSetFovAspectAndSize(PLAYER_DEFAULT_FOV, ratio, playerGetViewportWidth(), playerGetViewportHeight());
viSetViewPosition(playerGetViewportLeft(), playerGetViewportTop());
viSetSize(playerGetFbWidth(), playerGetFbHeight());
@@ -3241,21 +3226,13 @@ void playerTick(bool arg0)
return;
}
#ifdef PLATFORM_N64
playermgrSetFovY(60);
#else
playermgrSetFovY(g_PlayerDefaultFovY);
#endif
playermgrSetFovY(PLAYER_DEFAULT_FOV);
playermgrSetAspectRatio(aspectratio);
playermgrSetViewSize(playerGetViewportWidth(), playerGetViewportHeight());
playermgrSetViewPosition(playerGetViewportLeft(), playerGetViewportTop());
viSetMode(g_ViModes[g_ViRes].xscale);
#ifdef PLATFORM_N64
viSetFovAspectAndSize(60, aspectratio, playerGetViewportWidth(), playerGetViewportHeight());
#else
viSetFovAspectAndSize(g_PlayerDefaultFovY, aspectratio, playerGetViewportWidth(), playerGetViewportHeight());
#endif
viSetFovAspectAndSize(PLAYER_DEFAULT_FOV, aspectratio, playerGetViewportWidth(), playerGetViewportHeight());
viSetViewPosition(playerGetViewportLeft(), playerGetViewportTop());
viSetSize(playerGetFbWidth(), playerGetFbHeight());
viSetBufSize(playerGetFbWidth(), playerGetFbHeight());
+7
View File
@@ -307,10 +307,17 @@ Gfx *skyRender(Gfx *gdl)
if (&tl3dpos);
#ifdef PLATFORM_N64
skyGetWorldPosFromScreenPos(0.0f, 0.0f, &tl3dpos);
skyGetWorldPosFromScreenPos(camGetScreenWidth() - 0.1f, 0.0f, &tr3dpos);
skyGetWorldPosFromScreenPos(0.0f, camGetScreenHeight() - 0.1f, &bl3dpos);
skyGetWorldPosFromScreenPos(camGetScreenWidth() - 0.1f, camGetScreenHeight() - 0.1f, &br3dpos);
#else
skyGetWorldPosFromScreenPos(-4.0f, -4.0f, &tl3dpos);
skyGetWorldPosFromScreenPos(camGetScreenWidth() + 4.0f, -4.0f, &tr3dpos);
skyGetWorldPosFromScreenPos(-4.0f, camGetScreenHeight() + 4.0f, &bl3dpos);
skyGetWorldPosFromScreenPos(camGetScreenWidth() + 4.0f, camGetScreenHeight() + 4.0f, &br3dpos);
#endif
tlcornerissky = skyIsScreenCornerInSky(&tl3dpos, &sp644, &sp58c);
trcornerissky = skyIsScreenCornerInSky(&tr3dpos, &sp638, &sp588);
+14 -12
View File
@@ -370,6 +370,8 @@ Gfx *titleRenderLegal(Gfx *gdl)
#if !defined(PLATFORM_N64) && defined(VERSION_HASH)
if (elem->textid == L_OPTIONS_084) {
elem->textptr = VERSION_HASH " (" VERSION_TARGET ")";
} else if (elem->textid == L_OPTIONS_083) {
elem->textptr = VERSION_ROMID;
}
#endif
break;
@@ -456,6 +458,11 @@ Gfx *titleRenderLegal(Gfx *gdl)
gdl = text0f153628(gdl);
} else {
#ifdef PLATFORM_N64
#define ELEM_TEXT langGet(elem->textid)
#else
#define ELEM_TEXT (char *)(elem->textptr ? elem->textptr : langGet(elem->textid))
#endif
#if VERSION == VERSION_JPN_FINAL
u32 stack;
x = elem->x == -1 ? prevx : elem->x;
@@ -471,16 +478,16 @@ Gfx *titleRenderLegal(Gfx *gdl)
x += 24;
}
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
var8007fad0 = 1;
var80080108jf = 1;
} else {
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, (colour & 0xffffff00) | ((colour & 0xff) * 2 / 3), viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, (colour & 0xffffff00) | ((colour & 0xff) * 2 / 3), viGetWidth(), viGetHeight(), 0, 0);
x = elem->x == -1 ? prevx : elem->x;
y = elem->y;
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
prevx = x;
}
@@ -489,28 +496,23 @@ Gfx *titleRenderLegal(Gfx *gdl)
// Render a darker copy of the text one pixel above
x = elem->x == -1 ? prevx : elem->x;
y = elem->y - 1;
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, (colour & 0xffffff00) | ((colour & 0xff) * 2 / 3), viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, (colour & 0xffffff00) | ((colour & 0xff) * 2 / 3), viGetWidth(), viGetHeight(), 0, 0);
// Render the text properly
x = elem->x == -1 ? prevx : elem->x;
y = elem->y;
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
prevx = x;
#elif VERSION >= VERSION_PAL_BETA
x = elem->x == -1 ? prevx : elem->x;
y = elem->y;
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
prevx = x;
#else
x = elem->x;
y = elem->y;
#ifdef PLATFORM_N64
gdl = textRenderProjected(gdl, &x, &y, langGet(elem->textid), font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
#else
const char *textptr = elem->textptr ? elem->textptr : langGet(elem->textid);
gdl = textRenderProjected(gdl, &x, &y, textptr, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
#endif
gdl = textRenderProjected(gdl, &x, &y, ELEM_TEXT, font1, font2, colour, viGetWidth(), viGetHeight(), 0, 0);
#endif
}
}
+5
View File
@@ -1618,6 +1618,9 @@
#define MENUDIALOGFLAG_0400 0x0400
#define MENUDIALOGFLAG_DROPOUTONCLOSE 0x0800
#define MENUDIALOGFLAG_1000 0x1000
#ifndef PLATFORM_N64
#define MENUDIALOGFLAG_LITERAL_TEXT 0x2000
#endif
#define MENUDIALOGSTATE_PREOPEN 0
#define MENUDIALOGSTATE_OPENING 1
@@ -1658,6 +1661,8 @@
#define MENUITEMFLAG_LABEL_CUSTOMCOLOUR 0x01000000
#define MENUITEMFLAG_LESSHEIGHT 0x02000000
#define MENUITEMFLAG_CAROUSEL_04000000 0x04000000
#define MENUITEMFLAG_LITERAL_TEXT 0x08000000
#define MENUITEMFLAG_SLIDER_WIDE 0x10000000
#define MENUITEMTYPE_LABEL 0x01
#define MENUITEMTYPE_LIST 0x02
+10 -10
View File
@@ -531,32 +531,32 @@ extern struct menudialogdef g_HangarListMenuDialog;
#ifndef PLATFORM_N64
extern struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS];
extern struct weathercfg g_WeatherConfig[WEATHERCFG_MAX_STAGES];
extern const struct weathercfg g_DefaultWeatherConfig;
extern const struct weathercfg *g_CurWeatherConfig;
extern f32 g_PlayerCrosshairSway;
extern f32 g_PlayerDefaultFovY;
extern s32 g_PlayerMouseAimMode;
extern f32 g_PlayerMouseAimSpeedX;
extern f32 g_PlayerMouseAimSpeedY;
extern s32 g_PlayerFovAffectsZoom;
extern f32 g_PlayerFovZoomMultiplier;
extern s32 g_PlayerClassicCrouch;
extern f32 g_ViShakeIntensityMult;
extern u32 g_TexFilter2D;
extern s32 g_HudCenter;
extern u32 g_HudAlignModeL;
extern u32 g_HudAlignModeR;
extern s32 g_PrevFrameFb;
extern s32 g_PrevFrameCapTimer;
extern s32 g_BlurFb;
extern s32 g_BlurFbCapTimer;
#define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3]
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
#define TEX_FILTER_2D g_TexFilter2D
#define ADJUST_ZOOM_FOV(x) ((x) * g_PlayerFovZoomMultiplier)
#define ADJUST_ZOOM_FOV(x) ((x) * PLAYER_EXTCFG().fovzoommult)
#else // PLATFORM_N64
#define TEX_FILTER_2D G_TF_BILERP
#define ADJUST_ZOOM_FOV(x) (x)
#define PLAYER_DEFAULT_FOV 60.f
#endif // PLATFORM_N64
+8 -1
View File
@@ -49,7 +49,7 @@
// byteswap macros
#ifdef __GNUC__
#if defined(__GNUC__) || defined(__clang__)
#define PD_BSWAP16(x) __builtin_bswap16(x)
#define PD_BSWAP32(x) __builtin_bswap32(x)
#define PD_BSWAP64(x) __builtin_bswap64(x)
@@ -82,4 +82,11 @@
#define PD_LEPTR(x) PD_LE32(x)
#endif
// module constructor function attribute
#if defined(__GNUC__) || defined(__clang__)
#define PD_CONSTRUCTOR __attribute__((constructor))
#else
#error "Implement PD_CONSTRUCTOR macro for your compiler."
#endif
#endif
+16
View File
@@ -6123,4 +6123,20 @@ struct xz {
f32 z;
};
#ifndef PLATFORM_N64
struct extplayerconfig {
f32 fovy;
f32 fovzoommult;
s32 fovzoom;
s32 mouseaimmode;
f32 mouseaimspeedx;
f32 mouseaimspeedy;
s32 classiccrouch;
f32 radialmenuspeed;
f32 crosshairsway;
};
#endif
#endif
+2 -2
View File
@@ -345,8 +345,8 @@ void amgrFrame(void)
info->frameSamples = 184;
var8005cf94 = 2;
} else {
// have space in audio queue, render 2 naudio frames this frame
info->frameSamples = 368;
// have space in audio queue, render 2 naudio frames this frame (and 1 extra on PAL)
info->frameSamples = 368 + PAL * 184;
if (var8005cf94 != 0) {
var8005cf94--;