From 8d4c747023e8d71661c947aa87fc1e1cdca99bf6 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff <timfelgentreff@gmail.com> Date: Thu, 26 May 2016 01:55:39 +0200 Subject: [PATCH] allow cycling through shaders in both directions, load them from the game's shader directory --- src/include/shaders.h | 2 +- src/stratagus/stratagus.cpp | 1606 +++++++++++++++++------------------ src/video/sdl.cpp | 4 +- src/video/shaders.cpp | 29 +- 4 files changed, 828 insertions(+), 813 deletions(-) diff --git a/src/include/shaders.h b/src/include/shaders.h index 63ba7b26b..57697e8fd 100644 --- a/src/include/shaders.h +++ b/src/include/shaders.h @@ -10,7 +10,7 @@ extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer; #endif extern GLuint fullscreenFramebuffer; extern unsigned ShaderIndex; -extern bool LoadShaders(char* shadernameOut); +extern bool LoadShaders(int direction, char* shadernameOut); extern bool LoadShaderExtensions(); extern void SetupFramebuffer(); extern void RenderFramebufferToScreen(); diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp index c4c7b0d13..c38cf4b9a 100644 --- a/src/stratagus/stratagus.cpp +++ b/src/stratagus/stratagus.cpp @@ -1,803 +1,803 @@ -// _________ __ __ -// / _____// |_____________ _/ |______ ____ __ __ ______ -// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ -// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | -// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > -// \/ \/ \//_____/ \/ -// ______________________ ______________________ -// T H E W A R B E G I N S -// Stratagus - A free fantasy real time strategy game engine -// -/**@name stratagus.cpp - The main file. */ -// -// (c) Copyright 1998-2015 by Lutz Sammer, Francois Beerten, -// Jimmy Salmon, Pali Rohár and cybermind -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; only version 2 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -// 02111-1307, USA. -// - -//@{ - -/** -** @mainpage -** -** @section Introduction Introduction -** -** Welcome to the source code documentation of the Stratagus engine. -** Extract the source documentation with doxygen (http://www.doxygen.org) tool. -** -** Any help to improve this documention is welcome. If you didn't -** understand something or you found an error or a wrong spelling -** or wrong grammar please write an email (including a patch :). -** -** @section Information Information -** -** Visit the https://github.com/Wargus/stratagus web page for the latest news and -** <A HREF="../index.html">Stratagus Info</A> for other documentation. -** -** @section Modules Modules -** -** This are the main modules of the Stratagus engine. -** -** @subsection Map Map -** -** Handles the map. A map is made from tiles. -** -** @see map.h @see map.cpp @see tileset.h @see tileset.cpp -** -** @subsection Unit Unit -** -** Handles units. Units are ships, flyers, buildings, creatures, -** machines. -** -** @see unit.h @see unit.cpp @see unittype.h @see unittype.cpp -** -** @subsection Missile Missile -** -** Handles missiles. Missiles are all other sprites on map -** which are no unit. -** -** @see missile.h @see missile.cpp -** -** @subsection Player Player -** -** Handles players, all units are owned by a player. A player -** could be controlled by a human or a computer. -** -** @see player.h @see player.cpp @see ::CPlayer -** -** @subsection Sound Sound -** -** Handles the high and low level of the sound. There are the -** background music support, voices and sound effects. -** Following low level backends are supported: OSS and SDL. -** -** @todo adpcm file format support for sound effects -** @todo better separation of low and high level, assembler mixing -** support. -** @todo Streaming support of ogg/mp3 files. -** -** @see sound.h @see sound.cpp -** @see script_sound.cpp @see sound_id.cpp @see sound_server.cpp -** @see unitsound.cpp -** @see sdl_audio.cpp -** @see ogg.cpp @see wav.cpp -** -** @subsection Video Video -** -** Handles the high and low level of the graphics. -** This also contains the sprite and linedrawing routines. -** -** See page @ref VideoModule for more information upon supported -** features and video platforms. -** -** @see video.h @see video.cpp -** -** @subsection Network Network -** -** Handles the high and low level of the network protocol. -** The network protocol is needed for multiplayer games. -** -** See page @ref NetworkModule for more information upon supported -** features and API. -** -** @see network.h @see network.cpp -** -** @subsection Pathfinder Pathfinder -** -** @see pathfinder.h @see pathfinder.cpp -** -** @subsection AI AI -** -** There are currently two AI's. The old one is very hardcoded, -** but does things like placing buildings better than the new. -** The old AI shouldn't be used. The new is very flexible, but -** very basic. It includes none optimations. -** -** See page @ref AiModule for more information upon supported -** features and API. -** -** @see ai_local.h -** @see ai.h @see ai.cpp -** -** @subsection CCL CCL -** -** CCL is Craft Configuration Language, which is used to -** configure and customize Stratagus. -** -** @see script.h @see script.cpp -** -** @subsection Icon Icon -** -** @see icons.h @see icons.cpp -** -** @subsection Editor Editor -** -** This is the integrated editor, it shouldn't be a perfect -** editor. It is used to test new features of the engine. -** -** See page @ref EditorModule for more information upon supported -** features and API. -** -** @see editor.h @see editor.cpp -*/ - -/*---------------------------------------------------------------------------- --- Includes -----------------------------------------------------------------------------*/ - -#include <ctype.h> - -#ifdef USE_BEOS -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> - -extern void beos_init(int argc, char **argv); - -#endif - -#ifdef MAC_BUNDLE -#define Button ButtonOSX -#include <Carbon/Carbon.h> -#undef Button -#endif - -#include "SDL.h" - -#include "stratagus.h" - -#include "ai.h" -#include "editor.h" -#include "game.h" -#include "guichan.h" -#include "interface.h" -#include "iocompat.h" -#include "iolib.h" -#include "map.h" -#include "netconnect.h" -#include "network.h" -#include "parameters.h" -#include "player.h" -#include "replay.h" -#include "results.h" -#include "settings.h" -#include "sound_server.h" -#include "title.h" -#include "translate.h" -#include "ui.h" -#include "unit_manager.h" -#include "version.h" -#include "video.h" -#include "widgets.h" -#include "util.h" - -#include "missile.h" //for FreeBurningBuildingFrames - -#ifdef USE_STACKTRACE -#include <stdexcept> -#include <stacktrace/call_stack.hpp> -#include <stacktrace/stack_exception.hpp> -#endif - -#include <stdlib.h> -#include <stdio.h> - -#ifdef USE_WIN32 -#include <windows.h> -#include <dbghelp.h> -#endif - -#if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT) -#include "windows.h" -#define REDIRECT_OUTPUT -#endif - -#if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT) -#include "SetupConsole_win32.h" -#endif - -/*---------------------------------------------------------------------------- --- Variables -----------------------------------------------------------------------------*/ - -std::string StratagusLibPath; /// Path for data directory - -/// Name, Version, Copyright -const char NameLine[] = NAME " v" VERSION ", " COPYRIGHT; - -std::string CliMapName; /// Filename of the map given on the command line -std::string MenuRace; - -bool EnableDebugPrint; /// if enabled, print the debug messages -bool EnableAssert; /// if enabled, halt on assertion failures -bool EnableUnitDebug; /// if enabled, a unit info dump will be created - -/*============================================================================ -== MAIN -============================================================================*/ - -/** -** Pre menu setup. -*/ -void PreMenuSetup() -{ - // - // Initial menus require some gfx. - // - SetDefaultTextColors(FontYellow, FontWhite); - - LoadFonts(); - - InitVideoCursors(); - - if (MenuRace.empty()) { - LoadCursors(PlayerRaces.Name[0]); - } else { - LoadCursors(MenuRace); - } - - InitSettings(); - - InitUserInterface(); - UI.Load(); -} - -/** -** Run the guichan main menus loop. -** -** @return 0 for success, else exit. -*/ -static int MenuLoop() -{ - int status; - - initGuichan(); - InterfaceState = IfaceStateMenu; - // Clear screen - Video.ClearScreen(); - Invalidate(); - - ButtonUnderCursor = -1; - OldButtonUnderCursor = -1; - CursorState = CursorStatePoint; - GameCursor = UI.Point.Cursor; - - // FIXME delete this when switching to full guichan GUI - const std::string filename = LibraryFileName("scripts/guichan.lua"); - status = LuaLoadFile(filename); - - // We clean up later in Exit - return status; -} - -//---------------------------------------------------------------------------- - -/** -** Print headerline, copyright, ... -*/ -static void PrintHeader() -{ - std::string CompileOptions = -#ifdef DEBUG - "DEBUG " -#endif -#ifdef USE_ZLIB - "ZLIB " -#endif -#ifdef USE_BZ2LIB - "BZ2LIB " -#endif -#ifdef USE_VORBIS - "VORBIS " -#endif -#ifdef USE_THEORA - "THEORA " -#endif -#ifdef USE_FLUIDSYNTH - "FLUIDSYNTH " -#endif -#ifdef USE_MIKMOD - "MIKMOD " -#endif -#ifdef USE_MNG - "MNG " -#endif -#ifdef USE_OPENGL - "OPENGL " -#endif -#ifdef USE_GLES - "GLES " -#endif -#ifdef USE_WIN32 - "WIN32 " -#endif -#ifdef USE_LINUX - "LINUX " -#endif -#ifdef USE_BSD - "BSD " -#endif -#ifdef USE_BEOS - "BEOS " -#endif -#ifdef USE_MAC - "MAC " -#endif -#ifdef USE_X11 - "X11 " -#endif -#ifdef USE_TOUCHSCREEN - "TOUCHSCREEN " -#endif - ""; - - fprintf(stdout, - "%s\n written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n" - " Jon Gabrielson, Andreas Arens, Nehal Mistry, Jimmy Salmon, Pali Rohar,\n" - " cybermind and others.\n" - "\t" HOMEPAGE "\n" - "Compile options %s", - NameLine, CompileOptions.c_str()); -} - -void PrintLicense() -{ - printf("\n" - "\n" - "Stratagus may be copied only under the terms of the GNU General Public License\n" - "which may be found in the Stratagus source kit.\n" - "\n" - "DISCLAIMER:\n" - "This software is provided as-is. The author(s) can not be held liable for any\n" - "damage that might arise from the use of this software.\n" - "Use it at your own risk.\n" - "\n"); -} - - -/** -** Exit the game. -** -** @param err Error code to pass to shell. -*/ -void Exit(int err) -{ - if (GameRunning) { - StopGame(GameExit); - return; - } - - StopMusic(); - QuitSound(); - NetworkQuitGame(); - - ExitNetwork1(); - CleanModules(); - FreeBurningBuildingFrames(); - FreeSounds(); - FreeGraphics(); - FreePlayerColors(); - FreeButtonStyles(); - FreeAllContainers(); - freeGuichan(); - DebugPrint("Frames %lu, Slow frames %d = %ld%%\n" _C_ - FrameCounter _C_ SlowFrameCounter _C_ - (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1)); - lua_settop(Lua, 0); - lua_close(Lua); - DeInitVideo(); - - fprintf(stdout, "%s", _("Thanks for playing Stratagus.\n")); - exit(err); -} - -/** -** Do a fatal exit. -** Called on out of memory or crash. -** -** @param err Error code to pass to shell. -*/ -void ExitFatal(int err) -{ -#ifdef USE_STACKTRACE - throw stacktrace::stack_runtime_error((const char*)err); -#endif - exit(err); -} - -/** -** Display the usage. -*/ -static void Usage() -{ - PrintHeader(); - printf( - "\n\nUsage: %s [OPTIONS] [map.smp|map.smp.gz]\n" - "\t-a\t\tEnables asserts check in engine code (for debugging)\n" - "\t-c file.lua\tConfiguration start file (default stratagus.lua)\n" - "\t-d datapath\tPath to stratagus data (default current directory)\n" - "\t-D depth\tVideo mode depth = pixel per point\n" - "\t-e\t\tStart editor (instead of game)\n" - "\t-E file.lua\tEditor configuration start file (default editor.lua)\n" - "\t-F\t\tFull screen video mode\n" - "\t-G \"options\"\tGame options (passed to game scripts)\n" - "\t-h\t\tHelp shows this page\n" - "\t-i\t\tEnables unit info dumping into log (for debugging)\n" - "\t-I addr\t\tNetwork address to use\n" - "\t-l\t\tDisable command log\n" - "\t-N name\t\tName of the player\n" -#if defined(USE_OPENGL) || defined(USE_GLES) - "\t-o\t\tDo not use OpenGL or OpenGL ES 1.1\n" - "\t-O\t\tUse OpenGL or OpenGL ES 1.1\n" -#endif - "\t-p\t\tEnables debug messages printing in console\n" - "\t-P port\t\tNetwork port to use\n" - "\t-s sleep\tNumber of frames for the AI to sleep before it starts\n" - "\t-S speed\tSync speed (100 = 30 frames/s)\n" - "\t-u userpath\tPath where stratagus saves preferences, log and savegame\n" - "\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n" - "\t-W\t\tWindowed video mode\n" -#if defined(USE_OPENGL) || defined(USE_GLES) - "\t-x idx\t\tControls fullscreen scaling if your graphics card supports shaders.\n"\ - "\t \t\tPass 1 for nearest-neigubour, 2 for EPX/AdvMame, 3 for HQx, 4 for SAL, 5 for SuperEagle\n"\ - "\t \t\tYou can also use Ctrl+Alt+/ to cycle between these scaling algorithms at runtime.\n" - "\t \t\tPass -1 to force old-school nearest neighbour scaling without shaders\n"\ - "\t-Z\t\tUse OpenGL to scale the screen to the viewport (retro-style). Implies -O.\n" -#endif - "map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n", - Parameters::Instance.applicationName.c_str()); -} - -#ifdef REDIRECT_OUTPUT - -static std::string stdoutFile; -static std::string stderrFile; - -static void CleanupOutput() -{ - fclose(stdout); - fclose(stderr); - - struct stat st; - if (stat(stdoutFile.c_str(), &st) == 0 && st.st_size == 0) { - unlink(stdoutFile.c_str()); - } - if (stat(stderrFile.c_str(), &st) == 0 && st.st_size == 0) { - unlink(stderrFile.c_str()); - } -} - -static void RedirectOutput() -{ - std::string path = Parameters::Instance.GetUserDirectory(); - - makedir(path.c_str(), 0777); - - stdoutFile = path + "\\stdout.txt"; - stderrFile = path + "\\stderr.txt"; - - if (!freopen(stdoutFile.c_str(), "w", stdout)) { - printf("freopen stdout failed"); - } - if (!freopen(stderrFile.c_str(), "w", stderr)) { - printf("freopen stderr failed"); - } - atexit(CleanupOutput); -} -#endif - -void ParseCommandLine(int argc, char **argv, Parameters ¶meters) -{ - for (;;) { - switch (getopt(argc, argv, "ac:d:D:eE:FG:hiI:lN:oOP:ps:S:u:v:Wx:Z?-")) { - case 'a': - EnableAssert = true; - continue; - case 'c': - parameters.luaStartFilename = optarg; - if (strlen(optarg) > 4 && - !(strstr(optarg, ".lua") == optarg + strlen(optarg) - 4)) { - parameters.luaStartFilename += ".lua"; - } - continue; - case 'd': { - StratagusLibPath = optarg; - size_t index; - while ((index = StratagusLibPath.find('\\')) != std::string::npos) { - StratagusLibPath[index] = '/'; - } - continue; - } - case 'D': - Video.Depth = atoi(optarg); - continue; - case 'e': - Editor.Running = EditorCommandLine; - continue; - case 'E': - parameters.luaEditorStartFilename = optarg; - continue; - case 'F': - VideoForceFullScreen = 1; - Video.FullScreen = 1; - continue; - case 'G': - parameters.luaScriptArguments = optarg; - continue; - case 'i': - EnableUnitDebug = true; - continue; - case 'I': - CNetworkParameter::Instance.localHost = optarg; - continue; - case 'l': - CommandLogDisabled = true; - continue; - case 'N': - parameters.LocalPlayerName = optarg; - continue; -#if defined(USE_OPENGL) || defined(USE_GLES) - case 'o': - ForceUseOpenGL = 1; - UseOpenGL = 0; - if (ZoomNoResize) { - fprintf(stderr, "Error: -Z only works with OpenGL enabled\n"); - Usage(); - ExitFatal(-1); - } - continue; - case 'O': - ForceUseOpenGL = 1; - UseOpenGL = 1; - continue; -#endif - case 'P': - CNetworkParameter::Instance.localPort = atoi(optarg); - continue; - case 'p': - EnableDebugPrint = true; - continue; - case 's': - AiSleepCycles = atoi(optarg); - continue; - case 'S': - VideoSyncSpeed = atoi(optarg); - continue; - case 'u': - Parameters::Instance.SetUserDirectory(optarg); - continue; - case 'v': { - char *sep = strchr(optarg, 'x'); - if (!sep || !*(sep + 1)) { - fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg); - Usage(); - ExitFatal(-1); - } - Video.Height = atoi(sep + 1); - *sep = 0; - Video.Width = atoi(optarg); - if (!Video.Height || !Video.Width) { - fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1); - Usage(); - ExitFatal(-1); - } -#if defined(USE_OPENGL) || defined(USE_GLES) - if (ZoomNoResize) { - Video.ViewportHeight = Video.Height; - Video.ViewportWidth = Video.Width; - Video.Height = 0; - Video.Width = 0; - } -#endif - continue; - } - case 'W': - VideoForceFullScreen = 1; - Video.FullScreen = 0; - continue; -#if defined(USE_OPENGL) || defined(USE_GLES) - case 'x': - ShaderIndex = atoi(optarg) % MAX_SHADERS; - if (atoi(optarg) == -1) { - GLShaderPipelineSupported = false; - } - continue; - case 'Z': - ForceUseOpenGL = 1; - UseOpenGL = 1; - ZoomNoResize = 1; - Video.ViewportHeight = Video.Height; - Video.ViewportWidth = Video.Width; - Video.Height = 0; - Video.Width = 0; - continue; -#endif - case -1: - break; - case '?': - case 'h': - default: - Usage(); - ExitFatal(-1); - } - break; - } - - if (argc - optind > 1) { - fprintf(stderr, "too many map files. if you meant to pass game arguments, these go after '--'\n"); - Usage(); - ExitFatal(-1); - } - - if (argc - optind) { - size_t index; - CliMapName = argv[optind]; - while ((index = CliMapName.find('\\')) != std::string::npos) { - CliMapName[index] = '/'; - } - } -} - -#ifdef USE_WIN32 -static LONG WINAPI CreateDumpFile(EXCEPTION_POINTERS *ExceptionInfo) -{ - HANDLE hFile = CreateFile("crash.dmp", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - MINIDUMP_EXCEPTION_INFORMATION mei; - mei.ThreadId = GetCurrentThreadId(); - mei.ClientPointers = TRUE; - mei.ExceptionPointers = ExceptionInfo; - MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mei, NULL, NULL); - fprintf(stderr, "Stratagus crashed!\n"); - fprintf(stderr, "A mini dump file \"crash.dmp\" has been created in the Stratagus folder.\n"); - fprintf(stderr, "Please send it to our bug tracker: https://github.com/Wargus/stratagus/issues\n"); - fprintf(stderr, "and tell us what caused this bug to occur.\n"); - return EXCEPTION_EXECUTE_HANDLER; -} -#endif - -/** -** The main program: initialise, parse options and arguments. -** -** @param argc Number of arguments. -** @param argv Vector of arguments. -*/ -int stratagusMain(int argc, char **argv) -{ -#ifdef USE_BEOS - // Parse arguments for BeOS - beos_init(argc, argv); -#endif -#ifdef USE_WIN32 - SetUnhandledExceptionFilter(CreateDumpFile); -#endif -#if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT) - SetupConsole(); -#endif - // Setup some defaults. -#ifndef MAC_BUNDLE - StratagusLibPath = "."; -#else - freopen("/tmp/stdout.txt", "w", stdout); - freopen("/tmp/stderr.txt", "w", stderr); - // Look for the specified data set inside the application bundle - // This should be a subdir of the Resources directory - CFURLRef pluginRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), - CFSTR(MAC_BUNDLE_DATADIR), NULL, NULL); - CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle); - const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding()); - Assert(pathPtr); - StratagusLibPath = pathPtr; -#endif -#ifdef USE_STACKTRACE - try { -#endif - Parameters ¶meters = Parameters::Instance; - parameters.SetDefaultValues(); - parameters.SetLocalPlayerNameFromEnv(); - -#ifdef REDIRECT_OUTPUT - RedirectOutput(); -#endif - - if (argc > 0) { - parameters.applicationName = argv[0]; - } - - // FIXME: Parse options before or after scripts? - ParseCommandLine(argc, argv, parameters); - // Init the random number generator. - InitSyncRand(); - - makedir(parameters.GetUserDirectory().c_str(), 0777); - - // Init Lua and register lua functions! - InitLua(); - LuaRegisterModules(); - - // Initialise AI module - InitAiModule(); - - LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments); - - PrintHeader(); - PrintLicense(); - - // Setup video display - InitVideo(); - - // Setup sound card - if (!InitSound()) { - InitMusic(); - } - -#ifndef DEBUG // For debug it's better not to have: - srand(time(NULL)); // Random counter = random each start -#endif - - // Show title screens. - SetDefaultTextColors(FontYellow, FontWhite); - LoadFonts(); - SetClipping(0, 0, Video.Width - 1, Video.Height - 1); - Video.ClearScreen(); - ShowTitleScreens(); - - // Init player data - ThisPlayer = NULL; - //Don't clear the Players structure as it would erase the allowed units. - // memset(Players, 0, sizeof(Players)); - NumPlayers = 0; - - UnitManager.Init(); // Units memory management - PreMenuSetup(); // Load everything needed for menus - - MenuLoop(); - - Exit(0); -#ifdef USE_STACKTRACE - } catch (const std::exception &e) { - fprintf(stderr, "Stratagus crashed!\n"); - fprintf(stderr, "Please send this call stack to our bug tracker: https://github.com/Wargus/stratagus/issues\n"); - fprintf(stderr, "and tell us what caused this bug to occur.\n"); - fprintf(stderr, " === exception state traceback === \n"); - fprintf(stderr, "%s", e.what()); - exit(1); - } -#endif - return 0; -} - -//@} +// _________ __ __ +// / _____// |_____________ _/ |______ ____ __ __ ______ +// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ +// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | +// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > +// \/ \/ \//_____/ \/ +// ______________________ ______________________ +// T H E W A R B E G I N S +// Stratagus - A free fantasy real time strategy game engine +// +/**@name stratagus.cpp - The main file. */ +// +// (c) Copyright 1998-2015 by Lutz Sammer, Francois Beerten, +// Jimmy Salmon, Pali Rohár and cybermind +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; only version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// + +//@{ + +/** +** @mainpage +** +** @section Introduction Introduction +** +** Welcome to the source code documentation of the Stratagus engine. +** Extract the source documentation with doxygen (http://www.doxygen.org) tool. +** +** Any help to improve this documention is welcome. If you didn't +** understand something or you found an error or a wrong spelling +** or wrong grammar please write an email (including a patch :). +** +** @section Information Information +** +** Visit the https://github.com/Wargus/stratagus web page for the latest news and +** <A HREF="../index.html">Stratagus Info</A> for other documentation. +** +** @section Modules Modules +** +** This are the main modules of the Stratagus engine. +** +** @subsection Map Map +** +** Handles the map. A map is made from tiles. +** +** @see map.h @see map.cpp @see tileset.h @see tileset.cpp +** +** @subsection Unit Unit +** +** Handles units. Units are ships, flyers, buildings, creatures, +** machines. +** +** @see unit.h @see unit.cpp @see unittype.h @see unittype.cpp +** +** @subsection Missile Missile +** +** Handles missiles. Missiles are all other sprites on map +** which are no unit. +** +** @see missile.h @see missile.cpp +** +** @subsection Player Player +** +** Handles players, all units are owned by a player. A player +** could be controlled by a human or a computer. +** +** @see player.h @see player.cpp @see ::CPlayer +** +** @subsection Sound Sound +** +** Handles the high and low level of the sound. There are the +** background music support, voices and sound effects. +** Following low level backends are supported: OSS and SDL. +** +** @todo adpcm file format support for sound effects +** @todo better separation of low and high level, assembler mixing +** support. +** @todo Streaming support of ogg/mp3 files. +** +** @see sound.h @see sound.cpp +** @see script_sound.cpp @see sound_id.cpp @see sound_server.cpp +** @see unitsound.cpp +** @see sdl_audio.cpp +** @see ogg.cpp @see wav.cpp +** +** @subsection Video Video +** +** Handles the high and low level of the graphics. +** This also contains the sprite and linedrawing routines. +** +** See page @ref VideoModule for more information upon supported +** features and video platforms. +** +** @see video.h @see video.cpp +** +** @subsection Network Network +** +** Handles the high and low level of the network protocol. +** The network protocol is needed for multiplayer games. +** +** See page @ref NetworkModule for more information upon supported +** features and API. +** +** @see network.h @see network.cpp +** +** @subsection Pathfinder Pathfinder +** +** @see pathfinder.h @see pathfinder.cpp +** +** @subsection AI AI +** +** There are currently two AI's. The old one is very hardcoded, +** but does things like placing buildings better than the new. +** The old AI shouldn't be used. The new is very flexible, but +** very basic. It includes none optimations. +** +** See page @ref AiModule for more information upon supported +** features and API. +** +** @see ai_local.h +** @see ai.h @see ai.cpp +** +** @subsection CCL CCL +** +** CCL is Craft Configuration Language, which is used to +** configure and customize Stratagus. +** +** @see script.h @see script.cpp +** +** @subsection Icon Icon +** +** @see icons.h @see icons.cpp +** +** @subsection Editor Editor +** +** This is the integrated editor, it shouldn't be a perfect +** editor. It is used to test new features of the engine. +** +** See page @ref EditorModule for more information upon supported +** features and API. +** +** @see editor.h @see editor.cpp +*/ + +/*---------------------------------------------------------------------------- +-- Includes +----------------------------------------------------------------------------*/ + +#include <ctype.h> + +#ifdef USE_BEOS +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +extern void beos_init(int argc, char **argv); + +#endif + +#ifdef MAC_BUNDLE +#define Button ButtonOSX +#include <Carbon/Carbon.h> +#undef Button +#endif + +#include "SDL.h" + +#include "stratagus.h" + +#include "ai.h" +#include "editor.h" +#include "game.h" +#include "guichan.h" +#include "interface.h" +#include "iocompat.h" +#include "iolib.h" +#include "map.h" +#include "netconnect.h" +#include "network.h" +#include "parameters.h" +#include "player.h" +#include "replay.h" +#include "results.h" +#include "settings.h" +#include "sound_server.h" +#include "title.h" +#include "translate.h" +#include "ui.h" +#include "unit_manager.h" +#include "version.h" +#include "video.h" +#include "widgets.h" +#include "util.h" + +#include "missile.h" //for FreeBurningBuildingFrames + +#ifdef USE_STACKTRACE +#include <stdexcept> +#include <stacktrace/call_stack.hpp> +#include <stacktrace/stack_exception.hpp> +#endif + +#include <stdlib.h> +#include <stdio.h> + +#ifdef USE_WIN32 +#include <windows.h> +#include <dbghelp.h> +#endif + +#if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT) +#include "windows.h" +#define REDIRECT_OUTPUT +#endif + +#if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT) +#include "SetupConsole_win32.h" +#endif + +/*---------------------------------------------------------------------------- +-- Variables +----------------------------------------------------------------------------*/ + +std::string StratagusLibPath; /// Path for data directory + +/// Name, Version, Copyright +const char NameLine[] = NAME " v" VERSION ", " COPYRIGHT; + +std::string CliMapName; /// Filename of the map given on the command line +std::string MenuRace; + +bool EnableDebugPrint; /// if enabled, print the debug messages +bool EnableAssert; /// if enabled, halt on assertion failures +bool EnableUnitDebug; /// if enabled, a unit info dump will be created + +/*============================================================================ +== MAIN +============================================================================*/ + +/** +** Pre menu setup. +*/ +void PreMenuSetup() +{ + // + // Initial menus require some gfx. + // + SetDefaultTextColors(FontYellow, FontWhite); + + LoadFonts(); + + InitVideoCursors(); + + if (MenuRace.empty()) { + LoadCursors(PlayerRaces.Name[0]); + } else { + LoadCursors(MenuRace); + } + + InitSettings(); + + InitUserInterface(); + UI.Load(); +} + +/** +** Run the guichan main menus loop. +** +** @return 0 for success, else exit. +*/ +static int MenuLoop() +{ + int status; + + initGuichan(); + InterfaceState = IfaceStateMenu; + // Clear screen + Video.ClearScreen(); + Invalidate(); + + ButtonUnderCursor = -1; + OldButtonUnderCursor = -1; + CursorState = CursorStatePoint; + GameCursor = UI.Point.Cursor; + + // FIXME delete this when switching to full guichan GUI + const std::string filename = LibraryFileName("scripts/guichan.lua"); + status = LuaLoadFile(filename); + + // We clean up later in Exit + return status; +} + +//---------------------------------------------------------------------------- + +/** +** Print headerline, copyright, ... +*/ +static void PrintHeader() +{ + std::string CompileOptions = +#ifdef DEBUG + "DEBUG " +#endif +#ifdef USE_ZLIB + "ZLIB " +#endif +#ifdef USE_BZ2LIB + "BZ2LIB " +#endif +#ifdef USE_VORBIS + "VORBIS " +#endif +#ifdef USE_THEORA + "THEORA " +#endif +#ifdef USE_FLUIDSYNTH + "FLUIDSYNTH " +#endif +#ifdef USE_MIKMOD + "MIKMOD " +#endif +#ifdef USE_MNG + "MNG " +#endif +#ifdef USE_OPENGL + "OPENGL " +#endif +#ifdef USE_GLES + "GLES " +#endif +#ifdef USE_WIN32 + "WIN32 " +#endif +#ifdef USE_LINUX + "LINUX " +#endif +#ifdef USE_BSD + "BSD " +#endif +#ifdef USE_BEOS + "BEOS " +#endif +#ifdef USE_MAC + "MAC " +#endif +#ifdef USE_X11 + "X11 " +#endif +#ifdef USE_TOUCHSCREEN + "TOUCHSCREEN " +#endif + ""; + + fprintf(stdout, + "%s\n written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n" + " Jon Gabrielson, Andreas Arens, Nehal Mistry, Jimmy Salmon, Pali Rohar,\n" + " cybermind and others.\n" + "\t" HOMEPAGE "\n" + "Compile options %s", + NameLine, CompileOptions.c_str()); +} + +void PrintLicense() +{ + printf("\n" + "\n" + "Stratagus may be copied only under the terms of the GNU General Public License\n" + "which may be found in the Stratagus source kit.\n" + "\n" + "DISCLAIMER:\n" + "This software is provided as-is. The author(s) can not be held liable for any\n" + "damage that might arise from the use of this software.\n" + "Use it at your own risk.\n" + "\n"); +} + + +/** +** Exit the game. +** +** @param err Error code to pass to shell. +*/ +void Exit(int err) +{ + if (GameRunning) { + StopGame(GameExit); + return; + } + + StopMusic(); + QuitSound(); + NetworkQuitGame(); + + ExitNetwork1(); + CleanModules(); + FreeBurningBuildingFrames(); + FreeSounds(); + FreeGraphics(); + FreePlayerColors(); + FreeButtonStyles(); + FreeAllContainers(); + freeGuichan(); + DebugPrint("Frames %lu, Slow frames %d = %ld%%\n" _C_ + FrameCounter _C_ SlowFrameCounter _C_ + (SlowFrameCounter * 100) / (FrameCounter ? FrameCounter : 1)); + lua_settop(Lua, 0); + lua_close(Lua); + DeInitVideo(); + + fprintf(stdout, "%s", _("Thanks for playing Stratagus.\n")); + exit(err); +} + +/** +** Do a fatal exit. +** Called on out of memory or crash. +** +** @param err Error code to pass to shell. +*/ +void ExitFatal(int err) +{ +#ifdef USE_STACKTRACE + throw stacktrace::stack_runtime_error((const char*)err); +#endif + exit(err); +} + +/** +** Display the usage. +*/ +static void Usage() +{ + PrintHeader(); + printf( + "\n\nUsage: %s [OPTIONS] [map.smp|map.smp.gz]\n" + "\t-a\t\tEnables asserts check in engine code (for debugging)\n" + "\t-c file.lua\tConfiguration start file (default stratagus.lua)\n" + "\t-d datapath\tPath to stratagus data (default current directory)\n" + "\t-D depth\tVideo mode depth = pixel per point\n" + "\t-e\t\tStart editor (instead of game)\n" + "\t-E file.lua\tEditor configuration start file (default editor.lua)\n" + "\t-F\t\tFull screen video mode\n" + "\t-G \"options\"\tGame options (passed to game scripts)\n" + "\t-h\t\tHelp shows this page\n" + "\t-i\t\tEnables unit info dumping into log (for debugging)\n" + "\t-I addr\t\tNetwork address to use\n" + "\t-l\t\tDisable command log\n" + "\t-N name\t\tName of the player\n" +#if defined(USE_OPENGL) || defined(USE_GLES) + "\t-o\t\tDo not use OpenGL or OpenGL ES 1.1\n" + "\t-O\t\tUse OpenGL or OpenGL ES 1.1\n" +#endif + "\t-p\t\tEnables debug messages printing in console\n" + "\t-P port\t\tNetwork port to use\n" + "\t-s sleep\tNumber of frames for the AI to sleep before it starts\n" + "\t-S speed\tSync speed (100 = 30 frames/s)\n" + "\t-u userpath\tPath where stratagus saves preferences, log and savegame\n" + "\t-v mode\t\tVideo mode resolution in format <xres>x<yres>\n" + "\t-W\t\tWindowed video mode\n" +#if defined(USE_OPENGL) || defined(USE_GLES) + "\t-x idx\t\tControls fullscreen scaling if your graphics card supports shaders.\n"\ + "\t \t\tPass 1 for nearest-neigubour, 2 for EPX/AdvMame, 3 for HQx, 4 for SAL, 5 for SuperEagle\n"\ + "\t \t\tYou can also use Ctrl+Alt+/ to cycle between these scaling algorithms at runtime.\n" + "\t \t\tPass -1 to force old-school nearest neighbour scaling without shaders\n"\ + "\t-Z\t\tUse OpenGL to scale the screen to the viewport (retro-style). Implies -O.\n" +#endif + "map is relative to StratagusLibPath=datapath, use ./map for relative to cwd\n", + Parameters::Instance.applicationName.c_str()); +} + +#ifdef REDIRECT_OUTPUT + +static std::string stdoutFile; +static std::string stderrFile; + +static void CleanupOutput() +{ + fclose(stdout); + fclose(stderr); + + struct stat st; + if (stat(stdoutFile.c_str(), &st) == 0 && st.st_size == 0) { + unlink(stdoutFile.c_str()); + } + if (stat(stderrFile.c_str(), &st) == 0 && st.st_size == 0) { + unlink(stderrFile.c_str()); + } +} + +static void RedirectOutput() +{ + std::string path = Parameters::Instance.GetUserDirectory(); + + makedir(path.c_str(), 0777); + + stdoutFile = path + "\\stdout.txt"; + stderrFile = path + "\\stderr.txt"; + + if (!freopen(stdoutFile.c_str(), "w", stdout)) { + printf("freopen stdout failed"); + } + if (!freopen(stderrFile.c_str(), "w", stderr)) { + printf("freopen stderr failed"); + } + atexit(CleanupOutput); +} +#endif + +void ParseCommandLine(int argc, char **argv, Parameters ¶meters) +{ + for (;;) { + switch (getopt(argc, argv, "ac:d:D:eE:FG:hiI:lN:oOP:ps:S:u:v:Wx:Z?-")) { + case 'a': + EnableAssert = true; + continue; + case 'c': + parameters.luaStartFilename = optarg; + if (strlen(optarg) > 4 && + !(strstr(optarg, ".lua") == optarg + strlen(optarg) - 4)) { + parameters.luaStartFilename += ".lua"; + } + continue; + case 'd': { + StratagusLibPath = optarg; + size_t index; + while ((index = StratagusLibPath.find('\\')) != std::string::npos) { + StratagusLibPath[index] = '/'; + } + continue; + } + case 'D': + Video.Depth = atoi(optarg); + continue; + case 'e': + Editor.Running = EditorCommandLine; + continue; + case 'E': + parameters.luaEditorStartFilename = optarg; + continue; + case 'F': + VideoForceFullScreen = 1; + Video.FullScreen = 1; + continue; + case 'G': + parameters.luaScriptArguments = optarg; + continue; + case 'i': + EnableUnitDebug = true; + continue; + case 'I': + CNetworkParameter::Instance.localHost = optarg; + continue; + case 'l': + CommandLogDisabled = true; + continue; + case 'N': + parameters.LocalPlayerName = optarg; + continue; +#if defined(USE_OPENGL) || defined(USE_GLES) + case 'o': + ForceUseOpenGL = 1; + UseOpenGL = 0; + if (ZoomNoResize) { + fprintf(stderr, "Error: -Z only works with OpenGL enabled\n"); + Usage(); + ExitFatal(-1); + } + continue; + case 'O': + ForceUseOpenGL = 1; + UseOpenGL = 1; + continue; +#endif + case 'P': + CNetworkParameter::Instance.localPort = atoi(optarg); + continue; + case 'p': + EnableDebugPrint = true; + continue; + case 's': + AiSleepCycles = atoi(optarg); + continue; + case 'S': + VideoSyncSpeed = atoi(optarg); + continue; + case 'u': + Parameters::Instance.SetUserDirectory(optarg); + continue; + case 'v': { + char *sep = strchr(optarg, 'x'); + if (!sep || !*(sep + 1)) { + fprintf(stderr, "%s: incorrect format of video mode resolution -- '%s'\n", argv[0], optarg); + Usage(); + ExitFatal(-1); + } + Video.Height = atoi(sep + 1); + *sep = 0; + Video.Width = atoi(optarg); + if (!Video.Height || !Video.Width) { + fprintf(stderr, "%s: incorrect format of video mode resolution -- '%sx%s'\n", argv[0], optarg, sep + 1); + Usage(); + ExitFatal(-1); + } +#if defined(USE_OPENGL) || defined(USE_GLES) + if (ZoomNoResize) { + Video.ViewportHeight = Video.Height; + Video.ViewportWidth = Video.Width; + Video.Height = 0; + Video.Width = 0; + } +#endif + continue; + } + case 'W': + VideoForceFullScreen = 1; + Video.FullScreen = 0; + continue; +#if defined(USE_OPENGL) || defined(USE_GLES) + case 'x': + ShaderIndex = atoi(optarg); + if (atoi(optarg) == -1) { + GLShaderPipelineSupported = false; + } + continue; + case 'Z': + ForceUseOpenGL = 1; + UseOpenGL = 1; + ZoomNoResize = 1; + Video.ViewportHeight = Video.Height; + Video.ViewportWidth = Video.Width; + Video.Height = 0; + Video.Width = 0; + continue; +#endif + case -1: + break; + case '?': + case 'h': + default: + Usage(); + ExitFatal(-1); + } + break; + } + + if (argc - optind > 1) { + fprintf(stderr, "too many map files. if you meant to pass game arguments, these go after '--'\n"); + Usage(); + ExitFatal(-1); + } + + if (argc - optind) { + size_t index; + CliMapName = argv[optind]; + while ((index = CliMapName.find('\\')) != std::string::npos) { + CliMapName[index] = '/'; + } + } +} + +#ifdef USE_WIN32 +static LONG WINAPI CreateDumpFile(EXCEPTION_POINTERS *ExceptionInfo) +{ + HANDLE hFile = CreateFile("crash.dmp", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + MINIDUMP_EXCEPTION_INFORMATION mei; + mei.ThreadId = GetCurrentThreadId(); + mei.ClientPointers = TRUE; + mei.ExceptionPointers = ExceptionInfo; + MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mei, NULL, NULL); + fprintf(stderr, "Stratagus crashed!\n"); + fprintf(stderr, "A mini dump file \"crash.dmp\" has been created in the Stratagus folder.\n"); + fprintf(stderr, "Please send it to our bug tracker: https://github.com/Wargus/stratagus/issues\n"); + fprintf(stderr, "and tell us what caused this bug to occur.\n"); + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + +/** +** The main program: initialise, parse options and arguments. +** +** @param argc Number of arguments. +** @param argv Vector of arguments. +*/ +int stratagusMain(int argc, char **argv) +{ +#ifdef USE_BEOS + // Parse arguments for BeOS + beos_init(argc, argv); +#endif +#ifdef USE_WIN32 + SetUnhandledExceptionFilter(CreateDumpFile); +#endif +#if defined(USE_WIN32) && ! defined(REDIRECT_OUTPUT) + SetupConsole(); +#endif + // Setup some defaults. +#ifndef MAC_BUNDLE + StratagusLibPath = "."; +#else + freopen("/tmp/stdout.txt", "w", stdout); + freopen("/tmp/stderr.txt", "w", stderr); + // Look for the specified data set inside the application bundle + // This should be a subdir of the Resources directory + CFURLRef pluginRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), + CFSTR(MAC_BUNDLE_DATADIR), NULL, NULL); + CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle); + const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding()); + Assert(pathPtr); + StratagusLibPath = pathPtr; +#endif +#ifdef USE_STACKTRACE + try { +#endif + Parameters ¶meters = Parameters::Instance; + parameters.SetDefaultValues(); + parameters.SetLocalPlayerNameFromEnv(); + +#ifdef REDIRECT_OUTPUT + RedirectOutput(); +#endif + + if (argc > 0) { + parameters.applicationName = argv[0]; + } + + // FIXME: Parse options before or after scripts? + ParseCommandLine(argc, argv, parameters); + // Init the random number generator. + InitSyncRand(); + + makedir(parameters.GetUserDirectory().c_str(), 0777); + + // Init Lua and register lua functions! + InitLua(); + LuaRegisterModules(); + + // Initialise AI module + InitAiModule(); + + LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments); + + PrintHeader(); + PrintLicense(); + + // Setup video display + InitVideo(); + + // Setup sound card + if (!InitSound()) { + InitMusic(); + } + +#ifndef DEBUG // For debug it's better not to have: + srand(time(NULL)); // Random counter = random each start +#endif + + // Show title screens. + SetDefaultTextColors(FontYellow, FontWhite); + LoadFonts(); + SetClipping(0, 0, Video.Width - 1, Video.Height - 1); + Video.ClearScreen(); + ShowTitleScreens(); + + // Init player data + ThisPlayer = NULL; + //Don't clear the Players structure as it would erase the allowed units. + // memset(Players, 0, sizeof(Players)); + NumPlayers = 0; + + UnitManager.Init(); // Units memory management + PreMenuSetup(); // Load everything needed for menus + + MenuLoop(); + + Exit(0); +#ifdef USE_STACKTRACE + } catch (const std::exception &e) { + fprintf(stderr, "Stratagus crashed!\n"); + fprintf(stderr, "Please send this call stack to our bug tracker: https://github.com/Wargus/stratagus/issues\n"); + fprintf(stderr, "and tell us what caused this bug to occur.\n"); + fprintf(stderr, " === exception state traceback === \n"); + fprintf(stderr, "%s", e.what()); + exit(1); + } +#endif + return 0; +} + +//@} diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp index 675ae3c28..f36514a15 100644 --- a/src/video/sdl.cpp +++ b/src/video/sdl.cpp @@ -848,11 +848,11 @@ static void SdlDoEvent(const EventCallback &callbacks, SDL_Event &event) case SDL_KEYDOWN: if (GLShaderPipelineSupported - && event.key.keysym.sym == SDLK_SLASH + && (event.key.keysym.sym == SDLK_SLASH || event.key.keysym.sym == SDLK_BACKSLASH) && event.key.keysym.mod & KMOD_ALT && event.key.keysym.mod & KMOD_CTRL) { char shadername[1024] = { '\0' }; - LoadShaders(shadername); + LoadShaders(event.key.keysym.sym == SDLK_SLASH ? 1 : -1, shadername); SetMessage(shadername); break; } diff --git a/src/video/shaders.cpp b/src/video/shaders.cpp index 488a94ff6..de002c1e8 100644 --- a/src/video/shaders.cpp +++ b/src/video/shaders.cpp @@ -81,9 +81,18 @@ void printProgramInfoLog(GLuint obj, const char* prefix) } } -unsigned ShaderIndex = 0; +unsigned ShaderIndex = -1; + +/* This does not have to be very efficient, it is only called when the shader + is changed by the user. + */ +extern bool LoadShaders(int direction, char* shadernameOut) { + ShaderIndex += direction; + if (direction == 0 && ShaderIndex == -1) { + // TODO: load from preferences + ShaderIndex = 0; + } -extern bool LoadShaders(char* shadernameOut) { GLuint vs, fs; GLint params; fs = glCreateShader(GL_FRAGMENT_SHADER); @@ -92,7 +101,13 @@ extern bool LoadShaders(char* shadernameOut) { } std::vector<FileList> flp; - int n = ReadDataDirectory(".", flp); + std::string shaderPath(StratagusLibPath); +#ifdef _WIN32 + shaderPath.append("\\shaders\\"); +#else + shaderPath.append("/shaders/"); +#endif + int n = ReadDataDirectory(shaderPath.c_str(), flp); int numShaderFiles = 0; int shaderFileToIdx[1024]; for (int i = 0; i < n; ++i) { @@ -103,18 +118,18 @@ extern bool LoadShaders(char* shadernameOut) { } } if (numShaderFiles <= 0) return false; - if (numShaderFiles <= ShaderIndex) { + if (numShaderFiles <= ShaderIndex || ShaderIndex < 0) { ShaderIndex = ShaderIndex % numShaderFiles; } if (shadernameOut) { strncpy(shadernameOut, flp[shaderFileToIdx[ShaderIndex]].name.c_str(), 1023); } - std::ifstream myfile(flp[shaderFileToIdx[ShaderIndex]].name); + shaderPath.append(flp[shaderFileToIdx[ShaderIndex]].name); + std::ifstream myfile(shaderPath); std::string contents((std::istreambuf_iterator<char>(myfile)), std::istreambuf_iterator<char>()); myfile.close(); - ShaderIndex++; const char *fragmentSrc[2] = { "#define FRAGMENT\n", contents.c_str() }; const char *vertexSrc[2] = { "#define VERTEX\n", contents.c_str() }; @@ -200,7 +215,7 @@ extern bool LoadShaderExtensions() { glDrawBuffers = (PFNGLDRAWBUFFERSPROC)(uintptr_t)SDL_GL_GetProcAddress("glDrawBuffers"); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(uintptr_t)SDL_GL_GetProcAddress("glCheckFramebufferStatus"); if (glCreateShader && glGenFramebuffers && glGetUniformLocation && glActiveTextureProc) { - return LoadShaders(NULL); + return LoadShaders(0, NULL); } else { return false; }