Support multiple platform drivers (#444)
* Start of supporting multiple platform drivers * Remove dependency of null platform on SDL2 * cmake: support loading SDL2 dynamically * Move CMake options to project root for SDL2::SDL2 access * Don't link to OpenGL * Move common dynamic loading to header * Add SDL 1.2 platform * Add SDL1 platform backend * Remove accidental addition * Try multiple platform drivers until we find a good one * Fix sdl1 mouse * Use my BRender fork FIXME FIXME FIXME REMOVEME REMOVEME REMOVEME * Build dethrace supporting SDL1 on ci * use dethrace-labs BRender fork
This commit is contained in:
parent
33e49e8f0f
commit
a2cdd1f061
|
@ -41,7 +41,7 @@ jobs:
|
|||
if: ${{ runner.os == 'Linux' }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgl-dev libxext-dev ${{ matrix.platform.apt-packages }}
|
||||
sudo apt-get install -y libgl-dev libgl1-mesa-dev libglu1-mesa-dev libxext-dev
|
||||
- name: Set up SDL
|
||||
uses: libsdl-org/setup-sdl@main
|
||||
with:
|
||||
|
@ -52,6 +52,7 @@ jobs:
|
|||
cmake-toolchain-file: ${{ matrix.platform.cmake-toolchain-file }}
|
||||
discriminator: ${{ matrix.platform.arch }}
|
||||
version: 2-latest
|
||||
version-sdl12-compat: 1-head
|
||||
- name: 'Prepare sources for release'
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
run: |
|
||||
|
@ -68,6 +69,9 @@ jobs:
|
|||
-DDETHRACE_PACKAGE_PLATFORM=${{ matrix.platform.name }} \
|
||||
-DDETHRACE_PACKAGE_ARCH=${{ matrix.platform.arch }} \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${{ matrix.platform.cmake-toolchain-file }} \
|
||||
-DDETHRACE_PLATFORM_SDL1=ON \
|
||||
-DDETHRACE_PLATFORM_SDL2=ON \
|
||||
-DDETHRACE_PLATFORM_SDL_DYNAMIC=ON \
|
||||
${{ matrix.platform.cmake-args }}
|
||||
- name: 'Build (CMake)'
|
||||
run: |
|
||||
|
|
|
@ -14,6 +14,7 @@ if(MSVC)
|
|||
endif()
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CMakeDependentOption)
|
||||
include(TestBigEndian)
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
||||
|
@ -61,11 +62,39 @@ endfunction()
|
|||
|
||||
test_big_endian(IS_BIGENDIAN)
|
||||
|
||||
find_package(SDL2 CONFIG)
|
||||
if(NOT SDL2_FOUND)
|
||||
find_package(SDL2 MODULE REQUIRED)
|
||||
option(DETHRACE_PLATFORM_SDL1 "Support SDL 1.2 platform driver" OFF)
|
||||
option(DETHRACE_PLATFORM_SDL2 "Support SDL 2 platform driver" ON)
|
||||
set(count_sdl_platforms 0)
|
||||
|
||||
set(DETHRACE_PLATFORMS )
|
||||
if(DETHRACE_PLATFORM_SDL1)
|
||||
find_package(SDL REQUIRED)
|
||||
list(APPEND DETHRACE_PLATFORMS SDL1)
|
||||
math(EXPR count_sdl_platforms "${count_sdl_platforms} + 1")
|
||||
endif()
|
||||
if(DETHRACE_PLATFORM_SDL2)
|
||||
find_package(SDL2 CONFIG)
|
||||
if(NOT SDL2_FOUND)
|
||||
find_package(SDL2 MODULE REQUIRED)
|
||||
endif()
|
||||
list(APPEND DETHRACE_PLATFORMS SDL2)
|
||||
math(EXPR count_sdl_platforms "${count_sdl_platforms} + 1")
|
||||
endif()
|
||||
|
||||
if(count_sdl_platforms GREATER 1)
|
||||
# Force dynamic SDL when enabling 2 (or more) SDL platform backends
|
||||
set(dynamic_sdl_force TRUE)
|
||||
else()
|
||||
# When no SDL backend is selected, disable dynamic SDL backend
|
||||
# Enabling one SDL backend is a don-t-care
|
||||
set(dynamic_sdl_force FALSE)
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(DETHRACE_PLATFORM_SDL_DYNAMIC "Load SDL dynamically" FALSE "count_sdl_platforms EQUAL 1" "${dynamic_sdl_force}")
|
||||
|
||||
if(NOT DETHRACE_PLATFORMS)
|
||||
message(FATAL_ERROR "No platform drivers enabled")
|
||||
endif()
|
||||
|
||||
add_subdirectory(lib/BRender-v1.3.2)
|
||||
add_subdirectory(lib/libsmacker)
|
||||
|
|
|
@ -22,34 +22,58 @@ target_sources(harness PRIVATE
|
|||
...
|
||||
```
|
||||
|
||||
## IO Platform (windowing / input / rendering)
|
||||
## Platform (windowing / input)
|
||||
|
||||
A `Platform` in _dethrace_ implements windowing, rendering and input handling.
|
||||
A `Platform` in _dethrace_ implements windowing and input handling.
|
||||
|
||||
The default platform is `SDL_OpenGL`, which uses SDL for windowing and input, and OpenGL for rendering. See [platforms/sdl_opengl.c](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl_opengl.c).
|
||||
The default platform is `SDL2`, which uses SDL2 for windowing and input. See [platforms/sdl_opengl.c](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl2.c).
|
||||
|
||||
To add a new `Platform`:
|
||||
|
||||
1. Create `platforms/my_platform.c` file and add a `Harness_Platform_Init` function. Hook up all the function pointers using the `sdl_opengl` [implementation](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl_opengl.h) as a guide.
|
||||
1. Create a `src/harness/my_platform.c` file where you'll implement your platform-specific callbacks.
|
||||
Define a public fully-initialized `const tPlatform_bootstrap MYPLATFORM_bootstrap ` variable in this file.
|
||||
|
||||
2. Add a new conditional section in `src/harness/CMakeLists.txt` for your new platform
|
||||
2. Add the the following code fragments to appropriate locations in `src/harness/harness.c`:
|
||||
```c
|
||||
extern const tPlatform_bootstrap MYPLATFORM_bootstrap;
|
||||
```
|
||||
```c
|
||||
#ifdef DETHRACE_PLATFORM_MYPLATFORM
|
||||
&MYPLATFORM_bootstrap,
|
||||
#endif
|
||||
```
|
||||
|
||||
For example:
|
||||
```
|
||||
if (IO_PLATFORM STREQUAL "My_Platform")
|
||||
target_sources(harness PRIVATE
|
||||
io_platforms/my_platform.c
|
||||
)
|
||||
endif()
|
||||
```
|
||||
3. Add new conditionals to `CMakeLists.txt` and `src/harness/CMakeLists.txt` for your new platform
|
||||
|
||||
3. Run cmake to update your build with the new platform
|
||||
```sh
|
||||
cd build
|
||||
cmake -DIO_PLATFORM=My_Platform ..
|
||||
```
|
||||
For example:
|
||||
```cmake
|
||||
# CMakeLists.txt
|
||||
option(DETHRACE_PLATFORM_MYPLATFORM "Enable my platform" OFF)
|
||||
if(DETHRACE_PLATFORM_MYPLATFORM)
|
||||
find_package(MyPlatform REQUIRED)
|
||||
endif()
|
||||
```
|
||||
```cmake
|
||||
# src/harness/CMakeLists.txt
|
||||
if(DETHRACE_PLATFORM_MYPLATFORM)
|
||||
target_sources(harness PRIVATE
|
||||
my_platform.c
|
||||
)
|
||||
target_compile_definitions(harness PRIVATE DETHRACE_PLATFORM_MYPLATFORM)
|
||||
target_link_libraries(harness PRIVATE MyPlatform::MyPlatform)
|
||||
endif()
|
||||
```
|
||||
|
||||
4. Build
|
||||
```
|
||||
cmake --build .
|
||||
```
|
||||
4. Hook up all the function pointers using the [sdl2 platform](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl2.c) as a guide.
|
||||
|
||||
5. Run cmake to update your build with the new platform
|
||||
```sh
|
||||
cd build
|
||||
cmake -DDETHRACE_PLATFORM_MYPLATFORM=ON ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
6. Build
|
||||
```
|
||||
-cmake --build .
|
||||
```
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 89861762c3e0743eed484ef5dace8e882ecd1289
|
||||
Subproject commit fa8b5a90dff141f6e7e1f4f146ac593779fe6cea
|
|
@ -15,7 +15,7 @@ if (DETHRACE_ASAN)
|
|||
target_link_options(dethrace_obj PUBLIC -fsanitize=address)
|
||||
endif()
|
||||
|
||||
target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smackw32 harness BRender::Full BRender::DDI s3)
|
||||
target_link_libraries(dethrace_obj PUBLIC smackw32 harness BRender::Full BRender::DDI s3)
|
||||
|
||||
if(MSVC)
|
||||
target_compile_definitions(dethrace_obj PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
@ -177,6 +177,9 @@ add_executable(dethrace
|
|||
${CMAKE_SOURCE_DIR}/packaging/windows/dethrace.rc
|
||||
)
|
||||
|
||||
get_property(build_rpaths GLOBAL PROPERTY DETHRACE_BUILD_RPATHS)
|
||||
set_property(TARGET dethrace APPEND PROPERTY BUILD_RPATH "${build_rpaths}")
|
||||
|
||||
target_link_libraries(dethrace PRIVATE dethrace_obj compile_with_werror)
|
||||
target_sources(dethrace PRIVATE main.c)
|
||||
|
||||
|
@ -240,11 +243,25 @@ if(DETHRACE_INSTALL)
|
|||
DESTINATION "."
|
||||
OPTIONAL
|
||||
)
|
||||
endif()
|
||||
if(WIN32)
|
||||
install(FILES $<TARGET_RUNTIME_DLLS:dethrace>
|
||||
DESTINATION "."
|
||||
OPTIONAL
|
||||
)
|
||||
if(DETHRACE_PLATFORM_SDL_DYNAMIC)
|
||||
if(DETHRACE_PLATFORM_SDL1)
|
||||
get_filename_component(sdl1_lib_dir "${SDL_LIBRARY}" DIRECTORY)
|
||||
get_filename_component(sdl1_root_dir "${SDL_LIBRARY}" PATH)
|
||||
set(sdl1_bin_dir "${sdl1_root_dir}/bin" PATH)
|
||||
find_file(SDL1DLL_PATH NAMES "SDL.dll" PATHS ${sdl1_lib_dir} ${sdl1_root_dir} PATH_SUFFIXES "bin" REQUIRED)
|
||||
if(SDL1DLL_PATH)
|
||||
install(FILES "${SDL1DLL_PATH}"
|
||||
DESTINATION "."
|
||||
OPTIONAL
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(DETHRACE_PLATFORM_SDL2)
|
||||
install(FILES "$<TARGET_FILE:SDL2::SDL2>"
|
||||
DESTINATION "."
|
||||
OPTIONAL
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "brender.h"
|
||||
|
||||
extern void Harness_Init(int* argc, char* argv[]);
|
||||
extern int Harness_Init(int* argc, char* argv[]);
|
||||
extern int original_main(int pArgc, char* pArgv[]);
|
||||
|
||||
void BR_CALLBACK _BrBeginHook(void) {
|
||||
|
@ -28,6 +28,8 @@ void BR_CALLBACK _BrEndHook(void) {
|
|||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int result;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Attach to the console that started us if any */
|
||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||
|
@ -46,7 +48,10 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
#endif
|
||||
|
||||
Harness_Init(&argc, argv);
|
||||
result = Harness_Init(&argc, argv);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return original_main(argc, argv);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ target_include_directories(s3
|
|||
include
|
||||
)
|
||||
|
||||
target_link_libraries(s3 PRIVATE brender SDL2::SDL2 harness compile_with_werror)
|
||||
target_link_libraries(s3 PRIVATE brender harness compile_with_werror)
|
||||
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(s3 PUBLIC pthread m)
|
||||
|
|
|
@ -2,10 +2,6 @@ configure_file(version.h.in version.h @ONLY)
|
|||
|
||||
add_library(harness STATIC)
|
||||
|
||||
if (NOT DEFINED IO_PLATFORM)
|
||||
set(IO_PLATFORM "SDL2")
|
||||
endif()
|
||||
|
||||
target_include_directories(harness
|
||||
PRIVATE
|
||||
.
|
||||
|
@ -62,12 +58,41 @@ target_sources(harness PRIVATE
|
|||
"${CMAKE_CURRENT_BINARY_DIR}/version.h"
|
||||
)
|
||||
|
||||
if (IO_PLATFORM STREQUAL "SDL2")
|
||||
if(DETHRACE_PLATFORM_SDL1)
|
||||
target_sources(harness PRIVATE
|
||||
platforms/sdl1.c
|
||||
platforms/sdl1_scancode_to_dinput.h
|
||||
platforms/sdl1_syms.h
|
||||
)
|
||||
target_compile_definitions(harness PRIVATE DETHRACE_PLATFORM_SDL1)
|
||||
if(DETHRACE_PLATFORM_SDL_DYNAMIC)
|
||||
set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/platforms/sdl1.c" APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:SDL::SDL,INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
get_filename_component(sdl_library_directory "${SDL_LIBRARY}" DIRECTORY)
|
||||
set_property(GLOBAL APPEND PROPERTY DETHRACE_BUILD_RPATHS "${sdl_library_directory}")
|
||||
else()
|
||||
target_include_directories(harness PRIVATE ${SDL_INCLUDE_DIR})
|
||||
target_link_libraries(harness PRIVATE ${SDL_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DETHRACE_PLATFORM_SDL2)
|
||||
target_sources(harness PRIVATE
|
||||
platforms/sdl2.c
|
||||
platforms/sdl2_scancode_to_dinput.h
|
||||
platforms/sdl2_syms.h
|
||||
)
|
||||
target_link_libraries(harness PRIVATE SDL2::SDL2)
|
||||
target_compile_definitions(harness PRIVATE DETHRACE_PLATFORM_SDL2)
|
||||
if(DETHRACE_PLATFORM_SDL_DYNAMIC)
|
||||
set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/platforms/sdl2.c" APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:SDL2::SDL2,INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
set_property(GLOBAL APPEND PROPERTY DETHRACE_BUILD_RPATHS "$<TARGET_FILE_DIR:SDL2::SDL2>")
|
||||
else()
|
||||
target_link_libraries(harness PRIVATE SDL2::SDL2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DETHRACE_PLATFORM_SDL_DYNAMIC)
|
||||
target_compile_definitions(harness PRIVATE DETHRACE_SDL_DYNAMIC)
|
||||
target_link_libraries(harness PRIVATE ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -12,16 +12,22 @@
|
|||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
br_pixelmap* palette;
|
||||
uint32_t* screen_buffer;
|
||||
|
||||
br_pixelmap* last_dst = NULL;
|
||||
br_pixelmap* last_src = NULL;
|
||||
|
||||
int force_null_platform = 0;
|
||||
|
||||
extern uint32_t gI_am_cheating;
|
||||
|
||||
extern void Harness_Platform_Init(tHarness_platform* platform);
|
||||
|
||||
extern const tPlatform_bootstrap SDL1_bootstrap;
|
||||
extern const tPlatform_bootstrap SDL2_bootstrap;
|
||||
|
||||
static const tPlatform_bootstrap *platform_bootstraps[] = {
|
||||
#ifdef DETHRACE_PLATFORM_SDL2
|
||||
&SDL2_bootstrap,
|
||||
#endif
|
||||
#ifdef DETHRACE_PLATFORM_SDL1
|
||||
&SDL1_bootstrap,
|
||||
#endif
|
||||
};
|
||||
|
||||
// SplatPack or Carmageddon. This is where we represent the code differences between the two. For example, the intro smack file.
|
||||
tHarness_game_info harness_game_info;
|
||||
|
||||
|
@ -31,9 +37,15 @@ tHarness_game_config harness_game_config;
|
|||
// Platform hooks
|
||||
tHarness_platform gHarness_platform;
|
||||
|
||||
extern void Harness_Platform_Init(tHarness_platform* platform);
|
||||
static int force_null_platform = 0;
|
||||
|
||||
int Harness_ProcessCommandLine(int* argc, char* argv[]);
|
||||
typedef struct {
|
||||
const char *platform_name;
|
||||
uint32_t platform_capabilityies;
|
||||
int install_signalhandler;
|
||||
} tArgument_config;
|
||||
|
||||
static int Harness_ProcessCommandLine(tArgument_config* argument_config, int* argc, char* argv[]);
|
||||
|
||||
static void Harness_DetectGameMode(void) {
|
||||
if (access("DATA/RACES/CASTLE.TXT", F_OK) != -1) {
|
||||
|
@ -138,7 +150,7 @@ static void Harness_DetectGameMode(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void Harness_Init(int* argc, char* argv[]) {
|
||||
int Harness_Init(int* argc, char* argv[]) {
|
||||
int result;
|
||||
|
||||
printf("Dethrace version: %s\n", DETHRACE_VERSION);
|
||||
|
@ -169,12 +181,21 @@ void Harness_Init(int* argc, char* argv[]) {
|
|||
harness_game_config.no_bind = 0;
|
||||
// Disable verbose logging
|
||||
harness_game_config.verbose = 0;
|
||||
// install signal handler by default
|
||||
harness_game_config.install_signalhandler = 1;
|
||||
|
||||
Harness_ProcessCommandLine(argc, argv);
|
||||
tArgument_config argument_config;
|
||||
// don't require a particular platform
|
||||
argument_config.platform_name = NULL;
|
||||
// request software renderer capability
|
||||
argument_config.platform_capabilityies = ePlatform_cap_software;
|
||||
// install signal handler
|
||||
argument_config.install_signalhandler = 1;
|
||||
|
||||
if (harness_game_config.install_signalhandler) {
|
||||
if (Harness_ProcessCommandLine(&argument_config, argc, argv) != 0) {
|
||||
fprintf(stderr, "Failed to parse harness command line\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argument_config.install_signalhandler) {
|
||||
OS_InstallSignalHandler(argv[0]);
|
||||
}
|
||||
|
||||
|
@ -205,8 +226,54 @@ void Harness_Init(int* argc, char* argv[]) {
|
|||
if (force_null_platform) {
|
||||
Null_Platform_Init(&gHarness_platform);
|
||||
} else {
|
||||
Harness_Platform_Init(&gHarness_platform);
|
||||
const tPlatform_bootstrap* selected_bootstrap = NULL;
|
||||
|
||||
if (argument_config.platform_name != NULL) {
|
||||
size_t i;
|
||||
for (i = 0; i < BR_ASIZE(platform_bootstraps); i++) {
|
||||
if (strcasecmp(platform_bootstraps[i]->name, argument_config.platform_name) == 0) {
|
||||
if ((platform_bootstraps[i]->capabilities & argument_config.platform_capabilityies) != argument_config.platform_capabilityies) {
|
||||
fprintf(stderr, "Platform \"%s\" does not support requested capabilities. Try another video driver and/or add/remove --opengl\n", selected_bootstrap->name);
|
||||
return 1;
|
||||
}
|
||||
selected_bootstrap = platform_bootstraps[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (selected_bootstrap == NULL) {
|
||||
fprintf(stderr, "Could not find a platform named \"%s\"\n", argument_config.platform_name);
|
||||
return 1;
|
||||
}
|
||||
if (selected_bootstrap->init(&gHarness_platform) != 0) {
|
||||
fprintf(stderr, "%s initialization failed\n", selected_bootstrap->name);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < BR_ASIZE(platform_bootstraps); i++) {
|
||||
LOG_TRACE10("Attempting video driver \"%s\"", platform_bootstraps[i]->name);
|
||||
if ((platform_bootstraps[i]->capabilities & argument_config.platform_capabilityies) != argument_config.platform_capabilityies) {
|
||||
fprintf(stderr, "Skipping platform \"%s\". Does not support required capabilities.\n", platform_bootstraps[i]->name);
|
||||
continue;
|
||||
}
|
||||
LOG_TRACE10("Try platform \"%s\"...");
|
||||
if (platform_bootstraps[i]->init(&gHarness_platform) == 0) {
|
||||
selected_bootstrap = platform_bootstraps[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (selected_bootstrap == NULL) {
|
||||
fprintf(stderr, "Could not find a supported platform\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (selected_bootstrap == NULL) {
|
||||
fprintf(stderr, "Could not find a supported platform\n");
|
||||
return 1;
|
||||
}
|
||||
LOG_INFO("Platform: %s (%s)", selected_bootstrap->name, selected_bootstrap->description);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// used by unit tests
|
||||
|
@ -214,86 +281,94 @@ void Harness_ForceNullPlatform(void) {
|
|||
force_null_platform = 1;
|
||||
}
|
||||
|
||||
int Harness_ProcessCommandLine(int* argc, char* argv[]) {
|
||||
for (int i = 1; i < *argc; i++) {
|
||||
int handled = 0;
|
||||
int Harness_ProcessCommandLine(tArgument_config* config, int* argc, char* argv[]) {
|
||||
for (int i = 1; i < *argc;) {
|
||||
int consumed = -1;
|
||||
|
||||
if (strcasecmp(argv[i], "--cdcheck") == 0) {
|
||||
harness_game_config.enable_cd_check = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strstr(argv[i], "--debug=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_debug_level = atoi(s + 1);
|
||||
LOG_INFO("debug level set to %d", harness_debug_level);
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strstr(argv[i], "--physics-step-time=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_game_config.physics_step_time = atoi(s + 1);
|
||||
LOG_INFO("Physics step time set to %d", harness_game_config.physics_step_time);
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strstr(argv[i], "--fps=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_game_config.fps = atoi(s + 1);
|
||||
LOG_INFO("FPS limiter set to %f", harness_game_config.fps);
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--freeze-timer") == 0) {
|
||||
LOG_INFO("Timer frozen");
|
||||
harness_game_config.freeze_timer = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--no-signal-handler") == 0) {
|
||||
LOG_INFO("Don't install the signal handler");
|
||||
harness_game_config.install_signalhandler = 0;
|
||||
handled = 1;
|
||||
config->install_signalhandler = 0;
|
||||
consumed = 1;
|
||||
} else if (strstr(argv[i], "--demo-timeout=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_game_config.demo_timeout = atoi(s + 1) * 1000;
|
||||
LOG_INFO("Demo timeout set to %d milliseconds", harness_game_config.demo_timeout);
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--i-am-cheating") == 0) {
|
||||
gI_am_cheating = 0xa11ee75d;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--enable-diagnostics") == 0) {
|
||||
harness_game_config.enable_diagnostics = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strstr(argv[i], "--volume-multiplier=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_game_config.volume_multiplier = atof(s + 1);
|
||||
LOG_INFO("Volume multiplier set to %f", harness_game_config.volume_multiplier);
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--full-screen") == 0) {
|
||||
// option left for backwards compatibility
|
||||
harness_game_config.start_full_screen = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--window") == 0) {
|
||||
harness_game_config.start_full_screen = 0;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--gore-check") == 0) {
|
||||
harness_game_config.gore_check = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--sound-options") == 0) {
|
||||
harness_game_config.sound_options = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--no-bind") == 0) {
|
||||
harness_game_config.no_bind = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--opengl") == 0) {
|
||||
config->platform_capabilityies &= ~ePlatform_cap_video_mask;
|
||||
config->platform_capabilityies |= ePlatform_cap_opengl;
|
||||
harness_game_config.opengl_3dfx_mode = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--no-music") == 0) {
|
||||
harness_game_config.no_music = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcasecmp(argv[i], "--game-completed") == 0) {
|
||||
harness_game_config.game_completed = 1;
|
||||
handled = 1;
|
||||
consumed = 1;
|
||||
} else if (strcmp(argv[i], "--platform") == 0) {
|
||||
if (i < *argc + 1) {
|
||||
config->platform_name = argv[i + 1];
|
||||
consumed = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
if (consumed > 0) {
|
||||
// shift args downwards
|
||||
for (int j = i; j < *argc - 1; j++) {
|
||||
argv[j] = argv[j + 1];
|
||||
for (int j = i; j < *argc - consumed; j++) {
|
||||
argv[j] = argv[j + consumed];
|
||||
}
|
||||
(*argc)--;
|
||||
i--;
|
||||
*argc -= consumed;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,6 @@ typedef struct tHarness_game_config {
|
|||
int verbose;
|
||||
int opengl_3dfx_mode;
|
||||
int game_completed;
|
||||
|
||||
int install_signalhandler;
|
||||
} tHarness_game_config;
|
||||
|
||||
extern tHarness_game_info harness_game_info;
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef struct tHarness_platform {
|
|||
int (*ShowErrorMessage)(void* window, char* text, char* caption);
|
||||
|
||||
// Create a window. Uses an underscore to avoid name collisions with windows.h `CreateWindow` macro
|
||||
void (*CreateWindow_)(char* title, int nWidth, int nHeight, tHarness_window_type window_type);
|
||||
void (*CreateWindow_)(const char* title, int nWidth, int nHeight, tHarness_window_type window_type);
|
||||
void (*Swap)(br_pixelmap* back_buffer);
|
||||
void (*PaletteChanged)(br_colour entries[256]);
|
||||
// If this platform supports OpenGL
|
||||
|
@ -47,9 +47,22 @@ typedef struct tHarness_platform {
|
|||
|
||||
} tHarness_platform;
|
||||
|
||||
enum {
|
||||
ePlatform_cap_software = 0x1,
|
||||
ePlatform_cap_opengl = 0x2,
|
||||
ePlatform_cap_video_mask = ePlatform_cap_software | ePlatform_cap_opengl,
|
||||
};
|
||||
|
||||
typedef struct tPlatform_bootstrap {
|
||||
const char *name;
|
||||
const char *description;
|
||||
uint32_t capabilities;
|
||||
int (*init)(tHarness_platform* platform);
|
||||
} tPlatform_bootstrap;
|
||||
|
||||
extern tHarness_platform gHarness_platform;
|
||||
|
||||
void Harness_Init(int* argc, char* argv[]);
|
||||
int Harness_Init(int* argc, char* argv[]);
|
||||
|
||||
// Hooks are called from original game code.
|
||||
|
||||
|
|
|
@ -1,45 +1,64 @@
|
|||
#include "null.h"
|
||||
|
||||
// todo: shouldnt depend on sdl...
|
||||
#include <SDL.h>
|
||||
static uint32_t null_time;
|
||||
|
||||
static int null_set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
null_time += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void null_destroy_window(void* hWnd) {
|
||||
null_time += 1;
|
||||
}
|
||||
|
||||
static int null_show_error_message(void* window, char* text, char* caption) {
|
||||
null_time += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void null_get_and_handle_message(MSG_* msg) {
|
||||
null_time += 1;
|
||||
}
|
||||
|
||||
static void null_get_keyboard_state(unsigned int count, uint8_t* buffer) {
|
||||
null_time += 1;
|
||||
}
|
||||
|
||||
static int null_get_mouse_buttons(int* pButton1, int* pButton2) {
|
||||
null_time += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_get_mouse_position(int* pX, int* pY) {
|
||||
null_time += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_show_cursor(int show) {
|
||||
null_time += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void null_set_palette(PALETTEENTRY_* palette) {
|
||||
null_time += 1;
|
||||
}
|
||||
|
||||
static void null_sleep(uint32_t milliseconds) {
|
||||
null_time += 1;
|
||||
null_time += milliseconds;
|
||||
}
|
||||
|
||||
static uint32_t null_getticks(void) {
|
||||
null_time += 1;
|
||||
return null_time;
|
||||
}
|
||||
|
||||
void Null_Platform_Init(tHarness_platform* platform) {
|
||||
null_time = 0;
|
||||
platform->ProcessWindowMessages = null_get_and_handle_message;
|
||||
// todo: shouldnt depend on sdl...
|
||||
platform->Sleep = SDL_Delay;
|
||||
platform->GetTicks = SDL_GetTicks;
|
||||
|
||||
platform->Sleep = null_sleep;
|
||||
platform->GetTicks = null_getticks;
|
||||
platform->ShowCursor = null_show_cursor;
|
||||
platform->SetWindowPos = null_set_window_pos;
|
||||
platform->DestroyWindow = null_destroy_window;
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
#include <SDL.h>
|
||||
|
||||
#include "harness.h"
|
||||
#include "harness/config.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
#include "sdl1_scancode_to_dinput.h"
|
||||
#include "sdl1_syms.h"
|
||||
|
||||
SDL_COMPILE_TIME_ASSERT(sdl1_platform_requires_SDL1, SDL_MAJOR_VERSION == 1);
|
||||
|
||||
static SDL_Surface* screen;
|
||||
static uint32_t converted_palette[256];
|
||||
static br_pixelmap* last_screen_src;
|
||||
|
||||
static Uint32 last_frame_time;
|
||||
|
||||
static uint8_t directinput_key_state[SDLK_LAST];
|
||||
|
||||
static struct {
|
||||
int x, y;
|
||||
float scale_x, scale_y;
|
||||
} viewport;
|
||||
|
||||
// Callbacks back into original game code
|
||||
extern void QuitGame(void);
|
||||
extern uint32_t gKeyboard_bits[8];
|
||||
extern br_pixelmap* gBack_screen;
|
||||
static int window_width, window_height;
|
||||
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
#ifdef _WIN32
|
||||
static const char * const possible_locations[] = {
|
||||
"SDL.dll",
|
||||
};
|
||||
#elif defined(__APPLE__)
|
||||
#define SHARED_OBJECT_NAME "libSDL"
|
||||
#define SDL1_LIBNAME "libSDL.dylib"
|
||||
static const char * const possible_locations[] = {
|
||||
"@loader_path/" SDL1_LIBNAME, /* MyApp.app/Contents/MacOS/libSDL2_dylib */
|
||||
"@executable_path/" SDL1_LIBNAME, /* MyApp.app/Contents/MacOS/libSDL2_dylib */
|
||||
SDL1_LIBNAME /* oh well, anywhere the system can see the .dylib (/usr/local/lib or whatever) */
|
||||
};
|
||||
#else
|
||||
static const char * const possible_locations[] = {
|
||||
"libSDL-1.2.so.0",
|
||||
"libSDL-1.2.so",
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
static void *sdl1_so;
|
||||
#endif
|
||||
|
||||
#define OBJECT_NAME sdl1_so
|
||||
#define SYMBOL_PREFIX SDL1_
|
||||
#define FOREACH_SDLX_SYM FOREACH_SDL1_SYM
|
||||
|
||||
#include "sdl_dyn_common.h"
|
||||
|
||||
static void calculate_viewport(int window_width, int window_height) {
|
||||
int vp_width, vp_height;
|
||||
float target_aspect_ratio;
|
||||
float aspect_ratio;
|
||||
|
||||
aspect_ratio = (float)window_width / window_height;
|
||||
target_aspect_ratio = (float)gBack_screen->width / gBack_screen->height;
|
||||
|
||||
vp_width = window_width;
|
||||
vp_height = window_height;
|
||||
if (aspect_ratio != target_aspect_ratio) {
|
||||
if (aspect_ratio > target_aspect_ratio) {
|
||||
vp_width = window_height * target_aspect_ratio + .5f;
|
||||
} else {
|
||||
vp_height = window_width / target_aspect_ratio + .5f;
|
||||
}
|
||||
}
|
||||
viewport.x = (window_width - vp_width) / 2;
|
||||
viewport.y = (window_height - vp_height) / 2;
|
||||
viewport.scale_x = (float)vp_width / gBack_screen->width;
|
||||
viewport.scale_y = (float)vp_height / gBack_screen->height;
|
||||
}
|
||||
|
||||
static void recreate_screen(void) {
|
||||
int video_flags = SDL_RESIZABLE | SDL_HWSURFACE | SDL_DOUBLEBUF;
|
||||
|
||||
if (harness_game_config.start_full_screen) {
|
||||
video_flags |= SDL_FULLSCREEN;
|
||||
}
|
||||
screen = SDL1_SetVideoMode(window_width, window_height, 32, video_flags);
|
||||
if (screen == NULL) {
|
||||
LOG_PANIC("SDL_SetVideoMode failed (%s)", SDL1_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL1_Harness_CreateWindow(const char* title, int width, int height, tHarness_window_type window_type) {
|
||||
window_width = width;
|
||||
window_height = height;
|
||||
|
||||
initializeSDL1KeyNums();
|
||||
|
||||
if (SDL1_Init(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL1_GetError());
|
||||
}
|
||||
|
||||
if (window_type == eWindow_type_software) {
|
||||
recreate_screen();
|
||||
} else {
|
||||
LOG_PANIC("Unsupported window type (%d)", window_type);
|
||||
}
|
||||
|
||||
SDL1_WM_SetCaption("Carmageddon", NULL);
|
||||
|
||||
SDL1_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
static int SDL1_Harness_SetWindowPos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
// SDL_SetWindowPosition(hWnd, x, y);
|
||||
if (nWidth == 320 && nHeight == 200) {
|
||||
nWidth = 640;
|
||||
nHeight = 400;
|
||||
}
|
||||
window_width = nWidth;
|
||||
window_height = nHeight;
|
||||
recreate_screen();
|
||||
SDL1_UpdateRect(hWnd, x, y, nWidth, nHeight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SDL1_Harness_DestroyWindow(void* hWnd) {
|
||||
SDL1_FreeSurface(screen);
|
||||
SDL1_Quit();
|
||||
screen = NULL;
|
||||
}
|
||||
|
||||
// Checks whether the `flag_check` is the only modifier applied.
|
||||
// e.g. is_only_modifier(event.key.keysym.mod, KMOD_ALT) returns true when only the ALT key was pressed
|
||||
static int is_only_key_modifier(int modifier_flags, int flag_check) {
|
||||
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)) == (modifier_flags & flag_check);
|
||||
}
|
||||
|
||||
static void SDL1_Harness_ProcessWindowMessages(MSG_* msg) {
|
||||
SDL_Event event;
|
||||
int dinput_key;
|
||||
|
||||
while (SDL1_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
if (event.key.keysym.sym == SDLK_RETURN) {
|
||||
if (event.key.type == SDL_KEYDOWN) {
|
||||
if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META))) {
|
||||
// Ignore keydown of RETURN when used together with some modifier
|
||||
return;
|
||||
}
|
||||
} else if (event.key.type == SDL_KEYUP) {
|
||||
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
|
||||
SDL1_WM_ToggleFullScreen(screen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map incoming SDL scancode to DirectInput DIK_* key code.
|
||||
// https://github.com/DanielGibson/Snippets/blob/master/sdl2_scancode_to_dinput.h
|
||||
dinput_key = sdl1KeyToDirectInputKeyNum[event.key.keysym.sym];
|
||||
if (dinput_key == 0) {
|
||||
LOG_WARN("unexpected key \"%s\" (0x%x)", SDL1_GetKeyName(event.key.keysym.sym), event.key.keysym.sym);
|
||||
return;
|
||||
}
|
||||
// DInput expects high bit to be set if key is down
|
||||
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee418261(v=vs.85)
|
||||
directinput_key_state[dinput_key] = (event.type == SDL_KEYDOWN ? 0x80 : 0);
|
||||
if (event.type == SDL_KEYDOWN) {
|
||||
gKeyboard_bits[dinput_key >> 5] |= (1 << (dinput_key & 0x1F));
|
||||
} else {
|
||||
gKeyboard_bits[dinput_key >> 5] &= ~(1 << (dinput_key & 0x1F));
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_VIDEORESIZE:
|
||||
calculate_viewport(event.resize.w, event.resize.h);
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
QuitGame();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void get_keyboard_state(unsigned int count, uint8_t* buffer) {
|
||||
memcpy(buffer, directinput_key_state, count);
|
||||
}
|
||||
|
||||
static int get_mouse_buttons(int* pButton1, int* pButton2) {
|
||||
int state = SDL1_GetMouseState(NULL, NULL);
|
||||
*pButton1 = state & SDL_BUTTON_LMASK;
|
||||
*pButton2 = state & SDL_BUTTON_RMASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_mouse_position(int* pX, int* pY) {
|
||||
SDL1_GetMouseState(pX, pY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void limit_fps(void) {
|
||||
Uint32 now = SDL1_GetTicks();
|
||||
if (last_frame_time != 0) {
|
||||
unsigned int frame_time = now - last_frame_time;
|
||||
last_frame_time = now;
|
||||
if (frame_time < 100) {
|
||||
int sleep_time = (1000 / harness_game_config.fps) - frame_time;
|
||||
if (sleep_time > 5) {
|
||||
gHarness_platform.Sleep(sleep_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
last_frame_time = SDL1_GetTicks();
|
||||
}
|
||||
|
||||
static void SDL1_Renderer_Present(br_pixelmap* src) {
|
||||
// fastest way to convert 8 bit indexed to 32 bit
|
||||
uint8_t* src_pixels = src->pixels;
|
||||
uint32_t* dest_pixels;
|
||||
|
||||
SDL1_LockSurface(screen);
|
||||
dest_pixels = screen->pixels;
|
||||
for (int i = 0; i < src->height * src->width; i++) {
|
||||
*dest_pixels = converted_palette[*src_pixels];
|
||||
dest_pixels++;
|
||||
src_pixels++;
|
||||
}
|
||||
SDL1_UnlockSurface(screen);
|
||||
|
||||
SDL1_Flip(screen);
|
||||
|
||||
last_screen_src = src;
|
||||
|
||||
if (harness_game_config.fps != 0) {
|
||||
limit_fps();
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL1_Harness_Swap(br_pixelmap* back_buffer) {
|
||||
|
||||
SDL1_Harness_ProcessWindowMessages(NULL);
|
||||
|
||||
if (0) {
|
||||
SDL1_GL_SwapBuffers();
|
||||
} else {
|
||||
SDL1_Renderer_Present(back_buffer);
|
||||
|
||||
if (harness_game_config.fps != 0) {
|
||||
limit_fps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL1_Harness_PaletteChanged(br_colour entries[256]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
converted_palette[i] = (0xff << 24 | BR_RED(entries[i]) << 16 | BR_GRN(entries[i]) << 8 | BR_BLU(entries[i]));
|
||||
}
|
||||
if (last_screen_src != NULL) {
|
||||
SDL1_Harness_Swap(last_screen_src);
|
||||
}
|
||||
}
|
||||
|
||||
static int SDL1_Harness_ShowErrorMessage(void* window, char* text, char* caption) {
|
||||
fprintf(stderr, "%s", text);
|
||||
#ifdef _WIN32
|
||||
MessageBoxA(NULL, text, caption, MB_ICONERROR);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SDL1_Harness_GetViewport(int* x, int* y, float* width_multipler, float* height_multiplier) {
|
||||
*x = viewport.x;
|
||||
*y = viewport.y;
|
||||
*width_multipler = viewport.scale_x;
|
||||
*height_multiplier = viewport.scale_y;
|
||||
}
|
||||
|
||||
static int SDL1_Harness_Platform_Init(tHarness_platform* platform) {
|
||||
if (SDL1_LoadSymbols() != 0) {
|
||||
return 1;
|
||||
}
|
||||
platform->ProcessWindowMessages = SDL1_Harness_ProcessWindowMessages;
|
||||
platform->Sleep = SDL1_Delay;
|
||||
platform->GetTicks = SDL1_GetTicks;
|
||||
platform->ShowCursor = SDL1_ShowCursor;
|
||||
platform->SetWindowPos = SDL1_Harness_SetWindowPos;
|
||||
platform->DestroyWindow = SDL1_Harness_DestroyWindow;
|
||||
platform->GetKeyboardState = get_keyboard_state;
|
||||
platform->GetMousePosition = get_mouse_position;
|
||||
platform->GetMouseButtons = get_mouse_buttons;
|
||||
platform->ShowErrorMessage = SDL1_Harness_ShowErrorMessage;
|
||||
|
||||
platform->CreateWindow_ = SDL1_Harness_CreateWindow;
|
||||
platform->Swap = SDL1_Harness_Swap;
|
||||
platform->PaletteChanged = SDL1_Harness_PaletteChanged;
|
||||
platform->GL_GetProcAddress = SDL1_GL_GetProcAddress;
|
||||
platform->GetViewport = SDL1_Harness_GetViewport;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const tPlatform_bootstrap SDL1_bootstrap = {
|
||||
"sdl1",
|
||||
"SDL1 video backend (libsdl.org)",
|
||||
ePlatform_cap_software,
|
||||
SDL1_Harness_Platform_Init,
|
||||
};
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Maps SDL1 scancodes to directinput keynums/scancodes.
|
||||
* Useful if you're porting a game that uses dinput scancodes internally
|
||||
* (for key bindings etc) or any other lib (like CEGUI) that uses them.
|
||||
*
|
||||
* (C) 2015 Daniel Gibson
|
||||
*
|
||||
* Homepage: https://github.com/DanielGibson/Snippets/
|
||||
*
|
||||
* License:
|
||||
* This software is dual-licensed to the public domain and under the following
|
||||
* license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||
* publish, and distribute this file as you see fit.
|
||||
* No warranty implied; use at your own risk.
|
||||
*
|
||||
* So you can do whatever you want with this code, including copying it
|
||||
* (or parts of it) into your own source.
|
||||
* No need to mention me or this "license" in your code or docs, even though
|
||||
* it would be appreciated, of course.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#if 0 // Usage Example:
|
||||
#include "sdl2_scancode_to_dinput.h"
|
||||
static int SDLScanCodeToKeyNum(SDL_Scancode sc)
|
||||
{
|
||||
int idx = (int)sc;
|
||||
assert(idx >= 0 && idx < SDL_NUM_SCANCODES);
|
||||
return scanCodeToKeyNum[idx];
|
||||
}
|
||||
|
||||
static SDL_Scancode KeyNumToSDLScanCode( int keyNum )
|
||||
{
|
||||
if( keyNum >= 0 && keyNum < 0xEF )
|
||||
{
|
||||
for(int i = 0; i < SDL_NUM_SCANCODES; ++i)
|
||||
{
|
||||
if(scanCodeToKeyNum[i] == keyNum) return (SDL_Scancode)i;
|
||||
}
|
||||
}
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
#ifndef _SDL1_SCANCODE_TO_DINPUT_H_
|
||||
#define _SDL1_SCANCODE_TO_DINPUT_H_
|
||||
|
||||
// TODO: map the following keys, if possible:
|
||||
// #define DIK_UNDERLINE 0x93 /* (NEC PC98) */
|
||||
// #define DIK_KANJI 0x94 /* (Japanese keyboard) */
|
||||
// #define DIK_AX 0x96 /* (Japan AX) */
|
||||
// #define DIK_UNLABELED 0x97 /* (J3100) */
|
||||
//
|
||||
// #define DIK_WAKE 0xE3 /* System Wake */
|
||||
//
|
||||
// (#define DIK_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */ - system should map this to KP_COMMA or something,
|
||||
// according to USB doc, so probably it doesn't need mapping here)
|
||||
|
||||
// maps SDL1 keysyms to directinput keynums/scancodes - dinput_key = sdlScanCodeToDirectInputKeyNum[(int)your_sdl2_scancode];
|
||||
static int sdl1KeyToDirectInputKeyNum[SDLK_LAST];
|
||||
|
||||
static void initializeSDL1KeyNums(void) {
|
||||
memset(sdl1KeyToDirectInputKeyNum, 0, sizeof(sdl1KeyToDirectInputKeyNum));
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_a] = 0x1E; /* DIK_A */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_b] = 0x30; /* DIK_B */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_c] = 0x2E; /* DIK_C */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_d] = 0x20; /* DIK_D */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_e] = 0x12; /* DIK_E */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_f] = 0x21; /* DIK_F */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_g] = 0x22; /* DIK_G */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_h] = 0x23; /* DIK_H */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_i] = 0x17; /* DIK_I */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_j] = 0x24; /* DIK_J */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_k] = 0x25; /* DIK_K */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_l] = 0x26; /* DIK_L */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_m] = 0x32; /* DIK_M */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_n] = 0x31; /* DIK_N */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_o] = 0x18; /* DIK_O */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_p] = 0x19; /* DIK_P */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_q] = 0x10; /* DIK_Q */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_r] = 0x13; /* DIK_R */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_s] = 0x1F; /* DIK_S */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_t] = 0x14; /* DIK_T */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_u] = 0x16; /* DIK_U */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_v] = 0x2F; /* DIK_V */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_w] = 0x11; /* DIK_W */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_x] = 0x2D; /* DIK_X */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_y] = 0x15; /* DIK_Y */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_z] = 0x2C; /* DIK_Z */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_0] = 0x2C; /* DIK_Z */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_1] = 0x02; /* DIK_1 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_2] = 0x03; /* DIK_2 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_3] = 0x04; /* DIK_3 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_4] = 0x05; /* DIK_4 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_5] = 0x06; /* DIK_5 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_6] = 0x07; /* DIK_6 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_7] = 0x08; /* DIK_7 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_8] = 0x09; /* DIK_8 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_9] = 0x0A; /* DIK_9 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_0] = 0x0B; /* DIK_0 */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP1] = 0x4F; /* DIK_NUMPAD1 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP2] = 0x50; /* DIK_NUMPAD2 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP3] = 0x51; /* DIK_NUMPAD3 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP4] = 0x4B; /* DIK_NUMPAD4 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP5] = 0x4C; /* DIK_NUMPAD5 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP6] = 0x4D; /* DIK_NUMPAD6 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP7] = 0x47; /* DIK_NUMPAD7 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP8] = 0x48; /* DIK_NUMPAD8 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP9] = 0x49; /* DIK_NUMPAD9 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP0] = 0x52; /* DIK_NUMPAD0 */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RETURN] = 0x1C; /* DIK_RETURN */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_ESCAPE] = 0x01; /* DIK_ESCAPE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_BACKSPACE] = 0x0E; /* DIK_BACK */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_TAB] = 0x0F; /* DIK_TAB */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_SPACE] = 0x39; /* DIK_SPACE */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_MINUS] = 0x0C; /* DIK_MINUS */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_EQUALS] = 0x0D; /* DIK_EQUALS */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LEFTBRACKET] = 0x1A; /* DIK_LBRACKET */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RIGHTBRACKET] = 0x1B; /* DIK_RBRACKET */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_BACKSLASH] = 0x2B; /* DIK_BACKSLASH */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_HASH] = 0x2B; /* DIK_BACKSLASH */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_SEMICOLON] = 0x27; /* DIK_SEMICOLON */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_QUOTE] = 0x28; /* DIK_APOSTROPHE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_BACKQUOTE] = 0x29; /* DIK_GRAVE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_COMMA] = 0x33; /* DIK_COMMA */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_PERIOD] = 0x34; /* DIK_PERIOD */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_SLASH] = 0x35; /* DIK_SLASH */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_CAPSLOCK] = 0x3A; /* DIK_CAPITAL */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F1] = 0x3A; /* DIK_CAPITAL */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F1] = 0x3B; /* DIK_F1 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F2] = 0x3C; /* DIK_F2 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F3] = 0x3D; /* DIK_F3 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F4] = 0x3E; /* DIK_F4 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F5] = 0x3F; /* DIK_F5 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F6] = 0x40; /* DIK_F6 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F7] = 0x41; /* DIK_F7 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F8] = 0x42; /* DIK_F8 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F9] = 0x43; /* DIK_F9 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F10] = 0x44; /* DIK_F10 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F11] = 0x57; /* DIK_F11 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F12] = 0x58; /* DIK_F12 */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_PRINT] = 0xB7; /* DIK_F12 */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_SCROLLOCK] = 0x46; /* DIK_SCROLL */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_PAUSE] = 0xC5; /* DIK_PAUSE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_INSERT] = 0xD2; /* DIK_INSERT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_HOME] = 0xC7; /* DIK_HOME */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_PAGEUP] = 0xC9; /* DIK_PRIOR */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_DELETE] = 0xD3; /* DIK_DELETE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_END] = 0xCF; /* DIK_END */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_PAGEDOWN] = 0xD1; /* DIK_NEXT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RIGHT] = 0xCD; /* DIK_RIGHT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LEFT] = 0xCB; /* DIK_LEFT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_DOWN] = 0xD0; /* DIK_DOWN */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_UP] = 0xC8; /* DIK_UP */
|
||||
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LCTRL] = 0x1D; /* DIK_LCONTROL */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LSHIFT] = 0x2A; /* DIK_LSHIFT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LALT] = 0x38; /* DIK_LMENU */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_LMETA] = 0xDB; /* DIK_LWIN */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RCTRL] = 0x9D; /* DIK_RCONTROL */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RSHIFT] = 0x36; /* DIK_RSHIFT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RALT] = 0xB8; /* DIK_RMENU */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_RMETA] = 0xDC; /* DIK_RWIN */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_NUMLOCK] = 0x45; /* DIK_NUMLOCK */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_DIVIDE] = 0xB5; /* DIK_DIVIDE */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_MULTIPLY] = 0x37; /* DIK_MULTIPLY */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_MINUS] = 0x4A; /* DIK_SUBTRACT */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_PLUS] = 0x4E; /* DIK_ADD */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_ENTER] = 0x9C; /* DIK_NUMPADENTER */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP1] = 0x4F; /* DIK_NUMPAD1 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP2] = 0x50; /* DIK_NUMPAD2 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP3] = 0x51; /* DIK_NUMPAD3 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP4] = 0x4B; /* DIK_NUMPAD4 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP5] = 0x4C; /* DIK_NUMPAD5 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP6] = 0x4D; /* DIK_NUMPAD6 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP7] = 0x47; /* DIK_NUMPAD7 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP8] = 0x48; /* DIK_NUMPAD8 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP9] = 0x49; /* DIK_NUMPAD9 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP0] = 0x52; /* DIK_NUMPAD0 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_PERIOD] = 0x53; /* DIK_DECIMAL */
|
||||
|
||||
/* 0x56 - DIK_OEM_102 */
|
||||
/* 0xDD - DIK_APPS */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_POWER] = 0xDE; /* DIK_POWER */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_KP_EQUALS] = 0x8D; /* DIK_NUMPADEQUALS */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F13] = 0x8D; /* DIK_F13 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F14] = 0x64; /* DIK_F14 */
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_F15] = 0x65; /* DIK_F15 */
|
||||
|
||||
sdl1KeyToDirectInputKeyNum[SDLK_SYSREQ] = 0xB7; /* SDL_SCANCODE_SYSREQ */
|
||||
}
|
||||
|
||||
#endif /* _SDL1_SCANCODE_TO_DINPUT_H_ */
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef sdl1_syms_h
|
||||
#define sdl1_syms_h
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#define FOREACH_SDL1_SYM(X) \
|
||||
X(Init, int, (Uint32)) \
|
||||
X(Quit, void, (void)) \
|
||||
X(Delay, void, (Uint32)) \
|
||||
X(GetTicks, Uint32, (void)) \
|
||||
X(GetError, char*, (void)) \
|
||||
X(PollEvent, int, (SDL_Event*)) \
|
||||
X(SetVideoMode, SDL_Surface*, (int, int, int, Uint32)) \
|
||||
X(FreeSurface, void, (SDL_Surface*)) \
|
||||
X(LockSurface, int, (SDL_Surface*)) \
|
||||
X(UnlockSurface, void, (SDL_Surface*)) \
|
||||
X(UpdateRect, void, (SDL_Surface*, Sint32, Sint32, Sint32, Sint32)) \
|
||||
X(WM_SetCaption, void, (const char*, const char*)) \
|
||||
X(WM_ToggleFullScreen, int, (SDL_Surface*)) \
|
||||
X(Flip, int, (SDL_Surface*)) \
|
||||
X(ShowCursor, int, (int)) \
|
||||
X(GetMouseState, Uint8, (int*, int*)) \
|
||||
X(GetKeyName, char*, (SDLKey)) \
|
||||
X(GL_GetProcAddress, void*, (const char*)) \
|
||||
X(GL_SwapBuffers, void, (void))
|
||||
|
||||
#endif /* sdl1_syms_h */
|
|
@ -5,22 +5,25 @@
|
|||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
#include "sdl2_scancode_to_dinput.h"
|
||||
#include "sdl2_syms.h"
|
||||
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* screen_texture;
|
||||
uint32_t converted_palette[256];
|
||||
br_pixelmap* last_screen_src;
|
||||
SDL_COMPILE_TIME_ASSERT(sdl2_platform_requires_SDL2, SDL_MAJOR_VERSION == 2);
|
||||
|
||||
SDL_GLContext* gl_context;
|
||||
static SDL_Window* window;
|
||||
static SDL_Renderer* renderer;
|
||||
static SDL_Texture* screen_texture;
|
||||
static uint32_t converted_palette[256];
|
||||
static br_pixelmap* last_screen_src;
|
||||
|
||||
int render_width, render_height;
|
||||
static SDL_GLContext* gl_context;
|
||||
|
||||
Uint32 last_frame_time;
|
||||
static int render_width, render_height;
|
||||
|
||||
uint8_t directinput_key_state[SDL_NUM_SCANCODES];
|
||||
static Uint32 last_frame_time;
|
||||
|
||||
struct {
|
||||
static uint8_t directinput_key_state[SDL_NUM_SCANCODES];
|
||||
|
||||
static struct {
|
||||
int x, y;
|
||||
float scale_x, scale_y;
|
||||
} viewport;
|
||||
|
@ -30,6 +33,42 @@ extern void QuitGame(void);
|
|||
extern uint32_t gKeyboard_bits[8];
|
||||
extern br_pixelmap* gBack_screen;
|
||||
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
#ifdef _WIN32
|
||||
static const char * const possible_locations[] = {
|
||||
"SDL2.dll",
|
||||
};
|
||||
#elif defined(__APPLE__)
|
||||
#define SHARED_OBJECT_NAME "libSDL2"
|
||||
#define SDL2_LIBNAME "libSDL2.dylib"
|
||||
#define SDL2_FRAMEWORK "SDL2.framework/Versions/A/SDL2"
|
||||
static const char * const possible_locations[] = {
|
||||
"@loader_path/" SDL2_LIBNAME, /* MyApp.app/Contents/MacOS/libSDL2_dylib */
|
||||
"@loader_path/../Frameworks/" SDL2_FRAMEWORK, /* MyApp.app/Contents/Frameworks/SDL2_framework */
|
||||
"@executable_path/" SDL2_LIBNAME, /* MyApp.app/Contents/MacOS/libSDL2_dylib */
|
||||
"@executable_path/../Frameworks/" SDL2_FRAMEWORK, /* MyApp.app/Contents/Frameworks/SDL2_framework */
|
||||
NULL, /* /Users/username/Library/Frameworks/SDL2_framework */
|
||||
"/Library/Frameworks" SDL2_FRAMEWORK, /* /Library/Frameworks/SDL2_framework */
|
||||
SDL2_LIBNAME /* oh well, anywhere the system can see the .dylib (/usr/local/lib or whatever) */
|
||||
};
|
||||
#else
|
||||
static const char * const possible_locations[] = {
|
||||
"libSDL2-2.0.so.0",
|
||||
"libSDL2-2.0.so",
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
static void *sdl2_so;
|
||||
#endif
|
||||
|
||||
#define OBJECT_NAME sdl2_so
|
||||
#define SYMBOL_PREFIX SDL2_
|
||||
#define FOREACH_SDLX_SYM FOREACH_SDL2_SYM
|
||||
|
||||
#include "sdl_dyn_common.h"
|
||||
|
||||
static void calculate_viewport(int window_width, int window_height) {
|
||||
int vp_width, vp_height;
|
||||
float target_aspect_ratio;
|
||||
|
@ -53,20 +92,20 @@ static void calculate_viewport(int window_width, int window_height) {
|
|||
viewport.scale_y = (float)vp_height / gBack_screen->height;
|
||||
}
|
||||
|
||||
static int set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
static int SDL2_Harness_SetWindowPos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
// SDL_SetWindowPosition(hWnd, x, y);
|
||||
if (nWidth == 320 && nHeight == 200) {
|
||||
nWidth = 640;
|
||||
nHeight = 400;
|
||||
}
|
||||
SDL_SetWindowSize(hWnd, nWidth, nHeight);
|
||||
SDL2_SetWindowSize(hWnd, nWidth, nHeight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy_window(void* hWnd) {
|
||||
// SDL_GL_DeleteContext(context);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
static void SDL2_Harness_DestroyWindow(void* hWnd) {
|
||||
// SDL2_GL_DeleteContext(context);
|
||||
SDL2_DestroyWindow(window);
|
||||
SDL2_Quit();
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
|
@ -76,15 +115,15 @@ static int is_only_key_modifier(int modifier_flags, int flag_check) {
|
|||
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check);
|
||||
}
|
||||
|
||||
static void get_and_handle_message(MSG_* msg) {
|
||||
static void SDL2_Harness_ProcessWindowMessages(MSG_* msg) {
|
||||
SDL_Event event;
|
||||
int dinput_key;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
while (SDL2_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
if (event.key.windowID != SDL_GetWindowID(window)) {
|
||||
if (event.key.windowID != SDL2_GetWindowID(window)) {
|
||||
continue;
|
||||
}
|
||||
if (event.key.keysym.sym == SDLK_RETURN) {
|
||||
|
@ -95,7 +134,7 @@ static void get_and_handle_message(MSG_* msg) {
|
|||
}
|
||||
} else if (event.key.type == SDL_KEYUP) {
|
||||
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
|
||||
SDL_SetWindowFullscreen(window, (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL2_SetWindowFullscreen(window, (SDL2_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +143,7 @@ static void get_and_handle_message(MSG_* msg) {
|
|||
// https://github.com/DanielGibson/Snippets/blob/master/sdl2_scancode_to_dinput.h
|
||||
dinput_key = sdlScanCodeToDirectInputKeyNum[event.key.keysym.scancode];
|
||||
if (dinput_key == 0) {
|
||||
LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
|
||||
LOG_WARN("unexpected scan code %s (%d)", SDL2_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
|
||||
return;
|
||||
}
|
||||
// DInput expects high bit to be set if key is down
|
||||
|
@ -129,35 +168,35 @@ static void get_and_handle_message(MSG_* msg) {
|
|||
}
|
||||
}
|
||||
|
||||
static void get_keyboard_state(unsigned int count, uint8_t* buffer) {
|
||||
static void SDL2_Harness_GetKeyboardState(unsigned int count, uint8_t* buffer) {
|
||||
memcpy(buffer, directinput_key_state, count);
|
||||
}
|
||||
|
||||
static int get_mouse_buttons(int* pButton1, int* pButton2) {
|
||||
if (SDL_GetMouseFocus() != window) {
|
||||
static int SDL2_Harness_GetMouseButtons(int* pButton1, int* pButton2) {
|
||||
if (SDL2_GetMouseFocus() != window) {
|
||||
*pButton1 = 0;
|
||||
*pButton2 = 0;
|
||||
return 0;
|
||||
}
|
||||
int state = SDL_GetMouseState(NULL, NULL);
|
||||
int state = SDL2_GetMouseState(NULL, NULL);
|
||||
*pButton1 = state & SDL_BUTTON_LMASK;
|
||||
*pButton2 = state & SDL_BUTTON_RMASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_mouse_position(int* pX, int* pY) {
|
||||
static int SDL2_Harness_GetMousePosition(int* pX, int* pY) {
|
||||
int window_width, window_height;
|
||||
float lX, lY;
|
||||
|
||||
if (SDL_GetMouseFocus() != window) {
|
||||
if (SDL2_GetMouseFocus() != window) {
|
||||
return 0;
|
||||
}
|
||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
SDL2_GetWindowSize(window, &window_width, &window_height);
|
||||
|
||||
SDL_GetMouseState(pX, pY);
|
||||
SDL2_GetMouseState(pX, pY);
|
||||
if (renderer != NULL) {
|
||||
// software renderer
|
||||
SDL_RenderWindowToLogical(renderer, *pX, *pY, &lX, &lY);
|
||||
SDL2_RenderWindowToLogical(renderer, *pX, *pY, &lX, &lY);
|
||||
} else {
|
||||
// hardware renderer
|
||||
// handle case where window is stretched larger than the pixel size
|
||||
|
@ -170,7 +209,7 @@ static int get_mouse_position(int* pX, int* pY) {
|
|||
}
|
||||
|
||||
static void limit_fps(void) {
|
||||
Uint32 now = SDL_GetTicks();
|
||||
Uint32 now = SDL2_GetTicks();
|
||||
if (last_frame_time != 0) {
|
||||
unsigned int frame_time = now - last_frame_time;
|
||||
last_frame_time = now;
|
||||
|
@ -181,16 +220,16 @@ static void limit_fps(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
last_frame_time = SDL_GetTicks();
|
||||
last_frame_time = SDL2_GetTicks();
|
||||
}
|
||||
|
||||
int show_error_message(void* window, char* text, char* caption) {
|
||||
static int SDL2_Harness_ShowErrorMessage(void* window, char* text, char* caption) {
|
||||
fprintf(stderr, "%s", text);
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, window);
|
||||
SDL2_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, window);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_window(char* title, int width, int height, tHarness_window_type window_type) {
|
||||
static void SDL2_Harness_CreateWindow(const char* title, int width, int height, tHarness_window_type window_type) {
|
||||
int window_width, window_height;
|
||||
|
||||
render_width = width;
|
||||
|
@ -205,68 +244,68 @@ static void create_window(char* title, int width, int height, tHarness_window_ty
|
|||
window_height = 480;
|
||||
}
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError());
|
||||
if (SDL2_Init(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL2_GetError());
|
||||
}
|
||||
|
||||
if (window_type == eWindow_type_opengl) {
|
||||
|
||||
window = SDL_CreateWindow(title,
|
||||
window = SDL2_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window: %s", SDL_GetError());
|
||||
LOG_PANIC("Failed to create window: %s", SDL2_GetError());
|
||||
}
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
gl_context = SDL_GL_CreateContext(window);
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
gl_context = SDL2_GL_CreateContext(window);
|
||||
|
||||
if (gl_context == NULL) {
|
||||
LOG_WARN("Failed to create OpenGL core profile: %s. Trying OpenGLES...", SDL_GetError());
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
gl_context = SDL_GL_CreateContext(window);
|
||||
LOG_WARN("Failed to create OpenGL core profile: %s. Trying OpenGLES...", SDL2_GetError());
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL2_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
gl_context = SDL2_GL_CreateContext(window);
|
||||
}
|
||||
if (gl_context == NULL) {
|
||||
LOG_PANIC("Failed to create OpenGL context: %s", SDL_GetError());
|
||||
LOG_PANIC("Failed to create OpenGL context: %s", SDL2_GetError());
|
||||
}
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
SDL2_GL_SetSwapInterval(1);
|
||||
|
||||
} else {
|
||||
window = SDL_CreateWindow(title,
|
||||
window = SDL2_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window: %s", SDL_GetError());
|
||||
LOG_PANIC("Failed to create window: %s", SDL2_GetError());
|
||||
}
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
renderer = SDL2_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
if (renderer == NULL) {
|
||||
LOG_PANIC("Failed to create renderer: %s", SDL_GetError());
|
||||
LOG_PANIC("Failed to create renderer: %s", SDL2_GetError());
|
||||
}
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderSetLogicalSize(renderer, render_width, render_height);
|
||||
SDL2_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
SDL2_RenderSetLogicalSize(renderer, render_width, render_height);
|
||||
|
||||
screen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
screen_texture = SDL2_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (screen_texture == NULL) {
|
||||
SDL_RendererInfo info;
|
||||
SDL_GetRendererInfo(renderer, &info);
|
||||
SDL2_GetRendererInfo(renderer, &info);
|
||||
for (Uint32 i = 0; i < info.num_texture_formats; i++) {
|
||||
LOG_INFO("%s\n", SDL_GetPixelFormatName(info.texture_formats[i]));
|
||||
LOG_INFO("%s\n", SDL2_GetPixelFormatName(info.texture_formats[i]));
|
||||
}
|
||||
LOG_PANIC("Failed to create screen_texture: %s", SDL_GetError());
|
||||
LOG_PANIC("Failed to create screen_texture: %s", SDL2_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL2_ShowCursor(SDL_DISABLE);
|
||||
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
|
@ -274,30 +313,31 @@ static void create_window(char* title, int width, int height, tHarness_window_ty
|
|||
viewport.scale_y = 1;
|
||||
|
||||
if (harness_game_config.start_full_screen) {
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL2_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
}
|
||||
|
||||
static void swap(br_pixelmap* back_buffer) {
|
||||
uint8_t* src_pixels = back_buffer->pixels;
|
||||
uint32_t* dest_pixels;
|
||||
int dest_pitch;
|
||||
static void SDL2_Harness_Swap(br_pixelmap* back_buffer) {
|
||||
|
||||
get_and_handle_message(NULL);
|
||||
SDL2_Harness_ProcessWindowMessages(NULL);
|
||||
|
||||
if (gl_context != NULL) {
|
||||
SDL_GL_SwapWindow(window);
|
||||
SDL2_GL_SwapWindow(window);
|
||||
} else {
|
||||
SDL_LockTexture(screen_texture, NULL, (void**)&dest_pixels, &dest_pitch);
|
||||
uint8_t* src_pixels = back_buffer->pixels;
|
||||
uint32_t* dest_pixels;
|
||||
int dest_pitch;
|
||||
|
||||
SDL2_LockTexture(screen_texture, NULL, (void**)&dest_pixels, &dest_pitch);
|
||||
for (int i = 0; i < back_buffer->height * back_buffer->width; i++) {
|
||||
*dest_pixels = converted_palette[*src_pixels];
|
||||
dest_pixels++;
|
||||
src_pixels++;
|
||||
}
|
||||
SDL_UnlockTexture(screen_texture);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
SDL2_UnlockTexture(screen_texture);
|
||||
SDL2_RenderClear(renderer);
|
||||
SDL2_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||
SDL2_RenderPresent(renderer);
|
||||
last_screen_src = back_buffer;
|
||||
}
|
||||
|
||||
|
@ -306,37 +346,48 @@ static void swap(br_pixelmap* back_buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
static void palette_changed(br_colour entries[256]) {
|
||||
static void SDL2_Harness_PaletteChanged(br_colour entries[256]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
converted_palette[i] = (0xff << 24 | BR_RED(entries[i]) << 16 | BR_GRN(entries[i]) << 8 | BR_BLU(entries[i]));
|
||||
}
|
||||
if (last_screen_src != NULL) {
|
||||
swap(last_screen_src);
|
||||
SDL2_Harness_Swap(last_screen_src);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_viewport(int* x, int* y, float* width_multipler, float* height_multiplier) {
|
||||
static void SDL2_Harness_GetViewport(int* x, int* y, float* width_multipler, float* height_multiplier) {
|
||||
*x = viewport.x;
|
||||
*y = viewport.y;
|
||||
*width_multipler = viewport.scale_x;
|
||||
*height_multiplier = viewport.scale_y;
|
||||
}
|
||||
|
||||
void Harness_Platform_Init(tHarness_platform* platform) {
|
||||
platform->ProcessWindowMessages = get_and_handle_message;
|
||||
platform->Sleep = SDL_Delay;
|
||||
platform->GetTicks = SDL_GetTicks;
|
||||
platform->ShowCursor = SDL_ShowCursor;
|
||||
platform->SetWindowPos = set_window_pos;
|
||||
platform->DestroyWindow = destroy_window;
|
||||
platform->GetKeyboardState = get_keyboard_state;
|
||||
platform->GetMousePosition = get_mouse_position;
|
||||
platform->GetMouseButtons = get_mouse_buttons;
|
||||
platform->ShowErrorMessage = show_error_message;
|
||||
static int SDL2_Harness_Platform_Init(tHarness_platform* platform) {
|
||||
if (SDL2_LoadSymbols() != 0) {
|
||||
return 1;
|
||||
}
|
||||
platform->ProcessWindowMessages = SDL2_Harness_ProcessWindowMessages;
|
||||
platform->Sleep = SDL2_Delay;
|
||||
platform->GetTicks = SDL2_GetTicks;
|
||||
platform->ShowCursor = SDL2_ShowCursor;
|
||||
platform->SetWindowPos = SDL2_Harness_SetWindowPos;
|
||||
platform->DestroyWindow = SDL2_Harness_DestroyWindow;
|
||||
platform->GetKeyboardState = SDL2_Harness_GetKeyboardState;
|
||||
platform->GetMousePosition = SDL2_Harness_GetMousePosition;
|
||||
platform->GetMouseButtons = SDL2_Harness_GetMouseButtons;
|
||||
platform->ShowErrorMessage = SDL2_Harness_ShowErrorMessage;
|
||||
|
||||
platform->CreateWindow_ = create_window;
|
||||
platform->Swap = swap;
|
||||
platform->PaletteChanged = palette_changed;
|
||||
platform->GL_GetProcAddress = SDL_GL_GetProcAddress;
|
||||
platform->GetViewport = get_viewport;
|
||||
}
|
||||
platform->CreateWindow_ = SDL2_Harness_CreateWindow;
|
||||
platform->Swap = SDL2_Harness_Swap;
|
||||
platform->PaletteChanged = SDL2_Harness_PaletteChanged;
|
||||
platform->GL_GetProcAddress = SDL2_GL_GetProcAddress;
|
||||
platform->GetViewport = SDL2_Harness_GetViewport;
|
||||
return 0;
|
||||
};
|
||||
|
||||
const tPlatform_bootstrap SDL2_bootstrap = {
|
||||
"sdl2",
|
||||
"SDL2 video backend (libsdl.org)",
|
||||
ePlatform_cap_software | ePlatform_cap_opengl,
|
||||
SDL2_Harness_Platform_Init,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef sdl2_syms_h
|
||||
#define sdl2_syms_h
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#define FOREACH_SDL2_SYM(X) \
|
||||
X(Init, int, (Uint32)) \
|
||||
X(Quit, void, (void)) \
|
||||
X(Delay, void, (Uint32)) \
|
||||
X(GetTicks, Uint32, (void)) \
|
||||
X(GetError, const char*, (void)) \
|
||||
X(PollEvent, int, (SDL_Event*)) \
|
||||
X(ShowSimpleMessageBox, int, (Uint32, const char*, const char *, SDL_Window*)) \
|
||||
X(CreateWindow, SDL_Window*, (const char*, int, int, int, int, Uint32)) \
|
||||
X(DestroyWindow, void, (SDL_Window*)) \
|
||||
X(GetWindowFlags, Uint32, (SDL_Window*)) \
|
||||
X(GetWindowID, Uint32, (SDL_Window*)) \
|
||||
X(GetWindowSize, void, (SDL_Window*, int*, int*)) \
|
||||
X(SetWindowFullscreen, int, (SDL_Window*, Uint32)) \
|
||||
X(SetWindowSize, void, (SDL_Window*, int, int)) \
|
||||
X(CreateRenderer, SDL_Renderer*, (SDL_Window*, int, Uint32)) \
|
||||
X(RenderClear, int, (SDL_Renderer*)) \
|
||||
X(RenderCopy, int, (SDL_Renderer*,SDL_Texture*, const SDL_Rect*, const SDL_Rect*)) \
|
||||
X(RenderPresent, void, (SDL_Renderer*)) \
|
||||
X(RenderWindowToLogical, void, (SDL_Renderer*, int, int, float*, float*)) \
|
||||
X(GetRendererInfo, int, (SDL_Renderer*, SDL_RendererInfo*)) \
|
||||
X(RenderSetLogicalSize, int, (SDL_Renderer*, int, int)) \
|
||||
X(SetRenderDrawBlendMode, int, (SDL_Renderer*, SDL_BlendMode)) \
|
||||
X(CreateTexture, SDL_Texture*, (SDL_Renderer*, Uint32, int, int, int)) \
|
||||
X(LockTexture, int, (SDL_Texture*, const SDL_Rect*, void**, int*)) \
|
||||
X(UnlockTexture, void, (SDL_Texture*)) \
|
||||
X(GetMouseFocus, SDL_Window*, (void)) \
|
||||
X(GetMouseState, Uint32, (int*, int*)) \
|
||||
X(ShowCursor, int, (int)) \
|
||||
X(GetPixelFormatName, const char*, (Uint32)) \
|
||||
X(GetScancodeName, const char *, (SDL_Scancode)) \
|
||||
X(GL_CreateContext, SDL_GLContext, (SDL_Window*)) \
|
||||
X(GL_GetProcAddress, void*, (const char*)) \
|
||||
X(GL_SetAttribute, int, (SDL_GLattr, int)) \
|
||||
X(GL_SetSwapInterval, int, (int)) \
|
||||
X(GL_SwapWindow, void, (SDL_Window*))
|
||||
|
||||
#undef SDL2_SYM
|
||||
|
||||
#endif /* sdl2_syms_h */
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef sdl_dyn_common_h
|
||||
#define sdl_dyn_common_h
|
||||
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#ifdef CreateWindow
|
||||
#undef CreateWindow
|
||||
#endif
|
||||
static void *Harness_LoadObject(const char *name) {
|
||||
return LoadLibraryA(name);
|
||||
}
|
||||
static void Harness_UnloadObject(void *obj) {
|
||||
FreeLibrary(obj);
|
||||
}
|
||||
static void *Harness_LoadFunction(void *obj, const char *name) {
|
||||
return GetProcAddress(obj, name);
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
static void *Harness_LoadObject(const char *name) {
|
||||
return dlopen(name, RTLD_NOW | RTLD_LOCAL);
|
||||
}
|
||||
static void Harness_UnloadObject(void *obj) {
|
||||
dlclose(obj);
|
||||
}
|
||||
static void *Harness_LoadFunction(void *obj, const char *name) {
|
||||
return dlsym(obj, name);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define STR2_JOIN(A,B) A##B
|
||||
#define STR_JOIN(A,B) STR2_JOIN(A, B)
|
||||
|
||||
#define X_TYPEDEF(name, ret, args) typedef ret SDLCALL t##SDL_##name##_fn args;
|
||||
#define X_STATIC_SYMBOL(name, ret, args) static t##SDL_##name##_fn* STR_JOIN(SYMBOL_PREFIX, name);
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
#define X_LOAD_FUNCTION(name, ret, args) \
|
||||
STR_JOIN(SYMBOL_PREFIX, name) = Harness_LoadFunction(OBJECT_NAME, "SDL_" #name); \
|
||||
if (STR_JOIN(SYMBOL_PREFIX, name) == NULL) { \
|
||||
goto failure; \
|
||||
}
|
||||
#else
|
||||
#define X_LOAD_FUNCTION(name, ret, args) STR_JOIN(SYMBOL_PREFIX, name) = SDL_##name;
|
||||
#endif
|
||||
|
||||
FOREACH_SDLX_SYM(X_TYPEDEF)
|
||||
FOREACH_SDLX_SYM(X_STATIC_SYMBOL)
|
||||
|
||||
static int STR_JOIN(SYMBOL_PREFIX,LoadSymbols)(void) {
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
for (size_t i = 0; i < BR_ASIZE(possible_locations); i++) {
|
||||
OBJECT_NAME = Harness_LoadObject(possible_locations[i]);
|
||||
if (OBJECT_NAME != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OBJECT_NAME == NULL) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
FOREACH_SDLX_SYM(X_LOAD_FUNCTION)
|
||||
return 0;
|
||||
#ifdef DETHRACE_SDL_DYNAMIC
|
||||
failure:
|
||||
Harness_UnloadObject(OBJECT_NAME);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* sdl_dyn_common_h */
|
|
@ -1,8 +1,6 @@
|
|||
add_executable(dethrace_test)
|
||||
add_test(NAME test_dethrace COMMAND dethrace_test)
|
||||
|
||||
set(IO_PLATFORM "SDL2")
|
||||
|
||||
target_link_libraries(dethrace_test PRIVATE dethrace_obj)
|
||||
|
||||
target_include_directories(dethrace_test PRIVATE
|
||||
|
|
Loading…
Reference in New Issue