From 7e14a97692329453db274df139a16c6d298ac2ba Mon Sep 17 00:00:00 2001 From: Dethrace Engineering Department <78985374+dethrace-labs@users.noreply.github.com> Date: Mon, 21 Mar 2022 12:10:49 +1300 Subject: [PATCH] Easier platform porting (#108) * Create PORTING.md * Creates io_platform abstraction * removes miniposix * remove unistd refs * removes watcom functions * fixes shadow rendering memory leak --- CMakeLists.txt | 1 - docs/PORTING.md | 68 ++++ lib/miniposix/CMakeLists.txt | 50 --- lib/miniposix/dirent/dirent.c | 382 ------------------ lib/miniposix/dirent/dirent.h | 144 ------- lib/miniposix/fnmatch/fnmatch.c | 311 -------------- lib/miniposix/fnmatch/fnmatch.h | 55 --- lib/miniposix/getopt/getopt.c | 361 ----------------- lib/miniposix/getopt/getopt.h | 69 ---- lib/miniposix/libgen/libgen.c | 263 ------------ lib/miniposix/libgen/libgen.h | 27 -- lib/miniposix/strings/strings.c | 25 -- lib/miniposix/strings/strings.h | 105 ----- lib/miniposix/unistd/unistd.h | 265 ------------ src/BRSRC13/CMakeLists.txt | 2 +- src/BRSRC13/CORE/FW/brlists.c | 2 +- src/BRSRC13/CORE/FW/datafile.c | 88 ++-- src/DETHRACE/CMakeLists.txt | 4 +- src/DETHRACE/common/cutscene.c | 18 +- src/DETHRACE/common/drmem.c | 2 - src/DETHRACE/common/errors.c | 52 ++- src/DETHRACE/common/flicplay.c | 15 +- src/DETHRACE/common/graphics.c | 9 +- src/DETHRACE/common/loading.c | 3 - src/DETHRACE/common/mainloop.c | 2 - src/DETHRACE/common/utility.c | 3 +- src/DETHRACE/main.c | 7 +- src/DETHRACE/pc-dos/dosnet.c | 1 + src/DETHRACE/pc-dos/dossys.c | 71 +--- src/DETHRACE/watcom_functions.c | 26 -- src/DETHRACE/watcom_functions.h | 6 - src/harness/CMakeLists.txt | 40 +- src/harness/harness.c | 102 +++-- src/harness/harness.h | 20 +- src/harness/harness_trace.c | 1 - src/harness/include/harness/hooks.h | 5 +- src/harness/include/harness/os.h | 46 +++ src/harness/include/harness/trace.h | 39 +- src/harness/io_platforms/io_platform.h | 12 + .../{sdl/common.c => io_platforms/sdl_gl.c} | 85 +++- .../{stack_trace_handler.h => os/linux.c} | 247 +++++------ src/harness/os/macos.c | 286 +++++++++++++ src/harness/os/windows.c | 206 ++++++++++ src/harness/platforms/platform.h | 6 - src/harness/platforms/platform_linux.c | 45 --- src/harness/platforms/platform_macosx.c | 44 -- src/harness/platforms/platform_windows.c | 5 - src/harness/platforms/sdl_gl.h | 25 -- .../{sdl => renderers/gl}/gl_renderer.c | 87 +--- .../{sdl => renderers/gl}/gl_renderer.h | 9 +- .../gl/shaders.c} | 0 .../gl/shaders.h} | 0 .../gl/stored_context.c} | 3 +- .../gl/stored_context.h} | 2 +- src/harness/{platforms => renderers}/null.h | 16 +- src/harness/renderers/renderer.h | 20 + src/harness/sdl/common.h | 11 - test/CMakeLists.txt | 2 + test/DETHRACE/test_controls.c | 3 +- test/DETHRACE/test_dossys.c | 1 - test/DETHRACE/test_errors.c | 2 +- test/DETHRACE/test_input.c | 3 +- test/DETHRACE/test_loading.c | 1 - test/DETHRACE/test_powerup.c | 1 - test/main.c | 16 +- test/tests.h | 23 +- 66 files changed, 1079 insertions(+), 2772 deletions(-) create mode 100644 docs/PORTING.md delete mode 100644 lib/miniposix/CMakeLists.txt delete mode 100644 lib/miniposix/dirent/dirent.c delete mode 100644 lib/miniposix/dirent/dirent.h delete mode 100644 lib/miniposix/fnmatch/fnmatch.c delete mode 100644 lib/miniposix/fnmatch/fnmatch.h delete mode 100644 lib/miniposix/getopt/getopt.c delete mode 100644 lib/miniposix/getopt/getopt.h delete mode 100644 lib/miniposix/libgen/libgen.c delete mode 100644 lib/miniposix/libgen/libgen.h delete mode 100644 lib/miniposix/strings/strings.c delete mode 100644 lib/miniposix/strings/strings.h delete mode 100644 lib/miniposix/unistd/unistd.h delete mode 100644 src/DETHRACE/watcom_functions.c delete mode 100644 src/DETHRACE/watcom_functions.h create mode 100644 src/harness/include/harness/os.h create mode 100644 src/harness/io_platforms/io_platform.h rename src/harness/{sdl/common.c => io_platforms/sdl_gl.c} (58%) rename src/harness/{stack_trace_handler.h => os/linux.c} (53%) create mode 100644 src/harness/os/macos.c create mode 100644 src/harness/os/windows.c delete mode 100644 src/harness/platforms/platform.h delete mode 100644 src/harness/platforms/platform_linux.c delete mode 100644 src/harness/platforms/platform_macosx.c delete mode 100644 src/harness/platforms/platform_windows.c delete mode 100644 src/harness/platforms/sdl_gl.h rename src/harness/{sdl => renderers/gl}/gl_renderer.c (92%) rename src/harness/{sdl => renderers/gl}/gl_renderer.h (69%) rename src/harness/{sdl/gl_renderer_shaders.c => renderers/gl/shaders.c} (100%) rename src/harness/{sdl/gl_renderer_shaders.h => renderers/gl/shaders.h} (100%) rename src/harness/{sdl/gl_brender_stored_context.c => renderers/gl/stored_context.c} (93%) rename src/harness/{sdl/gl_brender_stored_context.h => renderers/gl/stored_context.h} (93%) rename src/harness/{platforms => renderers}/null.h (64%) create mode 100644 src/harness/renderers/renderer.h delete mode 100644 src/harness/sdl/common.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 389dea72..e4de246a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ option(BUILD_TESTS "Build unit tests." OFF) find_package(SDL2 REQUIRED) add_subdirectory(lib/libsmacker) -add_subdirectory(lib/miniposix) add_subdirectory(lib/glad) add_subdirectory(lib/cglm EXCLUDE_FROM_ALL) diff --git a/docs/PORTING.md b/docs/PORTING.md new file mode 100644 index 00000000..b084e9c3 --- /dev/null +++ b/docs/PORTING.md @@ -0,0 +1,68 @@ +# Porting Dethrace to other systems + +## Operating Systems + +See: xxx + +Assuming an operating system called _foo_, follow the steps to add support for it. + +1. Add a new file `os/foo.h` and implement the required functions defined in `os.h`: +- `OS_GetTime` +- `OS_Sleep` +- `OS_Basename` +- `OS_GetFirstFileInDirectory` +- `OS_GetNextFileInDirectory` +- `OS_IsDebuggerPresent` +- `OS_InstallSignalHandler` + +2. Update `src/harness/CMakeLists.h` and add a new conditional section for "os/foo.h", based on existing conditions for Windows, MacOS etc. + +For example: + +``` +... +elseif( _FOO_ ) +target_sources(harness PRIVATE + os/foo.c +) +... +``` + +## IO Platform (windowing / input / rendering) + +An `IOPlatform` in _dethrace_ implements windowing and input handling, and points to a _renderer_. + +The default IO platform is `SDL_OpenGL`, which uses SDL for windowing and input, and OpenGL for rendering. See `io_platforms/sdl_gl.c`. + +To add a new `IOPlatform`: + +1. Create `io_platforms/my_platform.c` file and implement the required functions defined in `io_platform.h`: +- `Window_Create` +- `Window_PollEvents` +- `Window_Swap` +- `Input_GetKeyMap` +- `Input_IsKeyDown` + +`Window_Create` returns a `tRenderer*`, which must implement the interface defined in `renderers/renderer.h`. See `renderers/gl` for an example. + +2. Add a new conditional section in `src/harness/CMakeLists.txt` for your new platform + +For example: +``` +if (IO_PLATFORM STREQUAL "My_Platform") + target_sources(harness PRIVATE + io_platforms/my_platform.c + ) +endif() +``` + +3. Run cmake to update your build with the new platform +```sh +cd build +cmake -DIO_PLATFORM=My_Platform .. +``` + +4. Build +``` +cmake --build . +``` diff --git a/lib/miniposix/CMakeLists.txt b/lib/miniposix/CMakeLists.txt deleted file mode 100644 index 44429475..00000000 --- a/lib/miniposix/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -include(CheckIncludeFile) - -# Check if we are missing any posix headers we consider required. -check_include_file(strings.h HAVE_STRINGS_H) -check_include_file(libgen.h HAVE_LIBGEN_H) -check_include_file(dirent.h HAVE_DIRENT_H) -check_include_file(fnmatch.h HAVE_FNMATCH_H) -check_include_file(getopt.h HAVE_GETOPT_H) -check_include_file(unistd.h HAVE_UNISTD_H) - -if(HAVE_STRINGS_H AND HAVE_UNISTD_H AND HAVE_LIBGEN_H AND HAVE_DIRENT_H AND HAVE_FNMATCH_H AND HAVE_GETOPT_H) - add_library(miniposix INTERFACE) -else() - add_library(miniposix STATIC) - - # Only win32 targets should really need miniposix at all, but just to be safe. - if(WIN32) - target_compile_definitions(miniposix PUBLIC _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE WIN32_LEAN_AND_MEAN) - endif() -endif() - -if(NOT HAVE_STRINGS_H) - target_sources(miniposix PRIVATE strings/strings.c strings/strings.h) - target_include_directories(miniposix PUBLIC strings) -endif() - -if(NOT HAVE_LIBGEN_H) - target_sources(miniposix PRIVATE libgen/libgen.c libgen/libgen.h) - target_include_directories(miniposix PUBLIC libgen) -endif() - -if(NOT HAVE_DIRENT_H) - target_sources(miniposix PRIVATE dirent/dirent.c dirent/dirent.h) - target_include_directories(miniposix PUBLIC dirent) -endif() - -if(NOT HAVE_FNMATCH_H) - target_sources(miniposix PRIVATE fnmatch/fnmatch.c fnmatch/fnmatch.h) - target_include_directories(miniposix PUBLIC fnmatch) -endif() - -if(NOT HAVE_GETOPT_H) - target_sources(miniposix PRIVATE getopt/getopt.c getopt/getopt.h) - target_include_directories(miniposix PUBLIC getopt) -endif() - -if(NOT HAVE_UNISTD_H) - target_sources(miniposix PRIVATE unistd/unistd.h) - target_include_directories(miniposix PUBLIC unistd) -endif() diff --git a/lib/miniposix/dirent/dirent.c b/lib/miniposix/dirent/dirent.c deleted file mode 100644 index 2a156be6..00000000 --- a/lib/miniposix/dirent/dirent.c +++ /dev/null @@ -1,382 +0,0 @@ -#include -#include -#include -#include - -struct __dir -{ - struct dirent *entries; - HANDLE fd; - long int count; - long int index; -}; - -static void __seterrno(int value) -{ -#ifdef _MSC_VER - _set_errno(value); -#else /* _MSC_VER */ - errno = value; -#endif /* _MSC_VER */ -} - -int closedir(DIR *dirp) -{ - struct __dir *data = NULL; - if (!dirp) { - __seterrno(EBADF); - return -1; - } - data = (struct __dir *)dirp; - CloseHandle((HANDLE)data->fd); - free(data->entries); - free(data); - return 0; -} - -static int __islink(const wchar_t *name, char *buffer) -{ - DWORD io_result = 0; - DWORD bytes_returned = 0; - HANDLE hFile = - CreateFileW(name, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - - io_result = DeviceIoControl( - hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytes_returned, NULL); - - CloseHandle(hFile); - - if (io_result == 0) - return 0; - - return ((REPARSE_GUID_DATA_BUFFER *)buffer)->ReparseTag == IO_REPARSE_TAG_SYMLINK; -} - -static __ino_t __inode(const wchar_t *name) -{ - __ino_t value = { 0 }; - BOOL result; - FILE_ID_INFO fileid; - BY_HANDLE_FILE_INFORMATION info; - HANDLE hFile = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); - if (hFile == INVALID_HANDLE_VALUE) - return value; - - result = GetFileInformationByHandleEx(hFile, FileIdInfo, &fileid, sizeof(fileid)); - if (result) { - value.serial = fileid.VolumeSerialNumber; - memcpy(value.fileid, fileid.FileId.Identifier, 16); - } else { - result = GetFileInformationByHandle(hFile, &info); - if (result) { - value.serial = info.dwVolumeSerialNumber; - memcpy(value.fileid + 8, &info.nFileIndexHigh, 4); - memcpy(value.fileid + 12, &info.nFileIndexLow, 4); - } - } - CloseHandle(hFile); - return value; -} - -static DIR *__internal_opendir(wchar_t *wname, int size) -{ - struct __dir *data = NULL; - struct dirent *tmp_entries = NULL; - static char default_char = '?'; - static wchar_t *prefix = L"\\\\?\\"; - static wchar_t *suffix = L"\\*.*"; - int extra_prefix = 4; /* use prefix "\\?\" to handle long file names */ - static int extra_suffix = 4; /* use suffix "\*.*" to find everything */ - WIN32_FIND_DATAW w32fd = { 0 }; - HANDLE hFindFile = INVALID_HANDLE_VALUE; - static int grow_factor = 2; - char *buffer = NULL; - - /* Ensure path only uses windows separator, of FindFirstFileW will fail. */ - wchar_t* rep = wname; - while ((rep = wcschr(rep, L'/')) != NULL) { - *rep++ = L'\\'; - } - - memcpy(wname + extra_prefix + size - 1, suffix, sizeof(wchar_t) * extra_prefix); - wname[size + extra_prefix + extra_suffix - 1] = 0; - - if (memcmp(wname + extra_prefix, L"\\\\?\\", sizeof(wchar_t) * extra_prefix) == 0) { - wname += extra_prefix; - extra_prefix = 0; - } - - hFindFile = FindFirstFileW(wname, &w32fd); - if (INVALID_HANDLE_VALUE == hFindFile) { - __seterrno(ENOENT); - return NULL; - } - - data = (struct __dir *)malloc(sizeof(struct __dir)); - if (!data) - goto out_of_memory; - wname[extra_prefix + size - 1] = 0; - data->fd = CreateFileW(wname, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - wname[extra_prefix + size - 1] = L'\\'; - data->count = 16; - data->index = 0; - data->entries = (struct dirent *)malloc(sizeof(struct dirent) * data->count); - if (!data->entries) - goto out_of_memory; - buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); - if (!buffer) - goto out_of_memory; - do { - WideCharToMultiByte( - CP_UTF8, 0, w32fd.cFileName, -1, data->entries[data->index].d_name, NAME_MAX, &default_char, NULL); - - memcpy(wname + extra_prefix + size, w32fd.cFileName, sizeof(wchar_t) * NAME_MAX); - - if (((w32fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT) - && __islink(wname, buffer)) - data->entries[data->index].d_type = DT_LNK; - else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) == FILE_ATTRIBUTE_DEVICE) - data->entries[data->index].d_type = DT_CHR; - else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) - data->entries[data->index].d_type = DT_DIR; - else - data->entries[data->index].d_type = DT_REG; - - data->entries[data->index].d_ino = __inode(wname); - data->entries[data->index].d_reclen = sizeof(struct dirent); - data->entries[data->index].d_namelen = (unsigned char)wcslen(w32fd.cFileName); - data->entries[data->index].d_off = 0; - - if (++data->index == data->count) { - tmp_entries = (struct dirent *)realloc(data->entries, sizeof(struct dirent) * data->count * grow_factor); - if (!tmp_entries) - goto out_of_memory; - data->entries = tmp_entries; - data->count *= grow_factor; - } - } while (FindNextFileW(hFindFile, &w32fd) != 0); - - free(buffer); - FindClose(hFindFile); - - data->count = data->index; - data->index = 0; - return (DIR *)data; -out_of_memory: - if (data) { - if (INVALID_HANDLE_VALUE != (HANDLE)data->fd) - CloseHandle((HANDLE)data->fd); - free(data->entries); - } - free(buffer); - free(data); - if (INVALID_HANDLE_VALUE != hFindFile) - FindClose(hFindFile); - __seterrno(ENOMEM); - return NULL; -} - -static wchar_t *__get_buffer() -{ - wchar_t *name = malloc(sizeof(wchar_t) * (NTFS_MAX_PATH + NAME_MAX + 8)); - if (name) - memcpy(name, L"\\\\?\\", sizeof(wchar_t) * 4); - return name; -} - -DIR *opendir(const char *name) -{ - DIR *dirp = NULL; - wchar_t *wname = __get_buffer(); - int size = 0; - if (!wname) { - __seterrno(ENOMEM); - return NULL; - } - size = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname + 4, NTFS_MAX_PATH); - if (0 == size) { - free(wname); - return NULL; - } - dirp = __internal_opendir(wname, size); - free(wname); - return dirp; -} - -DIR *_wopendir(const wchar_t *name) -{ - DIR *dirp = NULL; - wchar_t *wname = __get_buffer(); - int size = 0; - if (!wname) { - __seterrno(ENOMEM); - return NULL; - } - size = (int)wcslen(name); - if (size > NTFS_MAX_PATH) { - free(wname); - return NULL; - } - memcpy(wname + 4, name, sizeof(wchar_t) * (size + 1)); - dirp = __internal_opendir(wname, size + 1); - free(wname); - return dirp; -} - -DIR *fdopendir(int fd) -{ - DIR *dirp = NULL; - wchar_t *wname = __get_buffer(); - int size = 0; - if (!wname) { - __seterrno(ENOMEM); - return NULL; - } - size = GetFinalPathNameByHandleW((HANDLE)((intptr_t)fd), wname, NTFS_MAX_PATH, FILE_NAME_NORMALIZED); - if (0 == size) { - free(wname); - __seterrno(ENOTDIR); - return NULL; - } - dirp = __internal_opendir(wname, size + 1); - free(wname); - return dirp; -} - -struct dirent *readdir(DIR *dirp) -{ - struct __dir *data = (struct __dir *)dirp; - if (!data) { - __seterrno(EBADF); - return NULL; - } - if (data->index < data->count) { - return &data->entries[data->index++]; - } - return NULL; -} - -int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) -{ - struct __dir *data = (struct __dir *)dirp; - if (!data) { - return EBADF; - } - if (data->index < data->count) { - if (entry) - memcpy(entry, &data->entries[data->index++], sizeof(struct dirent)); - if (result) - *result = entry; - } else if (result) - *result = NULL; - return 0; -} - -void seekdir(DIR *dirp, long int offset) -{ - if (dirp) { - struct __dir *data = (struct __dir *)dirp; - data->index = (offset < data->count) ? offset : data->index; - } -} - -void rewinddir(DIR *dirp) -{ - seekdir(dirp, 0); -} - -long int telldir(DIR *dirp) -{ - if (!dirp) { - __seterrno(EBADF); - return -1; - } - return ((struct __dir *)dirp)->count; -} - -int dirfd(DIR *dirp) -{ - if (!dirp) { - __seterrno(EINVAL); - return -1; - } - return (int)((struct __dir *)dirp)->fd; -} - -int scandir(const char *dirp, - struct dirent ***namelist, - int (*filter)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)) -{ - struct dirent **entries = NULL, **tmp_entries = NULL; - long int i = 0, index = 0, count = 16; - DIR *d = opendir(dirp); - struct __dir *data = (struct __dir *)d; - if (!data) { - closedir(d); - __seterrno(ENOENT); - return -1; - } - entries = (struct dirent **)malloc(sizeof(struct dirent *) * count); - if (!entries) { - closedir(d); - __seterrno(ENOMEM); - return -1; - } - for (i = 0; i < data->count; ++i) { - if (!filter || filter(&data->entries[i])) { - entries[index] = (struct dirent *)malloc(sizeof(struct dirent)); - if (!entries[index]) { - closedir(d); - for (i = 0; i < index; ++i) - free(entries[index]); - free(entries); - __seterrno(ENOMEM); - return -1; - } - memcpy(entries[index], &data->entries[i], sizeof(struct dirent)); - if (++index == count) { - tmp_entries = (struct dirent **)realloc(entries, sizeof(struct dirent *) * count * 2); - if (!tmp_entries) { - closedir(d); - for (i = 0; i < index; ++i) - free(entries[index - 1]); - free(entries); - __seterrno(ENOMEM); - return -1; - } - entries = tmp_entries; - count *= 2; - } - } - } - qsort(entries, index, sizeof(struct dirent *), compar); - entries[index] = NULL; - if (namelist) - *namelist = entries; - closedir(d); - return 0; -} - -int alphasort(const void *a, const void *b) -{ - struct dirent **dira = (struct dirent **)a, **dirb = (struct dirent **)b; - if (!dira || !dirb) - return 0; - return strcoll((*dira)->d_name, (*dirb)->d_name); -} - -static int __strverscmp(const char *s1, const char *s2) -{ - return alphasort(s1, s2); -} - -int versionsort(const void *a, const void *b) -{ - struct dirent **dira = (struct dirent **)a, **dirb = (struct dirent **)b; - if (!dira || !dirb) - return 0; - return __strverscmp((*dira)->d_name, (*dirb)->d_name); -} diff --git a/lib/miniposix/dirent/dirent.h b/lib/miniposix/dirent/dirent.h deleted file mode 100644 index dff42581..00000000 --- a/lib/miniposix/dirent/dirent.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -MIT License -Copyright (c) 2019 win32ports -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#ifndef WIN32PORTS_DIRENT_H -#define WIN32PORTS_DIRENT_H - -#ifndef _WIN32 - -#pragma message("this dirent.h implementation is for Windows only!") - -#elif defined __MINGW32__ - -#include <../include/dirent.h> - -#else - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#ifndef NAME_MAX -#define NAME_MAX 260 -#endif /* NAME_MAX */ - -#ifndef DT_UNKNOWN -#define DT_UNKNOWN 0 -#endif /* DT_UNKNOWN */ - -#ifndef DT_FIFO -#define DT_FIFO 1 -#endif /* DT_FIFO */ - -#ifndef DT_CHR -#define DT_CHR 2 -#endif /* DT_CHR */ - -#ifndef DT_DIR -#define DT_DIR 4 -#endif /* DT_DIR */ - -#ifndef DT_BLK -#define DT_BLK 6 -#endif /* DT_BLK */ - -#ifndef DT_REG -#define DT_REG 8 -#endif /* DT_REF */ - -#ifndef DT_LNK -#define DT_LNK 10 -#endif /* DT_LNK */ - -#ifndef DT_SOCK -#define DT_SOCK 12 -#endif /* DT_SOCK */ - -#ifndef DT_WHT -#define DT_WHT 14 -#endif /* DT_WHT */ - -#ifndef _DIRENT_HAVE_D_NAMLEN -#define _DIRENT_HAVE_D_NAMLEN 1 -#endif /* _DIRENT_HAVE_D_NAMLEN */ - -#ifndef _DIRENT_HAVE_D_RECLEN -#define _DIRENT_HAVE_D_RECLEN 1 -#endif /* _DIRENT_HAVE_D_RECLEN */ - -#ifndef _DIRENT_HAVE_D_OFF -#define _DIRENT_HAVE_D_OFF 1 -#endif /* _DIRENT_HAVE_D_OFF */ - -#ifndef _DIRENT_HAVE_D_TYPE -#define _DIRENT_HAVE_D_TYPE 1 -#endif /* _DIRENT_HAVE_D_TYPE */ - -#ifndef NTFS_MAX_PATH -#define NTFS_MAX_PATH 32768 -#endif /* NTFS_MAX_PATH */ - -typedef struct __dir DIR; - -typedef struct ino_t -{ - unsigned long long serial; - unsigned char fileid[16]; -} __ino_t; - -struct dirent -{ - __ino_t d_ino; - off_t d_off; - unsigned short d_reclen; - unsigned char d_namelen; - unsigned char d_type; - char d_name[NAME_MAX]; -}; - -int closedir(DIR *dirp); -DIR *opendir(const char *name); -DIR *_wopendir(const wchar_t *name); -DIR *fdopendir(int fd); -struct dirent *readdir(DIR *dirp); -int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); -void seekdir(DIR *dirp, long int offset); -void rewinddir(DIR *dirp); -long int telldir(DIR *dirp); -int dirfd(DIR *dirp); -int scandir(const char *dirp, - struct dirent ***namelist, - int (*filter)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)); -int alphasort(const void *a, const void *b); -int versionsort(const void *a, const void *b); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _WIN32 */ - -#endif /* WIN32PORTS_DIRENT_H */ diff --git a/lib/miniposix/fnmatch/fnmatch.c b/lib/miniposix/fnmatch/fnmatch.c deleted file mode 100644 index a8a6a15c..00000000 --- a/lib/miniposix/fnmatch/fnmatch.c +++ /dev/null @@ -1,311 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Guido van Rossum. - * - * Copyright (c) 2011 The FreeBSD Foundation - * All rights reserved. - * Portions of this software were developed by David Chisnall - * under sponsorship from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. - * Compares a filename or pathname to a pattern. - */ - -/* - * Some notes on multibyte character support: - * 1. Patterns with illegal byte sequences match nothing. - * 2. Illegal byte sequences in the "string" argument are handled by treating - * them as single-byte characters with a value of the first byte of the - * sequence cast to wchar_t. - * 3. Multibyte conversion state objects (mbstate_t) are passed around and - * used for most, but not all, conversions. Further work will be required - * to support state-dependent encodings. - */ - -#include -#include -#include -#include -#include - -#define EOS '\0' - -#define RANGE_MATCH 1 -#define RANGE_NOMATCH 0 -#define RANGE_ERROR (-1) - -static int rangematch(const char *, wchar_t, int, char **, mbstate_t *); -static int fnmatch1(const char *, const char *, const char *, int, mbstate_t, - mbstate_t); - -int -fnmatch(const char *pattern, const char *string, int flags) -{ - static const mbstate_t initial; - - return (fnmatch1(pattern, string, string, flags, initial, initial)); -} - -static int -fnmatch1(const char *pattern, const char *string, const char *stringstart, - int flags, mbstate_t patmbs, mbstate_t strmbs) -{ - const char *bt_pattern, *bt_string; - mbstate_t bt_patmbs, bt_strmbs; - char *newp; - char c; - wchar_t pc, sc; - size_t pclen, sclen; - - bt_pattern = bt_string = NULL; - for (;;) { - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); - if (pclen == (size_t)-1 || pclen == (size_t)-2) - return (FNM_NOMATCH); - pattern += pclen; - sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); - if (sclen == (size_t)-1 || sclen == (size_t)-2) { - sc = (unsigned char)*string; - sclen = 1; - memset(&strmbs, 0, sizeof(strmbs)); - } - switch (pc) { - case EOS: - if ((flags & FNM_LEADING_DIR) && sc == '/') - return (0); - if (sc == EOS) - return (0); - goto backtrack; - case '?': - if (sc == EOS) - return (FNM_NOMATCH); - if (sc == '/' && (flags & FNM_PATHNAME)) - goto backtrack; - if (sc == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - goto backtrack; - string += sclen; - break; - case '*': - c = *pattern; - /* Collapse multiple stars. */ - while (c == '*') - c = *++pattern; - - if (sc == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - goto backtrack; - - /* Optimize for pattern with * at end or before /. */ - if (c == EOS) - if (flags & FNM_PATHNAME) - return ((flags & FNM_LEADING_DIR) || - strchr(string, '/') == NULL ? - 0 : FNM_NOMATCH); - else - return (0); - else if (c == '/' && flags & FNM_PATHNAME) { - if ((string = strchr(string, '/')) == NULL) - return (FNM_NOMATCH); - break; - } - - /* - * First try the shortest match for the '*' that - * could work. We can forget any earlier '*' since - * there is no way having it match more characters - * can help us, given that we are already here. - */ - bt_pattern = pattern, bt_patmbs = patmbs; - bt_string = string, bt_strmbs = strmbs; - break; - case '[': - if (sc == EOS) - return (FNM_NOMATCH); - if (sc == '/' && (flags & FNM_PATHNAME)) - goto backtrack; - if (sc == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - goto backtrack; - - switch (rangematch(pattern, sc, flags, &newp, - &patmbs)) { - case RANGE_ERROR: - goto norm; - case RANGE_MATCH: - pattern = newp; - break; - case RANGE_NOMATCH: - goto backtrack; - } - string += sclen; - break; - case '\\': - if (!(flags & FNM_NOESCAPE)) { - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, - &patmbs); - if (pclen == 0 || pclen == (size_t)-1 || - pclen == (size_t)-2) - return (FNM_NOMATCH); - pattern += pclen; - } - /* FALLTHROUGH */ - default: - norm: - string += sclen; - if (pc == sc) - ; - else if ((flags & FNM_CASEFOLD) && - (towlower(pc) == towlower(sc))) - ; - else { - backtrack: - /* - * If we have a mismatch (other than hitting - * the end of the string), go back to the last - * '*' seen and have it match one additional - * character. - */ - if (bt_pattern == NULL) - return (FNM_NOMATCH); - sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX, - &bt_strmbs); - if (sclen == (size_t)-1 || - sclen == (size_t)-2) { - sc = (unsigned char)*bt_string; - sclen = 1; - memset(&bt_strmbs, 0, - sizeof(bt_strmbs)); - } - if (sc == EOS) - return (FNM_NOMATCH); - if (sc == '/' && flags & FNM_PATHNAME) - return (FNM_NOMATCH); - bt_string += sclen; - pattern = bt_pattern, patmbs = bt_patmbs; - string = bt_string, strmbs = bt_strmbs; - } - break; - } - } - /* NOTREACHED */ -} - -static int __wcollate_range_cmp(wchar_t c1, wchar_t c2) -{ - wchar_t s1[2], s2[2]; - - s1[0] = c1; - s1[1] = L'\0'; - s2[0] = c2; - s2[1] = L'\0'; - return (wcscoll(s1, s2)); -} - -static int -rangematch(const char *pattern, wchar_t test, int flags, char **newp, - mbstate_t *patmbs) -{ - int negate, ok; - wchar_t c, c2; - size_t pclen; - const char *origpat; - - /* - * A bracket expression starting with an unquoted circumflex - * character produces unspecified results (IEEE 1003.2-1992, - * 3.13.2). This implementation treats it like '!', for - * consistency with the regular expression syntax. - * J.T. Conklin (conklin@ngai.kaleida.com) - */ - if ((negate = (*pattern == '!' || *pattern == '^'))) - ++pattern; - - if (flags & FNM_CASEFOLD) - test = towlower(test); - - /* - * A right bracket shall lose its special meaning and represent - * itself in a bracket expression if it occurs first in the list. - * -- POSIX.2 2.8.3.2 - */ - ok = 0; - origpat = pattern; - for (;;) { - if (*pattern == ']' && pattern > origpat) { - pattern++; - break; - } else if (*pattern == '\0') { - return (RANGE_ERROR); - } else if (*pattern == '/' && (flags & FNM_PATHNAME)) { - return (RANGE_NOMATCH); - } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) - pattern++; - pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs); - if (pclen == (size_t)-1 || pclen == (size_t)-2) - return (RANGE_NOMATCH); - pattern += pclen; - - if (flags & FNM_CASEFOLD) - c = towlower(c); - - if (*pattern == '-' && *(pattern + 1) != EOS && - *(pattern + 1) != ']') { - if (*++pattern == '\\' && !(flags & FNM_NOESCAPE)) - if (*pattern != EOS) - pattern++; - pclen = mbrtowc(&c2, pattern, MB_LEN_MAX, patmbs); - if (pclen == (size_t)-1 || pclen == (size_t)-2) - return (RANGE_NOMATCH); - pattern += pclen; - if (c2 == EOS) - return (RANGE_ERROR); - - if (flags & FNM_CASEFOLD) - c2 = towlower(c2); - - if (__wcollate_range_cmp(c, test) <= 0 - && __wcollate_range_cmp(test, c2) <= 0 - ) - ok = 1; - } else if (c == test) - ok = 1; - } - - *newp = (char *)pattern; - return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); -} diff --git a/lib/miniposix/fnmatch/fnmatch.h b/lib/miniposix/fnmatch/fnmatch.h deleted file mode 100644 index 8f9193de..00000000 --- a/lib/miniposix/fnmatch/fnmatch.h +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef WIN32PORTS_FNMATCH_H -#define WIN32PORTS_FNMATCH_H - -#define FNM_NOMATCH 1 /* Match failed. */ - -#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ -#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ -#define FNM_PERIOD 0x04 /* Period must be matched by period. */ - -#if __XSI_VISIBLE -#define FNM_NOSYS (-1) /* Reserved. */ -#endif - -#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ -#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ -#define FNM_IGNORECASE FNM_CASEFOLD -#define FNM_FILE_NAME FNM_PATHNAME - -int fnmatch(const char *, const char *, int); - -#endif /* !WIN32PORTS_FNMATCH_H */ diff --git a/lib/miniposix/getopt/getopt.c b/lib/miniposix/getopt/getopt.c deleted file mode 100644 index e1b27ba1..00000000 --- a/lib/miniposix/getopt/getopt.c +++ /dev/null @@ -1,361 +0,0 @@ -/* -Copyright (C) 1997 Gregory Pietsch - -[These files] are hereby placed in the public domain without restrictions. Just -give the author credit, don't claim you wrote it or prevent anyone else from -using it. -*/ - -/**************************************************************************** - -getopt.c - Read command line options - -AUTHOR: Gregory Pietsch -CREATED Fri Jan 10 21:13:05 1997 - -DESCRIPTION: - -The getopt() function parses the command line arguments. Its arguments argc -and argv are the argument count and array as passed to the main() function -on program invocation. The argument optstring is a list of available option -characters. If such a character is followed by a colon (`:'), the option -takes an argument, which is placed in optarg. If such a character is -followed by two colons, the option takes an optional argument, which is -placed in optarg. If the option does not take an argument, optarg is NULL. - -The external variable optind is the index of the next array element of argv -to be processed; it communicates from one call to the next which element to -process. - -The getopt_long() function works like getopt() except that it also accepts -long options started by two dashes `--'. If these take values, it is either -in the form - ---arg=value - - or - ---arg value - -It takes the additional arguments longopts which is a pointer to the first -element of an array of type GETOPT_LONG_OPTION_T. The last element of the -array has to be filled with NULL for the name field. - -The longind pointer points to the index of the current long option relative -to longopts if it is non-NULL. - -The getopt() function returns the option character if the option was found -successfully, `:' if there was a missing parameter for one of the options, -`?' for an unknown option character, and EOF for the end of the option list. - -The getopt_long() function's return value is described in the header file. - -The function getopt_long_only() is identical to getopt_long(), except that a -plus sign `+' can introduce long options as well as `--'. - -The following describes how to deal with options that follow non-option -argv-elements. - -If the caller did not specify anything, the default is REQUIRE_ORDER if the -environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. - -REQUIRE_ORDER means don't recognize them as options; stop option processing -when the first non-option is seen. This is what Unix does. This mode of -operation is selected by either setting the environment variable -POSIXLY_CORRECT, or using `+' as the first character of the optstring -parameter. - -PERMUTE is the default. We permute the contents of ARGV as we scan, so that -eventually all the non-options are at the end. This allows options to be -given in any order, even with programs that were not written to expect this. - -RETURN_IN_ORDER is an option available to programs that were written to -expect options and other argv-elements in any order and that care about the -ordering of the two. We describe each non-option argv-element as if it were -the argument of an option with character code 1. Using `-' as the first -character of the optstring parameter selects this mode of operation. - -The special argument `--' forces an end of option-scanning regardless of the -value of ordering. In the case of RETURN_IN_ORDER, only `--' can cause -getopt() and friends to return EOF with optind != argc. - -COPYRIGHT NOTICE AND DISCLAIMER: - -Copyright (C) 1997 Gregory Pietsch - -This file and the accompanying getopt.h header file are hereby placed in the -public domain without restrictions. Just give the author credit, don't -claim you wrote it or prevent anyone else from using it. - -Gregory Pietsch's current e-mail address: -gpietsch@comcast.net -****************************************************************************/ - -/* include files */ -#include -#include -#include -#include - -/* macros */ - -/* types */ -typedef enum GETOPT_ORDERING_T -{ - PERMUTE, - RETURN_IN_ORDER, - REQUIRE_ORDER -} GETOPT_ORDERING_T; - -/* globally-defined variables */ -char *optarg = NULL; -int optind = 0; -int opterr = 1; -int optopt = '?'; - -/* functions */ - -/* reverse_argv_elements: reverses num elements starting at argv */ -static void reverse_argv_elements(char **argv, int num) -{ - int i; - char *tmp; - - for (i = 0; i < (num >> 1); i++) { - tmp = argv[i]; - argv[i] = argv[num - i - 1]; - argv[num - i - 1] = tmp; - } -} - -/* permute: swap two blocks of argv-elements given their lengths */ -static void permute(char **argv, int len1, int len2) -{ - reverse_argv_elements(argv, len1); - reverse_argv_elements(argv, len1 + len2); - reverse_argv_elements(argv, len2); -} - -/* is_option: is this argv-element an option or the end of the option list? */ -static int is_option(char *argv_element, int only) -{ - return ((argv_element == NULL) || (argv_element[0] == '-') || (only && argv_element[0] == '+')); -} - -/* getopt_internal: the function that does all the dirty work */ -static int getopt_internal(int argc, char **argv, char *shortopts, GETOPT_LONG_OPTION_T *longopts, int *longind, int only) -{ - GETOPT_ORDERING_T ordering = PERMUTE; - static size_t optwhere = 0; - size_t permute_from = 0; - int num_nonopts = 0; - int optindex = 0; - size_t match_chars = 0; - char *possible_arg = NULL; - int longopt_match = -1; - int has_arg = -1; - char *cp = NULL; - int arg_next = 0; - - /* first, deal with silly parameters and easy stuff */ - if (argc == 0 || argv == NULL || (shortopts == NULL && longopts == NULL)) - return (optopt = '?'); - if (optind >= argc || argv[optind] == NULL) - return EOF; - if (strcmp(argv[optind], "--") == 0) { - optind++; - return EOF; - } - /* if this is our first time through */ - if (optind == 0) { - optind = 1; - optwhere = 1; - } - - /* define ordering */ - if (shortopts != NULL && (*shortopts == '-' || *shortopts == '+')) { - ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER; - shortopts++; - } else - ordering = (getenv("POSIXLY_CORRECT") != NULL) ? REQUIRE_ORDER : PERMUTE; - - /* - * based on ordering, find our next option, if we're at the beginning of - * one - */ - if (optwhere == 1) { - switch (ordering) { - case PERMUTE: - permute_from = optind; - num_nonopts = 0; - while (!is_option(argv[optind], only)) { - optind++; - num_nonopts++; - } - if (argv[optind] == NULL) { - /* no more options */ - optind = (int)permute_from; - return EOF; - } else if (strcmp(argv[optind], "--") == 0) { - /* no more options, but have to get `--' out of the way */ - permute(argv + permute_from, num_nonopts, 1); - optind = (int)(permute_from + 1); - return EOF; - } - break; - case RETURN_IN_ORDER: - if (!is_option(argv[optind], only)) { - optarg = argv[optind++]; - return (optopt = 1); - } - break; - case REQUIRE_ORDER: - if (!is_option(argv[optind], only)) - return EOF; - break; - } - } - /* we've got an option, so parse it */ - - /* first, is it a long option? */ - if (longopts != NULL && (strncmp(argv[optind], "--", 2) == 0 || (only && argv[optind][0] == '+')) && optwhere == 1) { - /* handle long options */ - if (strncmp(argv[optind], "--", 2) == 0) - optwhere = 2; - longopt_match = -1; - possible_arg = strchr(argv[optind] + optwhere, '='); - if (possible_arg == NULL) { - /* no =, so next argv might be arg */ - match_chars = strlen(argv[optind]); - possible_arg = argv[optind] + match_chars; - match_chars = match_chars - optwhere; - } else - match_chars = (possible_arg - argv[optind]) - optwhere; - for (optindex = 0; longopts[optindex].name != NULL; optindex++) { - if (strncmp(argv[optind] + optwhere, longopts[optindex].name, match_chars) == 0) { - /* do we have an exact match? */ - if (match_chars == strlen(longopts[optindex].name)) { - longopt_match = optindex; - break; - } - /* do any characters match? */ - else { - if (longopt_match < 0) - longopt_match = optindex; - else { - /* we have ambiguous options */ - if (opterr) - fprintf(stderr, - "%s: option `%s' is ambiguous " - "(could be `--%s' or `--%s')\n", - argv[0], - argv[optind], - longopts[longopt_match].name, - longopts[optindex].name); - return (optopt = '?'); - } - } - } - } - if (longopt_match >= 0) - has_arg = longopts[longopt_match].has_arg; - } - /* if we didn't find a long option, is it a short option? */ - if (longopt_match < 0 && shortopts != NULL) { - cp = strchr(shortopts, argv[optind][optwhere]); - if (cp == NULL) { - /* couldn't find option in shortopts */ - if (opterr) - fprintf(stderr, "%s: invalid option -- `-%c'\n", argv[0], argv[optind][optwhere]); - optwhere++; - if (argv[optind][optwhere] == '\0') { - optind++; - optwhere = 1; - } - return (optopt = '?'); - } - has_arg = ((cp[1] == ':') ? ((cp[2] == ':') ? optional_argument : required_argument) : no_argument); - possible_arg = argv[optind] + optwhere + 1; - optopt = *cp; - } - /* get argument and reset optwhere */ - arg_next = 0; - switch (has_arg) { - case optional_argument: - if (*possible_arg == '=') - possible_arg++; - if (*possible_arg != '\0') { - optarg = possible_arg; - optwhere = 1; - } else - optarg = NULL; - break; - case required_argument: - if (*possible_arg == '=') - possible_arg++; - if (*possible_arg != '\0') { - optarg = possible_arg; - optwhere = 1; - } else if (optind + 1 >= argc) { - if (opterr) { - fprintf(stderr, "%s: argument required for option `", argv[0]); - if (longopt_match >= 0) - fprintf(stderr, "--%s'\n", longopts[longopt_match].name); - else - fprintf(stderr, "-%c'\n", *cp); - } - optind++; - return (optopt = ':'); - } else { - optarg = argv[optind + 1]; - arg_next = 1; - optwhere = 1; - } - break; - case no_argument: - if (longopt_match < 0) { - optwhere++; - if (argv[optind][optwhere] == '\0') - optwhere = 1; - } else - optwhere = 1; - optarg = NULL; - break; - } - - /* do we have to permute or otherwise modify optind? */ - if (ordering == PERMUTE && optwhere == 1 && num_nonopts != 0) { - permute(argv + permute_from, num_nonopts, 1 + arg_next); - optind = (int)(permute_from + 1 + arg_next); - } else if (optwhere == 1) - optind = optind + 1 + arg_next; - - /* finally return */ - if (longopt_match >= 0) { - if (longind != NULL) - *longind = longopt_match; - if (longopts[longopt_match].flag != NULL) { - *(longopts[longopt_match].flag) = longopts[longopt_match].val; - return 0; - } else - return longopts[longopt_match].val; - } else - return optopt; -} - -int getopt(int argc, char **argv, char *optstring) -{ - return getopt_internal(argc, argv, optstring, NULL, NULL, 0); -} - -int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind) -{ - return getopt_internal(argc, argv, (char *)shortopts, (GETOPT_LONG_OPTION_T *)longopts, longind, 0); -} - -int getopt_long_only(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind) -{ - return getopt_internal(argc, argv, (char *)shortopts, (GETOPT_LONG_OPTION_T *)longopts, longind, 1); -} - -/* end of file GETOPT.C */ diff --git a/lib/miniposix/getopt/getopt.h b/lib/miniposix/getopt/getopt.h deleted file mode 100644 index e38f8921..00000000 --- a/lib/miniposix/getopt/getopt.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (C) 1997 Gregory Pietsch - -[These files] are hereby placed in the public domain without restrictions. Just -give the author credit, don't claim you wrote it or prevent anyone else from -using it. -*/ -#pragma once - -#ifndef WIN32PORTS_GETOPT_H -#define WIN32PORTS_GETOPT_H -#ifndef _WIN32 - -#pragma message("this getopt.h implementation is for Windows only!") - -#elif defined __MINGW32__ - -#include <../include/getopt.h> - -#else - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* include files needed by this include file */ - -/* macros defined by this include file */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -/* types defined by this include file */ - -/* GETOPT_LONG_OPTION_T: The type of long option */ -typedef struct GETOPT_LONG_OPTION_T -{ - const char *name; /* the name of the long option */ - int has_arg; /* one of the above macros */ - int *flag; /* determines if getopt_long() returns a - * value for a long option; if it is - * non-NULL, 0 is returned as a function - * value and the value of val is stored in - * the area pointed to by flag. Otherwise, - * val is returned. */ - int val; /* determines the value to return if flag is - * NULL. */ -} GETOPT_LONG_OPTION_T; - -typedef GETOPT_LONG_OPTION_T option; - -/* externally-defined variables */ -extern char *optarg; -extern int optind; -extern int opterr; -extern int optopt; - -/* function prototypes */ -int getopt(int argc, char **argv, char *optstring); -int getopt_long(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind); -int getopt_long_only(int argc, char **argv, const char *shortopts, const GETOPT_LONG_OPTION_T *longopts, int *longind); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _WIN32 */ - -#endif /* WIN32PORTS_GETOPT_H */ diff --git a/lib/miniposix/libgen/libgen.c b/lib/miniposix/libgen/libgen.c deleted file mode 100644 index a0afbc1f..00000000 --- a/lib/miniposix/libgen/libgen.c +++ /dev/null @@ -1,263 +0,0 @@ -/* basename.c - * - * $Id: basename.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $ - * - * Provides an implementation of the "basename" function, conforming - * to SUSv3, with extensions to accommodate Win32 drive designators, - * and suitable for use on native Microsoft(R) Win32 platforms. - * - * Written by Keith Marshall - * - * This is free software. You may redistribute and/or modify it as you - * see fit, without restriction of copyright. - * - * This software is provided "as is", in the hope that it may be useful, - * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of - * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no - * time will the author accept any form of liability for any damages, - * however caused, resulting from the use of this software. - * - */ - -#include -#include -#include -#include -#include -#include - -char *basename(char *path) -{ - static char *retfail = NULL; - size_t len; - /* to handle path names for files in multibyte character locales, - * we need to set up LC_CTYPE to match the host file system locale - */ - char *locale = setlocale(LC_CTYPE, NULL); - - if (locale != NULL) - locale = strdup(locale); - setlocale(LC_CTYPE, ""); - - if (path && *path) { - /* allocate sufficient local storage space, - * in which to create a wide character reference copy of path - */ - len = mbstowcs(NULL, path, 0); - wchar_t *refcopy = malloc(sizeof(wchar_t) * (1 + len)); - /* create the wide character reference copy of path, - * and step over the drive designator, if present ... - */ - wchar_t *refpath = refcopy; - - if ((len = mbstowcs(refpath, path, len)) > 1 && refpath[1] == L':') { - /* FIXME: maybe should confirm *refpath is a valid drive designator */ - refpath += 2; - } - /* ensure that our wide character reference path is NUL terminated */ - refcopy[len] = L'\0'; - /* check again, just to ensure we still have a non-empty path name ... */ - if (*refpath) { - /* and, when we do, process it in the wide character domain ... - * scanning from left to right, to the char after the final dir separator. */ - wchar_t *refname; - - for (refname = refpath; *refpath; ++refpath) { - if (*refpath == L'/' || *refpath == L'\\') { - /* we found a dir separator ... - * step over it, and any others which immediately follow it. */ - while (*refpath == L'/' || *refpath == L'\\') - ++refpath; - /* if we didn't reach the end of the path string ... */ - if (*refpath) - /* then we have a new candidate for the base name. */ - refname = refpath; - /* otherwise ... - * strip off any trailing dir separators which we found. */ - else - while (refpath > refname && (*--refpath == L'/' || *refpath == L'\\')) - *refpath = L'\0'; - } - } - /* in the wide character domain ... - * refname now points at the resolved base name ... */ - if (*refname) { - /* if it's not empty, - * then we transform the full normalised path back into - * the multibyte character domain, and skip over the dirname, - * to return the resolved basename. */ - if ((len = wcstombs(path, refcopy, len)) != (size_t)(-1)) - path[len] = '\0'; - *refname = L'\0'; - if ((len = wcstombs(NULL, refcopy, 0)) != (size_t)(-1)) - path += len; - } else { - /* the basename is empty, so return the default value of "/", - * transforming from wide char to multibyte char domain, and - * returning it in our own buffer. */ - retfail = realloc(retfail, len = 1 + wcstombs(NULL, L"/", 0)); - wcstombs(path = retfail, L"/", len); - } - /* restore the caller's locale, clean up, and return the result */ - setlocale(LC_CTYPE, locale); - free(locale); - free(refcopy); - return path; - } - /* or we had an empty residual path name, after the drive designator, - * in which case we simply fall through ... */ - free(refcopy); - } - /* and, if we get to here ... - * the path name is either NULL, or it decomposes to an empty string; - * in either case, we return the default value of "." in our own buffer, - * reloading it with the correct value, transformed from the wide char - * to the multibyte char domain, just in case the caller trashed it - * after a previous call. - */ - retfail = realloc(retfail, len = 1 + wcstombs(NULL, L".", 0)); - wcstombs(retfail, L".", len); - - /* restore the caller's locale, clean up, and return the result. */ - setlocale(LC_CTYPE, locale); - free(locale); - return retfail; -} - -char *dirname(char *path) -{ - static char *retfail = NULL; - size_t len; - /* to handle path names for files in multibyte character locales, - * we need to set up LC_CTYPE to match the host file system locale. */ - char *locale = setlocale(LC_CTYPE, NULL); - - if (locale != NULL) - locale = strdup(locale); - setlocale(LC_CTYPE, ""); - - if (path && *path) { - /* allocate sufficient local storage space, - * in which to create a wide character reference copy of path. */ - len = mbstowcs(NULL, path, 0); - wchar_t *refcopy = malloc(sizeof(wchar_t) * (1 + len)); - /* create the wide character reference copy of path */ - wchar_t *refpath = refcopy; - - len = mbstowcs(refpath, path, len); - refcopy[len] = L'\0'; - /* SUSv3 identifies a special case, where path is exactly equal to "//"; - * (we will also accept "\\" in the Win32 context, but not "/\" or "\/", - * and neither will we consider paths with an initial drive designator). - * For this special case, SUSv3 allows the implementation to choose to - * return "/" or "//", (or "\" or "\\", since this is Win32); we will - * simply return the path unchanged, (i.e. "//" or "\\"). */ - if (len > 1 && (refpath[0] == L'/' || refpath[0] == L'\\')) { - if (refpath[1] == refpath[0] && refpath[2] == L'\0') { - setlocale(LC_CTYPE, locale); - free(locale); - free(refcopy); - return path; - } - } - /* For all other cases ... - * step over the drive designator, if present ... */ - else if (len > 1 && refpath[1] == L':') { - /* FIXME: maybe should confirm *refpath is a valid drive designator. */ - refpath += 2; - } - /* check again, just to ensure we still have a non-empty path name ... */ - if (*refpath) { - /* reproduce the scanning logic of the "basename" function - * to locate the basename component of the current path string, - * (but also remember where the dirname component starts). */ - wchar_t *refname, *the_basename; - for (refname = the_basename = refpath; *refpath; ++refpath) { - if (*refpath == L'/' || *refpath == L'\\') { - /* we found a dir separator ... - * step over it, and any others which immediately follow it. */ - while (*refpath == L'/' || *refpath == L'\\') - ++refpath; - /* if we didn't reach the end of the path string ... */ - if (*refpath) - /* then we have a new candidate for the base name. */ - the_basename = refpath; - else - /* we struck an early termination of the path string, - * with trailing dir separators following the base name, - * so break out of the for loop, to avoid overrun. */ - break; - } - } - /* now check, - * to confirm that we have distinct dirname and basename components. */ - if (the_basename > refname) { - /* and, when we do ... - * backtrack over all trailing separators on the dirname component, - * (but preserve exactly two initial dirname separators, if identical), - * and add a NUL terminator in their place. */ - do - --the_basename; - while (the_basename > refname && (*the_basename == L'/' || *the_basename == L'\\')); - if (the_basename == refname && (refname[0] == L'/' || refname[0] == L'\\') && refname[1] == refname[0] - && refname[2] != L'/' && refname[2] != L'\\') - ++the_basename; - *++the_basename = L'\0'; - /* if the resultant dirname begins with EXACTLY two dir separators, - * AND both are identical, then we preserve them. */ - refpath = refcopy; - while ((*refpath == L'/' || *refpath == L'\\')) - ++refpath; - if ((refpath - refcopy) > 2 || refcopy[1] != refcopy[0]) - refpath = refcopy; - /* and finally ... - * we remove any residual, redundantly duplicated separators from the dirname, - * reterminate, and return it. */ - refname = refpath; - while (*refpath) { - if ((*refname++ = *refpath) == L'/' || *refpath++ == L'\\') { - while (*refpath == L'/' || *refpath == L'\\') - ++refpath; - } - } - *refname = L'\0'; - /* finally ... - * transform the resolved dirname back into the multibyte char domain, - * restore the caller's locale, and return the resultant dirname. */ - if ((len = wcstombs(path, refcopy, len)) != (size_t)(-1)) - path[len] = '\0'; - } else { - /* either there were no dirname separators in the path name, - * or there was nothing else ... */ - if (*refname == L'/' || *refname == L'\\') { - /* it was all separators, so return one. */ - ++refname; - } else { - /* there were no separators, so return '.'. */ - *refname++ = L'.'; - } - /* add a NUL terminator, in either case, - * then transform to the multibyte char domain, - * using our own buffer. */ - *refname = L'\0'; - retfail = realloc(retfail, len = 1 + wcstombs(NULL, refcopy, 0)); - wcstombs(path = retfail, refcopy, len); - } - /* restore caller's locale, clean up, and return the resolved dirname. */ - setlocale(LC_CTYPE, locale); - free(locale); - free(refcopy); - return path; - } - } - /* path is NULL, or an empty string; default return value is "." ... - * return this in our own buffer, regenerated by wide char transform, - * in case the caller trashed it after a previous call. - */ - retfail = realloc(retfail, len = 1 + wcstombs(NULL, L".", 0)); - wcstombs(retfail, L".", len); - /* restore caller's locale, clean up, and return the default dirname. */ - setlocale(LC_CTYPE, locale); - free(locale); - return retfail; -} diff --git a/lib/miniposix/libgen/libgen.h b/lib/miniposix/libgen/libgen.h deleted file mode 100644 index fabfb679..00000000 --- a/lib/miniposix/libgen/libgen.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef WIN32PORTS_LIBGEN_H -#define WIN32PORTS_LIBGEN_H - -#ifndef _WIN32 - -#pragma message("this libgen.h implementation is for Windows only!") - -#elif defined __MINGW32__ - -#include <../include/libgen.h> - -#else - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -char *basename(char *); -char *dirname(char *); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _WIN32 */ - -#endif /* WIN32PORTS_LIBGEN_H */ diff --git a/lib/miniposix/strings/strings.c b/lib/miniposix/strings/strings.c deleted file mode 100644 index 440a1e3e..00000000 --- a/lib/miniposix/strings/strings.c +++ /dev/null @@ -1,25 +0,0 @@ -/* -MIT License -Copyright (c) 2019 win32ports -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#include - -extern inline void explicit_bzero(void *s, size_t n); -extern inline int ffs(int i); -extern inline int ffsl(long i); -extern inline int ffsll(long long i); diff --git a/lib/miniposix/strings/strings.h b/lib/miniposix/strings/strings.h deleted file mode 100644 index 6c751f4b..00000000 --- a/lib/miniposix/strings/strings.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -MIT License -Copyright (c) 2019 win32ports -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once -#ifndef WIN32PORTS_STRINGS_H -#define WIN32PORTS_STRINGS_H - -#ifndef _WIN32 - -#pragma message("this strings.h implementation is for Windows only!") - -#elif defined __MINGW32__ - -#include <../include/strings.h> - -#else - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#define bcmp(s1, s2, n) memcmp(s1, s2, n) -#define bcopy(s, d, n) memcpy(d, s, n) -#define bzero(s, n) memset(s, 0, n) - -inline void explicit_bzero(void *s, size_t n) -{ - volatile char *vs = (volatile char *)s; - while (n) { - *vs++ = 0; - n--; - } -} - -#define index(s, c) strchr(s, c) -#define rindex(s, c) strrchr(s, c) - -inline int ffs(int i) -{ - int bit; - - if (0 == i) - return 0; - - for (bit = 1; !(i & 1); ++bit) - i >>= 1; - return bit; -} - -inline int ffsl(long i) -{ - int bit; - - if (0 == i) - return 0; - - for (bit = 1; !(i & 1); ++bit) - i >>= 1; - return bit; -} - -inline int ffsll(long long i) -{ - int bit; - - if (0 == i) - return 0; - - for (bit = 1; !(i & 1); ++bit) - i >>= 1; - return bit; -} - -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#define strcasecmp_l(s1, s2, loc) _stricmp_l(s1, s2, loc) -#define strncasecmp_l(s1, s2, n, loc) _strnicmp_l(s1, s2, n, loc) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _WIN32 */ - -#endif /* WIN32PORTS_STRINGS_H */ diff --git a/lib/miniposix/unistd/unistd.h b/lib/miniposix/unistd/unistd.h deleted file mode 100644 index a7a088c4..00000000 --- a/lib/miniposix/unistd/unistd.h +++ /dev/null @@ -1,265 +0,0 @@ -/* -MIT License -Copyright (c) 2019 win32ports -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#ifndef WIN32PORTS_UNISTD_H -#define WIN32PORTS_UNISTD_H - -#ifndef _WIN32 - -#pragma message("this unistd.h implementation is for Windows only!") - -#else -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include - -#ifndef _INC_IO -#include /* _access() */ -#endif /* _INC_IO */ - -#ifndef _INC_DIRECT -#include /* _chdir() */ -#endif /* _INC_DIRECT */ - -#ifndef _INC_PROCESS -#include /* _execl() */ -#endif /* _INC_PROCESS */ - -#include /* */ - -#include - -#ifndef R_OK -#define R_OK 04 -#endif /* R_OK */ - -#ifndef W_OK -#define W_OK 02 -#endif /* W_OK */ - -#ifndef X_OK -#define X_OK R_OK -#endif /* X_OK */ - -#ifndef F_OK -#define F_OK 00 -#endif /* F_OK */ - -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif /* STDIN_FILENO */ - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif /* STDOUT_FILENO */ - -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif /* STDERR_FILENO */ - -/* permission bits below must be defined in sys/stat.h, but MSVC lacks them */ - -#ifndef S_IRWXU -#define S_IRWXU 0700 -#endif /* S_IRWXU */ - -#ifndef S_IRUSR -#define S_IRUSR 0400 -#endif /* S_IRUSR */ - -#ifndef S_IWUSR -#define S_IWUSR 0200 -#endif /* S_IWUSR */ - -#ifndef S_IXUSR -#define S_IXUSR 0100 -#endif /* S_IXUSR */ - -#ifndef S_IRWXG -#define S_IRWXG 070 -#endif /* S_IRWXG */ - -#ifndef S_IRGRP -#define S_IRGRP 040 -#endif /* S_IRGRP */ - -#ifndef S_IWGRP -#define S_IWGRP 020 -#endif /* S_IWGRP */ - -#ifndef S_IXGRP -#define S_IXGRP 010 -#endif /* S_IXGRP */ - -#ifndef S_IRWXO -#define S_IRWXO 07 -#endif /* S_IRWXO */ - -#ifndef S_IROTH -#define S_IROTH 04 -#endif /* S_IROTH */ - -#ifndef S_IWOTH -#define S_IWOTH 02 -#endif /* S_IWOTH */ - -#ifndef S_IXOTH -#define S_IXOTH 01 -#endif /* S_IXOTH */ - -#ifndef S_ISUID -#define S_ISUID 04000 -#endif /* S_ISUID */ - -#ifndef S_ISGID -#define S_ISGID 02000 -#endif /* S_ISGID */ - -#ifndef S_ISVTX -#define S_ISVTX 01000 -#endif /* S_ISVTX */ - -#ifndef S_IRWXUGO -#define S_IRWXUGO 0777 -#endif /* S_IRWXUGO */ - -#ifndef S_IALLUGO -#define S_IALLUGO 0777 -#endif /* S_IALLUGO */ - -#ifndef S_IRUGO -#define S_IRUGO 0444 -#endif /* S_IRUGO */ - -#ifndef S_IWUGO -#define S_IWUGO 0222 -#endif /* S_IWUGO */ - -#ifndef S_IXUGO -#define S_IXUGO 0111 -#endif /* S_IXUGO */ - -#ifndef _S_IFMT -#define _S_IFMT 0xF000 -#endif /* _S_IFMT */ - -#ifndef _S_IFIFO -#define _S_IFIFO 0x1000 -#endif /* _S_IFIFO */ - -#ifndef _S_IFCHR -#define _S_IFCHR 0x2000 -#endif /* _S_IFCHR */ - -#ifndef _S_IFDIR -#define _S_IFDIR 0x4000 -#endif /* _S_IFDIR */ - -#ifndef _S_IFBLK -#define _S_IFBLK 0x6000 -#endif /* _S_IFBLK */ - -#ifndef _S_IFREG -#define _S_IFREG 0x8000 -#endif /* _S_IFREG */ - -#ifndef _S_IFLNK -#define _S_IFLNK 0xA000 -#endif /* _S_IFLNK */ - -#ifndef _S_IFSOCK -#define _S_IFSOCK 0xC000 -#endif /* _S_IFSOCK */ - -#ifndef S_IFMT -#define S_IFMT _S_IFMT -#endif /* S_IFMT */ - -#ifndef S_IFIFO -#define S_IFIFO _S_IFIFO -#endif /* S_IFIFO */ - -#ifndef S_IFCHR -#define S_IFCHR _S_IFCHR -#endif /* S_IFCHR */ - -#ifndef S_IFDIR -#define S_IFDIR _S_IFDIR -#endif /* S_IFDIR */ - -#ifndef S_IFBLK -#define S_IFBLK _S_IFBLK -#endif /* S_IFBLK */ - -#ifndef S_IFREG -#define S_IFREG _S_IFREG -#endif /* S_IFREG */ - -#ifndef S_IFLNK -#define S_IFLNK _S_IFLNK -#endif /* S_IFLNK */ - -#ifndef S_IFSOCK -#define S_IFSOCK _S_IFSOCK -#endif /* S_IFSOCK */ - -#ifndef S_ISTYPE -#define S_ISTYPE(mode, mask) (((mode)&S_IFMT) == (mask)) -#endif /* S_ISTYPE */ - -#ifndef S_ISFIFO -#define S_ISFIFO(mode) S_ISTYPE(mode, S_IFIFO) -#endif /* S_ISFIFO */ - -#ifndef S_ISCHR -#define S_ISCHR(mode) S_ISTYPE(mode, S_IFCHR) -#endif /* S_ISCHR */ - -#ifndef S_ISDIR -#define S_ISDIR(mode) S_ISTYPE(mode, S_IFDIR) -#endif /* S_ISDIR */ - -#ifndef S_ISBLK -#define S_ISBLK(mode) S_ISTYPE(mode, S_IFBLK) -#endif /* S_ISBLK */ - -#ifndef S_ISREG -#define S_ISREG(mode) S_ISTYPE(mode, S_IFREG) -#endif /* S_ISREG */ - -#ifndef S_ISLNK -#define S_ISLNK(mode) S_ISTYPE(mode, S_IFLNK) -#endif /* S_ISLNK */ - -#ifndef S_ISSOCK -#define S_ISSOCK(mode) S_ISTYPE(mode, S_IFSOCK) -#endif /* S_ISSOCK */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _WIN32 */ - -#endif /* WIN32PORTS_UNISTD_H */ diff --git a/src/BRSRC13/CMakeLists.txt b/src/BRSRC13/CMakeLists.txt index 9ab1423e..2375948b 100644 --- a/src/BRSRC13/CMakeLists.txt +++ b/src/BRSRC13/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(brender include ) -target_link_libraries(brender PRIVATE harness miniposix) +target_link_libraries(brender PRIVATE harness) if(NOT MSVC) target_compile_options(brender PRIVATE diff --git a/src/BRSRC13/CORE/FW/brlists.c b/src/BRSRC13/CORE/FW/brlists.c index ffae26bf..8c2c240c 100644 --- a/src/BRSRC13/CORE/FW/brlists.c +++ b/src/BRSRC13/CORE/FW/brlists.c @@ -2,7 +2,7 @@ #include "harness/trace.h" #include #include -#include + // IDA: void __cdecl BrNewList(br_list *list) void BrNewList(br_list* list) { diff --git a/src/BRSRC13/CORE/FW/datafile.c b/src/BRSRC13/CORE/FW/datafile.c index 35b12f7e..17bf9ef0 100644 --- a/src/BRSRC13/CORE/FW/datafile.c +++ b/src/BRSRC13/CORE/FW/datafile.c @@ -11,38 +11,38 @@ br_file_primitives _BrFilePrimsNull = { "NULL", - (int(*)(br_datafile*,br_uint_32))&BrNullOther, - (int(*)(br_datafile*, br_uint_32, br_uint_32))&BrNullOther, - (int(*)(br_datafile*, br_uint_32*))&BrNullOther, - (void(*)(br_datafile*, br_uint_32))&BrNullOther, - (br_uint_32(*)(br_datafile*))&BrNullOther, - (int(*)(br_datafile*))&BrNullOther, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, - (int(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, - (int(*)(br_datafile*, void*, int, int, int, int))&BrNullOther, - (void*(*)(br_datafile*, void*, int*, int, int))&BrNullOther, - (int(*)(br_datafile*, void*, int, int, int, int))&BrNullOther, - (int(*)(br_datafile*, char*))&BrNullOther, - (char*(*)(br_datafile*, char*))&BrNullOther, - (int(*)(br_datafile*, char*))&BrNullOther, + (int (*)(br_datafile*, br_uint_32)) & BrNullOther, + (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther, + (int (*)(br_datafile*, br_uint_32*)) & BrNullOther, + (void (*)(br_datafile*, br_uint_32)) & BrNullOther, + (br_uint_32(*)(br_datafile*)) & BrNullOther, + (int (*)(br_datafile*)) & BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, + (int (*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, + (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther, + (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther, + (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther, + (int (*)(br_datafile*, char*)) & BrNullOther, + (char* (*)(br_datafile*, char*)) & BrNullOther, + (int (*)(br_datafile*, char*)) & BrNullOther, }; br_file_primitives _BrFilePrimsReadBinary = { "Read Binary", &DfSkipBinary, - (int(*)(br_datafile*, br_uint_32, br_uint_32))&BrNullOther, + (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther, &DfChunkReadBinary, - (void(*)(br_datafile*, br_uint_32))&BrNullOther, + (void (*)(br_datafile*, br_uint_32)) & BrNullOther, &DfCountReadBinary, &DfCountSizeBinary, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, &DfStructReadBinary, &DfStructSizeBinary, - (int(*)(br_datafile*, void*, int, int, int, int))&BrNullOther, + (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther, &DfBlockReadBinary, &DfBlockSizeBinary, - (int(*)(br_datafile*, char*))&BrNullOther, + (int (*)(br_datafile*, char*)) & BrNullOther, &DfNameReadBinary, &DfNameSizeBinary, }; @@ -51,36 +51,36 @@ br_file_primitives _BrFilePrimsWriteBinary = { "Write Binary", &DfSkipBinary, &DfChunkWriteBinary, - (int(*)(br_datafile*, br_uint_32*))&BrNullOther, + (int (*)(br_datafile*, br_uint_32*)) & BrNullOther, &DfCountWriteBinary, - (br_uint_32(*)(br_datafile*))&BrNullOther, + (br_uint_32(*)(br_datafile*)) & BrNullOther, &DfCountSizeBinary, &DfStructWriteBinary, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, &DfStructSizeBinary, &DfBlockWriteBinary, - (void*(*)(br_datafile*, void*, int*, int, int))&BrNullOther, + (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther, &DfBlockSizeBinary, &DfNameWriteBinary, - (char*(*)(br_datafile*, char*))&BrNullOther, + (char* (*)(br_datafile*, char*)) & BrNullOther, &DfNameSizeBinary, }; br_file_primitives _BrFilePrimsReadText = { "Read Text", &DfSkipText, - (int(*)(br_datafile*, br_uint_32, br_uint_32))&BrNullOther, + (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther, &DfChunkReadText, - (void(*)(br_datafile*, br_uint_32))&BrNullOther, + (void (*)(br_datafile*, br_uint_32)) & BrNullOther, &DfCountReadText, &DfCountSizeText, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, &DfStructReadText, &DfStructSizeText, - (int(*)(br_datafile*, void*, int, int, int, int))&BrNullOther, + (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther, &DfBlockReadText, &DfBlockSizeText, - (int(*)(br_datafile*, char*))&BrNullOther, + (int (*)(br_datafile*, char*)) & BrNullOther, &DfNameReadText, &DfNameSizeText, }; @@ -89,18 +89,18 @@ br_file_primitives _BrFilePrimsWriteText = { "Write Text", &DfSkipText, &DfChunkWriteText, - (int(*)(br_datafile*, br_uint_32*))&BrNullOther, + (int (*)(br_datafile*, br_uint_32*)) & BrNullOther, &DfCountWriteText, - (br_uint_32(*)(br_datafile*))&BrNullOther, + (br_uint_32(*)(br_datafile*)) & BrNullOther, &DfCountSizeText, &DfStructWriteText, - (br_uint_32(*)(br_datafile*, br_file_struct*, void*))&BrNullOther, + (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther, &DfStructSizeText, &DfBlockWriteText, - (void*(*)(br_datafile*, void*, int*, int, int))&BrNullOther, + (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther, &DfBlockSizeText, &DfNameWriteText, - (char*(*)(br_datafile*, char*))&BrNullOther, + (char* (*)(br_datafile*, char*)) & BrNullOther, &DfNameSizeText, }; @@ -289,7 +289,8 @@ int TextReadLine(br_datafile* df, char** ident, char** data) { } for (; (*cp == ' ') || (*cp == '\t'); cp++) { } - if (*cp != '\0') break; + if (*cp != '\0') + break; } *ident = cp; while ((*cp != ' ') && (*cp != '\t') && (*cp != '\0')) { @@ -320,7 +321,7 @@ br_uint_16 scalarTypeConvert(br_datafile* df, br_uint_16 t) { LOG_TRACE9("(%p, %d)", df, t); if (df->scalar_type == BRT_FIXED) { - switch(t) { + switch (t) { case DF_TYPE_BR_SCALAR: return DF_TYPE_BR_FIXED; case DF_TYPE_BR_FRACTION: @@ -418,8 +419,8 @@ br_uint_32 DfStructWriteBinary(br_datafile* df, br_file_struct* str, void* base) DfStructWriteBinary(df, sm->extra, mp); break; case DF_TYPE_ASCIZ: - if (*(char **)mp != NULL) { - BrFileWrite(*(char **)mp, 1, BrStrLen(*(char**)mp), df->h); + if (*(char**)mp != NULL) { + BrFileWrite(*(char**)mp, 1, BrStrLen(*(char**)mp), df->h); } BrFilePutChar('\0', df->h); break; @@ -822,14 +823,14 @@ br_uint_32 StructWriteTextSub(br_datafile* df, br_file_struct* str, void* base, StructWriteTextSub(df, sm->extra, mp, indent + 2); break; case DF_TYPE_ASCIZ: - if (*(char **)mp == NULL) { + if (*(char**)mp == NULL) { w = BrFilePrintf(df->h, "NULL"); } else { - w = BrFilePrintf(df->h, "\"%s\"", *(char **)mp); + w = BrFilePrintf(df->h, "\"%s\"", *(char**)mp); } break; case DF_TYPE_BR_COLOUR: - w = BrFilePrintf(df->h, "%d,%d,%d", (br_uint_8)((*(br_uint_32 *)mp) >> 16), (br_uint_8)((*(br_uint_32 *)mp) >> 8), (br_uint_8)((*(br_uint_32 *)mp))); + w = BrFilePrintf(df->h, "%d,%d,%d", (br_uint_8)((*(br_uint_32*)mp) >> 16), (br_uint_8)((*(br_uint_32*)mp) >> 8), (br_uint_8)((*(br_uint_32*)mp))); break; case DF_TYPE_BR_FRACTION_X: w = BrFilePrintf(df->h, "%g", (double)BrFixedFractionToFloat(*(br_fraction_x*)mp)); @@ -1499,7 +1500,7 @@ int DfChunksInterpret(br_datafile* df, br_chunks_table* table) { while (1) { id = df->prims->chunk_read(df, &length); - //LOG_DEBUG("chunk id=%d, len=%d", id, length); + // LOG_DEBUG("chunk id=%d, len=%d", id, length); if (id == (br_uint_32)-1) { break; } @@ -1563,7 +1564,6 @@ br_datafile* DfOpen(char* name, int write, br_token scalar_type) { h = BrFileOpenRead(name, 8u, DfFileIdentify, &mode); } if (h == NULL) { - LOG_WARN("returning NULL"); return NULL; } df = BrResAllocate(fw.res, sizeof(br_datafile), BR_MEMORY_DATAFILE); diff --git a/src/DETHRACE/CMakeLists.txt b/src/DETHRACE/CMakeLists.txt index 83e1cbc7..47209999 100644 --- a/src/DETHRACE/CMakeLists.txt +++ b/src/DETHRACE/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(dethrace_obj pd ) -target_link_libraries(dethrace_obj PUBLIC miniposix SDL2::SDL2 smacker harness brender s3 cglm) +target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smacker harness brender s3 cglm) if (CMAKE_C_COMPILER_ID MATCHES "Clang") target_compile_options(dethrace_obj PRIVATE @@ -154,8 +154,6 @@ target_sources(dethrace_obj PRIVATE pd/net.h pc-dos/dossys.c pd/sys.h - watcom_functions.c - watcom_functions.h ) # Create our main game binary. diff --git a/src/DETHRACE/common/cutscene.c b/src/DETHRACE/common/cutscene.c index 79103d10..b06df457 100644 --- a/src/DETHRACE/common/cutscene.c +++ b/src/DETHRACE/common/cutscene.c @@ -4,6 +4,7 @@ #include "globvrpb.h" #include "graphics.h" #include "harness/config.h" +#include "harness/os.h" #include "harness/trace.h" #include "input.h" #include "loading.h" @@ -13,7 +14,6 @@ #include "utility.h" #include #include -#include tS32 gLast_demo_end_anim; @@ -38,7 +38,7 @@ void PlaySmackerFile(char* pSmack_name) { tPath_name the_path; br_colour* br_colours_ptr; tU8* smack_colours_ptr; - //Smack* smk; + // Smack* smk; int i; int j; int len; @@ -83,10 +83,7 @@ void PlaySmackerFile(char* pSmack_name) { smk_info_video(s, &w, &h, NULL); double fps = 1000000.0 / usf; int delay_ms = (1 / fps) * 1000; -#ifndef _WIN32 - ts.tv_sec = delay_ms / 1000; - ts.tv_nsec = (delay_ms % 1000) * 1000000; -#endif + smk_enable_video(s, 1); smk_first(s); @@ -112,13 +109,8 @@ void PlaySmackerFile(char* pSmack_name) { if (AnyKeyDown() || EitherMouseButtonDown()) { break; } - // wait until its time for the next frame -#ifndef _WIN32 - nanosleep(&ts, &ts); -#else - Sleep(delay_ms); -#endif + OS_Sleep(delay_ms); } while (smk_next(s) == SMK_MORE); smk_close(s); @@ -138,7 +130,7 @@ void DoOpeningAnimation() { LOG_TRACE("()"); PlaySmackerFile("LOGO.SMK"); PlaySmackerFile(harness_game_info.defines.INTRO_SMK_FILE); - return WaitForNoKeys(); + WaitForNoKeys(); } // IDA: void __cdecl DoNewGameAnimation() diff --git a/src/DETHRACE/common/drmem.c b/src/DETHRACE/common/drmem.c index 299c03a5..13a06ed8 100644 --- a/src/DETHRACE/common/drmem.c +++ b/src/DETHRACE/common/drmem.c @@ -282,8 +282,6 @@ void MAMSInitMem() { FILE* f; tPath_name the_path; LOG_TRACE("()"); - - LOG_WARN("nop in Windows (doing something for DOS?)"); } // IDA: void __usercall PrintMemoryDump(int pFlags@, char *pTitle@) diff --git a/src/DETHRACE/common/errors.c b/src/DETHRACE/common/errors.c index e32612cd..88fbed3e 100644 --- a/src/DETHRACE/common/errors.c +++ b/src/DETHRACE/common/errors.c @@ -5,6 +5,7 @@ #include #include +#include "globvars.h" #include "graphics.h" #include "harness/trace.h" #include "network.h" @@ -148,27 +149,26 @@ void FatalError(int pStr_index, ...) { va_start(ap, pStr_index); - int read_timer = PDGetTotalTime(); - gError_code = 0x20000000 + read_timer; - strcpy(the_str, gError_messages[pStr_index - 1]); + gError_code = 0x20000000 + PDGetTotalTime(); + strcpy(the_str, gError_messages[pStr_index]); sub_pt = temp_str; - for (i = 0; i < strlen(the_str); i++) { - if (the_str[i] == '%') { - sub_str = va_arg(ap, char*); - StripCR(sub_str); - strcpy(sub_pt, sub_str); - sub_pt += strlen(sub_str); - } else { - *sub_pt = the_str[i]; - sub_pt++; + while (1) { + + sub_pt = strchr(the_str, '%'); + if (!sub_pt) { + break; } + sub_str = va_arg(ap, char*); + StripCR(sub_str); + strcpy(temp_str, sub_pt + 1); + strcpy(sub_pt, sub_str); + strcat(the_str, temp_str); } - *sub_pt = 0; va_end(ap); dr_dprintf(the_str); FadePaletteUp(); - PDFatalError(temp_str); + PDFatalError(the_str); } // IDA: void __cdecl NonFatalError(int pStr_index, ...) @@ -205,22 +205,40 @@ void NonFatalError(int pStr_index, ...) { // IDA: void __cdecl CloseDiagnostics() void CloseDiagnostics() { LOG_TRACE("()"); + + fclose(gDiagnostic_file); } // IDA: void __cdecl OpenDiagnostics() void OpenDiagnostics() { LOG_TRACE("()"); + + gDiagnostic_file = fopen("DIAGNOST.TXT", "w"); + + fputs("DIAGNOSTIC OUTPUT\n", gDiagnostic_file); + // todo: generate a real date + fprintf(gDiagnostic_file, "Date / time : %s\n\n\n", "Mon Mar 24 16 : 32 : 33 1997"); } // Renamed from dprintf to avoid collisions to stdio +// This function is stripped from the retail binary, we've guessed at the implementation void dr_dprintf(char* fmt_string, ...) { + static tU32 first_time = 0; va_list args; + tU32 the_time; + + if (first_time == 0) { + first_time = GetTotalTime(); + } + the_time = GetTotalTime() - first_time; + + fprintf(gDiagnostic_file, "%7d.%02d: ", the_time / 1000, the_time % 100); - printf("dprintf: "); va_start(args, fmt_string); - vprintf(fmt_string, args); + vfprintf(gDiagnostic_file, fmt_string, args); va_end(args); - printf("\n"); + + fputs("\n", gDiagnostic_file); } // IDA: int __usercall DoErrorInterface@(int pMisc_text_index@) diff --git a/src/DETHRACE/common/flicplay.c b/src/DETHRACE/common/flicplay.c index d259b678..3b9fcf02 100644 --- a/src/DETHRACE/common/flicplay.c +++ b/src/DETHRACE/common/flicplay.c @@ -12,7 +12,6 @@ #include "sound.h" #include "utility.h" #include -#include int gPalette_allocate_count; int gPalette_fuck_prevention; @@ -694,7 +693,7 @@ int StartFlic(char* pFile_name, int pIndex, tFlic_descriptor_ptr pFlic_info, tU3 } else { pFlic_info->f = NULL; pFlic_info->data = (char*)pData_ptr; - //TOOD: remove this - we added this line because of the padding hack in PlayNextFlicFrame2 + // TOOD: remove this - we added this line because of the padding hack in PlayNextFlicFrame2 pFlic_info->data_start = (char*)pData_ptr; } pFlic_info->bytes_remaining = MemReadU32(&pFlic_info->data); @@ -746,7 +745,7 @@ int StartFlic(char* pFile_name, int pIndex, tFlic_descriptor_ptr pFlic_info, tU3 if (pDest_pixelmap) { pFlic_info->first_pixel = (tU8*)pDest_pixelmap->pixels + pDest_pixelmap->row_bytes * pFlic_info->y_offset + pFlic_info->x_offset; } - //LOG_DEBUG("first pixel %p %p", pFlic_info->first_pixel, pDest_pixelmap->pixels); + // LOG_DEBUG("first pixel %p %p", pFlic_info->first_pixel, pDest_pixelmap->pixels); pFlic_info->the_pixelmap = pDest_pixelmap; return 0; } @@ -809,7 +808,7 @@ void DoColourMap(tFlic_descriptor_ptr pFlic_info, tU32 chunk_length) { red = MemReadU8(&pFlic_info->data); blue = MemReadU8(&pFlic_info->data); green = MemReadU8(&pFlic_info->data); - //argb + // argb palette_pixels[0] = green * 4; palette_pixels[1] = blue * 4; palette_pixels[2] = red * 4; @@ -887,13 +886,13 @@ void DoColour256(tFlic_descriptor* pFlic_info, tU32 chunk_length) { red = MemReadU8(&pFlic_info->data); blue = MemReadU8(&pFlic_info->data); green = MemReadU8(&pFlic_info->data); - //argb + // argb palette_pixels[0] = green; palette_pixels[1] = blue; palette_pixels[2] = red; palette_pixels[3] = 0; palette_pixels += 4; - //LOG_DEBUG("color %d", current_colour); + // LOG_DEBUG("color %d", current_colour); } if (!gPalette_fuck_prevention) { DRSetPaletteEntries(gPalette, current_colour, change_count); @@ -1172,7 +1171,7 @@ int PlayNextFlicFrame2(tFlic_descriptor* pFlic_info, int pPanel_flic) { int data_knocked_off; int read_amount; - //LOG_DEBUG("%d (%p), frames left: %d offset: %d", pFlic_info->the_index, pFlic_info, pFlic_info->frames_left, (pFlic_info->data - pFlic_info->data_start) + 4); + // LOG_DEBUG("%d (%p), frames left: %d offset: %d", pFlic_info->the_index, pFlic_info, pFlic_info->frames_left, (pFlic_info->data - pFlic_info->data_start) + 4); PossibleService(); frame_length = MemReadU32(&pFlic_info->data); magic_bytes = MemReadU16(&pFlic_info->data); @@ -1229,7 +1228,7 @@ int PlayNextFlicFrame2(tFlic_descriptor* pFlic_info, int pPanel_flic) { MemSkipBytes(&pFlic_info->data, chunk_length - 6); break; } - //TODO: something like // p &= 0xfffffffffffffffe; + // TODO: something like // p &= 0xfffffffffffffffe; int a = (pFlic_info->data - pFlic_info->data_start); if (a % 2 == 1) { pFlic_info->data++; diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index d9038727..7bd76cff 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -32,7 +32,6 @@ #include "utility.h" #include "world.h" #include -#include #include @@ -2389,7 +2388,7 @@ void DropInImageFromTop(br_pixelmap* pImage, int pLeft, int pTop, int pTop_clip, tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - + start_time = PDGetTotalTime(); drop_distance = pImage->height - pTop_clip + pTop; while (1) { @@ -2413,7 +2412,7 @@ void DropOutImageThruBottom(br_pixelmap* pImage, int pLeft, int pTop, int pTop_c tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - + start_time = PDGetTotalTime(); drop_distance = pBottom_clip - pTop; while (1) { @@ -2437,7 +2436,7 @@ void DropInImageFromBottom(br_pixelmap* pImage, int pLeft, int pTop, int pTop_cl tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - + start_time = PDGetTotalTime(); drop_distance = pBottom_clip - pTop; while (1) { @@ -2461,7 +2460,7 @@ void DropOutImageThruTop(br_pixelmap* pImage, int pLeft, int pTop, int pTop_clip tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - + start_time = PDGetTotalTime(); drop_distance = pImage->height - pTop_clip + pTop; while (1) { diff --git a/src/DETHRACE/common/loading.c b/src/DETHRACE/common/loading.c index 784ec14a..7180666f 100644 --- a/src/DETHRACE/common/loading.c +++ b/src/DETHRACE/common/loading.c @@ -3195,9 +3195,6 @@ FILE* DRfopen(char* pFilename, char* pMode) { PDFatalError(msg); } } - if (result == NULL) { - LOG_WARN("failed for %d", errno); - } return result; } diff --git a/src/DETHRACE/common/mainloop.c b/src/DETHRACE/common/mainloop.c index dae0f1a2..33fef770 100644 --- a/src/DETHRACE/common/mainloop.c +++ b/src/DETHRACE/common/mainloop.c @@ -638,8 +638,6 @@ tRace_result MainGameLoop() { gAbandon_game = 0; } - Harness_Hook_MainGameLoop(); - } while (gProgram_state.prog_status == eProg_game_ongoing && !MungeRaceFinished() && !gAbandon_game diff --git a/src/DETHRACE/common/utility.c b/src/DETHRACE/common/utility.c index 49750b9e..1309c3f7 100644 --- a/src/DETHRACE/common/utility.c +++ b/src/DETHRACE/common/utility.c @@ -21,7 +21,6 @@ #include #include #include -#include // Added >> #define MIN_SERVICE_INTERVAL 200 @@ -1312,7 +1311,7 @@ void EncodeFile(char* pThe_path) { fclose(d); PDFileUnlock(pThe_path); - unlink(pThe_path); + remove(pThe_path); rename(new_file, pThe_path); } diff --git a/src/DETHRACE/main.c b/src/DETHRACE/main.c index 98961bfd..836963e9 100644 --- a/src/DETHRACE/main.c +++ b/src/DETHRACE/main.c @@ -1,7 +1,6 @@ #include "harness/hooks.h" #include "pd/sys.h" #include -#include extern int original_main(int pArgc, char* pArgv[]); @@ -10,15 +9,15 @@ int main(int argc, char* argv[]) { /* Attach to the console that started us if any */ if (AttachConsole(ATTACH_PARENT_PROCESS)) { /* We attached successfully, lets redirect IO to the consoles handles if not already redirected */ - if (_fileno(stdout) == -2 || _get_osfhandle(fileno(stdout)) == -2) { + if (_fileno(stdout) == -2 || _get_osfhandle(_fileno(stdout)) == -2) { freopen("CONOUT$", "w", stdout); } - if (_fileno(stderr) == -2 || _get_osfhandle(fileno(stderr)) == -2) { + if (_fileno(stderr) == -2 || _get_osfhandle(_fileno(stderr)) == -2) { freopen("CONOUT$", "w", stderr); } - if (_fileno(stdin) == -2 || _get_osfhandle(fileno(stdin)) == -2) { + if (_fileno(stdin) == -2 || _get_osfhandle(_fileno(stdin)) == -2) { freopen("CONIN$", "r", stdin); } } diff --git a/src/DETHRACE/pc-dos/dosnet.c b/src/DETHRACE/pc-dos/dosnet.c index 6414ed98..806453ee 100644 --- a/src/DETHRACE/pc-dos/dosnet.c +++ b/src/DETHRACE/pc-dos/dosnet.c @@ -352,6 +352,7 @@ void PDNetObtainSystemUserName(char* pName, int pMax_length) { int size; char buffer[16]; BOOL result; + #endif dr_dprintf("PDNetObtainSystemUserName()\n"); diff --git a/src/DETHRACE/pc-dos/dossys.c b/src/DETHRACE/pc-dos/dossys.c index 6479386b..a1e0a375 100644 --- a/src/DETHRACE/pc-dos/dossys.c +++ b/src/DETHRACE/pc-dos/dossys.c @@ -6,6 +6,7 @@ #include "graphics.h" #include "harness/config.h" #include "harness/hooks.h" +#include "harness/os.h" #include "harness/trace.h" #include "input.h" #include "loadsave.h" @@ -13,43 +14,12 @@ #include "pd/sys.h" #include "sound.h" #include "utility.h" -#include "watcom_functions.h" -#include #include #include #include #include -#include #include #include -#include - -#ifdef _WIN32 -#define NS_PER_SEC (1000ULL * 1000ULL * 1000ULL) -#define CLOCK_MONOTONIC 1 - -int clock_gettime(int dummy, struct timespec* tv) { - static LARGE_INTEGER ticksPerSec; - LARGE_INTEGER ticks; - double seconds; - - if (!ticksPerSec.QuadPart) { - QueryPerformanceFrequency(&ticksPerSec); - if (!ticksPerSec.QuadPart) { - errno = ENOTSUP; - return -1; - } - } - - QueryPerformanceCounter(&ticks); - - seconds = (double)ticks.QuadPart / (double)ticksPerSec.QuadPart; - tv->tv_sec = (time_t)seconds; - tv->tv_nsec = (long)((ULONGLONG)(seconds * NS_PER_SEC) % NS_PER_SEC); - - return 0; -} -#endif #ifdef __DOS__ #define GFX_INIT_STRING_32X20X8 "MCGA,W:320,H:200,B:8" @@ -230,9 +200,9 @@ void KeyBegin() { // *(_WORD *)gScan_code[9] = 56; // *(_WORD *)gScan_code[10] = 29; - //gPrev_keyboard_handler = (void (__fastcall *)())dos_getvect(9); - //unk_142E6C = v2; - //dos_setvect(9, KeyboardHandler); + // gPrev_keyboard_handler = (void (__fastcall *)())dos_getvect(9); + // unk_142E6C = v2; + // dos_setvect(9, KeyboardHandler); } // IDA: void __cdecl KeyEnd() @@ -297,8 +267,6 @@ void PDFatalError(char* pThe_str) { // wait for keypress - Harness_Debug_PrintStack(); - if (!_unittest_do_not_exit) { exit(1); } @@ -318,9 +286,9 @@ void PDInitialiseSystem() { KeyBegin(); - //v4 = DOSMouseBegin(); + // v4 = DOSMouseBegin(); gJoystick_deadzone = 8000; - //gUpper_loop_limit = sub_A1940(v4, v5, v3, v6) / 2; + // gUpper_loop_limit = sub_A1940(v4, v5, v3, v6) / 2; // Demo does not ship with KEYBOARD.COK file if (harness_game_info.mode != eGame_carmageddon_demo) { @@ -520,20 +488,12 @@ void PDBuildAppPath(char* pThe_path) { void PDForEveryFile(char* pThe_path, void (*pAction_routine)(char*)) { char find_path[256]; char found_path[256]; - //find_t the_find_buffer; - DIR* d; - struct dirent* entry; - d = opendir(pThe_path); - if (d) { - while ((entry = readdir(d)) != NULL) { - // only files, and only files that don't start with '.' - if (entry->d_type == DT_REG && entry->d_name[0] != '.') { - PathCat(found_path, pThe_path, entry->d_name); - pAction_routine(found_path); - } - } - closedir(d); + char* found = OS_GetFirstFileInDirectory(pThe_path); + while (found != NULL) { + PathCat(found_path, pThe_path, found); + pAction_routine(found_path); + found = OS_GetNextFileInDirectory(); } } @@ -592,9 +552,7 @@ void PDGetMousePosition(int* pX_coord, int* pY_coord) { // IDA: int __cdecl PDGetTotalTime() int PDGetTotalTime() { - struct timespec spec; - clock_gettime(CLOCK_MONOTONIC, &spec); - return spec.tv_sec * 1000 + spec.tv_nsec / 1000000; + return OS_GetTime(); } // IDA: int __usercall PDServiceSystem@(tU32 pTime_since_last_call@) @@ -637,9 +595,10 @@ void PDDisposeActionReplayBuffer(char* pBuffer) { // IDA: void __usercall Usage(char *pProgpath@) void Usage(char* pProgpath) { - char basename[9]; + // char basename[9]; + char basename[256]; // fix: changed from 9 to avoid overflow on longer filenames - splitpath(pProgpath, NULL, NULL, basename, NULL); + OS_Basename(pProgpath, basename); fprintf(stderr, "Usage: %s [%s] [%s YonFactor] [%s CarSimplificationLevel] [%s SoundDetailLevel] [%s] [%s] [%s] [%s] [%s] [%s]\nWhere YonFactor is between 0 and 1,\nCarSimplificationLevel is a whole number between 0 and %d,\nand SoundDetailLevel is a whole number.\n", diff --git a/src/DETHRACE/watcom_functions.c b/src/DETHRACE/watcom_functions.c deleted file mode 100644 index b8f75887..00000000 --- a/src/DETHRACE/watcom_functions.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "watcom_functions.h" - -#include -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#else -#include -#endif - -void splitpath(char* path, char* drive, char* dir, char* fname, char* ext) { -#if defined(_WIN32) || defined(_WIN64) - _splitpath(path, drive, dir, fname, ext); -#else - // shortcut - we only ever call this method asking for 'fname' - // 9 is hardcoded to match `basename` defined in `Usage` - strncpy(fname, basename(path), 9); - -#endif -} diff --git a/src/DETHRACE/watcom_functions.h b/src/DETHRACE/watcom_functions.h deleted file mode 100644 index e627db45..00000000 --- a/src/DETHRACE/watcom_functions.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _WATCOM_FUNCTIONS_H_ -#define _WATCOM_FUNCTIONS_H_ - -void splitpath(char* path, char* drive, char* dir, char* fname, char* ext); - -#endif diff --git a/src/harness/CMakeLists.txt b/src/harness/CMakeLists.txt index 350c27cb..5168b074 100644 --- a/src/harness/CMakeLists.txt +++ b/src/harness/CMakeLists.txt @@ -1,5 +1,9 @@ add_library(harness STATIC) +if (NOT DEFINED IO_PLATFORM) + set(IO_PLATFORM "SDL_OpenGL") +endif() + target_include_directories(harness PRIVATE . @@ -9,7 +13,7 @@ target_include_directories(harness include ) -target_link_libraries(harness PRIVATE miniposix brender SDL2::SDL2 glad s3 cglm_headers) +target_link_libraries(harness PRIVATE brender s3 cglm_headers) if(WIN32) target_link_libraries(harness PRIVATE dbghelp) @@ -30,39 +34,45 @@ target_sources(harness PRIVATE include/harness/hooks.h include/harness/trace.h include/harness/config.h + include/harness/os.h cameras/debug_camera.c cameras/debug_camera.h harness_trace.c harness.c harness.h - sdl/gl_renderer.c - sdl/gl_renderer.h - sdl/gl_renderer_shaders.c - sdl/gl_renderer_shaders.h - sdl/gl_brender_stored_context.c - sdl/gl_brender_stored_context.h + io_platforms/io_platform.h + renderers/null.h + renderers/renderer.h brender_emu/renderer_impl.c brender_emu/renderer_impl.h sound/sound.c sound/sound.h - sdl/common.c - sdl/common.h - platforms/sdl_gl.h - platforms/null.h - stack_trace_handler.h ) +if (IO_PLATFORM STREQUAL "SDL_OpenGL") + target_sources(harness PRIVATE + io_platforms/sdl_gl.c + renderers/gl/gl_renderer.c + renderers/gl/gl_renderer.h + renderers/gl/shaders.c + renderers/gl/shaders.h + renderers/gl/stored_context.c + renderers/gl/stored_context.h + ) + target_link_libraries(harness PRIVATE SDL2::SDL2 glad) +endif() + if(WIN32) target_sources(harness PRIVATE - platforms/platform_windows.c + os/windows.c ) elseif(APPLE) target_sources(harness PRIVATE - platforms/platform_macosx.c + os/macos.c ) else() target_sources(harness PRIVATE - platforms/platform_linux.c + os/linux.c ) endif() diff --git a/src/harness/harness.c b/src/harness/harness.c index 879e6bee..6db57fda 100644 --- a/src/harness/harness.c +++ b/src/harness/harness.c @@ -1,16 +1,17 @@ #include "harness.h" #include "brender_emu/renderer_impl.h" #include "include/harness/config.h" -#include "platforms/null.h" -#include "platforms/sdl_gl.h" +#include "include/harness/os.h" +#include "io_platforms/io_platform.h" +#include "renderers/null.h" #include "sound/sound.h" -#include "stack_trace_handler.h" -#include +#include +#include +#include #include -#include -tPlatform* platform; +tRenderer* renderer; br_pixelmap* palette; uint32_t* screen_buffer; harness_br_renderer* renderer_state; @@ -21,6 +22,7 @@ br_pixelmap* last_src = NULL; br_pixelmap *last_colour_buffer, *last_depth_buffer; unsigned int last_frame_time = 0; +int force_nullrenderer = 0; extern unsigned int GetTotalTime(); extern uint8_t gScan_code[123][2]; @@ -71,11 +73,10 @@ void Harness_Init(int* argc, char* argv[]) { Harness_ProcessCommandLine(argc, argv); if (harness_game_config.install_signalhandler) { - install_signal_handler(argv[0]); + OS_InstallSignalHandler(argv[0]); } - platform->Init(); - int* keymap = platform->GetKeyMap(); + int* keymap = Input_GetKeyMap(); if (keymap != NULL) { for (int i = 0; i < 123; i++) { gScan_code[i][0] = keymap[i]; @@ -98,15 +99,13 @@ void Harness_Init(int* argc, char* argv[]) { } } -void Harness_Debug_PrintStack() { -#ifndef _WIN32 - posix_print_stack_trace(); -#endif +// used by unit tests +void Harness_ForceNullRenderer() { + force_nullrenderer = 1; + renderer = &null_renderer; } int Harness_ProcessCommandLine(int* argc, char* argv[]) { - char* platform_name = NULL; - for (int i = 1; i < *argc; i++) { int handled = 0; @@ -118,10 +117,6 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) { harness_debug_level = atoi(s + 1); LOG_INFO("debug level set to %d", harness_debug_level); handled = 1; - } else if (strstr(argv[i], "--platform=") != NULL) { - platform_name = strstr(argv[i], "=") + 1; - LOG_INFO("Platform set to: %s", platform_name); - handled = 1; } else if (strstr(argv[i], "--physics-step-time=") != NULL) { char* s = strstr(argv[i], "="); harness_game_config.physics_step_time = atof(s + 1); @@ -152,39 +147,31 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) { } } - if (platform_name == NULL) { - platform_name = "sdl_gl"; - } - - if (strcmp(platform_name, "sdl_gl") == 0) { - platform = &sdl_gl_platform; - } else if (strcmp(platform_name, "null") == 0) { - platform = &null_platform; - } else { - LOG_PANIC("Invalid platform: %s", platform_name); - } return 0; } void Harness_Hook_DOSGfxBegin() { - platform->NewWindow("Dethrace", 640, 400, 320, 200); + if (force_nullrenderer) { + return; + } + renderer = Window_Create("Dethrace", 640, 400, 320, 200); } // Render 2d back buffer void Harness_RenderScreen(br_pixelmap* dst, br_pixelmap* src) { - platform->RenderFullScreenQuad((uint8_t*)src->pixels, 320, 200); + renderer->FullScreenQuad((uint8_t*)src->pixels, 320, 200); last_dst = dst; last_src = src; } void Harness_Hook_BrDevPaletteSetOld(br_pixelmap* pm) { - platform->SetPalette((uint8_t*)pm->pixels); + renderer->SetPalette((uint8_t*)pm->pixels); palette = pm; if (last_dst) { Harness_RenderScreen(last_dst, last_src); - platform->Swap(); + Window_Swap(0); } } @@ -200,74 +187,78 @@ void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db) { v1db->renderer = (br_renderer*)renderer_state; } -void Harness_Hook_MainGameLoop() { +int Harness_CalculateFrameDelay() { if (harness_game_config.fps == 0) { - return; + return 0; } - if (last_frame_time) { - unsigned int frame_time = GetTotalTime() - last_frame_time; + unsigned int now = GetTotalTime(); + 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) { - SDL_Delay(sleep_time); + return sleep_time; } } } - - last_frame_time = GetTotalTime(); + return 0; } // Begin 3d scene void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) { last_colour_buffer = colour_buffer; last_depth_buffer = depth_buffer; - platform->BeginScene(camera, colour_buffer); + renderer->BeginScene(camera, colour_buffer); } void Harness_Hook_BrZbSceneRenderAdd(br_actor* tree) { } void Harness_Hook_renderFaces(br_actor* actor, br_model* model, br_material* material, br_token type) { - platform->RenderModel(actor, model, renderer_state->state.matrix.model_to_view); + renderer->Model(actor, model, renderer_state->state.matrix.model_to_view); } void Harness_Hook_BrZbSceneRenderEnd() { - platform->EndScene(); + renderer->EndScene(); } // Called by game to swap buffers at end of frame rendering void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src) { // draw the current colour_buffer (2d screen) contents - platform->FlushBuffers(last_colour_buffer, last_depth_buffer); + renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); Harness_RenderScreen(dst, src); - platform->Swap(); - platform->PollEvents(); + int delay_ms = Harness_CalculateFrameDelay(); + Window_Swap(delay_ms); + + renderer->ClearBuffers(); + Window_PollEvents(); + + last_frame_time = GetTotalTime(); } int Harness_Hook_KeyDown(unsigned char pScan_code) { - return platform->IsKeyDown(pScan_code); + return Input_IsKeyDown(pScan_code); } void Harness_Hook_PDServiceSystem() { - platform->PollEvents(); + Window_PollEvents(); } void Harness_Hook_PDSetKeyArray() { - platform->PollEvents(); + Window_PollEvents(); } void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags) { - // LOG_DEBUG("buffermat %s", mat->identifier); - platform->BufferMaterial(mat); + renderer->BufferMaterial(mat); } void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags) { if (use == BRT_COLOUR_MAP_O || use == BRT_UNKNOWN) { - platform->BufferTexture(pm); + renderer->BufferTexture(pm); } else { LOG_PANIC("use %d", use); } @@ -281,6 +272,5 @@ void Harness_Hook_S3StopAllOutletSounds() { } void Harness_Hook_FlushRenderer() { - platform->FlushBuffers(last_colour_buffer, last_depth_buffer); + renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); } - diff --git a/src/harness/harness.h b/src/harness/harness.h index cd134d49..f5b6708c 100644 --- a/src/harness/harness.h +++ b/src/harness/harness.h @@ -4,23 +4,7 @@ #include "brender/br_types.h" #include "harness/trace.h" -typedef struct tPlatform { - void (*Init)(); - void (*NewWindow)(char* title, int width, int height, int render_width, int render_height); - void (*PollEvents)(); - int* (*GetKeyMap)(); - int (*IsKeyDown)(unsigned char pScan_code); - void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer); - void (*EndScene)(); - void (*SetPalette)(uint8_t* palette); - void (*RenderFullScreenQuad)(uint8_t* src, int width, int height); - void (*RenderModel)(br_actor* actor, br_model* model, br_matrix34 model_matrix); - void (*Swap)(); - void (*BufferTexture)(br_pixelmap* pm); - void (*BufferMaterial)(br_material* mat); - void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); - -} tPlatform; +void Harness_ForceNullRenderer(); typedef struct tCamera { void (*update)(); @@ -29,4 +13,6 @@ typedef struct tCamera { void (*setPosition)(); } tCamera; + + #endif \ No newline at end of file diff --git a/src/harness/harness_trace.c b/src/harness/harness_trace.c index d12271b1..fe36bad0 100644 --- a/src/harness/harness_trace.c +++ b/src/harness/harness_trace.c @@ -1,6 +1,5 @@ #include "harness/trace.h" -#include #include #include #include diff --git a/src/harness/include/harness/hooks.h b/src/harness/include/harness/hooks.h index 913963d5..7eba5faf 100644 --- a/src/harness/include/harness/hooks.h +++ b/src/harness/include/harness/hooks.h @@ -3,14 +3,15 @@ #include "brender/br_types.h" +void Harness_Init(int* argc, char* argv[]); + // Hooks are called from original game code. // Dethrace hooks -void Harness_Init(int* argc, char* argv[]); int Harness_Hook_KeyDown(unsigned char pScan_code); void Harness_Hook_PDServiceSystem(); void Harness_Hook_PDSetKeyArray(); -void Harness_Hook_MainGameLoop(); // limit FPS +// void Harness_Hook_MainGameLoop(); // limit FPS void Harness_Hook_FlushRenderer(); // synchronize in-memory framebuffer and depthbuffer // BRender hooks diff --git a/src/harness/include/harness/os.h b/src/harness/include/harness/os.h new file mode 100644 index 00000000..52ab9386 --- /dev/null +++ b/src/harness/include/harness/os.h @@ -0,0 +1,46 @@ +#ifndef HARNESS_OS_H +#define HARNESS_OS_H + +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#include +#define getcwd _getcwd +#define chdir _chdir +#define access _access +#define F_OK 0 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp + +#if _MSC_VER < 1900 +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + +#else +#include +#endif + +// Required: return timestamp in milliseconds. +uint32_t OS_GetTime(void); + +// Required: sleep for specified milliseconds +void OS_Sleep(int ms); + +// Required: begin a directory iteration and return name of first file +char* OS_GetFirstFileInDirectory(char* path); + +// Required: continue directory iteration. If no more files, return NULL +char* OS_GetNextFileInDirectory(void); + +// Required: copy the `basename` component of `path` into `base` +void OS_Basename(char* path, char* base); + +// Optional: return true if a debugger is detected +int OS_IsDebuggerPresent(void); + +// Optional: install a handler to print stack trace during a crash +void OS_InstallSignalHandler(char* program_name); + +#endif diff --git a/src/harness/include/harness/trace.h b/src/harness/include/harness/trace.h index 9485f168..d29003ce 100644 --- a/src/harness/include/harness/trace.h +++ b/src/harness/include/harness/trace.h @@ -3,16 +3,9 @@ #include "brender/br_types.h" #include -#include - -#if defined _WIN32 && !defined sleep -#define sleep(x) _sleep(x) -#endif extern int harness_debug_level; -extern int PlatformIsDebuggerPresent(void); - -void Harness_Debug_PrintStack(); +extern int OS_IsDebuggerPresent(void); void debug_printf(const char* fmt, const char* fn, const char* fmt2, ...); void debug_print_vector3(const char* fmt, const char* fn, char* msg, br_vector3* v); @@ -46,26 +39,26 @@ void debug_print_matrix4(const char* fmt, const char* fn, char* name, br_matrix4 #define LOG_MATRIX4(msg, m) debug_print_matrix4("\033[0;34m[DEBUG] %s ", __FUNCTION__, msg, m) #define LOG_INFO(...) debug_printf("\033[0;34m[INFO] %s ", __FUNCTION__, __VA_ARGS__) #define LOG_WARN(...) debug_printf("\033[0;33m[WARN] %s ", __FUNCTION__, __VA_ARGS__) -#define LOG_PANIC(...) \ - do { \ - debug_printf("\033[0;31m[PANIC] %s ", __FUNCTION__, __VA_ARGS__); \ - if (PlatformIsDebuggerPresent()) \ - abort(); \ - else \ - exit(1); \ +#define LOG_PANIC(...) \ + do { \ + debug_printf("\033[0;31m[PANIC] %s ", __FUNCTION__, __VA_ARGS__); \ + if (OS_IsDebuggerPresent()) \ + abort(); \ + else \ + exit(1); \ } while (0) -#define LOG_WARN_ONCE(...) \ - static int warn_printed = 0; \ - if (!warn_printed) { \ - debug_printf("\033[0;33m[WARN] %s ", __FUNCTION__, __VA_ARGS__); \ - warn_printed = 1; \ +#define LOG_WARN_ONCE(...) \ + static int warn_printed = 0; \ + if (!warn_printed) { \ + debug_printf("\033[0;33m[WARN] %s ", __FUNCTION__, __VA_ARGS__); \ + warn_printed = 1; \ } -#define NOT_IMPLEMENTED() \ +#define NOT_IMPLEMENTED() \ LOG_PANIC("not implemented") -#define TELL_ME_IF_WE_PASS_THIS_WAY() \ +#define TELL_ME_IF_WE_PASS_THIS_WAY() \ LOG_PANIC("code path not expected") #define STUB() \ @@ -78,6 +71,6 @@ void debug_print_matrix4(const char* fmt, const char* fn, char* name, br_matrix4 stub_printed = 1; \ } -//int count_open_fds(); +// int count_open_fds(); #endif diff --git a/src/harness/io_platforms/io_platform.h b/src/harness/io_platforms/io_platform.h new file mode 100644 index 00000000..e4ee4ea3 --- /dev/null +++ b/src/harness/io_platforms/io_platform.h @@ -0,0 +1,12 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +#include "../renderers/renderer.h" + +tRenderer* Window_Create(char* title, int width, int height, int pRender_width, int pRender_height); +void Window_PollEvents(void); +void Window_Swap(int delay_ms_after_swap); +int* Input_GetKeyMap(void); +int Input_IsKeyDown(unsigned char scan_code); + +#endif \ No newline at end of file diff --git a/src/harness/sdl/common.c b/src/harness/io_platforms/sdl_gl.c similarity index 58% rename from src/harness/sdl/common.c rename to src/harness/io_platforms/sdl_gl.c index ae2140e5..54e1b72d 100644 --- a/src/harness/sdl/common.c +++ b/src/harness/io_platforms/sdl_gl.c @@ -1,5 +1,12 @@ -#include "common.h" +#include + +// this needs to be included after glad.h #include +#include + +#include "../renderers/gl/gl_renderer.h" +#include "../renderers/renderer.h" +#include "harness/trace.h" // Errol's keymap int keymap[123] = { @@ -112,15 +119,69 @@ int keymap[123] = { SDL_SCANCODE_SPACE }; +SDL_Window* window; +SDL_GLContext context; uint8_t sdl_key_state[256]; -void SDLPlatform_Init() { - if (SDL_Init(SDL_INIT_TIMER) != 0) { - LOG_PANIC("SDL_INIT_TIMER error: %s", SDL_GetError()); +tRenderer gl_renderer = { + GLRenderer_Init, + GLRenderer_BeginScene, + GLRenderer_EndScene, + GLRenderer_SetPalette, + GLRenderer_FullScreenQuad, + GLRenderer_Model, + GLRenderer_ClearBuffers, + GLRenderer_BufferTexture, + GLRenderer_BufferMaterial, + GLRenderer_FlushBuffers +}; + +tRenderer* Window_Create(char* title, int width, int height, int pRender_width, int pRender_height) { + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError()); } + + if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) { + LOG_PANIC("Failed to set SDL_GL_CONTEXT_PROFILE_MASK attribute. %s", SDL_GetError()); + }; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + + SDL_GL_SetSwapInterval(1); + + window = SDL_CreateWindow(title, + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + width, height, + SDL_WINDOW_OPENGL); + + if (!window) { + LOG_PANIC("Failed to create window"); + } + + // Don't grab the mouse when a debugger is present + if (!OS_IsDebuggerPresent()) { + SDL_SetRelativeMouseMode(SDL_TRUE); + } + + // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + + context = SDL_GL_CreateContext(window); + if (!context) { + LOG_PANIC("Failed to call SDL_GL_CreateContext. %s", SDL_GetError()); + } + + // Load GL extensions using glad + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { + LOG_PANIC("Failed to initialize the OpenGL context with GLAD."); + exit(1); + } + + gl_renderer.Init(width, height, pRender_width, pRender_height); + return &gl_renderer; } -void SDLPlatform_PollEvents() { +void Window_PollEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { @@ -134,7 +195,7 @@ void SDLPlatform_PollEvents() { } if (event.key.type == SDL_KEYDOWN) { sdl_key_state[event.key.keysym.scancode] = 1; - //LOG_DEBUG("key %d", key->keysym.scancode); + // LOG_DEBUG("key %d", key->keysym.scancode); } else { sdl_key_state[event.key.keysym.scancode] = 0; } @@ -148,10 +209,18 @@ void SDLPlatform_PollEvents() { } } -int* SDLPlatform_GetKeyMap() { +void Window_Swap(int delay_ms_after_swap) { + SDL_GL_SwapWindow(window); + + if (delay_ms_after_swap != 0) { + SDL_Delay(delay_ms_after_swap); + } +} + +int* Input_GetKeyMap() { return (int*)keymap; } -int SDLPlatform_IsKeyDown(unsigned char scan_code) { +int Input_IsKeyDown(unsigned char scan_code) { return sdl_key_state[scan_code]; } diff --git a/src/harness/stack_trace_handler.h b/src/harness/os/linux.c similarity index 53% rename from src/harness/stack_trace_handler.h rename to src/harness/os/linux.c index 38c5e676..80c0e526 100644 --- a/src/harness/stack_trace_handler.h +++ b/src/harness/os/linux.c @@ -1,7 +1,14 @@ // Based on https://gist.github.com/jvranish/4441299 +#include "harness/os.h" #include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -9,158 +16,107 @@ #include #include #include +#include +#include +#include +#include #include -#ifdef _WIN32 -#include -#include -#ifdef _WIN64 -#define Esp Rsp -#define Eip Rip -#define Ebp Rbp -#endif -#else -#include -#include -#endif - static int stack_nbr = 0; static char _program_name[1024]; +#define MAX_STACK_FRAMES 64 +static void* stack_traces[MAX_STACK_FRAMES]; +#define TRACER_PID_STRING "TracerPid:" +DIR* directory_iterator; -/* Resolve symbol name and source location given the path to the executable - and an address */ +uint32_t OS_GetTime() { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec * 1000 + spec.tv_nsec / 1000000; +} + +void OS_Sleep(int delay_ms) { + struct timespec ts; + ts.tv_sec = delay_ms / 1000; + ts.tv_nsec = (delay_ms % 1000) * 1000000; + nanosleep(&ts, &ts); +} + +char* OS_GetFirstFileInDirectory(char* path) { + directory_iterator = opendir(path); + if (directory_iterator == NULL) { + return NULL; + } + return OS_GetNextFileInDirectory(); +} + +char* OS_GetNextFileInDirectory(void) { + struct dirent* entry; + + if (directory_iterator == NULL) { + return NULL; + } + while ((entry = readdir(directory_iterator)) != NULL) { + if (entry->d_type == DT_REG) { + return entry->d_name; + } + } + closedir(directory_iterator); + directory_iterator = NULL; + return NULL; +} + +void OS_Basename(char* path, char* base) { + strcpy(base, basename(path)); +} + +int OS_IsDebuggerPresent() { + char buf[4096]; + int status_fd; + ssize_t num_read; + char* tracer_pid_ptr; + char* char_ptr; + + status_fd = open("/proc/self/status", O_RDONLY); + if (status_fd == -1) { + return 0; + } + + num_read = read(status_fd, buf, sizeof(buf) - 1); + close(status_fd); + if (num_read <= 0) { + return 0; + } + + buf[num_read] = '\0'; + tracer_pid_ptr = strstr(buf, TRACER_PID_STRING); + if (tracer_pid_ptr == NULL) { + return 0; + } + + for (char_ptr = tracer_pid_ptr + sizeof(TRACER_PID_STRING) - 1; char_ptr <= buf + num_read; ++char_ptr) { + if (isspace(*char_ptr)) { + continue; + } else { + return isdigit(*char_ptr) != 0 && *char_ptr != '0'; + } + } + + return 0; +} + +// Resolve symbol name and source location given the path to the executable and an address int addr2line(char const* const program_name, void const* const addr) { char addr2line_cmd[512] = { 0 }; -/* have addr2line map the address to the relent line in the code */ -#ifdef __APPLE__ - /* apple does things differently... */ - sprintf(addr2line_cmd, "atos -o %.256s %p", program_name, addr); -#else + /* have addr2line map the address to the related line in the code */ sprintf(addr2line_cmd, "addr2line -f -p -e %.256s %p", program_name, addr); -#endif fprintf(stderr, "%d: ", stack_nbr++); return system(addr2line_cmd); } -#ifdef _WIN32 -void windows_print_stacktrace(CONTEXT* context) { - SymInitialize(GetCurrentProcess(), 0, true); - - STACKFRAME frame = { 0 }; - - /* setup initial stack frame */ - frame.AddrPC.Offset = context->Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = context->Esp; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context->Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - - while (StackWalk(IMAGE_FILE_MACHINE_I386, - GetCurrentProcess(), - GetCurrentThread(), - &frame, - context, - 0, - SymFunctionTableAccess, - SymGetModuleBase, - 0)) { - addr2line(_program_name, (void*)frame.AddrPC.Offset); - } - - SymCleanup(GetCurrentProcess()); -} - -LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo) { - switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr); - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); - break; - case EXCEPTION_BREAKPOINT: - fputs("Error: EXCEPTION_BREAKPOINT\n", stderr); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); - break; - case EXCEPTION_FLT_DENORMAL_OPERAND: - fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); - break; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_FLT_INEXACT_RESULT: - fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr); - break; - case EXCEPTION_FLT_INVALID_OPERATION: - fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr); - break; - case EXCEPTION_FLT_OVERFLOW: - fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr); - break; - case EXCEPTION_FLT_STACK_CHECK: - fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr); - break; - case EXCEPTION_FLT_UNDERFLOW: - fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); - break; - case EXCEPTION_IN_PAGE_ERROR: - fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr); - break; - case EXCEPTION_INT_DIVIDE_BY_ZERO: - fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_INT_OVERFLOW: - fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr); - break; - case EXCEPTION_INVALID_DISPOSITION: - fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr); - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); - break; - case EXCEPTION_PRIV_INSTRUCTION: - fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr); - break; - case EXCEPTION_SINGLE_STEP: - fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr); - break; - case EXCEPTION_STACK_OVERFLOW: - fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr); - break; - default: - fputs("Error: Unrecognized Exception\n", stderr); - break; - } - fflush(stderr); - /* If this is a stack overflow then we can't walk the stack, so just show - where the error happened */ - if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { - windows_print_stacktrace(ExceptionInfo->ContextRecord); - } else { - addr2line(_program_name, (void*)ExceptionInfo->ContextRecord->Eip); - } - - return EXCEPTION_EXECUTE_HANDLER; -} - -void install_signal_handler(char* program_name) { - strcpy(_program_name, program_name); - SetUnhandledExceptionFilter(windows_exception_handler); -} -#else - -#define MAX_STACK_FRAMES 64 -static void* stack_traces[MAX_STACK_FRAMES]; - -void posix_print_stack_trace() { +void print_stack_trace() { int i, trace_size = 0; char** messages = (char**)NULL; @@ -181,7 +137,7 @@ void posix_print_stack_trace() { } } -void posix_signal_handler(int sig, siginfo_t* siginfo, void* context) { +void signal_handler(int sig, siginfo_t* siginfo, void* context) { (void)context; fputs("\n******************\n", stderr); @@ -264,7 +220,7 @@ void posix_signal_handler(int sig, siginfo_t* siginfo, void* context) { break; } fputs("******************\n", stderr); - posix_print_stack_trace(); + print_stack_trace(); exit(1); } @@ -283,7 +239,7 @@ void resolve_full_path(char* path, const char* argv0) { } } -void install_signal_handler(char* program_name) { +void OS_InstallSignalHandler(char* program_name) { resolve_full_path(_program_name, program_name); @@ -304,16 +260,10 @@ void install_signal_handler(char* program_name) { /* register our signal handlers */ { struct sigaction sig_action = {}; - sig_action.sa_sigaction = posix_signal_handler; + sig_action.sa_sigaction = signal_handler; sigemptyset(&sig_action.sa_mask); -#ifdef __APPLE__ - /* for some reason we backtrace() doesn't work on osx - when we use an alternate stack */ - sig_action.sa_flags = SA_SIGINFO; -#else sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK; -#endif if (sigaction(SIGSEGV, &sig_action, NULL) != 0) { err(1, "sigaction"); @@ -335,4 +285,3 @@ void install_signal_handler(char* program_name) { } } } -#endif diff --git a/src/harness/os/macos.c b/src/harness/os/macos.c new file mode 100644 index 00000000..b0f13249 --- /dev/null +++ b/src/harness/os/macos.c @@ -0,0 +1,286 @@ +// Based on https://gist.github.com/jvranish/4441299 + +#include "harness/os.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int stack_nbr = 0; +static char _program_name[1024]; +#define MAX_STACK_FRAMES 64 +static void* stack_traces[MAX_STACK_FRAMES]; +DIR* directory_iterator; + +uint32_t OS_GetTime() { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec * 1000 + spec.tv_nsec / 1000000; +} + +void OS_Sleep(int delay_ms) { + struct timespec ts; + ts.tv_sec = delay_ms / 1000; + ts.tv_nsec = (delay_ms % 1000) * 1000000; + nanosleep(&ts, &ts); +} + +char* OS_GetFirstFileInDirectory(char* path) { + directory_iterator = opendir(path); + if (directory_iterator == NULL) { + return NULL; + } + return OS_GetNextFileInDirectory(); +} + +char* OS_GetNextFileInDirectory(void) { + struct dirent* entry; + + if (directory_iterator == NULL) { + return NULL; + } + while ((entry = readdir(directory_iterator)) != NULL) { + if (entry->d_type == DT_REG) { + return entry->d_name; + } + } + closedir(directory_iterator); + directory_iterator = NULL; + return NULL; +} + +void OS_Basename(char* path, char* base) { + strcpy(base, basename(path)); +} + +// https://developer.apple.com/library/archive/qa/qa1361/_index.html +// FIXME: +// Important: Because the definition of the kinfo_proc structure (in ) is conditionalized by __APPLE_API_UNSTABLE, +// you should restrict use of the above code to the debug build of your program. + +int OS_IsDebuggerPresent() +// Returns true if the current process is being debugged (either +// running under the debugger or has a debugger attached post facto). +{ + int junk; + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); + assert(junk == 0); + + // We're being debugged if the P_TRACED flag is set. + + return ((info.kp_proc.p_flag & P_TRACED) != 0); +} + +// Resolve symbol name and source location given the path to the executable and an address +int addr2line(char const* const program_name, void const* const addr) { + char addr2line_cmd[512] = { 0 }; + + /* have addr2line map the address to the related line in the code */ + sprintf(addr2line_cmd, "atos -o %.256s %p", program_name, addr); + + fprintf(stderr, "%d: ", stack_nbr++); + return system(addr2line_cmd); +} + +void print_stack_trace() { + int i, trace_size = 0; + char** messages = (char**)NULL; + + fputs("\nStack trace:\n", stderr); + + trace_size = backtrace(stack_traces, MAX_STACK_FRAMES); + messages = backtrace_symbols(stack_traces, trace_size); + + /* skip the first couple stack frames (as they are this function and + our handler) and also skip the last frame as it's (always?) junk. */ + for (i = 3; i < (trace_size - 1); ++i) { + if (addr2line(_program_name, stack_traces[i]) != 0) { + printf(" error determining line # for: %s\n", messages[i]); + } + } + if (messages) { + free(messages); + } +} + +void signal_handler(int sig, siginfo_t* siginfo, void* context) { + (void)context; + fputs("\n******************\n", stderr); + + switch (sig) { + case SIGSEGV: + fputs("Caught SIGSEGV\n", stderr); + break; + case SIGINT: + fputs("Caught SIGINT\n", stderr); + break; + case SIGFPE: + switch (siginfo->si_code) { + case FPE_INTDIV: + fputs("Caught SIGFPE: FPE_INTDIV\n", stderr); + break; + case FPE_INTOVF: + fputs("Caught SIGFPE: FPE_INTOVF\n", stderr); + break; + case FPE_FLTDIV: + fputs("Caught SIGFPE: FPE_FLTDIV\n", stderr); + break; + case FPE_FLTOVF: + fputs("Caught SIGFPE: FPE_FLTOVF\n", stderr); + break; + case FPE_FLTUND: + fputs("Caught SIGFPE: FPE_FLTUND\n", stderr); + break; + case FPE_FLTRES: + fputs("Caught SIGFPE: FPE_FLTRES\n", stderr); + break; + case FPE_FLTINV: + fputs("Caught SIGFPE: FPE_FLTINV\n", stderr); + break; + case FPE_FLTSUB: + fputs("Caught SIGFPE: FPE_FLTSUB\n", stderr); + break; + default: + fputs("Caught SIGFPE: Arithmetic Exception\n", stderr); + break; + } + break; + case SIGILL: + switch (siginfo->si_code) { + case ILL_ILLOPC: + fputs("Caught SIGILL: ILL_ILLOPC\n", stderr); + break; + case ILL_ILLOPN: + fputs("Caught SIGILL: ILL_ILLOPN\n", stderr); + break; + case ILL_ILLADR: + fputs("Caught SIGILL: ILL_ILLADR\n", stderr); + break; + case ILL_ILLTRP: + fputs("Caught SIGILL: ILL_ILLTRP\n", stderr); + break; + case ILL_PRVOPC: + fputs("Caught SIGILL: ILL_PRVOPC\n", stderr); + break; + case ILL_PRVREG: + fputs("Caught SIGILL: ILL_PRVREG\n", stderr); + break; + case ILL_COPROC: + fputs("Caught SIGILL: ILL_COPROC\n", stderr); + break; + case ILL_BADSTK: + fputs("Caught SIGILL: ILL_BADSTK\n", stderr); + break; + default: + fputs("Caught SIGILL: Illegal Instruction\n", stderr); + break; + } + break; + case SIGTERM: + fputs("Caught SIGTERM\n", stderr); + break; + case SIGABRT: + fputs("Caught SIGABRT\n", stderr); + break; + default: + break; + } + fputs("******************\n", stderr); + print_stack_trace(); + exit(1); +} + +static uint8_t alternate_stack[SIGSTKSZ]; + +void resolve_full_path(char* path, const char* argv0) { + if (argv0[0] == '/') { // run with absolute path + strcpy(path, argv0); + } else { // run with relative path + if (NULL == getcwd(path, PATH_MAX)) { + perror("getcwd error"); + return; + } + strcat(path, "/"); + strcat(path, argv0); + } +} + +void OS_InstallSignalHandler(char* program_name) { + + resolve_full_path(_program_name, program_name); + + /* setup alternate stack */ + { + stack_t ss = {}; + /* malloc is usually used here, I'm not 100% sure my static allocation + is valid but it seems to work just fine. */ + ss.ss_sp = (void*)alternate_stack; + ss.ss_size = SIGSTKSZ; + ss.ss_flags = 0; + + if (sigaltstack(&ss, NULL) != 0) { + err(1, "sigaltstack"); + } + } + + /* register our signal handlers */ + { + struct sigaction sig_action = {}; + sig_action.sa_sigaction = signal_handler; + sigemptyset(&sig_action.sa_mask); + + sig_action.sa_flags = SA_SIGINFO; + + if (sigaction(SIGSEGV, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + if (sigaction(SIGFPE, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + if (sigaction(SIGINT, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + if (sigaction(SIGILL, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + if (sigaction(SIGTERM, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + if (sigaction(SIGABRT, &sig_action, NULL) != 0) { + err(1, "sigaction"); + } + } +} diff --git a/src/harness/os/windows.c b/src/harness/os/windows.c new file mode 100644 index 00000000..0b5e6f0e --- /dev/null +++ b/src/harness/os/windows.c @@ -0,0 +1,206 @@ +// Based on https://gist.github.com/jvranish/4441299 + +// this has to be first +#include + +#include + +#include "harness/os.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN64 +#define Esp Rsp +#define Eip Rip +#define Ebp Rbp +#endif + +static int stack_nbr = 0; +static char _program_name[1024]; +LARGE_INTEGER qpc_start_time, EndingTime, ElapsedMicroseconds; +LARGE_INTEGER qpc_ticks_per_sec; + +HANDLE directory_handle = NULL; +char last_found_file[260]; + +uint32_t OS_GetTime() { + LARGE_INTEGER now; + if (qpc_start_time.QuadPart == 0) { + QueryPerformanceFrequency(&qpc_ticks_per_sec); + QueryPerformanceCounter(&qpc_start_time); + } + + QueryPerformanceCounter(&now); + return (uint32_t)(((now.QuadPart - qpc_start_time.QuadPart) * 1000) / qpc_ticks_per_sec.QuadPart); +} + +void OS_Sleep(int delay_ms) { + Sleep(delay_ms); +} + +char* OS_GetFirstFileInDirectory(char* path) { + char with_extension[256]; + WIN32_FIND_DATA find_data; + HANDLE hFind = NULL; + + strcpy(with_extension, path); + strcat(with_extension, "\\*.???"); + directory_handle = FindFirstFile(with_extension, &find_data); + if (directory_handle == INVALID_HANDLE_VALUE) { + return NULL; + } + strcpy(last_found_file, find_data.cFileName); + return last_found_file; +} + +// Required: continue directory iteration. If no more files, return NULL +char* OS_GetNextFileInDirectory(void) { + WIN32_FIND_DATA find_data; + if (directory_handle == NULL) { + return NULL; + } + + while (FindNextFile(directory_handle, &find_data)) { + strcpy(last_found_file, find_data.cFileName); + return last_found_file; + } + FindClose(directory_handle); + return NULL; +} + +void OS_Basename(char* path, char* base) { + _splitpath(path, NULL, NULL, base, NULL); +} + +int OS_IsDebuggerPresent() { + return IsDebuggerPresent(); +} + +int addr2line(char const* const program_name, void const* const addr) { + char addr2line_cmd[512] = { 0 }; + + sprintf(addr2line_cmd, "addr2line -f -p -e %.256s %p", program_name, addr); + + fprintf(stderr, "%d: ", stack_nbr++); + return system(addr2line_cmd); +} + +void print_stacktrace(CONTEXT* context) { + + SymInitialize(GetCurrentProcess(), 0, true); + + STACKFRAME frame = { 0 }; + + /* setup initial stack frame */ + frame.AddrPC.Offset = context->Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = context->Esp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context->Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + while (StackWalk(IMAGE_FILE_MACHINE_I386, + GetCurrentProcess(), + GetCurrentThread(), + &frame, + context, + 0, + SymFunctionTableAccess, + SymGetModuleBase, + 0)) { + addr2line(_program_name, (void*)frame.AddrPC.Offset); + } + + SymCleanup(GetCurrentProcess()); +} + +LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr); + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); + break; + case EXCEPTION_BREAKPOINT: + fputs("Error: EXCEPTION_BREAKPOINT\n", stderr); + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); + break; + case EXCEPTION_FLT_INEXACT_RESULT: + fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr); + break; + case EXCEPTION_FLT_INVALID_OPERATION: + fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr); + break; + case EXCEPTION_FLT_OVERFLOW: + fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr); + break; + case EXCEPTION_FLT_STACK_CHECK: + fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr); + break; + case EXCEPTION_FLT_UNDERFLOW: + fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); + break; + case EXCEPTION_IN_PAGE_ERROR: + fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr); + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); + break; + case EXCEPTION_INT_OVERFLOW: + fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr); + break; + case EXCEPTION_INVALID_DISPOSITION: + fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr); + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); + break; + case EXCEPTION_PRIV_INSTRUCTION: + fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr); + break; + case EXCEPTION_SINGLE_STEP: + fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr); + break; + case EXCEPTION_STACK_OVERFLOW: + fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr); + break; + default: + fputs("Error: Unrecognized Exception\n", stderr); + break; + } + fflush(stderr); + /* If this is a stack overflow then we can't walk the stack, so just show + where the error happened */ + if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { + print_stacktrace(ExceptionInfo->ContextRecord); + } else { + addr2line(_program_name, (void*)ExceptionInfo->ContextRecord->Eip); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +void OS_InstallSignalHandler(char* program_name) { + strcpy(_program_name, program_name); + SetUnhandledExceptionFilter(windows_exception_handler); +} \ No newline at end of file diff --git a/src/harness/platforms/platform.h b/src/harness/platforms/platform.h deleted file mode 100644 index d2262f24..00000000 --- a/src/harness/platforms/platform.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef HARNESS_PLATFORM_H -#define HARNESS_PLATFORM_H - -int PlatformIsDebuggerPresent(void); - -#endif diff --git a/src/harness/platforms/platform_linux.c b/src/harness/platforms/platform_linux.c deleted file mode 100644 index bd981f5b..00000000 --- a/src/harness/platforms/platform_linux.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "platforms/platform.h" - -#include -#include -#include -#include -#include - -#define TRACER_PID_STRING "TracerPid:" - -int PlatformIsDebuggerPresent() { - char buf[4096]; - int status_fd; - ssize_t num_read; - char* tracer_pid_ptr; - char* char_ptr; - - status_fd = open("/proc/self/status", O_RDONLY); - if (status_fd == -1) { - return 0; - } - - num_read = read(status_fd, buf, sizeof(buf) - 1); - close(status_fd); - if (num_read <= 0) { - return 0; - } - - buf[num_read] = '\0'; - tracer_pid_ptr = strstr(buf, TRACER_PID_STRING); - if (tracer_pid_ptr == NULL) { - return 0; - } - - for (char_ptr = tracer_pid_ptr + sizeof(TRACER_PID_STRING) - 1; char_ptr <= buf + num_read; ++char_ptr) - { - if (isspace(*char_ptr)) { - continue; - } else { - return isdigit(*char_ptr) != 0 && *char_ptr != '0'; - } - } - - return 0; -} diff --git a/src/harness/platforms/platform_macosx.c b/src/harness/platforms/platform_macosx.c deleted file mode 100644 index e51c6e39..00000000 --- a/src/harness/platforms/platform_macosx.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include -#include - - -// https://developer.apple.com/library/archive/qa/qa1361/_index.html -// FIXME: -// Important: Because the definition of the kinfo_proc structure (in ) is conditionalized by __APPLE_API_UNSTABLE, -// you should restrict use of the above code to the debug build of your program. - -int PlatformIsDebuggerPresent() - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). -{ - int junk; - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - assert(junk == 0); - - // We're being debugged if the P_TRACED flag is set. - - return ((info.kp_proc.p_flag & P_TRACED) != 0); -} diff --git a/src/harness/platforms/platform_windows.c b/src/harness/platforms/platform_windows.c deleted file mode 100644 index da742259..00000000 --- a/src/harness/platforms/platform_windows.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -int PlatformIsDebuggerPresent() { - return IsDebuggerPresent(); -} diff --git a/src/harness/platforms/sdl_gl.h b/src/harness/platforms/sdl_gl.h deleted file mode 100644 index 05591e8d..00000000 --- a/src/harness/platforms/sdl_gl.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SDL_GL_PLATFORM_H -#define SDL_GL_PLATFORM_H - -#include "harness.h" -#include "sdl/common.h" -#include "sdl/gl_renderer.h" - -tPlatform sdl_gl_platform = { - SDLPlatform_Init, - GLRenderer_CreateWindow, - SDLPlatform_PollEvents, - SDLPlatform_GetKeyMap, - SDLPlatform_IsKeyDown, - GLRenderer_BeginScene, - GLRenderer_EndScene, - GLRenderer_SetPalette, - GLRenderer_RenderFullScreenQuad, - GLRenderer_RenderModel, - GLRenderer_Swap, - GLRenderer_BufferTexture, - GLRenderer_BufferMaterial, - GLRenderer_FlushBuffers -}; - -#endif \ No newline at end of file diff --git a/src/harness/sdl/gl_renderer.c b/src/harness/renderers/gl/gl_renderer.c similarity index 92% rename from src/harness/sdl/gl_renderer.c rename to src/harness/renderers/gl/gl_renderer.c index c065b3ca..1f7590ff 100644 --- a/src/harness/sdl/gl_renderer.c +++ b/src/harness/renderers/gl/gl_renderer.c @@ -1,20 +1,15 @@ #include "gl_renderer.h" #include "brender/brender.h" #include "cameras/debug_camera.h" -#include "gl_brender_stored_context.h" -#include "gl_renderer_shaders.h" #include "harness.h" #include "harness/trace.h" -#include "platforms/platform.h" +#include "shaders.h" +#include "stored_context.h" #include #include +#include -// this needs to be included after glad.h -#include - -SDL_Window* window; -SDL_GLContext context; GLuint screen_buffer_vao, screen_buffer_ebo; GLuint screen_texture, palette_texture, depth_texture; @@ -178,18 +173,12 @@ void SetupFullScreenRectGeometry() { glBindVertexArray(0); } -void InitializeOpenGLContext() { +void GLRenderer_Init(int width, int height, int pRender_width, int pRender_height) { - context = SDL_GL_CreateContext(window); - if (!context) { - LOG_PANIC("Failed to call SDL_GL_CreateContext. %s", SDL_GetError()); - } - - // Load GL extensions using glad - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - LOG_PANIC("Failed to initialize the OpenGL context with GLAD."); - exit(1); - } + window_width = width; + window_height = height; + render_width = pRender_width; + render_height = pRender_height; int maxTextureImageUnits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); @@ -235,48 +224,10 @@ void InitializeOpenGLContext() { } glBindFramebuffer(GL_FRAMEBUFFER, 0); - CHECK_GL_ERROR("initializeOpenGLContext"); -} - -void GLRenderer_CreateWindow(char* title, int width, int height, int pRender_width, int pRender_height) { - window_width = width; - window_height = height; - render_width = pRender_width; - render_height = pRender_height; - - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError()); - } - - if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) { - LOG_PANIC("Failed to set SDL_GL_CONTEXT_PROFILE_MASK attribute. %s", SDL_GetError()); - }; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - - SDL_GL_SetSwapInterval(1); - - window = SDL_CreateWindow(title, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - width, height, - SDL_WINDOW_OPENGL); - - if (!window) { - LOG_PANIC("Failed to create window"); - } - - // Don't grab the mouse when a debugger is present - if (!PlatformIsDebuggerPresent()) { - SDL_SetRelativeMouseMode(SDL_TRUE); - } - - // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); - - InitializeOpenGLContext(); - screen_buffer_flip_pixels = malloc(sizeof(uint8_t) * render_width * render_height); depth_buffer_flip_pixels = malloc(sizeof(uint16_t) * render_width * render_height); + + CHECK_GL_ERROR("initializeOpenGLContext"); } void GLRenderer_SetPalette(uint8_t* rgba_colors) { @@ -374,7 +325,7 @@ void GLRenderer_EndScene() { CHECK_GL_ERROR("GLRenderer_RenderFullScreenQuad"); } -void GLRenderer_RenderFullScreenQuad(uint8_t* screen_buffer, int width, int height) { +void GLRenderer_FullScreenQuad(uint8_t* screen_buffer, int width, int height) { glViewport(0, 0, window_width, window_height); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -392,8 +343,7 @@ void GLRenderer_RenderFullScreenQuad(uint8_t* screen_buffer, int width, int heig CHECK_GL_ERROR("GLRenderer_RenderFullScreenQuad"); } -void GLRenderer_Swap() { - SDL_GL_SwapWindow(window); +void GLRenderer_ClearBuffers() { // clear our virtual framebuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id); @@ -407,6 +357,8 @@ void build_model(br_model* model) { tStored_model_context* ctx; v11model* v11; + LOG_DEBUG("called %s", model->identifier); + v11 = model->prepared; ctx = NewStoredModelContext(); @@ -469,13 +421,12 @@ void build_model(br_model* model) { } glGenVertexArrays(1, &ctx->vao_id); - GLuint vbo_id; - glGenBuffers(1, &vbo_id); + glGenBuffers(1, &ctx->vbo_id); glGenBuffers(1, &ctx->ebo_id); - // Vertices } + // Vertices glBindVertexArray(ctx->vao_id); - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, ctx->vbo_id); glBufferData(GL_ARRAY_BUFFER, sizeof(fmt_vertex) * total_verts, verts, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(fmt_vertex), (void*)offsetof(fmt_vertex, p)); glEnableVertexAttribArray(0); @@ -491,6 +442,7 @@ void build_model(br_model* model) { free(verts); free(indices); + model->stored = ctx; CHECK_GL_ERROR("after build model"); @@ -519,7 +471,7 @@ void setActiveMaterial(tStored_material* material) { } } -void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_matrix) { +void GLRenderer_Model(br_actor* actor, br_model* model, br_matrix34 model_matrix) { tStored_model_context* ctx; ctx = model->stored; v11model* v11 = model->prepared; @@ -533,6 +485,7 @@ void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_ if (ctx == NULL) { build_model(model); ctx = model->stored; + // DebugCamera_SetPosition(model_matrix.m[3][0], model_matrix.m[3][1], model_matrix.m[3][2]); } CHECK_GL_ERROR("rm1"); diff --git a/src/harness/sdl/gl_renderer.h b/src/harness/renderers/gl/gl_renderer.h similarity index 69% rename from src/harness/sdl/gl_renderer.h rename to src/harness/renderers/gl/gl_renderer.h index 54dc76f7..656da0a6 100644 --- a/src/harness/sdl/gl_renderer.h +++ b/src/harness/renderers/gl/gl_renderer.h @@ -2,7 +2,6 @@ #define HARNESS_GL_RENDERER #include "harness.h" -#include #define CHECK_GL_ERROR(msg) \ { \ @@ -12,15 +11,15 @@ } \ } -void GLRenderer_CreateWindow(char* title, int width, int height, int render_width, int render_height); +void GLRenderer_Init(int width, int height, int render_width, int render_height); void GLRenderer_SetPalette(uint8_t* rgba_colors); void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer); void GLRenderer_EndScene(); -void GLRenderer_RenderFullScreenQuad(uint8_t* screen_buffer, int width, int height); -void GLRenderer_Swap(); -void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_matrix); +void GLRenderer_FullScreenQuad(uint8_t* screen_buffer, int width, int height); +void GLRenderer_Model(br_actor* actor, br_model* model, br_matrix34 model_matrix); void GLRenderer_BufferTexture(br_pixelmap* pm); void GLRenderer_BufferMaterial(br_material* mat); +void GLRenderer_ClearBuffers(); void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); #endif \ No newline at end of file diff --git a/src/harness/sdl/gl_renderer_shaders.c b/src/harness/renderers/gl/shaders.c similarity index 100% rename from src/harness/sdl/gl_renderer_shaders.c rename to src/harness/renderers/gl/shaders.c diff --git a/src/harness/sdl/gl_renderer_shaders.h b/src/harness/renderers/gl/shaders.h similarity index 100% rename from src/harness/sdl/gl_renderer_shaders.h rename to src/harness/renderers/gl/shaders.h diff --git a/src/harness/sdl/gl_brender_stored_context.c b/src/harness/renderers/gl/stored_context.c similarity index 93% rename from src/harness/sdl/gl_brender_stored_context.c rename to src/harness/renderers/gl/stored_context.c index 4b886400..3bdf2ce7 100644 --- a/src/harness/sdl/gl_brender_stored_context.c +++ b/src/harness/renderers/gl/stored_context.c @@ -1,10 +1,11 @@ -#include "gl_brender_stored_context.h" +#include "stored_context.h" #include "../include/harness/trace.h" #include void _free(br_object* o) { tStored_model_context* ctx = (tStored_model_context*)o; glDeleteVertexArrays(1, &ctx->vao_id); + glDeleteBuffers(1, &ctx->vbo_id); glDeleteBuffers(1, &ctx->ebo_id); free(o); } diff --git a/src/harness/sdl/gl_brender_stored_context.h b/src/harness/renderers/gl/stored_context.h similarity index 93% rename from src/harness/sdl/gl_brender_stored_context.h rename to src/harness/renderers/gl/stored_context.h index 9665a070..3f134399 100644 --- a/src/harness/sdl/gl_brender_stored_context.h +++ b/src/harness/renderers/gl/stored_context.h @@ -6,7 +6,7 @@ typedef struct tStored_model_context { br_object_dispatch* dispatch; - GLuint vao_id, ebo_id; + GLuint vao_id, vbo_id, ebo_id; } tStored_model_context; typedef struct tStored_pixelmap { diff --git a/src/harness/platforms/null.h b/src/harness/renderers/null.h similarity index 64% rename from src/harness/platforms/null.h rename to src/harness/renderers/null.h index 149e4259..88737bfa 100644 --- a/src/harness/platforms/null.h +++ b/src/harness/renderers/null.h @@ -1,33 +1,25 @@ -#include "harness.h" +#include "renderer.h" void Null_Init() {} -void Null_CreateWindow(char* title, int width, int height, int render_width, int render_height) {} -void Null_PollEvents() {} -int* Null_GetKeyMap() { return NULL; } -int Null_IsKeyDown(unsigned char pScan_code) { return 0; } void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {} void Null_EndFrame() {} void Null_SetPalette(uint8_t* palette) {} void Null_RenderFullScreenQuad(uint8_t* src, int width, int height) {} void Null_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_matrix) {} void Null_RenderFrameBuffer() {} -void Null_Swap() {} +void Null_ClearBuffers() {} void Null_BufferTexture(br_pixelmap* pm) {} void Null_BufferMaterial(br_material* mat) {} void Null_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {} -tPlatform null_platform = { +tRenderer null_renderer = { Null_Init, - Null_CreateWindow, - Null_PollEvents, - Null_GetKeyMap, - Null_IsKeyDown, Null_BeginFrame, Null_EndFrame, Null_SetPalette, Null_RenderFullScreenQuad, Null_RenderModel, - Null_Swap, + Null_ClearBuffers, Null_BufferTexture, Null_BufferMaterial, Null_FlushBuffers diff --git a/src/harness/renderers/renderer.h b/src/harness/renderers/renderer.h new file mode 100644 index 00000000..7c8936d6 --- /dev/null +++ b/src/harness/renderers/renderer.h @@ -0,0 +1,20 @@ +#ifndef HARNESS_RENDERER_H +#define HARNESS_RENDERER_H + +#include "brender/br_types.h" + +typedef struct tRenderer { + void (*Init)(int width, int height, int pRender_width, int pRender_height); + void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer); + void (*EndScene)(); + void (*SetPalette)(uint8_t* palette); + void (*FullScreenQuad)(uint8_t* src, int width, int height); + void (*Model)(br_actor* actor, br_model* model, br_matrix34 model_matrix); + void (*ClearBuffers)(); + void (*BufferTexture)(br_pixelmap* pm); + void (*BufferMaterial)(br_material* mat); + void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); + +} tRenderer; + +#endif \ No newline at end of file diff --git a/src/harness/sdl/common.h b/src/harness/sdl/common.h deleted file mode 100644 index 493310a2..00000000 --- a/src/harness/sdl/common.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SDL_PLATFORM_H -#define SDL_PLATFORM_H - -#include "harness.h" - -void SDLPlatform_Init(); -void SDLPlatform_PollEvents(); -int* SDLPlatform_GetKeyMap(); -int SDLPlatform_IsKeyDown(unsigned char scan_code); - -#endif \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5863e66e..1dbf5950 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,8 @@ add_executable(dethrace_test) add_test(NAME test_dethrace COMMAND dethrace_test) +set(IO_PLATFORM "SDL_OpenGL") + target_link_libraries(dethrace_test PRIVATE glad dethrace_obj) target_include_directories(dethrace_test PRIVATE diff --git a/test/DETHRACE/test_controls.c b/test/DETHRACE/test_controls.c index d8251db2..4e7ffd5a 100644 --- a/test/DETHRACE/test_controls.c +++ b/test/DETHRACE/test_controls.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "tests.h" @@ -24,7 +23,7 @@ void test_controls_CheckKevKeys() { gKeys_pressed = 0; result = KevKeyService(); } - sleep_s(2); + OS_Sleep(2000); gKeys_pressed = 0; CheckKevKeys(); diff --git a/test/DETHRACE/test_dossys.c b/test/DETHRACE/test_dossys.c index 251f3862..35109274 100644 --- a/test/DETHRACE/test_dossys.c +++ b/test/DETHRACE/test_dossys.c @@ -1,7 +1,6 @@ #include "tests.h" #include -#include #include "common/globvars.h" #include "pd/sys.h" diff --git a/test/DETHRACE/test_errors.c b/test/DETHRACE/test_errors.c index 7e36b54e..01866c45 100644 --- a/test/DETHRACE/test_errors.c +++ b/test/DETHRACE/test_errors.c @@ -5,7 +5,7 @@ #include void test_errors_FatalError() { - FatalError(0x6c, "test_errors", "FATAL"); + FatalError(107, "test_errors", "FATAL"); TEST_ASSERT_EQUAL_STRING("Can't open 'test_errors'", _unittest_last_fatal_error); } diff --git a/test/DETHRACE/test_input.c b/test/DETHRACE/test_input.c index ce471f42..85525d81 100644 --- a/test/DETHRACE/test_input.c +++ b/test/DETHRACE/test_input.c @@ -3,7 +3,6 @@ #include "common/globvars.h" #include "common/input.h" #include -#include void test_input_KevKeyService() { int i; @@ -15,7 +14,7 @@ void test_input_KevKeyService() { gKeys_pressed = 0; result = KevKeyService(); } - sleep_s(2); + OS_Sleep(2000); gKeys_pressed = 0; result = KevKeyService(); diff --git a/test/DETHRACE/test_loading.c b/test/DETHRACE/test_loading.c index b0d37a17..11c34805 100644 --- a/test/DETHRACE/test_loading.c +++ b/test/DETHRACE/test_loading.c @@ -1,7 +1,6 @@ #include "tests.h" #include -#include #include "CORE/PIXELMAP/pixelmap.h" #include "common/globvars.h" diff --git a/test/DETHRACE/test_powerup.c b/test/DETHRACE/test_powerup.c index 7bab01a6..e9461b4f 100644 --- a/test/DETHRACE/test_powerup.c +++ b/test/DETHRACE/test_powerup.c @@ -1,7 +1,6 @@ #include "tests.h" #include -#include #include "common/globvars.h" #include "common/powerup.h" diff --git a/test/main.c b/test/main.c index 757dd78f..7599b952 100644 --- a/test/main.c +++ b/test/main.c @@ -1,4 +1,5 @@ #include "harness/hooks.h" +#include "harness/os.h" #include "tests.h" #include #include @@ -6,7 +7,6 @@ #include #include #include -#include #define UNITY_USE_COMMAND_LINE_ARGS 1 @@ -15,6 +15,7 @@ #include "CORE/PIXELMAP/pixelmap.h" #include "CORE/V1DB/actsupt.h" #include "CORE/V1DB/dbsetup.h" +#include "common/errors.h" #include "common/newgame.h" #include "common/utility.h" @@ -23,6 +24,7 @@ #include "common/grafdata.h" #include "harness.h" #include "harness/config.h" +#include "harness/os.h" #define debug(format_, ...) fprintf(stderr, format_, __VA_ARGS__) @@ -167,6 +169,8 @@ void setup_global_vars(int argc, char* argv[]) { strcpy(gBasic_car_names[0], "BLKEAGLE.TXT"); + OpenDiagnostics(); + setup_temp_folder(); printf("INFO: temp folder is \"%s\"\n", temp_folder); @@ -182,20 +186,14 @@ void setup_global_vars(int argc, char* argv[]) { fake_argv[fake_argc++] = "--no-signal-handler"; } Harness_Init(&fake_argc, fake_argv); + + Harness_ForceNullRenderer(); } int has_data_directory() { return root_dir != NULL; } -void sleep_s(int sec) { -#ifdef _WIN32 - Sleep(1000 * sec); -#else - sleep(sec); -#endif -} - void create_temp_file(char buffer[PATH_MAX + 1], const char* prefix) { #ifdef _WIN32 DWORD attributes; diff --git a/test/tests.h b/test/tests.h index 75aeb9f5..2ef52ac1 100644 --- a/test/tests.h +++ b/test/tests.h @@ -2,6 +2,7 @@ #define TESTS_H #include "framework/unity.h" +#include "harness/os.h" #include "harness/trace.h" #ifndef PATH_MAX @@ -14,23 +15,23 @@ #define HOST_NL "\n" #endif -void TEST_ASSERT_EQUAL_FILE_CONTENTS_BINARY(const uint8_t *expected, char *filename, int len); -void TEST_ASSERT_EQUAL_FILE_TEXT(const char *expected, char *filename); +void TEST_ASSERT_EQUAL_FILE_CONTENTS_BINARY(const uint8_t* expected, char* filename, int len); +void TEST_ASSERT_EQUAL_FILE_TEXT(const char* expected, char* filename); extern int has_data_directory(); -extern void sleep_s(int sec); -void create_temp_file(char buffer[PATH_MAX+1], const char *prefix); +void create_temp_file(char buffer[PATH_MAX + 1], const char* prefix); #define REQUIRES_DATA_DIRECTORY() \ if (!has_data_directory()) \ TEST_IGNORE(); -#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) do { \ - float *priv_expected = (float*)(expected); \ - float *priv_actual = (float*)(actual); \ - for(int it = (num_elements); it != 0; --it, ++priv_expected, ++priv_actual) { \ - TEST_ASSERT_FLOAT_WITHIN((delta), *priv_expected, *priv_actual); \ - } \ -} while (0) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) \ + do { \ + float* priv_expected = (float*)(expected); \ + float* priv_actual = (float*)(actual); \ + for (int it = (num_elements); it != 0; --it, ++priv_expected, ++priv_actual) { \ + TEST_ASSERT_FLOAT_WITHIN((delta), *priv_expected, *priv_actual); \ + } \ + } while (0) #endif