mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-24 00:02:43 +02:00
Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-debugger
This commit is contained in:
commit
df2ba8ec7d
36 files changed
+2049
-455
No files matched your search
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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());
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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--;
|
||||
|
||||
Reference in new issue
Block a user