diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4963f4b88..633b70729 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,12 +22,7 @@ jobs: matrix: os: - runner: windows-latest - preset: win32 - cc: cl - cxx: cl - name: Windows-x86 - - runner: windows-latest - preset: win64 + preset: win cc: cl cxx: cl name: Windows-x64 @@ -80,7 +75,7 @@ jobs: - uses: ilammy/msvc-dev-cmd@v1 if: ${{ matrix.os.runner == 'windows-latest' }} with: - arch: ${{ matrix.os.preset }} + arch: win64 - name: Configure CMake env: diff --git a/CMakeLists.txt b/CMakeLists.txt index 160ee9174..529a76051 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,12 +93,13 @@ install( if(UNIX) add_compile_options("$<$:-Wno-multichar;${BITS};${EXTRA_CXX_FLAGS}>") add_compile_options("$<$:${BITS}>") - - find_package(SDL2 REQUIRED) - # Some versions of the SDL2 find_package set SDL2_INCLUDE_DIR and some set a plural SDL2_INCLUDE_DIRS. Check both. - message("SDL2 Include Dir is ${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS}") endif() +find_package(SDL2 REQUIRED) +# Some versions of the SDL2 find_package set SDL2_INCLUDE_DIR and some set a plural SDL2_INCLUDE_DIRS. Check both. +message("SDL2 Include Dir is ${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS}") + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") message("Building for Linux") add_compile_definitions(__LINUX__ _USE_OGL_ACTIVE_TEXTURES PRIMARY_HOG=\"d3-linux.hog\") @@ -178,13 +179,13 @@ add_subdirectory(czip) add_subdirectory(d3music) add_subdirectory(ddebug) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if(BUILD_EDITOR AND CMAKE_SYSTEM_NAME STREQUAL "Windows") add_subdirectory(dd_grwin32) add_subdirectory(win32) -else() - add_subdirectory(linux) endif() +add_subdirectory(linux) + add_subdirectory(ddio) add_subdirectory(dd_video) add_subdirectory(fix) diff --git a/CMakePresets.json b/CMakePresets.json index 4797cadd3..0b5f90e51 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,25 +7,7 @@ "binaryDir": "${sourceDir}/builds/${presetName}" }, { - "name": "win32", - "inherits": "defaults", - "generator": "Ninja Multi-Config", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - }, - "architecture": { - "strategy": "external", - "value": "x86" - }, - "cacheVariables": { - "VCPKG_TARGET_TRIPLET": "x86-windows-static-md" - }, - "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - }, - { - "name": "win64", + "name": "win", "inherits": "defaults", "generator": "Ninja Multi-Config", "condition": { @@ -65,12 +47,8 @@ ], "buildPresets": [ { - "name": "win32", - "configurePreset": "win32" - }, - { - "name": "win64", - "configurePreset": "win64" + "name": "win", + "configurePreset": "win" }, { "name": "mac", @@ -90,16 +68,10 @@ } }, { - "name": "win32", - "inherits": "defaults", - "description": "Testing under Windows x86", - "configurePreset": "win32" - }, - { - "name": "win64", + "name": "win", "inherits": "defaults", "description": "Testing under Windows x64", - "configurePreset": "win64" + "configurePreset": "win" }, { "name": "mac", diff --git a/Descent3/CMakeLists.txt b/Descent3/CMakeLists.txt index ea6c1d362..212de4d0a 100644 --- a/Descent3/CMakeLists.txt +++ b/Descent3/CMakeLists.txt @@ -268,35 +268,30 @@ set(CPPS voice.cpp weapon.cpp WeaponFire.cpp - weather.cpp) + weather.cpp + loki_utils.c + sdlmain.cpp) if(WIN32) - set(PLATFORM_LIBS dd_grwin32 win32 wsock32.lib winmm.lib - ${DSOUND_LIBRARY} ${DINPUT_LIBRARY} ${DXGUID_LIBRARY} ${DDRAW_LIBRARY}) - set(PLATFORM_CPPS winmain.cpp) + set(PLATFORM_LIBS wsock32.lib winmm.lib) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:LIBC") endif() if(UNIX AND NOT APPLE) - set(PLATFORM_LIBS linux SDL2::SDL2 m ${CMAKE_DL_LIBS}) - set(PLATFORM_CPPS loki_utils.c lnxmain.cpp) + set(PLATFORM_LIBS m ${CMAKE_DL_LIBS}) endif() if(APPLE) - set(PLATFORM_LIBS linux SDL2::SDL2) - set(PLATFORM_CPPS loki_utils.c lnxmain.cpp) + set(PLATFORM_LIBS) set(CMAKE_EXE_LINKER_FLAGS "-framework IOKit -framework Cocoa -framework OpenGL -framework Carbon") endif() file(GLOB_RECURSE INCS "../lib/*.h") -add_executable(Descent3 - WIN32 - ${HEADERS} ${CPPS} ${PLATFORM_CPPS} ${INCS} -) -target_link_libraries(Descent3 +add_executable(Descent3 WIN32 ${HEADERS} ${CPPS} ${INCS}) +target_link_libraries(Descent3 PRIVATE 2dlib AudioEncode bitmap cfile czip d3music dd_video ddebug ddio libmve libacm - fix grtext manage mem misc model module movie stream_audio + fix grtext manage mem misc model module movie stream_audio linux SDL2::SDL2 music networking physics renderer rtperformance sndlib ui unzip vecmat md5 ${PLATFORM_LIBS}) target_include_directories(Descent3 PRIVATE ${PROJECT_BINARY_DIR}/lib) diff --git a/Descent3/SDLMain.h b/Descent3/SDLMain.h deleted file mode 100644 index 1914aed41..000000000 --- a/Descent3/SDLMain.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . -*/ - -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#ifndef _SDLMain_h_ -#define _SDLMain_h_ - -#import - -@interface SDLMain : NSObject -@end - -#endif /* _SDLMain_h_ */ diff --git a/Descent3/SDLMain.m b/Descent3/SDLMain.m deleted file mode 100644 index 2434f81aa..000000000 --- a/Descent3/SDLMain.m +++ /dev/null @@ -1,381 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#include "SDL.h" -#include "SDLMain.h" -#include /* for MAXPATHLEN */ -#include - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - const NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface NSApplication (SDLApplication) -@end - -@implementation NSApplication (SDLApplication) -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { - chdir(parentdir); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [NSApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/Descent3/ctlconfig.cpp b/Descent3/ctlconfig.cpp index 854c2d05d..9bb9e3b91 100644 --- a/Descent3/ctlconfig.cpp +++ b/Descent3/ctlconfig.cpp @@ -1126,12 +1126,6 @@ int weapon_select_dialog(int wpn, bool is_secondary) { return retval; } void joystick_calibration() { -#if defined(WIN32) - extern bool Win32JoystickCalibrate(); - if (!Win32JoystickCalibrate()) { - DoMessageBox(TXT_ERROR, TXT_CALIBJOYSTICKFAIL, MB_OK); - } -#endif } void joystick_settings_dialog() { newuiTiledWindow wnd; diff --git a/Descent3/descent.h b/Descent3/descent.h index 81c27db0b..65e0fcd32 100644 --- a/Descent3/descent.h +++ b/Descent3/descent.h @@ -128,7 +128,9 @@ #ifndef _DESCENT_H #define _DESCENT_H -#include +#include +#include + #include "application.h" // The name of this product @@ -181,6 +183,9 @@ extern bool Descent_overrided_intro; // The "root" directory of the D3 file tree extern char Base_directory[]; +// Variable to preserve current path. TODO: redundant? +extern std::filesystem::path orig_pwd; + // --------------------------------------------------------------------------- // Globals diff --git a/Descent3/game.cpp b/Descent3/game.cpp index fca5c9562..6f25d3433 100644 --- a/Descent3/game.cpp +++ b/Descent3/game.cpp @@ -1112,9 +1112,10 @@ void SetScreenMode(int sm, bool force_res_change) { // HACK!!! In editor, to get things working fine, reassert window handle attached to game screen // is the topmost window, since in the editor, if we're fullscreen the parent window is still // the editor window, the screen would belong to the editor window. - tWin32AppInfo appinfo; + tLnxAppInfo appinfo; Descent->get_info(&appinfo); - ddvid_SetVideoHandle(hGameWnd); + // LGT - Disabled: not using ddvid + // ddvid_SetVideoHandle(hGameWnd); #endif } diff --git a/Descent3/loki_utils.c b/Descent3/loki_utils.c index 1c6ad81e4..69a2a5d22 100644 --- a/Descent3/loki_utils.c +++ b/Descent3/loki_utils.c @@ -31,7 +31,7 @@ const char *loki_getdatapath(void) { return basepath; } const char *loki_getprefpath(void) { return prefpath; } -void loki_initialize(int argc, char **argv, char *desc) { +void loki_initialize() { basepath = SDL_GetBasePath(); if (basepath == NULL) { fprintf(stderr, "ERROR: Couldn't find game directory!\n"); diff --git a/Descent3/loki_utils.h b/Descent3/loki_utils.h index 93f68f15a..d0dc4ea46 100644 --- a/Descent3/loki_utils.h +++ b/Descent3/loki_utils.h @@ -30,7 +30,7 @@ extern "C" { #endif -void loki_initialize(int argc, char **argv, char *desc); +void loki_initialize(); const char *loki_getdatapath(void); const char *loki_getprefpath(void); diff --git a/Descent3/program.cpp b/Descent3/program.cpp index 4292369e5..1e8b80764 100644 --- a/Descent3/program.cpp +++ b/Descent3/program.cpp @@ -70,13 +70,7 @@ program_version Program_version; // Initializes the current program state void ProgramVersion(int version_type, uint8_t major, uint8_t minor, uint8_t build) { -#if defined(WIN32) // I'm sorry. Samir - oeWin32AppDatabase dbase((oeWin32AppDatabase *)Database); -#elif defined(__LINUX__) oeLnxAppDatabase dbase((oeLnxAppDatabase *)Database); -#else - oeAppDatabase dbase(Database); // this will fail without an operating system equiv -#endif Program_version.version_type = version_type; Program_version.major = major; diff --git a/Descent3/lnxmain.cpp b/Descent3/sdlmain.cpp similarity index 96% rename from Descent3/lnxmain.cpp rename to Descent3/sdlmain.cpp index 9d65df781..40f0ad7c4 100644 --- a/Descent3/lnxmain.cpp +++ b/Descent3/sdlmain.cpp @@ -25,8 +25,12 @@ #include #include -#include +#include + +#ifndef WIN32 #include +#include +#endif #include @@ -40,13 +44,14 @@ #include "osiris_dll.h" #include "loki_utils.h" + #include "log.h" extern bool ddio_mouseGrabbed; const char *DMFCGetString(int d); // void *x = (void *) DMFCGetString; // just force a reference to dmfc.so ... -char *__orig_pwd = NULL; +std::filesystem::path orig_pwd; bool linux_permit_gamma = false; @@ -137,10 +142,13 @@ void just_exit(void) { #endif SDL_Quit(); +#ifdef __LINUX__ sync(); // just in case. +#endif _exit(0); } +#ifdef __LINUX__ void fatal_signal_handler(int signum) { switch (signum) { case SIGHUP: @@ -172,7 +180,7 @@ void fatal_signal_handler(int signum) { void safe_signal_handler(int signum) {} -void install_signal_handlers(void) { +void install_signal_handlers() { struct sigaction sact, fact; memset(&sact, 0, sizeof(sact)); @@ -207,6 +215,9 @@ void install_signal_handlers(void) { if (sigaction(SIGTRAP, &fact, NULL)) fprintf(stderr, "SIG: Unable to install SIGTRAP\n"); } +#else +void install_signal_handlers() {} +#endif // --------------------------------------------------------------------------- // Define our operating system specific extensions to the gameos system // --------------------------------------------------------------------------- @@ -240,13 +251,18 @@ oeD3LnxDatabase::oeD3LnxDatabase() : oeLnxAppDatabase() { char netpath[_MAX_PATH]; // put directories into database + +#ifdef EDITOR + create_record("D3Edit"); +#else create_record("Descent3"); +#endif char *dir = getenv("D3_LOCAL"); char *netdir = getenv("D3_DIR"); if (!dir) - strcpy(path, loki_getdatapath()); //"/usr/local/games/descent3"); + strcpy(path, loki_getdatapath()); else strcpy(path, dir); @@ -260,7 +276,7 @@ oeD3LnxDatabase::oeD3LnxDatabase() : oeLnxAppDatabase() { Database = this; } -static void register_d3_args(void) { +static void register_d3_args() { loki_register_stdoptions(); for (int i = 0; i < sizeof(d3ArgTable) / sizeof(d3ArgTable[0]); i++) { @@ -279,7 +295,6 @@ int SDLCALL d3SDLEventFilter(void *userdata, SDL_Event *event) { case SDL_KEYUP: case SDL_KEYDOWN: return (sdlKeyFilter(event)); - case SDL_JOYBALLMOTION: case SDL_MOUSEMOTION: return (sdlMouseMotionFilter(event)); @@ -341,8 +356,16 @@ static void check_beta() { // creates all the OS objects and then runs Descent 3. // this is all this function should do. // --------------------------------------------------------------------------- +#ifdef WIN32 +int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow) { + strupr(szCmdLine); + GatherArgs(szCmdLine); +#else int main(int argc, char *argv[]) { - __orig_pwd = getcwd(NULL, 0); + GatherArgs(argv); +#endif + + orig_pwd = std::filesystem::current_path(); /* Setup the logging system */ InitLog(); @@ -415,7 +438,6 @@ int main(int argc, char *argv[]) { // if (getenv("SDL_VIDEO_YUV_HWACCEL") == NULL) // putenv("SDL_VIDEO_YUV_HWACCEL=0"); - GatherArgs(argv); snprintf(game_version_buffer, sizeof(game_version_buffer), "%d.%d.%d%s %s", D3_MAJORVER, D3_MINORVER, D3_BUILD, D3_GIT_HASH, GAME_VERS_EXT); @@ -429,6 +451,8 @@ int main(int argc, char *argv[]) { #if defined(__APPLE__) && defined(__MACH__) "macOS", +#elif defined(WIN32) + "Windows", #else "Linux", #endif @@ -445,7 +469,7 @@ int main(int argc, char *argv[]) { game_version += 2; // skip those first newlines for loki_initialize. register_d3_args(); - loki_initialize(argc, argv, game_version_buffer); + loki_initialize(); int x; @@ -588,6 +612,7 @@ int main(int argc, char *argv[]) { } bool run_d3 = true; +#ifdef __LINUX__ if (flags & APPFLAG_USESERVICE) { run_d3 = false; pid_t np = fork(); @@ -601,6 +626,7 @@ int main(int argc, char *argv[]) { printf("Successfully forked process [new sid=%d pid=%d]\n", np, pp); } } +#endif if (run_d3) { oeD3LnxApp d3(flags); diff --git a/Descent3/winmain.cpp b/Descent3/winmain.cpp deleted file mode 100644 index a15837502..000000000 --- a/Descent3/winmain.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . -*/ - -#include -#include -#include -#include -#include "mono.h" -#include "descent.h" -#include "texture.h" -#include "application.h" -#include "appdatabase.h" -#include "pserror.h" -#include "args.h" -#include "init.h" -#include "dedicated_server.h" -#include "resource.h" -#include "log.h" - -const char *English_strings[] = {"Descent 3 under Windows NT requires version 4.0 or greater of NT to run.", - "Descent 3 requires Windows 9x, NT 4.0 or greater to run.", - "", - "You must install DirectX through the Descent 3 Launcher before continuing.", - "You must install at least Service Pack 3 to run Descent 3 under Windows NT 4.0.", - "Failed to retrieve DirectX version.", - "Descent 3 requires DirectX 3 or greater on this machine.", - "This version of Windows NT doesn't have DirectX 3 or greater installed.", - "Your processor and system must support Katmai to run this game."}; - -const char *French_strings[] = { - "L'exécution de Descent 3 sous Windows NT nécessite la version 4.0 ou ultérieure de NT.", - "L'exécution de Descent 3 nécessite Windows 9x, NT 4.0 ou ultérieur.", - "", - "Vous devez installer DirectX a partir de l'installateur Descent 3 avant de continuer.", - "Vous devez installer au moins Service Pack 3 pour exécuter Descent 3 sous Windows NT 4.0.", - "+chec de la récupération de DirectX.", - "Descent 3 nécessite DirectX 3 ou ultérieur sur ce système.", - "Cette version de Windows NT n'est pas munie de DirectX 3 ou ultérieur.", - "Votre processeur et votre système doivent prendre en charge Katmai pour exécuter ce jeu."}; - -const char *German_strings[] = { - "Descent3 unter Windows NT benötigt fnr die Ausführung die NT-Version 4.0 oder höher", - "Descent 3 benötigt fnr die Ausführung Windows 9x, NT 4.0 oder höher.", - "", - "Sie müssen DirectX über den Descent 3 Starter installieren, bevor Sie fortsetzen.", - "Sie müssen mindestens Service Paket 3 installieren, um Descent 3 unter Windows NT 4.0 ausführen zu können.", - "Die DirectX Version konnte nicht abgerufen werden.", - "Descent 3 benötigt DirectX 3 oder höher auf diesem Computer.", - "In dieser Windows NT Version ist DirectX 3 oder höher nicht installiert.", - "Ihr Prozessor und System mu¯ Katmai unterstützen, um dieses Spiel auszuführen."}; - -const char *Italian_strings[] = { - "Descent 3 per Windows NT richiede la versione NT 4.0 o superiore.", - "Descent 3 funziona solo con Windows 9x, NT 4.0 o superiore.", - "", - "Prima di prosegure installare DirectX per mezzo di Descent 3 Launcher.", - "Per utilizzare Descent 3 sotto Windows NT 4.0 occorre installare Service Pack 3 o sup.", - "Versione di DirectX non trovata.", - "Descent 3 richiede l'installazione di DirectX 3 o superiore.", - "DirectX 3 o superiore non trovato in questa versione di Windows NT.", - "Per questo gioco occorrono un processore e un sistema che supportino Katmai."}; - -const char *Spanish_strings[] = {"Descent 3 bajo Windows NT requiere version 4.0 o mejor para correr.", - "Descent 3 requiere Windows 9x, NT 4.0 o mejor para correr.", - "", - "Debe instalar DirectX desde el lanzador de Descent 3 antes de continuar.", - "Debe instalar por lo menos Service Pack 3 para correr Descent 3 bajo Windows NT 4.0.", - "Falla en la detección de la versión de DirectX.", - "Descent 3 requiere DirectX 3 o mejor en el ordenador.", - "Esta versión de Windows NT no tiene DirectX 3 o mejor instalado.", - "Vuestro procesador y ordenador deben soportar Katmai para correr este juego."}; - -#if 0 -const char *Polish_strings[] = { - "Aby uruchomić grę Descent 3 potrzebujesz Windows NT w wersji 4.0 lub nowszej.", - "Descent 3 wymaga Windows 9x albo Windows NT w wersji 4.0 lub nowszej.", - "", - "Zanim uruchomisz grę, musisz zainstalować DirectX przy u¨yciu programu startowego.", - "Musisz zainstalować co najmniej Service Pack 3, aby uruchomić grę Descent 3 pod Windows NT 4.0.", - "Nie udało siˆ odczytać numeru wersji sterowników DirectX.", - "Descent 3 wymaga sterowników DirectX 3 lub nowszych.", - "Ta wersja Windows NT nie ma zainstalowanych sterownik¢w DirectX 3 lub nowszych.", - "Twój procesor musi obsługiwać rozkazy Katmai, aby uruchomić grę." -}; -#endif - -static int m_resource_language = 0; - -#define VENDOR_INTEL 0 -#define VENDOR_AMD 1 -#define VENDOR_CYRIX 2 -#define VENDOR_UMC 3 -#define VENDOR_CENTAUR 4 -#define VENDOR_NEXGEN 5 -#define VENDOR_UNKNOWN 6 - - -// --------------------------------------------------------------------------- -// Define our operating system specific extensions to the gameos system -// --------------------------------------------------------------------------- - -class oeD3Win32App : public oeWin32Application { - bool shutdown, final_shutdown; - int old_screen_mode; - HANDLE hAppMutex; - -public: - oeD3Win32App(unsigned flags, HInstance hinst) : oeWin32Application(PRODUCT_NAME, flags, hinst) { - Descent = this; - shutdown = false; - final_shutdown = false; - hAppMutex = CreateMutex(NULL, FALSE, "D3MainMutexName"); - if (!hAppMutex) { - exit(1); - } - win32_SetResourceDLL(NULL); - }; - - virtual ~oeD3Win32App() { - win32_SetResourceDLL(NULL); - if (hAppMutex) { - CloseHandle(hAppMutex); - hAppMutex = NULL; - } - - final_shutdown = true; - }; - - void run() { Descent3(); } - - // returns 0 if we pass to default window handler. - virtual LResult WndProc(HWnd hwnd, unsigned msg, WParam wParam, LParam lParam) override { - if (final_shutdown) { - return oeWin32Application::WndProc(hwnd, msg, wParam, lParam); - } - - switch (msg) { - case WM_ACTIVATEAPP: { - if (wParam == FALSE) { - this->deactivate(); - - if (!shutdown) { - ShutdownD3(); - shutdown = true; - if (m_Flags & OEAPP_FULLSCREEN) { - ShowWindow((HWND)hwnd, SW_MINIMIZE); - } - } - } else { - this->activate(); - - if (shutdown) { - ShowWindow((HWND)hwnd, SW_RESTORE); - RestartD3(); - shutdown = false; - } - } - } break; - } - - return oeWin32Application::WndProc(hwnd, msg, wParam, lParam); - } -}; - -class oeD3Win32Database : public oeWin32AppDatabase { -public: - oeD3Win32Database(); -}; - -// --------------------------------------------------------------------------- -// D3WinDatabase operating system specific initialization - -oeD3Win32Database::oeD3Win32Database() : oeWin32AppDatabase() { - char path[_MAX_PATH]; - bool res; - - // create descent III entry if it doesn't exit. - -#if defined(EDITOR) - lstrcat(m_Basepath, "\\D3Edit"); -#elif defined(DEMO) - lstrcat(m_Basepath, "\\Descent3Demo2"); -#elif defined(OEM_V3) - lstrcat(m_Basepath, "\\Descent3_OEM_V3"); -#elif defined(OEM_KATMAI) - lstrcat(m_Basepath, "\\Descent3_OEM_KM"); -#elif defined(OEM) - lstrcat(m_Basepath, "\\Descent3_OEM"); -#else - lstrcat(m_Basepath, "\\Descent3"); -#endif - - res = lookup_record(m_Basepath); - if (!res) { - res = create_record(m_Basepath); - if (!res) { - Error("Failed to create registry key for %s", PRODUCT_NAME); - } - } - - // create version key. - lstrcpy(path, m_Basepath); - lstrcat(path, "\\Version"); - res = lookup_record(path); - if (!res) { - res = create_record(path); - if (!res) { - Error("Failed to create registry key for %s", PRODUCT_NAME); - } - } - -#ifdef EDITOR // Maybe this code should be in the editor startup - lstrcpy(path, m_Basepath); - lstrcat(path, "\\editor"); - res = lookup_record(path); - if (!res) { - res = create_record(path); - if (!res) { - Error("Failed to create registry key for %s.", PRODUCT_NAME); - } - } -#endif - - res = lookup_record(m_Basepath); - - // Get net directory for manage system - char netpath[_MAX_PATH]; - lstrcpy(netpath, ""); -#ifndef EDITOR - if (FindArg("-update")) // For the game-only build, require -update to update data -#endif - // NOTE LINK TO ABOVE IF - { - char *netdir = getenv("D3_DIR"); - if (netdir) - lstrcpy(netpath, netdir); - } - write("net directory", netpath, lstrlen(netpath) + 1); - - Database = this; -} - -bool Win32JoystickCalibrate() { - // sorry. - PROCESS_INFORMATION pi; - STARTUPINFO si; - BOOL flag; - // DWORD dwval; - - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_SHOW; - - flag = CreateProcess(NULL, "rundll32.exe shell32.dll,Control_RunDLL joy.cpl", NULL, NULL, FALSE, - NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); - if (!flag) { - return false; - } else { - tWin32AppInfo appinfo; - HWND hWnd; - - Descent->get_info(&appinfo); - hWnd = (HWND)appinfo.hwnd; - - WaitForInputIdle(pi.hProcess, INFINITE); - ShowWindow(hWnd, SW_MINIMIZE); - Descent->delay(0.5f); - - while (WaitForSingleObject(pi.hProcess, 0) != WAIT_OBJECT_0) { - extern void D3DeferHandler(bool is_active); - D3DeferHandler(false); - } - - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - ShowWindow(hWnd, SW_MAXIMIZE); - Descent->delay(0.5f); - } - - return true; -} - -#ifdef EDITOR -// --------------------------------------------------------------------------- -// WinMainInitEditor -// creates all the App objects for the editor. -// this is all this function should do. -// --------------------------------------------------------------------------- - -#pragma message("Compiling editor WinMain substitute function.") - -void WinMainInitEditor(unsigned hwnd, unsigned hinst) { - tWin32AppInfo appinfo; - - appinfo.hwnd = (HWnd)hwnd; - appinfo.hinst = (HInstance)hinst; - appinfo.flags = OEAPP_WINDOWED; - - Descent = new oeWin32Application(&appinfo); - Database = new oeD3Win32Database; -} - -#else - -void D3End() { - if (Descent) { - delete Descent; - } -} - -// Localization defines -#define LANGUAGE_ENGLISH 0 -#define LANGUAGE_GERMAN 1 -#define LANGUAGE_SPANISH 2 -#define LANGUAGE_ITALIAN 3 -#define LANGUAGE_FRENCH 4 - -inline void MessageBoxStr(int id) { - const char *txt = "Unknown string"; - - id--; - if (id >= 0 && id <= 8) { - switch (m_resource_language) { - case LANGUAGE_FRENCH: - txt = French_strings[id]; - break; - case LANGUAGE_GERMAN: - txt = German_strings[id]; - break; - case LANGUAGE_ITALIAN: - txt = Italian_strings[id]; - break; - case LANGUAGE_SPANISH: - txt = Spanish_strings[id]; - break; - default: - txt = English_strings[id]; - } - } - - // win32_GetStringResource(id, str, sizeof(str)); - - MessageBox(NULL, txt, "Outrage Error", MB_OK); -} - -// Returns true if this machine can support katmai instructions -bool SupportsKatmai() { - // Note: we don't do anything Katmai specific -- just always enable it. - return true; -} - -// DirectX check, NT 4.0, 5.0, Win95 check. -bool Win32SystemCheck(HINSTANCE hInst) { - tWin32OS os; - int major, minor, build; - bool retval; - - os = oeWin32Application::version(&major, &minor, &build); - - if (os == WinNT) { - if (major < 4) { - MessageBoxStr(ID_TXT_WINNT); - return false; - } - } else if (os != Win9x) { - MessageBoxStr(ID_TXT_WIN32); - return false; - } - - // perform DirectX system check. - retval = false; - - // This function simply returns the interger version value of DirectX - // installed on the user's system - LONG lResult; - HKEY hKey = NULL; - int version_num = 0; - - lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectX", NULL, KEY_QUERY_VALUE, &hKey); - if (lResult == ERROR_SUCCESS) { - char version[32]; - DWORD dwType, dwLen = 32; - lResult = RegQueryValueEx(hKey, "Version", NULL, &dwType, (uint8_t *)version, &dwLen); - if (lResult == ERROR_SUCCESS) { - version_num = atoi(strstr(version, ".") + 1); - } else { - int val; - DWORD dwType, dwLen = 4; - - lResult = RegQueryValueEx(hKey, "InstalledVersion", NULL, &dwType, (uint8_t *)&val, &dwLen); - if (lResult == ERROR_SUCCESS) { - version_num = val; - } - } - RegCloseKey(hKey); - } else { - // if we don't have DSETUP.DLL and we are under Win95, then we're in trouble. - if (os == Win9x) { - MessageBoxStr(ID_TXT_DXVER); - MessageBoxStr(ID_TXT_DX95); - goto end_win32_check; - } - } - - // we should be either under NT 4 or greater, or 95 - if (version_num < 3) { - if (os == WinNT) { - if (major == 4) { - MessageBoxStr(ID_TXT_DXNT4); - } else { - MessageBoxStr(ID_TXT_DXNTERR); - } - goto end_win32_check; - } else { - // Win95 - MessageBoxStr(ID_TXT_DX95); - goto end_win32_check; - } - } - - if ((!SupportsKatmai()) || FindArg("-nopentium3")) { - mprintf(0, "No Katmai detected.\n"); - Katmai = false; - } else { - mprintf(0, "Katmai detected!\n"); - Katmai = true; - } - - retval = true; - -end_win32_check: - return retval; -} - -// --------------------------------------------------------------------------- -// WinMain -// creates all the OS objects and then runs Descent 3. -// this is all this function should do. -// --------------------------------------------------------------------------- - -// See below for real WinMain - -int PASCAL HandledWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow) { - /* initialize our OS Object. This could be a game dependant OS object, or a default OS object. - once we create it, if successful, we can start the game. - */ - oeD3Win32App *d3; - extern bool w32_mouseman_hack; // from winapp.cpp - extern bool joy_chpro_hack; // located in winjoy.cpp - - InitLog(); - - strupr(szCmdLine); - GatherArgs(szCmdLine); - - // This must come AFTER the GatherArgs() call, because its constructer used FindArg() - oeD3Win32Database dbase; - - no_debug_dialog = FindArg("-nocrashbox"); - - // If this is a dedicated server, then start one! - if (FindArg("-dedicated")) - StartDedicatedServer(); -#ifdef DEDICATED_ONLY - else { - MessageBox(NULL, "Error: -dedicated command line required", PRODUCT_NAME " Error", MB_OK); - return 0; - } - -#endif - - if (Dedicated_server) { - d3 = new oeD3Win32App(OEAPP_CONSOLE, (HInstance)hInst); - } else { - uint32_t flags = OEAPP_FULLSCREEN; -#ifndef RELEASE // TODO: remove #ifndef when window mode is ready for primetime - if (FindArg("-windowed")) { - // switch to windowed mode instead - flags = OEAPP_WINDOWED; - } -#endif - - d3 = new oeD3Win32App(flags, (HInstance)hInst); - } - atexit(D3End); - - w32_mouseman_hack = false; - joy_chpro_hack = false; - - if (FindArg("-mouseman")) { - w32_mouseman_hack = true; - } - if (FindArg("-chpro")) { - joy_chpro_hack = true; - } - - // determine preinit language for resource strings - int language = 0; - dbase.read_int("LanguageType", &language); - m_resource_language = language; - - if (!Win32SystemCheck(hInst)) - return 0; - - PreInitD3Systems(); - - d3->init(); - d3->run(); - - return 1; -} - -// This is the winmain that tests for exceptions.. -int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow) { - - int result = -1; - - __try { - result = HandledWinMain(hInst, hPrevInst, szCmdLine, nCmdShow); - } __except (RecordExceptionInfo(GetExceptionInformation(), "WinMain()")) { - } - return result; -} - -#endif diff --git a/README.md b/README.md index f0b1ef78a..080de55d9 100644 --- a/README.md +++ b/README.md @@ -114,16 +114,16 @@ The milestone needs testing on all platforms. Please report issues when found. --add Microsoft.VisualStudio.Component.VC.ATLMFC ``` -2. Open a “x86 Native Tools Command Prompt” and run: +2. Open a “x64 Native Tools Command Prompt” and run: ```batch git clone https://github.com/DescentDevelopers/Descent3 cd Descent3 - cmake --preset win32 -D ENABLE_LOGGER=[ON|OFF] -D BUILD_EDITOR=[ON|OFF] - cmake --build --preset win32 --config [Debug|Release] + cmake --preset win -D ENABLE_LOGGER=[ON|OFF] -D BUILD_EDITOR=[ON|OFF] + cmake --build --preset win --config [Debug|Release] ``` -Once CMake finishes, the built files will be put in `builds\win32\Descent3\Debug` or `builds\win32\Descent3\Release`. +Once CMake finishes, the built files will be put in `builds\win\Descent3\Debug` or `builds\win\Descent3\Release`. #### Building - macOS 1. Make sure that [Xcode](https://developer.apple.com/xcode) is installed. diff --git a/dd_grwin32/CMakeLists.txt b/dd_grwin32/CMakeLists.txt index adf8bdbc0..444724561 100644 --- a/dd_grwin32/CMakeLists.txt +++ b/dd_grwin32/CMakeLists.txt @@ -12,3 +12,5 @@ add_library(dd_grwin32 STATIC ${HEADERS} ${CPPS}) target_link_libraries(dd_grwin32 PRIVATE misc ) +target_compile_definitions(dd_grwin32 PRIVATE DX_APP) +target_link_libraries(dd_grwin32 PRIVATE ${DDRAW_LIBRARY}) diff --git a/dd_video/CMakeLists.txt b/dd_video/CMakeLists.txt index 7152166ad..fec366e8e 100644 --- a/dd_video/CMakeLists.txt +++ b/dd_video/CMakeLists.txt @@ -1,12 +1,5 @@ set(CPPS - $<$: - video_win32.cpp - vidWin32FS.cpp - vidWin32Win.cpp - > - $<$: video_lnx.cpp - > ) add_library(dd_video STATIC ${CPPS}) diff --git a/dd_video/ddvidlib.h b/dd_video/ddvidlib.h deleted file mode 100644 index d7e03ed8f..000000000 --- a/dd_video/ddvidlib.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddvid_win32/ddvidlib.h $ - * $Revision: 4 $ - * $Date: 3/06/98 2:22p $ - * $Author: Samir $ - * - * Video library internal header - * - * $Log: /DescentIII/Main/ddvid_win32/ddvidlib.h $ - * - * 4 3/06/98 2:22p Samir - * Added fullscreen windowed version. - * - * 3 2/03/98 3:12p Samir - * Enable access to directdraw object by DDAccess libraries. - * - * 2 12/30/97 1:54p Samir - * Upped max modes. - * - * 1 12/23/97 5:46p Samir - * Initial revision - * - * $NoKeywords: $ - */ - -#ifndef DDVIDLIB_H -#define DDVIDLIB_H - -#include "ddvid.h" - -#include -#include -#include - -#define VM_MAX_MODES 96 - -const int VID_GDIF_SUBSYSTEM = 0, // GDI fullscreen subsystem - VID_GDI_SUBSYSTEM = 1, // GDI subsystem - VID_GDIX_SUBSYSTEM = 2, // GDIX subsystem (GDI+DirectX) - VID_DX_SUBSYSTEM = 3; // DIRECTX subsystem - -class oeWin32Application; - -struct tDDVideoInfo { - oeWin32Application *app; - HWND hWnd; - HWND hVidWnd; - int subsystem; - - LPDIRECTDRAW lpDD; - LPDIRECTDRAWSURFACE lpDDSFront; - LPDIRECTDRAWSURFACE lpDDSBack; - DDSURFACEDESC DDModes[VM_MAX_MODES]; - int nDDModes; - int curmode; - char *surf_data; - - struct { - HBITMAP hBackBmp; - HDC hBackDC; - char *data; - int pitch; - int w, h, color_depth; - int ndevmodes; - int olddevmode; - int curdevmode; - } gdi; -}; - -// driver info. -extern tDDVideoInfo DDVideo_info; - -// inits fullscreen system -bool ddvidfs_Init(); - -// closes fullscreen system -void ddvidfs_Close(); - -// uses direct draw. if paged, allows frame buffer access. -bool ddvidfs_SetVideoMode(int w, int h, int color_depth, bool paged); - -// closes video mode for fs -void ddvidfs_CloseVideo(); - -// flips screen if there's a back buffer -void ddvidfs_VideoFlip(); - -// returns the directdraw object -uint32_t ddvidfs_GetDirectDrawObject(); - -// inits windowed system -bool ddvidwin_Init(); - -// closes windowed system -void ddvidwin_Close(); - -// creates an offscreen back bitmap if needed. otherwise doesn't do a thing really. -bool ddvidwin_SetVideoMode(int w, int h, int color_depth, bool paged, bool reschange = false); - -// closes video mode for fs -void ddvidwin_CloseVideo(); - -// flips screen if there's a back buffer -void ddvidwin_VideoFlip(); - -#endif diff --git a/dd_video/vidWin32FS.cpp b/dd_video/vidWin32FS.cpp deleted file mode 100644 index 1407a1b53..000000000 --- a/dd_video/vidWin32FS.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddvid_win32/vidWin32FS.cpp $ - * $Revision: 7 $ - * $Date: 7/15/98 5:56p $ - * $Author: Samir $ - * - * Fullscreen version of Win32 library - * - * $Log: /DescentIII/Main/ddvid_win32/vidWin32FS.cpp $ - * - * 7 7/15/98 5:56p Samir - * commented out GDIX subsystem. - * - * 6 6/04/98 7:04p Samir - * assert res-switch to be at least 16bpp. - * - * 5 3/04/98 5:01p Samir - * May have fixed problem with restoring old display modes. - * - * 4 2/03/98 3:12p Samir - * Enable access to directdraw object by DDAccess libraries. - * - * 3 12/30/97 3:35p Samir - * Added dummy mode to help in mode selection. - * - * 2 12/30/97 2:31p Jason - * Fixed mode finder. (samir) - * - * 1 12/23/97 5:46p Samir - * Initial revision - * - * $NoKeywords: $ - */ - -#include "ddvidlib.h" -#include "pserror.h" - -// DirectDraw Display mode enumeration callback -HRESULT WINAPI DDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext); - -// inits fullscreen system -bool ddvidfs_Init() { - HRESULT hres; - - hres = DirectDrawCreate(NULL, &DDVideo_info.lpDD, NULL); - - if (hres != DD_OK) { - Error("Failure to initialize DirectDraw driver. (%d)", LOWORD(hres)); - } - - hres = - DDVideo_info.lpDD->SetCooperativeLevel(DDVideo_info.hWnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); - if (hres != DD_OK) { - Error("Failed to set access mode for DirectDraw driver. (%d)", LOWORD(hres)); - } - - // dummy mode - DDVideo_info.DDModes[DDVideo_info.nDDModes].ddpfPixelFormat.dwRGBBitCount = 0; - DDVideo_info.DDModes[DDVideo_info.nDDModes].dwWidth = 0; - DDVideo_info.DDModes[DDVideo_info.nDDModes].dwHeight = 0; - DDVideo_info.nDDModes++; - - // enumerate all display modes. - if (DDVideo_info.lpDD->EnumDisplayModes(0, NULL, NULL, DDEnumModesCallback) != DD_OK) { - mprintf(0, "DDVID error: Error enumerating display modes.\n"); - return false; - } - - mprintf(0, "Video fullscreen system initialized.\n"); - - return true; -} - -// closes fullscreen system -void ddvidfs_Close() { - if (DDVideo_info.lpDDSFront) - DDVideo_info.lpDDSFront->Release(); - - if (DDVideo_info.lpDD) { - DDVideo_info.lpDD->RestoreDisplayMode(); - DDVideo_info.lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL); - DDVideo_info.lpDD->Release(); - DDVideo_info.lpDD = NULL; - } - - DDVideo_info.lpDDSFront = NULL; - DDVideo_info.lpDDSBack = NULL; - DDVideo_info.hWnd = NULL; - DDVideo_info.nDDModes = 0; -} - -// uses direct draw. if paged, allows frame buffer access. -bool ddvidfs_SetVideoMode(int w, int h, int color_depth, bool paged) { - HRESULT hres; - DDSCAPS ddscaps; - DDSURFACEDESC ddsd; - int i, mode; - bool found_mode; - - mode = 0; - found_mode = false; - - // find closest match for video mode. - for (i = 0; i < DDVideo_info.nDDModes; i++) { - if (color_depth == (int)DDVideo_info.DDModes[i].ddpfPixelFormat.dwRGBBitCount) { - if (DDVideo_info.DDModes[i].dwWidth >= (DWORD)w && DDVideo_info.DDModes[mode].dwWidth < (DWORD)w) - if (DDVideo_info.DDModes[i].dwHeight >= (DWORD)h && DDVideo_info.DDModes[mode].dwHeight < (DWORD)h) { - mode = i; - found_mode = true; - } - } - } - - if (!found_mode) { - // we couldn't find a mode, error! - return false; - } - - if (DDVideo_info.curmode != mode) { - - // mode should contain the video mode. - hres = DDVideo_info.lpDD->SetDisplayMode(DDVideo_info.DDModes[mode].dwWidth, DDVideo_info.DDModes[mode].dwHeight, - DDVideo_info.DDModes[mode].ddpfPixelFormat.dwRGBBitCount); - ASSERT(DDVideo_info.DDModes[mode].ddpfPixelFormat.dwRGBBitCount >= BPP_16); - if (hres != DD_OK) - Error("Unable to set DirectDraw display mode. (%d)", LOWORD(hres)); - } - - DDVideo_info.curmode = mode; - - // if not paged, then this is a single paged system (no lfb access, good for opengl) - if (!paged) - return true; - - // now create surface, dependant on whether an extra page was requested - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - if (paged) { - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - ddsd.dwBackBufferCount = 1; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; - } else { - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - } - - hres = DDVideo_info.lpDD->CreateSurface(&ddsd, &DDVideo_info.lpDDSFront, NULL); - if (hres != DD_OK) - Error("Unable to capture DirectDraw display surface. (%d)", LOWORD(hres)); - - if (paged) { - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; - - hres = DDVideo_info.lpDDSFront->GetAttachedSurface(&ddscaps, &DDVideo_info.lpDDSBack); - if (hres != DD_OK) { - mprintf(0, "Unable to capture DirectDraw display back surface (%d)", LOWORD(hres)); - return false; - } - } else { - DDVideo_info.lpDDSBack = NULL; - } - - return true; -} - -// closes video mode for fs -void ddvidfs_CloseVideo() { - // uninitialize old screen - if (DDVideo_info.lpDDSFront) { - DDVideo_info.lpDDSFront->Release(); - DDVideo_info.lpDDSFront = NULL; - DDVideo_info.lpDDSBack = NULL; - } -} - -// flips screen if there's a back buffer -void ddvidfs_VideoFlip() { - if (DDVideo_info.lpDDSBack) - DDVideo_info.lpDDSFront->Flip(NULL, DDFLIP_WAIT); -} - -// returns the directdraw object -uint32_t ddvidfs_GetDirectDrawObject() { return (uint32_t)DDVideo_info.lpDD; } - -// DirectDraw Display mode enumeration callback -HRESULT WINAPI DDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) { - if (DDVideo_info.nDDModes < VM_MAX_MODES) { - memcpy(&DDVideo_info.DDModes[DDVideo_info.nDDModes], lpDDSurfaceDesc, sizeof(DDSURFACEDESC)); - DDVideo_info.nDDModes++; - } - - return DDENUMRET_OK; -} diff --git a/dd_video/vidWin32Win.cpp b/dd_video/vidWin32Win.cpp deleted file mode 100644 index 522ad9ef8..000000000 --- a/dd_video/vidWin32Win.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddvid_win32/vidWin32Win.cpp $ - * $Revision: 5 $ - * $Date: 10/02/98 11:15a $ - * $Author: Jeff $ - * - * Windowed version of video library. - * - * $Log: /DescentIII/Main/ddvid_win32/vidWin32Win.cpp $ - * - * 5 10/02/98 11:15a Jeff - * added HBITMAP, HFONT and HBRUSH type casts where needed to satisfy the - * compiler - * - * 4 6/04/98 7:04p Samir - * assert res-switch to be at least 16bpp. - * - * 3 4/23/98 6:38p Jason - * made bitmaps use 1555 format - * - * 2 3/06/98 2:22p Samir - * Added fullscreen windowed version. - * - * 1 12/23/97 5:46p Samir - * Initial revision - * - * $NoKeywords: $ - */ - -#include "ddvidlib.h" -#include "pserror.h" -#include "Application.h" - -////////////////////////////////////////////////////////////////////////////// -// Variables - -struct tDIBHeader // used to create and manipulate DIBs (a 16/32BPP surface only) -{ - BITMAPINFOHEADER bmi; - DWORD red_mask; - DWORD green_mask; - DWORD blue_mask; -}; - -////////////////////////////////////////////////////////////////////////////// -// Functions - -// inits fullscreen system -bool ddvidwin_Init() { - // grab all device modes for the current display device. - unsigned i = 0; - DEVMODE devmode; - - while (EnumDisplaySettings(NULL, i, &devmode)) { - HDC hdc = CreateCompatibleDC(NULL); - - if (devmode.dmBitsPerPel == (uint32_t)GetDeviceCaps(hdc, BITSPIXEL) && - devmode.dmPelsWidth == (uint32_t)GetSystemMetrics(SM_CXSCREEN) && - devmode.dmPelsHeight == (uint32_t)GetSystemMetrics(SM_CYSCREEN)) { - if (DDVideo_info.app->NT() && devmode.dmDisplayFrequency == (uint32_t)GetDeviceCaps(hdc, VREFRESH)) - DDVideo_info.gdi.olddevmode = i; - else if (!DDVideo_info.app->NT()) - DDVideo_info.gdi.olddevmode = i; - } - - DeleteDC(hdc); - i++; - } - DDVideo_info.gdi.ndevmodes = i; - - DDVideo_info.gdi.curdevmode = DDVideo_info.gdi.olddevmode; - - return true; -} - -// closes windowed system -void ddvidwin_Close() { - DEVMODE devmode; - - if (DDVideo_info.gdi.hBackDC) { - DeleteDC(DDVideo_info.gdi.hBackDC); - DDVideo_info.gdi.hBackDC = NULL; - } - - if (DDVideo_info.gdi.hBackBmp) { - DeleteObject(DDVideo_info.gdi.hBackBmp); - DDVideo_info.gdi.hBackBmp = NULL; - } - - // if the current display mode is different than the default one, then restore default display mode - if (DDVideo_info.gdi.olddevmode != DDVideo_info.gdi.curdevmode) { - LONG lres; - - EnumDisplaySettings(NULL, DDVideo_info.gdi.olddevmode, &devmode); - - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; - - lres = ChangeDisplaySettings(&devmode, 0); - ASSERT(lres == DISP_CHANGE_SUCCESSFUL); - } -} - -// creates an offscreen back bitmap if needed. otherwise doesn't do a thing really -bool ddvidwin_SetVideoMode(int w, int h, int color_depth, bool paged, bool reschange) { - HDC hdc; - int i; - - DDVideo_info.hVidWnd = DDVideo_info.hWnd; - - // if resolution change, then do it. - if (reschange) { - int mode = 0; - bool found_mode = false; - DEVMODE devmode, curdevmode; - - EnumDisplaySettings(NULL, mode, &curdevmode); - curdevmode.dmPelsWidth = 0; - curdevmode.dmPelsHeight = 0; - curdevmode.dmBitsPerPel = 0; - - // check for display mode query match. - for (i = 0; i < DDVideo_info.gdi.ndevmodes; i++) { - EnumDisplaySettings(NULL, i, &devmode); - - if (color_depth == (int)devmode.dmBitsPerPel) { - if ((int)devmode.dmPelsWidth >= w && (int)curdevmode.dmPelsWidth < w) - if ((int)devmode.dmPelsHeight >= h && (int)curdevmode.dmPelsHeight < h) { - mode = i; - found_mode = true; - EnumDisplaySettings(NULL, mode, &curdevmode); - } - } - } - - if (!found_mode) { - // we couldn't find a mode, error! - Error("Unable to set Win32 device display mode (%dx%dx%d).", w, h, color_depth); - } - - if (DDVideo_info.gdi.curdevmode != mode) { - EnumDisplaySettings(NULL, mode, &devmode); - - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; - - ASSERT(devmode.dmBitsPerPel >= BPP_16); - LONG lres = ChangeDisplaySettings(&devmode, 0); - ASSERT(lres == DISP_CHANGE_SUCCESSFUL); - DDVideo_info.gdi.curdevmode = mode; - } - } - - // create a DC for blting and back buffer creation. - hdc = CreateCompatibleDC(NULL); - if (hdc == NULL) { - Error("Unable to create offscreen device context (%x).", GetLastError()); - return false; - } - - DDVideo_info.gdi.hBackDC = hdc; - DDVideo_info.gdi.w = w; - DDVideo_info.gdi.h = h; - DDVideo_info.gdi.color_depth = color_depth; - - // create offscreen back buffer if paged mode is requested. - if (paged) { - int nw = w; - if (nw % 4) - nw = ((w / 4) * 4) + 4; - tDIBHeader header; - - if (color_depth == BPP_16) { - header.bmi.biSize = sizeof(BITMAPINFOHEADER); - header.bmi.biWidth = nw; - header.bmi.biHeight = -h; // Always a top down bitmap!! - header.bmi.biPlanes = 1; - header.bmi.biBitCount = BPP_16; - header.bmi.biCompression = BI_BITFIELDS; - header.bmi.biSizeImage = 0; - header.bmi.biXPelsPerMeter = 0; - header.bmi.biYPelsPerMeter = 0; - header.bmi.biClrUsed = 0; - header.bmi.biClrImportant = 0; - - // setup RGB bit masks - header.red_mask = 0x7c00; - header.green_mask = 0x03e0; - header.blue_mask = 0x001f; - DDVideo_info.gdi.pitch = nw * 2; - } - - DDVideo_info.gdi.hBackBmp = CreateDIBSection(DDVideo_info.gdi.hBackDC, (BITMAPINFO *)&header, DIB_RGB_COLORS, - (void **)&DDVideo_info.gdi.data, NULL, 0); - - if (!DDVideo_info.gdi.hBackBmp) { - Error("CreateDIBSection failed (%x).", GetLastError()); - } - } - - return true; -} - -// closes video mode for fs -void ddvidwin_CloseVideo() { - // delete DC if it exists. - if (DDVideo_info.gdi.hBackDC) { - DeleteDC(DDVideo_info.gdi.hBackDC); - DDVideo_info.gdi.hBackDC = NULL; - } - - // destroy old back bitmap - if (DDVideo_info.gdi.hBackBmp) { - DeleteObject(DDVideo_info.gdi.hBackBmp); - DDVideo_info.gdi.hBackBmp = NULL; - } -} - -// retrieves screen information for windowed version -void ddvidwin_GetVideoProperties(int *w, int *h, int *color_depth) { - *w = DDVideo_info.gdi.w; - *h = DDVideo_info.gdi.h; - *color_depth = DDVideo_info.gdi.color_depth; -} - -// flips screen if there's a back buffer -void ddvidwin_VideoFlip() { - HBITMAP old_bmp, h_sbm; - HDC hdc_dest; - RECT rect; - int dw, dh; - - ASSERT(DDVideo_info.hVidWnd != NULL); - - // don't give an error if there's no backbuffer. - if (!DDVideo_info.gdi.hBackBmp) - return; - - h_sbm = DDVideo_info.gdi.hBackBmp; - - hdc_dest = GetDC(DDVideo_info.hVidWnd); - GetClientRect(DDVideo_info.hVidWnd, &rect); - - dw = rect.right - rect.left; - dh = rect.bottom - rect.top; - - old_bmp = (HBITMAP)SelectObject(DDVideo_info.gdi.hBackDC, h_sbm); - - BOOL bltres = BitBlt(hdc_dest, 0, 0, dw, dh, DDVideo_info.gdi.hBackDC, 0, 0, SRCCOPY); - - SelectObject(DDVideo_info.gdi.hBackDC, old_bmp); - - ReleaseDC(DDVideo_info.hVidWnd, hdc_dest); -} diff --git a/dd_video/video_win32.cpp b/dd_video/video_win32.cpp deleted file mode 100644 index fd0c239b5..000000000 --- a/dd_video/video_win32.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddvid_win32/video_win32.cpp $ - * $Revision: 6 $ - * $Date: 8/28/98 4:20p $ - * $Author: Jeff $ - * - * Video library. - * - * $Log: /DescentIII/Main/ddvid_win32/video_win32.cpp $ - * - * 6 8/28/98 4:20p Jeff - * fixed cinemtaics so they initialize ddraw to play the movie - * - * 5 7/15/98 5:56p Samir - * commented out GDIX subsystem. - * - * 4 3/06/98 2:22p Samir - * Added fullscreen windowed version. - * - * 3 2/03/98 3:12p Samir - * Enable access to directdraw object by DDAccess libraries. - * - * 2 12/23/97 6:17p Samir - * Added DDGR subsystem interface. - * - * 1 12/22/97 12:45p Samir - * Initial revision - * - * $NoKeywords: $ - */ - - -#include "ddvidlib.h" -#include "pserror.h" -#include "Application.h" - -#include - -////////////////////////////////////////////////////////////////////////////// -// Variables - -tDDVideoInfo DDVideo_info; -static bool DDVideo_init = false; - -char *DDVID_subsystem_names[] = {"GDIF", // Win32 GDI Fullscreen - "GDI", // Standard Win32 GDI DIBs - "GDIX", // GDI and DirectDraw for mode settings. - "DX", // Direct X! - NULL}; - -int DDVID_subsystems[] = {VID_GDIF_SUBSYSTEM, VID_GDI_SUBSYSTEM, VID_GDIX_SUBSYSTEM, VID_DX_SUBSYSTEM, -1}; - -////////////////////////////////////////////////////////////////////////////// -// Prototypes - -HRESULT WINAPI DDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext); - -////////////////////////////////////////////////////////////////////////////// -// Functions - -// called first to allow fullscreen video access -bool ddvid_Init(oeApplication *app, char *driver) { - int subsys_id; - - // preinitialize system. - if (!DDVideo_init) { - DDVideo_info.lpDD = NULL; - DDVideo_info.lpDDSFront = NULL; - DDVideo_info.lpDDSBack = NULL; - DDVideo_info.hWnd = NULL; - DDVideo_info.nDDModes = 0; - DDVideo_info.curmode = -1; - DDVideo_info.surf_data = NULL; - DDVideo_info.gdi.hBackBmp = NULL; - DDVideo_info.gdi.hBackDC = NULL; - DDVideo_info.gdi.data = NULL; - DDVideo_info.gdi.pitch = 0; - DDVideo_info.gdi.w = 0; - DDVideo_info.gdi.h = 0; - DDVideo_info.gdi.color_depth = 0; - - atexit(ddvid_Close); - } else { - ddvid_Close(); - } - - DDVideo_init = true; - - DDVideo_info.app = (oeWin32Application *)app; - - // find subsystem id based off of subsystem requested. - for (subsys_id = 0; DDVID_subsystems[subsys_id] != -1; subsys_id++) { - if (strcmp(DDVID_subsystem_names[subsys_id], driver) == 0) - break; - } - - if (DDVID_subsystems[subsys_id] == -1) - Error("Subsystem %s not found during startup.", driver); - - DDVideo_info.subsystem = DDVID_subsystems[subsys_id]; - DDVideo_info.hWnd = (HWND)(((oeWin32Application *)app)->m_hWnd); - - // initialize directdraw object. - switch (DDVideo_info.subsystem) { - case VID_GDIF_SUBSYSTEM: - case VID_GDI_SUBSYSTEM: - return ddvidwin_Init(); - case VID_GDIX_SUBSYSTEM: - return true; - case VID_DX_SUBSYSTEM: - return ddvidfs_Init(); - default: - Int3(); - } - - return false; -} - -// closes ddvid system manually. -void ddvid_Close() { - if (!DDVideo_init) - return; - - switch (DDVideo_info.subsystem) { - case VID_GDIF_SUBSYSTEM: - case VID_GDI_SUBSYSTEM: - ddvidwin_Close(); - break; - case VID_GDIX_SUBSYSTEM: - break; - case VID_DX_SUBSYSTEM: - ddvidfs_Close(); - break; - default: - Int3(); - } - - DDVideo_init = false; -} - -// sets the appropriate video mode. -bool ddvid_SetVideoMode(int w, int h, int color_depth, bool paged) { - ASSERT(DDVideo_init); - - switch (DDVideo_info.subsystem) { - case VID_GDIF_SUBSYSTEM: - ddvidwin_CloseVideo(); - return ddvidwin_SetVideoMode(w, h, color_depth, paged, true); - - case VID_GDI_SUBSYSTEM: - ddvidwin_CloseVideo(); - return ddvidwin_SetVideoMode(w, h, color_depth, paged); - - case VID_GDIX_SUBSYSTEM: - ddvidwin_CloseVideo(); - ddvidfs_CloseVideo(); - return (ddvidfs_SetVideoMode(w, h, color_depth, false) && - ddvidwin_SetVideoMode(DDVideo_info.DDModes[DDVideo_info.curmode].dwWidth, - DDVideo_info.DDModes[DDVideo_info.curmode].dwHeight, color_depth, paged)); - case VID_DX_SUBSYSTEM: - ddvidfs_CloseVideo(); - return ddvidfs_SetVideoMode(w, h, color_depth, paged); - default: - Int3(); - } - - return false; -} - -// sets screen handle -void ddvid_SetVideoHandle(unsigned handle) { DDVideo_info.hVidWnd = (HWND)handle; } diff --git a/ddio/CMakeLists.txt b/ddio/CMakeLists.txt index 5b51ea92f..77db61cea 100644 --- a/ddio/CMakeLists.txt +++ b/ddio/CMakeLists.txt @@ -3,27 +3,23 @@ set(CPPS ddio.cpp file.cpp key.cpp + lnxforcefeedback.cpp + lnxio.cpp + sdljoy.cpp + lnxkey.cpp + lnxkey_null.cpp + lnxmouse.cpp + lnxkey_sdl.cpp $<$: lnxfile.cpp - lnxforcefeedback.cpp - lnxio.cpp - sdljoy.cpp - lnxkey.cpp - lnxkey_null.cpp - lnxmouse.cpp - lnxkey_sdl.cpp > $<$: winfile.cpp - winforcefeedback.cpp - winio.cpp - winjoy.cpp - winkey.cpp - winmouse.cpp > ) add_library(ddio STATIC ${CPPS}) target_link_libraries(ddio PRIVATE + SDL2::SDL2 ddebug mem misc diff --git a/ddio/lnxio.cpp b/ddio/lnxio.cpp index 900764853..89e643f99 100644 --- a/ddio/lnxio.cpp +++ b/ddio/lnxio.cpp @@ -62,6 +62,10 @@ #include #endif +#ifdef WIN32 +#include +#endif + #include "application.h" #include "ddio.h" #include "pserror.h" @@ -103,12 +107,7 @@ void ddio_DebugMessage(unsigned err, char *fmt, ...) { } bool ddio_GetBinaryPath(char *exec_path, size_t len) { -#ifndef MACOSX - if (realpath("/proc/self/exe", exec_path) == NULL) { - perror("realpath"); - return false; - } -#else +#ifdef MACOSX if (exec_path == NULL || len == 0) { fprintf(stderr, "Invalid arguments\n"); return false; @@ -119,6 +118,20 @@ bool ddio_GetBinaryPath(char *exec_path, size_t len) { fprintf(stderr, "Buffer too small; need size %u\n", size); return false; } +#elif defined(__LINUX__) + if (realpath("/proc/self/exe", exec_path) == NULL) { + perror("realpath"); + return false; + } +#else + if (GetModuleFileName(NULL, exec_path, len) == 0) { + DWORD error = GetLastError(); + Error("GetModuleFileName failed!"); + return false; + } + exec_path[len - 1] = '\0'; + return true; + #endif exec_path[len - 1] = '\0'; return true; diff --git a/ddio/winforcefeedback.cpp b/ddio/winforcefeedback.cpp deleted file mode 100644 index 719b66797..000000000 --- a/ddio/winforcefeedback.cpp +++ /dev/null @@ -1,1524 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddio_win/winforcefeedback.cpp $ - * $Revision: 19 $ - * $Date: 4/09/99 12:02p $ - * $Author: Samir $ - * - * Low-level force feedback - * - * $Log: /DescentIII/Main/ddio_win/winforcefeedback.cpp $ - * - * 19 4/09/99 12:02p Samir - * joystick changes (Win32 DirectInput support) - * - * 18 3/28/99 5:53p Jeff - * fixed iforce crashes - * - * 17 3/11/99 5:52p Jeff - * always compile in immersion support - * - * 16 1/31/99 11:11p Jeff - * made immersion support as a dynamically loadable dll, and compiled in - * by default - * - * 15 1/30/99 11:27p Jeff - * added immersion support - * - * 14 1/28/99 12:09p Jeff - * added force feedback to player shake...fixed spelling error in define - * for forcefeedback - * - * 13 11/18/98 5:50p Jeff - * added some cheap recoil effects for ForceFeedback...not fully - * implemented - * - * 12 11/10/98 5:16p Jeff - * updated forcefeedback system...pretty complete now - * - * 11 11/06/98 7:00p Jeff - * first round of new force feedback installed - * - * 10 11/03/98 6:43p Jeff - * new low-level & high level Force Feedback system implemented, handles - * window losing focus, etc. - * - * 9 11/01/98 1:58a Jeff - * converted the vsprintf calls to use the Pvsprintf, which is a safe - * vsprintf, no buffer overflows allowed - * - * 8 10/16/98 1:54p Kevin - * Changes for Demo Beta 4 - * - * 7 10/12/98 3:49p Jeff - * struct changes - * - * 6 10/02/98 12:04p Jeff - * fixed forcefeedback bug if it couldn't disable autocenter - * - * 5 9/22/98 3:55p Samir - * ifdef out stuff for non-debug version. - * - * 4 9/21/98 11:10a Jeff - * general update, new low level, small high level implementation - * - * 3 9/18/98 7:38p Jeff - * creation of low-level forcefeedback and beginning of high-level - * forcefeedback - * - * 2 9/15/98 12:05p Jeff - * initial creation of low-level forcefeedback - * - * $NoKeywords: $ - */ - -#if 0 - -#include -#include - -#include -#include - -#include "pserror.h" -#include "mono.h" -#include "ddio.h" -#include "ddio_win.h" -#include "Application.h" -#include "forcefeedback.h" -#include "mem.h" -#include "dinput.h" - -//#include "iforce2.h" - -void ddio_LoadImmersionDLL(void); -void ddio_FreeImmersionDLL(void); - - -void PrintDirectInputErrorString( HRESULT hr,const char *format, ... ); - -#define DDIO_JOY_COOP_FLAGS (DISCL_EXCLUSIVE | DISCL_BACKGROUND) - -bool ddForce_found = false; //a Force Feedback device was found -bool ddForce_enabled = false; //Force Feedback is ready and can be used - - -// Force Feedback Effect Data -// -------------------------- -const GUID *effectGUID[kMaxEffectSubTypes] = { - &GUID_ConstantForce, - &GUID_RampForce, - &GUID_CustomForce, - // period - &GUID_Square, - &GUID_Sine, - &GUID_Triangle, - &GUID_SawtoothUp, - &GUID_SawtoothDown, - // condition - &GUID_Spring, - &GUID_Damper, - &GUID_Inertia, - &GUID_Friction -}; - -union tEffectClasses { - DICONSTANTFORCE constant; - DIRAMPFORCE ramp; - DIPERIODIC period; - DICONDITION condition; - DICUSTOMFORCE custom; -}; - -struct tEffect { - DIEFFECT general; - tEffectClasses specific; - DIENVELOPE envelope; - LONG direction[2]; -}tddEffect; - -static tddEffect ddEffect[DDIO_FF_MAXEFFECTS]; - -// DInput Data -// ----------- -static LPDIRECTINPUT DI = NULL; -static LPDIRECTINPUTDEVICE DID1_Rat = NULL; -static LPDIRECTINPUTDEVICE DID1_Key = NULL; -static LPDIRECTINPUTDEVICE2 DID2_Joy[kMaxJoy]; -static LPDIRECTINPUTEFFECT DIE_hEffect[DDIO_FF_MAXEFFECTS]; - -// Joystick Data -// ------------- -static int maskFFB = 0; -static int numJoy = 0; -static int numEffects = 0; -static char isWheel[kMaxJoy]; -static char joyName[kMaxJoy][_MAX_PATH]; -static DWORD dwAxes[2] = { DIJOFS_X, DIJOFS_Y }; - -// Private Functions -// ----------------- -BOOL CALLBACK FFEnumCallback(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef); -static int ddio_ffjoy_AcquireErr(HRESULT res, int dev_num); -static int ddio_ffjoy_UnacquireErr(HRESULT res, int dev_num); - -static int ddio_ff_SetCoopLevel(tDevice dev, int coop_level); -int ddio_ffb_Init(void); - -void *getwindowhandle(void) -{ - return DInputData.hwnd; -} - -/* -===================================================================== -= = -= Device & Low-Level Driver Functions = -= = -===================================================================== -*/ - -LPDIRECTINPUTDEVICE2 ddio_ff_get_joystick_obj(tDevice dev) -{ - return DID2_Joy[(int)dev]; -} - - -// ------------------------------------------------------------------- -// ddio_ff_AttachForce -// Purpose: -// Attaches variables initialized in the general ddio system to -// the force feedback system. -// ------------------------------------------------------------------- -void ddio_ff_AttachForce(void) -{ - ddio_LoadImmersionDLL(); - - for(int i=0;iEnumDevices(DIDEVTYPE_JOYSTICK,FF_CB_PTR,DI,DIEDFL_ATTACHEDONLY); - - for (i=0; i kAllDevices){ - mprintf(0,"ddio_ff_Acquire: Invalid device ID, out of range\n"); - return 0; - }else{ - if (DID2_Joy[dev]){ - int ret = ddio_ffjoy_AcquireErr(IDirectInputDevice2_Acquire(DID2_Joy[dev]),dev); - return ret; - } - }break; - } - }else - mprintf(0,"ddio_ff_Acquire: Direct Input object not initialized...\n"); - - return cnt; -} - -// ------------------------------------------------------------------- -// ddio_ff_Unacquire -// Purpose: -// Unacquires a direct input device -// -// Input: -// The device to unacquire (use kDI_MaxJoy to unacquire all available -// joysticks). -// -// Return: -// # of devices unacquired. -// -// Description: -// Call this to lose access to a device after the device has been -// aquired -// -// ------------------------------------------------------------------- -int ddio_ff_Unacquire(tDevice dev) -{ - int i,cnt=0; - - if(DI){ - if (dev == kAllDevices){ - cnt += ddio_ff_Unacquire(kMaxJoy); - return cnt; - } - - switch (dev){ - case kMaxJoy: - { - for (i=0; i kAllDevices){ - mprintf(0,"ddio_ff_Unacquire: Invalid device ID, out of range\n"); - return 0; - }else{ - if (DID2_Joy[dev]){ - int ret = ddio_ffjoy_UnacquireErr(IDirectInputDevice2_Unacquire(DID2_Joy[dev]),dev); - return ret; - } - }break; - } - }else - mprintf(0,"ddio_ff_Unacquire: Direct Input object not initialized...\n"); - - return cnt; -} - - -// ------------------------------------------------------------------- -// ddio_ff_SetCoopLevel -// ------------------------------------------------------------------- -static int ddio_ff_SetCoopLevel(tDevice dev, int coop_level) -{ - HWND hwin; - - if (!(hwin=(HWND)getwindowhandle())) - { - mprintf(0,"ddio_ff_SetCoopLevel: couldn't get window handle\n"); - } - - // Set a single joystick - // --------------------- - if (dev < kMaxJoy){ - if (DID2_Joy[dev]){ - // Set the cooperative level to share the device - // --------------------------------------------- - if (IDirectInputDevice2_SetCooperativeLevel(DID2_Joy[dev], (HWND)getwindowhandle(), coop_level)!= DI_OK){ - mprintf(0,"ddio_ff_SetCoopLevel: Could not set dinput device coop level\n"); - return 0; - } - } - }else// Set all single joysticks - if (dev == kMaxJoy){ - int i; - for (i=kJoy1; idwDevType)) - isWheel[numJoy] = TRUE; - else - isWheel[numJoy] = FALSE; - - // Create an instance of the device - // -------------------------------- - if (IDirectInput_CreateDevice(pdi, pdinst->guidInstance, &pdev, NULL)!= DI_OK){ - mprintf(0,"DIEnumJoysticks_Callback: Could not create dinput device obj\n"); - return DIENUM_CONTINUE; - } - - // Set the data format to the default - // ---------------------------------- - if (IDirectInputDevice_SetDataFormat(pdev, &c_dfDIJoystick)!= DI_OK){ - mprintf(0,"DIEnumJoysticks_Callback: Could not set dinput device data format\n"); - IDirectInputDevice_Unacquire(pdev); - IDirectInputDevice_Release (pdev); - return DIENUM_CONTINUE; - } - - // Get the DID2 from DID1 - // ---------------------- - if (IDirectInputDevice_QueryInterface(pdev, IID_IDirectInputDevice2, (void **) &DID2_Joy[numJoy])!= DI_OK){ - mprintf(0,"DIEnumJoysticks_Callback: QueryInterface did not return DI_OK\n"); - IDirectInputDevice_Unacquire(pdev); - IDirectInputDevice_Release (pdev); - return DIENUM_CONTINUE; - } - - // Set the cooperative level - // ------------------------- - if (!ddio_ff_SetCoopLevel((tDevice)numJoy, DDIO_JOY_COOP_FLAGS)){ - mprintf(0,"DIEnumJoysticks_Callback: Could not set dinput coop level\n"); - return FALSE; - } - - // Done with Device1 - // ----------------- - IDirectInputDevice_Unacquire(pdev); - IDirectInputDevice_Release (pdev); - - // Device was added successfully - // ----------------------------- - numJoy++; - - return DIENUM_CONTINUE; -} - - -// ------------------------------------------------------------------- -// ddio_ffjoy_Query -// Purpose: -// Besides checking what buttons/axis are available, this function -// also checks for force feedback support. -// ------------------------------------------------------------------- -int ddio_ffjoy_Query(int dev, int* but_flags, int* axis_flags) -{ - uint32_t i,bit; - DIDEVCAPS DICaps; - DIDEVICEOBJECTINSTANCE DIObjInst; - DWORD DIAxisOFS[6] = { DIJOFS_X, - DIJOFS_Y, - DIJOFS_Z, - DIJOFS_RX, - DIJOFS_SLIDER(0), - DIJOFS_SLIDER(1) }; - - // Make sure Main DInput OBJ has been created - // ------------------------------------------ - if (!DI){ - ddio_ff_Init(); - if (!DI){ - mprintf(0,"ddio_ffjoy_Query: Dinput not initialized yet\n"); - return FALSE; - } - } - - if (!DID2_Joy[dev]){ - mprintf(0,"ddio_ffjoy_Query: device not found #%d\n",dev); - return 0; - } - - if (!numJoy){ - if (but_flags)*but_flags=0; - if (axis_flags)*axis_flags=0; - return 0; - } - - ddio_ff_Acquire((tDevice)dev); - - DICaps.dwSize = sizeof(DIDEVCAPS); - - if (IDirectInputDevice2_GetCapabilities(DID2_Joy[dev],&DICaps) != DI_OK){ - mprintf(0,"ddio_ffjoy_Query: Failed getting device caps\n"); - return 0; - } - - if (DICaps.dwFlags & DIDC_FORCEFEEDBACK){ - mprintf(0,"ddio_ff_joy_Query: ffb support\n"); - maskFFB |= 1<= kMaxJoy){ - return; - } - - if (DID2_Joy[dev] && (maskFFB & 1<SetProperty(DIPROP_AUTOCENTER,&DIPropAutoCenter.diph); - ddio_ff_Acquire(dev); - - if (FAILED(hr)){ - PrintDirectInputErrorString(hr,"Force: Failed to change autocenter property."); - } - } -} - -// ------------------------------------------------------------------- -// ddio_ffjoy_SetGain -// Purpose: -// Sets the gain for joystick, pass a value of 0-1 -// ------------------------------------------------------------------- -void ddio_ffjoy_SetGain(tDevice dev,float value) -{ - DIPROPDWORD DIPropAutoCenter; - DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter); - DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER); - DIPropAutoCenter.diph.dwObj = 0; - DIPropAutoCenter.diph.dwHow = DIPH_DEVICE; - - DIPropAutoCenter.dwData = (DWORD)(value*10000.0f); - - if (dev >= kMaxJoy){ - return; - } - - if (DID2_Joy[dev] && (maskFFB & 1<SetProperty(DIPROP_FFGAIN ,&DIPropAutoCenter.diph); - - if (FAILED(hr)){ - PrintDirectInputErrorString(hr,"Force: Failed to set gain."); - } - } -} - -// ------------------------------------------------------------------- -// ddio_ffjoy_IsAutoCentered -// Purpose: -// Returns true if the joystick is set for autocentering -// ------------------------------------------------------------------- -bool ddio_ffjoy_IsAutoCentered(tDevice dev) -{ - DIPROPDWORD DIPropAutoCenter; - DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter); - DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER); - DIPropAutoCenter.diph.dwObj = 0; - DIPropAutoCenter.diph.dwHow = DIPH_DEVICE; - - if (dev >= kMaxJoy){ - return false; - } - - if (DID2_Joy[dev] && (maskFFB & 1<GetProperty(DIPROP_AUTOCENTER,&DIPropAutoCenter.diph); - ddio_ff_Acquire(dev); - - if (FAILED(hr)){ - PrintDirectInputErrorString(hr,"Force: Failed to get autocenter property"); - return false; - } - return (DIPropAutoCenter.dwData)?true:false; - } - return false; -} - -// ------------------------------------------------------------------- -// ddio_ffjoy_SupportAutoCenter -// Purpose: -// Returns true if the FF joystick supports auto centering -// ------------------------------------------------------------------- -bool ddio_ffjoy_SupportAutoCenter(tDevice dev) -{ - if (dev >= kMaxJoy){ - return false; - } - - if (DID2_Joy[dev] && (maskFFB & 1<SetProperty(DIPROP_AUTOCENTER,&DIPropAutoCenter.diph); - ddio_ff_Acquire(dev); - - switch(hr){ - case DI_OK: - case S_FALSE: - return true; - default: - PrintDirectInputErrorString(hr,""); - return false; - } - } - - return false; -} - -/* -============================================================================= -= = -= Force Feedback Effect Functions = -= = -============================================================================= -*/ - -// ------------------------------------------------------------------- -// ddio_ff_GetInfo -// Purpose: -// Returns information about the current state of the low-level -// Force Feedback system. -// ------------------------------------------------------------------- -void ddio_ff_GetInfo(bool *ff_found,bool *ff_enabled) -{ - if(ddForce_found){ - if(ff_found) - *ff_found = true; - if(ff_enabled) - *ff_enabled = ddForce_enabled; - - }else{ - if(ff_found) - *ff_found = false; - if(ff_enabled) - *ff_enabled = false; - } -} - - -// ------------------------------------------------------------------- -// ddio_ffb_Pause -// Purpose: -// Pause the FFB output on the given device. Use ddio_ffb_Continue to -// continue where you left off. -// ------------------------------------------------------------------- -void ddio_ffb_Pause(tDevice dev) -{ - if (dev == kMaxJoy){ - int i; - for (i=0; i= DDIO_FF_MAXEFFECTS){ - mprintf(0,"ddio_ffb_effectCreate: Reached hardcoded limit for # of effects.\n"); - return -1; - } - - if (!(DID2_Joy[dev] && (maskFFB & 1<Duration; - ddEffect[numEffects].general.dwSamplePeriod = eff->Period; - ddEffect[numEffects].general.dwGain = eff->Gain; - ddEffect[numEffects].general.dwTriggerButton = (eff->Trigger==kNoButton?DIEB_NOTRIGGER:DIJOFS_BUTTON(eff->Trigger)); - ddEffect[numEffects].general.dwTriggerRepeatInterval = eff->TriggerRepeatTime; - ddEffect[numEffects].direction[0] = eff->Direction; - memcpy(&ddEffect[numEffects].specific,&eff->TypeInfo,sizeof(tEffectClasses)); - - // COM related - ddEffect[numEffects].general.dwSize = sizeof(DIEFFECT); - ddEffect[numEffects].general.cAxes = isWheel[dev]?1:2; - ddEffect[numEffects].general.rgdwAxes = &dwAxes[0]; - ddEffect[numEffects].general.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; - ddEffect[numEffects].general.lpvTypeSpecificParams = &ddEffect[numEffects].specific; - ddEffect[numEffects].general.rglDirection = (LONG *)ddEffect[numEffects].direction; - ddEffect[numEffects].direction[1] = 0L; - ddEffect[numEffects].general.lpEnvelope = NULL; - - if(eff->Flags&FF_USEENVELOPE){ - ddEffect[numEffects].envelope.dwSize = sizeof(DIENVELOPE); - ddEffect[numEffects].envelope.dwAttackLevel = eff->Envelope.AttackLevel; - ddEffect[numEffects].envelope.dwAttackTime = eff->Envelope.AttackTime; - ddEffect[numEffects].envelope.dwFadeLevel = eff->Envelope.FadeLevel; - ddEffect[numEffects].envelope.dwFadeTime = eff->Envelope.FadeTime; - ddEffect[numEffects].general.lpEnvelope = &ddEffect[numEffects].envelope; - } - - - switch (eff->Type){ - case kConstant: - ddEffect[numEffects].general.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); - break; - case kRamp: - ddEffect[numEffects].general.cbTypeSpecificParams = sizeof(DIRAMPFORCE); - break; - case kCustom: - ddEffect[numEffects].general.cbTypeSpecificParams = sizeof(DICUSTOMFORCE); - break; - case kWave_Square: - case kWave_Sine: - case kWave_Triangle: - case kWave_SawUp: - case kWave_SawDown: - ddEffect[numEffects].general.cbTypeSpecificParams = sizeof(DIPERIODIC); - break; - case kCondition_Spring: - case kCondition_Damper: - case kCondition_Inertia: - case kCondition_Friction: - ddEffect[numEffects].general.cbTypeSpecificParams = sizeof(DICONDITION); - break; - default: - mprintf(0,"ddio_ffb_effectCreate: bad effect subType\n"); - return -1; - } - - hr=IDirectInputDevice2_CreateEffect( DID2_Joy[dev], - *effectGUID[eff->Type], - (LPCDIEFFECT) &ddEffect[numEffects], - (LPDIRECTINPUTEFFECT*) &DIE_hEffect[numEffects], 0); - - switch (hr){ - case DI_OK: - ddio_ffb_effectUnload(numEffects); - numEffects++; - return (numEffects-1); - case DIERR_DEVICENOTREG: - mprintf(0,"ddio_ffb_effectCreate: effect not created, DIERR_DEVICENOTREG\n"); - return -1; - case DIERR_DEVICEFULL: - mprintf(0,"ddio_ffb_effectCreate: effect not created, DIERR_DEVICEFULL\n"); - return -1; - default: - PrintDirectInputErrorString(hr,"Force Effect Create"); - break; - } - return -1; -} - -// ------------------------------------------------------------------- -// ddio_ffb_effectPlay -// Purpose: -// Play an effect that was previously created. -// ------------------------------------------------------------------- -void ddio_ffb_effectPlay(int16_t eID) -{ - if(eID<0 || eID>=DDIO_FF_MAXEFFECTS){ - Int3(); //invalid eID - return; - } - bool try_again = true; - -ff_try: - HRESULT hr = IDirectInputEffect_Start(DIE_hEffect[eID],1,0); - - - if(FAILED(hr)){ - PrintDirectInputErrorString(hr,"Force Play"); - if(try_again){ - ddio_ff_Acquire(kMaxJoy); - try_again = false; - goto ff_try; - } - } - -} - -// ------------------------------------------------------------------- -// ddio_ffb_effectStop -// Purpose: -// Stop a single effect. -// ------------------------------------------------------------------- -void ddio_ffb_effectStop(int16_t eID) -{ - if(eID<0 || eID>=DDIO_FF_MAXEFFECTS){ - Int3(); //invalid eID - return; - } - - IDirectInputEffect_Stop(DIE_hEffect[eID]); -} - -// ------------------------------------------------------------------- -// ddio_ffb_effectStopAll -// Purpose: -// Stops all forces on the given device. -// ------------------------------------------------------------------- -void ddio_ffb_effectStopAll(tDevice dev) -{ - if (DID2_Joy[dev] && (maskFFB & 1<=DDIO_FF_MAXEFFECTS){ - Int3(); //invalid eID - return; - } - IDirectInputEffect_Unload(DIE_hEffect[eID]); -} - - -// ------------------------------------------------------------------- -// ddio_ffb_effectModify -// Purpose: -// Modifies a single effect, only if the given parameters are -// different from what's currently loaded. -// ------------------------------------------------------------------- -void ddio_ffb_effectModify(int16_t eID, int* Direction, uint32_t* Duration, uint32_t* Gain, uint32_t* Period, tEffInfo* TypeInfo, tEffEnvelope* Envelope) -{ - uint32_t flags = 0; - - //return; - - if (Direction){ - if (ddEffect[eID].direction[0] != *Direction){ - ddEffect[eID].direction[0] = *Direction; - flags |= DIEP_DIRECTION; - } - } - - if (Duration){ - if (ddEffect[eID].general.dwDuration != *Duration){ - ddEffect[eID].general.dwDuration = *Duration; - flags |= DIEP_DURATION; - } - } - - if (Gain){ - if (ddEffect[eID].general.dwGain != *Gain){ - ddEffect[eID].general.dwGain = *Gain; - flags |= DIEP_GAIN; - } - } - - if (Period){ - if (ddEffect[eID].general.dwSamplePeriod != *Period){ - ddEffect[eID].general.dwSamplePeriod = *Period; - flags |= DIEP_SAMPLEPERIOD; - } - } - - if (TypeInfo){ - if (!memcmp( &ddEffect[eID].specific, TypeInfo, ddEffect[eID].general.cbTypeSpecificParams)){ - memcpy( &ddEffect[eID].specific, TypeInfo, ddEffect[eID].general.cbTypeSpecificParams); - flags |= DIEP_TYPESPECIFICPARAMS; - } - } - - if (Envelope){ - if (ddEffect[eID].envelope.dwAttackLevel != Envelope->AttackLevel || - ddEffect[eID].envelope.dwAttackTime != Envelope->AttackTime || - ddEffect[eID].envelope.dwFadeLevel != Envelope->FadeLevel || - ddEffect[eID].envelope.dwFadeTime != Envelope->FadeTime ){ - ddEffect[eID].envelope.dwAttackLevel = Envelope->AttackLevel; - ddEffect[eID].envelope.dwAttackTime = Envelope->AttackTime; - ddEffect[eID].envelope.dwFadeLevel = Envelope->FadeLevel; - ddEffect[eID].envelope.dwFadeTime = Envelope->FadeTime; - flags |= DIEP_ENVELOPE; - } - } - - if (!flags) - return; - - IDirectInputEffect_SetParameters(DIE_hEffect[eID], (LPCDIEFFECT)&ddEffect[eID], flags); -} - -// ------------------------------------------------------------------- -// ddio_ffb_GetEffectData -// Purpose: -// Retrieves affect data for the given parameters, pass NULL for those you don't want -// ------------------------------------------------------------------- -void ddio_ffb_GetEffectData(int16_t eID, int* Direction, uint32_t* Duration, uint32_t* Gain, uint32_t* Period, tEffInfo* TypeInfo, tEffEnvelope* Envelope) -{ - if (Direction){ - *Direction = ddEffect[eID].direction[0]; - } - - if (Duration){ - *Duration = ddEffect[eID].general.dwDuration; - } - - if (Gain){ - *Gain = ddEffect[eID].general.dwGain; - } - - if (Period){ - *Period = ddEffect[eID].general.dwSamplePeriod; - } - - if (TypeInfo){ - memcpy( TypeInfo,&ddEffect[eID].specific,ddEffect[eID].general.cbTypeSpecificParams); - } - - if (Envelope){ - Envelope->AttackLevel = ddEffect[eID].envelope.dwAttackLevel; - Envelope->AttackTime = ddEffect[eID].envelope.dwAttackTime; - Envelope->FadeLevel = ddEffect[eID].envelope.dwFadeLevel; - Envelope->FadeTime = ddEffect[eID].envelope.dwFadeTime; - } -} - - -//==================================================================== -// Private Fuctions -//==================================================================== - -// ------------------------------------------------------------------- -// ddio_ffjoy_AcquireErr -// Purpose: -// Handle success/err reporting -// ------------------------------------------------------------------- -static int ddio_ffjoy_AcquireErr(HRESULT res, int dev_num) -{ - if (res == DI_OK){ - mprintf(0,"device #%d acquired\n",dev_num); - return TRUE; - } - else - if (res == S_FALSE){ - mprintf(0,"device #%d already acquired\n",dev_num); - return TRUE; - } - else - if (res == DIERR_INVALIDPARAM){ - mprintf(0,"device %d DIERR_INVALIDPARAM\n",dev_num); - return FALSE; - } - else - if (res == DIERR_OTHERAPPHASPRIO){ - mprintf(0,"device %d DIERR_OTHERAPPHASPRIO\n",dev_num); - return TRUE; - } - else - mprintf(0,"Unknown Error acquiring device %d\n",dev_num); - - return FALSE; -} - -// ------------------------------------------------------------------- -// ddio_ffjoy_UnacquireErr -// Purpose: -// Handle success/err reporting -// ------------------------------------------------------------------- -static int ddio_ffjoy_UnacquireErr(HRESULT res, int dev_num) -{ - if (res == DI_OK){ - mprintf(0,"device #%d unacquired\n",dev_num); - return TRUE; - } - else - if (res == S_FALSE){ - mprintf(0,"device #%d already unacquired\n",dev_num); - return TRUE; - } - else - if (res == DIERR_INVALIDPARAM){ - mprintf(0,"device %d DIERR_INVALIDPARAM\n",dev_num); - return FALSE; - } - else - if (res == DIERR_OTHERAPPHASPRIO){ - mprintf(0,"device %d DIERR_OTHERAPPHASPRIO\n",dev_num); - return TRUE; - } - else - mprintf(0,"Unknown Error unacquiring device %d\n",dev_num); - - return FALSE; -} - - -/* -***************************************************************** - - Immersion - -***************************************************************** -*/ -#if 0 -#pragma message("Compiling Immersion Support.") - -HMODULE ImmersionHandle = NULL; -typedef HIFORCEPROJECT (__stdcall *IFLoadProjectFile_fp)(LPCSTR pProjectFileName,LPDIRECTINPUTDEVICE2A pDevice ); -IFLoadProjectFile_fp d_IFLoadProjectFile = NULL; - -typedef BOOL (__stdcall *IFReleaseProject_fp)(HIFORCEPROJECT hProject); -IFReleaseProject_fp d_IFReleaseProject = NULL; - -typedef LPDIRECTINPUTEFFECT *(__stdcall *IFCreateEffects_fp)(HIFORCEPROJECT hProject,LPCSTR pObjectName,int *pNumEffects ); -IFCreateEffects_fp d_IFCreateEffects = NULL; - - -void ddio_LoadImmersionDLL(void) -{ - if(ImmersionHandle!=NULL){ - ddio_FreeImmersionDLL(); - } - - ImmersionHandle = LoadLibrary("IForce2.dll"); - - if(ImmersionHandle==NULL){ - //not found - mprintf(0,"Force: Unable to find Immersion DLL\n"); - return; - } - - //get functions - d_IFLoadProjectFile = (IFLoadProjectFile_fp)GetProcAddress(ImmersionHandle,"_IFLoadProjectFile@8"); - d_IFReleaseProject = (IFReleaseProject_fp)GetProcAddress(ImmersionHandle,"_IFReleaseProject@4"); - d_IFCreateEffects = (IFCreateEffects_fp)GetProcAddress(ImmersionHandle,"_IFCreateEffects@12"); - - if( !d_IFLoadProjectFile || - !d_IFReleaseProject || - !d_IFCreateEffects){ - mprintf(0,"Force: Unable to bind Immersion functions\n"); - ddio_FreeImmersionDLL(); - return; - } - - mprintf(0,"Immersion IFORCE2 DLL loaded successfully\n"); -} - -void ddio_FreeImmersionDLL(void) -{ - if(ImmersionHandle){ - FreeLibrary(ImmersionHandle); - ImmersionHandle = NULL; - d_IFLoadProjectFile = NULL; - d_IFReleaseProject = NULL; - d_IFCreateEffects = NULL; - } -} - -// Given a filename resource, this loads the file and creates a resource -// for it. It returns a handle to that resource. -// If it returns NULL, then it couldn't load the project. -// Make sure device is aquired before calling. -FORCEPROJECT ddio_ForceLoadProject(char *filename,tDevice dev) -{ - if(!d_IFLoadProjectFile){ - return NULL; - } - - if( dev < 0 || dev >kMaxJoy ){ - mprintf(0,"illegal device id passed to ddio_ForceLoadProject() - %d\n",(int)dev); - return NULL; - } - - HIFORCEPROJECT prj = d_IFLoadProjectFile(filename,DID2_Joy[dev]); - return (FORCEPROJECT)prj; -} - -// Unloads a FORCEPROJECT file -void ddio_ForceUnloadProject(FORCEPROJECT prj) -{ - if(!d_IFReleaseProject) - return; - - if(!prj) - return; - - d_IFReleaseProject((HIFORCEPROJECT)prj); -} - -// Given a handle to a resource, and the name of the effect to load -// it will load that effect. Returns the effect ID, or -1 if it couldn't -// be created -int ddio_CreateForceFromProject(FORCEPROJECT project,const char *forcename) -{ - if(!d_IFCreateEffects){ - return -1; - } - - LPDIRECTINPUTEFFECT * gppdie; - HIFORCEPROJECT prj; - - if(!project) - return -1; - - prj = (HIFORCEPROJECT)project; - - gppdie = d_IFCreateEffects(prj,forcename,NULL); - - if( !gppdie ){ - return -1; - } - - DIE_hEffect[numEffects] = *gppdie; - numEffects++; - return (numEffects-1); -} - -#else -#pragma message("Not Compiling For Immersion Support.") -// Given a filename resource, this loads the file and creates a resource -// for it. It returns a handle to that resource. -// If it returns NULL, then it couldn't load the project. -// Make sure device is aquired before calling. -FORCEPROJECT ddio_ForceLoadProject(char *filename,tDevice dev) -{ - return NULL; -} - -// Unloads a FORCEPROJECT file -void ddio_ForceUnloadProject(FORCEPROJECT prj) -{ - return; -} - -// Given a handle to a resource, and the name of the effect to load -// it will load that effect. Returns the effect ID, or -1 if it couldn't -// be created -int ddio_CreateForceFromProject(FORCEPROJECT project,const char *forcename) -{ - return -1; -} - -void ddio_LoadImmersionDLL(void) -{ -} - -void ddio_FreeImmersionDLL(void) -{ -} - -#endif - - -//========================================================== -// Function: PrintDirectInputErrorString -// -// Description: -// Prints a debug message(s) of errors based on error -// code passed in. -// -//========================================================== -void PrintDirectInputErrorString( HRESULT hr,const char *format, ... ) -{ -#ifdef RELEASE - return; -#endif - char buffer[2048]; - - std::va_list marker; - va_start(marker,format); - std::vsnprintf(buffer,2048,format,marker); - va_end(marker); - strcat(buffer,": \n"); - - if(hr==S_FALSE){ - strcat(buffer,"*S_FALSE\n"); - mprintf(0,buffer); - return; - } - - if(hr==DI_BUFFEROVERFLOW) - strcat(buffer,"*The device buffer overflowed and some input was lost. This value is equal to the S_FALSE standard COM return value.\n"); - if(hr==DI_DOWNLOADSKIPPED) - strcat(buffer,"*The parameters of the effect were successfully updated, but the effect could not be downloaded because the associated device was not acquired in exclusive mode. \n"); - if(hr==DI_EFFECTRESTARTED) - strcat(buffer,"*The effect was stopped, the parameters were updated, and the effect was restarted.\n"); - if(hr==DI_NOEFFECT) - strcat(buffer,"*The operation had no effect. This value is equal to the S_FALSE standard COM return value.\n"); - if(hr==DI_NOTATTACHED) - strcat(buffer,"*The device exists but is not currently attached. This value is equal to the S_FALSE standard COM return value.\n"); - if(hr==DI_OK) - strcat(buffer,"*The operation completed successfully. This value is equal to the S_OK standard COM return value.\n"); - if(hr==DI_POLLEDDEVICE) - strcat(buffer,"*The device is a polled device. As a result, device buffering will not collect any data and event notifications will not be signaled until the IDirectInputDevice2::Poll method is called.\n"); - if(hr==DI_PROPNOEFFECT) - strcat(buffer,"*The change in device properties had no effect. This value is equal to the S_FALSE standard COM return value.\n"); - if(hr==DI_TRUNCATED) - strcat(buffer,"*The parameters of the effect were successfully updated, but some of them were beyond the capabilities of the device and were truncated to the nearest supported value.\n"); - if(hr==DI_TRUNCATEDANDRESTARTED) - strcat(buffer,"*Equal to DI_EFFECTRESTARTED | DI_TRUNCATED.\n"); - if(hr==DIERR_ACQUIRED) - strcat(buffer,"*The operation cannot be performed while the device is acquired.\n"); - if(hr==DIERR_ALREADYINITIALIZED) - strcat(buffer,"*This object is already initialized\n"); - if(hr==DIERR_BADDRIVERVER) - strcat(buffer,"*The object could not be created due to an incompatible driver version or mismatched or incomplete driver components.\n"); - if(hr==DIERR_BETADIRECTINPUTVERSION) - strcat(buffer,"*The application was written for an unsupported prerelease version of DirectInput.\n"); - if(hr==DIERR_DEVICEFULL) - strcat(buffer,"*The device is full.\n"); - if(hr==DIERR_DEVICENOTREG) - strcat(buffer,"*The device or device instance is not registered with DirectInput. This value is equal to the REGDB_E_CLASSNOTREG standard COM return value.\n"); - if(hr==DIERR_EFFECTPLAYING) - strcat(buffer,"*The parameters were updated in memory but were not downloaded to the device because the device does not support updating an effect while it is still playing. \n"); - if(hr==DIERR_HASEFFECTS) - strcat(buffer,"*The device cannot be reinitialized because there are still effects attached to it.\n"); - if(hr==DIERR_GENERIC) - strcat(buffer,"*An undetermined error occurred inside the DirectInput subsystem. This value is equal to the E_FAIL standard COM return value.\n"); - if(hr==DIERR_HANDLEEXISTS) - strcat(buffer,"*The device already has an event notification associated with it. This value is equal to the E_ACCESSDENIED standard COM return value.\n"); - if(hr==DIERR_INCOMPLETEEFFECT) - strcat(buffer,"*The effect could not be downloaded because essential information is missing. For example, no axes have been associated with the effect, or no type-specific information has been supplied.\n"); - if(hr==DIERR_INPUTLOST) - strcat(buffer,"*Access to the input device has been lost. It must be reacquired.\n"); - if(hr==DIERR_INVALIDPARAM) - strcat(buffer,"*An invalid parameter was passed to the returning function, or the object was not in a state that permitted the function to be called. This value is equal to the E_INVALIDARG standard COM return value.\n"); - if(hr==DIERR_MOREDATA) - strcat(buffer,"*Not all the requested information fitted into the buffer.\n"); - if(hr==DIERR_NOAGGREGATION) - strcat(buffer,"*This object does not support aggregation.\n"); - if(hr==DIERR_NOINTERFACE) - strcat(buffer,"*The specified interface is not supported by the object. This value is equal to the E_NOINTERFACE standard COM return value.\n"); - if(hr==DIERR_NOTACQUIRED) - strcat(buffer,"*The operation cannot be performed unless the device is acquired.\n"); - if(hr==DIERR_NOTBUFFERED) - strcat(buffer,"*The device is not buffered. Set the DIPROP_BUFFERSIZE property to enable buffering. \n"); - if(hr==DIERR_NOTDOWNLOADED) - strcat(buffer,"*The effect is not downloaded.\n"); - if(hr==DIERR_NOTEXCLUSIVEACQUIRED) - strcat(buffer,"*The operation cannot be performed unless the device is acquired in DISCL_EXCLUSIVE mode. \n"); - if(hr==DIERR_NOTFOUND) - strcat(buffer,"*The requested object does not exist.\n"); - if(hr==DIERR_NOTINITIALIZED) - strcat(buffer,"*This object has not been initialized.\n"); - if(hr==DIERR_OBJECTNOTFOUND) - strcat(buffer,"*The requested object does not exist.\n"); - if(hr==DIERR_OLDDIRECTINPUTVERSION) - strcat(buffer,"*The application requires a newer version of DirectInput.\n"); - if(hr==DIERR_OTHERAPPHASPRIO) - strcat(buffer,"*Another application has a higher priority level, preventing this call from succeeding. This value is equal to the E_ACCESSDENIED standard COM return value. This error can be returned when an application has only foreground access to a device but is attempting to acquire the device while in the background. \n"); - if(hr==DIERR_OUTOFMEMORY) - strcat(buffer,"*The DirectInput subsystem couldn't allocate sufficient memory to complete the call. This value is equal to the E_OUTOFMEMORY standard COM return value.\n"); - if(hr==DIERR_READONLY) - strcat(buffer,"*The specified property cannot be changed. This value is equal to the E_ACCESSDENIED standard COM return value.\n"); - //@@if(hr==DIERR_REPORTFULL) - //@@ strcat(buffer,"*More information was requested to be sent than can be sent to the device.\n"); - //@@if(hr==DIERR_UNPLUGGED) - //@@ strcat(buffer,"*The operation could not be completed because the device is not plugged in.\n"); - if(hr==DIERR_UNSUPPORTED) - strcat(buffer,"*The function called is not supported at this time. This value is equal to the E_NOTIMPL standard COM return value. \n"); - if(hr==E_PENDING) - strcat(buffer,"*Data is not yet available.\n"); - mprintf(0,buffer); -} - -#else - -#include "forcefeedback.h" - -void ddio_ff_GetInfo(bool *ff_found, bool *ff_enabled) { - if (ff_found) { - *ff_found = false; - } - - if (ff_enabled) { - *ff_enabled = false; - } -} - -void ddio_ffb_Pause(tDevice dev) {} - -void ddio_ffb_Continue(tDevice dev) {} - -int ddio_ff_Acquire(tDevice dev) { return 0; } - -void ddio_ffjoy_EnableAutoCenter(tDevice dev, bool enable) {} - -void ddio_ffjoy_SetGain(tDevice dev, float value) {} - -bool ddio_ffjoy_SupportAutoCenter(tDevice dev) { return false; } - -void ddio_ffb_DestroyAll(void) {} - -void ddio_ffb_effectPlay(int16_t eID) {} - -void ddio_ffb_effectModify(int16_t eID, int *Direction, uint32_t *Duration, uint32_t *Gain, uint32_t *Period, - tEffInfo *TypeInfo, tEffEnvelope *Envelope) {} - -int ddio_ffb_effectCreate(tDevice dev, tFFB_Effect *eff) { return -1; } - -int ddio_CreateForceFromProject(FORCEPROJECT project, const char *forcename) { return -1; } - -void ddio_ForceUnloadProject(FORCEPROJECT prj) {} - -FORCEPROJECT ddio_ForceLoadProject(char *filename, tDevice dev) { return NULL; } - -int ddio_ffjoy_Init(void) { return 0; } - -int ddio_ff_Init(void) { return 0; } - -void ddio_ff_AttachForce(void) {} - -void ddio_ff_DetachForce(void) {} - -LPDIRECTINPUTDEVICE2 ddio_ff_get_joystick_obj(tDevice dev) { return NULL; } - -#endif diff --git a/ddio/winio.cpp b/ddio/winio.cpp deleted file mode 100644 index 5edc69f97..000000000 --- a/ddio/winio.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddio_win/winio.cpp $ - * $Revision: 17 $ - * $Date: 7/09/01 1:55p $ - * $Author: Matt $ - * - * - * - * $Log: /DescentIII/Main/ddio_win/winio.cpp $ - * - * 17 7/09/01 1:55p Matt - * Try opening DX5 for NT so force feedback will work. - * - * 16 4/09/99 12:02p Samir - * joystick changes (Win32 DirectInput support) - * - * 15 1/25/99 11:02a Samir - * revamped mouse and key controls. - * - * 14 11/18/98 5:50p Jeff - * free up force feedback before unloading DI - * - * 13 11/03/98 6:43p Jeff - * new low-level & high level Force Feedback system implemented, handles - * window losing focus, etc. - * - * 12 11/01/98 1:58a Jeff - * converted the vsprintf calls to use the Pvsprintf, which is a safe - * vsprintf, no buffer overflows allowed - * - * 11 10/18/98 6:18p Matt - * Turn the pointer on when shutting down. This fixes a problem where you - * couldn't click Ok on an error message box because the pointer was off - * for our app. - * - * 10 9/18/98 7:38p Jeff - * creation of low-level forcefeedback and beginning of high-level - * forcefeedback - * - * 9 9/15/98 12:25p Jeff - * If we are in NT, then only require DX3, else require DX6 (we may need - * to change this due to NT5) - * - * 8 9/15/98 12:05p Jeff - * initial creation of low-level forcefeedback - * - * 7 6/29/98 6:43p Samir - * Took out GetMsgProc and legacy keyboard variables. - * - * 6 5/08/98 12:54p Samir - * newer unused mouse handler. - * - * 5 3/31/98 12:46p Samir - * keyboard IO system better. uses getmsgproc windows hook. - * - * 4 10/23/97 2:58p Samir - * Took out extranneous messages. - * - * 3 10/16/97 2:29p Samir - * Changed DirectInput Keyboard to FOREGROUND - * - * 2 8/01/97 7:30p Samir - * Better NT keyboard support. - * - * 10 6/11/97 1:07p Samir - * The removal of gameos and replaced with oeApplication, oeDatabase - * - * 9 5/08/97 1:56p Samir - * These functions should only be applicable to windows (no shared code) - * - * 8 3/18/97 11:14a Samir - * Use real error call when DirectInput init fails. - * - * 7 2/28/97 11:03a Samir - * Changes to reflect newer gameos interface. - * - * 6 1/30/97 6:08p Samir - * Reflects changes in gameos.h - * - * 5 1/23/97 2:23p Samir - * Preemptive flag now just affects timer. - * - * $NoKeywords: $ - */ - -// ---------------------------------------------------------------------------- -// Win32 IO System Main Library Interface -// ---------------------------------------------------------------------------- - -#include -#include - -#include -#include - -#include "pserror.h" -#include "Application.h" -#include "ddio_win.h" -#include "ddio.h" -#include "dinput.h" - -#include "forcefeedback.h" - -bool DDIO_init = 0; -dinput_data DInputData; - -// ---------------------------------------------------------------------------- -// Initialization and destruction functions -// ---------------------------------------------------------------------------- - -bool ddio_InternalInit(ddio_init_info *init_info) { - oeWin32Application *obj = (oeWin32Application *)init_info->obj; - LPDIRECTINPUT lpdi; - HRESULT dires; - - ASSERT(!DDIO_init); - - // Initialize DirectInput subsystem - mprintf(0, "DI system initializing.\n"); - - // Try to open DirectX 5.00 - dires = DirectInputCreate((HINSTANCE)obj->m_hInstance, DIRECTINPUT_VERSION, &lpdi, NULL); - - // Deal with error opening DX5 - if (dires != DI_OK) { - - // If running NT, try DirectX 3.0 - if (obj->NT()) { - - dires = DirectInputCreate((HINSTANCE)obj->m_hInstance, 0x0300, &lpdi, NULL); - if (dires != DI_OK) { - Error("Unable to DirectInput system (Requires at least DirectX 3.0 For NT) [DirectInput:%x]\n", dires); - } - } else { // Not running NT, so error out - - // Couldn't open DirectX, so print error - Error("Unable to DirectInput system (Requires at least DirectX 5.0) [DirectInput:%x]\n", dires); - } - } - - DInputData.app = obj; - DInputData.lpdi = lpdi; - DInputData.hwnd = (HWND)obj->m_hWnd; - - DDIO_init = 1; - - return 1; -} - -void ddio_InternalClose() { - ASSERT(DDIO_init); - - // //Close down forcefeedback - // ddio_ff_DetachForce(); - - DInputData.lpdi->Release(); - DInputData.lpdi = NULL; - DDIO_init = 0; - - mprintf(0, "DI system closed.\n"); -} - -#ifdef _DEBUG -void ddio_DebugMessage(unsigned err, char *fmt, ...) { - char buf[128]; - std::va_list arglist; - - va_start(arglist, fmt); - std::vsnprintf(buf, 128, fmt, arglist); - va_end(arglist); - - mprintf(0, "DDIO: %s\n", buf); - if (err) { - mprintf(1, "DIERR %x.\n", err); - } -} -#endif - -bool ddio_GetBinaryPath(char *exec_path, size_t len) { - if (GetModuleFileName(NULL, exec_path, len) == 0) { - DWORD error = GetLastError(); - Error("GetModuleFileName failed!"); - return false; - } - exec_path[len - 1] = '\0'; - return true; -} \ No newline at end of file diff --git a/ddio/winjoy.cpp b/ddio/winjoy.cpp deleted file mode 100644 index 1e16eccd3..000000000 --- a/ddio/winjoy.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddio_win/winjoy.cpp $ - * $Revision: 19 $ - * $Date: 8/10/99 5:11p $ - * $Author: Jeff $ - * - * joystick header - * - * $Log: /DescentIII/Main/ddio_win/winjoy.cpp $ - * - * 19 8/10/99 5:11p Jeff - * always call detachforce, it needs to free DLLs - * - * 18 7/30/99 1:06p Samir - * fixed hat code for direct input and apply sensitivities for calibration - * of axes. - * - * 17 7/26/99 11:59a Samir - * add code to get name of joystick - * - * 16 7/16/99 11:14a Samir - * multiple hat support and improved direct input support. - * - * 15 5/23/99 12:45a Samir - * if joystick was never found, when returning from joygetpos, set all - * position values to a neutral value. - * - * 14 5/19/99 4:38p Samir - * trying 'centered' flag for joyGetPosEx to automatically center joystick - * on midpoint of min and max values for axis. I don't know why this - * isn't the case anyway, but... - * - * 13 5/10/99 9:22p Samir - * added CH Flightstick Pro hack. - * - * 12 5/08/99 1:05a Samir - * initialize joysticks always, but return NULL values if the joystick is - * unplugged. - * - * 11 5/05/99 10:55p Samir - * moved force feedback code so it's always initialized. - * - * 10 4/24/99 8:41p Samir - * added debug code to get controller positions on mono. - * - * 9 4/12/99 12:12p Samir - * took out int3. - * - * 8 4/09/99 12:02p Samir - * joystick changes (Win32 DirectInput support) - * - * 7 2/21/99 6:38p Samir - * mouse and key input better. buffered mouse. - * - * 6 2/03/99 6:47p Jeff - * (Samir) hacked pov value, so it's always a word - * - * 5 10/18/98 7:25p Samir - * made joy_GetPos safe. - * - * 4 6/02/98 4:37p Samir - * multiple joysticks supported. - * - * 3 6/01/98 4:27p Samir - * pov may return multiple positions. - * - * 2 12/03/97 7:33p Samir - * Improved joystick interface. - * - * 4 6/11/97 2:40p Samir - * fixed bools. - * - * 3 2/26/97 6:16p Samir - * joy_init returns a 0 if no joysticks are present. - * - * 2 2/26/97 12:09p Samir - * Added some debug and error checking. - * - * $NoKeywords: $ - */ - -#include "joystick.h" -#include "forcefeedback.h" -#include "pserror.h" -#include "pstypes.h" -#include "mem.h" -#include "ddio_win.h" -#include "Macros.h" -#include "logfile.h" - -#include -#include -#include -#include -#include - -#define loword(_v) ((_v) & 0x0000ffff) - -////////////////////////////////////////////////////////////////////////////// -struct tJoystickRecord { - uint8_t valid; // is this a valid device. - uint8_t flags; // defined in ddio_win.h - int16_t spad; - - union { - int joyid; - tDevice ffdev; - } joy_context; // used to identify the joystick. - - tJoyInfo caps; // controller capabilities - tJoyPos pos; // current position -}; - -////////////////////////////////////////////////////////////////////////////// -static struct tJoystickLibraryData { - int16_t init; // library initialized? - int16_t njoy; // maximum number of joysticks supported. - tJoystickRecord *joystick; // list of joysticks. - - LPDIRECTINPUT lpdi; // if lpdi != NULL, we use direct input for joysticks -} WJD = {0, 0, NULL, NULL}; - -////////////////////////////////////////////////////////////////////////////// - -bool joyw_get_name(int id, char *buf, const char *regkey); - -bool joymm_init(); -void joymm_close(); -tJoystick joymm_init_stick(int joyid); -void joymm_close_stick(tJoystick handle); -void joymm_get_pos(tJoystick handle, tJoyPos *pos); - -tJoystick joydi_init_stick(int ffjoyid); -void joydi_get_pos(tJoystick handle, tJoyPos *pos); - -// joystick forcefeedback shares -extern LPDIRECTINPUTDEVICE2 ddio_ff_get_joystick_obj(tDevice dev); - -bool joy_chpro_hack = false; // flightstick pro hack for Win32 only - -////////////////////////////////////////////////////////////////////////////// -// initializes joystick interface. - -bool joy_Init(bool emulation) { - // Can we initialize DirectInput version? - // Try to init forcefeedback (which initializes joysticks) - uint32_t i, n; // = joyGetNumDevs(); - - ddio_ff_AttachForce(); - - // initializes forcefeedback system? - if (ddio_ff_Init()) { - mprintf(0, "DDForce: Force Feedback Joystick Found\n"); - } - - // initialize data structures. - n = 2; - if (n) { - WJD.joystick = (tJoystickRecord *)mem_malloc(sizeof(tJoystickRecord) * n); - for (i = 0; i < n; i++) { - WJD.joystick[i].valid = 0; - } - } else { - WJD.init = 0; - return false; - } - WJD.njoy = n; - - // attempt directinput initialization. - n = (!emulation) ? ddio_ffjoy_Init() : 0; - - if (n > 0) { - WJD.lpdi = DInputData.lpdi; - - // map all ffjoysticks to our joystick structure. - for (i = 0; i < n; i++) { - joydi_init_stick(i); - } - - } - // enumerate all windows joysticks (1 and 2 only) - else if (joymm_init()) { - WJD.lpdi = NULL; - } else { - WJD.init = 0; - return false; - } - - WJD.init = 1; - - return true; -} - -void joy_Close() { - ddio_ff_DetachForce(); - - if (!WJD.init) - return; - - if (!WJD.lpdi) { - joymm_close(); - } - - mem_free(WJD.joystick); - WJD.joystick = NULL; - WJD.njoy = 0; - WJD.lpdi = NULL; - WJD.init = 0; -} - -// returns true if joystick valid -bool joy_IsValid(tJoystick handle) { - if (!WJD.init) - return false; - if (handle < 0 || handle >= WJD.njoy) - return false; - - return WJD.joystick[handle].valid ? true : false; -} - -// retreive uncalibrated position of joystick -void joy_GetRawPos(tJoystick joy, tJoyPos *pos) { - joy_GetPos(joy, pos); - pos->x = (pos->x + 128) * JOYAXIS_RANGE; - pos->y = (pos->y + 128) * JOYAXIS_RANGE; - pos->z = (pos->z + 128) * JOYAXIS_RANGE; - pos->r = (pos->r + 128) * JOYAXIS_RANGE; - pos->u = (pos->u + 128) * JOYAXIS_RANGE; - pos->v = (pos->v + 128) * JOYAXIS_RANGE; -} - -// returns the state of a stick, remote or otherwise -void joy_GetPos(tJoystick stick, tJoyPos *pos) { - ASSERT(stick >= 0 || stick < WJD.njoy); - int i; - - for (i = 0; i < JOYPOV_NUM; i++) { - pos->pov[i] = JOYPOV_CENTER; - } - - if (stick < 0 || stick >= WJD.njoy) { - memset(pos, 0, sizeof(tJoyPos)); - return; - } - if (!WJD.joystick[stick].valid) { - memset(pos, 0, sizeof(tJoyPos)); - return; - } - - if (WJD.lpdi) { - joydi_get_pos(stick, pos); - } else { - joymm_get_pos(stick, pos); - } -} - -// retreive information about joystick. -void joy_GetJoyInfo(tJoystick joy, tJoyInfo *info) { - tJoyInfo *srcinfo; - ASSERT(joy >= 0 || joy < WJD.njoy); - - if (!WJD.init) - return; - if (!WJD.joystick[joy].valid) - return; - srcinfo = &WJD.joystick[joy].caps; - - memcpy(info, srcinfo, sizeof(tJoyInfo)); -} - -// hook into ddio system if joystick needs any additonal processing per frame. -void ddio_InternalJoyFrame() { - if (!WJD.init) - return; - - if (WJD.lpdi) { - int i; - tJoystickRecord *joystick = &WJD.joystick[0]; - for (i = 0; i < WJD.njoy; i++) { - int try_count = 0; - - if (joystick->valid) { - LPDIRECTINPUTDEVICE2 lpdidev = ddio_ff_get_joystick_obj(joystick->joy_context.ffdev); - - retry_joy_poll: - HRESULT hr = lpdidev->Poll(); - if (hr == DIERR_INPUTLOST && try_count < 2) { - ddio_ff_Acquire(joystick->joy_context.ffdev); - try_count++; - goto retry_joy_poll; - } - } - joystick++; - } - } -} - -////////////////////////////////////////////////////////////////////////////// -// initializes multimedia version of joystick interface. -bool joymm_init() { - joymm_init_stick(JOYSTICKID1); - if (!joy_chpro_hack) { - joymm_init_stick(JOYSTICKID2); - } - - return true; -} - -// frees joystick library. -void joymm_close() { - int i; - for (i = 0; i < WJD.njoy; i++) { - if (WJD.joystick[i].valid) { - joymm_close_stick(WJD.joystick[i].joy_context.joyid); - } - } -} - -// initializes one stick. -tJoystick joymm_init_stick(int joyid) { - int i; - - // find free joystick slot - for (i = 0; i < WJD.njoy; i++) { - if (!WJD.joystick[i].valid) { - // found slot, lets initialize it and return. - JOYCAPS jc; - - if (joyGetDevCaps(joyid, &jc, sizeof(jc)) == JOYERR_NOERROR) { - tJoyInfo *caps = &WJD.joystick[i].caps; - - WJD.joystick[i].valid = 1; - WJD.joystick[i].joy_context.joyid = joyid; - - memset(caps, 0, sizeof(tJoyInfo)); - caps->axes_mask = - ((jc.wCaps & JOYCAPS_HASR) ? JOYFLAG_RVALID : 0) | ((jc.wCaps & JOYCAPS_HASZ) ? JOYFLAG_ZVALID : 0) | - ((jc.wCaps & JOYCAPS_HASU) ? JOYFLAG_UVALID : 0) | ((jc.wCaps & JOYCAPS_HASV) ? JOYFLAG_VVALID : 0) | - ((jc.wCaps & JOYCAPS_HASPOV) ? JOYFLAG_POVVALID : 0) | (JOYFLAG_XVALID + JOYFLAG_YVALID); - caps->num_btns = (joy_chpro_hack) ? 32 : jc.wNumButtons; - caps->minx = jc.wXmin; - caps->miny = jc.wYmin; - caps->minz = jc.wZmin; - caps->minr = jc.wRmin; - caps->minu = jc.wUmin; - caps->minv = jc.wVmin; - caps->maxx = jc.wXmax; - caps->maxy = jc.wYmax; - caps->maxz = jc.wZmax; - caps->maxr = jc.wRmax; - caps->maxu = jc.wUmax; - caps->maxv = jc.wVmax; - - if (!joyw_get_name(joyid, caps->name, jc.szRegKey)) { - sprintf(caps->name, "Joystick-%d", i); - } - - return (tJoystick)(i); - } else { - return (tJoystick)(-1); - } - } - } - - return -1; -} - -void joymm_close_stick(tJoystick handle) { - if (handle < 0 || handle >= WJD.njoy) - return; - - WJD.joystick[handle].valid = 0; -} - -void joymm_get_pos(tJoystick handle, tJoyPos *pos) { - JOYINFOEX ji; - tJoyInfo *caps; - - if (handle < 0 || handle >= WJD.njoy) { - return; - } - if (!WJD.joystick[handle].valid) { - return; - } - - caps = &WJD.joystick[handle].caps; - - ZeroMemory(&ji, sizeof(JOYINFOEX)); - - ji.dwSize = sizeof(JOYINFOEX); - ji.dwFlags = JOY_RETURNCENTERED | JOY_USEDEADZONE | JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | - JOY_RETURNU | JOY_RETURNV | JOY_RETURNPOV | JOY_RETURNBUTTONS; - - if (joyGetPosEx(WJD.joystick[handle].joy_context.joyid, &ji) != JOYERR_NOERROR) { - memset(pos, 0, sizeof(tJoyPos)); - pos->pov[0] = JOYPOV_CENTER; - return; - } - - pos->x = (int)((ji.dwXpos << 8) / (caps->maxx - caps->minx)) - 128; - pos->y = (int)((ji.dwYpos << 8) / (caps->maxy - caps->miny)) - 128; - - if (caps->axes_mask & JOYFLAG_ZVALID) { - pos->z = (int)((ji.dwZpos << 8) / (caps->maxz - caps->minz)) - 128; - } else { - pos->z = 0; - } - if (caps->axes_mask & JOYFLAG_RVALID) { - pos->r = (int)((ji.dwRpos << 8) / (caps->maxr - caps->minr)) - 128; - } else { - pos->r = 0; - } - if (caps->axes_mask & JOYFLAG_UVALID) { - pos->u = (int)((ji.dwUpos << 8) / (caps->maxu - caps->minu)) - 128; - } else { - pos->u = 0; - } - if (caps->axes_mask & JOYFLAG_VVALID) { - pos->v = (int)((ji.dwVpos << 8) / (caps->maxv - caps->minv)) - 128; - } else { - pos->v = 0; - } - - if (caps->axes_mask & JOYFLAG_POVVALID) { - ji.dwPOV = ji.dwPOV & 0x0000ffff; - if (ji.dwPOV == JOY_POVCENTERED) - pos->pov[0] = JOYPOV_CENTER; - else - pos->pov[0] = (unsigned)(ji.dwPOV * JOYPOV_MAXVAL / 35900.0f); - } else { - pos->pov[0] = JOYPOV_CENTER; - } - - pos->buttons = 0; - if (joy_chpro_hack) { - if (ji.dwButtons > 0 && ji.dwButtons <= 32) { - pos->buttons = 1 << (ji.dwButtons - 1); - mprintf(0, "btns=%x\n", pos->buttons); - } - } else { - pos->buttons = (unsigned)ji.dwButtons; - } - - pos->btn = (unsigned)ji.dwButtonNumber; - -#ifdef _DEBUG - mprintf_at(4, handle + 1, 0, "%d:X:%04d Y:%04d Z:%04d %d:R:%04d U:%04d V:%04d", handle, pos->x, pos->y, pos->z, - pos->r, pos->u, pos->v, pos->buttons); -#endif -} - -void joydi_get_pos(tJoystick handle, tJoyPos *pos) { - tJoyInfo *caps; - tJoystickRecord *joystick; - LPDIRECTINPUTDEVICE2 lpdidev2; - DIJOYSTATE ji; - HRESULT hr; - int try_count = 0; - unsigned i; - - if (handle < 0 || handle >= WJD.njoy) - return; - if (!WJD.joystick[handle].valid) - return; - - joystick = &WJD.joystick[handle]; - caps = &joystick->caps; - lpdidev2 = ddio_ff_get_joystick_obj(joystick->joy_context.ffdev); - - if (!lpdidev2) { - return; - } - -retry_joy_input: - hr = lpdidev2->GetDeviceState(sizeof(ji), &ji); - if (hr == DIERR_NOTACQUIRED && try_count < 4) { - ddio_ff_Acquire(joystick->joy_context.ffdev); - try_count++; - goto retry_joy_input; - } else if (hr != DI_OK) { - memset(pos, 0, sizeof(pos)); - pos->pov[0] = JOYPOV_CENTER; - } - - // interpret data. - if (caps->axes_mask & JOYFLAG_XVALID) { - pos->x = (int)((ji.lX << 8) / (caps->maxx - caps->minx)) - 128; - } else { - pos->x = 0; - } - if (caps->axes_mask & JOYFLAG_YVALID) { - pos->y = (int)((ji.lY << 8) / (caps->maxy - caps->miny)) - 128; - } else { - pos->y = 0; - } - if (caps->axes_mask & JOYFLAG_ZVALID) { - pos->z = (int)((ji.lZ << 8) / (caps->maxz - caps->minz)) - 128; - } else { - pos->z = 0; - } - if (caps->axes_mask & JOYFLAG_RVALID) { - pos->r = (int)((ji.lRz << 8) / (caps->maxr - caps->minr)) - 128; - } else { - pos->r = 0; - } - if (caps->axes_mask & JOYFLAG_UVALID) { - pos->u = (int)((ji.rglSlider[0] << 8) / (caps->maxu - caps->minu)) - 128; - } else { - pos->u = 0; - } - if (caps->axes_mask & JOYFLAG_VVALID) { - pos->v = (int)((ji.rglSlider[1] << 8) / (caps->maxv - caps->minv)) - 128; - } else { - pos->v = 0; - } - - for (i = 0; i < 4; i++) { - if (caps->axes_mask & (JOYFLAG_POVVALID << i)) { - if (loword(ji.rgdwPOV[i]) == 0xffff) { - pos->pov[i] = JOYPOV_CENTER; - } else { - int index = (ji.rgdwPOV[i] / 4500); - pos->pov[i] = index * 0x20; - //@@ switch (index) - //@@ { - //@@ case 0: pos->pov = JOYPOV_UP; break; - //@@ case 1: pos->pov = JOYPOV_RIGHT; break; - //@@ case 2: pos->pov = JOYPOV_DOWN; break; - //@@ case 3: pos->pov = JOYPOV_LEFT; break; - //@@ default: pos->pov = JOYPOV_CENTER; - //@@ } - } - } else { - pos->pov[i] = JOYPOV_CENTER; - } - } - - pos->buttons = 0; - for (i = 0; i < caps->num_btns; i++) { - if (ji.rgbButtons[i] & 0x80) { - pos->buttons |= (1 << i); - pos->btn = i; - } - } - -#ifdef _DEBUG - mprintf_at(4, (handle * 2) + 1, 0, "J%d:X:%04d Y:%04d Z:%04d Rz:%04d S0:%04d S1:%04d", handle, pos->x, pos->y, - pos->z, pos->r, pos->u, pos->v); - mprintf_at(4, (handle * 2) + 2, 0, " POV0:%04d POV1:%04d POV2:%04d POV3:%04d", handle, pos->pov[0], pos->pov[1], - pos->pov[2], pos->pov[3]); -#endif -} - -// direct input implementation. -tJoystick joydi_init_stick(int ffjoyid) { - LPDIRECTINPUTDEVICE2 lpdidev2; - - lpdidev2 = ddio_ff_get_joystick_obj((tDevice)ffjoyid); - if (lpdidev2) { - // find free joystick slot - int i; - - for (i = 0; i < WJD.njoy; i++) { - if (!WJD.joystick[i].valid) { - // found slot, lets initialize it and return. - // get axis, and each of their ranges - DIDEVICEOBJECTINSTANCE DIObjInst; - DIDEVICEINSTANCE DIDevInst; - DIPROPRANGE dirange; - DIDEVCAPS dicaps; - tDevice dev = (tDevice)ffjoyid; - tJoyInfo *caps = &WJD.joystick[i].caps; - - memset(caps, 0, sizeof(tJoyInfo)); - - WJD.joystick[i].joy_context.ffdev = dev; - WJD.joystick[i].valid = 1; - - // get device info - DIDevInst.dwSize = sizeof(DIDEVICEINSTANCE); - if (lpdidev2->GetDeviceInfo(&DIDevInst) == DI_OK) { - strcpy(WJD.joystick[i].caps.name, DIDevInst.tszProductName); - } else { - sprintf(WJD.joystick[i].caps.name, "Joystick-%d", i); - } - - // get device object info - ddio_ff_Acquire(dev); - dicaps.dwSize = sizeof(DIDEVCAPS); - - if (lpdidev2->GetCapabilities(&dicaps) != DI_OK) { - mprintf(0, "ddio_ffjoy_Query: Failed getting device caps\n"); - return -1; - } - - DIObjInst.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); - - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_X, DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_XVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_Y, DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_YVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_Z, DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_ZVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_RZ, DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_RVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_SLIDER(0), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_UVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_SLIDER(1), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_VVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_POV(0), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_POVVALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_POV(1), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_POV2VALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_POV(2), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_POV3VALID; - } - if (lpdidev2->GetObjectInfo(&DIObjInst, DIJOFS_POV(3), DIPH_BYOFFSET) == DI_OK) { - caps->axes_mask |= JOYFLAG_POV4VALID; - } - - caps->num_btns = dicaps.dwButtons; - - dirange.diph.dwSize = sizeof(DIPROPRANGE); - dirange.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dirange.diph.dwHow = DIPH_BYOFFSET; - - dirange.diph.dwObj = DIJOFS_X; - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->minx = (int)dirange.lMin; - caps->maxx = (int)dirange.lMax; - } - dirange.diph.dwObj = DIJOFS_Y; - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->miny = (int)dirange.lMin; - caps->maxy = (int)dirange.lMax; - } - dirange.diph.dwObj = DIJOFS_Z; - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->minz = (int)dirange.lMin; - caps->maxz = (int)dirange.lMax; - } - dirange.diph.dwObj = DIJOFS_RZ; - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->minr = (int)dirange.lMin; - caps->maxr = (int)dirange.lMax; - } - dirange.diph.dwObj = DIJOFS_SLIDER(0); - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->minu = (int)dirange.lMin; - caps->maxu = (int)dirange.lMax; - } - dirange.diph.dwObj = DIJOFS_SLIDER(1); - if (lpdidev2->GetProperty(DIPROP_RANGE, (DIPROPHEADER *)&dirange) == DI_OK) { - caps->minv = (int)dirange.lMin; - caps->maxv = (int)dirange.lMax; - } - - lpdidev2->Poll(); - - return (tJoystick)(i); - } else { - return (tJoystick)(-1); - } - } - } - - Int3(); - return -1; -} - -// JAS: Taken from Nov 1996 Game Developer, page 49. -// Damn, that is some UGLY code! (But it works...) -/*---------------------------------------------------------------------*/ -bool joyw_get_name(int joy_num, char *szReturnName, const char *szRegKey) -/* - Description : Opens the MediaResources\Joysitick\mjstick.drv\JoystickSettings and - extracts Joystick%dOEMName string - Arguments : joy_num (r/o) - Joystick Number - szRegKey (r/o) - Registry Key of the msjstick.drv - ReturnName (r/w) - Return String for name listed in Control Panel - Returns : 0 for success 1 for failure -/*-----------------------------------------------------------------------*/ -{ - BYTE KeyStr[_MAX_PATH] = REGSTR_PATH_JOYCONFIG; // found in regstr.h - BYTE KeyJoySetStr[_MAX_PATH] = REGSTR_KEY_JOYSETTINGS; // found in Regstr.h - BYTE szOEMName[_MAX_PATH]; // OEM name from Current Settings - HKEY ConfigKey; - HKEY JoyConfigKey; // Joystick Configuration - HKEY DriverKey; // Joystick Driver Key - HKEY OEMPropKey; - HKEY PropKey; - DWORD Length; - if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG, &ConfigKey)) - - { - return (false); // It should never get here key received from Caps - } - - if (ERROR_SUCCESS != RegOpenKey(ConfigKey, szRegKey, &DriverKey)) { - return (false); // It should never get here key received from Caps - } - // Open CurrentSettings Key - - if (ERROR_SUCCESS != RegOpenKey(DriverKey, REGSTR_KEY_JOYCURR, &JoyConfigKey)) { - return (false); // It should never get here always a Current Settings - } - sprintf((char *)KeyStr, (char *)REGSTR_VAL_JOYNOEMNAME, joy_num + 1); - Length = sizeof(szOEMName); // Get OEMNAME Configuration - - if (ERROR_SUCCESS != - RegQueryValueEx(JoyConfigKey, (char *)KeyStr, NULL, NULL, (uint8_t *)&szOEMName, &Length)) { - return (false); // No OEM name listed return error - } - RegCloseKey(ConfigKey); // Closes the registry Key - - // Open OEM Properties Key - if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYOEM, &PropKey)) { - return (false); // It should never get here key received from Caps - } - - if (ERROR_SUCCESS != RegOpenKey(PropKey, (char *)szOEMName, &OEMPropKey)) { - return (false); // It should never get here if device is selected - } - Length = _MAX_PATH; // Get Name as listed in Control Panel - - if (ERROR_SUCCESS != - RegQueryValueEx(OEMPropKey, REGSTR_VAL_JOYOEMNAME, NULL, NULL, (uint8_t *)szReturnName, &Length)) { - return (false); // No OEM name listed return error - } - RegCloseKey(OEMPropKey); // Closes the registry Key - return true; - -} /* End GetJoystickName */ diff --git a/ddio/winkey.cpp b/ddio/winkey.cpp deleted file mode 100644 index 77ffa3dd9..000000000 --- a/ddio/winkey.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/ddio_win/winkey.cpp $ - * $Revision: 36 $ - * $Date: 4/24/99 5:41p $ - * $Author: Samir $ - * - * Keyboard IO with DirectInput 3.0 - * - * $Log: /DescentIII/Main/ddio_win/winkey.cpp $ - * - * 36 4/24/99 5:41p Samir - * moved key to ascii, ascii to key to the ddio_common library. - * - * 35 4/22/99 2:02a Jeff - * pass ddio_init_info through to keyboard handlers - * - * 34 3/05/99 3:27p Samir - * screenshot key works properly now. - * - * 33 3/02/99 2:01p Samir - * some small directinput changes. (note, for D3, we're now using emulated - * key input because of the silly pause and numlock issue which for some - * reason fails to work properly under DirectInput. - * - * 32 3/01/99 12:39a Samir - * key ups only occur when key was initially down. because of this, - * ddio_KeyFlush cleared the down events, but if the user released after - * flush, the up event would leak through and cause the illusion of key - * presses leaking through. HOPEFULLY this doesn't break anything else, - * but I played through the game a bit and it seems to work fine. - * - * 31 2/25/99 10:43p Matt - * Took out mprintf() - * - * 30 2/21/99 6:38p Samir - * mouse and key input better. buffered mouse. - * - * 29 2/05/99 1:16p Samir - * reset low level keys when flushing keyboard in the high level. added a - * function to the low level to reset the status of a key, called from - * high level key flush. - * - * 28 2/04/99 12:31p Samir - * use our timer for key capture if we're using the hook method. - * - * 27 1/28/99 6:22p Samir - * may fix thread issues. - * - * 26 1/25/99 7:27p Samir - * fixed timing issues with emulated keyboard key down times. (Win32 sends - * multiple keydown messages, so ignore them.) - * - * 25 1/25/99 6:47p Samir - * allow slow keyboard - * - * 24 1/25/99 11:02a Samir - * revamped mouse and key controls. - * - * 23 10/22/98 11:06a Samir - * added numeric keypad ascii translations. - * - * 22 10/21/98 12:02p Samir - * properly update odd keys when they are released throug - * ddio_KeyGetDownTime. - * - * 21 10/16/98 12:15p Samir - * took out ddio_KeyFrame - * - * 20 10/15/98 6:48p Samir - * added timer hooks. - * - * 19 9/17/98 12:50p Samir - * language. - * - * 18 6/29/98 6:43p Samir - * Took out GetMsgProc and legacy keyboard variables. - * - * 17 4/09/98 6:56p Samir - * PRINTSCREEN MUST WORK. - * - * 16 4/08/98 8:40p Samir - * Screen shots work with print screen by checking VK code. - * - * 15 3/31/98 12:46p Samir - * keyboard IO system better. uses getmsgproc windows hook. - * - * 14 3/24/98 11:21a Samir - * redid key handler. - * - * 13 2/25/98 6:11p Samir - * Added functions to better deal with key flushing. - * - * 12 1/21/98 6:46p Samir - * NT and 95 should have same keyboard behavior for framed handlers. - * - * 11 1/02/98 12:52p Samir - * Added ascii->keycode translation tables - * - * 10 12/10/97 1:12p Samir - * Use timestamp from DirectInput Key calls. - * - * 9 11/07/97 6:17p Samir - * Rollbacked some more efficient code since it slowed down some machines - * in the editor. Sleep thread until closed a little faster. - * - * 8 10/23/97 2:59p Samir - * Keyboard thread uses C runtime lib functions, and definitely ends. - * - * 7 10/22/97 4:37p Samir - * Thread doesn't end if thread is still blocking, I think. - * - * 6 10/17/97 5:03p Samir - * Default to preemptive keyboard handler (not under NT). - * - * 5 10/16/97 5:35p Samir - * Use different cooperative level for Win95 vs. NT. - * - * 4 10/16/97 2:29p Samir - * Changed DirectInput Keyboard to FOREGROUND - * - * 3 8/01/97 8:14p Samir - * Fixed keyboard handler for NT to work with extended keys. - * - * 2 8/01/97 7:30p Samir - * Better NT keyboard support. - * - * 14 5/23/97 4:09p Samir - * Keyboard thread uses new task system. - * - * 13 5/09/97 6:45p Samir - * Took out shared keyboard code from handler to ddio_common - * - * 12 5/08/97 1:56p Samir - * Moved a bunch of keyboard code to ddio_common library. - * - * 11 3/20/97 11:08a Samir - * Added function to peek for keys in queue without removing them. - * - * 10 3/13/97 3:02p Samir - * Hopefully fixed keyboard thread problem. - * - * 9 2/20/97 9:58a Matt - * Took out Int3() for directinput key buffer overflow, which would get - * hit if you switched to another task, typed a bunch, and switched back - * into the editor - * - * 8 1/23/97 2:22p Samir - * Keyboard thread now blocks properly, and added functionality for - * nonpreemptive keyboard polling. - * - * 7 1/20/97 3:46p Samir - * RCS header check in - * - * $NoKeywords: $ - */ - -// ---------------------------------------------------------------------------- -// Keyboard Interface -// ---------------------------------------------------------------------------- - -#include "pserror.h" -#include "mono.h" -#include "ddio.h" -#include "ddio_win.h" -#include "Application.h" -#include "TaskSystem.h" - -#include -#include - -// ---------------------------------------------------------------------------- -// Local global data -// ---------------------------------------------------------------------------- -#define DIKEY_BUFFER_SIZE 32 - -static struct tWinKeyData { - LPDIRECTINPUTDEVICE lpdikey; // key device - HANDLE evtnotify; // notify event - HHOOK winhook; // windows hook - uintptr_t thread; // thread id - //osMutex keyframe_mutex; // mutex between - // internal key frame and key thread. - bool nextframe; // used for mutexing between keyframe and thread. - bool acquired; // device acquired? - bool thread_active; // used in thread. - bool suspended; -} WKD = {NULL, NULL, NULL, 0xffffffff, false, false, false, true}; - -volatile struct tWinKeys { - union { - DWORD up_ticks; // windows ticks when key went up last - float up_time; - }; - union { - DWORD down_ticks; // windows ticks when key went down last - float down_time; - }; - bool status; // is it down? - bool mutex_flag; // done for mutexing between ddio_Internal and KeyThread - uint16_t mutex_data; -} WKeys[DDIO_MAX_KEYS]; - -static int DDIO_key_language = KBLANG_AMERICAN; - -/////////////////////////////////////////////////////////////////////////////// -// Initializes DirectInputDevice keyboard if we are under Win9x or at least NT5 -// we set the cooperative level, etc. -LPDIRECTINPUTDEVICE dikey_Init(LPDIRECTINPUT lpdi, HWND hwnd); - -// Shutsdown DirectInputDevice keyboard if passed device is valid. -void dikey_Shutdown(LPDIRECTINPUTDEVICE lpdikey); - -// sets up preemptive keyboard handling. -HANDLE dikey_EnableNotify(LPDIRECTINPUTDEVICE lpdikey); - -// disables event based notification. -bool dikey_DisableNotify(LPDIRECTINPUTDEVICE lpdikey, HANDLE evthandle); - -// acquires or unacquires device -// returns device acquisition state. -bool dikey_Acquire(LPDIRECTINPUTDEVICE lpdikey, bool acquire); - -// emulated keyboard functionality -bool ddio_Win_KeyInit(); -void ddio_Win_KeyClose(); - -int ddio_KeyHandler(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); - -LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam); - -// DirectInput Keyboard Thread -void __cdecl dikey_Thread(void *dp); - -// translates scan code to foreign equivs. -uint8_t xlate_scancode(uint8_t scan_code); - -/////////////////////////////////////////////////////////////////////////////// - -// ---------------------------------------------------------------------------- -// Initialization of keyboard device. -// ---------------------------------------------------------------------------- - -// this version will try to initialize a direct input keyboard device. if it fails -// it falls back to the old keyboard hook (less reliable but works.) -bool ddio_InternalKeyInit(ddio_init_info *init_info) { - bool emulated = init_info->key_emulation; - - LPDIRECTINPUTDEVICE lpdikey = NULL; - int i; - - // reset key list - for (i = 0; i < DDIO_MAX_KEYS; i++) { - WKeys[i].down_ticks = 0; - WKeys[i].up_ticks = 0; - WKeys[i].status = false; - } - - // start init. - if (!emulated) { - lpdikey = dikey_Init(DInputData.lpdi, (HWND)DInputData.app->m_hWnd); - } - -retry_key_init: - if (lpdikey) { - // direct input keyboard can work, so we initialize preemptive handling of the keyboard - HANDLE hevt = dikey_EnableNotify(lpdikey); - - if (hevt) { - // event handling will work, so let's create the keyboard thread. - bool acquired = dikey_Acquire(lpdikey, true); - if (acquired) { - // create keyboard thread - WKD.thread_active = true; - WKD.lpdikey = lpdikey; - WKD.thread = 0; - WKD.evtnotify = hevt; - WKD.acquired = acquired; - WKD.winhook = NULL; - WKD.suspended = false; - WKD.nextframe = false; - uintptr_t thrid = _beginthread(dikey_Thread, 0, nullptr); - if (thrid == -1) { - mprintf(0, "DDIO: DI_Keyboard thread failed to initialize.\n"); - WKD.thread_active = false; - WKD.lpdikey = NULL; - WKD.thread = 0xffffffff; - WKD.evtnotify = NULL; - WKD.acquired = false; - WKD.winhook = NULL; - WKD.suspended = false; - acquired = dikey_Acquire(lpdikey, false); - dikey_DisableNotify(lpdikey, hevt); - dikey_Shutdown(lpdikey); - lpdikey = NULL; - } else { - // success! init data. - // set priority of thread too. - WKD.thread = thrid; - if (SetThreadPriority((HANDLE)thrid, THREAD_PRIORITY_TIME_CRITICAL) == FALSE) { - SetThreadPriority((HANDLE)thrid, THREAD_PRIORITY_HIGHEST); - } - mprintf(0, "DDIO: DI_Keyboard initialized.\n"); - } - } else { - // failed to acquire device? can't do. - dikey_DisableNotify(lpdikey, hevt); - dikey_Shutdown(lpdikey); - lpdikey = NULL; - } - } else { - // somehow event notification failed, can't do. - dikey_Shutdown(lpdikey); - lpdikey = NULL; - } - - if (lpdikey == NULL) { - goto retry_key_init; - } - } else { - // here, initialize hook procedure. - return ddio_Win_KeyInit(); - } - - return true; -} - -// this will shutdown direct input or the windows hook, whichever was chosen. -void ddio_InternalKeyClose() { - if (WKD.lpdikey) { - // deactivate thread and free it, then unacquire device, disable event notification, and shutdown! - WKD.thread_active = false; - SetEvent(WKD.evtnotify); - Sleep(500); - WKD.acquired = dikey_Acquire(WKD.lpdikey, false); - dikey_DisableNotify(WKD.lpdikey, WKD.evtnotify); - dikey_Shutdown(WKD.lpdikey); - WKD.thread = 0xffffffff; - WKD.evtnotify = NULL; - WKD.lpdikey = NULL; - mprintf(0, "DDIO: DI_Keyboard shutdown.\n"); - } - if (WKD.winhook) { - ddio_Win_KeyClose(); - } -} - -// handled internally if keyboard system needs additional processing per frame -void ddio_InternalKeyFrame() {} - -////////////////////////////////////////////////////////////////////////////// -// Miscellaneous API -////////////////////////////////////////////////////////////////////////////// - -// returns if key is up or down -bool ddio_InternalKeyState(uint8_t key) { return WKeys[key].status; } - -float ddio_InternalKeyDownTime(uint8_t key) { - float down_time = 0.0f; - if (WKeys[key].status) { - if (WKD.winhook) { - float timer = timer_GetTime(); - down_time = timer - WKeys[key].down_time; - WKeys[key].down_time = timer; - } else { - DWORD curtickcount = GetTickCount(); - DWORD ticks = curtickcount - WKeys[key].down_ticks; - if (ticks == 0) { - // mprintf(0, "ticks=%d\n", ticks); - } - WKeys[key].down_ticks = curtickcount; - down_time = (ticks / 1000.0f); - } - } else { - if (WKD.winhook) { - down_time = WKeys[key].up_time - WKeys[key].down_time; - WKeys[key].down_time = WKeys[key].up_time = 0.0f; - } else { - DWORD ticks = WKeys[key].up_ticks - WKeys[key].down_ticks; - WKeys[key].down_ticks = 0; - WKeys[key].up_ticks = 0; - down_time = (ticks / 1000.0f); - } - } - - return down_time; -} - -// flush a key internally -void ddio_InternalResetKey(uint8_t key) { - WKeys[key].down_ticks = 0; - WKeys[key].up_ticks = 0; - WKeys[key].status = false; - WKeys[key].mutex_flag = false; - WKeys[key].mutex_data = 0; -} - -// sets type of keyboard to emulate -// #define KBLANG_AMERICAN 0 -// #define KBLANG_BRITISH 1 -// #define KBLANG_FRENCH 2 -// #define KBLANG_GERMAN 3 - -void ddio_SetKeyboardLanguage(int language) { DDIO_key_language = language; } - -// translates scan code to foreign equivs. -uint8_t xlate_scancode(uint8_t scan_code) { - uint8_t code = scan_code; - - if (DDIO_key_language == KBLANG_FRENCH) { - switch (scan_code) { - case KEY_A: - code = KEY_Q; - break; - case KEY_M: - code = KEY_COMMA; - break; - case KEY_Q: - code = KEY_A; - break; - case KEY_W: - code = KEY_Z; - break; - case KEY_Z: - code = KEY_W; - break; - case KEY_SEMICOL: - code = KEY_M; - break; - case KEY_COMMA: - code = KEY_SEMICOL; - break; - } - } else if (DDIO_key_language == KBLANG_GERMAN) { - switch (scan_code) { - case KEY_Y: - code = KEY_Z; - break; - case KEY_Z: - code = KEY_Y; - break; - } - } else if (DDIO_key_language == KBLANG_BRITISH) { - if (scan_code == KEY_BSLASH_UK) { // KEY_SLASH_UK == 0x56 - code = KEY_SLASH; // KEY_SLASH is really the backslash, 0x2B - } - } - - return code; -} - -////////////////////////////////////////////////////////////////////////////// -// DirectInput Functions -////////////////////////////////////////////////////////////////////////////// - -inline bool IS_NT4_OR_LOWER() { - int maj, min; - tWin32OS os = oeWin32Application::version(&maj, &min); - return (os == WinNT && maj < 5) ? true : false; -} - -// Initializes DirectInputDevice keyboard if we are under Win9x or at least NT5 -// we set the cooperative level, etc. -LPDIRECTINPUTDEVICE dikey_Init(LPDIRECTINPUT lpdi, HWND hwnd) { - LPDIRECTINPUTDEVICE lpdikey; - HRESULT hr; - - if (IS_NT4_OR_LOWER()) { - return NULL; - } - - // see if we can get the keyboard device. - hr = lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL); - if (hr != DI_OK) { - DDIO_MESSAGE((hr, "DI_Keyboard initialization failed.")); - return NULL; - } - - hr = lpdikey->SetDataFormat(&c_dfDIKeyboard); - if (hr != DI_OK) { - DDIO_MESSAGE((hr, "DI_Keyboard data format specification failed.")); - lpdikey->Release(); - return NULL; - } - - hr = lpdikey->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - if (hr != DI_OK) { - DDIO_MESSAGE((hr, "DI_Keyboard set cooperative level failed.")); - lpdikey->Release(); - return NULL; - } - - return lpdikey; -} - -// Shutsdown DirectInputDevice keyboard if passed device is valid. -void dikey_Shutdown(LPDIRECTINPUTDEVICE lpdikey) { - if (lpdikey) { - lpdikey->Release(); - } -} - -// sets up preemptive keyboard handling. -HANDLE dikey_EnableNotify(LPDIRECTINPUTDEVICE lpdikey) { - if (lpdikey) { - HANDLE hEvt = CreateEvent(NULL, TRUE, FALSE, "DDIOKeyEvent"); - HRESULT hr; - DIPROPDWORD dipropdw = { - { - sizeof(DIPROPDWORD), - sizeof(DIPROPHEADER), - 0, - DIPH_DEVICE, - }, - DIKEY_BUFFER_SIZE, - }; - - if (!hEvt) { - DDIO_MESSAGE((0, "DI_Keyboard failed to init system event.")); - return NULL; - } - - // set event - hr = lpdikey->SetEventNotification(hEvt); - if (hr != DI_OK) { - DDIO_MESSAGE((hr, "DI_Keyboard failed to set preemptive key event notification.")); - CloseHandle(hEvt); - return NULL; - } - - // set key buffer size - hr = lpdikey->SetProperty(DIPROP_BUFFERSIZE, &dipropdw.diph); - if (FAILED(hr)) { - DDIO_MESSAGE((hr, "DI_keyboard buffering failed.")); - lpdikey->SetEventNotification(NULL); - CloseHandle(hEvt); - return NULL; - } - - return hEvt; - } - - return NULL; -} - -// disables event based notification. -bool dikey_DisableNotify(LPDIRECTINPUTDEVICE lpdikey, HANDLE evthandle) { - if (lpdikey) { - lpdikey->SetEventNotification(NULL); - CloseHandle(evthandle); - return true; - } - - return false; -} - -// acquires or unacquires device -// returns device acquisition state. -bool dikey_Acquire(LPDIRECTINPUTDEVICE lpdikey, bool acquire) { - HRESULT hr = acquire ? lpdikey->Acquire() : lpdikey->Unacquire(); - - if (FAILED(hr)) { - DDIO_MESSAGE((hr, "DI_keyboard acquire/unacquire fail.")); - return !acquire; - } - - return acquire; -} - -// DirectInput Keyboard Thread -void __cdecl dikey_Thread(void *dp) { - unsigned event_count = 0; - - GetAsyncKeyState(VK_PAUSE); // this will tell if the 'pause' key is toggled - - while (WKD.thread_active) { - // this thread will hold until the direct input key event has been signaled by the OS. - // after this, we will get all the keys in the io buffer and register them with the - // key system. - - switch (WaitForSingleObject(WKD.evtnotify, INFINITE)) { - case WAIT_TIMEOUT: // this shouldn't happen, but if it does, no big deal. - break; - case WAIT_ABANDONED: // usually means calling thread quit. - WKD.thread_active = false; - break; - case WAIT_OBJECT_0: // event was signalled normally - { - DIDEVICEOBJECTDATA diobjdata[DIKEY_BUFFER_SIZE]; - DWORD diobjitems = DIKEY_BUFFER_SIZE; - HRESULT hr; - // SHORT async_key_state; - uint8_t key; - - int i; - - // don't read if suspended! - if (WKD.suspended) { - break; - } - - event_count++; - - // attempt acquisition if keyboard not already acquired - if (!WKD.acquired) { - WKD.acquired = dikey_Acquire(WKD.lpdikey, true); - } - if (WKD.acquired) { - hr = WKD.lpdikey->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), diobjdata, &diobjitems, 0); - if (SUCCEEDED(hr)) { - // the pause is key under Windows seems to act kinda strange. it's a toggle button - // and USUALLY is preceeded by a KEY_LCTRL press. If a pause toggle was indicated, flush the - // keyboard and quit. - - // note that dwOfs is the acutal key that is either down or up, and dwData tells us if - // it is up or down. So place on key array, and in queue. - for (i = 0; i < (int)diobjitems; i++) { - key = xlate_scancode((uint8_t)(diobjdata[i].dwOfs)); - if (diobjdata[i].dwData & 0x80) { - if (WKeys[key].status) { - WKeys[key].up_ticks = 0; - } - WKeys[key].down_ticks = diobjdata[i].dwTimeStamp; - WKeys[key].status = true; - if (key == KEY_LCTRL) { - WKeys[key].mutex_flag = true; - } - mprintf(0, "dkey=%x\n", key); - } else { - if (WKeys[key].status) { - WKeys[key].up_ticks = diobjdata[i].dwTimeStamp; - WKeys[key].status = false; - mprintf(0, "ukey=%x\n", key); - } - } - - ddio_UpdateKeyState(key, WKeys[key].status); - } - } else { - if (hr == DIERR_INPUTLOST) { - WKD.acquired = dikey_Acquire(WKD.lpdikey, true); - } else { - DDIO_MESSAGE((hr, "DI_keyboard unable to read.")); - } - } - } - } break; - } - - ResetEvent(WKD.evtnotify); - } - - DDIO_MESSAGE((0, "DI_Keyboard thread ended.")); -} - -void ddio_InternalKeySuspend() { - if (WKD.lpdikey && WKD.acquired) { - WKD.acquired = dikey_Acquire(WKD.lpdikey, false); - } - WKD.suspended = true; -} - -void ddio_InternalKeyResume() { - if (WKD.lpdikey && !WKD.acquired) { - WKD.acquired = dikey_Acquire(WKD.lpdikey, true); - } - WKD.suspended = false; -} - -// Win32 non-threaded version - -bool ddio_Win_KeyInit() { - /* Initialize hook handlers */ - WKD.winhook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, (HINSTANCE)DInputData.app->m_hInstance, - GetCurrentThreadId()); - if (!WKD.winhook) { - return false; - } - - mprintf(0, "Keyboard initialized.\n"); - - return true; -} - -void ddio_Win_KeyClose() { - /* Free up message handlers */ - if (WKD.winhook) { - UnhookWindowsHookEx(WKD.winhook); - WKD.winhook = NULL; - } - - mprintf(0, "Keyboard released.\n"); -} - -// ---------------------------------------------------------------------------- -// non DirectInput keyboard handler -// ---------------------------------------------------------------------------- - -LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) { - int res; - - if (code < 0) { - return CallNextHookEx(WKD.winhook, code, wParam, lParam); - } - - if (lParam & 0x80000000) - res = ddio_KeyHandler(0, WM_KEYUP, wParam, lParam); - else - res = ddio_KeyHandler(0, WM_KEYDOWN, wParam, lParam); - - return (!res); -} - -int ddio_KeyHandler(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { - uint8_t scan_code; - float timer = timer_GetTime(); - - if (!WKD.winhook) - return 1; - - switch (msg) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - scan_code = (uint8_t)((lParam >> 16) & 0xff); - if (lParam & 0x01000000) - scan_code |= 0x80; - - scan_code = xlate_scancode(scan_code); - - // print screen is a weird case. only accept key ups. - if (wParam != VK_SNAPSHOT) { - if (!WKeys[scan_code].status) { - WKeys[scan_code].up_time = 0; - WKeys[scan_code].down_time = timer; - } else { - WKeys[scan_code].up_time = 0; - } - WKeys[scan_code].status = true; - ddio_UpdateKeyState(scan_code, true); - } - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - scan_code = (uint8_t)((lParam >> 16) & 0xff); - if (lParam & 0x01000000) - scan_code |= 0x80; - - scan_code = xlate_scancode(scan_code); - - // handle special keys. print screen, we will simulate the keypress. - if (wParam == VK_SNAPSHOT) { - scan_code = KEY_PRINT_SCREEN; - WKeys[scan_code].down_time = timer; - WKeys[scan_code].status = true; - ddio_UpdateKeyState(scan_code, true); - } - if (WKeys[scan_code].status) { - WKeys[scan_code].status = false; - WKeys[scan_code].up_time = timer; - ddio_UpdateKeyState(scan_code, false); - } - - break; - } - - return 1; -} diff --git a/ddio/winmouse.cpp b/ddio/winmouse.cpp deleted file mode 100644 index eb474fc74..000000000 --- a/ddio/winmouse.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . -*/ - -// ---------------------------------------------------------------------------- -// Mouse Interface -// ---------------------------------------------------------------------------- - -#include -#include - -#include "pserror.h" -#include "mono.h" -#include "ddio.h" -#include "ddio_win.h" -#include "Application.h" -#include "psclass.h" -#include "Macros.h" - -struct t_mse_button_info { - bool is_down[N_MSEBTNS]; - uint8_t down_count[N_MSEBTNS]; - uint8_t up_count[N_MSEBTNS]; - DWORD time_down[N_MSEBTNS]; // in milliseconds windows ticks - DWORD time_up[N_MSEBTNS]; -}; - -struct t_mse_event { - int16_t btn; - int16_t state; -}; - -#define MOUSE_ZMIN 0 // mouse wheel z min and max (increments of 120 = 10 units) -#define MOUSE_ZMAX 1200 -#define N_DIMSEBTNS 4 // # of REAL mouse buttons -#define MSEBTN_WHL_UP (N_DIMSEBTNS) // button index for mouse wheel up -#define MSEBTN_WHL_DOWN (N_DIMSEBTNS + 1) // button index for mouse wheel down - -// taken from winuser.h -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 -#endif -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x20a -#endif - -bool rawInputOpened = false; - -// ---------------------------------------------------------------------------- - -static bool DDIO_mouse_init = 0; - -static struct mses_state { - LPDIRECTINPUTDEVICE lpdimse; - RECT brect; // limit rectangle of absolute mouse coords - int16_t x, y, z; // current x,y,z in absolute mouse coords - int16_t cx, cy, cz; // prior values of x,y,z from last mouse frame - int16_t zmin, zmax; // 3 dimensional mouse devices use this - int btn_mask, btn_flags; // btn_flags are the avaiable buttons on this device in mask form. - float timer; // done to keep track of mouse polling. [ISB] this is in InjectD3 but not here? - bool emulated; // are we emulating direct input? - bool acquired; - bool suspended; - int8_t cursor_count; - float x_aspect, y_aspect; // used in calculating coordinates returned from ddio_MouseGetState - HANDLE hmseevt; // signaled if mouse input is awaiting. - int16_t dx, dy, dz, imm_dz; - int16_t mode; // mode of mouse operation. - int16_t nbtns, naxis; // device caps. -} DDIO_mouse_state; - -// Normally mouse events use ticks, attempting to use timer_GetTime which has more accuracy to smooth over bug with -// mouse buttons dropping. -float localDownStart[N_MSEBTNS]; -float localUpStart[N_MSEBTNS]; - -static t_mse_button_info DIM_buttons; -static tQueue MB_queue; - -int wheelAccum = 0; - -void DDIOShowCursor(BOOL show) { - if (show) { - if (DDIO_mouse_state.cursor_count == -1) { - ShowCursor(TRUE); - } - DDIO_mouse_state.cursor_count = 0; - } else { - if (DDIO_mouse_state.cursor_count == 0) { - ShowCursor(FALSE); - } - DDIO_mouse_state.cursor_count = -1; - } -} - -void ddio_MouseMode(int mode) { - DDIO_mouse_state.mode = mode; -} - -void ddio_MouseQueueFlush() { - memset(&DIM_buttons, 0, sizeof(DIM_buttons)); - MB_queue.flush(); - - // Need to clear the new arrays, since otherwise the game will think you're holding down a button when leaving a UI - // screen. - memset(localDownStart, 0, sizeof(localDownStart)); - memset(localUpStart, 0, sizeof(localUpStart)); -} - -void ddio_MouseReset() { - // get relative window rect, 0/0 - width-1/height-1 - GetClientRect(DInputData.hwnd, &DDIO_mouse_state.brect); - // restrict mouse cursor to actual screen coords of the window - RECT clipRect = DDIO_mouse_state.brect; - ClientToScreen(DInputData.hwnd, reinterpret_cast(&clipRect.left)); - ClientToScreen(DInputData.hwnd, reinterpret_cast(&clipRect.right)); - ClipCursor(&clipRect); - - DDIO_mouse_state.zmin = MOUSE_ZMIN; - DDIO_mouse_state.zmax = MOUSE_ZMAX; - - // set up new coordinates for mouse pointer. - DDIO_mouse_state.btn_mask = 0; - DDIO_mouse_state.dx = 0; - DDIO_mouse_state.dy = 0; - DDIO_mouse_state.dz = 0; - DDIO_mouse_state.imm_dz = 0; - DDIO_mouse_state.x = (DDIO_mouse_state.brect.right + DDIO_mouse_state.brect.left) / 2; - DDIO_mouse_state.y = (DDIO_mouse_state.brect.bottom + DDIO_mouse_state.brect.top) / 2; - DDIO_mouse_state.z = (DDIO_mouse_state.zmax + DDIO_mouse_state.zmin) / 2; - DDIO_mouse_state.cx = DDIO_mouse_state.x; - DDIO_mouse_state.cy = DDIO_mouse_state.y; - DDIO_mouse_state.cz = 0; - DDIO_mouse_state.x_aspect = 1.0f; - DDIO_mouse_state.y_aspect = 1.0f; - - // reset button states - ddio_MouseQueueFlush(); -} - -// return mouse button down time. -// This function has been hacked to use timer_GetTime which can be much more accurate. -float ddio_MouseBtnDownTime(int btn) { - // DWORD ticks, curticks = GetTickCount(); - float time, curtime = timer_GetTime(); - - // ASSERT(btn >= 0 && btn < N_MSEBTNS); - - if (DIM_buttons.is_down[btn]) { - time = curtime - localDownStart[btn]; - DIM_buttons.time_down[btn] = (int)(curtime * 1000); - localDownStart[btn] = curtime; - } else { - time = localUpStart[btn] - localDownStart[btn]; - localUpStart[btn] = localDownStart[btn] = 0; - DIM_buttons.time_down[btn] = DIM_buttons.time_up[btn] = 0; - } - - DIM_buttons.is_down[MSEBTN_WHL_UP] = false; - DIM_buttons.is_down[MSEBTN_WHL_DOWN] = false; - - return time; -} - -int ddio_MouseGetState(int *x, int *y, int *dx, int *dy, int *z, int *dz) { - // update mouse timer. - int btn_mask = DDIO_mouse_state.btn_mask; - - DDIO_mouse_state.timer = timer_GetTime(); - - // get return values. - if (x) - *x = DDIO_mouse_state.x; - if (y) - *y = DDIO_mouse_state.y; - if (z) - *z = DDIO_mouse_state.z; - if (dx) - *dx = DDIO_mouse_state.dx; - if (dy) - *dy = DDIO_mouse_state.dy; - if (dz) - *dz = DDIO_mouse_state.dz; - - DDIO_mouse_state.dx = 0; - DDIO_mouse_state.dy = 0; - DDIO_mouse_state.dz = 0; - DDIO_mouse_state.btn_mask = 0; - - DIM_buttons.is_down[MSEBTN_WHL_UP] = false; - DIM_buttons.is_down[MSEBTN_WHL_DOWN] = false; - - return btn_mask; -} - -void ddio_InternalMouseFrame() { - int btn_mask = 0; - - // These need to be continually maintained, since a small number of inputs rely on it being set every frame. - if (DIM_buttons.is_down[0]) - btn_mask |= MOUSE_LB; - if (DIM_buttons.is_down[1]) - btn_mask |= MOUSE_RB; - if (DIM_buttons.is_down[2]) - btn_mask |= MOUSE_CB; - if (DIM_buttons.is_down[3]) - btn_mask |= MOUSE_B4; - if (DIM_buttons.is_down[4]) - btn_mask |= MOUSE_B5; - if (DIM_buttons.is_down[5]) - btn_mask |= MOUSE_B6; - if (DIM_buttons.is_down[6]) - btn_mask |= MOUSE_B7; - if (DIM_buttons.is_down[7]) - btn_mask |= MOUSE_B8; - - DDIO_mouse_state.btn_mask = btn_mask; -} - -void MouseError() { MessageBoxA(nullptr, "Failed to init raw input for mouse", "Error", MB_ICONERROR); } - -int RawInputHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - uint32_t buttons; - t_mse_event ev; - float curtime = timer_GetTime(); - - if (DDIO_mouse_state.suspended) { - DDIO_mouse_state.btn_mask = 0; - DDIO_mouse_state.dx = 0; - DDIO_mouse_state.dy = 0; - DDIO_mouse_state.dz = 0; - return 0; - } - - HRAWINPUT rawinputHandle = (HRAWINPUT)lParam; - UINT size = 0; - UINT result = GetRawInputData(rawinputHandle, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER)); - if (result == 0 && size > 0) { - void *buf = malloc(size); - if (!buf) { - return 0; - } - result = GetRawInputData(rawinputHandle, RID_INPUT, buf, &size, sizeof(RAWINPUTHEADER)); - - if (result >= 0) { - RAWINPUT *rawinput = (RAWINPUT *)buf; - if (rawinput->header.dwType == RIM_TYPEMOUSE) { - buttons = rawinput->data.mouse.ulButtons; - if (buttons & RI_MOUSE_LEFT_BUTTON_DOWN && !DIM_buttons.is_down[0]) { - DIM_buttons.down_count[0]++; - DIM_buttons.time_down[0] = GetTickCount(); - localDownStart[0] = curtime; - DIM_buttons.is_down[0] = true; - DDIO_mouse_state.btn_mask |= MOUSE_LB; - ev.btn = 0; - ev.state = true; - MB_queue.send(ev); - /*if (hack) - { - fprintf(hack, "MB1 down at %f\n", timer_GetTime()); - }*/ - } else if (buttons & RI_MOUSE_LEFT_BUTTON_UP && DIM_buttons.is_down[0]) { - DIM_buttons.up_count[0]++; - DIM_buttons.is_down[0] = false; - DIM_buttons.time_up[0] = GetTickCount(); - localUpStart[0] = curtime; - DDIO_mouse_state.btn_mask &= ~MOUSE_LB; - ev.btn = 0; - ev.state = false; - MB_queue.send(ev); - /*if (hack) - { - fprintf(hack, "MB1 up at %f\n", timer_GetTime()); - }*/ - } - if (buttons & RI_MOUSE_RIGHT_BUTTON_DOWN && !DIM_buttons.is_down[1]) { - DIM_buttons.down_count[1]++; - DIM_buttons.time_down[1] = GetTickCount(); - localDownStart[1] = curtime; - DIM_buttons.is_down[1] = true; - DDIO_mouse_state.btn_mask |= MOUSE_RB; - ev.btn = 1; - ev.state = true; - MB_queue.send(ev); - } else if (buttons & RI_MOUSE_RIGHT_BUTTON_UP && DIM_buttons.is_down[1]) { - DIM_buttons.up_count[1]++; - DIM_buttons.is_down[1] = false; - DIM_buttons.time_up[1] = GetTickCount(); - localUpStart[1] = curtime; - DDIO_mouse_state.btn_mask &= ~MOUSE_RB; - ev.btn = 1; - ev.state = false; - MB_queue.send(ev); - } - if (buttons & RI_MOUSE_MIDDLE_BUTTON_DOWN && !DIM_buttons.is_down[2]) { - DIM_buttons.down_count[2]++; - DIM_buttons.time_down[2] = GetTickCount(); - localDownStart[2] = curtime; - DIM_buttons.is_down[2] = true; - DDIO_mouse_state.btn_mask |= MOUSE_CB; - ev.btn = 2; - ev.state = true; - MB_queue.send(ev); - } else if (buttons & RI_MOUSE_MIDDLE_BUTTON_UP && DIM_buttons.is_down[2]) { - DIM_buttons.up_count[2]++; - DIM_buttons.is_down[2] = false; - DIM_buttons.time_up[2] = GetTickCount(); - localUpStart[2] = curtime; - DDIO_mouse_state.btn_mask &= ~MOUSE_CB; - ev.btn = 2; - ev.state = false; - MB_queue.send(ev); - } - - // JC: Imported extra mouse buttons code from Piccu Engine 2924ad2 - if (buttons & RI_MOUSE_BUTTON_4_DOWN && !DIM_buttons.is_down[3]) - { - DIM_buttons.down_count[3]++; - DIM_buttons.time_down[3] = curtime; - DIM_buttons.is_down[3] = true; - DDIO_mouse_state.btn_mask |= MOUSE_B4; - ev.btn = 3; - ev.state = true; - MB_queue.send(ev); - } - else if (buttons & RI_MOUSE_BUTTON_4_UP && DIM_buttons.is_down[3]) - { - DIM_buttons.up_count[3]++; - DIM_buttons.is_down[3] = false; - DIM_buttons.time_up[3] = curtime; - DDIO_mouse_state.btn_mask &= ~MOUSE_B4; - ev.btn = 3; - ev.state = false; - MB_queue.send(ev); - } - if (buttons & RI_MOUSE_BUTTON_5_DOWN && !DIM_buttons.is_down[6]) - { - DIM_buttons.down_count[6]++; - DIM_buttons.time_down[6] = curtime; - DIM_buttons.is_down[6] = true; - DDIO_mouse_state.btn_mask |= MOUSE_B7; - ev.btn = 6; - ev.state = true; - MB_queue.send(ev); - } else if (buttons & RI_MOUSE_BUTTON_5_UP && DIM_buttons.is_down[6]) - { - DIM_buttons.up_count[6]++; - DIM_buttons.is_down[6] = false; - DIM_buttons.time_up[6] = curtime; - DDIO_mouse_state.btn_mask &= ~MOUSE_B7; - ev.btn = 6; - ev.state = false; - MB_queue.send(ev); - } - - if (buttons & RI_MOUSE_WHEEL) { - wheelAccum += (int)(int16_t)rawinput->data.mouse.usButtonData; - if (wheelAccum >= WHEEL_DELTA) { - DIM_buttons.down_count[MSEBTN_WHL_UP]++; - DIM_buttons.up_count[MSEBTN_WHL_UP]++; - DIM_buttons.is_down[MSEBTN_WHL_UP] = true; - DIM_buttons.time_down[MSEBTN_WHL_UP] = GetTickCount(); - DIM_buttons.time_up[MSEBTN_WHL_UP] = GetTickCount() + 100; - localDownStart[MSEBTN_WHL_UP] = curtime; - localUpStart[MSEBTN_WHL_UP] = curtime + .1f; - wheelAccum = 0; - } else if (wheelAccum <= -WHEEL_DELTA) { - DIM_buttons.down_count[MSEBTN_WHL_DOWN]++; - DIM_buttons.up_count[MSEBTN_WHL_DOWN]++; - DIM_buttons.is_down[MSEBTN_WHL_DOWN] = true; - DIM_buttons.time_down[MSEBTN_WHL_DOWN] = GetTickCount(); - DIM_buttons.time_up[MSEBTN_WHL_DOWN] = GetTickCount() + 100; - localDownStart[MSEBTN_WHL_DOWN] = curtime; - localUpStart[MSEBTN_WHL_DOWN] = curtime + .1f; - wheelAccum = 0; - } - } - - DDIO_mouse_state.dx += rawinput->data.mouse.lLastX; - DDIO_mouse_state.dy += rawinput->data.mouse.lLastY; - // DDIO_mouse_state.btn_mask = buttons; - } - - DDIO_mouse_state.x += rawinput->data.mouse.lLastX; - DDIO_mouse_state.y += rawinput->data.mouse.lLastY; - DDIO_mouse_state.z = 0; - - // check bounds of mouse cursor. - if (DDIO_mouse_state.x < DDIO_mouse_state.brect.left) - DDIO_mouse_state.x = (int16_t)DDIO_mouse_state.brect.left; - if (DDIO_mouse_state.x >= DDIO_mouse_state.brect.right) - DDIO_mouse_state.x = (int16_t)DDIO_mouse_state.brect.right - 1; - if (DDIO_mouse_state.y < DDIO_mouse_state.brect.top) - DDIO_mouse_state.y = (int16_t)DDIO_mouse_state.brect.top; - if (DDIO_mouse_state.y >= DDIO_mouse_state.brect.bottom) - DDIO_mouse_state.y = (int16_t)DDIO_mouse_state.brect.bottom - 1; - if (DDIO_mouse_state.z > DDIO_mouse_state.zmax) - DDIO_mouse_state.z = (int16_t)DDIO_mouse_state.zmax; - if (DDIO_mouse_state.z < DDIO_mouse_state.zmin) - DDIO_mouse_state.z = (int16_t)DDIO_mouse_state.zmin; - } - - free(buf); - } - return 0; -} - -bool InitNewMouse() { - int i; - if (!rawInputOpened) { - RAWINPUTDEVICE rawInputDevice = {}; - - rawInputDevice.usUsage = 0x0002; - rawInputDevice.usUsagePage = 0x0001; - //TODO: This code should be renabled when some solution for mouse capturing is decided on. - // The game should free the capture when the cursor is visible, and recapture it when it isn't visible. - // Account for the original mode. - if (DDIO_mouse_state.mode == MOUSE_EXCLUSIVE_MODE) - rawInputDevice.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY; - else - rawInputDevice.dwFlags = 0; - - rawInputDevice.hwndTarget = DInputData.hwnd; - - if (RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice)) == FALSE) { - Error("InitNewMouse: HID Registration failed: %d", GetLastError()); - return false; - } - - // HACK: Need to flush messages for this to work. - MSG msg; - - while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessageA(&msg); - } - - DInputData.app->add_handler(WM_INPUT, (tOEWin32MsgCallback)&RawInputHandler); - - DDIO_mouse_state.timer = timer_GetTime(); - DDIO_mouse_state.naxis = 2; - DDIO_mouse_state.nbtns = N_DIMSEBTNS + 3; // always have a mousewheel. [ISB] disgusting hack: Can't change mousewheel bindings for old pilots, so make button 5 after the two mouse wheel buttons. - for (i = 0; i < DDIO_mouse_state.nbtns; i++) { - DDIO_mouse_state.btn_flags |= (1 << i); - } - - memset(&DIM_buttons, 0, sizeof(t_mse_button_info)); - rawInputOpened = true; - } - return true; -} - -bool ddio_MouseInit() { - tWin32OS os; - int major, minor; - - // see if we need to emulate directinput. - os = oeWin32Application::version(&major, &minor); - DDIO_mouse_state.emulated = true; - DDIO_mouse_state.lpdimse = NULL; - - InitNewMouse(); - - // standard initialization - DDIO_mouse_state.emulated = (DDIO_mouse_state.lpdimse) ? false : true; - DDIO_mouse_state.cursor_count = ShowCursor(TRUE); // get initial count - while (DDIO_mouse_state.cursor_count >= 0) // hide cursor until truly hidden. - { - DDIO_mouse_state.cursor_count = ShowCursor(FALSE); - } - - DDIOShowCursor(DDIO_mouse_state.mode == MOUSE_EXCLUSIVE_MODE ? FALSE : TRUE); - - DDIO_mouse_state.suspended = false; - ddio_MouseReset(); - DDIO_mouse_init = true; - - return true; -} - -// here we deinitialize our Mouse from DirectInput. -void ddio_MouseClose() { - if (!DDIO_mouse_init) - return; - - if (rawInputOpened) { - RAWINPUTDEVICE rawInputDevice = {}; - - rawInputDevice.usUsage = 0x0002; - rawInputDevice.usUsagePage = 0x0001; - rawInputDevice.dwFlags = RIDEV_REMOVE; - rawInputDevice.hwndTarget = 0; // not sure why? - - if (RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice)) == FALSE) { - rawInputOpened = false; - DDIO_mouse_init = false; - Error("ddio_MouseClose: HID Registration failed: %d", GetLastError()); - } - DInputData.app->remove_handler(WM_INPUT, (tOEWin32MsgCallback)&RawInputHandler); - rawInputOpened = false; - } - - DDIO_mouse_init = false; -} - -// used to prevent mouse input from being registered -void ddio_InternalMouseSuspend() { - if (!DDIO_mouse_init) - return; - - DDIO_mouse_state.suspended = true; -} - -void ddio_InternalMouseResume() { - if (!DDIO_mouse_init) - return; - - DDIO_mouse_state.suspended = false; -} - -// return mouse button down time -int ddio_MouseBtnDownCount(int btn) { - if (btn < 0 || btn >= N_MSEBTNS) - return 0; - int n_downs = DIM_buttons.down_count[btn]; - - if (n_downs) { - - DIM_buttons.down_count[btn] = 0; - } - - return n_downs; -} - -// return mouse button up count -int ddio_MouseBtnUpCount(int btn) { - if (btn < 0 || btn >= N_MSEBTNS) - return 0; - int n_ups = DIM_buttons.up_count[btn]; - DIM_buttons.up_count[btn] = 0; - return n_ups; -} - -// get device caps -int ddio_MouseGetCaps(int *btn, int *axis) { - *btn = (int)DDIO_mouse_state.nbtns; - *axis = (int)DDIO_mouse_state.naxis; - - return DDIO_mouse_state.btn_flags; -} - -// gets limits on the position of the mouse cursor (or atleast what's returned from GetState) -void ddio_MouseGetLimits(int *left, int *top, int *right, int *bottom, int *zmin, int *zmax) { - *left = DDIO_mouse_state.brect.left; - *top = DDIO_mouse_state.brect.top; - *right = DDIO_mouse_state.brect.right; - *bottom = DDIO_mouse_state.brect.bottom; - - if (zmin) - *zmin = DDIO_mouse_state.zmin; - if (zmax) - *zmax = DDIO_mouse_state.zmax; -} - -// sets limits on the position of the mouse cursor (or atleast what's returned from GetState) -void ddio_MouseSetLimits(int left, int top, int right, int bottom, int zmin, int zmax) { - bool zaxis = (DDIO_mouse_state.naxis >= 3); - SetRect(&DDIO_mouse_state.brect, left, top, right, bottom); - DDIO_mouse_state.zmin = (!zmin && zaxis) ? MOUSE_ZMIN : zmin; - DDIO_mouse_state.zmax = (!zmax && zaxis) ? MOUSE_ZMAX : zmax; - DDIO_mouse_state.cx = (right + left) / 2; - DDIO_mouse_state.cy = (bottom + top) / 2; -} - -// virtual coordinate system for mouse (match to video resolution set for optimal mouse usage. -void ddio_MouseSetVCoords(int width, int height) { ddio_MouseSetLimits(0, 0, width, height); } - -// gets a mouse button event, returns false if none. -bool ddio_MouseGetEvent(int *btn, bool *state) { - t_mse_event evt; - - if (MB_queue.recv(&evt)) { - *btn = (int)evt.btn; - *state = evt.state ? true : false; - return true; - } - - return false; -} - -/////////////////////////////////////////////////////////////////////////////// -char Ctltext_MseBtnBindings[N_MSEBTNS][32] = {"mse-l\0\0\0\0\0\0\0\0\0\0\0\0", - "mse-r\0\0\0\0\0\0\0\0\0\0\0\0", - "mse-c\0\0\0\0\0\0\0\0\0\0\0\0", - "mse-b4\0\0\0\0\0\0\0\0\0\0\0", - "msew-u\0\0\0\0\0\0\0\0\0\0\0", - "msew-d\0\0\0\0\0\0\0\0\0\0\0", - "mse-b5", - ""}; - -char Ctltext_MseAxisBindings[][32] = {"mse-X\0\0\0\0\0\0\0\0\0\0\0\0", "mse-Y\0\0\0\0\0\0\0\0\0\0\0\0", - "msewheel\0\0\0\0\0\0\0\0\0\0"}; - -// returns string to binding. -const char *ddio_MouseGetBtnText(int btn) { - if (btn >= N_MSEBTNS || btn < 0) - return (""); - return Ctltext_MseBtnBindings[btn]; -} - -const char *ddio_MouseGetAxisText(int axis) { - if (axis >= (sizeof(Ctltext_MseAxisBindings) / sizeof(char *)) || axis < 0) - return (""); - return Ctltext_MseAxisBindings[axis]; -} diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index d623ba2d3..88ad692e1 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -559,60 +559,25 @@ set(SOURCE WorldTexturesDialog.cpp WorldWeaponsDialog.cpp editor.rc + ../Descent3/loki_utils.c + ../Descent3/sdlmain.cpp ) -# Editor only works in Windows -set(PLATFORM_LIBS dd_grwin32 win32 wsock32.lib winmm.lib - ${DSOUND_LIBRARY} ${DINPUT_LIBRARY} ${DXGUID_LIBRARY} ${DDRAW_LIBRARY}) -set(PLATFORM_SOURCES ../descent3/winmain.cpp) -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /SUBSYSTEM:WINDOWS /NODEFAULTLIB:LIBC") +# Editor only works in Windows, because of MFC and DirectX dependencies +set(PLATFORM_LIBS linux wsock32.lib winmm.lib dd_grwin32 win32 SDL2::SDL2) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:LIBC") +add_executable(Descent3Editor WIN32 ${HEADERS} ${SOURCE}) -add_executable(Descent3Editor ${HEADERS} ${SOURCE} ${PLATFORM_SOURCES}) target_include_directories(Descent3Editor PRIVATE ../lib ../ ../manage/ ${PROJECT_BINARY_DIR}/lib) +target_compile_definitions(Descent3Editor PUBLIC _AFXDLL EDITOR) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /Zc:forScope-") -if(MSVC) - target_compile_definitions(Descent3Editor PUBLIC _CRT_SECURE_NO_WARNINGS _AFXDLL EDITOR) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /Zc:forScope-") -endif() - -# Link libraries -target_link_libraries(Descent3Editor - 2dlib - AudioEncode - bitmap - cfile - czip - d3music - dd_video - ddio - ddebug - libmve - libacm - fix - grtext - manage - mem - misc - model - module - movie - stream_audio - music - networking - physics - renderer - rtperformance - sndlib - ui - unzip - vecmat - md5 - ${PLATFORM_LIBS} -) - -if (WIN32) - set_target_properties(Descent3Editor PROPERTIES WIN32_EXECUTABLE ON) -endif() +target_link_libraries(Descent3Editor PRIVATE + 2dlib AudioEncode bitmap cfile czip d3music dd_video ddebug ddio libmve libacm + fix grtext manage mem misc model module movie stream_audio + music networking physics renderer rtperformance sndlib ui unzip vecmat md5 + ${PLATFORM_LIBS}) +add_dependencies(Descent3Editor get_git_hash) install(TARGETS Descent3Editor RUNTIME) diff --git a/editor/MainFrm.cpp b/editor/MainFrm.cpp index 9bd8ce4d3..320b80adf 100644 --- a/editor/MainFrm.cpp +++ b/editor/MainFrm.cpp @@ -1463,6 +1463,18 @@ void InitCScripts() { ddio_MakePath(path, Base_directory, "data", "levels", NULL); } +// Copied from winmain.cpp +void WinMainInitEditor(unsigned hwnd, unsigned hinst) { + tLnxAppInfo appinfo; + + // TODO: HWnd from SDL2 Window + // appinfo.hwnd = (HWnd)hwnd; + // appinfo.hinst = (HInstance)hinst; + appinfo.flags = OEAPP_WINDOWED; + + Descent = new oeLnxApplication(&appinfo); + Database = new oeLnxAppDatabase; +} // Initializes OS components for Descent3. MUST BE DONE BEFORE ANYTHING ELSE! BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext) { @@ -1557,7 +1569,7 @@ void CMainFrame::OnActivateApp(BOOL bActive, HTASK hTask) { mprintf_at(2,0,0, "App Inactive"); } - ((oeWin32Application *)Descent)->run_handler(this->m_hWnd, WM_ACTIVATEAPP, (unsigned)bActive, 0); + ((oeLnxApplication *)Descent)->run_handler(this->m_hWnd, WM_ACTIVATEAPP, (unsigned)bActive, 0); #endif } diff --git a/editor/TextureGrWnd.cpp b/editor/TextureGrWnd.cpp index 3dcf9bb4c..fa627f928 100644 --- a/editor/TextureGrWnd.cpp +++ b/editor/TextureGrWnd.cpp @@ -598,14 +598,15 @@ extern float Just_returned_time; int Successive_count = 0; HWND save_wnd; -oeWin32Application *app; +oeLnxApplication *app; void CTextureGrWnd::TexGrStartOpenGL() { if (DoOpenGL) { - app = (oeWin32Application *)Descent; + app = (oeLnxApplication *)Descent; StateLimited = 1; - save_wnd = (HWND)app->m_hWnd; - app->m_hWnd = (HWnd)m_hWnd; + // TODO - hwnd from SDL windows + // save_wnd = (HWND)app->m_hWnd; + // app->m_hWnd = (HWnd)m_hWnd; // rend_SetOpenGLWindowState (1,Descent,NULL); // LGT: not defined anymore rend_ClearScreen(0); StateLimited = 1; @@ -617,7 +618,8 @@ void CTextureGrWnd::TexGrStartOpenGL() { void CTextureGrWnd::TexGrStopOpenGL() { if (DoOpenGL) { // rend_SetOpenGLWindowState (0,Descent,NULL); // LGT: not defined anymore - app->m_hWnd = (HWnd)save_wnd; + // TODO - hwnd from SDL windows + // app->m_hWnd = (HWnd)save_wnd; } } @@ -784,18 +786,18 @@ void CTextureGrWnd::OnPaint() { if (DoOpenGL) { HWND save_wnd; - oeWin32Application *app; + oeLnxApplication *app; - app = (oeWin32Application *)Descent; + app = (oeLnxApplication *)Descent; - save_wnd = (HWND)app->m_hWnd; - app->m_hWnd = (HWnd)m_hWnd; + // save_wnd = (HWND)app->m_hWnd; + // app->m_hWnd = (HWnd)m_hWnd; // rend_SetOpenGLWindowState (1,Descent,NULL); // LGT: not defined anymore rend_Flip(); // rend_SetOpenGLWindowState (0,Descent,NULL); // LGT: not defined anymore - app->m_hWnd = (HWnd)save_wnd; + // app->m_hWnd = (HWnd)save_wnd; } else { m_grScreen->flip(); m_grViewport->clear(); diff --git a/editor/editor.cpp b/editor/editor.cpp index 8189f5cc8..fa8526d2c 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -813,7 +813,7 @@ BOOL CEditorApp::OnIdle(LONG lCount) { // Save current editor settings to the registry void SaveEditorSettings() { - oeWin32AppDatabase Editor_database((oeWin32AppDatabase *)Database); + oeLnxAppDatabase Editor_database((oeLnxAppDatabase *)Database); bool res; int speed; @@ -874,7 +874,7 @@ void SaveEditorSettings() { // Load editor settings from the registry void LoadEditorSettings() { - oeWin32AppDatabase Editor_database((oeWin32AppDatabase *)Database); + oeLnxAppDatabase Editor_database((oeLnxAppDatabase *)Database); bool res; int speed = (int)((Slew_key_speed - 0.5) / 0.5); diff --git a/editor/gameeditor.cpp b/editor/gameeditor.cpp index 352d288ca..c85ede763 100644 --- a/editor/gameeditor.cpp +++ b/editor/gameeditor.cpp @@ -736,7 +736,7 @@ void EditorToGame() { /* Create a new window and display it. Initialize a new GameOS Object and use this for our game */ - tWin32AppInfo app_info; + tLnxAppInfo app_info; bool paged = true; char subsystem[8]; ddio_init_info io_info; @@ -821,12 +821,13 @@ void EditorToGame() { // create window and start game. if (PROGRAM(windowed)) { flags = OEAPP_WINDOWED; - Descent = new oeWin32Application("D3 Game Window", flags, app_info.hinst); + Descent = new oeLnxApplication(flags); Descent->init(); set_size = true; Descent->get_info(&app_info); - hGameWnd = app_info.hwnd; - SetForegroundWindow((HWND)hGameWnd); + // TODO: retrieve hwnd from SDL window handle + // hGameWnd = app_info.hwnd; + // SetForegroundWindow((HWND)hGameWnd); Saved_editor_app->defer(); Descent->defer(); @@ -841,12 +842,13 @@ void EditorToGame() { theApp.main_frame->SetMenu(NULL); flags = OEAPP_FULLSCREEN; - Descent = new oeWin32Application("D3 Game Window Debug", flags, app_info.hinst); + Descent = new oeLnxApplication(flags); Descent->init(); set_size = true; Descent->get_info(&app_info); - hGameWnd = app_info.hwnd; - SetForegroundWindow((HWND)hGameWnd); + // TODO: get hwnd from SDL Window + // hGameWnd = app_info.hwnd; + // SetForegroundWindow((HWND)hGameWnd); Saved_editor_app->defer(); Descent->defer(); @@ -892,7 +894,7 @@ void EditorToGame() { // maybe we should CLEAR HERE if (set_size) { - ((oeWin32Application *)Descent)->set_sizepos(0, 0, 640, 480); + ((oeLnxApplication *)Descent)->set_sizepos(0, 0, 640, 480); } Just_returned_from_game = 1; diff --git a/lib/Controller.h b/lib/Controller.h index 29381d85e..370a378bc 100644 --- a/lib/Controller.h +++ b/lib/Controller.h @@ -264,9 +264,9 @@ class gameController { gameController *CreateController(int num_funcs, ct_function *funcs, char *remote_ip); void DestroyController(gameController *ctl); -#if defined(WIN32) +#if defined(DX_APP) #include "win\WinController.h" -#elif defined(__LINUX__) +#else #include "lnxcontroller.h" #endif diff --git a/lib/appdatabase.h b/lib/appdatabase.h index a29e1d0e3..d80209527 100644 --- a/lib/appdatabase.h +++ b/lib/appdatabase.h @@ -100,9 +100,9 @@ class oeAppDatabase { Win32 Samir Win32Database.h 06/97 */ -#if defined(WIN32) -#include "win\Win32Database.h" -#elif defined(__LINUX__) +#if defined(DX_APP) +#include "win\win32database.h" +#else #include "linux/lnxdatabase.h" #endif diff --git a/lib/application.h b/lib/application.h index 7dcc45ad1..85a7c0586 100644 --- a/lib/application.h +++ b/lib/application.h @@ -109,9 +109,10 @@ class oeApplication { Add a platform to this list once implemented: Win32 Samir Win32App.h 06/97 */ -#if defined(WIN32) +#if defined(DX_APP) #include "win\win32app.h" -#elif defined(__LINUX__) +#else #include "lnxapp.h" #endif -#endif + +#endif // APP_H diff --git a/lib/linux/lnxdatabase.h b/lib/linux/lnxdatabase.h index 32f839ca2..bae181d0d 100644 --- a/lib/linux/lnxdatabase.h +++ b/lib/linux/lnxdatabase.h @@ -31,6 +31,7 @@ class CRegistry; #include "Macros.h" +#include "appdatabase.h" /* oeLnxAppDatabase to get info about the application from a managed database (or a custom info file) diff --git a/lib/lnxscreenmode.h b/lib/lnxscreenmode.h index 7f10e4dde..3f036f4c9 100644 --- a/lib/lnxscreenmode.h +++ b/lib/lnxscreenmode.h @@ -52,7 +52,9 @@ #ifndef __LNXVIDEOMODE_H__ #define __LNXVIDEOMODE_H__ +#ifdef __LINUX__ #include "linux_fix.h" +#endif #include #define MODE_OK 0 diff --git a/libmve/CMakeLists.txt b/libmve/CMakeLists.txt index 7b92311a4..6c20a973f 100644 --- a/libmve/CMakeLists.txt +++ b/libmve/CMakeLists.txt @@ -5,16 +5,12 @@ set(HEADERS platform.h snd8to16.h SystemInterfaces.h) + set(CPPS mveasm.cpp mvelibl.cpp - platform.cpp) - -set(PLATFORM_CPPS) - -if(UNIX) - set(PLATFORM_CPPS "lnxdsound.cpp") -endif() + platform.cpp + lnxdsound.cpp) add_library(libmve STATIC ${HEADERS} ${CPPS} ${PLATFORM_CPPS}) - +target_link_libraries(libmve PRIVATE SDL2::SDL2) diff --git a/libmve/lnxdsound.cpp b/libmve/lnxdsound.cpp index 0cc133a9e..64dbed72a 100644 --- a/libmve/lnxdsound.cpp +++ b/libmve/lnxdsound.cpp @@ -19,9 +19,12 @@ #include #include #include +#ifdef __LINUX__ #include #include #include +#include +#endif #include #include #include @@ -33,7 +36,6 @@ #include "SDL.h" #include "SDL_audio.h" -#include #define FRAGMENT_LENGTH (LnxBuffers[0]->bps >> 4) #define FREQUENCY_SHIFT (14) diff --git a/libmve/mvelibl.h b/libmve/mvelibl.h index b0169c9fd..0540ef4de 100644 --- a/libmve/mvelibl.h +++ b/libmve/mvelibl.h @@ -23,9 +23,8 @@ #include #include "SystemInterfaces.h" -#if defined(__LINUX__) #include "lnxdsound.h" -#endif + // Call this function to provide hooks into your memory management. typedef void *(mve_cb_alloc)(unsigned size); typedef void(mve_cb_free)(void *p); diff --git a/linux/lnxapp.cpp b/linux/lnxapp.cpp index c3109abd3..f95c1a0be 100644 --- a/linux/lnxapp.cpp +++ b/linux/lnxapp.cpp @@ -70,9 +70,13 @@ #include #include +#ifdef __LINUX__ #include #include #include +#else +#include "winsock.h" +#endif #include "application.h" #include "lnxapp.h" @@ -81,7 +85,9 @@ #undef buttons #endif +#ifdef __LINUX__ static struct termios Linux_initial_terminal_settings; +#endif bool oeLnxApplication::os_initialized = false; bool oeLnxApplication::first_time = true; @@ -116,7 +122,9 @@ void LnxAppShutdown() { LinuxAppDontCallShutdown = true; if (LinuxAppFlags & OEAPP_CONSOLE) { con_Destroy(); +#ifdef __LINUX__ tcsetattr(0, TCSANOW, &Linux_initial_terminal_settings); +#endif } } @@ -126,7 +134,9 @@ oeLnxApplication::oeLnxApplication(unsigned flags) { m_AppActive = true; if (flags & OEAPP_CONSOLE) { +#ifdef __LINUX__ tcgetattr(0, &Linux_initial_terminal_settings); +#endif con_Create(m_Flags); } @@ -140,7 +150,9 @@ oeLnxApplication::oeLnxApplication(unsigned flags) { // Create object with a premade info oeLnxApplication::oeLnxApplication(tLnxAppInfo *appinfo) { +#ifdef __LINUX__ tcgetattr(0, &Linux_initial_terminal_settings); +#endif m_Flags = appinfo->flags; m_X = appinfo->wnd_x; m_Y = appinfo->wnd_y; diff --git a/linux/lnxapp.h b/linux/lnxapp.h index e3b059a51..486aac75d 100644 --- a/linux/lnxapp.h +++ b/linux/lnxapp.h @@ -19,7 +19,9 @@ #ifndef LNXAPP_H #define LNXAPP_H +#ifdef __LINUX__ #include "linux_fix.h" +#endif // if no-display/input specifier is given, it will use defaults #define APPFLAG_USESERVICE 0x00000100 // console (run no output/input) diff --git a/linux/lnxcon.cpp b/linux/lnxcon.cpp index fbd3773d7..566958099 100644 --- a/linux/lnxcon.cpp +++ b/linux/lnxcon.cpp @@ -101,18 +101,18 @@ void con_raw_Puts(int window, const char *str); Console_Commands commands[Console_total] = { { - .con_Create = con_null_Create, - .con_Destroy = con_null_Destroy, - .con_Defer = con_null_Defer, - .con_Input = con_null_Input, - .con_Puts = con_null_Puts, + con_null_Create, + con_null_Destroy, + con_null_Defer, + con_null_Input, + con_null_Puts, }, { - .con_Create = con_raw_Create, - .con_Destroy = con_raw_Destroy, - .con_Defer = con_raw_Defer, - .con_Input = con_raw_Input, - .con_Puts = con_raw_Puts, + con_raw_Create, + con_raw_Destroy, + con_raw_Defer, + con_raw_Input, + con_raw_Puts, }, }; diff --git a/linux/lnxdata.cpp b/linux/lnxdata.cpp index a87655d46..48c09388c 100644 --- a/linux/lnxdata.cpp +++ b/linux/lnxdata.cpp @@ -42,11 +42,17 @@ */ #include -#include #include -#include #include +#ifdef __LINUX__ +#include +#include +#else +#include +#include +#endif + #include "appdatabase.h" #include "linux/lnxdatabase.h" #include "pserror.h" @@ -64,13 +70,14 @@ oeLnxAppDatabase::oeLnxAppDatabase() { // then close the database char *prefPath = (char *)loki_getprefpath(); - size_t fileLen = strlen(prefPath) + strlen(REGISTRY_FILENAME) + 2; - char fileName[fileLen]; + const size_t fileLen = strlen(prefPath) + strlen(REGISTRY_FILENAME) + 2; + char* fileName = new char[fileLen]; snprintf(fileName, fileLen, "%s/%s", prefPath, REGISTRY_FILENAME); database = new CRegistry(fileName); database->Import(); create_record("Version"); + delete [] fileName; } oeLnxAppDatabase::oeLnxAppDatabase(oeLnxAppDatabase *parent) { @@ -208,6 +215,7 @@ bool oeLnxAppDatabase::write(const char *label, int entry) { // get the current user's name from the os void oeLnxAppDatabase::get_user_name(char *buffer, size_t *size) { +#ifdef __LINUX__ struct passwd *pwuid = getpwuid(geteuid()); if ((pwuid != NULL) && (pwuid->pw_name != NULL)) { @@ -219,4 +227,9 @@ void oeLnxAppDatabase::get_user_name(char *buffer, size_t *size) { buffer[(*size) - 1] = '\0'; *size = strlen(buffer); } +#else +DWORD unamelen = 0; +GetUserName(buffer, &unamelen); +*size = static_cast(unamelen); +#endif } diff --git a/linux/registry.cpp b/linux/registry.cpp index 7068abe6d..21d345bcb 100644 --- a/linux/registry.cpp +++ b/linux/registry.cpp @@ -55,6 +55,10 @@ #include "registry.h" #include "mono.h" +#if defined(_WIN32) +#define strcasecmp stricmp +#endif + // Convert a string that represents a hex value into an int int hextoi(char *p) { int value = 0; diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index df1f003c3..b94f5ddd9 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -10,10 +10,7 @@ set(CPPS add_library(misc STATIC ${CPPS}) target_link_libraries(misc PRIVATE ddebug - # For SDL_Assert() - $<$: - SDL2::SDL2 - > + SDL2::SDL2 ) target_include_directories(misc PUBLIC $Release(); - delete this; - return 0; - } - - ////////////////////////////// - // SetVolume - ////////////////////////////// - // Sets the volume of a buffer. - // - // Returns: - // 0 : no error - // -1 : Cannot set volume - // -2 : Invalid parameters - int SetVolume(int32_t vol) { return m_pBuffer->SetVolume(vol); } - - /////////////////////////// - // SetPan - /////////////////////////// - // Sets the pan of a buffer. - // - // Returns: - // 0 : no error - // -1 : Cannot set pan - // -2 : Invalid parameters - int SetPan(int32_t pan) { return m_pBuffer->SetPan(pan); } - - ///////////////////////// - // Stop - ///////////////////////// - // Stops a buffer from playing - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int Stop() { return m_pBuffer->Stop(); } - - ///////////////////////// - // Play - ///////////////////////// - // Starts a buffer playing (or changes the flags for a buffer currently - // playing). - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int Play(uint32_t flags) { - DWORD dsFlags = (flags & LNXSND_LOOPING) ? DSBPLAY_LOOPING : 0; - return m_pBuffer->Play(0, 0, dsFlags); - } - - //////////////////////////// - // GetCaps - //////////////////////////// - // Get the capabilities of a sound buffer - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int GetCaps(SysSoundCaps *caps) { - DSBCAPS dsCaps; - dsCaps.dwSize = sizeof(dsCaps); - int res = m_pBuffer->GetCaps(&dsCaps); - if (res != 0) - return res; - - caps->dwBufferBytes = dsCaps.dwBufferBytes; - caps->dwFlags = dsCaps.dwFlags; - return 0; - } - - ////////////////////////////// - // GetStatus - ////////////////////////////// - // Returns the status of a buffer - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int GetStatus(uint32_t *status) { return m_pBuffer->GetStatus(reinterpret_cast(status)); } - - /////////////////////////////////////// - // GetCurrentPosition - /////////////////////////////////////// - // Returns the current play and write positions of the buffer - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int GetCurrentPosition(uint32_t *ppos, uint32_t *wpos) { - return m_pBuffer->GetCurrentPosition(reinterpret_cast(ppos), reinterpret_cast(wpos)); - } - - /////////////////////////////////////// - // SetCurrentPosition - /////////////////////////////////////// - // Sets the current play position of the buffer - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int SetCurrentPosition(uint32_t pos) { return m_pBuffer->SetCurrentPosition(pos); } - - ///////////////////////// - // Lock - ///////////////////////// - // Locks the given buffer, returning pointer(s) to the buffer(s) along with - // available the size of the buffer(s) for writing. - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int Lock(uint32_t pos, uint32_t numbytes, void **ptr1, uint32_t *numbytes1, void **ptr2, - uint32_t *numbytes2, uint32_t flags) { - return m_pBuffer->Lock(pos, numbytes, ptr1, reinterpret_cast(numbytes1), ptr2, - reinterpret_cast(numbytes2), flags); - } - - /////////////////////////// - // Unlock - /////////////////////////// - // Unlocks a buffer. - // - // Returns: - // 0 : no error - // -1 : invalid parameters - int Unlock(void *ptr1, uint32_t num1, void *ptr2, uint32_t num2) { - return m_pBuffer->Unlock(ptr1, num1, ptr2, num2); - } -}; - -class MovieSoundDevice : public ISoundDevice { -private: - LPDIRECTSOUND m_ds; - -public: - MovieSoundDevice() : m_ds(NULL) {} - - void SetDirectSound(LPDIRECTSOUND ds) { m_ds = ds; } - - LPDIRECTSOUND GetDirectSound() { return m_ds; } - - /////////////////////////////// - // CreateSoundBuffer - /////////////////////////////// - // Creates a sound buffer to be used with mixing and output. - // - // Returns: - // -1 : Invalid Parameter - // -2 : Out of memory - // 0 : Ok! - int CreateSoundBuffer(SysSoundBufferDesc *lbdesc, ISysSoundBuffer **lsndb) { - if (m_ds == NULL) - return -1; - - DSBUFFERDESC dsBufferDesc; - dsBufferDesc.dwSize = sizeof(dsBufferDesc); - dsBufferDesc.dwFlags = lbdesc->dwFlags; - dsBufferDesc.dwBufferBytes = lbdesc->dwBufferBytes; - dsBufferDesc.dwReserved = 0; - dsBufferDesc.lpwfxFormat = reinterpret_cast(lbdesc->lpwfxFormat); - - LPDIRECTSOUNDBUFFER dsSndBuffer = NULL; - int res = m_ds->CreateSoundBuffer(&dsBufferDesc, &dsSndBuffer, NULL); - if (res != DS_OK) { - *lsndb = NULL; - return res; - } - - *lsndb = new MovieSoundBuffer(dsSndBuffer); - return res; - } -}; - -#else - class MovieSoundBuffer : public ISysSoundBuffer { private: LnxSoundBuffer *m_pBuffer; @@ -427,7 +233,6 @@ class MovieSoundDevice : public ISoundDevice { } }; -#endif #endif } // namespace @@ -857,105 +662,6 @@ void mve_ClearRect(int16_t x1, int16_t y1, int16_t x2, int16_t y2) { } #ifndef NO_MOVIES -#ifdef WIN32 -// Internal function to enumerate sound devices -BOOL CALLBACK DSEnumCallback(LPGUID lp_guid, LPCSTR lpstr_description, LPCSTR lpstr_module, LPVOID lp_Context) { - GUID FAR *lp_ret_guid = (GUID FAR *)lp_Context; - - if (SoundCardName[0]) { - if (strcmp(lpstr_description, SoundCardName) == 0) { - if (lp_guid) { - memmove(lp_ret_guid, lp_guid, sizeof(GUID)); - } - - return FALSE; - } - } - - return TRUE; -} - -bool mve_InitSound(oeApplication *app, MovieSoundDevice &device) { - // Perform Direct Sound Initialization - device.SetDirectSound(NULL); - - GUID *pguid = NULL; - GUID card_guid, zero_card_guid; - ZeroMemory(&card_guid, sizeof(GUID)); - ZeroMemory(&zero_card_guid, sizeof(GUID)); - HRESULT hr = DirectSoundEnumerate(DSEnumCallback, &card_guid); - if (hr == DS_OK) { - if (memcmp(&card_guid, &zero_card_guid, sizeof(GUID)) != 0) { - pguid = &card_guid; - } - } - - LPDIRECTSOUND lpDS; - if (DirectSoundCreate(pguid, &lpDS, NULL) != DS_OK) { - return false; - } - - HWND hWnd = (HWND)((oeWin32Application *)app)->m_hWnd; - hr = lpDS->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE); - if (hr != DS_OK) { - lpDS->Release(); - return false; - } - - bool use_22k_sound = false; - - // Start Mixer - LPDIRECTSOUNDBUFFER lpPrimaryBuffer; - DSBUFFERDESC dsbd; - memset(&dsbd, 0, sizeof(DSBUFFERDESC)); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = lpDS->CreateSoundBuffer(&dsbd, &lpPrimaryBuffer, NULL); - if (hr == DS_OK) { - // set format to 44khz if requested. - WAVEFORMATEX fmt; - fmt.cbSize = sizeof(fmt); - fmt.wFormatTag = WAVE_FORMAT_PCM; - fmt.nChannels = 2; - fmt.wBitsPerSample = 16; - fmt.nSamplesPerSec = use_22k_sound ? 22050 : 44100; - fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8); - fmt.nAvgBytesPerSec = ((DWORD)fmt.nSamplesPerSec) * ((DWORD)fmt.nBlockAlign); - hr = lpPrimaryBuffer->SetFormat(&fmt); - if (hr != DS_OK) { - lpPrimaryBuffer->Release(); - lpDS->Release(); - lpDS = NULL; - return false; - } - - hr = lpPrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING); - if (hr != DS_OK) { - lpPrimaryBuffer->Release(); - lpDS->Release(); - return false; - } - - lpPrimaryBuffer->Release(); - } else { - lpDS->Release(); - return false; - } - - device.SetDirectSound(lpDS); - MVE_sndInit(&device); - - return true; -} - -void mve_CloseSound(MovieSoundDevice &device) { - LPDIRECTSOUND ds = device.GetDirectSound(); - if (ds) { - ds->Release(); - device.SetDirectSound(NULL); - } -} -#else bool mve_InitSound(oeApplication *app, MovieSoundDevice &device) { LnxSoundDevice snddev; @@ -975,6 +681,5 @@ bool mve_InitSound(oeApplication *app, MovieSoundDevice &device) { void mve_CloseSound(MovieSoundDevice &device) { // TODO: close the driver out } -#endif #endif diff --git a/networking/CMakeLists.txt b/networking/CMakeLists.txt index aae004327..9fcc29c49 100644 --- a/networking/CMakeLists.txt +++ b/networking/CMakeLists.txt @@ -6,9 +6,14 @@ set(CPPS > ) +if(WIN32) + set(PLATFORM_LIBS ${DXGUID_LIBRARY}) +endif() + add_library(networking STATIC ${HEADERS} ${CPPS}) target_link_libraries(networking PRIVATE ddio mem misc + ${PLATFORM_LIBS} ) diff --git a/renderer/CMakeLists.txt b/renderer/CMakeLists.txt index 248f799bb..5c161cb16 100644 --- a/renderer/CMakeLists.txt +++ b/renderer/CMakeLists.txt @@ -12,12 +12,9 @@ set(CPPS HardwarePoints.cpp HardwareSetup.cpp HardwareTransforms.cpp + lnxscreenmode.cpp ) -if(UNIX) - set(CPPS ${CPPS} lnxscreenmode.cpp) -endif() - # These are excluded. #opengl.cpp #renderer.cpp @@ -25,6 +22,7 @@ endif() add_library(renderer STATIC ${HEADERS} ${CPPS}) target_link_libraries(renderer PRIVATE + SDL2::SDL2 bitmap ddio mem diff --git a/renderer/HardwareOpenGL.cpp b/renderer/HardwareOpenGL.cpp index 259c0ac33..8e85bc894 100644 --- a/renderer/HardwareOpenGL.cpp +++ b/renderer/HardwareOpenGL.cpp @@ -16,14 +16,17 @@ * along with this program. If not, see . */ -#include "byteswap.h" +#include +#include +#include +#include +#include + #if defined(WIN32) #include -#elif defined(__LINUX__) -#include "lnxscreenmode.h" -#else #endif +#include "byteswap.h" #include "pserror.h" #include "mono.h" #include "3d.h" @@ -36,13 +39,9 @@ #include "mem.h" #include "config.h" #include "rtperformance.h" -#include -#include -#include #include "HardwareInternal.h" #include "../Descent3/args.h" - -#include +#include "NewBitmap.h" #define DECLARE_OPENGL #include "dyna_gl.h" @@ -51,13 +50,9 @@ #include "win/arb_extensions.h" #endif -#include - int FindArg(const char *); void rend_SetLightingState(light_state state); -#define CHANGE_RESOLUTION_IN_FULLSCREEN - // General renderer states extern int gpu_Overlay_map; int Bump_map = 0; @@ -69,9 +64,6 @@ extern uint8_t Renderer_initted; renderer_type Renderer_type = RENDERER_OPENGL; int WindowGL = 0; -extern matrix Unscaled_matrix; -extern vector View_position; - #ifndef GL_UNSIGNED_SHORT_5_5_5_1 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #endif @@ -82,18 +74,9 @@ extern vector View_position; #define CHECK_ERROR(x) -#if defined(WIN32) -// Moved from DDGR library -static HWND hOpenGLWnd = NULL; -static HDC hOpenGLDC = NULL; -HGLRC ResourceContext; -static WORD Saved_gamma_values[256 * 3]; -#elif defined(__LINUX__) SDL_Window *GSDLWindow = NULL; SDL_GLContext GSDLGLContext = NULL; char loadedLibrary[_MAX_PATH]; -#else -#endif #define GET_WRAP_STATE(x) (x >> 4) #define GET_FILTER_STATE(x) (x & 0x0f) @@ -406,103 +389,6 @@ void opengl_SetDefaults() { } } -#if defined(WIN32) -// Check for OpenGL support, -int opengl_Setup(HDC glhdc) { - if (!Already_loaded) { - if (!(OpenGLDLLHandle = LoadOpenGLDLL("opengl32.dll"))) { - rend_SetErrorMessage("Failed to load opengl dll!\n"); - Int3(); - return 0; - } - } - - // Finds an acceptable pixel format to render to - PIXELFORMATDESCRIPTOR pfd, pfd_copy; - int pf; - - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED; - pfd.iPixelType = PFD_TYPE_RGBA; - - /*if (!WindowGL) - { - if (gpu_preferred_state.bit_depth==32) - { - pfd.cColorBits = 32; - pfd.cDepthBits = 32; - } - else - { - pfd.cColorBits = gpu_preferred_state.bit_depth; - pfd.cDepthBits =gpu_preferred_state.bit_depth; - } - - pfd.cColorBits = 16; - pfd.cDepthBits =16; - - } - else - { - pfd.cColorBits = 16; - pfd.cDepthBits =16; - }*/ - - // Find the user's "best match" PFD - pf = ChoosePixelFormat(glhdc, &pfd); - if (pf == 0) { - Int3(); - // FreeLibrary(opengl_dll_handle); - return NULL; - } - - mprintf(0, "Choose pixel format successful!\n"); - - // Try and set the new PFD - if (SetPixelFormat(glhdc, pf, &pfd) == FALSE) { - DWORD ret = GetLastError(); - Int3(); - // FreeLibrary(opengl_dll_handle); - return NULL; - } - - mprintf(0, "SetPixelFormat successful!\n"); - - // Get a copy of the newly set PFD - if (DescribePixelFormat(glhdc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd_copy) == 0) { - Int3(); - // FreeLibrary(opengl_dll_handle); - return NULL; - } - - // Check the returned PFD to see if it is hardware accelerated - if ((pfd_copy.dwFlags & PFD_GENERIC_ACCELERATED) == 0 && (pfd_copy.dwFlags & PFD_GENERIC_FORMAT) != 0) { - Int3(); - // FreeLibrary(opengl_dll_handle); - return NULL; - } - - // Create an OpenGL context, and make it the current context - ResourceContext = dwglCreateContext((HDC)glhdc); - if (ResourceContext == NULL) { - DWORD ret = GetLastError(); - // FreeLibrary(opengl_dll_handle); - Int3(); - return NULL; - } - - ASSERT(ResourceContext != NULL); - mprintf(0, "Making context current\n"); - dwglMakeCurrent((HDC)glhdc, ResourceContext); - - Already_loaded = 1; - - return 1; -} -#elif defined(__LINUX__) - extern bool linux_permit_gamma; extern renderer_preferred_state Render_preferred_state; extern bool ddio_mouseGrabbed; @@ -560,13 +446,18 @@ int opengl_Setup(oeApplication *app, int *width, int *height) { OpenGLDLLHandle = LoadOpenGLDLL(gl_library); if (!(OpenGLDLLHandle)) { // rcg07072000 last ditch effort... - OpenGLDLLHandle = LoadOpenGLDLL("libGL.so.1"); +#ifdef __LINUX__ + strcpy(gl_library, "libGL.so.1"); +#else + strcpy(gl_library, "opengl32.dll"); +#endif + OpenGLDLLHandle = LoadOpenGLDLL(gl_library); if (!(OpenGLDLLHandle)) { success = false; } } // if - if (success == false) { + if (!success) { char buffer[512]; snprintf(buffer, sizeof(buffer), "Failed to load library [%s].\n", gl_library); fprintf(stderr, "%s", buffer); @@ -743,7 +634,6 @@ int opengl_Setup(oeApplication *app, int *width, int *height) { Already_loaded = 1; return 1; } -#endif // Sets up our OpenGL rendering context // Returns 1 if ok, 0 if something bad @@ -763,104 +653,7 @@ int opengl_Init(oeApplication *app, renderer_preferred_state *pref_state) { } int windowX = 0, windowY = 0; -#if defined(WIN32) - /*********************************************************** - * WINDOWS OPENGL - *********************************************************** - */ - static HWnd hwnd = NULL; - if (ParentApplication != NULL) { - hwnd = static_cast(reinterpret_cast(ParentApplication)->m_hWnd); - } - - if (!WindowGL) { - // First set our display mode - // Create direct draw surface - - DEVMODE devmode; - devmode.dmSize = sizeof(devmode); - devmode.dmBitsPerPel = 32; - // devmode.dmBitsPerPel=gpu_preferred_state.bit_depth; - devmode.dmPelsWidth = gpu_preferred_state.width; - devmode.dmPelsHeight = gpu_preferred_state.height; - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - -#ifdef CHANGE_RESOLUTION_IN_FULLSCREEN - int retval = ChangeDisplaySettings(&devmode, 0); -#else - int retval = DISP_CHANGE_SUCCESSFUL; -#endif - if (retval != DISP_CHANGE_SUCCESSFUL) { - mprintf(0, "Display mode change failed (err=%d), trying default!\n", retval); - retval = -1; - devmode.dmBitsPerPel = 32; - devmode.dmPelsWidth = 640; - devmode.dmPelsHeight = 480; - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - - retval = ChangeDisplaySettings(&devmode, 0); - if (retval != DISP_CHANGE_SUCCESSFUL) { - mprintf(0, "OpenGL_INIT:Change display setting failed failed!\n"); - rend_SetErrorMessage("OGL: ChangeDisplaySettings failed. Make sure your desktop is set to 16bit mode!"); - ChangeDisplaySettings(NULL, 0); - opengl_Close(); - return 0; - } else { - gpu_preferred_state.bit_depth = 32; - gpu_preferred_state.width = 640; - gpu_preferred_state.height = 480; - } - } else { - mprintf(0, "Setdisplaymode to %d x %d (%d bits) is successful!\n", gpu_preferred_state.width, - gpu_preferred_state.height, gpu_preferred_state.bit_depth); - } - } - - memset(&gpu_state, 0, sizeof(rendering_state)); - - // These values are set here - samir - if (app != NULL) { - hOpenGLWnd = (HWND)((oeWin32Application *)app)->m_hWnd; - } - - hOpenGLDC = GetDC(hOpenGLWnd); - - if (WindowGL) { - RECT rect; - POINT topLeft; - GetClientRect((HWND)hOpenGLWnd, &rect); - - topLeft.x = rect.left; - topLeft.y = rect.top; - ClientToScreen((HWND)hOpenGLWnd, &topLeft); - - width = rect.right - rect.left + 1; - height = rect.bottom - rect.top + 1; - windowX = topLeft.x; - windowY = topLeft.y; - } else { - SetWindowPos(hOpenGLWnd, HWND_TOPMOST, 0, 0, gpu_preferred_state.width, gpu_preferred_state.height, - SWP_FRAMECHANGED); - width = gpu_preferred_state.width; - height = gpu_preferred_state.height; - RECT rect; - GetWindowRect((HWND)hOpenGLWnd, &rect); - mprintf(0, "rect=%d %d %d %d\n", rect.top, rect.right, rect.bottom, rect.left); - } - - gpu_state.screen_width = width; - gpu_state.screen_height = height; - - if (!opengl_Setup(hOpenGLDC)) { - opengl_Close(); - return 0; - } - - // Save gamma values for later - GetDeviceGammaRamp(hOpenGLDC, (LPVOID)Saved_gamma_values); - -#elif defined(__LINUX__) /*********************************************************** * LINUX OPENGL *********************************************************** @@ -877,10 +670,7 @@ int opengl_Init(oeApplication *app, renderer_preferred_state *pref_state) { memset(&gpu_state, 0, sizeof(rendering_state)); gpu_state.screen_width = width; gpu_state.screen_height = height; -#else - // Setup gpu_state.screen_width & gpu_state.screen_height & width & height -#endif // Get some info opengl_GetInformation(); @@ -1056,34 +846,18 @@ void opengl_Close(const bool just_resizing) { mem_free(delete_list); -#if defined(WIN32) - if (dwglMakeCurrent) - dwglMakeCurrent(NULL, NULL); - - if (dwglDeleteContext) - dwglDeleteContext(ResourceContext); - - // Change our display back - if (!WindowGL) { -#ifdef CHANGE_RESOLUTION_IN_FULLSCREEN - ChangeDisplaySettings(NULL, 0); -#endif + if (GSDLGLContext) { + SDL_GL_MakeCurrent(NULL, NULL); + SDL_GL_DeleteContext(GSDLGLContext); + GSDLGLContext = NULL; + GOpenGLFBOWidth = GOpenGLFBOHeight = GOpenGLFBO = GOpenGLRBOColor = GOpenGLRBODepth = 0; } -#elif defined(__LINUX__) - if (GSDLGLContext) { - SDL_GL_MakeCurrent(NULL, NULL); - SDL_GL_DeleteContext(GSDLGLContext); - GSDLGLContext = NULL; - GOpenGLFBOWidth = GOpenGLFBOHeight = GOpenGLFBO = GOpenGLRBOColor = GOpenGLRBODepth = 0; - } - if (!just_resizing && GSDLWindow) { - SDL_DestroyWindow(GSDLWindow); - GSDLWindow = NULL; - } -#else + if (!just_resizing && GSDLWindow) { + SDL_DestroyWindow(GSDLWindow); + GSDLWindow = NULL; + } -#endif if (OpenGL_packed_pixels) { if (opengl_packed_Upload_data) { @@ -1118,16 +892,6 @@ void opengl_Close(const bool just_resizing) { OpenGL_cache_initted = 0; } -#if defined(WIN32) - // Restore gamma values - SetDeviceGammaRamp(hOpenGLDC, (LPVOID)Saved_gamma_values); - // I'm freeing the DC here - samir - ReleaseDC(hOpenGLWnd, hOpenGLDC); -#elif defined(__LINUX__) - -#else - -#endif // mod_FreeModule (OpenGLDLLHandle); gpu_state.initted = 0; } @@ -1577,26 +1341,6 @@ void rend_SetGammaValue(float val) { gpu_preferred_state.gamma = val; mprintf(0, "Setting gamma to %f\n", val); - -#if defined(WIN32) - WORD rampvals[3 * 256]; - - for (int i = 0; i < 256; i++) { - float norm = (float)i / 255.0f; - - float newval = powf(norm, 1.0f / val); - - newval *= 65535; - - newval = std::min(65535, newval); - - rampvals[i] = newval; - rampvals[i + 256] = newval; - rampvals[i + 512] = newval; - } - - SetDeviceGammaRamp(hOpenGLDC, (LPVOID)rampvals); -#endif } // Resets the texture cache @@ -1967,16 +1711,8 @@ void rend_Flip(void) { // if we're rendering to an FBO, scale to the window framebuffer! if (GOpenGLFBO != 0) { - #if defined(WIN32) - // !!! FIXME: is this expensive? - RECT rectWindow; // rectangle for the client area of the window - GetClientRect(hOpenGLWnd, &rectWindow); - int w = (int) (rectWindow.right - rectWindow.left); - int h = (int) (rectWindow.bottom - rectWindow.top); - #else int w, h; SDL_GL_GetDrawableSize(GSDLWindow, &w, &h); - #endif int scaledHeight, scaledWidth; if (w < h) { @@ -1999,11 +1735,7 @@ void rend_Flip(void) { dglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } -#if defined(WIN32) - SwapBuffers((HDC)hOpenGLDC); -#elif defined(__LINUX__) SDL_GL_SwapWindow(GSDLWindow); -#endif // go back to drawing on the FBO until we want to blit to the window framebuffer again. if (GOpenGLFBO != 0) { diff --git a/renderer/dyna_gl.h b/renderer/dyna_gl.h index 17e9d871d..2e7aa32b3 100644 --- a/renderer/dyna_gl.h +++ b/renderer/dyna_gl.h @@ -18,12 +18,15 @@ #pragma once +#include + #if defined(WIN32) -#include +#include #else -#include "SDL_opengl.h" +#include #endif +#include "descent.h" #include "module.h" #if defined(WIN32) @@ -31,8 +34,6 @@ #elif defined(__LINUX__) #include #define GLFUNCCALL -#else -#define GLFUNCCALL #endif // ryan's adds. 04/18/2000. @@ -219,18 +220,17 @@ DYNAEXTERN(glBlitFramebufferEXT_fp, dglBlitFramebufferEXT); #ifdef DECLARE_OPENGL static module OpenGLDLLInst; -#ifdef __LINUX__ static void *__SDL_mod_GetSymbol(const char *funcStr) { void *retVal = NULL; - mprintf(0, "Looking up GL function [%s]...", funcStr); + mprintf(0, "Looking up GL function [%s]... ", funcStr); retVal = SDL_GL_GetProcAddress(funcStr); if (retVal == NULL) fprintf(stderr, " Could not find GL symbol [%s]!\n\n", funcStr); else { - mprintf(0, "Found at (%p).", retVal); + mprintf(0, "Found at (%p).\n", retVal); } // else return (retVal); @@ -240,20 +240,16 @@ static void *__SDL_mod_GetSymbol(const char *funcStr) { #define mod_GetSymbol(x, funcStr, y) __SDL_mod_GetSymbol(funcStr) /****************** WARNING: NASTY HACK! ***********************/ -#endif - -#ifdef __LINUX__ -extern char *__orig_pwd; extern char loadedLibrary[_MAX_PATH]; -#endif + module *LoadOpenGLDLL(const char *dllname) { mprintf(0, "Loading OpenGL dll...\n"); -#ifdef __LINUX__ - char *tmp = getcwd(NULL, 0); - chdir(__orig_pwd); - int rc = SDL_GL_LoadLibrary(dllname[0] ? dllname : NULL); - chdir(tmp); - free(tmp); + + std::filesystem::path tmp = std::filesystem::current_path(); + std::filesystem::current_path(orig_pwd); + int rc = SDL_GL_LoadLibrary(dllname[0] ? dllname : nullptr); + std::filesystem::current_path(tmp); + if (rc < 0) { const char *sdlErr = SDL_GetError(); mprintf(0, "OpenGL: Couldn't open library [%s].\n", dllname[0] ? dllname : "system default"); @@ -263,13 +259,6 @@ module *LoadOpenGLDLL(const char *dllname) { strcpy(loadedLibrary, dllname); -#else - if (!mod_LoadModule(&OpenGLDLLInst, dllname, MODF_LAZY | MODF_GLOBAL)) { - int err = mod_GetLastError(); - mprintf(0, "Couldn't open module called %s\n", dllname); - return NULL; - } -#endif dglAlphaFunc = (glAlphaFunc_fp)mod_GetSymbol(&OpenGLDLLInst, "glAlphaFunc", 255); if (!dglAlphaFunc) diff --git a/sndlib/CMakeLists.txt b/sndlib/CMakeLists.txt index a194d455a..6f9ad8d3a 100644 --- a/sndlib/CMakeLists.txt +++ b/sndlib/CMakeLists.txt @@ -4,17 +4,9 @@ set(CPPS soundload.cpp ddsoundload.cpp ssl_lib.cpp - $<$: - ds3dlib.cpp - ds3dgeometry.cpp - dsound3d.cpp - eax.cpp - > - $<$: - mixer.cpp - sdlgeometry.cpp - sdlsound.cpp - > + mixer.cpp + sdlgeometry.cpp + sdlsound.cpp ) add_library(sndlib STATIC ${CPPS}) @@ -24,6 +16,7 @@ target_link_libraries(sndlib PRIVATE mem misc stream_audio + SDL2::SDL2 ) target_include_directories(sndlib PUBLIC $. - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Source: $ - * $Revision: 8 $ - * $Author: Jeff $ - * $Date: 10/21/99 9:28p $ - * - * Hardware occlusion and reflection sound support - * - * $Log: /DescentIII/Main/dd_sndlib/geometry.cpp $ - * - * 8 10/21/99 9:28p Jeff - * B.A. Macintosh code merge - * - * 7 8/13/99 2:00p Samir - * more aureal and geometry fixes. - * - * 6 8/11/99 3:12p Samir - * fixes for aureal support. - * - * 5 4/13/99 4:09p Samir - * more priority stuff. - * - * 4 4/06/99 8:30p Samir - * added reflection support. - * - * 3 3/30/99 5:36p Matt - * Fixed compile warnings - * - * 2 3/29/99 10:52a Samir - * occlusion support almost complete. - * - */ - -#include "ds3dlib_internal.h" -#include "auddev.h" -#include "pserror.h" - -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -llsGeometry::llsGeometry() { - m_snd_system = NULL; - m_snd_mixer = SOUND_MIXER_NONE; - m_lib_init = false; -} - -// specify a sound library to associate geometry with -bool llsGeometry::Init(llsSystem *snd_sys) { - int i; - - if (m_lib_init) { - Int3(); // really, this shouldn't happen. - return true; - } - if (!snd_sys) { - Int3(); - return false; - } - - if (!m_lib_init) { - mprintf(0, "DDSNDGEO: Failed to initialize geometry interface.\n"); - return false; - } - - m_snd_mixer = snd_sys->GetSoundMixer(); - - m_snd_system = snd_sys; - m_lib_init = true; - - // create material list. - for (i = 0; i < SNDGEO_MATERIAL_COUNT; i++) { - m_snd_materials[i] = NULL; - } - - CreateMaterial(SNDGEO_MATERIAL_ROCK, 0.2f, 0.5f, 0.9f, 0.8f); - CreateMaterial(SNDGEO_MATERIAL_WATER, 1.0f, 0.3f, 0.8f, 0.7f); - CreateMaterial(SNDGEO_MATERIAL_METAL, 0.1f, 0.1f, 0.95f, 0.85f); - - mprintf(0, "DDSNDGEO: Initialized.\n"); - return true; -} - -// closes low level geometry system. -void llsGeometry::Shutdown() { - int i; - - if (!m_lib_init) { // damn this shouldn't happen. - Int3(); - return; - } - - // destroy materials list - for (i = 0; i < SNDGEO_MATERIAL_COUNT; i++) { - DestroyMaterial(i); - } - - m_snd_mixer = SOUND_MIXER_NONE; - m_snd_system = NULL; - m_lib_init = false; - - mprintf(0, "DDSNDGEO: Shutdown.\n"); -} - -void llsGeometry::StartFrame() { - n_primatives_used = 0; - n_reflections_used = 0; - n_materials_used = 0; -} - -void llsGeometry::EndFrame() { - mprintf_at(3, 4, 20, "sndpoly=%04d", n_primatives_used); - mprintf_at(3, 4, 38, "sndmat=%04d", n_materials_used); - mprintf_at(3, 5, 20, "sndref=%04d", n_reflections_used); -} - -// polygon lists - -// marks beginning of a list of polygons to render -// -1 group if non cached (user doesn't want to reuse this. -void llsGeometry::StartPolygonGroup(int group) { - ASSERT(m_lib_init); -} - -// ends a list of polygons to render. -void llsGeometry::EndPolygonGroup(int group) { - ASSERT(m_lib_init); -} - -// renders a group. -void llsGeometry::RenderGroup(int group) { - ASSERT(m_lib_init); -} - -void llsGeometry::Clear() { - ASSERT(m_lib_init); -} - -// primatives -// 4 verts here. -void llsGeometry::AddQuad(unsigned tag, vector **verts) { - n_primatives_used++; -} - -// 3 verts here. -void llsGeometry::AddTriangle(unsigned tag, vector **verts) { - n_primatives_used++; -} - -void llsGeometry::AddPoly(int nv, vector **verts, unsigned tag, tSoundMaterial material) { - int i, saved_primatives_used; //,p; - void *matp = NULL; - - if (nv < 3) { - Int3(); - return; - } - - if (material >= 0 && material < SNDGEO_MATERIAL_COUNT) { - matp = m_snd_materials[material]; - } - - if (matp) { - n_materials_used++; - } - saved_primatives_used = n_primatives_used; - - // add polygons or split. - switch (nv) { - case 3: - AddTriangle(tag, verts); - break; - case 4: - AddQuad(tag, verts); - break; - default: - Int3(); - } - - if (matp) { - n_reflections_used += (n_primatives_used - saved_primatives_used); - } -} - -// values MUST be from 0 to 1 for gain and highfreq. -void llsGeometry::CreateMaterial(tSoundMaterial material, float transmit_gain, float transmit_highfreq, - float reflect_gain, float reflect_highfreq) { - if (m_snd_materials[material] || material < 0 || material >= SNDGEO_MATERIAL_COUNT) { - Int3(); // get samir, trying to intiialize a material in an existing slot. - return; - } - - // check values. - if (transmit_gain < 0) { - transmit_gain = 0; - } else if (transmit_gain > 1) { - transmit_gain = 1; - } - if (transmit_highfreq < 0) { - transmit_highfreq = 0; - } else if (transmit_highfreq > 1) { - transmit_highfreq = 1; - } - if (reflect_gain < 0) { - reflect_gain = 0; - } else if (reflect_gain > 1) { - reflect_gain = 1; - } - if (reflect_highfreq < 0) { - reflect_highfreq = 0; - } else if (reflect_highfreq > 1) { - reflect_highfreq = 1; - } -} - -void llsGeometry::DestroyMaterial(tSoundMaterial material) { - if (!m_snd_materials[material]) { - if (material < 0 || material >= SNDGEO_MATERIAL_COUNT) { - Int3(); // get samir, trying to destroy a material in an nonexisting slot. - } - return; - } - - if (m_snd_materials[material]) { - m_snd_materials[material] = NULL; - } -} diff --git a/sndlib/ds3dlib.cpp b/sndlib/ds3dlib.cpp deleted file mode 100644 index 7f8e97761..000000000 --- a/sndlib/ds3dlib.cpp +++ /dev/null @@ -1,3312 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Logfile: /DescentIII/Main/dd_sndlib/Ds3dlib.cpp $ - * $Revision: 149 $ - * $Date: 9/27/99 5:38p $ - * $Author: Samir $ - * - * DirectSound(2d and 3d) implementation of the Descent III low-level sound interface - * - * $Log: /DescentIII/Main/dd_sndlib/Ds3dlib.cpp $ - * - * 149 9/27/99 5:38p Samir - * EAX 2.0->1.0 compatibility checkin. - * - * 148 8/23/99 5:29p Samir - * incremental EAX 2.0 checkin - * - * 147 8/13/99 2:00p Samir - * more aureal and geometry fixes. - * - * 146 5/23/99 12:48a Samir - * decreased rolloff factor of 3d sounds under 3d sound mixers from 0.75 - * to 0.5 - * - * 145 5/20/99 6:23p Kevin - * minor speed up of software mixer and fix for memory debugging - * - * 144 5/20/99 1:00a Samir - * changes in ordering of EAX and NONE mixers. - * - * 143 5/09/99 7:09p Samir - * fixed sound card selection (enumeration) problems. - * - * 142 5/07/99 5:39p Samir - * better error checking for CheckAndForceDataAlloc for PageInSound. - * - * 141 5/03/99 3:12a Samir - * fixed up aureal so it works (a little slow though...) - * - * 140 5/01/99 10:25p Jeff - * (samir) fixed crash bug when alt-tabbing,inserting cds,etc - * - * 139 4/29/99 4:36p Kevin - * fixed a problem with low quality sounds & the optimizd software mixer - * - * 138 4/29/99 3:01p Samir - * added code for direct sound mixers only (and function for Aureal - * really) that will use direct sound looping for simple loops. - * - * 137 4/27/99 7:08p Kevin - * optimized software mixer! - * - * 136 4/27/99 6:21p Samir - * if callback gets a NULL guid, just return, assume that the sound device - * is the default? - * - * 135 4/27/99 5:19p Samir - * mprintf change. - * - * 134 4/27/99 2:10p Samir - * added code to set the desired sound card given the descriptive name of - * a sound card. - * - * 133 4/25/99 9:52p Samir - * fixed looping sequencing bug with thread for direct sound mixers. - * SSF_PLAY_LOOPING must be set before any buffer filling occurs, - * otherwise bad things happen with very small loops.... - * - * 132 4/23/99 7:51p Samir - * looping fixes for directsound - * - * 131 4/22/99 10:33p Samir - * modifications so that DirectSound mixers use one thread for all looping - * and streaming sounds. It worked without crashing for about twenty - * minutes of playing from level 1 to level 2 of D3. We'll see. - * - * 130 4/18/99 5:37p Kevin - * Very simple optimization for the software mixer - * - * 129 4/13/99 4:15p Jason - * took out register keyword because it was hurting performance - * - * 128 4/13/99 4:09p Samir - * more priority stuff. - * - * - * 126 4/12/99 7:14p Samir - * prioritization code added. - * - * 125 4/10/99 5:08p Samir - * took out obsolete data from play_information structure that should save - * around 70 bytes per instance. - * - * 124 4/09/99 5:00p Kevin - * put the memset in -- memset should be doing at least 32 bit copies, - * which is FAR better than a for loop. - * - * 123 4/09/99 12:03p Samir - * took out windows.h again, this time made HWND a void pointer, and - * checked under both editor and main projects. - * - * 122 4/06/99 8:29p Samir - * added error check system. - * - * 121 3/29/99 11:00a Samir - * added system to support different 3d sound options. - * - * 120 3/17/99 4:20p Samir - * added functions to pause and resume individual sounds. - * - * 119 3/04/99 1:23p Kevin - * Fixed Poping sound!!! - * - * 118 3/03/99 6:53p Matt - * Fixed compile warning - * - * 117 3/03/99 3:12p Chris - * Fixed volume problems - * - * 116 3/01/99 8:12p Samir - * pause sounds when switching sound quality! - * - * 115 2/25/99 4:50p Kevin - * Semi-hack to fix the problem with music looping and stuttering in DS - * - * 114 2/24/99 3:15p Kevin - * OEM menu changes, and bug fixes for the save/load system - * - * 113 2/22/99 6:28p Kevin - * Fixed a bug that was introduced (?) when the thread problem was fixed. - * - * 112 2/20/99 1:14a Kevin - * Fixed another bug - * - * 111 2/19/99 10:45p Kevin - * Fixed bug I just introduced... - * - * 110 2/19/99 5:21p Kevin - * Fixed some connection DLLs and a Direct Sound bug with threads. - * - * 109 2/11/99 3:30p Doug - * error checking in PlaySoundBuffer. - * - * 108 2/04/99 9:46a Kevin - * OEM version changes - * - * 107 1/14/99 6:10p Samir - * added DirectSound buffer duplication code. - * - * 106 1/11/99 5:51p Samir - * reverb on the buffer level. - * - * 105 1/08/99 6:31p Samir - * added reverb - * - * 104 1/08/99 11:36a Samir - * implemented basic Aureal 2.0 support. - * - * 103 1/08/99 10:32a Chris - * - * 102 12/23/98 11:49a Samir - * reorganized code so it works with different APIs. - * - * 101 12/11/98 5:21p Samir - * (chris) fixed problem with software streaming audio. - * - * 100 12/10/98 3:16p Chris - * added mprintfs for later use - * - * 99 12/10/98 2:18p Chris - * Added more asserts to the streaming code - * - * 98 11/13/98 4:55p Nate - * don't do dedicated server check in lowlevel. - * - * 97 11/13/98 12:17p Chris - * - * 96 11/12/98 12:15p Chris - * Fixed a bug with streaming mixers - * - * 95 10/30/98 1:20p Chris - * Fixed a m_unique_id bug where it was being used before it was being - * assigned - * - * - * $NoKeywords: $ - */ - -#include "ds3dlib_internal.h" - -#include -#include -#include -#include "cfile.h" -#include "pserror.h" -#include "mono.h" -#include "soundload.h" -#include "mem.h" -#include "application.h" -#include "auddev.h" -#include "Macros.h" -#include "ddio.h" - -// Hacked window handle -- chrishack -static oeWin32Application *SoundApp = NULL; -static void *GameWindowHandle; -#define MIN_SOUND_MIX_VOLUME 0.0 -#define MAX_WRITE_AHEAD .04 // Seconds to write ahead of the play position (in seconds) - -// write position - -#define IS_3D_MIXER(_type) ((_type) >= SOUND_MIXER_DS3D_16 && (_type) != SOUND_MIXER_NONE) - -win_llsSystem *ll_sound_ptr; -emulated_listener *g_emulated_listener = NULL; // silly hack (Samir) -int16_t Global_DS_alloced_sounds = 0; - -int *Fast_mixer = NULL; -int Fast_mixer_len = 0; - -#define VOLUME_FIX_BITS 1024 - -// Streaming primary buffer information -DSSTREAM m_sb_info; -char m_sound_device_name[256] = ""; // set by set sound card - -// Loads a sound buffer with data -HRESULT LoadSoundData(LPDIRECTSOUNDBUFFER lp_dsb, char *sound_data_ptr, DWORD total_bytes); - -/////////////////////////////////////////////////////////////////////////////// - -static t3dEnvironmentValues Env3dValues; -static t3dEnvironmentToggles Env3dToggles; - -#define ENV3DTOG_DOPPLER true -#define ENV3DTOG_GEOMETRY true - -#define ENV3DVAL_DOPPLER_DEFAULT 0.5f -#define ENV3DVAL_ROLLOFF_DEFAULT 0.5f - -/////////////////////////////////////////////////////////////////////////////// - -win_llsSystem::win_llsSystem(void) : llsSystem() { - m_lp_ds = NULL; - m_f_sound_lib_init = 0; - m_hwnd_main = NULL; - m_mixer_type = -1; - m_sound_quality = SQT_NORMAL; - m_cache_stress_timer = 0.0f; - ll_sound_ptr = NULL; - m_timer_last_frametime = -1; - memset(&Env3dValues, 0, sizeof(Env3dValues)); - memset(&Env3dToggles, 0, sizeof(Env3dToggles)); - SetError(SSL_OK); -} - -win_llsSystem::~win_llsSystem(void) { - DestroySoundLib(); - SetSoundCard(NULL); -} - -inline void opti_8m_mix(uint8_t *cur_sample_8bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - int l_sample; - int r_sample; - - sample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - - l_sample = *mb + (sample * fix_lvol); - r_sample = *(mb + 1) + (sample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_8s_mix(uint8_t *cur_sample_8bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int lsample; - int rsample; - int l_sample; - int r_sample; - - lsample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - rsample = (((*cur_sample_8bit)) - 128) << 8; - cur_sample_8bit++; - - l_sample = *mb + (lsample * fix_lvol); - r_sample = *(mb + 1) + (rsample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_16m_mix(int16_t *cur_sample_16bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - int l_sample; - int r_sample; - - sample = *cur_sample_16bit; - cur_sample_16bit++; - - l_sample = *mb + (sample * fix_lvol); - r_sample = *(mb + 1) + (sample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - mb++; - } - samples_played += (i / 2); -} - -inline void opti_16s_mix(int16_t *cur_sample_16bit, const int num_write, int &samples_played, int *mixer_buffer16, - const float l_volume, const float r_volume) { - int i; - int *mb = mixer_buffer16; - - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int lsample; - int rsample; - int l_sample; - int r_sample; - - lsample = *cur_sample_16bit; - cur_sample_16bit++; - rsample = *cur_sample_16bit; - cur_sample_16bit++; - - l_sample = *mb + (lsample * fix_lvol); - r_sample = *(mb + 1) + (rsample * fix_rvol); - - *mb = l_sample; - mb++; - *mb = r_sample; - *mb++; - } - samples_played += (i / 2); -} - -//////////////////////////////////////////////////////////////////////////////////// - -#define MAX_DS_PAN 1000.0f - -int GamePanToDsPan(float pan) { - int ds_pan; - ds_pan = (int)(pan * MAX_DS_PAN); - - if (ds_pan > MAX_DS_PAN) - ds_pan = MAX_DS_PAN; - if (ds_pan < -MAX_DS_PAN) - ds_pan = -MAX_DS_PAN; - - // mprintf(0, "P %f %d\n", pan, ds_pan); - return ds_pan; -} - -int GameVolumeToDsAttenuation(float volume) { - float fvol; - - if (volume <= 0.0f) { - fvol = 2000.0f; - } else { - fvol = logf(volume) / logf(10.0f); - fvol *= 2000.0; - } - - if (volume <= 0.01f) { - fvol = DSBVOLUME_MIN; - } - - // mprintf(0, "V %f %f\n", volume, fvol); - return (int)fvol; -} - -//////////////////////////////////////////////////////////////////////////////////// - -inline char *get_sound_info(sound_buffer_info *sb, int *length, bool *f16bit) { - if (sb->m_sound_index < 0) { - if (sb->s) { - *f16bit = sb->s->f_sample_16bit; - } - return NULL; - } - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_8bit) { - *length = SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length; - *f16bit = false; - return (char *)SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_8bit; - } else { - ASSERT(SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_16bit); - *f16bit = true; - *length = SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length * 2; - return (char *)SoundFiles[Sounds[sb->m_sound_index].sample_index].sample_16bit; - } -} - -////////////////////////////////////////////////////////////////////////////////// -#define SB_STATUS_PLAYING 0x1 -#define SB_STATUS_INVALID 0x2 - -inline int sb_get_status(sound_buffer_info *sb) { - int retflags = 0; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - LPDIRECTSOUNDBUFFER sound_ptr = sb->m_sound_buffer; - unsigned long status; - - if (sound_ptr) { - sound_ptr->GetStatus(&status); - if (status & DSBSTATUS_PLAYING) - retflags |= SB_STATUS_PLAYING; - } else { - retflags |= SB_STATUS_INVALID; - } - } - - return retflags; -} - -inline void sb_adjust_properties_3d(sound_buffer_info *sb, float f_volume, pos_state *pos, float reverb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - sb->m_volume = f_volume; - - if (IS_3D_MIXER(sb->m_mixer_type)) { - LPDIRECTSOUNDBUFFER lp_dsb = sb->m_sound_buffer; - LPDIRECTSOUND3DBUFFER lpDSB3D = sb->m_sound_buffer_3d; - - lp_dsb->SetVolume(GameVolumeToDsAttenuation(f_volume)); - - ASSERT(lpDSB3D != NULL); - - if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - lpDSB3D->SetMinDistance(30.0f, DS3D_IMMEDIATE); - } else { - lpDSB3D->SetMinDistance(Sounds[sb->m_sound_index].min_distance, DS3D_IMMEDIATE); - } - lpDSB3D->SetMaxDistance(Sounds[sb->m_sound_index].max_distance, DS3D_IMMEDIATE); - lpDSB3D->SetConeOrientation(pos->orient->fvec.x, pos->orient->fvec.y, pos->orient->fvec.z, DS3D_IMMEDIATE); - lpDSB3D->SetPosition(pos->position->x, pos->position->y, pos->position->z, DS3D_IMMEDIATE); - lpDSB3D->SetVelocity(pos->velocity->x, pos->velocity->y, pos->velocity->z, DS3D_IMMEDIATE); - - // if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - // EAX_SetBufferReverbMix(lpDSB3D, reverb); - // } - } else { - mprintf(0, "m_mixer_type = %d\n", sb->m_mixer_type); - Int3(); - } -} - -inline void sb_adjust_properties_2d(sound_buffer_info *sb, float f_volume, float f_pan, uint16_t frequency) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - sb->m_volume = f_volume; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - LPDIRECTSOUNDBUFFER lpdsb; - - ASSERT(f_pan >= -1.0f && f_pan <= 1.0f); - ASSERT(f_volume >= 0.0f && f_volume <= 1.0f); - - lpdsb = sb->m_sound_buffer; - if (lpdsb == NULL) - return; - - // mprintf(0, "Sound UID %d is now at %d volume,%d pan\n", sound_uid, volume, pan); - - lpdsb->SetVolume(GameVolumeToDsAttenuation(f_volume)); - lpdsb->SetPan(GamePanToDsPan(f_pan)); // chrishack pan is off - lpdsb->SetFrequency(frequency); - } -} - -// functions for different APIs -int sb_get_current_position(sound_buffer_info *sb, uint32_t *writep) { - DWORD playp, wp; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->m_sound_buffer && sb->m_sound_buffer->GetCurrentPosition(&playp, &wp) == DS_OK) { - *writep = (uint32_t)wp; - } else { - playp = (DWORD)(-1); - *writep = (uint32_t)(-1); - } - } - - return (uint32_t)playp; -} - -inline void sb_set_current_position(sound_buffer_info *sb, uint32_t pos) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->SetCurrentPosition((DWORD)pos); - } -} - -void sb_free_buffer(sound_buffer_info *sb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - if (!sb->m_sound_buffer) - return; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_FreeSource(sb->m_lpksps); - } - - if (sb->m_sound_buffer) { - sb->m_sound_buffer->Release(); - sb->m_sound_buffer = NULL; - } - if (sb->m_sound_buffer_3d) { - sb->m_sound_buffer_3d->Release(); - sb->m_sound_buffer_3d = NULL; - } - } -} - -void sb_stop_buffer(sound_buffer_info *sb) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->Stop(); - } -} - -bool sb_lock_buffer(sound_buffer_info *sb, uint32_t dwWriteCursor, uint32_t dwWriteBytes, void **lplpvAudioPtr1, - uint32_t *lpdwAudioBytes1, void **lplpvAudioPtr2, uint32_t *lpdwAudioBytes2) { - DWORD len1, len2; - - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - TryLockAgainLabel: - switch (sb->m_sound_buffer->Lock(dwWriteCursor, dwWriteBytes, lplpvAudioPtr1, &len1, lplpvAudioPtr2, &len2, 0)) { - case DS_OK: - *lpdwAudioBytes1 = len1; - *lpdwAudioBytes2 = len2; - return true; - - case DSERR_BUFFERLOST: - if (sb->m_sound_buffer->Restore() == DS_OK) - goto TryLockAgainLabel; - } - - return false; - } - - return false; -} - -bool sb_unlock_buffer(sound_buffer_info *sb, void *ptr1, uint32_t len1, void *ptr2, uint32_t len2) { - if (sb->m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sb->m_sound_buffer->Unlock(ptr1, len1, ptr2, len2); - return true; - } - - return false; -} - -bool sb_load_buffer(sound_buffer_info *sb, void *sample_data, int length) { - if (!ll_sound_ptr->m_in_sound_frame) - ll_sound_ptr->m_pending_actions = true; - - if (LoadSoundData(sb->m_sound_buffer, (char *)sample_data, length) != DS_OK) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -// The actual mixer code that sum's the sounds on each channel and does all the actual -// mixing and effects (writes data to the locked primary buffer) -void StreamMixer(char *ptr, int len) { - int i; - int16_t *mixer_buffer16 = (int16_t *)ptr; - int current_slot = 0; - bool f_loop; - bool f_mono; - - const int buff_len = len / ll_sound_ptr->m_primary_alignment; - - // this code will assure that this function will not be called when sound system is in error mode. - if (ll_sound_ptr->m_lib_error_code != SSL_OK) { - return; - } - - ASSERT(len <= m_sb_info.BufferSize); - ASSERT(ptr && len >= 0); - - ASSERT((len % ll_sound_ptr->m_primary_alignment) == 0); - - // memset((char *)ptr, 0, len); - - // This memset is hopefully temporary - memset(Fast_mixer, 0, Fast_mixer_len * sizeof(int)); - int *fast_mix_ptr = Fast_mixer; - - // Mix the sound slots - while (current_slot < ll_sound_ptr->m_sound_mixer.m_max_sounds_played) { - sound_buffer_info *cur_buf = &ll_sound_ptr->m_sound_mixer.m_sound_cache[current_slot]; - int num_samples = buff_len; - // mixer_buffer16 = (int16_t *) ptr; - fast_mix_ptr = Fast_mixer; - f_mono = true; - - // Find slots with sounds in them - if ((cur_buf->m_status != SSF_UNUSED) && !(cur_buf->m_status & SSF_PAUSED)) { - float l_volume = cur_buf->play_info->left_volume; - float r_volume = cur_buf->play_info->right_volume; - int skip_interval = cur_buf->play_info->sample_skip_interval; - int samples_played = cur_buf->play_info->m_samples_played; - int16_t *sample_16bit; - uint8_t *sample_8bit; - int np_sample_length; - int sample_length; - int loop_start; - int loop_end; - - if (cur_buf->m_status & SSF_PLAY_STREAMING) { - switch (cur_buf->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - sample_8bit = NULL; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 2; - break; - case SIF_STREAMING_8_M: - sample_16bit = NULL; - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size; - break; - case SIF_STREAMING_16_S: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - sample_8bit = NULL; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 4; - f_mono = false; - break; - case SIF_STREAMING_8_S: - sample_16bit = NULL; - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - np_sample_length = sample_length = cur_buf->play_info->m_stream_size / 2; - f_mono = false; - break; - default: - Int3(); - break; - } - loop_start = 0; - loop_end = np_sample_length - 1; - } else { - int sound_index = cur_buf->m_sound_index; - int sample_index = Sounds[sound_index].sample_index; - sound_file_info *snd_file = &SoundFiles[sample_index]; - sample_16bit = snd_file->sample_16bit; - sample_8bit = snd_file->sample_8bit; - np_sample_length = snd_file->np_sample_length; - sample_length = snd_file->sample_length; - loop_start = Sounds[sound_index].loop_start; - loop_end = Sounds[sound_index].loop_end; - if (!sample_16bit && !sample_8bit) { - mprintf(0, "sound file %s didn't have data for samples.\n", snd_file->name); - } - } - - // cleanly continue if this happens, and inform a logfile, if it does. error handling - // ASSERT(sample_16bit || sample_8bit); - if (!sample_16bit && !sample_8bit) { - sound_file_info *snd_file = &SoundFiles[Sounds[cur_buf->m_sound_index].sample_index]; - ll_sound_ptr->SetError(SSL_ERROR_SAMPLE_NODATA); - ll_sound_ptr->ErrorText("ASSERT(sample_16bit || sample_8bit)\nNo data found for sound file: %s", - snd_file->name); - cur_buf->m_status = SSF_UNUSED; - goto error_bail; - } - - ASSERT(np_sample_length <= sample_length); - ASSERT(samples_played >= 0 || samples_played <= sample_length); - - int num_write; - - error_trap: - - // We have not looped -- yet - f_loop = false; - - // Verify the volume levels are o.k. - ASSERT(l_volume >= 0.0 && l_volume <= 1.0); - ASSERT(r_volume >= 0.0 && r_volume <= 1.0); - - looping: // Will go to this label to do the next iteration of a looping sample - - if (cur_buf->m_status & - (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING)) // Looping sample's process is broken up into linear pieces - { - if (f_loop) { - ASSERT(num_write >= 0); - - num_samples -= num_write; - ASSERT(num_samples > 0); - - fast_mix_ptr += (num_write * 2); - // mixer_buffer16 += num_write << 1; // update to the new start position - // (2x because of left and right channels) - - samples_played = loop_start; - } - - if (cur_buf->m_status & SSF_PLAY_LOOPING) // Looping sample's process is broken up into linear pieces - { - ASSERT(loop_end < sample_length); - if (loop_end < samples_played) { - // CHRISHACK -- Fuck milestone. Fix later. Code below is a major hack (but it works). :) - - if (loop_end != loop_start) { - while (loop_end < samples_played) { - // Int3(); - samples_played -= loop_end - loop_start; - } - - ASSERT(samples_played >= 0); - } else { - cur_buf->m_status &= ~SSF_PLAY_LOOPING; - cur_buf->m_status |= SSF_PLAY_NORMAL; - } - - goto error_trap; - } - } - // The number of samples to write to the primary buffer - num_write = ((num_samples) < (loop_end - samples_played + 1)) ? (num_samples) : (loop_end - samples_played + 1); - ASSERT(num_write >= 0 && num_write <= num_samples); - - if (num_write < num_samples) - f_loop = true; - else - f_loop = false; - - if (num_write <= 0) { - num_write = 0; - mprintf(0, "d"); - goto stream_done; - } - } else { - // The number of samples to write to the primary buffer - num_write = - ((num_samples) < (np_sample_length - samples_played)) ? (num_samples) : (np_sample_length - samples_played); - if (!(num_write > 0 && num_write <= num_samples)) { - num_write = 0; - goto done; - } - - // Optimization for silent sounds - if (l_volume <= MIN_SOUND_MIX_VOLUME && r_volume <= MIN_SOUND_MIX_VOLUME) { - cur_buf->play_info->m_samples_played += num_write; - goto done; - } - } - - if (!(num_write > 0 && num_write <= num_samples)) // this was an assert - { - num_write = 0; - mprintf(0, "D"); - goto done; - } - - // Mix at 16 bits per sample - if (skip_interval == 0) { - int16_t *cur_sample_16bit = sample_16bit; - uint8_t *cur_sample_8bit = sample_8bit; - - if (f_mono) { - if (sample_8bit) { - cur_sample_8bit += samples_played; - opti_8m_mix(cur_sample_8bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } else { - cur_sample_16bit += samples_played; - opti_16m_mix(cur_sample_16bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } - } else { - if (sample_8bit) { - cur_sample_8bit += (samples_played << 1); - opti_8s_mix(cur_sample_8bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } else { - cur_sample_16bit += (samples_played << 1); - opti_16s_mix(cur_sample_16bit, num_write, samples_played, fast_mix_ptr, l_volume, r_volume); - } - } - } else - // Account for lower-sampling rate - { - if (skip_interval == 1) { - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - - if (sample_16bit) { - if (samples_played & 0x0001) { - sample = ((int)sample_16bit[samples_played ^ 0x0001] + (int)sample_16bit[samples_played + 1]) >> 1; - } else - sample = sample_16bit[samples_played]; - } else { - if (samples_played & 0x0001) { - // Notes: (<<7) is from a (<<8) - (>>1) - // Notes: (-256) is from (-128) + (-128) - sample = ((int)sample_8bit[samples_played ^ 0x0001] + (int)sample_8bit[samples_played + 1] - 256) << 7; - } else - sample = (((int)sample_8bit[samples_played]) - (int)128) << 8; - } - - samples_played++; - - ASSERT(i >= 0 && (i + 1 < num_samples * 2)); - - int l_sample = fast_mix_ptr[i] + (sample * fix_lvol); - int r_sample = fast_mix_ptr[i + 1] + (sample * fix_rvol); - - fast_mix_ptr[i] = l_sample; - fast_mix_ptr[i + 1] = r_sample; - } - } else { - const int fix_rvol = r_volume * VOLUME_FIX_BITS; - const int fix_lvol = l_volume * VOLUME_FIX_BITS; - for (i = 0; i < (num_write << 1); i += 2) { - int sample; - const int mod_pos = samples_played % 4; - - if (sample_16bit) { - switch (mod_pos) { - case 0: - sample = sample_16bit[samples_played]; - break; - case 1: - sample = (sample_16bit[samples_played - 1] * 3 + sample_16bit[samples_played + 3]) >> 2; - break; - case 2: - sample = (sample_16bit[samples_played - 2] + sample_16bit[samples_played + 2]) >> 1; - break; - case 3: - sample = (sample_16bit[samples_played - 3] + sample_16bit[samples_played + 1] * 3) >> 2; - break; - } - } else { - switch (mod_pos) { - case 0: - sample = ((((int)sample_8bit[samples_played]) - 128) << 8); - break; - case 1: - sample = (((((int)sample_8bit[samples_played - 1]) - 128) << 8) * 3 + - ((((int)sample_8bit[samples_played + 3]) - 128) << 8)) >> - 2; - break; - case 2: - sample = (((((int)sample_8bit[samples_played - 2]) - 128) << 8) + - ((((int)sample_8bit[samples_played + 2]) - 128) << 8)) >> - 1; - break; - case 3: - sample = (((((int)sample_8bit[samples_played - 3]) - 128) << 8) + - ((((int)sample_8bit[samples_played + 1]) - 128) << 8) * 3) >> - 2; - break; - } - } - - samples_played++; - - ASSERT(i >= 0 && (i + 1 < num_samples * 2)); - - int l_sample = fast_mix_ptr[i] + (sample * fix_lvol); - int r_sample = fast_mix_ptr[i + 1] + (sample * fix_rvol); - - fast_mix_ptr[i] = l_sample; - fast_mix_ptr[i + 1] = r_sample; - } - } - } - - stream_done: - - cur_buf->play_info->m_samples_played = samples_played; - - if (cur_buf->m_status & SSF_PLAY_STREAMING) { - if (f_loop) { - if (cur_buf->play_info->m_stream_cback && cur_buf->play_info->m_stream_data) { - cur_buf->play_info->m_stream_data = (*cur_buf->play_info->m_stream_cback)( - cur_buf->play_info->user_data, cur_buf->play_info->m_stream_handle, &cur_buf->play_info->m_stream_size); -// cur_buf->s->current_position = (char*)cur_buf->play_info->m_stream_data; -// mprintf(0, "%x %d\n", cur_buf->play_info->m_stream_data, cur_buf->play_info->m_stream_size)); - ASSERT(!(cur_buf->play_info->m_stream_data && cur_buf->play_info->m_stream_size <= 0)); -/* - mprintf(0, "Data %X, length %d\n", - cur_buf->play_info->m_stream_data, - cur_buf->play_info->m_stream_size); -*/ - - if (cur_buf->play_info->m_stream_data) { - switch (cur_buf->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 2; - break; - case SIF_STREAMING_8_M: - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size; - break; - case SIF_STREAMING_16_S: - sample_16bit = (int16_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 4; - break; - case SIF_STREAMING_8_S: - sample_8bit = (uint8_t *)cur_buf->play_info->m_stream_data; - loop_end = sample_length = np_sample_length = cur_buf->play_info->m_stream_size / 2; - break; - default: - Int3(); - break; - } - loop_end -= 1; - } else { - mprintf(0, "SE: Data is NULL\n"); - cur_buf->m_status &= ~SSF_PLAY_STREAMING; - f_loop = false; - } - } else { - mprintf(0, "SE: Callback/data is NULL\n"); - cur_buf->m_status &= ~SSF_PLAY_STREAMING; - f_loop = false; - } - } - } - - if (f_loop) - goto looping; - - done: - - if (cur_buf->play_info->m_samples_played >= (np_sample_length) && - !(cur_buf->m_status & (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING))) { - ll_sound_ptr->StopSound(cur_buf->m_unique_id); - } - } - - error_bail: - current_slot++; - } - - for (int a = 0; a < (buff_len * 2); a++) { - Fast_mixer[a] = Fast_mixer[a] / VOLUME_FIX_BITS; - - if (Fast_mixer[a] > 32767) - Fast_mixer[a] = 32767; - if (Fast_mixer[a] < -32767) - Fast_mixer[a] = -32767; - - mixer_buffer16[a] = Fast_mixer[a]; - - Fast_mixer[a + 1] = Fast_mixer[a + 1] / VOLUME_FIX_BITS; - - if (Fast_mixer[a + 1] > 32767) - Fast_mixer[a + 1] = 32767; - if (Fast_mixer[a + 1] < -32767) - Fast_mixer[a + 1] = -32767; - - mixer_buffer16[a + 1] = Fast_mixer[a + 1]; - - a++; - } - // mprintf(0," -%d- ",a); -} - -// Locks the primary buffer and fills in the new data -void StreamFill(int start_byte, int num_bytes) { - char *ptr1; - char *ptr2; - int len1, len2; - - if ((num_bytes % ll_sound_ptr->m_primary_alignment) != 0) { - ll_sound_ptr->SetError(SSL_ERROR_STREAMMIXER); - ll_sound_ptr->ErrorText("ASSERT((len % ll_sound_ptr->m_primary_alignment) == 0)\nLen:%d PrA:%d", num_bytes, - ll_sound_ptr->m_primary_alignment); - return; - } - ASSERT((num_bytes % ll_sound_ptr->m_primary_alignment) == 0); - ASSERT((start_byte % ll_sound_ptr->m_primary_alignment) == 0); - - start_byte = (start_byte % m_sb_info.BufferSize); - -TryLockAgainLabel: - - switch (m_sb_info.m_lp_looping_buffer->Lock(start_byte, num_bytes, (void **)&ptr1, (DWORD *)&len1, (void **)&ptr2, - (DWORD *)&len2, 0)) { - ASSERT((len1 % ll_sound_ptr->m_primary_alignment) == 0); - ASSERT((len2 % ll_sound_ptr->m_primary_alignment) == 0); - - // The pointers are to the lock areas of the primary buffer. There are two because locked region - // might be a discontinuous chunk (wrapped around the end of the buffer i.e. 'LLLLBBBBBBLLLLL' - // L is for Locked and B is unlocked buffer. - case DS_OK: - StreamMixer(ptr1, len1); - if (ptr2) - StreamMixer(ptr2, len2); - - m_sb_info.m_lp_looping_buffer->Unlock(ptr1, len1, ptr2, len2); - - m_sb_info.NextWritePos = (start_byte + num_bytes) % m_sb_info.BufferSize; - break; - - case DSERR_BUFFERLOST: - if (m_sb_info.m_lp_primary_buffer->Restore() == DS_OK && m_sb_info.m_lp_looping_buffer->Restore() == DS_OK) - goto TryLockAgainLabel; - break; - } -} - -// A peroidic mixer that uses the primary buffer as a stream buffer -void __cdecl StreamTimer(void *user_ptr) { - int playp, writep; - int try_count = 0; - DSSTREAM *sb_info = (DSSTREAM *)user_ptr; - DWORD result; - - m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - - while (!sb_info->thread_request_kill) { - try_count = 0; - - TryAgain: - try_count++; - - // hresult = m_sb_info.m_lp_primary_buffer->GetStatus(&stat_result); - // - // if(hresult != DS_OK || !(stat_result & DSBSTATUS_LOOPING)) - // { - // m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Restore(); - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - // } - - result = sb_info->m_lp_looping_buffer->GetCurrentPosition((DWORD *)&playp, (DWORD *)&writep); - - // mprintf(0, "(%d,%d)\n", playp, writep); - - // If primary buffer was stopped from playing - if (writep == playp) { - sb_info->NextWritePos = -1; - - if ((try_count == 1) && - (m_sb_info.m_lp_primary_buffer->Restore() == DS_OK && m_sb_info.m_lp_looping_buffer->Restore() == DS_OK)) { - if ((try_count == 1) && (m_sb_info.m_lp_looping_buffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK)) { - goto TryAgain; - } - } - - goto done; - } - - // Insert mixer code - { - int num_write_bytes; - - if (sb_info->NextWritePos < 0) - sb_info->NextWritePos = writep; - - // Debugging code (not sure what would happen if we hit these without an Int3()) -- Skipping noise - if (sb_info->LastPlayPos < sb_info->NextWritePos) { - - if (playp >= sb_info->NextWritePos || playp < sb_info->LastPlayPos) { - if (!sb_info->m_f_secondary_looping) - goto done; - playp = sb_info->NextWritePos - 4; - num_write_bytes = 4 * (int)(22050 * DSPB_TICK_INTERVAL); - } else { - // Determine how much we can write out. - num_write_bytes = (sb_info->MaxWriteBytes + playp) - sb_info->NextWritePos; - } - } else { - if (playp >= sb_info->NextWritePos && playp < sb_info->LastPlayPos) { - if (!sb_info->m_f_secondary_looping) - goto done; - - playp = sb_info->NextWritePos - 4; - num_write_bytes = 4 * (int)(22050 * DSPB_TICK_INTERVAL); - } else { - // Determine how much we can write out. - if (playp < sb_info->NextWritePos) - num_write_bytes = (sb_info->MaxWriteBytes + playp) - sb_info->NextWritePos; - else - num_write_bytes = sb_info->MaxWriteBytes - (sb_info->NextWritePos + (sb_info->BufferSize - playp)); - } - } - - num_write_bytes &= (0xFFFFFFFF & (~(ll_sound_ptr->m_primary_alignment))); - - if (num_write_bytes > 0) { - // ASSERT(num_write_bytes < sb_info->BufferSize); - if (num_write_bytes >= sb_info->BufferSize) { - num_write_bytes = sb_info->BufferSize / 2; - } - - StreamFill(sb_info->NextWritePos, num_write_bytes); - } - } - - sb_info->LastPlayPos = playp; - - done: - Sleep(DSPB_TICK_MILLISECONDS); - } - - sb_info->thread_alive = false; -} - -// Begins the whole streaming process -bool win_llsSystem::StartStreaming(void) { - DSBCAPS dsbcaps; - - dsbcaps.dwSize = sizeof(DSBCAPS); - m_sb_info.m_lp_looping_buffer->GetCaps(&dsbcaps); - - m_sb_info.m_f_secondary_looping = (m_sb_info.m_lp_looping_buffer != m_sb_info.m_lp_primary_buffer); - - m_sb_info.BufferSize = dsbcaps.dwBufferBytes; - - m_sb_info.MaxWriteSamples = m_primary_frequency * MAX_WRITE_AHEAD; - m_sb_info.MaxWriteBytes = m_sb_info.MaxWriteSamples * m_primary_alignment; - - m_sb_info.NextWritePos = -1; - m_sb_info.LastPlayPos = 0; - - StreamFill(0, dsbcaps.dwBufferBytes); - - m_sb_info.thread_request_kill = false; - m_sb_info.thread_alive = true; - - // Start mixing thread. - m_sb_info.thread_handle = _beginthread(StreamTimer, 16384, (void *)&m_sb_info); - if (m_sb_info.thread_handle == -1) { - m_sb_info.thread_alive = false; - mprintf(0, "Thread failed\n"); - Int3(); - return false; - } - - if (m_sb_info.m_f_secondary_looping) { - if (!SetThreadPriority((HANDLE)m_sb_info.thread_handle, THREAD_PRIORITY_HIGHEST)) - Int3(); - } else { - if (!SetThreadPriority((HANDLE)m_sb_info.thread_handle, THREAD_PRIORITY_TIME_CRITICAL)) - Int3(); - } - - return true; -} - -// Creates a 2d, 3d, or Primary direct sound buffer -HRESULT win_llsSystem::CreateDSBuffer(int buffer_type, LPDIRECTSOUNDBUFFER *lp_lp_dsb, LPDIRECTSOUND3DBUFFER *lp_lp_dsb_3d, - DWORD sound_bytes, DWORD frequency, bool f_is_stereo, bool f_is_16_bit) { - DSBUFFERDESC dsbd; - tWAVEFORMATEX fmt; - HRESULT result = DS_OK; - - ASSERT(m_lp_ds != NULL && sound_bytes >= 0); - ASSERT(frequency == 44100 || frequency == 22050 || frequency == 11025); - if (!m_f_sound_lib_init) - return 0; - - if (lp_lp_dsb) { - *lp_lp_dsb = NULL; - } - if (lp_lp_dsb_3d) { - *lp_lp_dsb_3d = NULL; - } - - // Setup the wave format - fmt.nChannels = (f_is_stereo) ? 2 : 1; - fmt.wBitsPerSample = (f_is_16_bit) ? 16 : 8; - fmt.nSamplesPerSec = ((DWORD)frequency); - fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample >> 3); - fmt.nAvgBytesPerSec = ((DWORD)fmt.nSamplesPerSec) * ((DWORD)fmt.nBlockAlign); - fmt.wFormatTag = WAVE_FORMAT_PCM; - - // Setup the secondary direct sound buffer - memset(&dsbd, 0, sizeof(dsbd)); - dsbd.lpwfxFormat = (LPWAVEFORMATEX)&fmt; - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwBufferBytes = sound_bytes; - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2; - - ASSERT(buffer_type == SBT_PRIMARY); - - m_primary_frequency = m_current_frequency = frequency; - m_primary_bit_depth = fmt.wBitsPerSample; - m_primary_alignment = fmt.nBlockAlign; - - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; - } else if (m_mixer_type == SOUND_MIXER_DS_16 || m_mixer_type == SOUND_MIXER_DS_8) { - // There are three buffer types that we should consider. - switch (buffer_type) { - case SBT_2D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; - break; - case SBT_PRIMARY: - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - break; - default: - ASSERT(0); // Invalid type of buffer - } - } else if (IS_3D_MIXER(m_mixer_type)) { - // There are three buffer types that we should consider. - switch (buffer_type) { - case SBT_2D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; - break; - case SBT_3D: - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - break; - case SBT_PRIMARY: - dsbd.lpwfxFormat = NULL; - dsbd.dwBufferBytes = 0; - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - break; - default: - ASSERT(0); // Invalid type of buffer - } - } else { - mprintf(0, "DS3DLIB: Unsupported function for mixer specfied in CreateDSBuffer (%d,%d)\n", m_mixer_type, buffer_type); - Int3(); // Get Samir!!! - return DSERR_UNSUPPORTED; - } - - // Create the buffer - result = m_lp_ds->CreateSoundBuffer(&dsbd, lp_lp_dsb, 0); - /// ASSERT(result == DS_OK); - - if (result == DS_OK && buffer_type == SBT_PRIMARY) { - // Creative EAX Init - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - if (!EAX_SetPrimaryBuffer()) { - mprintf(0, "CreateDSBuffer: EAX Init failed.\n"); - result = DSERR_UNSUPPORTED; - goto ds_error; - } - } - - // Succeeded. Set primary buffer to desired format. - result = (*lp_lp_dsb)->SetFormat(&fmt); - } - - if (result != DS_OK) { - mprintf(0, "DS3DLIB: Failed to init sound buffer of type %d for mixer %d.\n", buffer_type, m_mixer_type); - goto ds_error; - } - - // call get format to make sure we're okay. - if (buffer_type == SBT_PRIMARY) { - } - - // do 3d sound support stuff. - if (IS_3D_MIXER(m_mixer_type)) { - // a 3d buffer needs a 3d interface pointer - if (buffer_type == SBT_3D) { - ASSERT(lp_lp_dsb_3d != NULL); - result = (*lp_lp_dsb)->QueryInterface(IID_IDirectSound3DBuffer, (void **)lp_lp_dsb_3d); - if (result != DS_OK) { - goto ds_error; - } - - // ASSERT(result == DS_OK); - } else if (buffer_type == SBT_PRIMARY) { - if ((result = (*lp_lp_dsb)->QueryInterface(IID_IDirectSound3DListener, (void **)&m_lp_listener)) == S_OK) { - m_lp_listener->SetRolloffFactor(ENV3DVAL_ROLLOFF_DEFAULT, DS3D_IMMEDIATE); - } - } - } - -ds_error: - if (result != DS_OK) { - mprintf(0, "DS3DLIB:result=%x\n", result); - if (lp_lp_dsb_3d && (*lp_lp_dsb_3d)) { - (*lp_lp_dsb_3d)->Release(); - *lp_lp_dsb_3d = NULL; - } - - if (lp_lp_dsb && (*lp_lp_dsb)) { - (*lp_lp_dsb)->Release(); - *lp_lp_dsb = NULL; - } - } - - return (long)result; -} - -// Internal function to enumerate sound devices -BOOL CALLBACK LLEnumCallback(LPGUID lp_guid, LPCSTR lpstr_description, LPCSTR lpstr_module, LPVOID lp_Context) { - GUID FAR *lp_ret_guid = (GUID FAR *)lp_Context; - - if (m_sound_device_name[0]) { - if (strcmp(lpstr_description, m_sound_device_name) == 0) { - mprintf(0, "Using sound card:%s-%s\n", lpstr_description, lpstr_module); - if (lp_guid) { - memmove(lp_ret_guid, lp_guid, sizeof(GUID)); - } - return FALSE; - } - } - - return TRUE; -} - -void win_llsSystem::SetSoundCard(const char *name) { - if (name) { - strcpy(m_sound_device_name, name); - } else { - m_sound_device_name[0] = 0; - } -} - -// Initializes the sound library -int win_llsSystem::InitSoundLib(char mixer_type, oeApplication *sos, uint8_t MaxSoundsPlayed) // add playlist info -{ - GUID card_guid, zero_card_guid; - GUID *pguid = NULL; - DSCAPS dscaps; - HRESULT hresult; - bool f16bit; - bool retval = true; - - // reset error system. - SetError(SSL_OK); - SoundApp = (oeWin32Application *)sos; - - if (sos) { - oeWin32Application *obj = (oeWin32Application *)sos; - - // If the the library if already init'ed, then return o.k. - if (m_f_sound_lib_init) - return 1; - - GameWindowHandle = (void *)obj->m_hWnd; - } else { - ASSERT(GameWindowHandle); - } - - ll_sound_ptr = this; - m_timer_last_frametime = -1; - m_cache_stress_timer = 0.0f; - m_in_sound_frame = false; - m_pending_actions = false; - - ////////////////////////////////////////////////////////////////////////////// - // chrishack -- Need to enumerate sound devices for now - // Attempt to enumerate the sound device - // if(DirectSoundEnumerate(&LLEnumCallback, NULL) != DS_OK) return 0; - - // Setup the game handle - m_hwnd_main = GameWindowHandle; - - // Check for invalid values and NULL pointers - ASSERT(m_hwnd_main != NULL); - ASSERT(Sounds != NULL); - ASSERT(SoundFiles != NULL); - ASSERT(MaxSoundsPlayed > 0); - - memset(&m_sb_info, 0, sizeof(DSSTREAM)); - - // Currently restart total sounds played count (for unique ids and stats) - m_total_sounds_played = 0; - - // Setup the sound mixer object - m_sound_mixer.m_cur_sounds_played = 0; - m_sound_mixer.m_max_sounds_played = MaxSoundsPlayed; - m_sound_mixer.m_sound_cache = new sound_buffer_info[MaxSoundsPlayed]; - m_mixer_type = SOUND_MIXER_NONE; - - if (m_sound_mixer.m_sound_cache == NULL) { - Int3(); - goto error_sub; - } - - // Create the Direct Sound Interface - // determine GUID for sound card which was chosen in the launcher... - ZeroMemory(&card_guid, sizeof(GUID)); - ZeroMemory(&zero_card_guid, sizeof(GUID)); - hresult = DirectSoundEnumerate(LLEnumCallback, &card_guid); - if (hresult == DS_OK) { - if (memcmp(&card_guid, &zero_card_guid, sizeof(GUID)) != 0) { - pguid = &card_guid; - } - } - - if (mixer_type != SOUND_MIXER_NONE) { - if (mixer_type == SOUND_MIXER_CREATIVE_EAX) { - if (!EAX_Create(pguid, &m_lp_ds)) { - mprintf(0, "Sound NT: Error EAX\n"); - retval = false; - goto error_sub; - } - } else { - hresult = DirectSoundCreate(pguid, &m_lp_ds, NULL); - if (hresult != DS_OK) { - retval = false; - goto error_sub; - } - } - - ASSERT(m_lp_ds != NULL); - - // determine if we're using a crappy card - dscaps.dwSize = sizeof(DSCAPS); - m_lp_ds->GetCaps(&dscaps); - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { - mixer_type = SOUND_MIXER_DS_8; - mprintf(0, "SOUND INIT(1): We are in NT or have a crappy sound card\n"); - } - - m_sound_mixer.m_loop_method = DSLOOP_STREAM_METHOD; - } - - if (mixer_type != SOUND_MIXER_NONE) { - m_f_sound_lib_init = 1; - } - -// This section initializes the primary buffer -// software mixer try. -retry_mixer_init: - if (mixer_type == SOUND_MIXER_SOFTWARE_16) { - // test different conditions to see if we really can play sound in software - hresult = m_lp_ds->SetCooperativeLevel((HWND)m_hwnd_main, DSSCL_WRITEPRIMARY); - if (hresult != DS_OK) { - mprintf(0, "SOUND INIT(2): SCL: WritePrimary failed. Attempting DS 8 init.\n"); - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - - // Creates a primary buffer and makes sure we are at the specified frequency, bit depth, and that we - // can to 3d stuff too :) - m_mixer_type = SOUND_MIXER_SOFTWARE_16; - f16bit = true; - hresult = CreateDSBuffer(SBT_PRIMARY, &m_sb_info.m_lp_primary_buffer, NULL, 0, - 22050, // frequency - true, // stereo - f16bit); // 16-bit - if (hresult != DS_OK) { - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - mprintf(0, "SOUND INIT(3): Cannot create primary buffer.\n"); - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } else { - // Determine if we are running NT or have a shitty Win95 sound card - DSBCAPS dsbcaps; - - ASSERT(m_sb_info.m_lp_primary_buffer); - - dsbcaps.dwSize = sizeof(DSBCAPS); - m_sb_info.m_lp_primary_buffer->GetCaps(&dsbcaps); - - // Let's allocate our array of ints for our optimized software mixer! - if (!Fast_mixer) { - Fast_mixer = (int *)mem_malloc(dsbcaps.dwBufferBytes * sizeof(int)); - Fast_mixer_len = dsbcaps.dwBufferBytes; - mprintf(0, "Using %d ints for fast software mixer\n", dsbcaps.dwBufferBytes); - } - - // Is you want to see the caps, here is where -- mprintf all you want - if (!(dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE)) { - mprintf(0, "SOUND INIT(4): Primary is not in hardware\n"); - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - } - - // looping buffer is the same as the primary buffer for software mixers. - m_sb_info.m_lp_looping_buffer = m_sb_info.m_lp_primary_buffer; - - // Start the primary and have it always play. - m_f_sound_lib_init = StartStreaming(); - if (!m_f_sound_lib_init) { - mprintf(0, "SOUND INIT(5): Something went wrong in StartStreaming\n"); - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - mixer_type = SOUND_MIXER_DS_8; - goto retry_mixer_init; - } - - } else if (mixer_type == SOUND_MIXER_NONE) { - m_mixer_type = mixer_type; - m_f_sound_lib_init = 0; - } else { - // This is for DirectSound Internal Mixers. We let DirectSound do its magic. - m_mixer_type = mixer_type; - hresult = m_lp_ds->SetCooperativeLevel((HWND)m_hwnd_main, DSSCL_PRIORITY); - if (hresult != DS_OK) { - mprintf(0, "Sound NT: Error 1\n"); - retval = false; - goto error_sub; - } - - // start primary buffer - f16bit = (mixer_type == SOUND_MIXER_DS_16 || mixer_type == SOUND_MIXER_DS3D_16 || - mixer_type == SOUND_MIXER_CREATIVE_EAX); - hresult = CreateDSBuffer(SBT_PRIMARY, &m_sb_info.m_lp_primary_buffer, NULL, 0, - 22050, // frequency - true, // stereo - f16bit); // 8 or 16 bit - if (hresult != DS_OK) { - mprintf(0, "Sound NT: Error 2\n"); - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - retval = false; - goto error_sub; - } - - m_sb_info.m_lp_primary_buffer->Play(0, 0, DSBPLAY_LOOPING); - } - - // buffered method doesn't use threads at all. - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && m_mixer_type != SOUND_MIXER_NONE && - m_sound_mixer.m_loop_method != DSLOOP_BUFFER_METHOD) { - // start looping thread, failure results in a 'clean exit' - if (!sb_loop_thread_init(this)) { - retval = false; - if (m_sb_info.m_lp_primary_buffer) { - m_sb_info.m_lp_primary_buffer->Release(); - m_sb_info.m_lp_primary_buffer = NULL; - } - goto error_sub; - } - } - - mprintf(0, "Sound mixer: "); - retval = true; - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - mprintf(0, "Software 16\n"); - break; - case SOUND_MIXER_DS_8: - mprintf(0, "DS 8\n"); - break; - case SOUND_MIXER_DS_16: - mprintf(0, "DS 16\n"); - break; - case SOUND_MIXER_DS3D_16: - mprintf(0, "DS3D 16\n"); - break; - case SOUND_MIXER_CREATIVE_EAX: - mprintf(0, "Creative EAX\n"); - break; - case SOUND_MIXER_NONE: - mprintf(0, "None\n"); - break; - default: - mprintf(0, "LLSound ERROR: Unsupported mixer"); - Int3(); - retval = false; - break; - } - - // set 3d environment settings - t3dEnvironmentToggles env_toggles; - t3dEnvironmentValues env_values; - - memset(&Env3dValues, 0, sizeof(Env3dValues)); - memset(&Env3dToggles, 0, sizeof(Env3dToggles)); - - env_toggles.flags = 0; // get supported features - GetEnvironmentToggles(&env_toggles); - - env_values.flags = 0; // set up values and toggles to be set - env_toggles.flags = env_toggles.supported; - - // we may want to check this with configured options later -- samir - if (CHECK_FLAG(env_toggles.supported, ENV3DVALF_DOPPLER) && ENV3DTOG_DOPPLER) { - env_values.flags |= ENV3DVALF_DOPPLER; - env_values.doppler_scalar = ENV3DVAL_DOPPLER_DEFAULT; - env_toggles.doppler = true; - } - if (CHECK_FLAG(env_toggles.supported, ENV3DVALF_GEOMETRY) && ENV3DTOG_GEOMETRY) { - env_toggles.geometry = true; - } - SetEnvironmentToggles(&env_toggles); - SetEnvironmentValues(&env_values); - - ///////////////////////////////////////////////////////////////////////////// - g_emulated_listener = &m_emulated_listener; - -error_sub: - if (retval == false) { - // Only gets here if there was an error - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_Destroy(); - } else if (m_lp_ds) { - m_lp_ds->Release(); - } - m_lp_ds = NULL; - mprintf(0, "Sound Warning: Didn't initialize sound library.\n"); - if (m_sound_mixer.m_sound_cache != NULL) - delete[] m_sound_mixer.m_sound_cache; - m_f_sound_lib_init = 0; - m_mixer_type = SOUND_MIXER_NONE; - } - - Global_DS_alloced_sounds = 0; - - return (m_f_sound_lib_init); -} - -// Cleans up after the sound library is done being used -void win_llsSystem::DestroySoundLib(void) { - bool f_all_done = false; - - if (!m_f_sound_lib_init) - return; - - mprintf(0, "Start of sound system close\n"); - - // kill sound geometry object if any. - if (m_geometry) { - m_geometry->Shutdown(); - m_geometry = NULL; - } - - StopAllSounds(); - - // Wait till they are all done - mprintf(0, "Waiting for sounds to stop\n"); - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - while (!f_all_done) { - f_all_done = true; - int i; - - for (i = 0; i < m_sound_mixer.m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[i]; - if (sb->s && sb->s->kill_me && !(sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM))) { - cleanup_directsound_looping_sb(&m_sound_mixer.m_sound_cache[i]); - } else if (sb->m_status & (SSF_PLAY_LOOPING | SSF_PLAY_STREAMING)) { - // this should block until the sound is truly free, so we don't need to do a 'all done' - StopSound(m_sound_mixer.m_sound_cache[i].m_unique_id, SKT_HOLD_UNTIL_STOP); - // f_all_done = false; - } - } - } - - // buffered method doesn't use threads at all. - if (m_sound_mixer.m_loop_method != DSLOOP_BUFFER_METHOD) { - sb_loop_thread_kill(); - } - } - mprintf(0, "All sounds stopped\n"); - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - // Kill thread goes here - if (m_sb_info.thread_handle) { - m_sb_info.thread_request_kill = true; - while (m_sb_info.thread_alive) { - } - } - - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - m_sb_info.m_lp_looping_buffer->Stop(); - m_sb_info.m_lp_looping_buffer->Release(); - } - } - - // free audio device; - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_Destroy(); - } else if (m_lp_ds) { - m_lp_ds->Release(); - } - - m_lp_ds = NULL; - m_sb_info.m_lp_looping_buffer = NULL; - - mprintf(0, "End of sound system close\n"); - - if (m_sound_mixer.m_sound_cache != NULL) - delete[] m_sound_mixer.m_sound_cache; - - m_f_sound_lib_init = false; - g_emulated_listener = NULL; - m_mixer_type = -1; - ll_sound_ptr = NULL; - if (Fast_mixer) { - mem_free(Fast_mixer); - Fast_mixer = NULL; - Fast_mixer_len = 0; - } -} - -// used to clean up direct sound buffer stuff -void win_llsSystem::cleanup_directsound_looping_sb(sound_buffer_info *sb) { - if (!sb->s) - return; - if (!sb->s->kill_me) - return; - - // should occur when kill_me set, sb_stop_buffer(&ll_sound_ptr->m_sound_mixer.m_sound_cache[i]); - sb_free_buffer(sb); - - sb->m_sound_buffer = NULL; - sb->s->playing = 0; - - void *p = (void *)sb->s; - sb->s = NULL; - sb->m_status = SSF_UNUSED; - mem_free(p); -} - -// cleans up a sound -replaces a lot of repeated code whenever we cleanup sounds. -void win_llsSystem::update_directsound_sb(sound_buffer_info *sb, bool update_looping) { - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16 || m_mixer_type == SOUND_MIXER_NONE) { - return; - } - - // take care of any streamed threaded method looping sounds that are done. - // orphan streaming structure, clean it up! (sound buffer is NULL yet sb->s is valid - if (sb->s && (((sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM)) && !sb->m_sound_buffer) || sb->s->kill_me)) { - cleanup_directsound_looping_sb(sb); - } else if (sb->m_status && !(sb->m_status & SSF_PAUSED)) { - // non playing sounds should be stopped always - int status = sb_get_status(sb); - - if (update_looping) { - if (status & SB_STATUS_PLAYING) { - if ((sb->m_status & (SSF_PLAY_STREAMING + SSF_BUFFERED_STRM)) == (SSF_PLAY_STREAMING + SSF_BUFFERED_STRM)) { - sb_stream_buffered_update(sb); - } - } else { - if ((sb->m_status & (SSF_PLAY_LOOPING + SSF_BUFFERED_LOOP)) == (SSF_PLAY_LOOPING + SSF_BUFFERED_LOOP)) { - sb_buffered_loop_step(this, sb); - status = sb_get_status(sb); // get new status for following checks. - } - } - } - if (!(status & SB_STATUS_PLAYING)) { - StopSound(sb->m_unique_id); - } else if (status & SB_STATUS_INVALID) { - StopSound(sb->m_unique_id); - } - } -} - -// Stops the sound from playing -- f_immediately is used for looping samples -- i.e. so we can -// play the end of loop snipit -void win_llsSystem::StopSound(int sound_uid, uint8_t f_immediately) { - int current_slot; - sound_buffer_info *sb; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - - sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_status == SSF_UNUSED) - return; - - // update sound count. - m_sound_mixer.m_cur_sounds_played--; - - if (f_immediately == SKT_STOP_AFTER_LOOP) { - sb->m_status &= ~SSF_PLAY_LOOPING; - sb->m_status |= SSF_PLAY_NORMAL; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_status & SSF_BUFFERED_LOOP)) { - sb_buffered_loop_step(this, sb, DSBUFLOOP_FINISH_STEP); - } - return; - } - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - if (sb->s && !(sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM))) { - sb_loop_element_kill(sb); - if (f_immediately == SKT_HOLD_UNTIL_STOP) { - sb_loop_element_wait_until_dead(sb); - cleanup_directsound_looping_sb(sb); - } - return; - } else if (sb->m_sound_buffer) // this works for buffered loops too. - { - if (sb->m_status & (SSF_BUFFERED_LOOP + SSF_BUFFERED_STRM)) { - if (sb->m_status & SSF_PLAY_STREAMING) { - sb_stream_element_kill(sb); - } - - void *p = (void *)sb->s; - if (p) { - mem_free(p); - sb->s = NULL; - } - } - GetSoundPos(sb->m_unique_id); - sb_stop_buffer(sb); - sb_free_buffer(sb); - - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count > 0) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count--; - // DUPSND if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count == 0) { - // DUPSND Global_DS_alloced_sounds--; - // DUPSND } - } - Global_DS_alloced_sounds--; - } - m_sound_mixer.m_sound_cache[current_slot].m_sound_buffer = NULL; - } - - // mprintf(0, "SL cleaning slot %d\n", current_slot); - m_sound_mixer.m_sound_cache[current_slot].m_status = SSF_UNUSED; -} - -// Copies sound data from the external sound data block to an individual sound buffer -HRESULT LoadSoundData(LPDIRECTSOUNDBUFFER lp_dsb, char *sound_data_ptr, DWORD total_bytes) { - LPVOID ptr1, ptr2; - DWORD len1, len2; - HRESULT result; - - ASSERT(lp_dsb != NULL && sound_data_ptr != NULL && total_bytes > 0); - -TryLockAgainLabel: - result = lp_dsb->Lock(0, total_bytes, &ptr1, &len1, &ptr2, &len2, 0); - - switch (result) { - case DS_OK: - memcpy(ptr1, sound_data_ptr, len1); - if (ptr2) - memcpy(ptr2, sound_data_ptr + len1, len2); - lp_dsb->Unlock(ptr1, len1, ptr2, len2); - break; - case DSERR_BUFFERLOST: - result = lp_dsb->Restore(); - if (result == DS_OK) - goto TryLockAgainLabel; - break; - } - - return (long)result; -} - -// Determines if a sound will play. Takes into account maximum allowable -// sounds. -// Also put prioritization code in here -// ignore reserved slots - -#ifdef _DEBUG -int16_t win_llsSystem::FindFreeSoundSlot(int sound_index, float volume, int priority) -#else -int16_t win_llsSystem::FindFreeSoundSlot(float volume, int priority) -#endif -{ - int current_slot; - sound_buffer_info *sb; - - // stop any left over sounds for Direct Sound. - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - update_directsound_sb(sb); - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status == SSF_UNUSED) { - if (!((m_mixer_type == SOUND_MIXER_DS_8 || m_mixer_type == SOUND_MIXER_DS_16 || - m_mixer_type == SOUND_MIXER_DS3D_16 || - m_mixer_type == SOUND_MIXER_CREATIVE_EAX) && - sb->s)) - return current_slot; - } - } - - // no more slots? take priority into account. - // throw out lowest priority sound slot (must be lower than or equal to new sound priority) - float weighted_priority = (priority * 2.0f) * volume; - if (current_slot == m_sound_mixer.m_max_sounds_played) { - int throw_out_slot = -1, equiv_priority_slot = -1; - float weighted_priorityA, weighted_priorityB; - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (!(sb->m_status & (SSF_PLAY_LOOPING + SSF_PLAY_STREAMING))) { - weighted_priorityA = sb->play_info->priority * 2.0f * sb->m_volume; - if (weighted_priorityA < weighted_priority) { - if (throw_out_slot == -1) { - throw_out_slot = current_slot; - } else { - play_information *play_info2 = m_sound_mixer.m_sound_cache[throw_out_slot].play_info; - weighted_priorityB = play_info2->priority * 2.0f * sb->m_volume; - if (weighted_priorityB > weighted_priorityA) { - throw_out_slot = current_slot; - } - } - } - - else if (equiv_priority_slot == -1 && weighted_priorityA == weighted_priority) { - equiv_priority_slot = current_slot; - } - } - } - - // if no slot found to stop, look for a slot with priority == new priority - if (throw_out_slot == -1) { - throw_out_slot = equiv_priority_slot; - } - if (throw_out_slot > -1) { - sb = &m_sound_mixer.m_sound_cache[throw_out_slot]; - win_llsSystem::StopSound(sb->m_unique_id, SKT_HOLD_UNTIL_STOP); -/* - mprintf(0, "DDSNDLIB: Replace sound (p:%d) with sound (p:%d) in slot %d\n", - sb->play_info->priority, - priority, - throw_out_slot)); -*/ - return throw_out_slot; - } - } - -#ifdef _DEBUG - if (sound_index > -1) { - mprintf(0, "DDSNDLIB: Sound %s with priority (%d) too low.\n", Sounds[sound_index].name, priority); - } else { - mprintf(0, "DDSNDLIB: Sound unknown with priority (%d) too low.\n", priority); - } -#endif - - return -1; -} - -int win_llsSystem::PlaySound2d(play_information *play_info, int sound_index, float f_volume, float f_pan, - bool f_looped) { - sound_buffer_info *sb = NULL; - int16_t sound_slot; - - if (!m_f_sound_lib_init) { - return -1; - } - - // calculate volume and pan - f_volume = (f_volume < 0.0f) ? 0.0f : (f_volume > 1.0f) ? 1.0f : f_volume; - play_info->left_volume = play_info->right_volume = f_volume; - - f_pan = (f_pan < -1.0f) ? -1.0f : (f_pan > 1.0f) ? 1.0f : f_pan; - if (f_pan < 0.0) { - play_info->right_volume += f_volume * f_pan; - } else { - play_info->left_volume -= f_volume * f_pan; - } - - // do common processing. - if (SoundFiles[Sounds[sound_index].sample_index].used == 0) { - mprintf(0, "Tryed to play %d sound, it DNE.\n", sound_index); - return -1; - } -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(sound_index, f_volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(f_volume, play_info->priority); -#endif - if (sound_slot < 0) { - // do prioritization code here. - return -1; - } - sb = &m_sound_mixer.m_sound_cache[sound_slot]; - m_total_sounds_played++; - sb->play_info = play_info; - sb->m_unique_id = MakeUniqueId(sound_slot); - sb->m_buffer_type = SBT_2D; - sb->m_sound_index = sound_index; - sb->m_status = SSF_UNUSED; - - ASSERT(sb->m_unique_id != -1); - - // play 2d sound - if (m_mixer_type == SOUND_MIXER_SOFTWARE_16) { - sb->m_status = (f_looped) ? SSF_PLAY_LOOPING : SSF_PLAY_NORMAL; - return sb->m_unique_id; - } - - if (f_looped) { - LoopStartStreaming(sb, SBT_2D, f_volume, f_pan, NULL); - if (sb->m_snd_obj == NULL) { - sb->m_status = SSF_UNUSED; - Int3(); - return -1; - } - } else { - tPSBInfo psb; - - if (SoundFiles[Sounds[sound_index].sample_index].use_count > 0) { - if (DuplicateSoundBuffer(sb)) { - goto play_sound; - } - } - if (!CreateSoundBuffer(sb, false)) { - return -1; - } - if (!LoadSoundBuffer(sb)) { - sb_free_buffer(sb); - return -1; - } - - play_sound: - sb->m_status = SSF_PLAY_NORMAL; - - psb.volume = f_volume; - psb.pan = f_pan; - psb.freq = 22050; - psb.looping = false; - if (!PlaySoundBuffer(sb, &psb)) { - sb_free_buffer(sb); - return -1; - } - } - - m_sound_mixer.m_cur_sounds_played++; - - return sb->m_unique_id; -} - -void win_llsSystem::LoopStartStreaming(sound_buffer_info *sb, int buffer_type, float volume, float pan, - pos_state *cur_pos) { - // unsigned long thread_handle; - int sound_length, buffer_size; - int determined_method; - bool f_sample_16bit; - char *sample_ptr; - tPSBInfo psb; - DSLOOPSTREAM *s; - - // setup looping buffer. must clear out before assigning to sound buffer for thread security. - s = (DSLOOPSTREAM *)mem_malloc(sizeof(DSLOOPSTREAM)); - if (s == NULL) { - sb->s = NULL; - return; - } - memset((void *)s, 0, sizeof(DSLOOPSTREAM)); - sb->s = s; - - sample_ptr = get_sound_info(sb, &sound_length, &f_sample_16bit); - sb->s->f_sample_16bit = f_sample_16bit; - sb->m_buffer_type = buffer_type; - - if (m_sound_mixer.m_loop_method == DSLOOP_SMART_METHOD) { - int loop_startb, loop_endb; - bool b; - if (sb_get_loop_info(sb, &loop_startb, &loop_endb, &b)) { - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].np_sample_length == (loop_endb - loop_startb + 1)) { - determined_method = DSLOOP_BUFFER_METHOD; - } else { - determined_method = DSLOOP_STREAM_METHOD; - } - } else { // wtf? - return; - } - } else { - determined_method = m_sound_mixer.m_loop_method; - } - - switch (determined_method) { - case DSLOOP_BUFFER_METHOD: - sound_length = 0; - sb->s->loop_step = -1; - while (!sound_length && sb->s->loop_step < 2) { - sample_ptr = sb_get_loop_step_info(sb, sb->s->loop_step, f_sample_16bit, &sound_length); - sb->s->loop_step++; - } - if (!sound_length && sb->s->loop_step == 2) { - // hmm, weird loop. no sample? - return; - } - sb->s->loop_step--; // return to proper step. - sb->s->loop_timer = 0.0f; - sb->s->bytes_left = sound_length; - buffer_size = sound_length; - sb->m_status = SSF_PLAY_LOOPING | SSF_BUFFERED_LOOP; - // mprintf(0, "DDSNDLIB: Starting buffered loop %d (step %d).\n", sb->m_unique_id, sb->s->loop_step); - break; - default: - buffer_size = STREAM_BUFFER_SIZE; - sb->m_status = SSF_PLAY_LOOPING; // must go before buffer is initialized!!!!!! - } - - sb->sample_data = sample_ptr; - - // allocate buffer for playback - if (!CreateSoundBuffer(sb, false, buffer_size, (sb->m_status & SSF_BUFFERED_LOOP) ? false : true)) { - return; - } - - // remind sb system and play. - if (determined_method == DSLOOP_BUFFER_METHOD) { - psb.looping = (sb->s->loop_step == 0) ? true : false; - if (!sb_load_buffer(sb, sb->sample_data, sound_length)) - return; - } else if (sb_loop_element_init(sb, sample_ptr, sound_length, STREAM_BUFFER_SIZE)) { - psb.looping = true; - } else { - sb->s->playing = 0; - return; - } - - if (buffer_type == SBT_3D) { - psb.cur_pos = cur_pos; - } else { - ASSERT(buffer_type == SBT_2D); - psb.pan = pan; - } - psb.volume = volume; - psb.freq = 22050; - - PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; -} - -void win_llsSystem::DSStartStreaming(sound_buffer_info *sb, float volume, float pan) { - tPSBInfo psb; - int sound_length; - int stream_buflength; - int determined_method; - char *sample_ptr; - bool f_stereo; - - sb->s = (DSLOOPSTREAM *)mem_malloc(sizeof(DSLOOPSTREAM)); - ASSERT(sb->s); - if (sb->s == NULL) - return; - - memset((void *)sb->s, 0, sizeof(DSLOOPSTREAM)); - - sample_ptr = (char *)sb->play_info->m_stream_data; - sound_length = sb->play_info->m_stream_size; - stream_buflength = sb->play_info->m_stream_bufsize; - - switch (sb->play_info->m_stream_format) { - case SIF_STREAMING_16_M: - sb->s->f_sample_16bit = true; - f_stereo = false; - break; - - case SIF_STREAMING_8_M: - sb->s->f_sample_16bit = false; - f_stereo = false; - break; - - case SIF_STREAMING_16_S: - sb->s->f_sample_16bit = true; - f_stereo = true; - break; - - case SIF_STREAMING_8_S: - sb->s->f_sample_16bit = false; - f_stereo = true; - break; - - default: - ASSERT(0); - break; - } - - ASSERT(sb->m_buffer_type == SBT_2D); - sb->m_sound_index = -1; - - // determine how we will stream this data - determined_method = m_sound_mixer.m_loop_method; - switch (determined_method) { - case DSLOOP_BUFFER_METHOD: - sb->m_status = SSF_PLAY_STREAMING | SSF_BUFFERED_STRM; - break; - default: - sb->m_status = SSF_PLAY_STREAMING; // must go before buffer is initialized!!!!!! - break; - } - - if (!CreateSoundBuffer(sb, f_stereo, stream_buflength, true)) { - mem_free((void *)sb->s); - sb->s = NULL; - return; - } - - // set wave event or do thread streamed method - if (sb_stream_element_init(sb, sample_ptr, sound_length, stream_buflength)) { - psb.pan = pan; - psb.volume = volume; - psb.freq = 22050; - psb.looping = true; - - PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; - } -} - -int win_llsSystem::PlayStream(play_information *play_info) { - int16_t sound_slot; - DWORD ds_flags = 0; - - ASSERT(play_info != NULL); - - float volume = (play_info->left_volume > play_info->right_volume) ? play_info->left_volume : play_info->right_volume; - - if (!m_f_sound_lib_init) - return -1; - -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(-1, volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(volume, play_info->priority); -#endif - // Out of sound slots - if (sound_slot < 0) { - return -1; - } - - // mprintf(0, "TS(%d)Playing sound index %d at %d volume,%d pan\n", TotalSoundsPlayed, sound_index, volume, pan); - - m_total_sounds_played++; - m_sound_mixer.m_sound_cache[sound_slot].play_info = play_info; - - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id = MakeUniqueId(sound_slot); - ASSERT(m_sound_mixer.m_sound_cache[sound_slot].m_unique_id != -1); - - m_sound_mixer.m_sound_cache[sound_slot].m_buffer_type = SBT_2D; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - float volume; - float pan; - LPDIRECTSOUNDBUFFER sound_ptr; - - if (play_info->left_volume > play_info->right_volume) { - volume = play_info->left_volume; - pan = -1.0f + (play_info->right_volume / play_info->left_volume); - } else { - volume = play_info->right_volume; - pan = 1.0f - (play_info->left_volume / play_info->right_volume); - } - - DSStartStreaming(&m_sound_mixer.m_sound_cache[sound_slot], volume, pan); - sound_ptr = m_sound_mixer.m_sound_cache[sound_slot].m_sound_buffer; - if (sound_ptr == NULL) { - m_sound_mixer.m_sound_cache[sound_slot].m_sound_buffer = NULL; - return -1; - } - } else { - m_sound_mixer.m_sound_cache[sound_slot].m_status = SSF_PLAY_STREAMING; - } - - m_sound_mixer.m_cur_sounds_played++; - - return (m_sound_mixer.m_sound_cache[sound_slot].m_unique_id); -} - -// Checks a Unique Sound ID and determines if that sound is still playing -bool win_llsSystem::IsSoundInstancePlaying(int sound_uid) { - int current_slot; - - if (!m_f_sound_lib_init) - return false; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return false; - - // mprintf(0, "Checking slot %d of UID %d\n", current_slot, sound_uid); - - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) { - return true; - } - - return false; -} - -// Is this sound placing on any "channel" -int win_llsSystem::IsSoundPlaying(int sound_index) { - int current_slot; - - if (!m_f_sound_lib_init) - return -1; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if ((m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) && - (m_sound_mixer.m_sound_cache[current_slot].m_sound_index == sound_index)) { - return m_sound_mixer.m_sound_cache[current_slot].m_unique_id; - } - } - - return -1; -} - -// This function limits the number of sounds cached to 255(8bits) and 256 bit is for invalid channel -// The purpose is to create unique signatures for each sound played (and allow for -// the slot_number to be quickly determined) -inline int win_llsSystem::MakeUniqueId(int sound_slot) { return ((((int)m_total_sounds_played) << 8) + sound_slot); } - -inline int win_llsSystem::ValidateUniqueId(int sound_uid) { - if (sound_uid == m_sound_mixer.m_sound_cache[sound_uid & 0x00FF].m_unique_id) { - return sound_uid & 0x00FF; - } else { - return -1; - } -} - -void win_llsSystem::PauseSounds() { - int current_slot; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - update_directsound_sb(sb); - - /* if((sb->m_status != SSF_UNUSED) && - ((sb->m_status & SSF_PAUSED) == 0)) - { - int status = sb_get_status(sb); - - if(!(status & SB_STATUS_PLAYING)) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else if (status & SB_STATUS_INVALID) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - } - */ - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status != SSF_UNUSED && !(sb->m_status & SSF_PAUSED)) { - sb->m_status |= SSF_PAUSED; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_sound_buffer)) { - sb_stop_buffer(sb); - } - } - } -} - -void win_llsSystem::ResumeSounds() { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_status != SSF_UNUSED && (sb->m_status & SSF_PAUSED)) { - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - PlaySoundBuffer(sb, NULL); - } - - m_sound_mixer.m_sound_cache[current_slot].m_status &= (~SSF_PAUSED); - } - } -} - -void win_llsSystem::PauseSound(int sound_uid) { - int current_slot; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->m_unique_id == sound_uid) { - update_directsound_sb(sb); - - /* if((sb->m_status != SSF_UNUSED) && ((sb->m_status & SSF_PAUSED) == 0)) - { - int status = sb_get_status(sb); - - if(!(status & SB_STATUS_PLAYING)) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else if (status & SB_STATUS_INVALID) { - ll_sound_ptr->StopSound(sb->m_unique_id); - } - } - */ - break; - } - } - } - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_unique_id == sound_uid) { - if (sb->m_status != SSF_UNUSED && !(sb->m_status & SSF_PAUSED)) { - sb->m_status |= SSF_PAUSED; - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16 && (sb->m_sound_buffer)) { - sb_stop_buffer(sb); - } - } - break; - } - } -} - -void win_llsSystem::ResumeSound(int sound_uid) { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if (sound_uid == m_sound_mixer.m_sound_cache[current_slot].m_unique_id) { - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED && - (m_sound_mixer.m_sound_cache[current_slot].m_status & SSF_PAUSED)) { - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - PlaySoundBuffer(&m_sound_mixer.m_sound_cache[current_slot], NULL); - } - - m_sound_mixer.m_sound_cache[current_slot].m_status &= (~SSF_PAUSED); - break; - } - } - } -} - -void win_llsSystem::StopAllSounds() { - int current_slot; - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - if (m_sound_mixer.m_sound_cache[current_slot].m_status != SSF_UNUSED) { - StopSound(m_sound_mixer.m_sound_cache[current_slot].m_unique_id); - } - } -} - -// Begin sound frame -void win_llsSystem::SoundStartFrame(void) { - float frame_time; - int current_slot; - int i; - - if (m_timer_last_frametime == -1) { - frame_time = 0.0f; - } else { - frame_time = (timer_GetMSTime() - m_timer_last_frametime) / 1000.0f; - } - m_timer_last_frametime = timer_GetMSTime(); - - // perform necessary functions if sound events are pending for frame, this doesn't have to do anything - // if the mixer doesn't require such actions. Aureal does though. - if (m_pending_actions) { - mprintf(0, "pending actions\n"); - } - - // start mixer dependant frame - m_in_sound_frame = true; - m_pending_actions = false; - - // cleanup sound cache. - // mprintf(0, "StartCleanup\n"); - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - for (i = 0; i < m_sound_mixer.m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[i]; - update_directsound_sb(sb, true); - } - } - // mprintf(0, "EndCleanup\n"); - - int counter = 0, loop_counter = 0, stream_counter = 0, buf_loop_counter = 0; - -#ifdef _DEBUG - int n_p5 = 0, n_p4 = 0, n_p3 = 0, n_p2 = 0, n_p1 = 0, n_p0 = 0; -#endif - - for (current_slot = 0; current_slot < m_sound_mixer.m_max_sounds_played; current_slot++) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - if (sb->m_status != SSF_UNUSED) { - counter++; - if (sb->m_status & SSF_PLAY_LOOPING) { - if (sb->m_status & SSF_BUFFERED_LOOP) - buf_loop_counter++; - loop_counter++; - } - if (sb->m_status & SSF_PLAY_STREAMING) - stream_counter++; - -#ifdef _DEBUG - if (sb->play_info->priority == SND_PRIORITY_CRITICAL) - n_p5++; - else if (sb->play_info->priority == SND_PRIORITY_HIGHEST) - n_p4++; - else if (sb->play_info->priority == SND_PRIORITY_HIGH) - n_p3++; - else if (sb->play_info->priority == SND_PRIORITY_NORMAL) - n_p2++; - else if (sb->play_info->priority == SND_PRIORITY_LOW) - n_p1++; - else if (sb->play_info->priority == SND_PRIORITY_LOWEST) - n_p0++; -#endif - } - } - - // update cache stress timer. - if (counter < (m_sound_mixer.m_max_sounds_played * 3 / 4)) { - m_cache_stress_timer += frame_time; - } else { - m_cache_stress_timer = 0.0f; - } - -#ifdef _DEBUG - mprintf_at(3, 2, 0, "LNS: %02d/%02d", counter, m_sound_mixer.m_max_sounds_played); - mprintf_at(3, 3, 1, "Lp: %02d", loop_counter); - mprintf_at(3, 4, 1, "St: %02d", stream_counter); - mprintf_at(3, 5, 0, " Ot: %02d", counter - loop_counter - stream_counter); - - if (m_sound_mixer.m_loop_method != DSLOOP_STREAM_METHOD && m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - mprintf_at(3, 3, 10, "Bf: %02d", buf_loop_counter); - } - - mprintf_at(3, 2, 20, "P5:%02d P4:%02d P3:%02d", n_p5, n_p4, n_p3); - mprintf_at(3, 3, 20, "P2:%02d P1:%02d P0:%02d", n_p2, n_p1, n_p0); -#endif -} - -// End sound frame -void win_llsSystem::SoundEndFrame(void) { - CheckForErrors(); // handles errors. - - m_in_sound_frame = false; -} - -bool win_llsSystem::LockSound(int sound_uid) { return false; } - -bool win_llsSystem::UnlockSound(int sound_uid) { return false; } - -// True means it was already loaded, false means that it was not -bool win_llsSystem::CheckAndForceSoundDataAlloc(int sound_index) { - int result; - int sound_file_index = Sounds[sound_index].sample_index; - - ASSERT(sound_file_index >= 0 && sound_file_index < MAX_SOUND_FILES); - - if (sound_file_index < 0 || sound_file_index >= MAX_SOUND_FILES) { - return false; - } - - // Check if the sample data is already loaded - if (SoundFiles[sound_file_index].sample_16bit != NULL || SoundFiles[sound_file_index].sample_8bit != NULL) - return true; - - // If not, get the sound data - result = SoundLoadWaveFile(SoundFiles[sound_file_index].name, Sounds[sound_index].import_volume, sound_file_index, - (m_sound_quality == SQT_HIGH), true); - - // Why would it load once (table load time) and not now? - if (!result) - return false; - - mprintf(0, "Sound %s loaded.\n", SoundFiles[sound_file_index].name); - - return true; -} - -bool win_llsSystem::SetSoundQuality(char quality) { - int i; - - if (quality == m_sound_quality) - return true; - - // pause any sounds that may be playing - win_llsSystem::PauseSounds(); - - if (quality == SQT_NORMAL) { - m_sound_quality = SQT_NORMAL; - } else { - m_sound_quality = SQT_HIGH; - } - - for (i = 0; i < MAX_SOUNDS; i++) { - if (Sounds[i].used != 0) { - int j = Sounds[i].sample_index; - - if (SoundFiles[j].sample_8bit && m_sound_quality == SQT_HIGH) { - mem_free(SoundFiles[j].sample_8bit); - SoundFiles[j].sample_8bit = NULL; - - CheckAndForceSoundDataAlloc(i); - } - if (SoundFiles[j].sample_16bit && m_sound_quality == SQT_NORMAL) { - int count; - - ASSERT(SoundFiles[j].sample_8bit == NULL); - SoundFiles[j].sample_8bit = (uint8_t *)mem_malloc(SoundFiles[j].sample_length); - - // NOTE: Interesting note on sound conversion: 16 bit sounds are signed (0 biase). 8 bit sounds are unsigned - // (+128 biase). - for (count = 0; count < (int)SoundFiles[j].sample_length; count++) { - SoundFiles[j].sample_8bit[count] = (uint8_t)((((int)SoundFiles[j].sample_16bit[count]) + 32767) >> 8); - } - - mem_free(SoundFiles[j].sample_16bit); - SoundFiles[j].sample_16bit = NULL; - } - } - } - - win_llsSystem::ResumeSounds(); - - return true; -} - -char win_llsSystem::GetSoundQuality(void) { return m_sound_quality; } - -bool win_llsSystem::SetSoundMixer(char mixer_type) { - if (mixer_type == m_mixer_type) - return true; - else { - // Chris note: This is not the best way to do this. All the currently playing - // sounds are lost. This shouldn't happen. A real solutions has to take in account - // for three things: Normal sounds, looping sounds, and streaming audio. - DestroySoundLib(); - InitSoundLib(mixer_type, SoundApp, m_sound_mixer.m_max_sounds_played); - SetSoundQuality(m_sound_quality); - } - return true; -} - -char win_llsSystem::GetSoundMixer(void) { return m_mixer_type; } - -void win_llsSystem::SetListener(pos_state *cur_pos) { - if (!m_f_sound_lib_init) - return; - - m_emulated_listener.orient = *cur_pos->orient; - m_emulated_listener.position = *cur_pos->position; - m_emulated_listener.velocity = *cur_pos->velocity; - - if (IS_3D_MIXER(m_mixer_type)) { - m_lp_listener->SetOrientation(cur_pos->orient->fvec.x, cur_pos->orient->fvec.y, cur_pos->orient->fvec.z, - cur_pos->orient->uvec.x, cur_pos->orient->uvec.y, cur_pos->orient->uvec.z, - DS3D_DEFERRED); - m_lp_listener->SetPosition(cur_pos->position->x, cur_pos->position->y, cur_pos->position->z, DS3D_DEFERRED); - m_lp_listener->SetVelocity(cur_pos->velocity->x, cur_pos->velocity->y, cur_pos->velocity->z, DS3D_DEFERRED); - m_lp_listener->CommitDeferredSettings(); - } -} - -// AdjustSound2d -- adjusts the volume, pan, and freq. of a sound -void win_llsSystem::AdjustSound(int sound_uid, float f_volume, float f_pan, uint16_t frequency) { - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return; - - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - play_information *play_info = sb->play_info; - - play_info->left_volume = play_info->right_volume = f_volume; - if (f_pan < 0.0) - play_info->right_volume += f_volume * f_pan; - else - play_info->left_volume -= f_volume * f_pan; - - sb_adjust_properties_2d(&m_sound_mixer.m_sound_cache[current_slot], f_volume, f_pan, frequency); - - return; -} - -void win_llsSystem::AdjustSound(int sound_uid, pos_state *cur_pos, float adjusted_volume, float reverb) { - if (!m_f_sound_lib_init) - return; - - LPDIRECTSOUNDBUFFER lp_dsb; - // LPDIRECTSOUND3DBUFFER lpDSB3D; - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return; - - // sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (IS_3D_MIXER(m_mixer_type)) { - int sound_index = m_sound_mixer.m_sound_cache[current_slot].m_sound_index; - lp_dsb = m_sound_mixer.m_sound_cache[current_slot].m_sound_buffer; - if (lp_dsb == NULL) - return; - - sb_adjust_properties_3d(&m_sound_mixer.m_sound_cache[current_slot], adjusted_volume, cur_pos, reverb); - } else { - // We need to determine the pan and volume - float volume; - - volume = adjusted_volume; - - float dist; - vector dir_to_sound = *cur_pos->position - m_emulated_listener.position; - float pan; - - dist = vm_NormalizeVector(&dir_to_sound); - if (dist < .1f) { - dir_to_sound = m_emulated_listener.orient.fvec; - } - - if (dist >= Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].max_distance) { - volume = 0.0f; - } else if (dist > Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance) { - volume *= (1.0 - ((dist - Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance) / - (Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].max_distance - - Sounds[m_sound_mixer.m_sound_cache[current_slot].m_sound_index].min_distance))); - } - - pan = (dir_to_sound * m_emulated_listener.orient.rvec); - - if (volume < 0.0f) - volume = 0.0f; - else if (volume > 1.0f) - volume = 1.0f; - - if (pan < -1.0f) - pan = -1.0f; - else if (pan > 1.0f) - pan = 1.0f; - - AdjustSound(m_sound_mixer.m_sound_cache[current_slot].m_unique_id, volume, pan, 22050); - } - - return; -} - -int win_llsSystem::PlaySound3d(play_information *play_info, int sound_index, pos_state *cur_pos, float adjusted_volume, - bool f_looped, float reverb) { - int16_t sound_slot; - DWORD ds_flags = 0; - float volume; - - volume = adjusted_volume; // Adjust base volume by sent volume, let 3d stuff do the rest - - if (!m_f_sound_lib_init) - return -1; - - ASSERT(Sounds[sound_index].used != 0); - if (Sounds[sound_index].used == 0) - return -1; - - if (!IS_3D_MIXER(m_mixer_type)) { - float dist; - vector dir_to_sound = *cur_pos->position - m_emulated_listener.position; - float pan; - - dist = vm_NormalizeVector(&dir_to_sound); - if (dist < .1f) { - dir_to_sound = m_emulated_listener.orient.fvec; - } - - if (dist >= Sounds[sound_index].max_distance) { - return -1; - } else if (dist > Sounds[sound_index].min_distance) { - volume *= (1.0 - ((dist - Sounds[sound_index].min_distance) / - (Sounds[sound_index].max_distance - Sounds[sound_index].min_distance))); - } - - pan = (dir_to_sound * m_emulated_listener.orient.rvec); - - if (volume < 0.0f) - volume = 0.0f; - else if (volume > 1.0f) - volume = 1.0f; - - if (pan < -1.0f) - pan = -1.0f; - else if (pan > 1.0f) - pan = 1.0f; - - return PlaySound2d(play_info, sound_index, volume, pan, f_looped); - } - -// Out of sound slots -#ifdef _DEBUG - sound_slot = FindFreeSoundSlot(sound_index, volume, play_info->priority); -#else - sound_slot = FindFreeSoundSlot(volume, play_info->priority); -#endif - - if (sound_slot < 0) { - return -1; - } - - m_sound_mixer.m_sound_cache[sound_slot].play_info = play_info; - m_total_sounds_played++; - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id = MakeUniqueId(sound_slot); - ASSERT(m_sound_mixer.m_sound_cache[sound_slot].m_unique_id != -1); - - // 3-D!! - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[sound_slot]; - - sb->m_buffer_type = SBT_3D; - sb->m_sound_index = sound_index; - - if (f_looped) { - LoopStartStreaming(sb, SBT_3D, adjusted_volume, 0.0, cur_pos); - if (sb->m_snd_obj == NULL) { - sb->m_sound_buffer = NULL; - Int3(); - return -1; - } - } else { - tPSBInfo psb; - - if (SoundFiles[Sounds[sound_index].sample_index].use_count > 0) { - if (DuplicateSoundBuffer(sb)) { - goto play_sound; - } - } - if (!CreateSoundBuffer(sb, false)) { - return -1; - } - if (!LoadSoundBuffer(sb)) { - sb_free_buffer(sb); - return -1; - } - - play_sound: - sb->m_status = SSF_PLAY_NORMAL; - - psb.cur_pos = cur_pos; - psb.volume = volume; - psb.freq = 22050; - psb.reverb = reverb; - psb.looping = false; - if (!PlaySoundBuffer(sb, &psb)) { - sb_free_buffer(sb); - return -1; - } -/* - mprintf(0, "SL Play sound on slot %d, TP = %d UI = %X\n", - sound_slot, - TotalSoundsPlayed, - m_sound_mixer.m_sound_cache[sound_slot].m_unique_id); -*/ - } - - m_sound_mixer.m_cur_sounds_played++; - - return (sb->m_unique_id); -} - -// These work in samples to make things easier in the long run -int win_llsSystem::SetSoundPos(int sound_uid, int pos) { - int current_slot; - - if (pos <= 0) - return 1; - - if (!m_f_sound_lib_init) - return -1; - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return -1; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return -1; - - m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played = pos; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - if (sb->stereo) { - pos *= 2; - } - - if (sb->bps == 16) { - pos *= 2; - } - - sb_set_current_position(sb, pos); - } - - return 1; -} - -// These work in samples to make things easier in the long run -int win_llsSystem::GetSoundPos(int sound_uid) { - int current_slot; - uint32_t temp, pos; - - if (!m_f_sound_lib_init) - return -1; - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return -1; - if (m_sound_mixer.m_sound_cache[current_slot].m_status == SSF_UNUSED) - return -1; - - if (m_mixer_type != SOUND_MIXER_SOFTWARE_16) { - sound_buffer_info *sb = &m_sound_mixer.m_sound_cache[current_slot]; - - temp = sb_get_current_position(sb, &pos); - - if (sb->stereo) { - pos /= 2; - } - if (sb->bps == 16) { - pos /= 2; - } - - // Updates the readable data - m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played = pos; - - return pos; - } else { - return m_sound_mixer.m_sound_cache[current_slot].play_info->m_samples_played; - } - - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -bool win_llsSystem::CreateSoundBuffer(sound_buffer_info *sb, bool f_is_stereo, int size, bool dynamic) { - // do buffer creation - int buftype = sb->m_buffer_type; - bool f_sample_16bit; - int sound_length; - - get_sound_info(sb, &sound_length, &f_sample_16bit); - - if (size != -1) { - sound_length = size; - } - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - default: - CreateDSBuffer(buftype, &sb->m_sound_buffer, &sb->m_sound_buffer_3d, sound_length, 22050, f_is_stereo, - f_sample_16bit); - - sb->m_lpksps = NULL; - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - EAX_InitSource(sb->m_sound_buffer_3d, &sb->m_lpksps); - } - - if (!sb->m_sound_buffer) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - } - - sb->m_mixer_type = m_mixer_type; - sb->bps = f_sample_16bit ? 16 : 8; - sb->stereo = f_is_stereo; - - if (sb->m_sound_index > -1) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count++; - // Global_DS_alloced_sounds++; - } - - return true; -} - -bool win_llsSystem::LoadSoundBuffer(sound_buffer_info *sb) { - // play 2d sound - int buftype = sb->m_buffer_type; - bool f_sample_16bit; - char *sample_ptr; - int sound_length; - - // get pointer - sample_ptr = get_sound_info(sb, &sound_length, &f_sample_16bit); - sb->sample_data = sample_ptr; - sb->sample_length = (int)sound_length; - - // do buffer creation - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - default: - if (LoadSoundData(sb->m_sound_buffer, sample_ptr, sound_length) != DS_OK) { - Int3(); - sb->m_status = SSF_UNUSED; - return false; - } - } - - return true; -} - -bool win_llsSystem::PlaySoundBuffer(sound_buffer_info *sb, tPSBInfo *psb) { - bool f_looping; - - if (!m_f_sound_lib_init) - return false; - if (!m_in_sound_frame) - m_pending_actions = true; - -TryPlayAgainLabel: - if (psb) { - if (sb->m_buffer_type == SBT_2D) { - AdjustSound(sb->m_unique_id, psb->volume, psb->pan, psb->freq); - } else if (sb->m_buffer_type == SBT_3D) { - AdjustSound(sb->m_unique_id, psb->cur_pos, psb->volume, psb->reverb); - } - - SetSoundPos(sb->m_unique_id, sb->play_info->m_samples_played); - - f_looping = psb->looping; - } else { - f_looping = ((sb->m_status & SSF_PLAY_LOOPING) || sb->s) ? true : false; - if (f_looping && m_sound_mixer.m_loop_method == DSLOOP_BUFFER_METHOD && sb->s->loop_step != 0 && - (sb->m_status & SSF_BUFFERED_LOOP)) { - f_looping = false; - } - } - - switch (m_mixer_type) { - case SOUND_MIXER_SOFTWARE_16: - Int3(); - break; - - default: { - LPDIRECTSOUNDBUFFER sound_ptr = sb->m_sound_buffer; - DWORD ds_flags = f_looping ? DSBPLAY_LOOPING : 0; - - ASSERT(sound_ptr); - - if (sound_ptr->Play(0, 0, ds_flags) == DSERR_BUFFERLOST) { - if (LoadSoundData(sound_ptr, sb->sample_data, sb->sample_length) == DS_OK) { - goto TryPlayAgainLabel; - } - - sb->m_status = SSF_UNUSED; - - // Some type of error -- we cannot play the sound? -- get chris - Int3(); - return false; - } - } - } - - return true; -} - -bool win_llsSystem::DuplicateSoundBuffer(sound_buffer_info *sb) { - return false; // for now, let's not do this. -/* - sound_buffer_info *source_sb = m_sound_mixer.FindSoundBuffer(sb->m_sound_index); - - ASSERT(m_mixer_type != SOUND_MIXER_SOFTWARE_16); - - if (!source_sb) { - Int3(); - return false; - } - - // we have a source sound buffer. let's use it. - if (m_mixer_type == SOUND_MIXER_AUREAL) { - sb->m_snd_obj = A3D_DuplicateSource(source_sb->m_snd_obj); - if (!sb->m_snd_obj) { - return false; - } - } else { - HRESULT hr; - hr = m_lp_ds->DuplicateSoundBuffer(source_sb->m_sound_buffer, &sb->m_sound_buffer); - if (FAILED(hr)) { - mprintf(0, "DDSNDLIB: Failed to duplicate sound buffer (%x)\n", hr); - return false; - } - - if (IS_3D_MIXER(m_mixer_type)) { - // a 3d buffer needs a 3d interface pointer - if (sb->m_buffer_type == SBT_3D) { - hr = sb->m_sound_buffer->QueryInterface(IID_IDirectSound3DBuffer, (void **)&sb->m_sound_buffer_3d); - if (FAILED(hr)) { - mprintf(0, "DDSNDLIB: Failed to acquire 3d interface from duplicate buffer (%x)\n", hr); - return false; - } - } - } - } - - sb->m_mixer_type = source_sb->m_mixer_type; - sb->bps = source_sb->bps; - sb->stereo = source_sb->stereo; - sb->sample_data = source_sb->sample_data; - sb->sample_length = source_sb->sample_length; - - // mprintf(0, "Duplicated!!\n"); - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count++; - - return true; - */ -} - -// environmental sound interface -// volume modifier (0-1), damping(0-1), 1 = complete, 0 = none -// decay 0.1 to 100 seconds, how long it takes for a sound to die. -bool win_llsSystem::SetGlobalReverbProperties(float volume, float damping, float decay) { - if (m_mixer_type == SOUND_MIXER_CREATIVE_EAX) { - return EAX_SetEnvironmentalReverb(volume, damping, decay); - } - - return false; -} - -sound_buffer_info *sound_buffer_cache::FindSoundBuffer(int sound_index) { - int i; - - // is there's no use count for this soudn, then there should be no available buffer. - if (SoundFiles[Sounds[sound_index].sample_index].use_count == 0) { - return NULL; - } - - // returns a sound buffer with the 'sound_index' if it is still active. - // we can use the sound buffer to create duplicates. - for (i = 0; i < m_max_sounds_played; i++) { - sound_buffer_info *sb = &m_sound_cache[i]; - - if (sb->m_status != SSF_UNUSED) { - if (sb->m_sound_index == sound_index) { - return sb; - } - } - } - - return NULL; -} - -// set special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::SetEnvironmentValues(const t3dEnvironmentValues *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - Env3dValues.doppler_scalar = env->doppler_scalar; - } -} - -// get special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::GetEnvironmentValues(t3dEnvironmentValues *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - env->doppler_scalar = Env3dValues.doppler_scalar; - } -} - -// enable special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::SetEnvironmentToggles(const t3dEnvironmentToggles *env) { - t3dEnvironmentValues values; - - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - // set toggle then set doppler again. - Env3dToggles.doppler = env->doppler; - values.flags = ENV3DVALF_DOPPLER; - values.doppler_scalar = Env3dValues.doppler_scalar; - SetEnvironmentValues(&Env3dValues); - } - if (CHECK_FLAG(env->flags, ENV3DVALF_GEOMETRY)) { - // initialize geometry object if available and true. - if (m_geometry) { - delete m_geometry; - } - m_geometry = NULL; - Env3dToggles.geometry = m_geometry ? true : false; - } -} - -// get states of special parameters for the 3d environment. -// of strcuture passed, you must set the appropriate 'flags' value for values you wish to modify -void win_llsSystem::GetEnvironmentToggles(t3dEnvironmentToggles *env) { - if (CHECK_FLAG(env->flags, ENV3DVALF_DOPPLER)) { - env->doppler = Env3dToggles.doppler; - } - - env->supported = 0; -} - -// Sound System Error Handler. -void win_llsSystem::CheckForErrors() { - // if a fatal error occurred, quit and display an error - // non fatal errors should be put inside a logfile, or just mprinted out. - switch (m_lib_error_code) { - case SSL_ERROR_SAMPLE_NODATA: - Error("%s\nSample had no data.", m_error_text); - break; - - case SSL_ERROR_STREAMMIXER: - Error("%s\nMixer alignment check failed.", m_error_text); - break; - - case SSL_ERROR_GENERIC: - Error("%s\nGeneric error.", m_error_text); - break; - } - - // must call! - llsSystem::CheckForErrors(); - - // add our default error string. - char buf[8]; - sprintf(buf, "mix:%d\n", m_mixer_type); - strcat(m_error_text, buf); -} - -///////////////////////////////////////////////////////////////////////////////////// -// set auxillary 3d sound properties -bool win_llsSystem::SoundPropertySupport() const { - switch (m_mixer_type) { - case SOUND_MIXER_CREATIVE_EAX: - if (EAX_Caps() & EAXF_SOURCE_OBSTRUCTION) { - return true; - } - break; - } - - return false; -} - -// sound obstruction from 0 to 1.0 (1.0 = fully obstructed) -void win_llsSystem::SetSoundProperties(int sound_uid, float obstruction) { - sound_buffer_info *sb; - int current_slot; - - if (!m_f_sound_lib_init) - return; - - if ((current_slot = ValidateUniqueId(sound_uid)) == -1) - return; - - sb = &m_sound_mixer.m_sound_cache[current_slot]; - - switch (m_mixer_type) { - case SOUND_MIXER_CREATIVE_EAX: - EAX_SetSourceProperties(sb->m_lpksps, obstruction); - break; - } -} diff --git a/sndlib/dsound3d.cpp b/sndlib/dsound3d.cpp deleted file mode 100644 index 4af8c3b41..000000000 --- a/sndlib/dsound3d.cpp +++ /dev/null @@ -1,616 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Source: $ - * $Revision: 6 $ - * $Author: Samir $ - * $Date: 5/03/99 3:12a $ - * - * Direct Sound subsystem. - * - * $Log: /DescentIII/Main/dd_sndlib/dsound3d.cpp $ - * - * 6 5/03/99 3:12a Samir - * fixed up aureal so it works (a little slow though...) - * - * 5 4/29/99 3:01p Samir - * added code for direct sound mixers only (and function for Aureal - * really) that will use direct sound looping for simple loops. - * - * 4 4/25/99 9:53p Samir - * added debugging. - * - * 3 4/23/99 7:51p Samir - * looping fixes for directsound. - * - * 2 4/22/99 10:33p Samir - * modifications so that DirectSound mixers use one thread for all looping - * and streaming sounds. It worked without crashing for about twenty - * minutes of playing from level 1 to level 2 of D3. We'll see. - * - * 1 4/22/99 10:30p Samir - * initial revision ( a bit messy) - * - */ - -#include "ds3dlib_internal.h" -#include "auddev.h" - -#include "pserror.h" - -#include - -static struct t_sb_loop_thread_data { - win_llsSystem *m_ll_sndsys; - uintptr_t thread_handle; - int16_t no_callbacks; - bool request_kill; - bool thread_alive; -} m_ds; - -static uint8_t m_sb_cur_timeslice; - -//////////////////////////////////////////////////////////////////////////////// -// DSLOOP_STREAM_METHOD - -inline void sb_loop_thread_clean_buffer(sound_buffer_info *sb) { - m_ds.m_ll_sndsys->GetSoundPos(sb->m_unique_id); - sb_stop_buffer(sb); - sb->s->playing = 0; - sb->s->kill_me = true; - - // TODO: investigate why this is -1 sometimes, 32bit builds seem to work by - // chance while 64bit builds crash without this ckeck - if (sb->m_sound_index < 0) { - return; - } - - if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count > 0) { - SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count--; - // DUPSND if (SoundFiles[Sounds[sb->m_sound_index].sample_index].use_count == 0) { - // Global_DS_alloced_sounds--; - // DUPSND } - } -} - -// helper functions for loop streaming. -void sb_loop_stream_copy(sound_buffer_info *sb, char *ptr, DWORD len) { - DWORD amt; - bool f_looping = (sb->m_status & SSF_PLAY_LOOPING) != 0; - char *sample_ptr; - - if (f_looping) { - const int sound_index = sb->m_sound_index; - int loop_start = Sounds[sound_index].loop_start; - int loop_end = Sounds[sound_index].loop_end; - if (sb->s->f_sample_16bit) { - loop_start = loop_start << 1; - loop_end = loop_end << 1; - sample_ptr = (char *)SoundFiles[Sounds[sound_index].sample_index].sample_16bit; - } else { - sample_ptr = (char *)SoundFiles[Sounds[sound_index].sample_index].sample_8bit; - } - - while (sb->s->num_written + (int)len >= loop_end) { - int num_till_loop_end = loop_end - sb->s->num_written; - int num_to_loop_start = sb->s->num_written - loop_start; - - if (num_till_loop_end > 0) { - memcpy(ptr, sb->s->current_position, num_till_loop_end); - len -= num_till_loop_end; - } - ptr += num_till_loop_end; - - sb->s->current_position = sample_ptr + loop_start; - // ASSERT(sb->s->current_position >= sample_ptr && sample_ptr == sb->sample_data); - - sb->s->num_written -= num_to_loop_start; - sb->s->bytes_left += num_to_loop_start; - - // ASSERT(sb->s->num_written == loop_start); - } - } - - amt = (len > sb->s->bytes_left) ? sb->s->bytes_left : len; - - // int i_amt = (int)amt; - - // ASSERT(i_amt >= 0); - - if (amt) { - memcpy(ptr, sb->s->current_position, amt); - sb->s->current_position += amt; - sb->s->bytes_left -= amt; - sb->s->num_written += amt; - // ASSERT(sb->s->current_position >= sb->sample_data); - } - - len -= amt; - - if (len) { - memset(ptr + amt, sb->s->silence_byte, len); - sb->s->close_on_next = 1; - } -} - -// helper functions for loop streaming. -void sb_loop_stream_fillhalf(sound_buffer_info *sb, DWORD half) { - char *ptr1 = NULL; - char *ptr2 = NULL; - uint32_t len1, len2; - - if (sb_lock_buffer(sb, half, sb->s->half_buffer_point, (void **)&ptr1, &len1, (void **)&ptr2, &len2)) { - // memset(ptr1, sb->s->silence_byte, len1); - sb_loop_stream_copy(sb, ptr1, len1); - if (ptr2) { - sb_loop_stream_copy(sb, ptr2, len2); - } - sb_unlock_buffer(sb, ptr1, len1, ptr2, len2); - } -} - -// helper functions for streaming -void sb_stream_copy(sound_buffer_info *sb, char *ptr, DWORD len) { - DWORD amt; - -new_data: - - amt = (len > sb->s->bytes_left) ? sb->s->bytes_left : len; - - ASSERT(amt >= 0); - - if (amt) { - ASSERT(sb->s->current_position); - - memcpy(ptr, sb->s->current_position, amt); - sb->s->current_position += amt; - sb->s->bytes_left -= amt; - } - - len -= amt; - - if (len) { - if (sb->play_info->m_stream_cback && sb->s->current_position) { - memset(ptr + amt, sb->s->silence_byte, len); - int new_len = sb->play_info->m_stream_size; - sb->s->current_position = - (char *)(*sb->play_info->m_stream_cback)(sb->play_info->user_data, sb->play_info->m_stream_handle, &new_len); - sb->play_info->m_stream_data = sb->s->current_position; - ASSERT(!(sb->play_info->m_stream_data && sb->play_info->m_stream_size <= 0)); - - sb->s->bytes_left = sb->play_info->m_stream_size; - - if (sb->s->current_position == NULL) { - sb->s->bytes_left = sb->play_info->m_stream_size = 0; - } - - goto new_data; - } - - memset(ptr + amt, sb->s->silence_byte, len); - sb->s->close_on_next = 1; - } -} - -void sb_stream_fillhalf(sound_buffer_info *sb, DWORD half) { - char *ptr1 = NULL; - char *ptr2 = NULL; - uint32_t len1, len2; - - if (sb_lock_buffer(sb, half, sb->s->half_buffer_point, (void **)&ptr1, &len1, (void **)&ptr2, &len2)) { - sb_stream_copy(sb, ptr1, len1); - if (ptr2) { - sb_stream_copy(sb, ptr2, len2); - } - sb_unlock_buffer(sb, ptr1, len1, ptr2, len2); - } -} - -// main looping thread. -void __cdecl sb_loop_thread(void *user_ptr) { - sound_buffer_cache *sndcache; - DWORD playp, writep, whichhalf; - int i; - uint8_t iteration; - - // validate thread - m_ds.m_ll_sndsys = (win_llsSystem *)user_ptr; - m_ds.thread_alive = true; - sndcache = &m_ds.m_ll_sndsys->m_sound_mixer; - iteration = 0; - - mprintf(0, "DS3DLIB: Looping thread begins.\n"); - - // main thread body - while (!m_ds.request_kill) { - if (m_ds.no_callbacks++ == 0) { - for (i = 0; i < sndcache->m_max_sounds_played; i++) { - sound_buffer_info *sb = &sndcache->m_sound_cache[i]; - - // skip unused slots and only handle looping (maybe streaming) slots. - if ((sb->m_status == SSF_UNUSED) || (sb->m_status & SSF_BUFFERED_LOOP) || !sb->s) { - continue; - } - if (!sb->s->playing) { // loops before calling play do have SSF_PLAY_LOOPING set, and MUST!! - continue; - } - - // at this point it's definitely either a streaming buffer or loop streaming buffer - if (sb->m_status & SSF_PLAY_STREAMING) { - // streams will stop at the request of the application always, unlike looping buffers (see below) - if (sb->s->please_close) { - sb_loop_thread_clean_buffer(sb); - // mprintf(0, "ds thread pleas_close request processed.\n"); - } else if (sb->m_status & SSF_PAUSED) { - continue; // just continue - } else if ((iteration % 4) == (sb->s->time_slice % 4)) { - // update streamed buffer only when allowed - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - if (sb->s->close_on_next) { - sb_loop_thread_clean_buffer(sb); - } else { - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - // mprintf(0, "ds thread stream update.\n"); - } - } else if (!(sb->m_status & SSF_BUFFERED_LOOP)) { - // this slot is a looping slot. check to see if app requested closing this loop. - // also we don't check the looping flag because we could be playing the end part of a loop - // and the stream filling code below will set close_on_next when done itself. - if (sb->s->please_close) { - sb_loop_thread_clean_buffer(sb); - } else if (sb->m_status & SSF_PAUSED) { - continue; // just continue - } else if ((iteration % 4) == (sb->s->time_slice % 4)) { - // update looped buffer only when allowed - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - if (sb->s->close_on_next) { - sb_loop_thread_clean_buffer(sb); - } else { - sb_loop_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - } - } - } - iteration++; - } - m_ds.no_callbacks--; - Sleep(DSPB_TICK_MILLISECONDS); // defer to OS - } - - // invalidate thread - m_ds.thread_alive = false; - m_ds.m_ll_sndsys = NULL; - mprintf(0, "DS3DLIB: Looping thread done.\n"); -} - -/////////////////////////////////////////////////////////////////////////////// -// this will initialize the looping thread - -bool sb_loop_thread_init(win_llsSystem *lls) { - // start looping thread - m_sb_cur_timeslice = 0; - - m_ds.request_kill = false; - m_ds.thread_alive = false; - m_ds.no_callbacks = 1; - - m_ds.thread_handle = _beginthread(sb_loop_thread, 16384, (void *)lls); - if (m_ds.thread_handle == -1) { - return false; - } - if (!SetThreadPriority((HANDLE)m_ds.thread_handle, THREAD_PRIORITY_TIME_CRITICAL)) { - return false; - } - - m_ds.no_callbacks = 0; - - return true; -} - -void sb_loop_thread_kill() { - if (m_ds.thread_alive) { - mprintf(0, "DS3DLIB: Killing looping thread.\n"); - m_ds.request_kill = true; - while (m_ds.thread_alive) { - Sleep(DSPB_TICK_MILLISECONDS); - } - } -} - -// a lot of looping info will be initialized here, including copying data, etc. -bool sb_loop_element_init(sound_buffer_info *sb, char *sample_ptr, int sound_length, int buffer_size) { - // finish initting loop - if (!sb->s) { - Int3(); - return false; - } - - sb->s->time_slice = m_sb_cur_timeslice; // allocate timeslice for updating. - sb->s->half_buffer_point = buffer_size / 2; - sb->s->current_position = sample_ptr; - sb->s->bytes_left = sound_length; - sb->s->silence_byte = (sb->s->f_sample_16bit) ? 0 : 128; - sb_loop_stream_fillhalf(sb, 0); - sb_loop_stream_fillhalf(sb, sb->s->half_buffer_point); - - sb->s->close_on_next = 0; - sb->s->kill_me = false; - m_ds.m_ll_sndsys->SetSoundPos(sb->m_unique_id, sb->play_info->m_samples_played); - - m_sb_cur_timeslice++; - - return true; -} - -void sb_loop_element_kill(sound_buffer_info *sb) { sb->s->please_close = 1; } - -void sb_loop_element_wait_until_dead(sound_buffer_info *sb) { - if (!sb->s) - return; - - while (!sb->s->kill_me) { - } -} - -// initialize streaming audio. -bool sb_stream_element_init(sound_buffer_info *sb, char *sample_ptr, int sound_length, int buffer_size) { - // finish initting loop - if (!sb->s) { - Int3(); - return false; - } - - sb->s->time_slice = m_sb_cur_timeslice; // allocate timeslice for updating. - - sb->s->half_buffer_point = buffer_size / 2; - sb->s->current_position = sample_ptr; - sb->s->bytes_left = sound_length; - sb->s->silence_byte = (sb->s->f_sample_16bit) ? 0 : 128; - sb_stream_fillhalf(sb, 0); - sb_stream_fillhalf(sb, sb->s->half_buffer_point); - sb->s->close_on_next = 0; - sb->s->kill_me = false; - - if (sb->m_status & SSF_BUFFERED_STRM) { - sb->s->hEvent = NULL; - /* sb->s->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (sb->m_mixer_type == SOUND_MIXER_AUREAL) { - if (!A3D_SetSourceWaveEvent(sb->m_snd_obj, sb->s->half_buffer_point, sb->s->hEvent)) { - CloseHandle(sb->s->hEvent); - sb->s->hEvent = NULL; - return false; - } - } - else { - Int3(); - // unimplemented for normal DirectSound CloseHandle(sb->s->hEvent); sb->s->hEvent = NULL; - } - */ - } - - m_sb_cur_timeslice++; - - return true; -} - -// these work on buffered streams only -void sb_stream_element_kill(sound_buffer_info *sb) { - if (sb->m_status & SSF_BUFFERED_STRM) { - if (sb->s->hEvent) { - CloseHandle(sb->s->hEvent); - sb->s->hEvent = NULL; - } - } -} - -void sb_stream_buffered_update(sound_buffer_info *sb) { - DWORD playp, writep, whichhalf; - ASSERT((sb->m_status & SSF_BUFFERED_STRM)); - - playp = sb_get_current_position(sb, (uint32_t *)&writep); - whichhalf = (playp < sb->s->half_buffer_point) ? 0 : sb->s->half_buffer_point; - - if (whichhalf != sb->s->last_half) { - // mprintf(0, "DSOUND3D: event triggered. Updating stream half %d.\n", sb->s->last_half); - if (sb->s->close_on_next) { - extern win_llsSystem *ll_sound_ptr; - ll_sound_ptr->StopSound(sb->m_unique_id); - } else { - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = whichhalf; - } - } - - /* if (WaitForSingleObject(sb->s->hEvent, 0) == WAIT_OBJECT_0) { - // event was signaled by DirectSound/Aureal. do appropriate stream fill. - if (sb->s->close_on_next) { - extern win_llsSystem *ll_sound_ptr; - ll_sound_ptr->StopSound(sb->m_unique_id); - } - else { - mprintf(0, "DSOUND3D: event triggered. Updating stream half %d.\n", sb->s->last_half); - A3D_ClearSourceWaveEvents(sb->m_snd_obj); - sb_stream_fillhalf(sb, sb->s->last_half); - sb->s->last_half = (sb->s->last_half) ? 0 : sb->s->half_buffer_point; - ResetEvent(sb->s->hEvent); - if (sb->m_mixer_type == SOUND_MIXER_AUREAL) { - A3D_SetSourceWaveEvent(sb->m_snd_obj, sb->s->last_half, sb->s->hEvent); - } - else { - Int3(); - } - } - } - */ -} - -//////////////////////////////////////////////////////////////////////////////// -// DSLOOP_BUFFER_METHOD - -char *sb_get_loop_info(const sound_buffer_info *sb, int *loop_start, int *loop_end, bool *is_16_bit) { - int sound_index = sb->m_sound_index; - - if (sound_index > -1) { - *loop_start = Sounds[sound_index].loop_start; - *loop_end = Sounds[sound_index].loop_end; - - if (SoundFiles[Sounds[sound_index].sample_index].sample_16bit) { - *is_16_bit = true; - return (char *)SoundFiles[Sounds[sound_index].sample_index].sample_16bit; - } - if (SoundFiles[Sounds[sound_index].sample_index].sample_8bit) { - *is_16_bit = false; - return (char *)SoundFiles[Sounds[sound_index].sample_index].sample_8bit; - } - } - Int3(); - return NULL; -} - -char *sb_get_loop_step_info(const sound_buffer_info *sb, int step, bool is16bit, int *length) { - sound_file_info *sf; - char *sample_ptr; - - if (sb->m_sound_index < 0) { - Int3(); - return NULL; - } - - int loop_start_byte = Sounds[sb->m_sound_index].loop_start; - int loop_end_byte = Sounds[sb->m_sound_index].loop_end; - - if (is16bit) { - loop_start_byte = loop_start_byte << 1; - loop_end_byte = loop_end_byte << 1; - } - - sf = &SoundFiles[Sounds[sb->m_sound_index].sample_index]; - sample_ptr = is16bit ? (char *)sf->sample_16bit : (char *)sf->sample_8bit; - - if (step == DSBUFLOOP_INIT_STEP) { - *length = loop_start_byte; - return sample_ptr; - } - if (step == DSBUFLOOP_LOOP_STEP) { - *length = (loop_end_byte - loop_start_byte); - return (sample_ptr + loop_start_byte); - } - if (step == DSBUFLOOP_FINISH_STEP) { - int sample_length_byte = is16bit ? (sf->np_sample_length * 2) : sf->np_sample_length; - *length = (sample_length_byte - loop_end_byte); - return (sample_ptr + loop_end_byte); - } - - Int3(); // illegal step!! - *length = 0; - - return NULL; -} - -// steps to next state of buffered loop. -// force_next_step = -2, do it automatically, otherwise set 'next_step' using passed value. -// this will stop and free the current ds object -// advance to next valid step (may skip a step) -// if new step is > 1, then we're done. -// else create and play the new one if we can. - -// before destroying old object, we must get the current sound properties depending on buffer type. -// and set them for the new sound object. -// we will call either direct sound or custom mixer functions. -// yuck. - -void sb_buffered_loop_step(win_llsSystem *lls, sound_buffer_info *sb, int force_next_step) { - if (!sb->s) - return; - if (!(sb->m_status & SSF_BUFFERED_LOOP)) - return; - - tPSBInfo psb; - char *sample_ptr; - int sound_length; - - pos_state old_pos_state; - float old_pan; - float old_volume = 0.0f; - - ASSERT(lls->m_mixer_type != SOUND_MIXER_SOFTWARE_16 && lls->m_mixer_type != SOUND_MIXER_NONE); - - // get current properties. - old_pan = 0; - - // advance to next step. - sound_length = 0; - sb->s->loop_step = (force_next_step == -2) ? (sb->s->loop_step + 1) : force_next_step; - while (!sound_length && sb->s->loop_step < 2) { - sample_ptr = sb_get_loop_step_info(sb, sb->s->loop_step, sb->s->f_sample_16bit, &sound_length); - sb->s->loop_step++; - } - if (!sound_length && sb->s->loop_step == 2) { - // mprintf(0, "DS3DLIB: Buffered loop %d advancing to post-end step (done)\n", sb->m_unique_id); - lls->StopSound(sb->m_unique_id); - return; - } else { - sb_stop_buffer(sb); - sb_free_buffer(sb); - } - - sb->s->loop_step--; // return to proper step. - sb->s->loop_timer = 0.0f; - sb->s->bytes_left = sound_length; - sb->m_status = SSF_PLAY_LOOPING | SSF_BUFFERED_LOOP; - sb->sample_data = sample_ptr; - - // allocate buffer for playback - if (!lls->CreateSoundBuffer(sb, false, sb->s->bytes_left, true)) { - return; - } - - if (!sb_load_buffer(sb, sb->sample_data, sound_length)) { - return; - } - - // using old sound properties, play the next buffer with those qualities! - psb.looping = (sb->s->loop_step == 0) ? true : false; - - if (sb->m_buffer_type == SBT_3D) { - psb.cur_pos = &old_pos_state; - } else { - psb.pan = old_pan; - } - - psb.volume = old_volume; - psb.freq = 22050; - lls->PlaySoundBuffer(sb, &psb); - - // must be at end to initiate thread management. - sb->s->playing = 1; - - // mprintf(0, "DDSNDLIB: Buffered loop %d advancing to step %d.\n", sb->m_unique_id, sb->s->loop_step); -} diff --git a/sndlib/eax.cpp b/sndlib/eax.cpp deleted file mode 100644 index 823c77393..000000000 --- a/sndlib/eax.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . - ---- HISTORICAL COMMENTS FOLLOW --- - - * $Source: $ - * $Revision: 10 $ - * $Author: Samir $ - * $Date: 9/27/99 5:38p $ - * - * - * - * $Log: /DescentIII/Main/dd_sndlib/eax.cpp $ - * - * 10 9/27/99 5:38p Samir - * EAX 2.0->1.0 compatibility checkin. - * - * 9 8/24/99 3:42p Samir - * load EAX dynamically - * - * 8 8/24/99 1:47p Samir - * updated header file. - * - * 7 8/23/99 5:29p Samir - * incremental EAX 2.0 checkin - * - * 6 1/11/99 5:54p Samir - * made environment a hangar. - * - * 5 1/11/99 5:52p Samir - * updated EAX support. - * - * 4 1/08/99 6:31p Samir - * added reverb - * - * 3 12/23/98 11:50a Samir - * - * 2 12/23/98 11:48a Samir - * basic functionality. - * - * 1 12/21/98 7:06p Samir - * Creative Labs EAX - * - */ - -#include "auddev.h" - -#include -#include - -#include "eax.h" -#include "eax2.h" -#include "pserror.h" - -// DATA -#define EAX_ENVIRONMENTS_AVAILABLE (1 << 0) -#define VOICE_MANAGMENT_AVAILABLE (1 << 1) - -struct { - HINSTANCE m_dll; - LPDIRECTSOUND m_lpds; - LPDIRECTSOUNDBUFFER m_lpdsb; - LPKSPROPERTYSET m_lpksps; - DWORD m_dwSoundProperties; - VmMode m_vmode; - EAX_REVERBPROPERTIES m_preset; -} EAX = {NULL, NULL, 0, 0, 0}; - -const EAX_REVERBPROPERTIES EAX_Environments[EAX_ENVIRONMENT_COUNT] = { - {EAX_PRESET_GENERIC}, {EAX_PRESET_PADDEDCELL}, {EAX_PRESET_ROOM}, {EAX_PRESET_BATHROOM}, - {EAX_PRESET_LIVINGROOM}, {EAX_PRESET_STONEROOM}, {EAX_PRESET_AUDITORIUM}, {EAX_PRESET_CONCERTHALL}, - {EAX_PRESET_CAVE}, {EAX_PRESET_ARENA}, {EAX_PRESET_HANGAR}, {EAX_PRESET_CARPETEDHALLWAY}, - {EAX_PRESET_HALLWAY}, {EAX_PRESET_STONECORRIDOR}, {EAX_PRESET_ALLEY}, {EAX_PRESET_FOREST}, - {EAX_PRESET_CITY}, {EAX_PRESET_MOUNTAINS}, {EAX_PRESET_QUARRY}, {EAX_PRESET_PLAIN}, - {EAX_PRESET_PARKINGLOT}, {EAX_PRESET_SEWERPIPE}, {EAX_PRESET_UNDERWATER}, {EAX_PRESET_DRUGGED}, - {EAX_PRESET_DIZZY}, {EAX_PRESET_PSYCHOTIC}}; - -// FUNCTIONS - -HRESULT(FAR PASCAL *DLLEAXDirectSoundCreate)(GUID *, LPDIRECTSOUND *, IUnknown FAR *) = NULL; - -// EAX 1.0 support. -bool EAX_SetEnvironmentPreset(unsigned environment); -bool EAX_SetEnvironmentalReverb(float volume, float damping, float decay); - -// CODE -bool EAX_Create(GUID *pGuid, LPDIRECTSOUND *lpds) { - HRESULT hr; - - EAX.m_dll = LoadLibrary("eax.dll"); - if (EAX.m_dll) { - DLLEAXDirectSoundCreate = (LPEAXDIRECTSOUNDCREATE)GetProcAddress(EAX.m_dll, "EAXDirectSoundCreate"); - if (!DLLEAXDirectSoundCreate) { - Error("EAX DLL doesn't contain latest code for 2.0 functionality."); - return false; - } - - mprintf(0, "EAX 2.0 support detected.\n"); - hr = (*DLLEAXDirectSoundCreate)(pGuid, &EAX.m_lpds, NULL); - } else { - mprintf(0, "EAX 1.0 support detected.\n"); - hr = DirectSoundCreate(pGuid, &EAX.m_lpds, NULL); - } - - if (hr != DS_OK) { - *lpds = NULL; - return false; - } - EAX.m_lpdsb = NULL; - EAX.m_dwSoundProperties = 0; - - *lpds = EAX.m_lpds; - - return true; -} - -void EAX_Destroy() { - if (EAX.m_lpds) { - if (EAX.m_lpksps != NULL) { - EAX.m_lpksps->Release(); - EAX.m_lpksps = NULL; - } - if (EAX.m_lpdsb) { - EAX.m_lpdsb->Release(); - EAX.m_lpdsb = NULL; - } - EAX.m_lpds->Release(); - EAX.m_lpds = NULL; - } - if (EAX.m_dll) { - FreeLibrary(EAX.m_dll); - EAX.m_dll = NULL; - DLLEAXDirectSoundCreate = NULL; - } - EAX.m_dwSoundProperties = 0; -} - -// returns EAX caps -int EAX_Caps() { return EAX.m_dwSoundProperties; } - -// initializes EAX specific interfaces. -bool EAX_SetPrimaryBuffer() { - HRESULT hr; - DWORD support; - bool retval = true; - WAVEFORMATEX wave; - DSBUFFERDESC dsbdesc; - EAX_REVERBPROPERTIES props = {EAX_PRESET_HANGAR}; - - ASSERT(EAX.m_lpds); - - memset(&wave, 0, sizeof(WAVEFORMATEX)); - wave.wFormatTag = WAVE_FORMAT_PCM; - wave.nChannels = 2; - wave.nSamplesPerSec = 22050; - wave.wBitsPerSample = 16; - wave.nBlockAlign = wave.wBitsPerSample / 8 * wave.nChannels; - wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockAlign; - - memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRL3D; - dsbdesc.dwBufferBytes = DSBSIZE_MIN * 2; - dsbdesc.lpwfxFormat = &wave; - - if (FAILED(EAX.m_lpds->CreateSoundBuffer(&dsbdesc, &EAX.m_lpdsb, NULL))) { - return false; - } - - if (EAX.m_lpksps == NULL) { - if (FAILED(EAX.m_lpdsb->QueryInterface(IID_IKsPropertySet, (LPVOID *)&EAX.m_lpksps))) { - mprintf(0, "EAX: Error failed to query property set interface.\n"); - Int3(); - retval = false; - goto error_sub; - } - } - - // now, query support depending on EAX 2.0 availability - if (EAX.m_dll) { - hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, &support); - if (SUCCEEDED(hr)) { - if ((support & (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) == - (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) { - EAX.m_dwSoundProperties |= EAX_ENVIRONMENTS_AVAILABLE; - } - } - - hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTION, &support); - if (SUCCEEDED(hr)) { - if ((support & (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) == - (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) { - EAX.m_dwSoundProperties |= EAXF_SOURCE_OBSTRUCTION; - } - } - } else { - hr = EAX.m_lpksps->QuerySupport(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_ALL, &support); - if (SUCCEEDED(hr)) { - if ((support & KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET) == - (KSPROPERTY_SUPPORT_SET | KSPROPERTY_SUPPORT_GET)) { - EAX.m_dwSoundProperties |= EAX_ENVIRONMENTS_AVAILABLE; - /* - Here the reverb environment is initialized to off. - */ - EAX_SetEnvironmentPreset(EAX_ENVIRONMENT_HANGAR); - } - } - } - - retval = (EAX.m_dwSoundProperties & EAX_ENVIRONMENTS_AVAILABLE) ? true : false; - EAX_SetEnvironmentalReverb(props.fVolume, props.fDamping, props.fDecayTime_sec); - -error_sub: - if (retval == false) { - mprintf(0, "EAX: Error failed to query environmental support.\n"); - Int3(); - if (EAX.m_lpksps) { - EAX.m_lpksps->Release(); - EAX.m_lpksps = NULL; - } - } - - return retval; -} - -/* - - This routine can be used to change the current EAX preset environment. The environment applies - to all 3D buffers. - -*/ -// sets up current global environment reverb -bool EAX_SetEnvironmentalReverb(float volume, float damping, float decay) { - if (EAX.m_dwSoundProperties & EAX_ENVIRONMENTS_AVAILABLE) { - int i; - - EAX.m_preset.environment = EAX_ENVIRONMENT_GENERIC; - EAX.m_preset.fVolume = volume; - EAX.m_preset.fDecayTime_sec = decay; - EAX.m_preset.fDamping = damping; - - if (EAX.m_dll) { - for (i = 0; i < EAX_ENVIRONMENT_COUNT; i++) { - if (volume == EAX_Environments[i].fVolume && damping == EAX_Environments[i].fDamping && - decay == EAX_Environments[i].fDecayTime_sec) { - EAX.m_preset.environment = (uint32_t)i; - break; - } - } - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, NULL, 0, - &EAX.m_preset.environment, sizeof(uint32_t)))) { - return false; - } - } else { - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_VOLUME, NULL, 0, - &EAX.m_preset.fVolume, sizeof(float)))) { - return false; - } - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_DECAYTIME, NULL, 0, - &EAX.m_preset.fDecayTime_sec, sizeof(float)))) { - return false; - } - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_DAMPING, NULL, 0, - &EAX.m_preset.fDamping, sizeof(float)))) { - return false; - } - } - - return true; - } - - return false; -} - -// intializes a sound source for EAX -bool EAX_InitSource(LPDIRECTSOUND3DBUFFER lpBuffer3D, LPKSPROPERTYSET *plpksp) { - if (!lpBuffer3D) - return true; - - if (SUCCEEDED(lpBuffer3D->QueryInterface(IID_IKsPropertySet, (void **)plpksp))) { - return true; - } - - return false; -} - -// frees an eax sound source -void EAX_FreeSource(LPKSPROPERTYSET lpksp) { - if (lpksp) { - lpksp->Release(); - } -} - -// sets source properties -void EAX_SetSourceProperties(LPKSPROPERTYSET lpksp, float obstruction) { - if (!lpksp) - return; - - if (EAX.m_dwSoundProperties & EAXF_SOURCE_OBSTRUCTION) { - LONG lValue = (DWORD)(-10000 * obstruction); - lpksp->Set(DSPROPSETID_EAX_BufferProperties, DSPROPERTY_EAXBUFFER_OBSTRUCTION, NULL, 0, &lValue, sizeof(LONG)); - } -} - -/* - - This routine can be used to change the current EAX preset environment. The environment applies - to all 3D buffers. - -*/ -// sets up current global environment reverb -bool EAX_SetEnvironmentPreset(unsigned environment) { - EAX.m_preset.environment = environment; - - if (FAILED(EAX.m_lpksps->Set(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_ENVIRONMENT, NULL, 0, - &EAX.m_preset.environment, sizeof(float)))) { - return false; - } - - return true; -} diff --git a/sndlib/eax.h b/sndlib/eax.h deleted file mode 100644 index f11b928c8..000000000 --- a/sndlib/eax.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . -*/ - - -// EAX.H -- DirectSound Environmental Audio Extensions - -#ifndef EAX_H_INCLUDED -#define EAX_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// EAX (listener) reverb property set {4a4e6fc1-c341-11d1-b73a-444553540000} -DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties, 0x4a4e6fc1, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, - 0x00); - -enum DSPROPERTY_EAX_REVERBPROPERTY { - DSPROPERTY_EAX_ALL, // all reverb properties - DSPROPERTY_EAX_ENVIRONMENT, // standard environment no. - DSPROPERTY_EAX_VOLUME, // loudness of the reverb - DSPROPERTY_EAX_DECAYTIME, // how long the reverb lasts - DSPROPERTY_EAX_DAMPING // the high frequencies decay faster -}; - -#define EAX_NUM_STANDARD_PROPERTIES (DSPROPERTY_EAX_DAMPING + 1) - -// use this structure for get/set all properties... -struct EAX_REVERBPROPERTIES { - uint32_t environment; // 0 to EAX_ENVIRONMENT_COUNT-1 - float fVolume; // 0 to 1 - float fDecayTime_sec; // seconds, 0.1 to 100 - float fDamping; // 0 to 1 -}; - -// #define EAX_MAX_ENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) - -// presets -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F - -// EAX buffer reverb property set {4a4e6fc0-c341-11d1-b73a-444553540000} -DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties, 0x4a4e6fc0, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, - 0x00, 0x00); - -enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY { - DSPROPERTY_EAXBUFFER_ALL, // all reverb buffer properties - DSPROPERTY_EAXBUFFER_REVERBMIX // the wet source amount -}; - -// use this structure for get/set all properties... -struct EAXBUFFER_REVERBPROPERTIES { - float fMix; // linear factor, 0.0F to 1.0F -}; - -#define EAX_REVERBMIX_USEDISTANCE \ - -1.0F // out of normal range - // signifies the reverb engine should - // calculate it's own reverb mix value - // based on distance - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/sndlib/eax2.h b/sndlib/eax2.h deleted file mode 100644 index 35b02f332..000000000 --- a/sndlib/eax2.h +++ /dev/null @@ -1,404 +0,0 @@ -/* -* Descent 3 -* Copyright (C) 2024 Parallax Software -* -* 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 3 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, see . -*/ - -/****************************************************************** - * - * EAX.H - DirectSound3D Environmental Audio Extensions version 2.0 - * Updated June 18, 1999 - * - ******************************************************************* - */ - -#ifndef EAX2_H_INCLUDED -#define EAX2_H_INCLUDED - -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#pragma pack(push, 4) - -/* - EAX Wrapper Interface -*/ -// {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} -DEFINE_GUID(CLSID_EAXDirectSound, 0x4ff53b81, 0x1ce0, 0x11d3, 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); - -__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID *, LPDIRECTSOUND *, IUnknown FAR *); - -typedef HRESULT(FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID *, LPDIRECTSOUND *, IUnknown FAR *); - -/* - * EAX 2.0 listener property set {0306A6A8-B224-11d2-99E5-0000E8D8C722} - */ -DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties, 0x306a6a8, 0xb224, 0x11d2, 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, - 0x22); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX20_ListenerProperties - -enum DSPROPERTY_EAX_LISTENERPROPERTY { - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_FLAGS -}; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | DSPROPERTY_EAXLISTENER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times are in seconds -// - the reference for high frequency controls is 5 kHz -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -struct EAXLISTENERPROPERTIES { - LONG lRoom; // room effect level at low frequencies - LONG lRoomHF; // room effect high-frequency level re. low frequency level - FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - FLOAT flDecayTime; // reverberation decay time at low frequencies - FLOAT flDecayHFRatio; // high-frequency to low-frequency decay time ratio - LONG lReflections; // early reflections level relative to room effect - FLOAT flReflectionsDelay; // initial reflection delay time - LONG lReverb; // late reverberation level relative to room effect - FLOAT flReverbDelay; // late reverberation delay time relative to initial reflection - DWORD dwEnvironment; // sets all listener properties - FLOAT flEnvironmentSize; // environment size in meters - FLOAT flEnvironmentDiffusion; // environment diffusion - FLOAT flAirAbsorptionHF; // change in level per meter at 5 kHz - DWORD dwFlags; // modifies the behavior of properties -}; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum { - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFFC0 // reserved future use - -// property ranges and defaults: - -#define EAXLISTENER_MINROOM -10000 -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM -1000 - -#define EAXLISTENER_MINROOMHF -10000 -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF -100 - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINREFLECTIONS -10000 -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS -2602 - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB -10000 -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF -100.0f -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF -5.0f - -#define EAXLISTENER_DEFAULTFLAGS \ - (EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REFLECTIONSSCALE | EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | EAXLISTENERFLAGS_REVERBDELAYSCALE | EAXLISTENERFLAGS_DECAYHFLIMIT) - -/* - * EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722} - */ -DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties, 0x306a6a7, 0xb224, 0x11d2, 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, - 0x22); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX20_BufferProperties - -enum DSPROPERTY_EAX_BUFFERPROPERTY { - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -}; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -struct EAXBUFFERPROPERTIES { - LONG lDirect; // direct path level - LONG lDirectHF; // direct path level at high frequencies - LONG lRoom; // room effect level - LONG lRoomHF; // room effect level at high frequencies - FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - LONG lObstruction; // main obstruction control (attenuation at high frequencies) - FLOAT flObstructionLFRatio; // obstruction low-frequency level re. main control - LONG lOcclusion; // main occlusion control (attenuation at high frequencies) - FLOAT flOcclusionLFRatio; // occlusion low-frequency level re. main control - FLOAT flOcclusionRoomRatio; // occlusion room effect level re. main control - LONG lOutsideVolumeHF; // outside sound cone level at high frequencies - FLOAT flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - DWORD dwFlags; // modifies the behavior of properties -}; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// property ranges and defaults: - -#define EAXBUFFER_MINDIRECT -10000 -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF -10000 -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM -10000 -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF -10000 -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINOBSTRUCTION -10000 -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION -10000 -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 0.5f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF -10000 -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO | EAXBUFFERFLAGS_ROOMHFAUTO) - -// Material transmission presets -// 3 values in this order: -// 1: occlusion (or obstruction) -// 2: occlusion LF Ratio (or obstruction LF Ratio) -// 3: occlusion Room Ratio - -// Single window material preset -#define EAX_MATERIAL_SINGLEWINDOW -2800 -#define EAX_MATERIAL_SINGLEWINDOWLF 0.71 -#define EAX_MATERIAL_SINGLEWINDOWROOMRATIO 0.43 - -// Double window material preset -#define EAX_MATERIAL_DOUBLEWINDOW -5000 -#define EAX_MATERIAL_DOUBLEWINDOWHF 0.40 -#define EAX_MATERIAL_DOUBLEWINDOWROOMRATIO 0.24 - -// Thin door material preset -#define EAX_MATERIAL_THINDOOR -1800 -#define EAX_MATERIAL_THINDOORLF 0.66 -#define EAX_MATERIAL_THINDOORROOMRATIO 0.66 - -// Thick door material preset -#define EAX_MATERIAL_THICKDOOR -4400 -#define EAX_MATERIAL_THICKDOORLF 0.64 -#define EAX_MATERIAL_THICKDOORROOMRTATION 0.27 - -// Wood wall material preset -#define EAX_MATERIAL_WOODWALL -4000 -#define EAX_MATERIAL_WOODWALLLF 0.50 -#define EAX_MATERIAL_WOODWALLROOMRATIO 0.30 - -// Brick wall material preset -#define EAX_MATERIAL_BRICKWALL -5000 -#define EAX_MATERIAL_BRICKWALLLF 0.60 -#define EAX_MATERIAL_BRICKWALLROOMRATIO 0.24 - -// Stone wall material preset -#define EAX_MATERIAL_STONEWALL -6000 -#define EAX_MATERIAL_STONEWALLLF 0.68 -#define EAX_MATERIAL_STONEWALLROOMRATIO 0.20 - -// Curtain material preset -#define EAX_MATERIAL_CURTAIN -1200 -#define EAX_MATERIAL_CURTAINLF 0.15 -#define EAX_MATERIAL_CURTAINROOMRATIO 1.00 - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/sndlib/hlsoundlib.cpp b/sndlib/hlsoundlib.cpp index f5223a2e0..19d00008d 100644 --- a/sndlib/hlsoundlib.cpp +++ b/sndlib/hlsoundlib.cpp @@ -464,11 +464,7 @@ #include "voice.h" #include "descent.h" -#if defined(WIN32) -#include "ds3dlib.h" -#elif defined(__LINUX__) #include "sdlsound.h" -#endif hlsSystem Sound_system; char Sound_quality = SQT_NORMAL; @@ -528,11 +524,7 @@ int hlsSystem::InitSoundLib(oeApplication *sos, char mixer_type, char quality, b // Create and initialize the low-level sound library if (m_ll_sound_ptr == NULL) -#if defined(WIN32) - m_ll_sound_ptr = new win_llsSystem; -#elif defined(__LINUX__) m_ll_sound_ptr = new lnxsound; -#endif ASSERT(m_ll_sound_ptr); if (m_ll_sound_ptr == NULL) return 0; diff --git a/sndlib/sdlsound.cpp b/sndlib/sdlsound.cpp index ce84b5bc2..cdb87f3c1 100644 --- a/sndlib/sdlsound.cpp +++ b/sndlib/sdlsound.cpp @@ -99,7 +99,7 @@ int lnxsound::InitSoundLib(char mixer_type, oeApplication *sos, uint8_t max_soun spec.callback = StreamAudio; spec.userdata = &m_mixer; - sound_device = SDL_OpenAudioDevice(nullptr, 0, &spec, nullptr, SDL_AUDIO_ALLOW_ANY_CHANGE); + sound_device = SDL_OpenAudioDevice(nullptr, 0, &spec, nullptr, 0); if (sound_device == 0) { strcpy(m_error_text, SDL_GetError()); return false; diff --git a/vcpkg.json b/vcpkg.json index 73e1e6871..56db60f8a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,17 @@ { - "builtin-baseline": "000d1bda1ffa95a73e0b40334fa4103d6f4d3d48", + "builtin-baseline": "f7423ee180c4b7f40d43402c2feb3859161ef625", "dependencies": [ "gtest", - "zlib" + "zlib", + { + "name": "sdl2", + "version>=": "2.30.3" + } + ], + "overrides": [ + { + "name": "sdl2", + "version": "2.30.3" + } ] } diff --git a/win32/CMakeLists.txt b/win32/CMakeLists.txt index 86aa40481..ec3b6e24b 100644 --- a/win32/CMakeLists.txt +++ b/win32/CMakeLists.txt @@ -9,6 +9,7 @@ set(CPPS add_library(win32 STATIC ${CPPS}) add_dependencies(win32 get_git_hash) target_include_directories(win32 PRIVATE ${PROJECT_BINARY_DIR}/lib) +target_compile_definitions(win32 PRIVATE DX_APP) target_link_libraries(win32 PRIVATE ddio misc