forked from Ports/perfect_dark
port: add simple config file
includes an option to disable vsync and enable cpu-side frame limiter
This commit is contained in:
1 parent
1eb30b28e1
commit
0c01ab76cf
14 files changed
+162
-40
No files matched your search
@@ -27,7 +27,7 @@ static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen);
|
||||
|
||||
static uint64_t previous_time;
|
||||
|
||||
static int target_fps = 60;
|
||||
static int target_fps = 120; // above 60 since vsync is enabled by default
|
||||
|
||||
static uint64_t qpc_freq;
|
||||
|
||||
@@ -190,7 +190,9 @@ static inline void sync_framerate_with_timer(void) {
|
||||
}
|
||||
|
||||
static void gfx_sdl_swap_buffers_begin(void) {
|
||||
//sync_framerate_with_timer();
|
||||
if (target_fps) {
|
||||
sync_framerate_with_timer();
|
||||
}
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
}
|
||||
|
||||
@@ -218,6 +220,11 @@ static void gfx_sdl_set_window_title(const char *title) {
|
||||
SDL_SetWindowTitle(wnd, title);
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_swap_interval(int interval) {
|
||||
SDL_GL_SetSwapInterval(interval);
|
||||
vsync_enabled = (interval != 0);
|
||||
}
|
||||
|
||||
struct GfxWindowManagerAPI gfx_sdl = {
|
||||
gfx_sdl_init,
|
||||
gfx_sdl_close,
|
||||
@@ -234,5 +241,6 @@ struct GfxWindowManagerAPI gfx_sdl = {
|
||||
gfx_sdl_set_target_fps,
|
||||
gfx_sdl_can_disable_vsync,
|
||||
gfx_sdl_get_window_handle,
|
||||
gfx_sdl_set_window_title
|
||||
gfx_sdl_set_window_title,
|
||||
gfx_sdl_set_swap_interval,
|
||||
};
|
||||
@@ -22,6 +22,7 @@ struct GfxWindowManagerAPI {
|
||||
bool (*can_disable_vsync)(void);
|
||||
void *(*get_window_handle)(void);
|
||||
void (*set_window_title)(const char *);
|
||||
void (*set_swap_interval)(int);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
void configInit(void);
|
||||
s32 configLoad(const char *fname);
|
||||
s32 configSave(const char *fname);
|
||||
|
||||
s32 configGetInt(const char *key, s32 defval);
|
||||
f32 configGetFloat(const char *key, f32 defval);
|
||||
const char *configGetString(const char *key, const char *defval);
|
||||
|
||||
void configSetInt(const char *key, s32 val);
|
||||
void configSetFloat(const char *key, f32 val);
|
||||
void configSetString(const char *key, const char *val);
|
||||
File renamed without changes.
+7
-5
@@ -1,18 +1,20 @@
|
||||
#ifndef _IN_FS_H
|
||||
#define _IN_FS_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
#ifdef PATH_MAX
|
||||
#define FS_MAXPATH PATH_MAX
|
||||
#else
|
||||
#define FS_MAXPATH 1024
|
||||
#endif
|
||||
|
||||
s32 fsInit(void);
|
||||
|
||||
const char *fsFullPath(const char *relPath);
|
||||
|
||||
void *fsFileLoad(const char *name, u32 *outSize);
|
||||
s32 fsFileSize(const char *name);
|
||||
|
||||
FILE *fsFileOpenWrite(const char *name);
|
||||
FILE *fsFileOpenRead(const char *name);
|
||||
void fsFileClose(FILE *f);
|
||||
|
||||
#endif
|
||||
@@ -8,4 +8,6 @@ u64 sysGetTicksPerSecond(void);
|
||||
|
||||
void sysFatalError(const char *fmt, ...) __attribute__((noreturn));
|
||||
|
||||
void sysGetExecutablePath(char *outPath, const u32 outLen);
|
||||
|
||||
#endif
|
||||
+6
-2
@@ -1,11 +1,13 @@
|
||||
#include <PR/ultratypes.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
#include "config.h"
|
||||
#include "audio.h"
|
||||
|
||||
static SDL_AudioDeviceID dev;
|
||||
static const s16 *nextBuf;
|
||||
static u32 nextSize = 0;
|
||||
static u32 queueLimit = 8192;
|
||||
|
||||
s32 audioInit(void)
|
||||
{
|
||||
@@ -19,7 +21,7 @@ s32 audioInit(void)
|
||||
want.freq = 22020; // TODO: this might cause trouble for some platforms
|
||||
want.format = AUDIO_S16SYS;
|
||||
want.channels = 2;
|
||||
want.samples = 512;
|
||||
want.samples = configGetInt("Audio.BufferSize", 512);
|
||||
want.callback = NULL;
|
||||
|
||||
nextBuf = NULL;
|
||||
@@ -30,6 +32,8 @@ s32 audioInit(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
queueLimit = configGetInt("Audio.QueueLimit", 8192);
|
||||
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
|
||||
return 0;
|
||||
@@ -54,7 +58,7 @@ void audioSetNextBuffer(const s16 *buf, u32 len)
|
||||
void audioEndFrame(void)
|
||||
{
|
||||
if (nextBuf && nextSize) {
|
||||
if (audioGetSamplesBuffered() < 8192) {
|
||||
if (audioGetSamplesBuffered() < queueLimit) {
|
||||
SDL_QueueAudio(dev, nextBuf, nextSize);
|
||||
}
|
||||
nextBuf = NULL;
|
||||
|
||||
+46
-12
@@ -4,18 +4,14 @@
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "fs.h"
|
||||
|
||||
#ifdef PATH_MAX
|
||||
#define FS_MAXPATH PATH_MAX
|
||||
#else
|
||||
#define FS_MAXPATH 1024
|
||||
#endif
|
||||
|
||||
#define FS_BASEDIR "data"
|
||||
#define FS_MAX_FILES 2048
|
||||
|
||||
static char baseDir[FS_MAXPATH + 1];
|
||||
static char exeDir[FS_MAXPATH + 1];
|
||||
|
||||
static struct {
|
||||
char *name[FS_MAXPATH + 1];
|
||||
@@ -23,17 +19,40 @@ static struct {
|
||||
void *data;
|
||||
} fileSlots[FS_MAX_FILES];
|
||||
|
||||
static const char *fsFullPath(const char *relPath)
|
||||
const char *fsFullPath(const char *relPath)
|
||||
{
|
||||
static char pathBuf[FS_MAXPATH];
|
||||
snprintf(pathBuf, sizeof(pathBuf), "%s/%s", baseDir, relPath);
|
||||
static char pathBuf[FS_MAXPATH + 1];
|
||||
|
||||
if (relPath[0] == '!') {
|
||||
// path relative to the exe
|
||||
const u32 len = strlen(exeDir);
|
||||
if (len > 0) {
|
||||
memcpy(pathBuf, exeDir, len);
|
||||
strncpy(pathBuf + len, relPath + 1, FS_MAXPATH - len);
|
||||
return pathBuf;
|
||||
}
|
||||
} else if (relPath[0] == '.') {
|
||||
// user explicitly wants working directory
|
||||
return relPath;
|
||||
}
|
||||
|
||||
// path relative to basedir
|
||||
snprintf(pathBuf, FS_MAXPATH, "%s/%s", baseDir, relPath);
|
||||
return pathBuf;
|
||||
}
|
||||
|
||||
s32 fsInit(void)
|
||||
{
|
||||
// TODO: support appdata/home/whatever
|
||||
strcpy(baseDir, FS_BASEDIR);
|
||||
sysGetExecutablePath(exeDir, FS_MAXPATH);
|
||||
|
||||
// get path to data dir and expand it if needed
|
||||
const char *path = configGetString("Game.BaseDir", "./data");
|
||||
if (path[0] == '!') {
|
||||
strncpy(baseDir, fsFullPath(path), FS_MAXPATH);
|
||||
} else {
|
||||
strncpy(baseDir, path, FS_MAXPATH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,3 +106,18 @@ s32 fsFileSize(const char *name)
|
||||
return st.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *fsFileOpenWrite(const char *name)
|
||||
{
|
||||
return fopen(fsFullPath(name), "wb");
|
||||
}
|
||||
|
||||
FILE *fsFileOpenRead(const char *name)
|
||||
{
|
||||
return fopen(fsFullPath(name), "rb");
|
||||
}
|
||||
|
||||
void fsFileClose(FILE *f)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
+32
-11
@@ -4,6 +4,7 @@
|
||||
#include <PR/os_cont.h>
|
||||
#include "input.h"
|
||||
#include "video.h"
|
||||
#include "config.h"
|
||||
|
||||
#define MAX_BINDS 4
|
||||
#define TRIG_THRESHOLD (30 * 256)
|
||||
@@ -15,6 +16,7 @@ static u32 binds[MAXCONTROLLERS][CK_TOTAL_COUNT][MAX_BINDS]; // [i][CK_][b] = [V
|
||||
|
||||
static s32 connectedMask = 0;
|
||||
|
||||
static s32 mouseEnabled = 1;
|
||||
static s32 mouseLocked = 0;
|
||||
static s32 mouseX, mouseY;
|
||||
static s32 mouseDX, mouseDY;
|
||||
@@ -23,16 +25,13 @@ static u32 mouseButtons;
|
||||
static f32 mouseSensX = 1.5f;
|
||||
static f32 mouseSensY = 1.5f;
|
||||
|
||||
// NOTE: default is inverted for 1.2
|
||||
// NOTE: by default this gets inverted for 1.2
|
||||
static u32 axisMap[2][2] = {
|
||||
{ SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY }, // stick x/y
|
||||
{ SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY }, // cbuttons x/y
|
||||
{ SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY },
|
||||
{ SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY },
|
||||
};
|
||||
|
||||
static u32 deadzone[2][2] = {
|
||||
{ DEFAULT_DEADZONE, DEFAULT_DEADZONE },
|
||||
{ DEFAULT_DEADZONE, DEFAULT_DEADZONE },
|
||||
};
|
||||
static u32 deadzone[2] = { DEFAULT_DEADZONE, DEFAULT_DEADZONE };
|
||||
|
||||
void inputSetDefaultKeyBinds(void) {
|
||||
// TODO: make VK constants for all these
|
||||
@@ -114,6 +113,21 @@ s32 inputInit(void)
|
||||
|
||||
inputSetDefaultKeyBinds();
|
||||
|
||||
mouseEnabled = configGetInt("Input.MouseEnabled", 1);
|
||||
mouseSensX = configGetFloat("Input.MouseSpeedX", 1.5f);
|
||||
mouseSensY = configGetFloat("Input.MouseSpeedY", 1.5f);
|
||||
|
||||
deadzone[0] = configGetInt("Input.LStickDeadzone", DEFAULT_DEADZONE);
|
||||
deadzone[1] = configGetInt("Input.RStickDeadzone", DEFAULT_DEADZONE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
connectedMask = ret;
|
||||
|
||||
return ret;
|
||||
@@ -165,7 +179,7 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
||||
if (rightY > +0x4000) npad->button |= D_CBUTTONS;
|
||||
|
||||
const s32 leftMag = leftX * leftX + leftY * leftY;
|
||||
const s32 deadzoneMag = deadzone[0][0] * deadzone[0][0] + deadzone[0][1] * deadzone[0][1];
|
||||
const s32 deadzoneMag = deadzone[0] * deadzone[0] + deadzone[0] * deadzone[0];
|
||||
if (leftMag > deadzoneMag) {
|
||||
const s32 stickY = -leftY / 0x100;
|
||||
if (!npad->stick_x) {
|
||||
@@ -179,10 +193,8 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inputUpdate(void)
|
||||
static inline void inputUpdateMouse(void)
|
||||
{
|
||||
SDL_GameControllerUpdate();
|
||||
|
||||
s32 mx, my;
|
||||
mouseButtons = SDL_GetMouseState(&mx, &my);
|
||||
|
||||
@@ -201,6 +213,15 @@ void inputUpdate(void)
|
||||
} else if (mouseLocked && inputKeyPressed(VK_ESCAPE)) {
|
||||
inputLockMouse(0);
|
||||
}
|
||||
}
|
||||
|
||||
void inputUpdate(void)
|
||||
{
|
||||
SDL_GameControllerUpdate();
|
||||
|
||||
if (mouseEnabled) {
|
||||
inputUpdateMouse();
|
||||
}
|
||||
|
||||
for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) {
|
||||
if (pads[i] && !SDL_GameControllerGetAttached(pads[i])) {
|
||||
|
||||
+6
-5
@@ -9,9 +9,10 @@
|
||||
#include "input.h"
|
||||
#include "video.h"
|
||||
#include "audio.h"
|
||||
#include "fs.h"
|
||||
|
||||
#define EEPROM_SIZE (EEP16K_MAXBLOCKS * 8)
|
||||
#define EEPROM_FNAME "eeprom.bin"
|
||||
#define EEPROM_FNAME "./eeprom.bin"
|
||||
#define OS_COUNTER_RATE 46875000ULL
|
||||
|
||||
u64 osClockRate = OS_CLOCK_RATE;
|
||||
@@ -252,7 +253,7 @@ s32 osEepromLongRead(OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
|
||||
{
|
||||
u8 content[EEPROM_SIZE];
|
||||
s32 ret = -1;
|
||||
FILE *fp = fopen(EEPROM_FNAME, "rb");
|
||||
FILE *fp = fsFileOpenRead(EEPROM_FNAME);
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@@ -260,7 +261,7 @@ s32 osEepromLongRead(OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
|
||||
memcpy(buffer, content + address * 8, nbytes);
|
||||
ret = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
fsFileClose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -271,12 +272,12 @@ s32 osEepromLongWrite(OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
|
||||
osEepromLongRead(mq, 0, content, EEPROM_SIZE);
|
||||
}
|
||||
memcpy(content + address * 8, buffer, nbytes);
|
||||
FILE* fp = fopen(EEPROM_FNAME, "wb");
|
||||
FILE* fp = fsFileOpenWrite(EEPROM_FNAME);
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
s32 ret = fwrite(content, 1, EEPROM_SIZE, fp) == EEPROM_SIZE ? 0 : -1;
|
||||
fclose(fp);
|
||||
fsFileClose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "input.h"
|
||||
#include "fs.h"
|
||||
#include "romdata.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
||||
u32 g_OsMemSize = 0;
|
||||
@@ -54,6 +55,7 @@ void bootCreateSched(void)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
fsInit();
|
||||
configInit();
|
||||
videoInit();
|
||||
inputInit();
|
||||
audioInit();
|
||||
@@ -61,6 +63,8 @@ int main(int argc, const char **argv)
|
||||
|
||||
bootCreateSched();
|
||||
|
||||
osMemSize = configGetInt("Game.MemorySize", 16) * 1024 * 1024;
|
||||
|
||||
g_OsMemSize = osGetMemSize();
|
||||
|
||||
g_MempHeapSize = g_OsMemSize;
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#include "platform.h"
|
||||
|
||||
#define MINIMP3_IMPLEMENTATION
|
||||
#include "minimp3.h"
|
||||
#include "external/minimp3.h"
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
#include <immintrin.h>
|
||||
|
||||
@@ -46,3 +46,22 @@ void sysFatalError(const char *fmt, ...)
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", errmsg, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void sysGetExecutablePath(char *outPath, const u32 outLen)
|
||||
{
|
||||
// try asking SDL
|
||||
char *sdlPath = SDL_GetBasePath();
|
||||
if (sdlPath && *sdlPath) {
|
||||
// -1 to trim trailing slash
|
||||
const u32 len = strlen(sdlPath) - 1;
|
||||
if (len < outLen) {
|
||||
memcpy(outPath, sdlPath, len);
|
||||
outPath[len] = '\0';
|
||||
}
|
||||
} else if (outLen > 1) {
|
||||
// give up, use working directory instead
|
||||
outPath[0] = '.';
|
||||
outPath[1] = '\0';
|
||||
}
|
||||
SDL_free(sdlPath);
|
||||
}
|
||||
+12
-1
@@ -4,6 +4,8 @@
|
||||
#include <string.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/gbi.h>
|
||||
#include "config.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "../fast3d/gfx_api.h"
|
||||
#include "../fast3d/gfx_sdl.h"
|
||||
@@ -25,7 +27,16 @@ s32 videoInit(void)
|
||||
renderingAPI = &gfx_opengl_api;
|
||||
gfx_current_native_viewport.width = 320;
|
||||
gfx_current_native_viewport.height = 240;
|
||||
gfx_init(wmAPI, renderingAPI, "PD", false, 640, 480, 100, 100);
|
||||
|
||||
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", 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
|
||||
|
||||
initDone = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user