/* * Copyright (C) 2000-2002 Ryan Nunn * * 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; either version 2 of the License, or * (at your option) any later version. * * 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. */ /* * What is this? * * EXCONFIG is a dll that is used by the InstallShield Wizard to get and set the * Black Gate and Serpent Isle paths. * */ #include "stdafx.h" #include "exconfig.h" #include "Configuration.h" #include #define MAX_STRLEN 512 #ifdef _DEBUF #define MessageBoxDebug(a,b,c,d) MessageBox(a,b,c,d); #else #define MessageBoxDebug(a,b,c,d) #endif const std::string c_empty_string; char *config_defaults[] = { "config/disk/game/blackgate/keys", "(default)", "config/disk/game/blackgate/waves", "jmsfx.flx", "config/disk/game/serpentisle/keys", "(default)", "config/disk/game/serpentisle/waves", "jmsisfx.flx", "config/audio/enabled", "yes", "config/audio/effects/enabled", "yes", "config/audio/effects/convert", "gs", "config/audio/midi/enabled", "yes", "config/audio/midi/convert", "gm", "config/audio/midi/reverb/enabled", "no", "config/audio/midi/reverb/level", "0", "config/audio/midi/chorus/enabled", "no", "config/audio/midi/chorus/level", "0", "config/audio/midi/volume_curve", "1.000000", "config/audio/speech/enabled", "yes", "config/gameplay/cheat", "yes", "config/gameplay/skip_intro", "no", "config/gameplay/skip_splash", "no", "config/video/width", "320", "config/video/height", "200", "config/video/scale", "2", "config/video/scale_method", "2xSaI", "config/video/fullscreen", "no", "config/video/disable_fades", "no", "config/video/gamma/red", "1.00", "config/video/gamma/green", "1.00", "config/video/gamma/blue", "1.00", 0 }; class Path { struct Directory { char name[256]; Directory *next; Directory() : next(0) { name[0] = 0; } }; bool network;// Networked? char drive; // Drive letter (if set) Directory *dirs; // Directories void RemoveAll(); int Addit(const char* p); public: Path() : network(false), drive(0), dirs(0) { } Path(const char* p) : network(false), drive(0), dirs(0) { AddString(p); } ~Path(); void RemoveLast() { Addit(".."); } void AddString(const char* p); void GetString(char p[MAX_STRLEN]); }; // Destructor Path::~Path() { RemoveAll(); network = false; drive = 0; } void Path::RemoveAll() { Directory *d = dirs; while (d) { Directory *next = d->next; delete d; d = next; } dirs = 0; } int Path::Addit(const char* p) { Directory *d = dirs; Directory *prev = 0; Directory *prevprev = 0; // Check for . and .. // Create new if (!d) { dirs = d = new Directory; } else { while (d->next) { prevprev = d; d = d->next; } d->next = new Directory; prev = d; d = d->next; } for (int i = 0; p[i] != 0 && p[i] != '\\' && p[i] != '/'; i++) d->name[i] = p[i]; d->name[i] = 0; // Skip all 'slashes' while (p[i] && (p[i] == '\\' || p[i] == '/')) i++; // Check for . and .. if (!std::strcmp(d->name, ".")) { delete d; prev->next = 0; } else if (!std::strcmp(d->name, "..")) { delete d; delete prev; prevprev->next = 0; } return i; } // Add path void Path::AddString(const char *p) { int len = std::strlen (p); // Root dir of this drive if (*p == '\\' || *p == '/') { // Remove all the entires RemoveAll(); p++; // Could be network drive if (*p == '\\') { network = true; p++; } } else if (p[0] && p[1] == ':') // Drive { RemoveAll(); drive = *p; network = false; p+= 2; } // Skip all slashes while (*p && (*p == '\\' || *p == '/')) p++; while (*p) { p+= Addit(p); } } void Path::GetString(char p[MAX_STRLEN]) { p[0] = 0; if (network) std::strncat(p, "\\\\", MAX_STRLEN); else if (drive) _snprintf (p, MAX_STRLEN, "%c:\\", drive); else std::strncat(p, "\\", MAX_STRLEN); Directory *d = dirs; while (d) { std::strncat (p, d->name, MAX_STRLEN); d = d->next; if (d) std::strncat(p, "\\", MAX_STRLEN); } } // The exports #ifdef __cplusplus extern "C" { #endif EXCONFIG_API LONG APIENTRY GetPaths(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { Path path(lpszValue); char p[MAX_STRLEN]; path.AddString("exult.cfg"); path.GetString(p); char *si_pathdef = ""; char *bg_pathdef = ""; MessageBoxDebug (hwnd, lpszValue, p, MB_OK); try { //chdir (lpszValue); Configuration config; config.read_config_file(p); std::string data_directory; config.value("config/disk/game/serpentisle/path",data_directory,si_pathdef); if (data_directory != si_pathdef) { path.~Path(); path.AddString(lpszValue); path.AddString(data_directory.c_str()); path.GetString(p); } else { std::strncpy (p, si_pathdef, MAX_STRLEN); } config.value("config/disk/game/blackgate/path",data_directory,bg_pathdef); if (data_directory != bg_pathdef) { path.~Path(); path.AddString(lpszValue); path.AddString(data_directory.c_str()); path.GetString(lpszValue); } else { std::strncpy (lpszValue, bg_pathdef, MAX_STRLEN); } std::strncat(lpszValue, "\n", MAX_STRLEN); std::strncat(lpszValue, p, MAX_STRLEN); MessageBoxDebug (hwnd, lpszValue, data_directory.c_str(), MB_OK); } catch(...) { std::strncpy(lpszValue, bg_pathdef, MAX_STRLEN); std::strncat(lpszValue, "\n", MAX_STRLEN); std::strncat(lpszValue, si_pathdef, MAX_STRLEN); } return 0; } EXCONFIG_API LONG APIENTRY WriteConfig(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { MessageBoxDebug (hwnd, lpszValue, "WriteConfig", MB_OK); int len = std::strlen (lpszValue); char *p = new char [len+1]; int i, j, bgstart, sistart; for (i = 0; i < len && lpszValue[i] != '\n'; i++) p[i] = lpszValue[i]; p[i] = 0; bgstart = i+1; Path path(p); path.AddString("exult.cfg"); path.GetString(p); MessageBoxDebug (hwnd, p, "WriteConfig: p", MB_OK); try { //chdir (lpszValue); Configuration config; config.read_config_file(p); for (j = 0, i = bgstart; i < len && lpszValue[i] != '\n'; j++, i++) p[j] = lpszValue[i]; p[j] = 0; sistart = i+1; if (j > 1 && p[j-1] == '\\') p[j-1] = 0; MessageBoxDebug (hwnd, p, "WriteConfig: BG", MB_OK); config.set("config/disk/game/blackgate/path", p, true); for (j = 0, i = sistart ; i < len && lpszValue[i]; j++, i++) p[j] = lpszValue[i]; p[j] = 0; if (j > 1 && p[j-1] == '\\') p[j-1] = 0; MessageBoxDebug (hwnd, p, "WriteConfig: SI", MB_OK); config.set("config/disk/game/serpentisle/path", p, true); std::string s; for (i = 0; config_defaults[i]; i+=2) { config.value(config_defaults[i], s, ""); if (s.empty()) config.set(config_defaults[i], config_defaults[i+1], true); } // Fix broken SI SFX stuff config.value("config/disk/game/serpentisle/waves", s, ""); const char *si_sfx = s.c_str(); int slen = std::strlen(si_sfx); slen -= std::strlen ("jmsfxsi.flx"); if (slen >= 0 && !std::strcmp(si_sfx+slen, "jmsfxsi.flx")) { char *fixed = new char[slen+1]; std::strncpy (fixed, si_sfx, slen); fixed[slen] = 0; s = fixed; s += "jmsisfx.flx"; config.set("config/disk/game/serpentisle/waves", s, true); } config.write_back(); } catch(...) { } delete [] p; return 0; } EXCONFIG_API LONG APIENTRY LaunchApp(HWND hwnd, LPLONG lpIValue, LPSTR lpszValue) { Path path(lpszValue); char p[MAX_STRLEN]; PROCESS_INFORMATION pi; STARTUPINFO si; path.RemoveLast(); path.GetString(p); std::memset (&si, 0, sizeof(si)); si.cb = sizeof(si); MessageBoxDebug(hwnd, lpszValue, "LaunchApp", MB_OK); CreateProcess (NULL, lpszValue, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, *lpIValue==1?p:NULL, &si, &pi); return 0; } #ifdef __cplusplus } #endif BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }