diff --git a/src_rebuild/EMULATOR/EMULATOR.C b/src_rebuild/EMULATOR/EMULATOR.C index a90ed25d..5db245f2 100644 --- a/src_rebuild/EMULATOR/EMULATOR.C +++ b/src_rebuild/EMULATOR/EMULATOR.C @@ -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; - } } diff --git a/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H b/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H index e73059e6..b6cf2428 100644 --- a/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H +++ b/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H @@ -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); diff --git a/src_rebuild/EMULATOR/LIBGTE.C b/src_rebuild/EMULATOR/LIBGTE.C index c0ec98d4..c16c6cae 100644 --- a/src_rebuild/EMULATOR/LIBGTE.C +++ b/src_rebuild/EMULATOR/LIBGTE.C @@ -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 } diff --git a/src_rebuild/premake5.lua b/src_rebuild/premake5.lua index 81c7f21c..7bb007f4 100644 --- a/src_rebuild/premake5.lua +++ b/src_rebuild/premake5.lua @@ -87,6 +87,7 @@ project "REDRIVER2" files { "utils/**.h", "utils/**.cpp", + "utils/**.c", "redriver2_psxpc.cpp", "DebugOverlay.cpp", } diff --git a/src_rebuild/redriver2_psxpc.cpp b/src_rebuild/redriver2_psxpc.cpp index f743edcb..593647e5 100644 --- a/src_rebuild/redriver2_psxpc.cpp +++ b/src_rebuild/redriver2_psxpc.cpp @@ -9,6 +9,7 @@ #include "EMULATOR.H" #include "EMULATOR_PRIVATE.H" +#include "utils/ini.h" #include @@ -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(); + } diff --git a/src_rebuild/utils/ini.c b/src_rebuild/utils/ini.c new file mode 100644 index 00000000..f22bd942 --- /dev/null +++ b/src_rebuild/utils/ini.c @@ -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 +#include +#include +#include + +#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; +} diff --git a/src_rebuild/utils/ini.h b/src_rebuild/utils/ini.h new file mode 100644 index 00000000..cd6af9f6 --- /dev/null +++ b/src_rebuild/utils/ini.h @@ -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