port: add simple config file

includes an option to disable vsync and enable cpu-side frame limiter
This commit is contained in:
fgsfds committed 2023-08-15 21:45:23 +02:00
1 parent 1eb30b28e1
commit 0c01ab76cf
14 files changed
+162 -40

No files matched your search

+11 -3
View File
@@ -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,
};
+1
View File
@@ -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
+15
View File
@@ -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
View File
@@ -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
+2
View File
@@ -8,4 +8,6 @@ u64 sysGetTicksPerSecond(void);
void sysFatalError(const char *fmt, ...) __attribute__((noreturn));
void sysGetExecutablePath(char *outPath, const u32 outLen);
#endif
+6 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+4
View File
@@ -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
View File
@@ -7,7 +7,7 @@
#include "platform.h"
#define MINIMP3_IMPLEMENTATION
#include "minimp3.h"
#include "external/minimp3.h"
#ifdef __SSE4_1__
#include <immintrin.h>
+19
View File
@@ -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
View File
@@ -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;
}