mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 02:12:43 +01:00
- add INI configuration support
- add fullscreen support
This commit is contained in:
parent
6de9f86938
commit
6fc37b1498
@ -111,9 +111,16 @@ void Emulator_ResetDevice()
|
||||
}
|
||||
|
||||
#if defined(D3D9)
|
||||
static int Emulator_InitialiseD3D9Context(char* windowName)
|
||||
static int Emulator_InitialiseD3D9Context(char* windowName, int fullscreen)
|
||||
{
|
||||
g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_RESIZABLE);
|
||||
int windowFlags = SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags);
|
||||
if (g_window == NULL)
|
||||
{
|
||||
eprinterr("Failed to initialise SDL window!\n");
|
||||
@ -152,9 +159,16 @@ static int Emulator_InitialiseD3D9Context(char* windowName)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int Emulator_InitialiseGLContext(char* windowName)
|
||||
static int Emulator_InitialiseGLContext(char* windowName, int fullscreen)
|
||||
{
|
||||
g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
int windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if(fullscreen)
|
||||
{
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags);
|
||||
|
||||
#if defined(OGL)
|
||||
SDL_GL_CreateContext(g_window);
|
||||
@ -196,7 +210,7 @@ const EGLint config16bpp[] =
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
static int Emulator_InitialiseGLESContext(char* windowName)
|
||||
static int Emulator_InitialiseGLESContext(char* windowName, int fullscreen)
|
||||
{
|
||||
unsigned int windowFlags = SDL_WINDOW_OPENGL;
|
||||
|
||||
@ -261,7 +275,7 @@ static int Emulator_InitialiseGLESContext(char* windowName)
|
||||
|
||||
#endif
|
||||
|
||||
static int Emulator_InitialiseSDL(char* windowName, int width, int height)
|
||||
static int Emulator_InitialiseSDL(char* windowName, int width, int height, int fullscreen)
|
||||
{
|
||||
windowWidth = width;
|
||||
windowHeight = height;
|
||||
@ -303,19 +317,19 @@ static int Emulator_InitialiseSDL(char* windowName, int width, int height)
|
||||
}
|
||||
|
||||
#if defined(OGL)
|
||||
if (Emulator_InitialiseGLContext(windowName) == FALSE)
|
||||
if (Emulator_InitialiseGLContext(windowName, fullscreen) == FALSE)
|
||||
{
|
||||
eprinterr("Failed to Initialise GL Context!\n");
|
||||
return FALSE;
|
||||
}
|
||||
#elif defined(OGLES)
|
||||
if (Emulator_InitialiseGLESContext(windowName) == FALSE)
|
||||
if (Emulator_InitialiseGLESContext(windowName, fullscreen) == FALSE)
|
||||
{
|
||||
eprinterr("Failed to Initialise GLES Context!\n");
|
||||
return FALSE;
|
||||
}
|
||||
#elif defined(D3D9)
|
||||
if (Emulator_InitialiseD3D9Context(windowName) == FALSE)
|
||||
if (Emulator_InitialiseD3D9Context(windowName, fullscreen) == FALSE)
|
||||
{
|
||||
eprinterr("Failed to Initialise D3D9 Context!\n");
|
||||
return FALSE;
|
||||
@ -429,13 +443,13 @@ static int Emulator_InitialiseCore()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Emulator_Initialise(char* windowName, int width, int height)
|
||||
void Emulator_Initialise(char* windowName, int width, int height, int fullscreen)
|
||||
{
|
||||
eprintf("Initialising Emulator.\n");
|
||||
eprintf("VERSION: %d.%d\n", EMULATOR_MAJOR_VERSION, EMULATOR_MINOR_VERSION);
|
||||
eprintf("Compile Date: %s Time: %s\n", EMULATOR_COMPILE_DATE, EMULATOR_COMPILE_TIME);
|
||||
|
||||
if (Emulator_InitialiseSDL(windowName, width, height) == FALSE)
|
||||
if (Emulator_InitialiseSDL(windowName, width, height, fullscreen) == FALSE)
|
||||
{
|
||||
eprinterr("Failed to Intialise SDL\n");
|
||||
Emulator_ShutDown();
|
||||
@ -1857,6 +1871,7 @@ void Emulator_DoDebugKeys(int nKey, bool down)
|
||||
{
|
||||
switch (nKey)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
case SDL_SCANCODE_1:
|
||||
g_wireframeMode ^= 1;
|
||||
eprintf("wireframe mode: %d\n", g_wireframeMode);
|
||||
@ -1876,7 +1891,7 @@ void Emulator_DoDebugKeys(int nKey, bool down)
|
||||
if (g_emulatorPaused)
|
||||
g_polygonSelected += (nKey == SDL_SCANCODE_UP) ? 3 : -3;
|
||||
break;
|
||||
|
||||
#endif
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__)
|
||||
case SDL_SCANCODE_4:
|
||||
eprintf("saving screenshot\n");
|
||||
@ -1900,7 +1915,6 @@ void Emulator_DoDebugKeys(int nKey, bool down)
|
||||
case SDL_SCANCODE_7:
|
||||
g_pgxpTextureCorrection ^= 1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define EMULATOR_PRIVATE_H
|
||||
|
||||
/* Usually called at the beginning of main function */
|
||||
extern void Emulator_Initialise(char* windowName, int screenWidth, int screenHeight);
|
||||
extern void Emulator_Initialise(char* windowName, int screenWidth, int screenHeight, int fullscreen);
|
||||
|
||||
/* Returns the screen size dimensions */
|
||||
extern void Emulator_GetScreenSize(int& screenWidth, int& screenHeight);
|
||||
|
@ -469,7 +469,7 @@ PGXPVector3D g_FP_SXYZ2;
|
||||
|
||||
PGXPVData g_pgxpCache[65535];
|
||||
int g_pgxpVertexIndex = 0;
|
||||
bool g_pgxpTransformed = false;
|
||||
int g_pgxpTransformed = 0;
|
||||
|
||||
void PGXP_ClearCache()
|
||||
{
|
||||
@ -480,7 +480,7 @@ ushort PGXP_GetIndex()
|
||||
{
|
||||
if (g_pgxpTransformed)
|
||||
{
|
||||
g_pgxpTransformed = false;
|
||||
g_pgxpTransformed = 0;
|
||||
return g_pgxpVertexIndex;
|
||||
}
|
||||
|
||||
@ -577,7 +577,7 @@ int docop2(int op) {
|
||||
vdata.pz = g_FP_SXYZ2.pz;
|
||||
|
||||
g_pgxpCache[g_pgxpVertexIndex++] = vdata;
|
||||
g_pgxpTransformed = true;
|
||||
g_pgxpTransformed = 1;
|
||||
}
|
||||
#endif
|
||||
C2_MAC0 = int(F((long long)C2_DQB + ((long long)C2_DQA * h_over_sz3)));
|
||||
@ -1008,7 +1008,7 @@ int docop2(int op) {
|
||||
vdata.pz = g_FP_SXYZ2.pz;
|
||||
|
||||
g_pgxpCache[g_pgxpVertexIndex++] = vdata;
|
||||
g_pgxpTransformed = true;
|
||||
g_pgxpTransformed = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,7 @@ project "REDRIVER2"
|
||||
files {
|
||||
"utils/**.h",
|
||||
"utils/**.cpp",
|
||||
"utils/**.c",
|
||||
"redriver2_psxpc.cpp",
|
||||
"DebugOverlay.cpp",
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "EMULATOR.H"
|
||||
#include "EMULATOR_PRIVATE.H"
|
||||
#include "utils/ini.h"
|
||||
|
||||
#include <SDL_scancode.h>
|
||||
|
||||
@ -194,7 +195,7 @@ extern void FunkUpDaBGMTunez(int funk);
|
||||
|
||||
int cursorX, cursorY, cursorOldX, cursorOldY;
|
||||
|
||||
void GameDebugMouse(int x, int y)
|
||||
void FreeCameraMouseHandler(int x, int y)
|
||||
{
|
||||
if (g_FreeCameraEnabled)
|
||||
{
|
||||
@ -219,7 +220,7 @@ void GameDebugMouse(int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
void GameDebugKeys(int nKey, bool down)
|
||||
void FreeCameraKeyboardHandler(int nKey, bool down)
|
||||
{
|
||||
if (g_FreeCameraEnabled)
|
||||
{
|
||||
@ -253,6 +254,11 @@ void GameDebugKeys(int nKey, bool down)
|
||||
g_FreeCameraControls &= ~0x8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameDebugKeys(int nKey, bool down)
|
||||
{
|
||||
FreeCameraKeyboardHandler(nKey, down);
|
||||
|
||||
if (!down)
|
||||
return;
|
||||
@ -355,6 +361,8 @@ char g_Replay_buffer[0x50000]; // 0x1fABBC
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ini_t *config;
|
||||
|
||||
#ifdef USE_CRT_MALLOC
|
||||
_overlay_buffer = (char*)malloc(0x50000); // 0x1C0000
|
||||
_frontend_buffer = (char*)malloc(0x50000); // 0xFB400
|
||||
@ -378,15 +386,65 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_OPTIONS) || defined(_DEBUG)
|
||||
gameDebugKeys = GameDebugKeys;
|
||||
gameDebugMouse = GameDebugMouse;
|
||||
GPU_printf = printf;
|
||||
#endif // _DEBUG
|
||||
|
||||
gDrawDistance = 600; // best distance
|
||||
config = ini_load("config.ini");
|
||||
|
||||
|
||||
Emulator_Initialise("DRIVER2", 800, 600);
|
||||
// best distance
|
||||
gDrawDistance = 600;
|
||||
|
||||
int windowWidth = 800;
|
||||
int windowHeight = 600;
|
||||
int fullScreen = 0;
|
||||
int enableFreecamera = 0;
|
||||
extern int g_pgxpTextureCorrection;
|
||||
|
||||
ini_sget(config, "render", "windowWidth", "%d", &windowWidth);
|
||||
ini_sget(config, "render", "windowHeight", "%d", &windowHeight);
|
||||
ini_sget(config, "render", "fullscreen", "%d", &fullScreen);
|
||||
ini_sget(config, "render", "pgxpTextureMapping", "%d", &g_pgxpTextureCorrection);
|
||||
ini_sget(config, "game", "drawDistance", "%d", &gDrawDistance);
|
||||
ini_sget(config, "game", "freeCamera", "%d", &enableFreecamera);
|
||||
|
||||
#if defined(DEBUG_OPTIONS)
|
||||
int unlockAll = 0;
|
||||
ini_sget(config, "game", "unlockAll", "%d", &unlockAll);
|
||||
|
||||
if(unlockAll)
|
||||
{
|
||||
gFurthestMission = 40;
|
||||
AvailableCheats.cheat5 = 1;
|
||||
AvailableCheats.cheat6 = 1;
|
||||
AvailableCheats.cheat7 = 1;
|
||||
AvailableCheats.cheat8 = 1;
|
||||
AvailableCheats.cheat2 = 1;
|
||||
AvailableCheats.cheat11 = 1;
|
||||
AvailableCheats.cheat1 = 1;
|
||||
AvailableCheats.cheat3 = 1;
|
||||
AvailableCheats.cheat4 = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _DEBUG
|
||||
if(enableFreecamera)
|
||||
{
|
||||
gameDebugKeys = FreeCameraKeyboardHandler;
|
||||
gameDebugMouse = FreeCameraMouseHandler;
|
||||
}
|
||||
#else
|
||||
|
||||
gameDebugKeys = GameDebugKeys;
|
||||
gameDebugMouse = FreeCameraMouseHandler;
|
||||
|
||||
#endif
|
||||
|
||||
ini_free(config);
|
||||
|
||||
Emulator_Initialise("DRIVER2", windowWidth, windowHeight, fullScreen);
|
||||
redriver2_main(argc, argv);
|
||||
|
||||
Emulator_ShutDown();
|
||||
|
||||
}
|
||||
|
274
src_rebuild/utils/ini.c
Normal file
274
src_rebuild/utils/ini.c
Normal file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* Copyright (c) 2016 rxi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ini.h"
|
||||
|
||||
struct ini_t {
|
||||
char *data;
|
||||
char *end;
|
||||
};
|
||||
|
||||
|
||||
/* Case insensitive string compare */
|
||||
static int strcmpci(const char *a, const char *b) {
|
||||
for (;;) {
|
||||
int d = tolower(*a) - tolower(*b);
|
||||
if (d != 0 || !*a) {
|
||||
return d;
|
||||
}
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the next string in the split data */
|
||||
static char* next(ini_t *ini, char *p) {
|
||||
p += strlen(p);
|
||||
while (p < ini->end && *p == '\0') {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void trim_back(ini_t *ini, char *p) {
|
||||
while (p >= ini->data && (*p == ' ' || *p == '\t' || *p == '\r')) {
|
||||
*p-- = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static char* discard_line(ini_t *ini, char *p) {
|
||||
while (p < ini->end && *p != '\n') {
|
||||
*p++ = '\0';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static char *unescape_quoted_value(ini_t *ini, char *p) {
|
||||
/* Use `q` as write-head and `p` as read-head, `p` is always ahead of `q`
|
||||
* as escape sequences are always larger than their resultant data */
|
||||
char *q = p;
|
||||
p++;
|
||||
while (p < ini->end && *p != '"' && *p != '\r' && *p != '\n') {
|
||||
if (*p == '\\') {
|
||||
/* Handle escaped char */
|
||||
p++;
|
||||
switch (*p) {
|
||||
default : *q = *p; break;
|
||||
case 'r' : *q = '\r'; break;
|
||||
case 'n' : *q = '\n'; break;
|
||||
case 't' : *q = '\t'; break;
|
||||
case '\r' :
|
||||
case '\n' :
|
||||
case '\0' : goto end;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Handle normal char */
|
||||
*q = *p;
|
||||
}
|
||||
q++, p++;
|
||||
}
|
||||
end:
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/* Splits data in place into strings containing section-headers, keys and
|
||||
* values using one or more '\0' as a delimiter. Unescapes quoted values */
|
||||
static void split_data(ini_t *ini) {
|
||||
char *value_start, *line_start;
|
||||
char *p = ini->data;
|
||||
|
||||
while (p < ini->end) {
|
||||
switch (*p) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case ' ':
|
||||
*p = '\0';
|
||||
/* Fall through */
|
||||
|
||||
case '\0':
|
||||
p++;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
p += strcspn(p, "]\n");
|
||||
*p = '\0';
|
||||
break;
|
||||
|
||||
case ';':
|
||||
p = discard_line(ini, p);
|
||||
break;
|
||||
|
||||
default:
|
||||
line_start = p;
|
||||
p += strcspn(p, "=\n");
|
||||
|
||||
/* Is line missing a '='? */
|
||||
if (*p != '=') {
|
||||
p = discard_line(ini, line_start);
|
||||
break;
|
||||
}
|
||||
trim_back(ini, p - 1);
|
||||
|
||||
/* Replace '=' and whitespace after it with '\0' */
|
||||
do {
|
||||
*p++ = '\0';
|
||||
} while (*p == ' ' || *p == '\r' || *p == '\t');
|
||||
|
||||
/* Is a value after '=' missing? */
|
||||
if (*p == '\n' || *p == '\0') {
|
||||
p = discard_line(ini, line_start);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '"') {
|
||||
/* Handle quoted string value */
|
||||
value_start = p;
|
||||
p = unescape_quoted_value(ini, p);
|
||||
|
||||
/* Was the string empty? */
|
||||
if (p == value_start) {
|
||||
p = discard_line(ini, line_start);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Discard the rest of the line after the string value */
|
||||
p = discard_line(ini, p);
|
||||
|
||||
} else {
|
||||
/* Handle normal value */
|
||||
p += strcspn(p, "\n");
|
||||
trim_back(ini, p - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ini_t* ini_load(const char *filename) {
|
||||
ini_t *ini = NULL;
|
||||
FILE *fp = NULL;
|
||||
int n, sz;
|
||||
|
||||
/* Init ini struct */
|
||||
ini = (ini_t*)malloc(sizeof(*ini));
|
||||
if (!ini) {
|
||||
goto fail;
|
||||
}
|
||||
memset(ini, 0, sizeof(*ini));
|
||||
|
||||
/* Open file */
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get file size */
|
||||
fseek(fp, 0, SEEK_END);
|
||||
sz = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
/* Load file content into memory, null terminate, init end var */
|
||||
ini->data = (char*)malloc(sz + 1);
|
||||
ini->data[sz] = '\0';
|
||||
ini->end = ini->data + sz;
|
||||
n = fread(ini->data, 1, sz, fp);
|
||||
if (n != sz) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Prepare data */
|
||||
split_data(ini);
|
||||
|
||||
/* Clean up and return */
|
||||
fclose(fp);
|
||||
return ini;
|
||||
|
||||
fail:
|
||||
if (fp) fclose(fp);
|
||||
if (ini) ini_free(ini);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void ini_free(ini_t *ini) {
|
||||
free(ini->data);
|
||||
free(ini);
|
||||
}
|
||||
|
||||
|
||||
const char* ini_get(ini_t *ini, const char *section, const char *key) {
|
||||
char *current_section = "";
|
||||
char *val;
|
||||
char *p = ini->data;
|
||||
|
||||
if (*p == '\0') {
|
||||
p = next(ini, p);
|
||||
}
|
||||
|
||||
while (p < ini->end) {
|
||||
if (*p == '[') {
|
||||
/* Handle section */
|
||||
current_section = p + 1;
|
||||
|
||||
} else {
|
||||
/* Handle key */
|
||||
val = next(ini, p);
|
||||
if (!section || !strcmpci(section, current_section)) {
|
||||
if (!strcmpci(p, key)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
p = val;
|
||||
}
|
||||
|
||||
p = next(ini, p);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ini_sget(
|
||||
ini_t *ini, const char *section, const char *key,
|
||||
const char *scanfmt, void *dst
|
||||
) {
|
||||
const char *val = ini_get(ini, section, key);
|
||||
if (!val) {
|
||||
return 0;
|
||||
}
|
||||
if (scanfmt) {
|
||||
sscanf(val, scanfmt, dst);
|
||||
} else {
|
||||
*((const char**) dst) = val;
|
||||
}
|
||||
return 1;
|
||||
}
|
20
src_rebuild/utils/ini.h
Normal file
20
src_rebuild/utils/ini.h
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2016 rxi
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the MIT license. See `ini.c` for details.
|
||||
*/
|
||||
|
||||
#ifndef INI_H
|
||||
#define INI_H
|
||||
|
||||
#define INI_VERSION "0.1.1"
|
||||
|
||||
typedef struct ini_t ini_t;
|
||||
|
||||
ini_t* ini_load(const char *filename);
|
||||
void ini_free(ini_t *ini);
|
||||
const char* ini_get(ini_t *ini, const char *section, const char *key);
|
||||
int ini_sget(ini_t *ini, const char *section, const char *key, const char *scanfmt, void *dst);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user