Implements win95sys.c (#301)

* refactor to use win95sys instead of dossys

* added underscore to avoid conflict with windows functions
This commit is contained in:
Dethrace Engineering Department 2023-04-18 22:50:05 +12:00 committed by GitHub
parent d4fb64029a
commit ef9e4d668d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 2995 additions and 1584 deletions

View File

@ -5,13 +5,9 @@
Assuming an operating system called _foo_, follow the steps to add support for it. 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](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/include/harness/os.h): 1. Add a new file `os/foo.h` and implement the required functions defined in [os.h](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/include/harness/os.h):
- `OS_GetTime`
- `OS_Sleep`
- `OS_Basename`
- `OS_GetFirstFileInDirectory`
- `OS_GetNextFileInDirectory`
- `OS_IsDebuggerPresent`
- `OS_InstallSignalHandler` - `OS_InstallSignalHandler`
- `OS_fopen`
- `OS_ConsoleReadPassword`
2. Update `src/harness/CMakeLists.h` and add a new conditional section for "os/foo.h", based on existing conditions for Windows, MacOS etc. 2. Update `src/harness/CMakeLists.h` and add a new conditional section for "os/foo.h", based on existing conditions for Windows, MacOS etc.
@ -28,24 +24,13 @@ target_sources(harness PRIVATE
## IO Platform (windowing / input / rendering) ## IO Platform (windowing / input / rendering)
An `IOPlatform` in _dethrace_ implements windowing and input handling, and points to a _renderer_. A `Platform` in _dethrace_ implements windowing, rendering and input handling.
The default IO platform is `SDL_OpenGL`, which uses SDL for windowing and input, and OpenGL for rendering. See [io_platforms/sdl_gl.c](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/io_platforms/sdl_gl.c). The default platform is `SDL_OpenGL`, which uses SDL for windowing and input, and OpenGL for rendering. See [platforms/sdl_opengl.c](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl_opengl.c).
To add a new `IOPlatform`: To add a new `Platform`:
1. Create `io_platforms/my_platform.c` file and implement the required functions defined in [io_platforms/io_platform.h](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/io_platforms/io_platform.h): 1. Create `platforms/my_platform.c` file and add a `Harness_Platform_Init` function. Hook up all the function pointers using the `sdl_opengl` [implementation](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/platforms/sdl_opengl.h) as a guide.
- `IOPlatform_Init`
- `IOPlatform_CreateWindow`
- `IOPlatform_PollEvents`
- `IOPlatform_SwapWindow`
- `IOPlatform_GetKeyMap`
- `IOPlatform_IsKeyDown`
- `IOPlatform_GetMousePosition`
- `IOPlatform_GetMouseButtons`
- `IOPlatform_Shutdown`
`IOPlatform_CreateWindow` returns a `tRenderer*`, which must implement the interface defined in [renderers/renderer.h](https://github.com/dethrace-labs/dethrace/blob/main/src/harness/renderers/renderer.h). See [renderers/gl](https://github.com/dethrace-labs/dethrace/tree/main/src/harness/renderers/gl) for an example.
2. Add a new conditional section in `src/harness/CMakeLists.txt` for your new platform 2. Add a new conditional section in `src/harness/CMakeLists.txt` for your new platform

View File

@ -72,12 +72,12 @@ void BrDevEndOld() {
// IDA: void __cdecl BrDevPaletteSetOld(br_pixelmap *pm) // IDA: void __cdecl BrDevPaletteSetOld(br_pixelmap *pm)
void BrDevPaletteSetOld(br_pixelmap* pm) { void BrDevPaletteSetOld(br_pixelmap* pm) {
Harness_Hook_BrDevPaletteSetOld(pm); NOT_IMPLEMENTED();
} }
// IDA: void __cdecl BrDevPaletteSetEntryOld(int i, br_colour colour) // IDA: void __cdecl BrDevPaletteSetEntryOld(int i, br_colour colour)
void BrDevPaletteSetEntryOld(int i, br_colour colour) { void BrDevPaletteSetEntryOld(int i, br_colour colour) {
Harness_Hook_BrDevPaletteSetEntryOld(i, colour); NOT_IMPLEMENTED();
} }
// IDA: br_error __cdecl BrRendererFacilityFind(br_renderer_facility **prf, br_device_pixelmap *destination, br_token scalar_type) // IDA: br_error __cdecl BrRendererFacilityFind(br_renderer_facility **prf, br_device_pixelmap *destination, br_token scalar_type)

View File

@ -11,9 +11,13 @@ void BrMapUpdate(br_pixelmap* map, br_uint_16 flags) {
void BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags) { void BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags) {
br_token_value tv[3]; br_token_value tv[3];
Harness_Hook_BrBufferUpdate(pm, use, flags);
// renderer->dispatch->bufferStoredNew ... // renderer->dispatch->bufferStoredNew ...
// Added by dethrace
if (use != BRT_COLOUR_MAP_O && use != BRT_UNKNOWN) {
LOG_PANIC("use %d", use);
}
gHarness_platform.Renderer_BufferTexture(pm);
} }
// IDA: void __usercall BrBufferClear(br_pixelmap *pm@<EAX>) // IDA: void __usercall BrBufferClear(br_pixelmap *pm@<EAX>)

View File

@ -9,9 +9,10 @@ void BrMaterialUpdate(br_material* mat, br_uint_16 flags) {
br_token t; br_token t;
br_int_32 c; br_int_32 c;
//TODO: ? // TODO: ?
Harness_Hook_BrMaterialUpdate(mat, flags); // Added by dethrace
gHarness_platform.Renderer_BufferMaterial(mat);
} }
// IDA: void __usercall BrMaterialClear(br_material *mat@<EAX>) // IDA: void __usercall BrMaterialClear(br_material *mat@<EAX>)

View File

@ -700,7 +700,8 @@ void BrModelUpdate(br_model* model, br_uint_16 flags) {
model->stored = NULL; model->stored = NULL;
} }
Harness_Hook_BrModelUpdate(model); // Added by dethrace
gHarness_platform.Renderer_BufferModel(model);
} }
// IDA: void __usercall BrModelClear(br_model *model@<EAX>) // IDA: void __usercall BrModelClear(br_model *model@<EAX>)

View File

@ -269,13 +269,13 @@ void BrDbSceneRenderBegin(br_actor* world, br_actor* camera) {
// this is not complete // this is not complete
STUB_ONCE(); STUB_ONCE();
/* /*
* Collect transforms from camera to root * Collect transforms from camera to root
* *
* Make a stack of cumulative transforms for each level between * Make a stack of cumulative transforms for each level between
* the camera and the root - this is so that model->view * the camera and the root - this is so that model->view
* transforms can use the shortest route, rather than via the root * transforms can use the shortest route, rather than via the root
*/ */
for (i = 0; i < BR_ASIZE(v1db.camera_path); i++) { for (i = 0; i < BR_ASIZE(v1db.camera_path); i++) {
v1db.camera_path[i].a = NULL; v1db.camera_path[i].a = NULL;
} }
@ -323,7 +323,7 @@ void BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour
// LOG_TRACE("(%p, %p, %p, %p)", world, camera, colour_buffer, depth_buffer); // LOG_TRACE("(%p, %p, %p, %p)", world, camera, colour_buffer, depth_buffer);
BrDbSceneRenderBegin(world, camera); BrDbSceneRenderBegin(world, camera);
Harness_Hook_BrZbSceneRenderBegin(world, camera, colour_buffer, depth_buffer); gHarness_platform.Renderer_BeginScene(camera, colour_buffer, depth_buffer);
} }
// IDA: void __cdecl BrZbSceneRenderAdd(br_actor *tree) // IDA: void __cdecl BrZbSceneRenderAdd(br_actor *tree)
@ -335,7 +335,9 @@ void BrZbSceneRenderAdd(br_actor* tree) {
// IDA: void __cdecl BrZbSceneRenderEnd() // IDA: void __cdecl BrZbSceneRenderEnd()
void BrZbSceneRenderEnd() { void BrZbSceneRenderEnd() {
// LOG_TRACE("()"); // LOG_TRACE("()");
Harness_Hook_BrZbSceneRenderEnd();
gHarness_platform.Renderer_FlushBuffers();
gHarness_platform.Renderer_EndScene();
} }
// IDA: void __cdecl BrZbSceneRender(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, br_pixelmap *depth_buffer) // IDA: void __cdecl BrZbSceneRender(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, br_pixelmap *depth_buffer)

View File

@ -13,7 +13,6 @@ target_include_directories(dethrace_obj
target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smacker harness brender s3) target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smacker harness brender s3)
if (CMAKE_C_COMPILER_ID MATCHES "MSVC") if (CMAKE_C_COMPILER_ID MATCHES "MSVC")
target_compile_definitions(dethrace_obj PRIVATE -D_CRT_SECURE_NO_WARNINGS) target_compile_definitions(dethrace_obj PRIVATE -D_CRT_SECURE_NO_WARNINGS)
target_compile_options(dethrace_obj PRIVATE target_compile_options(dethrace_obj PRIVATE
@ -158,6 +157,10 @@ target_sources(dethrace_obj PRIVATE
pd/net.h pd/net.h
pc-dos/dossys.c pc-dos/dossys.c
pd/sys.h pd/sys.h
pc-win95/win95sys.c
pc-win95/dinput.h
pc-win95/ssdx.c
pc-win95/ssdx.h
) )
# Create our main game binary. # Create our main game binary.

View File

@ -6,6 +6,7 @@
#include "globvrpb.h" #include "globvrpb.h"
#include "graphics.h" #include "graphics.h"
#include "harness/config.h" #include "harness/config.h"
#include "harness/hooks.h"
#include "harness/os.h" #include "harness/os.h"
#include "harness/trace.h" #include "harness/trace.h"
#include "input.h" #include "input.h"
@ -72,7 +73,7 @@ void PlaySmackerFile(char* pSmack_name) {
unsigned long w, h, f; unsigned long w, h, f;
unsigned char r, g, b; unsigned char r, g, b;
double usf; double usf;
struct timespec ts; tU32 last_frame_time;
if (!gSound_override && !gCut_scene_override) { if (!gSound_override && !gCut_scene_override) {
StopMusic(); StopMusic();
@ -126,12 +127,16 @@ void PlaySmackerFile(char* pSmack_name) {
} }
} }
PDScreenBufferSwap(0); PDScreenBufferSwap(0);
last_frame_time = PDGetTotalTime();
if (AnyKeyDown() || EitherMouseButtonDown()) { do {
fuck_off = AnyKeyDown() || EitherMouseButtonDown();
// added by dethrace to avoid 100% cpu
gHarness_platform.Sleep(1);
} while (!fuck_off && PDGetTotalTime() - last_frame_time < delay_ms);
if (fuck_off) {
break; break;
} }
// wait until its time for the next frame
OS_Sleep(delay_ms);
} while (smk_next(s) == SMK_MORE); } while (smk_next(s) == SMK_MORE);
smk_close(s); smk_close(s);

View File

@ -2,15 +2,15 @@
#define _ERRORS_H_ #define _ERRORS_H_
#include "brender/br_types.h" #include "brender/br_types.h"
#include "harness/compiler.h"
#include "dr_types.h" #include "dr_types.h"
#include "harness/compiler.h"
extern char* gError_messages[126]; extern char* gError_messages[126];
extern int gError_code; extern int gError_code;
extern char* gPalette_copy__errors; // suffix added to avoid duplicate symbol extern char* gPalette_copy__errors; // suffix added to avoid duplicate symbol
extern int gPixel_buffer_size__errors; // suffix added to avoid duplicate symbol extern int gPixel_buffer_size__errors; // suffix added to avoid duplicate symbol
extern int gMouse_was_started__errors; // suffix added to avoid duplicate symbol extern int gMouse_was_started__errors; // suffix added to avoid duplicate symbol
extern char* gPixels_copy__errors; // suffix added to avoid duplicate symbol extern char* gPixels_copy__errors; // suffix added to avoid duplicate symbol
HARNESS_NORETURN void FatalError(int pStr_index, ...); HARNESS_NORETURN void FatalError(int pStr_index, ...);

View File

@ -1136,12 +1136,12 @@ void DoBlack(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
the_row_bytes = pFlic_info->the_pixelmap->row_bytes; the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
the_width = pFlic_info->width; the_width = pFlic_info->width;
for (i = 0; i < pFlic_info->height; i++) { for (i = 0; i < pFlic_info->height; i++) {
line_pixel_ptr = (tU32*)pixel_ptr; line_pixel_ptr = (tU32*)pixel_ptr;
for (j = 0; j < the_width / sizeof(tU32); j++) { for (j = 0; j < the_width / sizeof(tU32); j++) {
*line_pixel_ptr = 0; *line_pixel_ptr = 0;
line_pixel_ptr++; line_pixel_ptr++;
} }
pixel_ptr += the_row_bytes; pixel_ptr += the_row_bytes;
} }
} }
@ -1268,7 +1268,7 @@ void DoUncompressedTrans(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
for (i = 0; i < pFlic_info->height; i++) { for (i = 0; i < pFlic_info->height; i++) {
line_pixel_ptr = pixel_ptr; line_pixel_ptr = pixel_ptr;
for (j = 0; j < the_width; j++) { for (j = 0; j < the_width; j++) {
#if defined (DETHRACE_FIX_BUGS) #if defined(DETHRACE_FIX_BUGS)
the_byte = MemReadU8(&pFlic_info->data); the_byte = MemReadU8(&pFlic_info->data);
#else #else
the_byte = MemReadU32(&pFlic_info->data); the_byte = MemReadU32(&pFlic_info->data);
@ -1465,13 +1465,13 @@ int PlayFlic(int pIndex, tU32 pSize, tS8* pData_ptr, br_pixelmap* pDest_pixelmap
gSound_time = 0; gSound_time = 0;
} }
if (frame_period >= the_flic.frame_period) { if (frame_period >= the_flic.frame_period) {
last_frame = new_time;
finished_playing = PlayNextFlicFrame(&the_flic); finished_playing = PlayNextFlicFrame(&the_flic);
DoPerFrame(); DoPerFrame();
if (!gDark_mode) { if (!gDark_mode) {
EnsurePaletteUp(); EnsurePaletteUp();
} }
ServiceGame(); ServiceGame();
last_frame = new_time;
} }
} }
ServiceGame(); ServiceGame();

View File

@ -637,7 +637,7 @@ void ScreenLarger() {
// IDA: void __usercall DRSetPaletteEntries(br_pixelmap *pPalette@<EAX>, int pFirst_colour@<EDX>, int pCount@<EBX>) // IDA: void __usercall DRSetPaletteEntries(br_pixelmap *pPalette@<EAX>, int pFirst_colour@<EDX>, int pCount@<EBX>)
void DRSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) { void DRSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) {
LOG_TRACE("(%p, %d, %d)", pPalette, pFirst_colour, pCount); LOG_TRACE("(%p, %d, %d)", pPalette, pFirst_colour, pCount);
if (!pFirst_colour) { if (pFirst_colour == 0) {
((br_int_32*)pPalette->pixels)[0] = 0; ((br_int_32*)pPalette->pixels)[0] = 0;
} }
memcpy(gCurrent_palette_pixels + 4 * pFirst_colour, (char*)pPalette->pixels + 4 * pFirst_colour, 4 * pCount); memcpy(gCurrent_palette_pixels + 4 * pFirst_colour, (char*)pPalette->pixels + 4 * pFirst_colour, 4 * pCount);
@ -1671,7 +1671,7 @@ void RenderAFrame(int pDepth_mask_on) {
RenderLollipops(); RenderLollipops();
// dethrace: must flush gpu buffer before rendering depth effect into framebuffer // dethrace: must flush gpu buffer before rendering depth effect into framebuffer
Harness_Hook_FlushRenderer(); gHarness_platform.Renderer_FlushBuffers();
DepthEffectSky(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world); DepthEffectSky(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world);
DepthEffect(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world); DepthEffect(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world);
if (!gAusterity_mode) { if (!gAusterity_mode) {
@ -1679,7 +1679,7 @@ void RenderAFrame(int pDepth_mask_on) {
} }
RenderSplashes(); RenderSplashes();
// dethrace: must flush gpu buffer before rendering smoke into framebuffer // dethrace: must flush gpu buffer before rendering smoke into framebuffer
Harness_Hook_FlushRenderer(); gHarness_platform.Renderer_FlushBuffers();
RenderSmoke(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); RenderSmoke(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period);
RenderSparks(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); RenderSparks(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period);
RenderProximityRays(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period); RenderProximityRays(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period);
@ -2574,10 +2574,10 @@ int DoMouseCursor() {
period = 1000; period = 1000;
} }
while (period <= 20) { while (period <= 20) {
// Sleep 1 ms to avoid 100% CPU usage
OS_Sleep(1);
this_call_time = PDGetTotalTime(); this_call_time = PDGetTotalTime();
period = this_call_time - last_call_time; period = this_call_time - last_call_time;
// added by dethrace to avoid 100% CPU usage
gHarness_platform.Sleep(1);
} }
GetMousePosition(&x_coord, &y_coord); GetMousePosition(&x_coord, &y_coord);
mouse_moved = x_coord != gMouse_last_x_coord || y_coord != gMouse_last_y_coord; mouse_moved = x_coord != gMouse_last_x_coord || y_coord != gMouse_last_y_coord;

View File

@ -362,6 +362,7 @@ void InitialiseApplication(int pArgc, char** pArgv) {
FatalError(kFatalError_UnsupportedScreenDepth); FatalError(kFatalError_UnsupportedScreenDepth);
} }
CalcGrafDataIndex(); CalcGrafDataIndex();
PDInitScreen();
InitializeBRenderEnvironment(); InitializeBRenderEnvironment();
InitDRFonts(); InitDRFonts();
InitBRFonts(); InitBRFonts();

View File

@ -46,6 +46,11 @@ br_vector3 gCamera_velocity;
// IDA: void __cdecl UsePathFileToDetermineIfFullInstallation() // IDA: void __cdecl UsePathFileToDetermineIfFullInstallation()
void UsePathFileToDetermineIfFullInstallation() { void UsePathFileToDetermineIfFullInstallation() {
// changed by dethrace for compatibility
// char line1[80];
// char line2[80];
// char line3[80];
// char path_file[80];
char line1[MAX_PATH_LENGTH]; char line1[MAX_PATH_LENGTH];
char line2[MAX_PATH_LENGTH]; char line2[MAX_PATH_LENGTH];
char line3[MAX_PATH_LENGTH]; char line3[MAX_PATH_LENGTH];

View File

@ -475,7 +475,7 @@ enum {
#define FONT_LITPLAQ1 19 #define FONT_LITPLAQ1 19
#define FONT_DRKPLAQ1 20 #define FONT_DRKPLAQ1 20
#define MAX_PATH_LENGTH 256 #define MAX_PATH_LENGTH 1024
#define ROLLING_LETTER_LOOP_RANDOM 96 #define ROLLING_LETTER_LOOP_RANDOM 96
#define PLAYER_NAME_MAX_LENGTH 13 #define PLAYER_NAME_MAX_LENGTH 13

View File

@ -11,35 +11,34 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 // #ifdef _WIN32
#include <windows.h> // #include <windows.h>
#else // #else
typedef short SHORT; // typedef short short;
typedef unsigned short USHORT; // typedef unsigned short unsigned short;
typedef int INT; // typedef int INT;
typedef int BOOL; // typedef int BOOL;
typedef unsigned int UINT; // typedef unsigned int UINT;
typedef unsigned char BYTE; // typedef unsigned char unsigned char;
typedef unsigned short WORD; // typedef unsigned short WORD;
typedef long LONG; // typedef long long;
typedef unsigned long DWORD; // typedef unsigned long unsigned long;
typedef BYTE* PBYTE; // typedef unsigned char* Punsigned char;
typedef char* PSTR; // typedef char* char*;
typedef WORD* PWORD; // typedef WORD* PWORD;
typedef unsigned short* PSHORT; // typedef unsigned short* Pshort;
typedef LONG* PLONG; // typedef long* Plong;
typedef void* PVOID; // typedef void* PVOID;
typedef BYTE* LPBYTE; // typedef unsigned char* LPunsigned char;
typedef BYTE* LPSTR; // typedef unsigned char* Lchar*;
typedef WORD* LPWORD; // typedef WORD* LPWORD;
typedef LONG* LPLONG; // typedef long* LPlong;
typedef void* LPVOID; // typedef void* LPVOID;
typedef BYTE* HPBYTE; // typedef unsigned char* HPunsigned char;
typedef BYTE* HPSTR; // typedef unsigned char* Hchar*;
typedef LONG* HPLONG; // typedef long* HPlong;
typedef void* HPVOID; // typedef void* HPVOID;
typedef unsigned int HANDLE; // #endif
#endif
typedef unsigned int W32; typedef unsigned int W32;
typedef unsigned short W16; typedef unsigned short W16;
typedef W32* LPW32; typedef W32* LPW32;
@ -534,27 +533,27 @@ typedef struct _HMI_REGS {
} _HMI_REGS; } _HMI_REGS;
typedef struct _tagIPX_HEADER { typedef struct _tagIPX_HEADER {
USHORT wChecksum; unsigned short wChecksum;
USHORT wLength; unsigned short wLength;
BYTE bTransportControl; unsigned char bTransportControl;
BYTE bPacketType; unsigned char bPacketType;
BYTE bDestNetworkNumber[4]; unsigned char bDestNetworkNumber[4];
BYTE bDestNetworkNode[6]; unsigned char bDestNetworkNode[6];
USHORT wDestNetworkSocket; unsigned short wDestNetworkSocket;
BYTE bSourceNetworkNumber[4]; unsigned char bSourceNetworkNumber[4];
BYTE bSourceNetworkNode[6]; unsigned char bSourceNetworkNode[6];
USHORT wSourceNetworkSocket; unsigned short wSourceNetworkSocket;
} _IPX_HEADER; } _IPX_HEADER;
typedef struct _PACKET { typedef struct _PACKET {
PSTR pData; char* pData;
USHORT wLength; unsigned short wLength;
} _PACKET; } _PACKET;
typedef struct _REAL_PACKET { typedef struct _REAL_PACKET {
SHORT wOffset; short wOffset;
SHORT wSegment; short wSegment;
USHORT wLength; unsigned short wLength;
} _REAL_PACKET; } _REAL_PACKET;
typedef struct _ECB_PACKET { typedef struct _ECB_PACKET {
@ -563,52 +562,52 @@ typedef struct _ECB_PACKET {
} _ECB_PACKET; } _ECB_PACKET;
typedef struct _tagIPX_ECB { typedef struct _tagIPX_ECB {
PSTR pLinkAddress; char* pLinkAddress;
PSTR pESRRoutine; char* pESRRoutine;
BYTE bInUse; unsigned char bInUse;
BYTE bCompletionCode; unsigned char bCompletionCode;
USHORT wSocket; unsigned short wSocket;
USHORT wConnectionID; unsigned short wConnectionID;
USHORT wWorkSpace; unsigned short wWorkSpace;
BYTE bDriverWorkSpace[12]; unsigned char bDriverWorkSpace[12];
BYTE bImmediateAddress[6]; unsigned char bImmediateAddress[6];
USHORT wPacketCount; unsigned short wPacketCount;
_ECB_PACKET sPacket[2]; _ECB_PACKET sPacket[2];
} _IPX_ECB; } _IPX_ECB;
typedef struct _tagIPX_INTERNET_ADDR { typedef struct _tagIPX_INTERNET_ADDR {
BYTE bNetwork[4]; unsigned char bNetwork[4];
BYTE bNode[6]; unsigned char bNode[6];
} _IPX_INTERNET_ADDR; } _IPX_INTERNET_ADDR;
typedef struct _tagIPX_NETWORK_ADDR { typedef struct _tagIPX_NETWORK_ADDR {
_IPX_INTERNET_ADDR sInternetAddr; _IPX_INTERNET_ADDR sInternetAddr;
BYTE bSocket[2]; unsigned char bSocket[2];
} _IPX_NETWORK_ADDR; } _IPX_NETWORK_ADDR;
typedef struct _tagIPX_LOCAL_TARGET { typedef struct _tagIPX_LOCAL_TARGET {
_IPX_INTERNET_ADDR sInternetAddr; _IPX_INTERNET_ADDR sInternetAddr;
BYTE bImmediate[6]; unsigned char bImmediate[6];
} _IPX_LOCAL_TARGET; } _IPX_LOCAL_TARGET;
typedef struct _tagIPX_ELEMENT { typedef struct _tagIPX_ELEMENT {
USHORT wFlags; unsigned short wFlags;
USHORT wOffset; unsigned short wOffset;
_IPX_HEADER sHeader; _IPX_HEADER sHeader;
_IPX_ECB sECB; _IPX_ECB sECB;
_IPX_ECB* pECB; _IPX_ECB* pECB;
_IPX_HEADER* pIPXHeader; _IPX_HEADER* pIPXHeader;
PSTR pHeader; char* pHeader;
USHORT wHSize; unsigned short wHSize;
} _IPX_ELEMENT; } _IPX_ELEMENT;
typedef struct _PROT_PTR { typedef struct _PROT_PTR {
PSTR pData; char* pData;
} _PROT_PTR; } _PROT_PTR;
typedef struct _REAL_PTR { typedef struct _REAL_PTR {
SHORT wOffset; short wOffset;
SHORT wSegment; short wSegment;
} _REAL_PTR; } _REAL_PTR;
typedef struct _PTR { typedef struct _PTR {
@ -617,68 +616,68 @@ typedef struct _PTR {
} _PTR; } _PTR;
typedef struct _tag_NETBIOS_NCB { typedef struct _tag_NETBIOS_NCB {
BYTE bCommand; unsigned char bCommand;
BYTE bReturnCode; unsigned char bReturnCode;
BYTE bLocalSession; unsigned char bLocalSession;
BYTE bNetworkNameNumber; unsigned char bNetworkNameNumber;
_PTR sPtr; _PTR sPtr;
USHORT wLength; unsigned short wLength;
BYTE bCallName[16]; unsigned char bCallName[16];
BYTE bName[16]; unsigned char bName[16];
BYTE bReceiveTimeOut; unsigned char bReceiveTimeOut;
BYTE bSendTimeOut; unsigned char bSendTimeOut;
PSTR pPostFunction; char* pPostFunction;
BYTE bAdapter; unsigned char bAdapter;
BYTE bCompletionCode; unsigned char bCompletionCode;
BYTE bReserve[14]; unsigned char bReserve[14];
} _NETBIOS_NCB; } _NETBIOS_NCB;
typedef struct _tagNETBIOS_ADAPTER_STATUS { typedef struct _tagNETBIOS_ADAPTER_STATUS {
BYTE bCardID[6]; unsigned char bCardID[6];
BYTE bReleaseLevel; unsigned char bReleaseLevel;
BYTE bReserved1; unsigned char bReserved1;
BYTE bTypeOfAdapter; unsigned char bTypeOfAdapter;
BYTE bOldOrNewParameters; unsigned char bOldOrNewParameters;
USHORT wReportingPeriodMinutes; unsigned short wReportingPeriodMinutes;
USHORT wFrameRejectReceivedCount; unsigned short wFrameRejectReceivedCount;
USHORT wFrameRejectSentCount; unsigned short wFrameRejectSentCount;
USHORT wReceivedDataFrameErrors; unsigned short wReceivedDataFrameErrors;
USHORT wUnsuccessfulTransmissions; unsigned short wUnsuccessfulTransmissions;
LONG dwGoodTransmissions; long dwGoodTransmissions;
LONG dwGoodReceptions; long dwGoodReceptions;
USHORT wRetransmissions; unsigned short wRetransmissions;
USHORT wExhaustedResourceCount; unsigned short wExhaustedResourceCount;
USHORT wT1TimerExpiredCount; unsigned short wT1TimerExpiredCount;
USHORT wTITimerExpiredCount; unsigned short wTITimerExpiredCount;
BYTE bReserved2[4]; unsigned char bReserved2[4];
USHORT wAvailableNCBS; unsigned short wAvailableNCBS;
USHORT wMaxNCBSConfigured; unsigned short wMaxNCBSConfigured;
USHORT wMaxNCBSPossible; unsigned short wMaxNCBSPossible;
USHORT wBufferOrStationBusyCount; unsigned short wBufferOrStationBusyCount;
USHORT wMaxDatagramSize; unsigned short wMaxDatagramSize;
USHORT wPendingSessions; unsigned short wPendingSessions;
USHORT wMaxSessionsConfigured; unsigned short wMaxSessionsConfigured;
USHORT wMaxSessionsPossible; unsigned short wMaxSessionsPossible;
USHORT wMaxFrameSize; unsigned short wMaxFrameSize;
USHORT wNameCount; unsigned short wNameCount;
struct { struct {
BYTE bName[16]; unsigned char bName[16];
BYTE bNameNumber; unsigned char bNameNumber;
BYTE bNameStatus; unsigned char bNameStatus;
} sNameTable[20]; } sNameTable[20];
} _NETBIOS_ADAPTER_STATUS; } _NETBIOS_ADAPTER_STATUS;
typedef struct _tagNETBIOS_ELEMENT { typedef struct _tagNETBIOS_ELEMENT {
USHORT wFlags; unsigned short wFlags;
USHORT wOffset; unsigned short wOffset;
_NETBIOS_NCB sNCB; _NETBIOS_NCB sNCB;
_NETBIOS_NCB* pNCB; _NETBIOS_NCB* pNCB;
PSTR pHeader; char* pHeader;
USHORT wHSize; unsigned short wHSize;
} _NETBIOS_ELEMENT; } _NETBIOS_ELEMENT;
typedef struct _tagNETBIOS_LOCAL_TARGET { typedef struct _tagNETBIOS_LOCAL_TARGET {
BYTE bNode[16]; unsigned char bNode[16];
} _NETBIOS_LOCAL_TARGET; } _NETBIOS_LOCAL_TARGET;
typedef struct _tagXFER_BLOCK_HEADER { typedef struct _tagXFER_BLOCK_HEADER {
@ -2793,40 +2792,40 @@ typedef struct _tag_sos_vds_struct {
} _SOS_VDS_STRUCT; } _SOS_VDS_STRUCT;
typedef struct _tag_sos_sample { typedef struct _tag_sos_sample {
PSTR pSample; char* pSample;
PSTR pSampleCurrent; char* pSampleCurrent;
PSTR pSampleLoop; char* pSampleLoop;
DWORD wLength; unsigned long wLength;
DWORD wLoopLength; unsigned long wLoopLength;
DWORD wLoopEndLength; unsigned long wLoopEndLength;
DWORD wLoopStage; unsigned long wLoopStage;
DWORD wID; unsigned long wID;
DWORD wFlags; unsigned long wFlags;
DWORD wPriority; unsigned long wPriority;
DWORD hSample; unsigned long hSample;
DWORD wVolume; unsigned long wVolume;
DWORD wLoopCount; unsigned long wLoopCount;
DWORD wRate; unsigned long wRate;
DWORD wBitsPerSample; unsigned long wBitsPerSample;
DWORD wChannels; unsigned long wChannels;
DWORD wFormat; unsigned long wFormat;
DWORD wPanPosition; unsigned long wPanPosition;
DWORD wPanSpeed; unsigned long wPanSpeed;
DWORD wPanStart; unsigned long wPanStart;
DWORD wPanEnd; unsigned long wPanEnd;
DWORD wPanMode; unsigned long wPanMode;
DWORD wTotalBytesProcessed; unsigned long wTotalBytesProcessed;
void (*pfnSampleProcessed)(PSOSSAMPLE*); void (*pfnSampleProcessed)(PSOSSAMPLE*);
void (*pfnSampleDone)(PSOSSAMPLE*); void (*pfnSampleDone)(PSOSSAMPLE*);
void (*pfnSampleLoop)(PSOSSAMPLE*); void (*pfnSampleLoop)(PSOSSAMPLE*);
DWORD wSystem[16]; unsigned long wSystem[16];
DWORD wUser[16]; unsigned long wUser[16];
PSOSSAMPLE* pLink; PSOSSAMPLE* pLink;
PSOSSAMPLE* pNext; PSOSSAMPLE* pNext;
} _SOS_SAMPLE; } _SOS_SAMPLE;
typedef struct _tagCAPABILITIES { typedef struct _tagCAPABILITIES {
BYTE szDeviceName[32]; unsigned char szDeviceName[32];
W32 wDeviceVersion; W32 wDeviceVersion;
W32 wBitsPerSample; W32 wBitsPerSample;
W32 wChannels; W32 wChannels;
@ -2853,35 +2852,35 @@ typedef struct _SOS_HARDWARE {
typedef struct _tag_sos_driver { typedef struct _tag_sos_driver {
W32 wFlags; W32 wFlags;
DWORD wDriverRate; unsigned long wDriverRate;
DWORD wDriverChannels; unsigned long wDriverChannels;
DWORD wDriverBitsPerSample; unsigned long wDriverBitsPerSample;
DWORD wDriverFormat; unsigned long wDriverFormat;
DWORD wMixerChannels; unsigned long wMixerChannels;
DWORD wDMACountRegister; unsigned long wDMACountRegister;
DWORD wDMAPosition; unsigned long wDMAPosition;
DWORD wDMALastPosition; unsigned long wDMALastPosition;
DWORD wDMADistance; unsigned long wDMADistance;
PSTR pXFERPosition; char* pXFERPosition;
DWORD wXFERJumpAhead; unsigned long wXFERJumpAhead;
_SOS_SAMPLE* pSampleList; _SOS_SAMPLE* pSampleList;
void (*pfnPseudoDMAFunction)(void); void (*pfnPseudoDMAFunction)(void);
PSTR pDMABuffer; char* pDMABuffer;
PSTR pDMABufferEnd; char* pDMABufferEnd;
DWORD wDMABufferSize; unsigned long wDMABufferSize;
PSTR pMixingBuffer; char* pMixingBuffer;
PSTR pMixingBufferEnd; char* pMixingBufferEnd;
DWORD wMixingBufferSize; unsigned long wMixingBufferSize;
DWORD wActiveChannels; unsigned long wActiveChannels;
_SOS_SAMPLE* pSamples; _SOS_SAMPLE* pSamples;
_SOS_HARDWARE sHardware; _SOS_HARDWARE sHardware;
_SOS_CAPABILITIES sCaps; _SOS_CAPABILITIES sCaps;
LPSTR lpDriverDS; char* lpDriverDS;
LPSTR lpDriverCS; char* lpDriverCS;
W32 wSize; W32 wSize;
DWORD dwLinear; unsigned long dwLinear;
DWORD dwDMAPhysical; unsigned long dwDMAPhysical;
LPSTR lpDMABuffer; char* lpDMABuffer;
W32 hMemory; W32 hMemory;
W32 wDMARealSeg; W32 wDMARealSeg;
W32 wID; W32 wID;
@ -2889,14 +2888,14 @@ typedef struct _tag_sos_driver {
} _SOS_DIGI_DRIVER; } _SOS_DIGI_DRIVER;
typedef struct _SOS_DRV_FILEHEADER { typedef struct _SOS_DRV_FILEHEADER {
BYTE szName[32]; unsigned char szName[32];
W32 wDrivers; W32 wDrivers;
W32 lOffset; W32 lOffset;
W32 lFileSize; W32 lFileSize;
} _SOS_DRV_FILEHEADER; } _SOS_DRV_FILEHEADER;
typedef struct _SOS_DRV_DRIVERHEADER { typedef struct _SOS_DRV_DRIVERHEADER {
BYTE szName[32]; unsigned char szName[32];
W32 lNextDriver; W32 lNextDriver;
W32 wSize; W32 wSize;
W32 wDeviceID; W32 wDeviceID;
@ -2905,32 +2904,31 @@ typedef struct _SOS_DRV_DRIVERHEADER {
typedef struct _tag_sos_system { typedef struct _tag_sos_system {
W32 wFlags; W32 wFlags;
BYTE szDriverPath[128]; unsigned char szDriverPath[128];
BYTE szTempDriverPath[128]; unsigned char szTempDriverPath[128];
PSOSDIGIDRIVER pDriver[5]; PSOSDIGIDRIVER pDriver[5];
_SOS_VDS_STRUCT sVDS; _SOS_VDS_STRUCT sVDS;
_SOS_DRV_FILEHEADER sFileHeader; _SOS_DRV_FILEHEADER sFileHeader;
_SOS_DRV_DRIVERHEADER sDriverHeader; _SOS_DRV_DRIVERHEADER sDriverHeader;
PSTR(*pMemAllocFunction) char* (*pMemAllocFunction)(unsigned long);
(DWORD); void (*pMemFreeFunction)(char*, W32);
void (*pMemFreeFunction)(PSTR, W32);
} _SOS_SYSTEM; } _SOS_SYSTEM;
typedef struct _tag_sos_det_system { typedef struct _tag_sos_det_system {
W32 wFlags; W32 wFlags;
BYTE szDriverPath[128]; unsigned char szDriverPath[128];
BYTE szTempDriverPath[128]; unsigned char szTempDriverPath[128];
_SOS_DRV_FILEHEADER sFileHeader; _SOS_DRV_FILEHEADER sFileHeader;
_SOS_DRV_DRIVERHEADER sDriverHeader; _SOS_DRV_DRIVERHEADER sDriverHeader;
_SOS_CAPABILITIES sCaps; _SOS_CAPABILITIES sCaps;
PSOSCAPABILITIES pCaps; PSOSCAPABILITIES pCaps;
LPSTR lpBufferDS; char* lpBufferDS;
LPSTR lpBufferCS; char* lpBufferCS;
W32 hFile; W32 hFile;
DWORD dwDriverIndex; unsigned long dwDriverIndex;
W32 wDriverIndexCur; W32 wDriverIndexCur;
W32 hMemory; W32 hMemory;
DWORD dwLinear; unsigned long dwLinear;
} _SOS_DET_SYSTEM; } _SOS_DET_SYSTEM;
typedef struct _tag_sos_timer_system { typedef struct _tag_sos_timer_system {
@ -2938,8 +2936,8 @@ typedef struct _tag_sos_timer_system {
W32 wChipDivisor; W32 wChipDivisor;
void (*pfnEvent[16])(void); void (*pfnEvent[16])(void);
W32 wEventRate[16]; W32 wEventRate[16];
DWORD dwAdditiveFraction[16]; unsigned long dwAdditiveFraction[16];
DWORD dwCurrentSummation[16]; unsigned long dwCurrentSummation[16];
W32 wMIDIEventSongHandle[16]; W32 wMIDIEventSongHandle[16];
W32 wMIDIActiveSongHandle; W32 wMIDIActiveSongHandle;
} _SOS_TIMER_SYSTEM; } _SOS_TIMER_SYSTEM;
@ -3935,7 +3933,7 @@ typedef struct BYTEREGS {
unsigned short _4; unsigned short _4;
} BYTEREGS; } BYTEREGS;
typedef struct REGS { typedef union REGS {
DWORDREGS x; DWORDREGS x;
WORDREGS w; WORDREGS w;
BYTEREGS h; BYTEREGS h;
@ -4131,7 +4129,7 @@ typedef struct tPD_net_game_info {
} tPD_net_game_info; } tPD_net_game_info;
typedef struct tIPX_netnum { typedef struct tIPX_netnum {
BYTE bNetwork[4]; unsigned char bNetwork[4];
} tIPX_netnum; } tIPX_netnum;
typedef struct tRM_info { typedef struct tRM_info {

View File

@ -1,11 +1,13 @@
#include "harness/hooks.h"
#include "pd/sys.h"
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32 #ifdef _WIN32
#include <io.h> #include <io.h>
#include <stdio.h>
#include <windows.h>
#endif #endif
extern void Harness_Init(int* argc, char* argv[]);
extern int original_main(int pArgc, char* pArgv[]); extern int original_main(int pArgc, char* pArgv[]);
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {

View File

@ -32,7 +32,7 @@ int gNumber_of_hosts;
tRM_info RMI; tRM_info RMI;
_IPX_HEADER gLast_received_IPX_header; _IPX_HEADER gLast_received_IPX_header;
tU16 gSocket_number_network_order; tU16 gSocket_number_network_order;
USHORT gECB_offset; unsigned short gECB_offset;
tU16 gListen_selector; tU16 gListen_selector;
tU16 gSend_selector; tU16 gSend_selector;
@ -125,8 +125,8 @@ int BroadcastMessage() {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall hmiIPXCloseSocket@<EAX>(W32 wSocket@<EAX>) // IDA: int __usercall hmiIPXCloseSocket@<EAX>(W32 wSocket@<EAX>)
BOOL hmiIPXCloseSocket(W32 wSocket) { int hmiIPXCloseSocket(W32 wSocket) {
REGS regs; REGS regs;
SREGS sregs; SREGS sregs;
LOG_TRACE("(%d)", wSocket); LOG_TRACE("(%d)", wSocket);
@ -143,14 +143,14 @@ void hmiIPXListenForPacket(_IPX_ECB* pECB_ptr, tU32 pOffset) {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall hmiIPXPostListen@<EAX>(_IPX_ECB *pECB_ptr@<EAX>, tU32 pOffset@<EDX>) // IDA: int __usercall hmiIPXPostListen@<EAX>(_IPX_ECB *pECB_ptr@<EAX>, tU32 pOffset@<EDX>)
BOOL hmiIPXPostListen(_IPX_ECB* pECB_ptr, tU32 pOffset) { int hmiIPXPostListen(_IPX_ECB* pECB_ptr, tU32 pOffset) {
LOG_TRACE("(%p, %d)", pECB_ptr, pOffset); LOG_TRACE("(%p, %d)", pECB_ptr, pOffset);
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __cdecl hmiIPXGetData(PSTR pData, tU32 wDSize) // IDA: int __cdecl hmiIPXGetData(char* pData, tU32 wDSize)
BOOL hmiIPXGetData(PSTR pData, tU32 wDSize) { int hmiIPXGetData(char* pData, tU32 wDSize) {
tU32 packets_checked; tU32 packets_checked;
tU32 full_packet_ooer_missus; tU32 full_packet_ooer_missus;
_IPX_ECB* ECB_ptr; _IPX_ECB* ECB_ptr;
@ -159,19 +159,19 @@ BOOL hmiIPXGetData(PSTR pData, tU32 wDSize) {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: void __usercall hmiIPXSendPacket(_IPX_ECB *sECB@<EAX>, _IPX_ECB **pPacket@<EDX>, PSTR pHeader@<EBX>, W32 wSize@<ECX>) // IDA: void __usercall hmiIPXSendPacket(_IPX_ECB *sECB@<EAX>, _IPX_ECB **pPacket@<EDX>, char* pHeader@<EBX>, W32 wSize@<ECX>)
void hmiIPXSendPacket(_IPX_ECB* sECB, _IPX_ECB** pPacket, PSTR pHeader, W32 wSize) { void hmiIPXSendPacket(_IPX_ECB* sECB, _IPX_ECB** pPacket, char* pHeader, W32 wSize) {
SREGS sregs; SREGS sregs;
REGS regs; REGS regs;
_IPX_HEADER* sIPXHeader; _IPX_HEADER* sIPXHeader;
_IPX_ECB* sIPXECB; _IPX_ECB* sIPXECB;
PSTR pIPXData; char* pIPXData;
LOG_TRACE("(%p, %p, %d, %d)", sECB, pPacket, pHeader, wSize); LOG_TRACE("(%p, %p, %d, %d)", sECB, pPacket, pHeader, wSize);
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall hmiIPXSendDataDirect@<EAX>(PSTR pHeader@<EAX>, W32 wHSize@<EDX>, PSTR pData@<EBX>, W32 wDSize@<ECX>, _NETNOW_NODE_ADDR *sNode) // IDA: int __usercall hmiIPXSendDataDirect@<EAX>(char* pHeader@<EAX>, W32 wHSize@<EDX>, char* pData@<EBX>, W32 wDSize@<ECX>, _NETNOW_NODE_ADDR *sNode)
BOOL hmiIPXSendDataDirect(PSTR pHeader, W32 wHSize, PSTR pData, W32 wDSize, _NETNOW_NODE_ADDR* sNode) { int hmiIPXSendDataDirect(char* pHeader, W32 wHSize, char* pData, W32 wDSize, _NETNOW_NODE_ADDR* sNode) {
W32 wIndex; W32 wIndex;
_IPX_ELEMENT* sElement; _IPX_ELEMENT* sElement;
W32* pSequence; W32* pSequence;
@ -195,8 +195,8 @@ void hmiIPXGetLocalTarget(_IPX_LOCAL_TARGET* sNetworkAddr) {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall AllocateRealMem@<EAX>(W32 wSize@<EAX>, PSTR *pPtr@<EDX>, W32 *pSegment@<EBX>, tU16 *pSelector@<ECX>) // IDA: int __usercall AllocateRealMem@<EAX>(W32 wSize@<EAX>, char* *pPtr@<EDX>, W32 *pSegment@<EBX>, tU16 *pSelector@<ECX>)
BOOL AllocateRealMem(W32 wSize, PSTR* pPtr, W32* pSegment, tU16* pSelector) { int AllocateRealMem(W32 wSize, char** pPtr, W32* pSegment, tU16* pSelector) {
REGS regs; REGS regs;
SREGS sregs; SREGS sregs;
W32 wAddress; W32 wAddress;
@ -207,8 +207,8 @@ BOOL AllocateRealMem(W32 wSize, PSTR* pPtr, W32* pSegment, tU16* pSelector) {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall FreeRealMem@<EAX>(tU16 pSelector@<EAX>) // IDA: int __usercall FreeRealMem@<EAX>(tU16 pSelector@<EAX>)
BOOL FreeRealMem(tU16 pSelector) { int FreeRealMem(tU16 pSelector) {
REGS regs; REGS regs;
SREGS sregs; SREGS sregs;
W32 wAddress; W32 wAddress;
@ -219,16 +219,16 @@ BOOL FreeRealMem(tU16 pSelector) {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __cdecl hmiIPXInstalled() // IDA: int __cdecl hmiIPXInstalled()
BOOL hmiIPXInstalled() { int hmiIPXInstalled() {
SREGS sregs; SREGS sregs;
REGS regs; REGS regs;
LOG_TRACE("()"); LOG_TRACE("()");
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall hmiIPXOpenSocket@<EAX>(W32 wSocket@<EAX>) // IDA: int __usercall hmiIPXOpenSocket@<EAX>(W32 wSocket@<EAX>)
BOOL hmiIPXOpenSocket(W32 wSocket) { int hmiIPXOpenSocket(W32 wSocket) {
SREGS sregs; SREGS sregs;
REGS regs; REGS regs;
LOG_TRACE("(%d)", wSocket); LOG_TRACE("(%d)", wSocket);
@ -243,13 +243,13 @@ void GetLargestPacketSizeOoErBetterInsertLinfordChristieJokeHere() {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
// IDA: BOOL __usercall hmiIPXInitSystem@<EAX>(W32 wSocket@<EAX>) // IDA: int __usercall hmiIPXInitSystem@<EAX>(W32 wSocket@<EAX>)
BOOL hmiIPXInitSystem(W32 wSocket) { int hmiIPXInitSystem(W32 wSocket) {
W32 wNIndex; W32 wNIndex;
W32 wIndex; W32 wIndex;
W32 wMIndex; W32 wMIndex;
USHORT wSOffset; unsigned short wSOffset;
USHORT wLOffset; unsigned short wLOffset;
LOG_TRACE("(%d)", wSocket); LOG_TRACE("(%d)", wSocket);
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
@ -349,14 +349,15 @@ tPlayer_ID PDNetExtractPlayerID(tNet_game_details* pDetails) {
// IDA: void __usercall PDNetObtainSystemUserName(char *pName@<EAX>, int pMax_length@<EDX>) // IDA: void __usercall PDNetObtainSystemUserName(char *pName@<EAX>, int pMax_length@<EDX>)
void PDNetObtainSystemUserName(char* pName, int pMax_length) { void PDNetObtainSystemUserName(char* pName, int pMax_length) {
#ifdef _WIN32 #ifdef _WIN32
DWORD size; uint32_t size;
char buffer[16]; char buffer[16];
BOOL result; int result;
#endif #endif
dr_dprintf("PDNetObtainSystemUserName()\n"); dr_dprintf("PDNetObtainSystemUserName()\n");
#ifdef _WIN32 // todo
#if 0
size = COUNT_OF(buffer); size = COUNT_OF(buffer);
result = GetComputerNameA(buffer, &size); result = GetComputerNameA(buffer, &size);
if (result == 0) { if (result == 0) {

View File

@ -24,42 +24,12 @@
#ifdef __DOS__ #ifdef __DOS__
#define GFX_INIT_STRING_32X20X8 "MCGA,W:320,H:200,B:8" #define GFX_INIT_STRING_32X20X8 "MCGA,W:320,H:200,B:8"
#define GFX_INIT_STRING_64X48X8 "VESA,W:640,H:480,B:8" #define GFX_INIT_STRING_64X48X8 "VESA,W:640,H:480,B:8"
#else
#define GFX_INIT_STRING_32X20X8 "320x200 init string"
#define GFX_INIT_STRING_64X48X8 "640x480 init string"
#endif
int gDOSGfx_initialized; int gDOSGfx_initialized;
int gExtra_mem;
int gReplay_override;
tGraf_spec gGraf_specs[2] = {
{ 8, 1, 0, 320, 200, 0, 0, "32X20X8", GFX_INIT_STRING_32X20X8, 320, 320, 200, NULL },
{ 8, 1, 0, 640, 480, 0, 0, "64X48X8", GFX_INIT_STRING_64X48X8, 640, 640, 480, NULL }
};
int gASCII_table[128];
tU32 gKeyboard_bits[8];
int gASCII_shift_table[128];
char gNetwork_profile_fname[256];
tS32 gJoystick_min1y;
tS32 gJoystick_min2y;
tS32 gJoystick_min2x;
tS32 gRaw_joystick2y;
tS32 gRaw_joystick2x;
tS32 gRaw_joystick1y;
tS32 gRaw_joystick1x;
tS32 gJoystick_range2y;
tS32 gJoystick_range2x;
tS32 gJoystick_range1y;
tS32 gJoystick_range1x;
int gNo_voodoo;
int gSwitched_resolution;
br_pixelmap* gReal_back_screen;
tS32 gJoystick_min1x;
br_pixelmap* gTemp_screen;
tU32 gUpper_loop_limit; tU32 gUpper_loop_limit;
int gReal_back_screen_locked; int gReal_back_screen_locked;
void (*gPrev_keyboard_handler)(); void (*gPrev_keyboard_handler)();
tU8 gScan_code[123][2];
char* _unittest_last_fatal_error; char* _unittest_last_fatal_error;
@ -74,7 +44,7 @@ void KeyboardHandler() {
// IDA: int __usercall KeyDown@<EAX>(tU8 pScan_code@<EAX>) // IDA: int __usercall KeyDown@<EAX>(tU8 pScan_code@<EAX>)
int KeyDown(tU8 pScan_code) { int KeyDown(tU8 pScan_code) {
return Harness_Hook_KeyDown(pScan_code); NOT_IMPLEMENTED();
} }
// IDA: void __usercall KeyTranslation(tU8 pKey_index@<EAX>, tU8 pScan_code_1@<EDX>, tU8 pScan_code_2@<EBX>) // IDA: void __usercall KeyTranslation(tU8 pKey_index@<EAX>, tU8 pScan_code_1@<EDX>, tU8 pScan_code_2@<EBX>)
@ -85,123 +55,7 @@ void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2) {
// IDA: void __cdecl KeyBegin() // IDA: void __cdecl KeyBegin()
void KeyBegin() { void KeyBegin() {
NOT_IMPLEMENTED();
// int v0; // edx@0
// int v1; // ST00_4@1
// __int16 v2; // dx@1
// *(_WORD *)gScan_code[11] = 11;
// *(_WORD *)gScan_code[13] = 3;
// *(_WORD *)gScan_code[14] = 4;
// *(_WORD *)gScan_code[12] = 2;
// *(_WORD *)gScan_code[15] = 5;
// *(_WORD *)gScan_code[17] = 7;
// *(_WORD *)gScan_code[18] = 8;
// *(_WORD *)gScan_code[16] = 6;
// *(_WORD *)gScan_code[19] = 9;
// *(_WORD *)gScan_code[21] = 30;
// *(_WORD *)gScan_code[22] = 48;
// *(_WORD *)gScan_code[20] = 10;
// *(_WORD *)gScan_code[23] = 46;
// *(_WORD *)gScan_code[25] = 18;
// *(_WORD *)gScan_code[26] = 33;
// *(_WORD *)gScan_code[24] = 32;
// *(_WORD *)gScan_code[27] = 34;
// *(_WORD *)gScan_code[29] = 23;
// *(_WORD *)gScan_code[30] = 36;
// *(_WORD *)gScan_code[28] = 35;
// *(_WORD *)gScan_code[31] = 37;
// *(_WORD *)gScan_code[33] = 50;
// *(_WORD *)gScan_code[34] = 49;
// *(_WORD *)gScan_code[32] = 38;
// *(_WORD *)gScan_code[35] = 24;
// *(_WORD *)gScan_code[37] = 16;
// *(_WORD *)gScan_code[38] = 19;
// *(_WORD *)gScan_code[36] = 25;
// *(_WORD *)gScan_code[39] = 31;
// *(_WORD *)gScan_code[41] = 22;
// *(_WORD *)gScan_code[42] = 47;
// *(_WORD *)gScan_code[40] = 20;
// *(_WORD *)gScan_code[43] = 17;
// *(_WORD *)gScan_code[44] = 45;
// *(_WORD *)gScan_code[45] = 21;
// *(_WORD *)gScan_code[46] = 44;
// *(_WORD *)gScan_code[47] = 41;
// *(_WORD *)gScan_code[48] = 12;
// *(_WORD *)gScan_code[49] = 13;
// *(_WORD *)gScan_code[50] = 14;
// *(_WORD *)gScan_code[51] = 28;
// *(_WORD *)gScan_code[52] = 156;
// *(_WORD *)gScan_code[0] = 13866;
// *(_WORD *)gScan_code[1] = -18376;
// *(_WORD *)gScan_code[2] = -25315;
// *(_WORD *)gScan_code[3] = -25315;
// *(_WORD *)gScan_code[4] = 58;
// *(_WORD *)gScan_code[55] = 86;
// *(_WORD *)gScan_code[54] = 53;
// *(_WORD *)gScan_code[56] = 39;
// *(_WORD *)gScan_code[59] = 51;
// *(_WORD *)gScan_code[53] = 15;
// *(_WORD *)gScan_code[58] = 52;
// *(_WORD *)gScan_code[60] = 26;
// *(_WORD *)gScan_code[63] = 1;
// *(_WORD *)gScan_code[57] = 40;
// *(_WORD *)gScan_code[62] = 43;
// *(_WORD *)gScan_code[64] = 210;
// *(_WORD *)gScan_code[67] = 207;
// *(_WORD *)gScan_code[61] = 27;
// *(_WORD *)gScan_code[66] = 199;
// *(_WORD *)gScan_code[68] = 201;
// *(_WORD *)gScan_code[71] = 205;
// *(_WORD *)gScan_code[65] = 211;
// *(_WORD *)gScan_code[70] = 203;
// *(_WORD *)gScan_code[72] = 200;
// *(_WORD *)gScan_code[69] = 209;
// *(_WORD *)gScan_code[74] = 69;
// *(_WORD *)gScan_code[73] = 208;
// *(_WORD *)gScan_code[75] = 181;
// *(_WORD *)gScan_code[76] = 55;
// *(_WORD *)gScan_code[78] = 78;
// *(_WORD *)gScan_code[77] = 74;
// *(_WORD *)gScan_code[80] = 0;
// *(_WORD *)gScan_code[79] = 83;
// *(_WORD *)gScan_code[82] = 79;
// *(_WORD *)gScan_code[84] = 81;
// *(_WORD *)gScan_code[81] = 82;
// *(_WORD *)gScan_code[83] = 80;
// *(_WORD *)gScan_code[86] = 76;
// *(_WORD *)gScan_code[88] = 71;
// *(_WORD *)gScan_code[85] = 75;
// *(_WORD *)gScan_code[87] = 77;
// *(_WORD *)gScan_code[90] = 73;
// *(_WORD *)gScan_code[92] = 60;
// *(_WORD *)gScan_code[89] = 72;
// *(_WORD *)gScan_code[91] = 59;
// *(_WORD *)gScan_code[94] = 62;
// *(_WORD *)gScan_code[96] = 64;
// *(_WORD *)gScan_code[93] = 61;
// *(_WORD *)gScan_code[95] = 63;
// *(_WORD *)gScan_code[98] = 66;
// *(_WORD *)gScan_code[100] = 68;
// *(_WORD *)gScan_code[97] = 65;
// *(_WORD *)gScan_code[99] = 67;
// *(_WORD *)gScan_code[102] = 88;
// *(_WORD *)gScan_code[104] = 70;
// *(_WORD *)gScan_code[101] = 87;
// *(_WORD *)gScan_code[103] = 0;
// *(_WORD *)gScan_code[105] = 0;
// *(_WORD *)gScan_code[106] = 57;
// *(_WORD *)gScan_code[5] = 54;
// *(_WORD *)gScan_code[6] = 184;
// *(_WORD *)gScan_code[7] = 157;
// *(_WORD *)gScan_code[8] = 42;
// *(_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);
} }
// IDA: void __cdecl KeyEnd() // IDA: void __cdecl KeyEnd()
@ -222,29 +76,6 @@ void PDSetKeyArray(int* pKeys, int pMark) {
tS32 joyX; tS32 joyX;
tS32 joyY; tS32 joyY;
LOG_TRACE10("(%p, %d)", pKeys, pMark); LOG_TRACE10("(%p, %d)", pKeys, pMark);
Harness_Hook_PDSetKeyArray();
gKeys_pressed = 0;
for (i = 0; i < COUNT_OF(gScan_code); i++) {
if (KeyDown(gScan_code[i][0])) { //} || KeyDown(gScan_code[i][1])) {
gKeys_pressed = (gKeys_pressed << 8) + i + 1;
pKeys[i] = pMark;
} else if (pKeys[i] == pMark) {
pKeys[i] = 0;
}
}
}
// IDA: int __usercall PDGetASCIIFromKey@<EAX>(int pKey@<EAX>)
int PDGetASCIIFromKey(int pKey) {
LOG_TRACE("(%d)", pKey);
if (PDKeyDown(KEY_LSHIFT)) {
return gASCII_shift_table[pKey];
} else {
return gASCII_table[pKey];
}
} }
// IDA: void __usercall PDFatalError(char *pThe_str@<EAX>) // IDA: void __usercall PDFatalError(char *pThe_str@<EAX>)
@ -614,8 +445,6 @@ void Usage(char* pProgpath) {
// char basename[9]; // char basename[9];
char basename[256]; // fix: changed from 9 to avoid overflow on longer filenames char basename[256]; // fix: changed from 9 to avoid overflow on longer filenames
OS_Basename(pProgpath, basename);
fprintf(stderr, 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", "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",
basename, basename,
@ -687,63 +516,6 @@ int OurGetChar() {
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
int CheckGorePasswordFile(char* pPassword) {
tPath_name path;
FILE* f;
char line[10];
PathCat(path, "DATA", "PASS.TXT");
f = fopen(path, "rb");
if (f == NULL) {
return 0;
}
if (fgets(line, sizeof(line), f) == NULL) {
fclose(f);
return 0;
}
fclose(f);
#if defined(DETHRACE_FIX_BUGS)
// Allow a final newline in DATA/PASS.TXT
while (strlen(line) > 0 && (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r')) {
line[strlen(line) - 1] = '\0';
}
#endif
#ifdef _WIN32
return stricmp(line, pPassword) == 0;
#else
return strcasecmp(line, pPassword) == 0;
#endif
}
// IDA: int __cdecl PDGetGorePassword()
int PDGetGorePassword() {
int ch;
int len;
int chances;
char password[17];
LOG_TRACE("()");
for (chances = 0; chances < 3; chances++) {
printf(chances == 0 ? "\n\n\n\n\nEnter password for uncut version...\n" : "\nIncorrect password, please try again...\n");
OS_ConsoleReadPassword(password, sizeof(password));
dr_dprintf("Password entered is '%s'", password);
if (CheckGorePasswordFile(password)) {
return 1;
}
}
return 0;
}
// IDA: void __usercall PDDisplayGoreworthiness(int pGory@<EAX>)
void PDDisplayGoreworthiness(int pGory) {
tU32 delay_start;
LOG_TRACE("(%d)", pGory);
printf(pGory ? "\nPlaying full version...\n" : "\nPlaying zombie version...\n");
delay_start = 2;
OS_Sleep(delay_start * 1000);
}
// IDA: void __usercall PDEnterDebugger(char *pStr@<EAX>) // IDA: void __usercall PDEnterDebugger(char *pStr@<EAX>)
void PDEnterDebugger(char* pStr) { void PDEnterDebugger(char* pStr) {
static unsigned char* save_it; static unsigned char* save_it;
@ -758,42 +530,6 @@ void PDEnterDebugger(char* pStr) {
// ShowCursor(0); // ShowCursor(0);
} }
// Added function
br_material* PDMissingMaterial(char* name) {
LOG_TRACE("(\"%s\")", name);
// FIXME: call functiont in harness
dr_dprintf("SOMETHING MISSING WARNING - Can't find material '%s'", name);
return NULL;
}
// Added function
br_pixelmap* PDMissingTable(char* name) {
LOG_TRACE("(\"%s\")", name);
// FIXME: call function in harness
dr_dprintf("SOMETHING MISSING WARNING - Can't find shade table '%s'", name);
return NULL;
}
// Added function
br_model* PDMissingModel(char* name) {
LOG_TRACE("(\"%s\")", name);
// FIXME: call function in harness
dr_dprintf("SOMETHING MISSING WARNING - Can't find model '%s'", name);
return NULL;
}
// Added function
br_pixelmap* PDMissingMap(char* name) {
LOG_TRACE("(\"%s\")", name);
// FIXME: call function in harness
dr_dprintf("SOMETHING MISSING WARNING - Can't find pixelmap '%s'", name);
return NULL;
}
// IDA: void __cdecl PDEndItAllAndReRunTheBastard() // IDA: void __cdecl PDEndItAllAndReRunTheBastard()
void PDEndItAllAndReRunTheBastard() { void PDEndItAllAndReRunTheBastard() {
LOG_TRACE("()"); LOG_TRACE("()");
@ -970,3 +706,62 @@ int PDDoWeLeadAnAustereExistance() {
} }
return block < 15000000; return block < 15000000;
} }
#endif
int CheckGorePasswordFile(char* pPassword) {
tPath_name path;
FILE* f;
char line[10];
PathCat(path, "DATA", "PASS.TXT");
f = fopen(path, "rb");
if (f == NULL) {
return 0;
}
if (fgets(line, sizeof(line), f) == NULL) {
fclose(f);
return 0;
}
fclose(f);
#if defined(DETHRACE_FIX_BUGS)
// Allow a final newline in DATA/PASS.TXT
while (strlen(line) > 0 && (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r')) {
line[strlen(line) - 1] = '\0';
}
#endif
#ifdef _WIN32
return stricmp(line, pPassword) == 0;
#else
return strcasecmp(line, pPassword) == 0;
#endif
}
// IDA: int __cdecl PDGetGorePassword()
int PDGetGorePassword() {
int ch;
int len;
int chances;
char password[17];
LOG_TRACE("()");
for (chances = 0; chances < 3; chances++) {
printf(chances == 0 ? "\n\n\n\n\nEnter password for uncut version...\n" : "\nIncorrect password, please try again...\n");
OS_ConsoleReadPassword(password, sizeof(password));
dr_dprintf("Password entered is '%s'", password);
if (CheckGorePasswordFile(password)) {
return 1;
}
}
return 0;
}
// IDA: void __usercall PDDisplayGoreworthiness(int pGory@<EAX>)
void PDDisplayGoreworthiness(int pGory) {
tU32 delay_start;
LOG_TRACE("(%d)", pGory);
printf(pGory ? "\nPlaying full version...\n" : "\nPlaying zombie version...\n");
delay_start = 2;
gHarness_platform.Sleep(delay_start * 1000);
}

View File

@ -0,0 +1,153 @@
/****************************************************************************
*
* DirectInput keyboard scan codes
*
****************************************************************************/
#define DIK_ESCAPE 0x01
#define DIK_1 0x02
#define DIK_2 0x03
#define DIK_3 0x04
#define DIK_4 0x05
#define DIK_5 0x06
#define DIK_6 0x07
#define DIK_7 0x08
#define DIK_8 0x09
#define DIK_9 0x0A
#define DIK_0 0x0B
#define DIK_MINUS 0x0C /* - on main keyboard */
#define DIK_EQUALS 0x0D
#define DIK_BACK 0x0E /* backspace */
#define DIK_TAB 0x0F
#define DIK_Q 0x10
#define DIK_W 0x11
#define DIK_E 0x12
#define DIK_R 0x13
#define DIK_T 0x14
#define DIK_Y 0x15
#define DIK_U 0x16
#define DIK_I 0x17
#define DIK_O 0x18
#define DIK_P 0x19
#define DIK_LBRACKET 0x1A
#define DIK_RBRACKET 0x1B
#define DIK_RETURN 0x1C /* Enter on main keyboard */
#define DIK_LCONTROL 0x1D
#define DIK_A 0x1E
#define DIK_S 0x1F
#define DIK_D 0x20
#define DIK_F 0x21
#define DIK_G 0x22
#define DIK_H 0x23
#define DIK_J 0x24
#define DIK_K 0x25
#define DIK_L 0x26
#define DIK_SEMICOLON 0x27
#define DIK_APOSTROPHE 0x28
#define DIK_GRAVE 0x29 /* accent grave */
#define DIK_LSHIFT 0x2A
#define DIK_BACKSLASH 0x2B
#define DIK_Z 0x2C
#define DIK_X 0x2D
#define DIK_C 0x2E
#define DIK_V 0x2F
#define DIK_B 0x30
#define DIK_N 0x31
#define DIK_M 0x32
#define DIK_COMMA 0x33
#define DIK_PERIOD 0x34 /* . on main keyboard */
#define DIK_SLASH 0x35 /* / on main keyboard */
#define DIK_RSHIFT 0x36
#define DIK_MULTIPLY 0x37 /* * on numeric keypad */
#define DIK_LMENU 0x38 /* left Alt */
#define DIK_SPACE 0x39
#define DIK_CAPITAL 0x3A
#define DIK_F1 0x3B
#define DIK_F2 0x3C
#define DIK_F3 0x3D
#define DIK_F4 0x3E
#define DIK_F5 0x3F
#define DIK_F6 0x40
#define DIK_F7 0x41
#define DIK_F8 0x42
#define DIK_F9 0x43
#define DIK_F10 0x44
#define DIK_NUMLOCK 0x45
#define DIK_SCROLL 0x46 /* Scroll Lock */
#define DIK_NUMPAD7 0x47
#define DIK_NUMPAD8 0x48
#define DIK_NUMPAD9 0x49
#define DIK_SUBTRACT 0x4A /* - on numeric keypad */
#define DIK_NUMPAD4 0x4B
#define DIK_NUMPAD5 0x4C
#define DIK_NUMPAD6 0x4D
#define DIK_ADD 0x4E /* + on numeric keypad */
#define DIK_NUMPAD1 0x4F
#define DIK_NUMPAD2 0x50
#define DIK_NUMPAD3 0x51
#define DIK_NUMPAD0 0x52
#define DIK_DECIMAL 0x53 /* . on numeric keypad */
#define DIK_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */
#define DIK_F11 0x57
#define DIK_F12 0x58
#define DIK_F13 0x64 /* (NEC PC98) */
#define DIK_F14 0x65 /* (NEC PC98) */
#define DIK_F15 0x66 /* (NEC PC98) */
#define DIK_KANA 0x70 /* (Japanese keyboard) */
#define DIK_ABNT_C1 0x73 /* /? on Brazilian keyboard */
#define DIK_CONVERT 0x79 /* (Japanese keyboard) */
#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */
#define DIK_YEN 0x7D /* (Japanese keyboard) */
#define DIK_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */
#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */
#define DIK_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
#define DIK_AT 0x91 /* (NEC PC98) */
#define DIK_COLON 0x92 /* (NEC PC98) */
#define DIK_UNDERLINE 0x93 /* (NEC PC98) */
#define DIK_KANJI 0x94 /* (Japanese keyboard) */
#define DIK_STOP 0x95 /* (NEC PC98) */
#define DIK_AX 0x96 /* (Japan AX) */
#define DIK_UNLABELED 0x97 /* (J3100) */
#define DIK_NEXTTRACK 0x99 /* Next Track */
#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */
#define DIK_RCONTROL 0x9D
#define DIK_MUTE 0xA0 /* Mute */
#define DIK_CALCULATOR 0xA1 /* Calculator */
#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */
#define DIK_MEDIASTOP 0xA4 /* Media Stop */
#define DIK_VOLUMEDOWN 0xAE /* Volume - */
#define DIK_VOLUMEUP 0xB0 /* Volume + */
#define DIK_WEBHOME 0xB2 /* Web home */
#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */
#define DIK_DIVIDE 0xB5 /* / on numeric keypad */
#define DIK_SYSRQ 0xB7
#define DIK_RMENU 0xB8 /* right Alt */
#define DIK_PAUSE 0xC5 /* Pause */
#define DIK_HOME 0xC7 /* Home on arrow keypad */
#define DIK_UP 0xC8 /* UpArrow on arrow keypad */
#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */
#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */
#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */
#define DIK_END 0xCF /* End on arrow keypad */
#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */
#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */
#define DIK_INSERT 0xD2 /* Insert on arrow keypad */
#define DIK_DELETE 0xD3 /* Delete on arrow keypad */
/*
* Alternate names for keys, to facilitate transition from DOS.
*/
#define DIK_BACKSPACE DIK_BACK /* backspace */
#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */
#define DIK_LALT DIK_LMENU /* left Alt */
#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */
#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */
#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */
#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */
#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */
#define DIK_RALT DIK_RMENU /* right Alt */
#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */
#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */
#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */
#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */
#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */
#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */

View File

@ -0,0 +1,64 @@
#include "ssdx.h"
#include "errors.h"
#include "harness/hooks.h"
int gSSDX_windowed;
void* gSSDX_hwnd;
int SSDXStart(void* hWnd, int windowed, int flags) {
int res = 0;
dr_dprintf("SSDXStart(): START...");
if (windowed) {
gSSDX_windowed = 1;
}
gSSDX_hwnd = hWnd;
// Not required
// if ((flags & 1) != 0) {
// dr_dprintf("Calling DirectDrawCreate()...");
// res = DirectDrawCreate(0, &gDirect_draw, 0);
// if (!res) {
// dr_dprintf("Calling SetCooperativeLevel()...");
// if (gSSDX_windowed) {
// res = gDirect_draw->lpVtbl->SetCooperativeLevel(gDirect_draw, gSSDX_hwnd, 8);
// } else {
// res = gDirect_draw->lpVtbl->SetCooperativeLevel(gDirect_draw, gSSDX_hwnd, 83);
// }
// }
// }
// if (!res && (flags & 2) != 0) {
// dr_dprintf("Calling DirectSoundCreate()...");
// res = DirectSoundCreate(0, &gDirect_sound, 0);
// }
// if (res) {
// SSDXHandleError(res);
// }
dr_dprintf("SSDXStart(): END.");
return res;
}
int SSDXInitDirectDraw(int width, int height, int* row_bytes) {
DirectDraw_CreateSurface(width, height);
*row_bytes = width;
return 0;
}
void SSDXRelease() {}
void SSDXGetWindowRect(void* hWnd) {
// none of this is required
// GetClientRect(hWnd, &gSSDX_rect);
// ClientToScreen(hWnd, (LPPOINT)&gSSDX_rect);
// ClientToScreen(hWnd, (LPPOINT)&gSSDX_rect.right);
// dr_dprintf("New window rect: (%d,%d)(%d,%d)", gSSDX_rect.left, gSSDX_rect.top, gSSDX_rect.right, gSSDX_rect.bottom);
}
void SSDXHandleError(int error) {
// no-op
}
void SSDXSetPaleeteEntries(PALETTEENTRY_* palette, int pFirst_color, int pCount) {
DirectDrawDevice_SetPaletteEntries(palette, pFirst_color, pCount);
}

View File

@ -0,0 +1,18 @@
#ifndef SSDX_H
#define SSDX_H
#include "harness/win95_polyfill.h"
// All we know about these functions are two names - "SSDXStart" and "SSDXLockAttachedSurface".
// SSDX stands for Stainless Software Direct X ?
int SSDXStart(void* hWnd, int windowed, int flags);
int SSDXInitDirectDraw(int width, int height, int* row_bytes);
void SSDXRelease();
void SSDXLockAttachedSurface();
void SSDXGetWindowRect(void* hWnd);
void SSDXHandleError(int error);
void SSDXSetPaleeteEntries(PALETTEENTRY_* palette, int pFirst_color, int pCount);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -34,33 +34,33 @@
// int BroadcastMessage(void); // int BroadcastMessage(void);
// BOOL hmiIPXCloseSocket(W32 wSocket); // int hmiIPXCloseSocket(W32 wSocket);
// void hmiIPXListenForPacket(_IPX_ECB* pECB_ptr, tU32 pOffset); // void hmiIPXListenForPacket(_IPX_ECB* pECB_ptr, tU32 pOffset);
// BOOL hmiIPXPostListen(_IPX_ECB* pECB_ptr, tU32 pOffset); // int hmiIPXPostListen(_IPX_ECB* pECB_ptr, tU32 pOffset);
// BOOL hmiIPXGetData(PSTR pData, tU32 wDSize); // int hmiIPXGetData(PSTR pData, tU32 wDSize);
// void hmiIPXSendPacket(_IPX_ECB* sECB, _IPX_ECB** pPacket, PSTR pHeader, W32 wSize); // void hmiIPXSendPacket(_IPX_ECB* sECB, _IPX_ECB** pPacket, PSTR pHeader, W32 wSize);
// BOOL hmiIPXSendDataDirect(PSTR pHeader, W32 wHSize, PSTR pData, W32 wDSize, _NETNOW_NODE_ADDR* sNode); // int hmiIPXSendDataDirect(PSTR pHeader, W32 wHSize, PSTR pData, W32 wDSize, _NETNOW_NODE_ADDR* sNode);
// void hmiIPXGetInternetworkAddr(_IPX_INTERNET_ADDR* sInterworkAddr); // void hmiIPXGetInternetworkAddr(_IPX_INTERNET_ADDR* sInterworkAddr);
// void hmiIPXGetLocalTarget(_IPX_LOCAL_TARGET* sNetworkAddr); // void hmiIPXGetLocalTarget(_IPX_LOCAL_TARGET* sNetworkAddr);
// BOOL AllocateRealMem(W32 wSize, PSTR* pPtr, W32* pSegment, tU16* pSelector); // int AllocateRealMem(W32 wSize, PSTR* pPtr, W32* pSegment, tU16* pSelector);
// BOOL FreeRealMem(tU16 pSelector); // int FreeRealMem(tU16 pSelector);
// BOOL hmiIPXInstalled(void); // int hmiIPXInstalled(void);
// BOOL hmiIPXOpenSocket(W32 wSocket); // int hmiIPXOpenSocket(W32 wSocket);
// void GetLargestPacketSizeOoErBetterInsertLinfordChristieJokeHere(void); // void GetLargestPacketSizeOoErBetterInsertLinfordChristieJokeHere(void);
// BOOL hmiIPXInitSystem(W32 wSocket); // int hmiIPXInitSystem(W32 wSocket);
// void GetIPXToStickItsEarToTheGround(void); // void GetIPXToStickItsEarToTheGround(void);

View File

@ -39,38 +39,42 @@ extern int gReplay_override;
extern br_pixelmap* gReal_back_screen; extern br_pixelmap* gReal_back_screen;
extern tS32 gJoystick_min1x; extern tS32 gJoystick_min1x;
extern br_pixelmap* gTemp_screen; extern br_pixelmap* gTemp_screen;
//extern int gDOSGfx_initialized; extern int gDOSGfx_initialized;
extern tU32 gUpper_loop_limit; extern tU32 gUpper_loop_limit;
extern int gExtra_mem; extern int gExtra_mem;
extern int gReal_back_screen_locked; extern int gReal_back_screen_locked;
extern void (*gPrev_keyboard_handler)(void); extern void (*gPrev_keyboard_handler)(void);
extern tU8 gScan_code[123][2];
// DOS
// extern tU8 gScan_code[123][2];
// Windows
extern tU32 gScan_code[123];
extern char* _unittest_last_fatal_error; extern char* _unittest_last_fatal_error;
// void KeyboardHandler(void); // void KeyboardHandler(void);
//int KeyDown(tU8 pScan_code); // int KeyDown(tU8 pScan_code);
// void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2); // void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2);
//void KeyBegin(void); // void KeyBegin(void);
//void KeyEnd(void); // void KeyEnd(void);
//int KeyDown22(int pKey_index); // int KeyDown22(int pKey_index);
void PDSetKeyArray(int* pKeys, int pMark); void PDSetKeyArray(int* pKeys, int pMark);
int PDGetASCIIFromKey(int pKey); int PDGetASCIIFromKey(int pKey);
HARNESS_NORETURN void PDFatalError(char* pThe_str); void PDFatalError(char* pThe_str);
void PDNonFatalError(char* pThe_str); void PDNonFatalError(char* pThe_str);
void PDInitialiseSystem(void); void PDInitialiseSystem(void);
void PDShutdownSystem(void); HARNESS_NORETURN void PDShutdownSystem(void);
void PDSaveOriginalPalette(void); void PDSaveOriginalPalette(void);
@ -86,17 +90,17 @@ void PDUnlockRealBackScreen(void);
void PDAllocateScreenAndBack(void); void PDAllocateScreenAndBack(void);
//void Copy8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette); // void Copy8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette);
//void Double8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette, tU16 pOff, tU16 pSrc_width, tU16 pSrc_height); // void Double8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette, tU16 pOff, tU16 pSrc_width, tU16 pSrc_height);
br_pixelmap* PDInterfacePixelmap(void); br_pixelmap* PDInterfacePixelmap(void);
//void SwapBackScreen(void); // void SwapBackScreen(void);
//void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom); // void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom);
//void CopyBackScreen(int pRendering_area_only); // void CopyBackScreen(int pRendering_area_only);
void PDScreenBufferSwap(int pRendering_area_only); void PDScreenBufferSwap(int pRendering_area_only);
@ -130,7 +134,7 @@ int PDGetTotalTime(void);
int PDServiceSystem(tU32 pTime_since_last_call); int PDServiceSystem(tU32 pTime_since_last_call);
//tU32 LargestBlockAvail(void); // tU32 LargestBlockAvail(void);
void* PDGrabLargestMammaryWeCanPlayWith(tU32 pMaximum_required, tU32* pAmount_allocated); void* PDGrabLargestMammaryWeCanPlayWith(tU32 pMaximum_required, tU32* pAmount_allocated);
@ -138,15 +142,15 @@ void PDAllocateActionReplayBuffer(char** pBuffer, tU32* pBuffer_size);
void PDDisposeActionReplayBuffer(char* pBuffer); void PDDisposeActionReplayBuffer(char* pBuffer);
//void Usage(char* pProgpath); // void Usage(char* pProgpath);
//int OurGetChar(void); // int OurGetChar(void);
int PDGetGorePassword(void); int PDGetGorePassword(void);
void PDDisplayGoreworthiness(int pGory); void PDDisplayGoreworthiness(int pGory);
HARNESS_NORETURN void PDEnterDebugger(char* pStr); void PDEnterDebugger(char* pStr);
// Added function // Added function
br_material* PDMissingMaterial(char* name); br_material* PDMissingMaterial(char* name);
@ -162,15 +166,15 @@ br_pixelmap* PDMissingMap(char* name);
void PDEndItAllAndReRunTheBastard(void); void PDEndItAllAndReRunTheBastard(void);
//int matherr(struct exception_* err); // int matherr(struct exception_* err);
//int LoopLimitTooLow(tU32 limit); // int LoopLimitTooLow(tU32 limit);
//tS32 UpperLoopLimit(void); // tS32 UpperLoopLimit(void);
//int InitJoysticks(void); // int InitJoysticks(void);
//tU32 ReadJoystickAxis(int pBit); // tU32 ReadJoystickAxis(int pBit);
void PDReadJoySticks(void); void PDReadJoySticks(void);

View File

@ -200,6 +200,4 @@ typedef struct tWAVEFORMATEX_ {
} tWAVEFORMATEX_; } tWAVEFORMATEX_;
#pragma pack(pop) #pragma pack(pop)
#define MAX_PATH_LENGTH 256 #endif
#endif

View File

@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAX_PATH_LENGTH 1024
extern void dr_dprintf(char* fmt_string, ...); extern void dr_dprintf(char* fmt_string, ...);
int gS3_sample_filter_funcs_registered; int gS3_sample_filter_funcs_registered;
@ -17,10 +18,12 @@ tS3_sample_filter* gS3_sample_filter_disable_func;
extern ma_engine miniaudio_engine; extern ma_engine miniaudio_engine;
int S3LoadSample(tS3_sound_id id) { int S3LoadSample(tS3_sound_id id) {
// changed by dethrace for compatibility
// char filename[80]; // [esp+10h] [ebp-5Ch] BYREF
char filename[MAX_PATH_LENGTH];
tS3_descriptor* descriptor; // [esp+60h] [ebp-Ch]
tS3_sample* sample; // [esp+68h] [ebp-4h]
// LPDIRECTSOUNDBUFFER WavFile; // eax // LPDIRECTSOUNDBUFFER WavFile; // eax
char filename[MAX_PATH_LENGTH]; // [esp+10h] [ebp-5Ch] BYREF
tS3_descriptor* descriptor; // [esp+60h] [ebp-Ch]
tS3_sample* sample; // [esp+68h] [ebp-4h]
if (!gS3_enabled) { if (!gS3_enabled) {
return 0; return 0;

View File

@ -48,19 +48,20 @@ target_sources(harness PRIVATE
include/harness/trace.h include/harness/trace.h
include/harness/config.h include/harness/config.h
include/harness/os.h include/harness/os.h
include/harness/win95_polyfill.h
include/harness/win95_polyfill_defs.h
# cameras/debug_camera.c # cameras/debug_camera.c
# cameras/debug_camera.h # cameras/debug_camera.h
harness_trace.c harness_trace.c
harness.c harness.c
harness.h harness.h
io_platforms/io_platform.h
renderers/null.h
renderers/renderer.h
brender_emu/renderer_impl.c brender_emu/renderer_impl.c
brender_emu/renderer_impl.h brender_emu/renderer_impl.h
sound/sound.c sound/sound.c
sound/sound.h sound/sound.h
win95/polyfill.c
platforms/null.h
"${CMAKE_CURRENT_BINARY_DIR}/version.h" "${CMAKE_CURRENT_BINARY_DIR}/version.h"
) )
@ -75,7 +76,8 @@ if (IO_PLATFORM STREQUAL "SDL_OpenGL")
endforeach() endforeach()
target_sources(harness PRIVATE target_sources(harness PRIVATE
io_platforms/sdl_gl.c platforms/sdl_opengl.c
platforms/sdl2_scancode_to_dinput.h
renderers/gl/gl_renderer.c renderers/gl/gl_renderer.c
renderers/gl/gl_renderer.h renderers/gl/gl_renderer.h
renderers/gl/stored_context.c renderers/gl/stored_context.c

View File

@ -1,9 +1,9 @@
#include "harness.h" #include "harness.h"
#include "brender_emu/renderer_impl.h" #include "brender_emu/renderer_impl.h"
#include "include/harness/config.h" #include "include/harness/config.h"
#include "include/harness/hooks.h"
#include "include/harness/os.h" #include "include/harness/os.h"
#include "io_platforms/io_platform.h" #include "platforms/null.h"
#include "renderers/null.h"
#include "sound/sound.h" #include "sound/sound.h"
#include "version.h" #include "version.h"
@ -12,7 +12,6 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
tRenderer* renderer;
br_pixelmap* palette; br_pixelmap* palette;
uint32_t* screen_buffer; uint32_t* screen_buffer;
harness_br_renderer* renderer_state; harness_br_renderer* renderer_state;
@ -21,10 +20,10 @@ br_pixelmap* last_dst = NULL;
br_pixelmap* last_src = NULL; br_pixelmap* last_src = NULL;
unsigned int last_frame_time = 0; unsigned int last_frame_time = 0;
int force_nullrenderer = 0; int force_null_platform = 0;
extern unsigned int GetTotalTime(); extern unsigned int GetTotalTime();
extern uint8_t gScan_code[123][2];
extern br_v1db_state v1db; extern br_v1db_state v1db;
extern uint32_t gI_am_cheating; extern uint32_t gI_am_cheating;
@ -34,6 +33,9 @@ tHarness_game_info harness_game_info;
// Configuration options // Configuration options
tHarness_game_config harness_game_config; tHarness_game_config harness_game_config;
// Platform hooks
tHarness_platform gHarness_platform;
/* clang-format off */ /* clang-format off */
// German ASCII codes // German ASCII codes
static int carmageddon_german_ascii_table[128] = { static int carmageddon_german_ascii_table[128] = {
@ -78,6 +80,8 @@ static int splatpack_xmasdemo_ascii_shift_table[128] = {
}; };
/* clang-format on */ /* clang-format on */
extern void Harness_Platform_Init();
int Harness_ProcessCommandLine(int* argc, char* argv[]); int Harness_ProcessCommandLine(int* argc, char* argv[]);
void Harness_DetectGameMode() { void Harness_DetectGameMode() {
@ -221,19 +225,16 @@ void Harness_Init(int* argc, char* argv[]) {
Harness_DetectGameMode(); Harness_DetectGameMode();
} }
IOPlatform_Init(); if (force_null_platform) {
int* keymap = IOPlatform_GetKeyMap(); Null_Platform_Init(&gHarness_platform);
if (keymap != NULL) { } else {
for (int i = 0; i < 123; i++) { Harness_Platform_Init(&gHarness_platform);
gScan_code[i][0] = keymap[i];
}
} }
} }
// used by unit tests // used by unit tests
void Harness_ForceNullRenderer() { void Harness_ForceNullPlatform() {
force_nullrenderer = 1; force_null_platform = 1;
renderer = &null_renderer;
} }
int Harness_ProcessCommandLine(int* argc, char* argv[]) { int Harness_ProcessCommandLine(int* argc, char* argv[]) {
@ -306,50 +307,14 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
return 0; return 0;
} }
void Harness_Hook_GraphicsInit(int render_width, int render_height) {
int window_width, window_height;
if (force_nullrenderer) {
return;
}
if (render_width == 320) {
window_width = render_width * 2;
window_height = render_height * 2;
} else {
window_width = render_width;
window_height = render_height;
}
renderer = IOPlatform_CreateWindow("Dethrace", window_width, window_height, render_width, render_height);
}
void Harness_Hook_PDShutdownSystem() {
IOPlatform_Shutdown();
}
// Render 2d back buffer // Render 2d back buffer
void Harness_RenderScreen(br_pixelmap* dst, br_pixelmap* src) { void Harness_RenderScreen(br_pixelmap* dst, br_pixelmap* src) {
renderer->FullScreenQuad((uint8_t*)src->pixels); gHarness_platform.Renderer_FullScreenQuad((uint8_t*)src->pixels);
last_dst = dst; last_dst = dst;
last_src = src; last_src = src;
} }
void Harness_Hook_BrDevPaletteSetOld(br_pixelmap* pm) {
renderer->SetPalette((uint8_t*)pm->pixels);
palette = pm;
if (last_dst) {
Harness_RenderScreen(last_dst, last_src);
IOPlatform_SwapWindow(0);
}
}
void Harness_Hook_BrDevPaletteSetEntryOld(int i, br_colour colour) {
if (palette != NULL) {
uint32_t* colors = palette->pixels;
colors[i] = colour;
}
}
void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db) { void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db) {
renderer_state = NewHarnessBrRenderer(); renderer_state = NewHarnessBrRenderer();
v1db->renderer = (br_renderer*)renderer_state; v1db->renderer = (br_renderer*)renderer_state;
@ -375,18 +340,8 @@ int Harness_CalculateFrameDelay() {
return 0; return 0;
} }
// Begin 3d scene
void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {
renderer->BeginScene(camera, colour_buffer, depth_buffer);
}
void Harness_Hook_renderActor(br_actor* actor, br_model* model, br_material* material, br_token type) { void Harness_Hook_renderActor(br_actor* actor, br_model* model, br_material* material, br_token type) {
renderer->Model(actor, model, material, type, renderer_state->state.matrix.model_to_view); gHarness_platform.Renderer_Model(actor, model, material, type, renderer_state->state.matrix.model_to_view);
}
void Harness_Hook_BrZbSceneRenderEnd() {
renderer->FlushBuffers(eFlush_all);
renderer->EndScene();
} }
// Called by game to swap buffers at end of frame rendering // Called by game to swap buffers at end of frame rendering
@ -396,54 +351,22 @@ void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src) {
Harness_RenderScreen(dst, src); Harness_RenderScreen(dst, src);
int delay_ms = Harness_CalculateFrameDelay(); int delay_ms = Harness_CalculateFrameDelay();
IOPlatform_SwapWindow(delay_ms); gHarness_platform.SwapWindow();
if (delay_ms > 0) {
renderer->ClearBuffers(); gHarness_platform.Sleep(delay_ms);
IOPlatform_PollEvents(); }
gHarness_platform.Renderer_ClearBuffers();
last_frame_time = GetTotalTime(); last_frame_time = GetTotalTime();
} }
int Harness_Hook_KeyDown(unsigned char pScan_code) { void Harness_RenderLastScreen() {
return IOPlatform_IsKeyDown(pScan_code); if (last_dst) {
} Harness_RenderScreen(last_dst, last_src);
gHarness_platform.SwapWindow(0);
void Harness_Hook_PDServiceSystem() {
IOPlatform_PollEvents();
}
void Harness_Hook_PDSetKeyArray() {
IOPlatform_PollEvents();
}
void Harness_Hook_FlushRenderer() {
renderer->FlushBuffers(eFlush_all);
}
void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags) {
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) {
renderer->BufferTexture(pm);
} else {
LOG_PANIC("use %d", use);
} }
} }
void Harness_Hook_BrModelUpdate(br_model* model) {
renderer->BufferModel(model);
}
// Input hooks
void Harness_Hook_GetMousePosition(int* pX, int* pY) {
IOPlatform_GetMousePosition(pX, pY);
}
void Harness_Hook_GetMouseButtons(int* pButton1, int* pButton2) {
IOPlatform_GetMouseButtons(pButton1, pButton2);
}
// Filesystem hooks // Filesystem hooks
FILE* Harness_Hook_fopen(const char* pathname, const char* mode) { FILE* Harness_Hook_fopen(const char* pathname, const char* mode) {
return OS_fopen(pathname, mode); return OS_fopen(pathname, mode);

View File

@ -4,7 +4,7 @@
#include "brender/br_types.h" #include "brender/br_types.h"
#include "harness/trace.h" #include "harness/trace.h"
void Harness_ForceNullRenderer(); void Harness_ForceNullPlatform();
typedef struct tCamera { typedef struct tCamera {
void (*update)(); void (*update)();
@ -13,6 +13,4 @@ typedef struct tCamera {
void (*setPosition)(); void (*setPosition)();
} tCamera; } tCamera;
#endif
#endif

View File

@ -2,37 +2,75 @@
#define HARNESS_HOOKS_H #define HARNESS_HOOKS_H
#include "brender/br_types.h" #include "brender/br_types.h"
#include "harness/win95_polyfill_defs.h"
#include <stdio.h> #include <stdio.h>
typedef enum {
eFlush_all,
eFlush_color_buffer
} tRenderer_flush_type;
// Platform implementation functions
typedef struct tHarness_platform {
// Initialize the renderer
void (*Renderer_Init)(int width, int height, int pRender_width, int pRender_height);
// Called when beginning a 3D scene
void (*Renderer_BeginScene)(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer);
// Called at the end of a 3D scene
void (*Renderer_EndScene)();
// Render a fullscreen quad using the specified pixel data
void (*Renderer_FullScreenQuad)(uint8_t* src);
// Render a model
void (*Renderer_Model)(br_actor* actor, br_model* model, br_material* material, br_token render_type, br_matrix34 model_matrix);
// Clear frame and depth buffers
void (*Renderer_ClearBuffers)();
// Load pixelmap into video memory
void (*Renderer_BufferTexture)(br_pixelmap* pm);
// Load material
void (*Renderer_BufferMaterial)(br_material* mat);
// Load model into video memory
void (*Renderer_BufferModel)(br_model* model);
// Pull contents of frame and depth buffers from video into main memory for software effects
void (*Renderer_FlushBuffers)();
// Set the 256 color palette to use (BGRA format)
void (*Renderer_SetPalette)(PALETTEENTRY_* palette);
// Set the viewport for 3d rendering
void (*Renderer_SetViewport)(int x, int y, int width, int height);
// Create a window. Return a handle to the window
void* (*CreateWindowAndRenderer)(char* title, int x, int y, int nWidth, int nHeight);
// Get mouse button state
int (*GetMouseButtons)(int* button_1, int* button_2);
// Get mouse position
int (*GetMousePosition)(int* pX, int* pY);
// Close specified window
void (*DestroyWindow)(void* window);
// Process window messages, return any WM_QUIT message
int (*ProcessWindowMessages)(MSG_* msg);
// Set position of a window
int (*SetWindowPos)(void* hWnd, int x, int y, int nWidth, int nHeight);
// Show/hide the cursor
int (*ShowCursor)(int show);
// Get keyboard state. Expected to be in DirectInput key codes
void (*GetKeyboardState)(unsigned int count, uint8_t* buffer);
// Sleep
void (*Sleep)(uint32_t dwMilliseconds);
// Get ticks
uint32_t (*GetTicks)();
// Swap window
void (*SwapWindow)();
} tHarness_platform;
extern tHarness_platform gHarness_platform;
void Harness_Init(int* argc, char* argv[]); void Harness_Init(int* argc, char* argv[]);
// Hooks are called from original game code. // Hooks are called from original game code.
// Dethrace hooks
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_FlushRenderer(); // synchronize in-memory framebuffer and depthbuffer
void Harness_Hook_GraphicsInit(int render_width, int render_height);
void Harness_Hook_PDShutdownSystem();
// BRender hooks // BRender hooks
void Harness_Hook_BrDevPaletteSetOld(br_pixelmap* pm);
void Harness_Hook_BrDevPaletteSetEntryOld(int i, br_colour colour);
void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src); void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src);
void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db); void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db);
void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer);
void Harness_Hook_renderActor(br_actor* actor, br_model* model, br_material* material, br_token type); void Harness_Hook_renderActor(br_actor* actor, br_model* model, br_material* material, br_token type);
void Harness_Hook_BrZbSceneRenderEnd();
void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags);
void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags);
void Harness_Hook_BrModelUpdate(br_model* model);
// Input hooks
void Harness_Hook_GetMousePosition(int* pX, int* pY);
void Harness_Hook_GetMouseButtons(int* pButton1, int* pButton2);
// Sound hooks // Sound hooks
void Harness_Hook_S3Service(int unk1, int unk2); void Harness_Hook_S3Service(int unk1, int unk2);
@ -41,4 +79,6 @@ void Harness_Hook_S3StopAllOutletSounds();
// Filesystem hooks // Filesystem hooks
FILE* Harness_Hook_fopen(const char* pathname, const char* mode); FILE* Harness_Hook_fopen(const char* pathname, const char* mode);
void Harness_RenderLastScreen();
#endif #endif

View File

@ -23,32 +23,11 @@
#include <unistd.h> #include <unistd.h>
#endif #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 // Optional: install a handler to print stack trace during a crash
void OS_InstallSignalHandler(char* program_name); void OS_InstallSignalHandler(char* program_name);
FILE* OS_fopen(const char* pathname, const char* mode); FILE* OS_fopen(const char* pathname, const char* mode);
// Required: return a buffer for action replay. Preferably 20MB. If that is not available, then allocate a buffer of 12MB, 6MB, 4MB, 500kB or 64kiB
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size);
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen); size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen);
#endif #endif

View File

@ -42,10 +42,7 @@ void debug_print_matrix4(const char* fmt, const char* fn, char* name, br_matrix4
#define LOG_PANIC(...) \ #define LOG_PANIC(...) \
do { \ do { \
debug_printf("\033[0;31m[PANIC] %s ", __FUNCTION__, __VA_ARGS__); \ debug_printf("\033[0;31m[PANIC] %s ", __FUNCTION__, __VA_ARGS__); \
if (OS_IsDebuggerPresent()) { \ abort(); \
abort(); \
} \
exit(1); \
} while (0) } while (0)
#define LOG_WARN_ONCE(...) \ #define LOG_WARN_ONCE(...) \

View File

@ -0,0 +1,88 @@
#ifndef _POLYFILL_H_
#define _POLYFILL_H_
#include "harness/compiler.h"
#include "win95_polyfill_defs.h"
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
// All functions have a "_" suffix to avoid collisions with <windows.h>-defined types
uint32_t GetFileAttributesA_(char* path);
int SetFileAttributesA_(char* lpFileName, uint32_t dwFileAttributes);
void* CreateFileA_(
char* lpFileName,
uint32_t dwDesiredAccess,
uint32_t dwShareMode,
void* lpSecurityAttributes,
uint32_t dwCreationDisposition,
uint32_t dwFlagsAndAttributes,
void* hTemplateFile);
uint32_t GetFileSize_(
void* hFile,
uint32_t* lpFileSizeHigh);
int CloseHandle_(
void* hObject);
void GlobalMemoryStatus_(MEMORYSTATUS_* lpBuffer);
int GetCursorPos_(POINT_* lpPoint);
int ScreenToClient_(void* hWnd, POINT_* lpPoint);
uint32_t timeGetTime_();
uint32_t GetCurrentDirectoryA_(uint32_t nBufferLength, char* lpBuffer);
int SetCurrentDirectoryA_(char* lpPathName);
uint32_t GetShortPathNameA_(char* lpszLongPath, char* lpszShortPath, uint32_t cchBuffer);
HANDLE_ FindFirstFileA_(char* lpFileName, WIN32_FIND_DATAA_* lpFindFileData);
int FindNextFileA_(HANDLE_ hFindFile, WIN32_FIND_DATAA_* lpFindFileData);
int FindClose_(HANDLE_ hFindFile);
void* CreateWindowExA_(uint32_t dwExStyle, char* lpClassName, char* lpWindowName, uint32_t dwStyle, int X, int Y, int nWidth, int nHeight, void* hWndParent, void* hMenu, void* hInstance, void* lpParam);
int SetWindowPos_(void* hWnd, void* hWndInsertAfter, int X, int Y, int cx, int cy, unsigned int uFlags);
int ShowCursor_(int bShow);
int SendMessageA_(void* hWnd, unsigned int Msg, unsigned int wParam, long lParam);
int MessageBoxA_(void* hWnd, char* lpText, char* lpCaption, unsigned int uType);
int DestroyWindow_(void* hWnd);
HARNESS_NORETURN void ExitProcess_(unsigned int uExitCode);
void TranslateMessage_(MSG_* lpMsg);
void DispatchMessageA_(MSG_* lpMsg);
int PeekMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax, unsigned int wRemoveMsg);
int GetMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax);
void Sleep_(uint32_t dwMilliseconds);
void DirectDraw_CreateSurface();
void DirectDrawDevice_SetPaletteEntries(PALETTEENTRY_* palette, int pFirst_colour, int pCount);
void DirectInputDevice_GetDeviceState(unsigned int keys, uint8_t* buffer);
void _splitpath_(char* path, char* drive, char* dir, char* fname, char* ext);
int _CrtDbgReport_(int reportType, const char* filename, int linenumber, const char* moduleName, const char* format, ...);
#endif

View File

@ -0,0 +1,72 @@
#ifndef WIN95_POLYFILL_TYPES_H
#define WIN95_POLYFILL_TYPES_H
#include <stddef.h>
#include <stdint.h>
typedef void* HANDLE_;
#define GENERIC_READ 0x80000000
#define OPEN_EXISTING 3
#define FILE_ATTRIBUTE_NORMAL 0x80
#define INVALID_HANDLE_VALUE ((HANDLE_*)-1)
#define INVALID_FILE_ATTRIBUTES -1
#define FILE_ATTRIBUTE_READONLY 0x01
#define FILE_ATTRIBUTE_NORMAL 0x80
#define HWND_BROADCAST ((void*)0xffff)
#define _CRT_ASSERT 2
#define WM_QUIT 0x0012
typedef struct _MEMORYSTATUS_ {
uint32_t dwLength;
uint32_t dwMemoryLoad;
size_t dwTotalPhys;
size_t dwAvailPhys;
size_t dwTotalPageFile;
size_t dwAvailPageFile;
size_t dwTotalVirtual;
size_t dwAvailVirtual;
} MEMORYSTATUS_;
typedef struct tagPOINT_ {
long x;
long y;
} POINT_;
#pragma pack(push, 1)
typedef struct tagPALETTEENTRY_ {
uint8_t peRed;
uint8_t peGreen;
uint8_t peBlue;
uint8_t peFlags;
} PALETTEENTRY_;
#pragma pack(pop)
typedef struct _WIN32_FIND_DATA_ {
// uint32_t dwFileAttributes;
// FILETIME ftCreationTime;
// FILETIME ftLastAccessTime;
// FILETIME ftLastWriteTime;
// uint32_t nFileSizeHigh;
// uint32_t nFileSizeLow;
// uint32_t dwReserved0;
// uint32_t dwReserved1;
char cFileName[1024];
// char cAlternateFileName[14];
} WIN32_FIND_DATAA_;
typedef struct tagMSG_ {
void* hwnd;
unsigned int message;
int wParam;
long lParam;
uint32_t time;
POINT_ pt;
uint32_t lPrivate;
} MSG_;
#endif

View File

@ -1,16 +0,0 @@
#ifndef PLATFORM_H
#define PLATFORM_H
#include "../renderers/renderer.h"
void IOPlatform_Init();
tRenderer* IOPlatform_CreateWindow(char* title, int width, int height, int pRender_width, int pRender_height);
void IOPlatform_PollEvents(void);
void IOPlatform_SwapWindow(int delay_ms_after_swap);
int* IOPlatform_GetKeyMap(void);
int IOPlatform_IsKeyDown(unsigned char scan_code);
void IOPlatform_GetMousePosition(int* pX, int* pY);
void IOPlatform_GetMouseButtons(int* pButton1, int* pButton2);
void IOPlatform_Shutdown();
#endif

View File

@ -1,339 +0,0 @@
#include <glad/glad.h>
// this needs to be included after glad.h
#include <SDL.h>
#include <SDL_opengl.h>
#include "../renderers/gl/gl_renderer.h"
#include "../renderers/renderer.h"
#include "harness/config.h"
#include "harness/trace.h"
#include "globvars.h"
#include "grafdata.h"
#include "pd/sys.h"
extern void QuitGame();
#define ARRAY_LEN(array) (sizeof((array)) / sizeof((array)[0]))
int scancode_map[123];
const int scancodes_dethrace2sdl[123] = {
-1, // 0 (LSHIFT || RSHIFT)
-1, // 1 (LALT || RALT)
-1, // 2 (LCTRL || RCTRL)
-1, // 3 (LCTRL || RCTRL)
SDL_SCANCODE_CAPSLOCK, // 4
SDL_SCANCODE_RSHIFT, // 5
SDL_SCANCODE_RALT, // 6
SDL_SCANCODE_RCTRL, // 7
SDL_SCANCODE_LSHIFT, // 8
SDL_SCANCODE_LALT, // 9
SDL_SCANCODE_LCTRL, // 10
SDL_SCANCODE_0, // 11
SDL_SCANCODE_1, // 12
SDL_SCANCODE_2, // 13
SDL_SCANCODE_3, // 14
SDL_SCANCODE_4, // 15
SDL_SCANCODE_5, // 16
SDL_SCANCODE_6, // 17
SDL_SCANCODE_7, // 18
SDL_SCANCODE_8, // 19
SDL_SCANCODE_9, // 20
SDL_SCANCODE_A, // 21
SDL_SCANCODE_B, // 22
SDL_SCANCODE_C, // 23
SDL_SCANCODE_D, // 24
SDL_SCANCODE_E, // 25
SDL_SCANCODE_F, // 26
SDL_SCANCODE_G, // 27
SDL_SCANCODE_H, // 28
SDL_SCANCODE_I, // 29
SDL_SCANCODE_J, // 30
SDL_SCANCODE_K, // 31
SDL_SCANCODE_L, // 32
SDL_SCANCODE_M, // 33
SDL_SCANCODE_N, // 34
SDL_SCANCODE_O, // 35
SDL_SCANCODE_P, // 36
SDL_SCANCODE_Q, // 37
SDL_SCANCODE_R, // 38
SDL_SCANCODE_S, // 39
SDL_SCANCODE_T, // 40
SDL_SCANCODE_U, // 41
SDL_SCANCODE_V, // 42
SDL_SCANCODE_W, // 43
SDL_SCANCODE_X, // 44
SDL_SCANCODE_Y, // 45
SDL_SCANCODE_Z, // 46
SDL_SCANCODE_GRAVE, // 47
SDL_SCANCODE_MINUS, // 48
SDL_SCANCODE_EQUALS, // 49
SDL_SCANCODE_BACKSPACE, // 50
SDL_SCANCODE_RETURN, // 51
SDL_SCANCODE_KP_ENTER, // 52
SDL_SCANCODE_TAB, // 53
SDL_SCANCODE_SLASH, // 54
-1, // 55
SDL_SCANCODE_SEMICOLON, // 56
SDL_SCANCODE_APOSTROPHE, // 57
SDL_SCANCODE_PERIOD, // 58
SDL_SCANCODE_COMMA, // 59
SDL_SCANCODE_LEFTBRACKET, // 60
SDL_SCANCODE_RIGHTBRACKET, // 61
SDL_SCANCODE_BACKSLASH, // 62
SDL_SCANCODE_ESCAPE, // 63
SDL_SCANCODE_INSERT, // 64
SDL_SCANCODE_DELETE, // 65
SDL_SCANCODE_HOME, // 66
SDL_SCANCODE_END, // 67
SDL_SCANCODE_PAGEUP, // 68
SDL_SCANCODE_PAGEDOWN, // 69
SDL_SCANCODE_LEFT, // 70
SDL_SCANCODE_RIGHT, // 71
SDL_SCANCODE_UP, // 72
SDL_SCANCODE_DOWN, // 73
SDL_SCANCODE_NUMLOCKCLEAR, // 74
SDL_SCANCODE_KP_DIVIDE, // 75
SDL_SCANCODE_KP_MULTIPLY, // 76
SDL_SCANCODE_KP_MINUS, // 77
SDL_SCANCODE_KP_PLUS, // 78
SDL_SCANCODE_KP_PERIOD, // 79
SDL_SCANCODE_KP_EQUALS, // 80
SDL_SCANCODE_KP_0, // 81
SDL_SCANCODE_KP_1, // 82
SDL_SCANCODE_KP_2, // 83
SDL_SCANCODE_KP_3, // 84
SDL_SCANCODE_KP_4, // 85
SDL_SCANCODE_KP_5, // 86
SDL_SCANCODE_KP_6, // 87
SDL_SCANCODE_KP_7, // 88
SDL_SCANCODE_KP_8, // 89
SDL_SCANCODE_KP_9, // 90
SDL_SCANCODE_F1, // 91
SDL_SCANCODE_F2, // 92
SDL_SCANCODE_F3, // 93
SDL_SCANCODE_F4, // 94
SDL_SCANCODE_F5, // 95
SDL_SCANCODE_F6, // 96
SDL_SCANCODE_F7, // 97
SDL_SCANCODE_F8, // 98
SDL_SCANCODE_F9, // 99
SDL_SCANCODE_F10, // 100
SDL_SCANCODE_F11, // 101
SDL_SCANCODE_F12, // 102
SDL_SCANCODE_PRINTSCREEN, // 103
SDL_SCANCODE_SCROLLLOCK, // 104
SDL_SCANCODE_PAUSE, // 105
SDL_SCANCODE_SPACE, // 106
};
int scancodes_sdl2dethrace[SDL_NUM_SCANCODES];
SDL_Window* window;
SDL_GLContext context;
uint8_t sdl_key_state[256];
struct {
float x;
float y;
} sdl_window_scale;
tRenderer gl_renderer = {
GLRenderer_Init,
GLRenderer_BeginScene,
GLRenderer_EndScene,
GLRenderer_SetPalette,
GLRenderer_FullScreenQuad,
GLRenderer_Model,
GLRenderer_ClearBuffers,
GLRenderer_BufferTexture,
GLRenderer_BufferMaterial,
GLRenderer_BufferModel,
GLRenderer_FlushBuffers,
GLRenderer_GetRenderSize,
GLRenderer_GetWindowSize,
GLRenderer_SetWindowSize,
GLRenderer_GetViewport
};
tRenderer* IOPlatform_CreateWindow(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, 1);
SDL_GL_SetSwapInterval(1);
window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (window == NULL) {
LOG_PANIC("Failed to create window. %s", SDL_GetError());
}
sdl_window_scale.x = ((float)pRender_width) / width;
sdl_window_scale.y = ((float)pRender_height) / height;
if (harness_game_config.start_full_screen) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
SDL_ShowCursor(SDL_DISABLE);
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 IOPlatform_Shutdown() {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
window = NULL;
}
// Checks whether the `flag_check` is the only modifier applied.
// e.g. is_only_modifier(event.key.keysym.mod, KMOD_ALT) returns true when only the ALT key was pressed
static int is_only_key_modifier(int modifier_flags, int flag_check) {
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check);
}
void IOPlatform_PollEvents() {
SDL_Event event;
int dethrace_key;
int w_w, w_h;
int vp_x, vp_y;
int vp_w, vp_h;
int r_w, r_h;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_RETURN) {
if (event.key.type == SDL_KEYDOWN) {
if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI))) {
// Ignore keydown of RETURN when used together with some modifier
return;
}
} else if (event.key.type == SDL_KEYUP) {
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
SDL_SetWindowFullscreen(window, (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
}
dethrace_key = scancodes_sdl2dethrace[event.key.keysym.scancode];
if (dethrace_key == -1) {
LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
return;
}
sdl_key_state[scancodes_sdl2dethrace[event.key.keysym.scancode]] = event.type == SDL_KEYDOWN;
sdl_key_state[0] = sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_LSHIFT]] || sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_RSHIFT]];
sdl_key_state[1] = sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_LALT]] || sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_RALT]];
sdl_key_state[2] = sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_LCTRL]] || sdl_key_state[scancodes_sdl2dethrace[SDL_SCANCODE_RCTRL]];
sdl_key_state[3] = sdl_key_state[2];
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED:
SDL_GetWindowSize(window, &w_w, &w_h);
gl_renderer.SetWindowSize(w_w, w_h);
gl_renderer.GetViewport(&vp_x, &vp_y, &vp_w, &vp_h);
gl_renderer.GetRenderSize(&r_w, &r_h);
sdl_window_scale.x = (float)r_w / vp_w;
sdl_window_scale.y = (float)r_h / vp_h;
break;
}
break;
case SDL_QUIT:
QuitGame();
break;
}
}
}
void IOPlatform_SwapWindow(int delay_ms_after_swap) {
SDL_GL_SwapWindow(window);
if (delay_ms_after_swap != 0) {
SDL_Delay(delay_ms_after_swap);
}
}
void IOPlatform_Init() {
for (size_t i = 0; i < ARRAY_LEN(scancodes_sdl2dethrace); i++) {
scancodes_sdl2dethrace[i] = -1;
}
for (size_t i = 0; i < ARRAY_LEN(scancodes_dethrace2sdl); i++) {
if (scancodes_dethrace2sdl[i] != -1) {
scancodes_sdl2dethrace[scancodes_dethrace2sdl[i]] = i;
}
}
for (size_t i = 0; i < ARRAY_LEN(scancode_map); i++) {
scancode_map[i] = i;
}
}
int* IOPlatform_GetKeyMap() {
return (int*)scancode_map;
}
int IOPlatform_IsKeyDown(unsigned char scan_code) {
return sdl_key_state[scan_code];
}
void IOPlatform_GetMousePosition(int* pX, int* pY) {
int vp_x, vp_y, vp_w, vp_h;
SDL_GetMouseState(pX, pY);
gl_renderer.GetViewport(&vp_x, &vp_y, &vp_w, &vp_h);
if (*pX < vp_x) {
*pX = vp_x;
} else if (*pX >= vp_x + vp_w) {
*pX = vp_x + vp_w - 1;
}
if (*pY < vp_y) {
*pY = vp_y;
} else if (*pY >= vp_y + vp_h) {
*pY = vp_y + vp_h - 1;
}
*pX -= vp_x;
*pY -= vp_y;
*pX *= sdl_window_scale.x;
*pY *= sdl_window_scale.y;
#if defined(DETHRACE_FIX_BUGS)
// In hires mode (640x480), the menus are still rendered at (320x240),
// so prescale the cursor coordinates accordingly.
*pX *= gGraf_specs[gGraf_data_index].phys_width;
*pX /= gGraf_specs[gReal_graf_data_index].phys_width;
*pY *= gGraf_specs[gGraf_data_index].phys_height;
*pY /= gGraf_specs[gReal_graf_data_index].phys_height;
#endif
}
void IOPlatform_GetMouseButtons(int* pButton1, int* pButton2) {
int state = SDL_GetMouseState(NULL, NULL);
*pButton1 = state & SDL_BUTTON_LMASK;
*pButton2 = state & SDL_BUTTON_RMASK;
}

View File

@ -31,8 +31,6 @@ static char _program_name[1024];
#define MAX_STACK_FRAMES 64 #define MAX_STACK_FRAMES 64
static void* stack_traces[MAX_STACK_FRAMES]; static void* stack_traces[MAX_STACK_FRAMES];
#define TRACER_PID_STRING "TracerPid:" #define TRACER_PID_STRING "TracerPid:"
DIR* directory_iterator;
uint32_t first_clock_time = 0;
struct dl_iterate_callback_data { struct dl_iterate_callback_data {
int initialized; int initialized;
@ -56,85 +54,6 @@ static intptr_t get_dethrace_offset() {
return dethrace_dl_data.start; return dethrace_dl_data.start;
} }
uint32_t OS_GetTime() {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
if (first_clock_time == 0) {
first_clock_time = spec.tv_sec * 1000 + spec.tv_nsec / 1000000;
}
return (spec.tv_sec * 1000 + spec.tv_nsec / 1000000) - first_clock_time;
}
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 // 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) { int addr2line(char const* const program_name, void const* const addr) {
char addr2line_cmd[512] = { 0 }; char addr2line_cmd[512] = { 0 };
@ -341,34 +260,6 @@ FILE* OS_fopen(const char* pathname, const char* mode) {
return f; return f;
} }
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
unsigned i;
const int wanted_sizes[] = {
20000000,
16000000,
6000000,
4000000,
500000,
};
if (!allocated) {
allocated = 1;
buffer_size = 0;
for (i = 0; i < ARRAY_SIZE(wanted_sizes); i++) {
buffer = malloc(wanted_sizes[i]);
if (buffer != NULL) {
buffer_size = wanted_sizes[i];
break;
}
}
}
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) { size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
struct termios old, new; struct termios old, new;
char c; char c;

View File

@ -25,92 +25,6 @@ static int stack_nbr = 0;
static char _program_name[1024]; static char _program_name[1024];
#define MAX_STACK_FRAMES 64 #define MAX_STACK_FRAMES 64
static void* stack_traces[MAX_STACK_FRAMES]; static void* stack_traces[MAX_STACK_FRAMES];
DIR* directory_iterator;
uint32_t first_clock_time = 0;
uint32_t OS_GetTime() {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
if (first_clock_time == 0) {
first_clock_time = spec.tv_sec * 1000 + spec.tv_nsec / 1000000;
}
return (spec.tv_sec * 1000 + spec.tv_nsec / 1000000) - first_clock_time;
}
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 <sys/sysctl.h>) 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);
(void)junk;
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 // 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) { int addr2line(char const* const program_name, void const* const addr) {
@ -297,34 +211,6 @@ FILE* OS_fopen(const char* pathname, const char* mode) {
return fopen(pathname, mode); return fopen(pathname, mode);
} }
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
unsigned i;
const int wanted_sizes[] = {
20000000,
16000000,
6000000,
4000000,
500000,
};
if (!allocated) {
allocated = 1;
buffer_size = 0;
for (i = 0; i < ARRAY_SIZE(wanted_sizes); i++) {
buffer = malloc(wanted_sizes[i]);
if (buffer != NULL) {
buffer_size = wanted_sizes[i];
break;
}
}
}
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) { size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
// FIXME: unsafe implementation (echos the password) // FIXME: unsafe implementation (echos the password)
pBuffer[0] = '\0'; pBuffer[0] = '\0';

View File

@ -28,63 +28,6 @@ void dr_dprintf(char* fmt_string, ...);
static int stack_nbr = 0; static int stack_nbr = 0;
static char _program_name[1024]; 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;
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) { int addr2line(char const* const program_name, void const* const addr) {
char addr2line_cmd[512] = { 0 }; char addr2line_cmd[512] = { 0 };
@ -220,95 +163,6 @@ FILE* OS_fopen(const char* pathname, const char* mode) {
return f; return f;
} }
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
MEMORYSTATUS memory_status;
unsigned wanted;
if (allocated) {
*pBuffer = buffer;
*pBuffer_size = buffer_size;
return;
}
allocated = 1;
buffer = NULL;
memory_status.dwLength = sizeof(memory_status);
GlobalMemoryStatus(&memory_status);
dr_dprintf(
"Win32AllocateActionReplayBuffer(): Memory Status BEFORE Action Replay Allocation:\n"
" dwLength %u\n"
" dwMemoryLoad %u\n"
" dwTotalPhys %u\n"
" dwAvailPhys %u\n"
" dwTotalPageFile %u\n"
" dwAvailPageFile %u\n"
" dwTotalVirtual %u\n"
" dwAvailVirtual %u",
memory_status.dwLength,
memory_status.dwMemoryLoad,
memory_status.dwTotalPhys,
memory_status.dwAvailPhys,
memory_status.dwTotalPageFile,
memory_status.dwAvailPageFile,
memory_status.dwTotalVirtual,
memory_status.dwAvailVirtual);
wanted = 20000000;
if (memory_status.dwTotalPhys < 16000000) {
wanted = 500000;
} else if (memory_status.dwTotalPhys < 24000000) {
wanted = 4000000;
} else if (memory_status.dwTotalPhys < 32000000) {
wanted = 6000000;
} else if (memory_status.dwTotalPhys < 48000000) {
wanted = 12000000;
}
dr_dprintf("Win32AllocateActionReplayBuffer(): We want %d bytes...", wanted);
if (memory_status.dwAvailPageFile + memory_status.dwAvailPhys < wanted) {
wanted = (memory_status.dwAvailPageFile + memory_status.dwAvailPhys) - 0x100000;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but there's only %d bytes available...", wanted);
}
if (wanted < 0x10000) {
wanted = 0x10000;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but we have to have a minimum size of %d bytes...", wanted);
}
while (wanted >= 0x10000) {
buffer = malloc(wanted);
if (buffer != NULL) {
break;
}
}
if (buffer == NULL) {
buffer_size = 0;
} else {
buffer_size = wanted;
// Sleep(1000); // Commented out 1s sleep
}
dr_dprintf("Win32AllocateActionReplayBuffer(): Actually allocated %d bytes.", wanted);
GlobalMemoryStatus(&memory_status);
dr_dprintf(
"Win32AllocateActionReplayBuffer(): Memory Status AFTER Action Replay Allocation:\n"
" dwLength %u\n"
" dwMemoryLoad %u\n"
" dwTotalPhys %u\n"
" dwAvailPhys %u\n"
" dwTotalPageFile %u\n"
" dwAvailPageFile %u\n"
" dwTotalVirtual %u\n"
" dwAvailVirtual %u",
memory_status.dwLength,
memory_status.dwMemoryLoad,
memory_status.dwTotalPhys,
memory_status.dwAvailPhys,
memory_status.dwTotalPageFile,
memory_status.dwAvailPageFile,
memory_status.dwTotalVirtual,
memory_status.dwAvailVirtual);
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) { size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
// FIXME: unsafe implementation (echos the password) // FIXME: unsafe implementation (echos the password)
pBuffer[0] = '\0'; pBuffer[0] = '\0';

View File

@ -0,0 +1,83 @@
#ifndef PLATFORM_NULL
#define PLATFORM_NULL
#include "harness/hooks.h"
// todo: shouldnt depend on sdl...
#include <SDL.h>
void* null_create_window_and_renderer(char* title, int x, int y, int width, int height) {
return 0;
}
int null_set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
return 0;
}
void null_destroy_window(void* hWnd) {
}
int null_get_and_handle_message(MSG_* msg) {
return 0;
}
void null_swap_window() {
}
void null_get_keyboard_state(unsigned int count, uint8_t* buffer) {
}
int null_get_mouse_buttons(int* pButton1, int* pButton2) {
return 0;
}
int null_get_mouse_position(int* pX, int* pY) {
return 0;
}
int null_show_cursor(int show) {
return 0;
}
void NullRenderer_Init() {}
void NullRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {}
void NullRenderer_EndScene() {}
void NullRenderer_SetPalette(PALETTEENTRY_* palette) {}
void NullRenderer_FullScreenQuad(uint8_t* src) {}
void NullRenderer_Model(br_actor* actor, br_model* model, br_material* material, br_token render_type, br_matrix34 model_matrix) {}
void NullRenderer_RenderFrameBuffer() {}
void NullRenderer_ClearBuffers() {}
void NullRenderer_BufferTexture(br_pixelmap* pm) {}
void NullRenderer_BufferMaterial(br_material* mat) {}
void NullRenderer_BufferModel(br_model* model) {}
void NullRenderer_FlushBuffers() {}
void NullRenderer_SetViewport(int x, int y, int width, int height) {}
void Null_Platform_Init(tHarness_platform* platform) {
platform->ProcessWindowMessages = null_get_and_handle_message;
// todo: shouldnt depend on sdl...
platform->Sleep = SDL_Delay;
platform->GetTicks = SDL_GetTicks;
platform->CreateWindowAndRenderer = null_create_window_and_renderer;
platform->ShowCursor = null_show_cursor;
platform->SetWindowPos = null_set_window_pos;
platform->SwapWindow = null_swap_window;
platform->DestroyWindow = null_destroy_window;
platform->GetKeyboardState = null_get_keyboard_state;
platform->GetMousePosition = null_get_mouse_position;
platform->GetMouseButtons = null_get_mouse_buttons;
platform->DestroyWindow = null_destroy_window;
platform->Renderer_BufferModel = NullRenderer_BufferModel;
platform->Renderer_BufferMaterial = NullRenderer_BufferMaterial;
platform->Renderer_BufferTexture = NullRenderer_BufferTexture;
platform->Renderer_SetPalette = NullRenderer_SetPalette;
platform->Renderer_FullScreenQuad = NullRenderer_FullScreenQuad;
platform->Renderer_Model = NullRenderer_Model;
platform->Renderer_ClearBuffers = NullRenderer_ClearBuffers;
platform->Renderer_FlushBuffers = NullRenderer_FlushBuffers;
platform->Renderer_BeginScene = NullRenderer_BeginScene;
platform->Renderer_EndScene = NullRenderer_EndScene;
platform->Renderer_SetViewport = NullRenderer_SetViewport;
}
#endif

View File

@ -0,0 +1,392 @@
/*
* Maps SDL2 scancodes to directinput keynums/scancodes.
* Useful if you're porting a game that uses dinput scancodes internally
* (for key bindings etc) or any other lib (like CEGUI) that uses them.
*
* (C) 2015 Daniel Gibson
*
* Homepage: https://github.com/DanielGibson/Snippets/
*
* License:
* This software is dual-licensed to the public domain and under the following
* license: you are granted a perpetual, irrevocable license to copy, modify,
* publish, and distribute this file as you see fit.
* No warranty implied; use at your own risk.
*
* So you can do whatever you want with this code, including copying it
* (or parts of it) into your own source.
* No need to mention me or this "license" in your code or docs, even though
* it would be appreciated, of course.
*
*/
#include <glad/glad.h>
#include <SDL.h>
#if 0 // Usage Example:
#include "sdl2_scancode_to_dinput.h"
static int SDLScanCodeToKeyNum(SDL_Scancode sc)
{
int idx = (int)sc;
assert(idx >= 0 && idx < SDL_NUM_SCANCODES);
return scanCodeToKeyNum[idx];
}
static SDL_Scancode KeyNumToSDLScanCode( int keyNum )
{
if( keyNum >= 0 && keyNum < 0xEF )
{
for(int i = 0; i < SDL_NUM_SCANCODES; ++i)
{
if(scanCodeToKeyNum[i] == keyNum) return (SDL_Scancode)i;
}
}
return SDL_SCANCODE_UNKNOWN;
}
#endif // 0
#ifndef _SDL2_SCANCODE_TO_DINPUT_H_
#define _SDL2_SCANCODE_TO_DINPUT_H_
// TODO: map the following keys, if possible:
// #define DIK_UNDERLINE 0x93 /* (NEC PC98) */
// #define DIK_KANJI 0x94 /* (Japanese keyboard) */
// #define DIK_AX 0x96 /* (Japan AX) */
// #define DIK_UNLABELED 0x97 /* (J3100) */
//
// #define DIK_WAKE 0xE3 /* System Wake */
//
// (#define DIK_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */ - system should map this to KP_COMMA or something,
// according to USB doc, so probably it doesn't need mapping here)
// maps SDL2 scancodes to directinput keynums/scancodes - dinput_key = sdlScanCodeToDirectInputKeyNum[(int)your_sdl2_scancode];
static int sdlScanCodeToDirectInputKeyNum[SDL_NUM_SCANCODES] = {
0x0, // SDL_SCANCODE_UNKNOWN = 0, => 0 should also work for dinput codes as "not assigned/unknown"
0x0, // // 1 (unused)
0x0, // // 2 (unused)
0x0, // // 3 (unused)
0x1E, // SDL_SCANCODE_A = 4, - DIK_A
0x30, // SDL_SCANCODE_B = 5, - DIK_B
0x2E, // SDL_SCANCODE_C = 6, - DIK_C
0x20, // SDL_SCANCODE_D = 7, - DIK_D
0x12, // SDL_SCANCODE_E = 8, - DIK_E
0x21, // SDL_SCANCODE_F = 9, - DIK_F
0x22, // SDL_SCANCODE_G = 10, - DIK_G
0x23, // SDL_SCANCODE_H = 11, - DIK_H
0x17, // SDL_SCANCODE_I = 12, - DIK_I
0x24, // SDL_SCANCODE_J = 13, - DIK_J
0x25, // SDL_SCANCODE_K = 14, - DIK_K
0x26, // SDL_SCANCODE_L = 15, - DIK_L
0x32, // SDL_SCANCODE_M = 16, - DIK_M
0x31, // SDL_SCANCODE_N = 17, - DIK_N
0x18, // SDL_SCANCODE_O = 18, - DIK_O
0x19, // SDL_SCANCODE_P = 19, - DIK_P
0x10, // SDL_SCANCODE_Q = 20, - DIK_Q
0x13, // SDL_SCANCODE_R = 21, - DIK_R
0x1F, // SDL_SCANCODE_S = 22, - DIK_S
0x14, // SDL_SCANCODE_T = 23, - DIK_T
0x16, // SDL_SCANCODE_U = 24, - DIK_U
0x2F, // SDL_SCANCODE_V = 25, - DIK_V
0x11, // SDL_SCANCODE_W = 26, - DIK_W
0x2D, // SDL_SCANCODE_X = 27, - DIK_X
0x15, // SDL_SCANCODE_Y = 28, - DIK_Y
0x2C, // SDL_SCANCODE_Z = 29, - DIK_Z
0x02, // SDL_SCANCODE_1 = 30, - DIK_1
0x03, // SDL_SCANCODE_2 = 31, - DIK_2
0x04, // SDL_SCANCODE_3 = 32, - DIK_3
0x05, // SDL_SCANCODE_4 = 33, - DIK_4
0x06, // SDL_SCANCODE_5 = 34, - DIK_5
0x07, // SDL_SCANCODE_6 = 35, - DIK_6
0x08, // SDL_SCANCODE_7 = 36, - DIK_7
0x09, // SDL_SCANCODE_8 = 37, - DIK_8
0x0A, // SDL_SCANCODE_9 = 38, - DIK_9
0x0B, // SDL_SCANCODE_0 = 39, - DIK_0
0x1C, // SDL_SCANCODE_RETURN = 40, - DIK_RETURN
0x01, // SDL_SCANCODE_ESCAPE = 41, - DIK_ESCAPE
0x0E, // SDL_SCANCODE_BACKSPACE = 42, - DIK_BACK
0x0F, // SDL_SCANCODE_TAB = 43, - DIK_TAB
0x39, // SDL_SCANCODE_SPACE = 44, - DIK_SPACE
0x0C, // SDL_SCANCODE_MINUS = 45, - DIK_MINUS
0x0D, // SDL_SCANCODE_EQUALS = 46, - DIK_EQUALS
0x1A, // SDL_SCANCODE_LEFTBRACKET = 47, - DIK_LBRACKET
0x1B, // SDL_SCANCODE_RIGHTBRACKET = 48, - DIK_RBRACKET
0x2B, // SDL_SCANCODE_BACKSLASH = 49, // next to enter, US: [\|] DE: [#'] UK: [#~] - DIK_BACKSLASH
0x2B, // SDL_SCANCODE_NONUSHASH = 50, // same key as before actually on some layouts, systems should map this to SDL_SCANCODE_BACKSLASH - DIK_BACKSLASH
0x27, // SDL_SCANCODE_SEMICOLON = 51, - DIK_SEMICOLON
0x28, // SDL_SCANCODE_APOSTROPHE = 52, - DIK_APOSTROPHE
0x29, // SDL_SCANCODE_GRAVE = 53, // "quake/doom3 console key" - DIK_GRAVE
0x33, // SDL_SCANCODE_COMMA = 54, - DIK_COMMA
0x34, // SDL_SCANCODE_PERIOD = 55, - DIK_PERIOD
0x35, // SDL_SCANCODE_SLASH = 56, - DIK_SLASH
0x3A, // SDL_SCANCODE_CAPSLOCK = 57, - DIK_CAPITAL
0x3B, // SDL_SCANCODE_F1 = 58, - DIK_F1
0x3C, // SDL_SCANCODE_F2 = 59, - DIK_F2
0x3D, // SDL_SCANCODE_F3 = 60, - DIK_F3
0x3E, // SDL_SCANCODE_F4 = 61, - DIK_F4
0x3F, // SDL_SCANCODE_F5 = 62, - DIK_F5
0x40, // SDL_SCANCODE_F6 = 63, - DIK_F6
0x41, // SDL_SCANCODE_F7 = 64, - DIK_F7
0x42, // SDL_SCANCODE_F8 = 65, - DIK_F8
0x43, // SDL_SCANCODE_F9 = 66, - DIK_F9
0x44, // SDL_SCANCODE_F10 = 67, - DIK_F10
0x57, // SDL_SCANCODE_F11 = 68, - DIK_F11
0x58, // SDL_SCANCODE_F12 = 69, - DIK_F12
0xB7, // SDL_SCANCODE_PRINTSCREEN = 70, // - DIK_SYSRQ; SDL_SCANCODE_SYSREQ also maps to this!
0x46, // SDL_SCANCODE_SCROLLLOCK = 71, - DIK_SCROLL
0xC5, // SDL_SCANCODE_PAUSE = 72, - DIK_PAUSE
0xD2, // SDL_SCANCODE_INSERT = 73, // insert on PC, help on some Mac keyboards (but does send code 73, not 117) - DIK_INSERT
0xC7, // SDL_SCANCODE_HOME = 74, - DIK_HOME
0xC9, // SDL_SCANCODE_PAGEUP = 75, - DIK_PRIOR
0xD3, // SDL_SCANCODE_DELETE = 76, - DIK_DELETE
0xCF, // SDL_SCANCODE_END = 77, - DIK_END
0xD1, // SDL_SCANCODE_PAGEDOWN = 78, - DIK_NEXT
0xCD, // SDL_SCANCODE_RIGHT = 79, - DIK_RIGHT
0xCB, // SDL_SCANCODE_LEFT = 80, - DIK_LEFT
0xD0, // SDL_SCANCODE_DOWN = 81, - DIK_DOWN
0xC8, // SDL_SCANCODE_UP = 82, - DIK_UP
0x45, // SDL_SCANCODE_NUMLOCKCLEAR = 83, // num lock on PC, clear on Mac keyboards - DIK_NUMLOCK
0xB5, // SDL_SCANCODE_KP_DIVIDE = 84, - DIK_DIVIDE
0x37, // SDL_SCANCODE_KP_MULTIPLY = 85, - DIK_MULTIPLY
0x4A, // SDL_SCANCODE_KP_MINUS = 86, - DIK_SUBTRACT
0x4E, // SDL_SCANCODE_KP_PLUS = 87, - DIK_ADD
0x9C, // SDL_SCANCODE_KP_ENTER = 88, - DIK_NUMPADENTER
0x4F, // SDL_SCANCODE_KP_1 = 89, - DIK_NUMPAD1
0x50, // SDL_SCANCODE_KP_2 = 90, - DIK_NUMPAD2
0x51, // SDL_SCANCODE_KP_3 = 91, - DIK_NUMPAD3
0x4B, // SDL_SCANCODE_KP_4 = 92, - DIK_NUMPAD4
0x4C, // SDL_SCANCODE_KP_5 = 93, - DIK_NUMPAD5
0x4D, // SDL_SCANCODE_KP_6 = 94, - DIK_NUMPAD6
0x47, // SDL_SCANCODE_KP_7 = 95, - DIK_NUMPAD7
0x48, // SDL_SCANCODE_KP_8 = 96, - DIK_NUMPAD8
0x49, // SDL_SCANCODE_KP_9 = 97, - DIK_NUMPAD9
0x52, // SDL_SCANCODE_KP_0 = 98, - DIK_NUMPAD0
0x53, // SDL_SCANCODE_KP_PERIOD = 99, - DIK_DECIMAL
0x56, // SDL_SCANCODE_NONUSBACKSLASH = 100, // [<>|] on german keyboard, next to left shift - DIK_OEM_102
0xDD, // SDL_SCANCODE_APPLICATION = 101, // windows contextual menu, compose - DIK_APPS
0xDE, // SDL_SCANCODE_POWER = 102, // should be a status flag, but some mac keyboards have a power key - DIK_POWER
0x8D, // SDL_SCANCODE_KP_EQUALS = 103, - DIK_NUMPADEQUALS
0x64, // SDL_SCANCODE_F13 = 104, - DIK_F13
0x65, // SDL_SCANCODE_F14 = 105, - DIK_F14
0x66, // SDL_SCANCODE_F15 = 106, - DIK_F15
0x67, // SDL_SCANCODE_F16 = 107, // TODO: F16 and up don't have DIK_ constants! is this right?
0x68, // SDL_SCANCODE_F17 = 108, // (at least 0x67-0x6F have no DIK_constants at all)
0x69, // SDL_SCANCODE_F18 = 109,
0x6A, // SDL_SCANCODE_F19 = 110,
0x6B, // SDL_SCANCODE_F20 = 111,
0x6C, // SDL_SCANCODE_F21 = 112,
0x6D, // SDL_SCANCODE_F22 = 113,
0x6E, // SDL_SCANCODE_F23 = 114,
0x6F, // SDL_SCANCODE_F24 = 115,
0x0, // SDL_SCANCODE_EXECUTE = 116,
0x0, // SDL_SCANCODE_HELP = 117,
0x0, // SDL_SCANCODE_MENU = 118,
0x0, // SDL_SCANCODE_SELECT = 119,
0x95, // SDL_SCANCODE_STOP = 120, - DIK_STOP
0x0, // SDL_SCANCODE_AGAIN = 121, // redo
0x0, // SDL_SCANCODE_UNDO = 122,
0x0, // SDL_SCANCODE_CUT = 123,
0x0, // SDL_SCANCODE_COPY = 124,
0x0, // SDL_SCANCODE_PASTE = 125,
0x0, // SDL_SCANCODE_FIND = 126,
0x0, // SDL_SCANCODE_MUTE = 127,
0xB0, // SDL_SCANCODE_VOLUMEUP = 128, - DIK_VOLUMEUP
0xAE, // SDL_SCANCODE_VOLUMEDOWN = 129, - DIK_VOLUMEDOWN
// /* not sure whether there's a reason to enable these */
0x0, // /* SDL_SCANCODE_LOCKINGCAPSLOCK = 130, */
0x0, // /* SDL_SCANCODE_LOCKINGNUMLOCK = 131, */
0x0, // /* SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */
0xB3, // SDL_SCANCODE_KP_COMMA = 133, - DIK_NUMPADCOMMA
0x0, // SDL_SCANCODE_KP_EQUALSAS400 = 134,
0x73, // SDL_SCANCODE_INTERNATIONAL1 = 135, // this is really brazilian / and ? - DIK_ABNT_C1
0x0, // SDL_SCANCODE_INTERNATIONAL2 = 136, // TODO: Hut1_12v2.pdf page 60, footnote 16
0x7D, // SDL_SCANCODE_INTERNATIONAL3 = 137, - DIK_YEN
0x79, // SDL_SCANCODE_INTERNATIONAL4 = 138, // Japan: XFER/"convert kana -> kanji", right of space - DIK_CONVERT
0x7B, // SDL_SCANCODE_INTERNATIONAL5 = 139, // Japan: NFER/"don't convert kana -> kanji", left of space - DIK_NOCONVERT
0x0, // SDL_SCANCODE_INTERNATIONAL6 = 140, // TODO: Hut1_12v2.pdf page 60, footnote 20
0x0, // SDL_SCANCODE_INTERNATIONAL7 = 141, // Toggle Double-Byte/Single-Byte mode.
0x0, // SDL_SCANCODE_INTERNATIONAL8 = 142, // Undefined, available for other Front End Language Processors
0x0, // SDL_SCANCODE_INTERNATIONAL9 = 143, // Undefined, available for other Front End Language Processors
0x0, // SDL_SCANCODE_LANG1 = 144, // Hangul/English toggle (Korea)
0x0, // SDL_SCANCODE_LANG2 = 145, // Hanja conversion (Korea)
0x70, // SDL_SCANCODE_LANG3 = 146, // Katakana (Japan) - DIK_KANA
0x0, // SDL_SCANCODE_LANG4 = 147, // Hiragana (Japan)
0x0, // SDL_SCANCODE_LANG5 = 148, // Zenkaku/Hankaku (Japan)
0x0, // SDL_SCANCODE_LANG6 = 149, // reserved
0x0, // SDL_SCANCODE_LANG7 = 150, // reserved
0x0, // SDL_SCANCODE_LANG8 = 151, // reserved
0x0, // SDL_SCANCODE_LANG9 = 152, // reserved
0x0, // SDL_SCANCODE_ALTERASE = 153, // Erase-Eaze
0xB7, // SDL_SCANCODE_SYSREQ = 154, - DIK_SYSRQ; SDL_SCANCODE_PRINTSCREEN also maps to this!
0x0, // SDL_SCANCODE_CANCEL = 155,
0x0, // SDL_SCANCODE_CLEAR = 156,
0x0, // SDL_SCANCODE_PRIOR = 157,
0x0, // SDL_SCANCODE_RETURN2 = 158,
0x0, // SDL_SCANCODE_SEPARATOR = 159,
0x0, // SDL_SCANCODE_OUT = 160,
0x0, // SDL_SCANCODE_OPER = 161,
0x0, // SDL_SCANCODE_CLEARAGAIN = 162,
0x0, // SDL_SCANCODE_CRSEL = 163,
0x0, // SDL_SCANCODE_EXSEL = 164,
0x0, // 165 (unused)
0x0, // 166 (unused)
0x0, // 167 (unused)
0x0, // 168 (unused)
0x0, // 169 (unused)
0x0, // 170 (unused)
0x0, // 171 (unused)
0x0, // 172 (unused)
0x0, // 173 (unused)
0x0, // 174 (unused)
0x0, // 175 (unused)
0x0, // SDL_SCANCODE_KP_00 = 176,
0x0, // SDL_SCANCODE_KP_000 = 177,
0x0, // SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
0x0, // SDL_SCANCODE_DECIMALSEPARATOR = 179,
0x0, // SDL_SCANCODE_CURRENCYUNIT = 180,
0x0, // SDL_SCANCODE_CURRENCYSUBUNIT = 181,
0x0, // SDL_SCANCODE_KP_LEFTPAREN = 182,
0x0, // SDL_SCANCODE_KP_RIGHTPAREN = 183,
0x0, // SDL_SCANCODE_KP_LEFTBRACE = 184,
0x0, // SDL_SCANCODE_KP_RIGHTBRACE = 185,
0x0, // SDL_SCANCODE_KP_TAB = 186,
0x0, // SDL_SCANCODE_KP_BACKSPACE = 187,
0x0, // SDL_SCANCODE_KP_A = 188,
0x0, // SDL_SCANCODE_KP_B = 189,
0x0, // SDL_SCANCODE_KP_C = 190,
0x0, // SDL_SCANCODE_KP_D = 191,
0x0, // SDL_SCANCODE_KP_E = 192,
0x0, // SDL_SCANCODE_KP_F = 193,
0x0, // SDL_SCANCODE_KP_XOR = 194,
0x0, // SDL_SCANCODE_KP_POWER = 195,
0x0, // SDL_SCANCODE_KP_PERCENT = 196,
0x0, // SDL_SCANCODE_KP_LESS = 197,
0x0, // SDL_SCANCODE_KP_GREATER = 198,
0x0, // SDL_SCANCODE_KP_AMPERSAND = 199,
0x0, // SDL_SCANCODE_KP_DBLAMPERSAND = 200,
0x0, // SDL_SCANCODE_KP_VERTICALBAR = 201,
0x0, // SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
0x92, // SDL_SCANCODE_KP_COLON = 203, - DIK_COLON
0x0, // SDL_SCANCODE_KP_HASH = 204,
0x0, // SDL_SCANCODE_KP_SPACE = 205,
0x91, // SDL_SCANCODE_KP_AT = 206, - DIK_AT
0x0, // SDL_SCANCODE_KP_EXCLAM = 207,
0x0, // SDL_SCANCODE_KP_MEMSTORE = 208,
0x0, // SDL_SCANCODE_KP_MEMRECALL = 209,
0x0, // SDL_SCANCODE_KP_MEMCLEAR = 210,
0x0, // SDL_SCANCODE_KP_MEMADD = 211,
0x0, // SDL_SCANCODE_KP_MEMSUBTRACT = 212,
0x0, // SDL_SCANCODE_KP_MEMMULTIPLY = 213,
0x0, // SDL_SCANCODE_KP_MEMDIVIDE = 214,
0x0, // SDL_SCANCODE_KP_PLUSMINUS = 215,
0x0, // SDL_SCANCODE_KP_CLEAR = 216,
0x0, // SDL_SCANCODE_KP_CLEARENTRY = 217,
0x0, // SDL_SCANCODE_KP_BINARY = 218,
0x0, // SDL_SCANCODE_KP_OCTAL = 219,
0x0, // SDL_SCANCODE_KP_DECIMAL = 220,
0x0, // SDL_SCANCODE_KP_HEXADECIMAL = 221,
0x0, // 222 (unused)
0x0, // 223 (unused)
0x1D, // SDL_SCANCODE_LCTRL = 224, - DIK_LCONTROL
0x2A, // SDL_SCANCODE_LSHIFT = 225, - DIK_LSHIFT
0x38, // SDL_SCANCODE_LALT = 226, // left Alt, option - DIK_LMENU
0xDB, // SDL_SCANCODE_LGUI = 227, // left windows, command (apple), meta - DIK_LWIN
0x9D, // SDL_SCANCODE_RCTRL = 228, - DIK_RCONTROL
0x36, // SDL_SCANCODE_RSHIFT = 229, - DIK_RSHIFT
0xB8, // SDL_SCANCODE_RALT = 230, // right Alt/AltGr, option - DIK_RMENU, also used for SDL_SCANCODE_MODE!
0xDC, // SDL_SCANCODE_RGUI = 231, // left windows, command (apple), meta - DIK_RWIN
// 232 - 256 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, // 232 - 240 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 241-250 unused
0, 0, 0, 0, 0, 0, // 251-256 unused
0xB8, // SDL_SCANCODE_MODE = 257, // this seems to be the AltGr Key? - DIK_RMENU (right alt)
// These values are mapped from usage page 0x0C (USB consumer page).
0x99, // SDL_SCANCODE_AUDIONEXT = 258, - DIK_NEXTTRACK
0x90, // SDL_SCANCODE_AUDIOPREV = 259, - DIK_PREVTRACK, which is DIK_CIRCUMFLEX on japanese keyboards
0xA4, // SDL_SCANCODE_AUDIOSTOP = 260, - DIK_MEDIASTOP
0xA2, // SDL_SCANCODE_AUDIOPLAY = 261, - DIK_PLAYPAUSE
0xA0, // SDL_SCANCODE_AUDIOMUTE = 262, - DIK_MUTE
0xED, // SDL_SCANCODE_MEDIASELECT = 263, - DIK_MEDIASELECT
0x0, // SDL_SCANCODE_WWW = 264,
0xEC, // SDL_SCANCODE_MAIL = 265, - DIK_MAIL
0xA1, // SDL_SCANCODE_CALCULATOR = 266, - DIK_CALCULATOR
0xEB, // SDL_SCANCODE_COMPUTER = 267, - DIK_MYCOMPUTER
0xE5, // SDL_SCANCODE_AC_SEARCH = 268, - DIK_WEBSEARCH
0xB2, // SDL_SCANCODE_AC_HOME = 269, - DIK_WEBHOME
0xEA, // SDL_SCANCODE_AC_BACK = 270, - DIK_WEBBACK
0xE9, // SDL_SCANCODE_AC_FORWARD = 271, - DIK_WEBFORWARD
0xE8, // SDL_SCANCODE_AC_STOP = 272, - DIK_WEBSTOP
0xE7, // SDL_SCANCODE_AC_REFRESH = 273, - DIK_WEBREFRESH
0xE6, // SDL_SCANCODE_AC_BOOKMARKS = 274, - DIK_WEBFAVORITES
// These are values that Christian Walther added (for mac keyboard?).
0x0, // SDL_SCANCODE_BRIGHTNESSDOWN = 275,
0x0, // SDL_SCANCODE_BRIGHTNESSUP = 276,
0x0, // SDL_SCANCODE_DISPLAYSWITCH = 277, // display mirroring/dual display switch, video mode switch
0x0, // SDL_SCANCODE_KBDILLUMTOGGLE = 278,
0x0, // SDL_SCANCODE_KBDILLUMDOWN = 279,
0x0, // SDL_SCANCODE_KBDILLUMUP = 280,
0x0, // SDL_SCANCODE_EJECT = 281,
0xDF, // SDL_SCANCODE_SLEEP = 282, - DIK_SLEEP
0x0, // SDL_SCANCODE_APP1 = 283,
0x0, // SDL_SCANCODE_APP2 = 284,
// end of Walther-keys
// the rest up to 511 are currently not named in SDL
0, 0, 0, 0, 0, 0, // 285-290 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 291-300 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 301-320 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 321-340 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 341-360 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 361-380 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 381-400 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 401-420 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 421-440 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 441-460 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 461-480 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 481-500 unused
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 501-511 unused
};
#endif /* _SDL2_SCANCODE_TO_DINPUT_H_ */

View File

@ -0,0 +1,247 @@
#include <glad/glad.h>
// this needs to be included after glad.h
#include <SDL.h>
#include <SDL_opengl.h>
#include "../renderers/gl/gl_renderer.h"
#include "harness/config.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "sdl2_scancode_to_dinput.h"
#include "globvars.h"
#include "grafdata.h"
#include "pd/sys.h"
SDL_Window* window;
SDL_GLContext context;
uint8_t directinput_key_state[SDL_NUM_SCANCODES];
int render_width, render_height;
int window_width, window_height;
int vp_x, vp_y, vp_width, vp_height;
struct {
float x;
float y;
} sdl_window_scale;
static void update_viewport() {
const float target_aspect_ratio = (float)render_width / render_height;
const float aspect_ratio = (float)window_width / window_height;
vp_width = window_width;
vp_height = window_height;
if (aspect_ratio != target_aspect_ratio) {
if (aspect_ratio > target_aspect_ratio) {
vp_width = window_height * target_aspect_ratio + .5f;
} else {
vp_height = window_width / target_aspect_ratio + .5f;
}
}
vp_x = (window_width - vp_width) / 2;
vp_y = (window_height - vp_height) / 2;
GLRenderer_SetViewport(vp_x, vp_y, vp_width, vp_height);
}
void* create_window_and_renderer(char* title, int x, int y, int width, int height) {
window_width = width;
window_height = height;
render_width = width;
render_height = 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, 1);
SDL_GL_SetSwapInterval(1);
window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (window == NULL) {
LOG_PANIC("Failed to create window. %s", SDL_GetError());
}
sdl_window_scale.x = ((float)render_width) / width;
sdl_window_scale.y = ((float)render_height) / height;
if (harness_game_config.start_full_screen) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
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);
}
GLRenderer_Init(render_width, render_height);
update_viewport();
return window;
}
int set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
// SDL_SetWindowPosition(hWnd, x, y);
if (nWidth == 320 && nHeight == 200) {
nWidth = 640;
nHeight = 400;
}
SDL_SetWindowSize(hWnd, nWidth, nHeight);
return 0;
}
void destroy_window(void* hWnd) {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
window = NULL;
}
// Checks whether the `flag_check` is the only modifier applied.
// e.g. is_only_modifier(event.key.keysym.mod, KMOD_ALT) returns true when only the ALT key was pressed
static int is_only_key_modifier(int modifier_flags, int flag_check) {
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check);
}
int get_and_handle_message(MSG_* msg) {
SDL_Event event;
int dinput_key;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_RETURN) {
if (event.key.type == SDL_KEYDOWN) {
if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI))) {
// Ignore keydown of RETURN when used together with some modifier
return 0;
}
} else if (event.key.type == SDL_KEYUP) {
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
SDL_SetWindowFullscreen(window, (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
}
// Map incoming SDL scancode to DirectInput DIK_* key code.
// https://github.com/DanielGibson/Snippets/blob/master/sdl2_scancode_to_dinput.h
dinput_key = sdlScanCodeToDirectInputKeyNum[event.key.keysym.scancode];
if (dinput_key == 0) {
LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
return 0;
}
// DInput expects high bit to be set if key is down
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee418261(v=vs.85)
directinput_key_state[dinput_key] = (event.type == SDL_KEYDOWN ? 0x80 : 0);
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED:
SDL_GetWindowSize(window, &window_width, &window_height);
update_viewport();
sdl_window_scale.x = (float)render_width / vp_width;
sdl_window_scale.y = (float)render_height / vp_height;
break;
}
break;
case SDL_QUIT:
msg->message = WM_QUIT;
return 1;
}
}
return 0;
}
void swap_window() {
SDL_GL_SwapWindow(window);
}
void get_keyboard_state(unsigned int count, uint8_t* buffer) {
memcpy(buffer, directinput_key_state, count);
}
int get_mouse_buttons(int* pButton1, int* pButton2) {
int state = SDL_GetMouseState(NULL, NULL);
*pButton1 = state & SDL_BUTTON_LMASK;
*pButton2 = state & SDL_BUTTON_RMASK;
return 0;
}
int get_mouse_position(int* pX, int* pY) {
SDL_GetMouseState(pX, pY);
if (*pX < vp_x) {
*pX = vp_x;
} else if (*pX >= vp_x + vp_width) {
*pX = vp_x + vp_width - 1;
}
if (*pY < vp_y) {
*pY = vp_y;
} else if (*pY >= vp_y + vp_height) {
*pY = vp_y + vp_height - 1;
}
*pX -= vp_x;
*pY -= vp_y;
*pX *= sdl_window_scale.x;
*pY *= sdl_window_scale.y;
#if defined(DETHRACE_FIX_BUGS)
// In hires mode (640x480), the menus are still rendered at (320x240),
// so prescale the cursor coordinates accordingly.
*pX *= gGraf_specs[gGraf_data_index].phys_width;
*pX /= gGraf_specs[gReal_graf_data_index].phys_width;
*pY *= gGraf_specs[gGraf_data_index].phys_height;
*pY /= gGraf_specs[gReal_graf_data_index].phys_height;
#endif
return 0;
}
void set_palette(PALETTEENTRY_* pal) {
GLRenderer_SetPalette((uint8_t*)pal);
}
void Harness_Platform_Init(tHarness_platform* platform) {
platform->ProcessWindowMessages = get_and_handle_message;
platform->Sleep = SDL_Delay;
platform->GetTicks = SDL_GetTicks;
platform->CreateWindowAndRenderer = create_window_and_renderer;
platform->ShowCursor = SDL_ShowCursor;
platform->SetWindowPos = set_window_pos;
platform->SwapWindow = swap_window;
platform->DestroyWindow = destroy_window;
platform->GetKeyboardState = get_keyboard_state;
platform->GetMousePosition = get_mouse_position;
platform->GetMouseButtons = get_mouse_buttons;
platform->DestroyWindow = destroy_window;
platform->Renderer_BufferModel = GLRenderer_BufferModel;
platform->Renderer_BufferMaterial = GLRenderer_BufferMaterial;
platform->Renderer_BufferTexture = GLRenderer_BufferTexture;
platform->Renderer_SetPalette = set_palette;
platform->Renderer_FullScreenQuad = GLRenderer_FullScreenQuad;
platform->Renderer_Model = GLRenderer_Model;
platform->Renderer_ClearBuffers = GLRenderer_ClearBuffers;
platform->Renderer_FlushBuffers = GLRenderer_FlushBuffers;
platform->Renderer_BeginScene = GLRenderer_BeginScene;
platform->Renderer_EndScene = GLRenderer_EndScene;
platform->Renderer_SetViewport = GLRenderer_SetViewport;
}

View File

@ -26,10 +26,11 @@ static uint8_t gl_palette[4 * 256]; // RGBA
static uint8_t* screen_buffer_flip_pixels; static uint8_t* screen_buffer_flip_pixels;
static uint16_t* depth_buffer_flip_pixels; static uint16_t* depth_buffer_flip_pixels;
static int window_width, window_height, render_width, render_height; static int render_width, render_height;
static int vp_x, vp_y, vp_width, vp_height; static int vp_x, vp_y, vp_width, vp_height;
static br_pixelmap *last_colour_buffer, *last_depth_buffer; static br_pixelmap *last_colour_buffer,
*last_depth_buffer;
static int dirty_buffers = 0; static int dirty_buffers = 0;
static br_pixelmap *last_colour_buffer, *last_depth_buffer; static br_pixelmap *last_colour_buffer, *last_depth_buffer;
@ -207,29 +208,9 @@ void SetupFullScreenRectGeometry() {
glBindVertexArray(0); glBindVertexArray(0);
} }
static void update_viewport() { void GLRenderer_Init(int pRender_width, int pRender_height) {
const float target_aspect_ratio = (float)render_width / render_height;
const float aspect_ratio = (float)window_width / window_height;
vp_width = window_width;
vp_height = window_height;
if (aspect_ratio != target_aspect_ratio) {
if (aspect_ratio > target_aspect_ratio) {
vp_width = window_height * target_aspect_ratio + .5f;
} else {
vp_height = window_width / target_aspect_ratio + .5f;
}
}
vp_x = (window_width - vp_width) / 2;
vp_y = (window_height - vp_height) / 2;
}
void GLRenderer_Init(int width, int height, int pRender_width, int pRender_height) {
window_width = width;
window_height = height;
render_width = pRender_width; render_width = pRender_width;
render_height = pRender_height; render_height = pRender_height;
update_viewport();
LOG_INFO("OpenGL vendor string: %s", glGetString(GL_VENDOR)); LOG_INFO("OpenGL vendor string: %s", glGetString(GL_VENDOR));
LOG_INFO("OpenGL renderer string: %s", glGetString(GL_RENDERER)); LOG_INFO("OpenGL renderer string: %s", glGetString(GL_RENDERER));
@ -750,25 +731,9 @@ void GLRenderer_FlushBuffers(tRenderer_flush_type flush_type) {
dirty_buffers = 0; dirty_buffers = 0;
} }
void GLRenderer_GetRenderSize(int* width, int* height) { void GLRenderer_SetViewport(int x, int y, int width, int height) {
*width = render_width; vp_x = x;
*height = render_height; vp_y = y;
} vp_width = width;
vp_height = height;
void GLRenderer_GetWindowSize(int* width, int* height) {
*width = window_width;
*height = window_height;
}
void GLRenderer_SetWindowSize(int width, int height) {
window_width = width;
window_height = height;
update_viewport();
}
void GLRenderer_GetViewport(int* x, int* y, int* width, int* height) {
*x = vp_x;
*y = vp_y;
*width = vp_width;
*height = vp_height;
} }

View File

@ -2,7 +2,7 @@
#define HARNESS_GL_RENDERER #define HARNESS_GL_RENDERER
#include "harness.h" #include "harness.h"
#include "renderers/renderer.h" #include "harness/hooks.h"
#define CHECK_GL_ERROR(msg) \ #define CHECK_GL_ERROR(msg) \
{ \ { \
@ -42,7 +42,7 @@
} \ } \
} }
void GLRenderer_Init(int width, int height, int render_width, int render_height); void GLRenderer_Init(int render_width, int render_height);
void GLRenderer_SetPalette(uint8_t* rgba_colors); void GLRenderer_SetPalette(uint8_t* rgba_colors);
void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer); void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer);
void GLRenderer_EndScene(); void GLRenderer_EndScene();
@ -53,9 +53,6 @@ void GLRenderer_BufferMaterial(br_material* mat);
void GLRenderer_BufferModel(br_model* model); void GLRenderer_BufferModel(br_model* model);
void GLRenderer_ClearBuffers(); void GLRenderer_ClearBuffers();
void GLRenderer_FlushBuffers(tRenderer_flush_type flush_type); void GLRenderer_FlushBuffers(tRenderer_flush_type flush_type);
void GLRenderer_GetRenderSize(int* width, int* height); void GLRenderer_SetViewport(int x, int y, int width, int height);
void GLRenderer_GetWindowSize(int* width, int* height);
void GLRenderer_SetWindowSize(int width, int height);
void GLRenderer_GetViewport(int* x, int* y, int* width, int* height);
#endif #endif

View File

@ -1,47 +0,0 @@
#include "renderer.h"
void Null_Init() {}
void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {}
void Null_EndFrame() {}
void Null_SetPalette(uint8_t* palette) {}
void Null_RenderFullScreenQuad(uint8_t* src) {}
void Null_RenderModel(br_actor* actor, br_model* model, br_material* material, br_token render_type, br_matrix34 model_matrix) {}
void Null_RenderFrameBuffer() {}
void Null_ClearBuffers() {}
void Null_BufferTexture(br_pixelmap* pm) {}
void Null_BufferMaterial(br_material* mat) {}
void Null_BufferModel(br_model* model) {}
void Null_FlushBuffers() {}
void Null_GetRenderSize(int* width, int* height) {
*width = 640;
*height = 480;
}
void Null_GetWindowSize(int* width, int* height) {
*width = 640;
*height = 480;
}
void Null_SetWindowSize(int width, int height) {}
void Null_GetViewportSize(int* x, int* y, int* width, int* height) {
*x = 0;
*y = 0;
*width = 640;
*height = 480;
}
tRenderer null_renderer = {
Null_Init,
Null_BeginFrame,
Null_EndFrame,
Null_SetPalette,
Null_RenderFullScreenQuad,
Null_RenderModel,
Null_ClearBuffers,
Null_BufferTexture,
Null_BufferMaterial,
Null_BufferModel,
Null_FlushBuffers,
Null_GetRenderSize,
Null_GetWindowSize,
Null_SetWindowSize,
Null_GetViewportSize
};

View File

@ -1,29 +0,0 @@
#ifndef HARNESS_RENDERER_H
#define HARNESS_RENDERER_H
#include "brender/br_types.h"
typedef enum {
eFlush_all,
eFlush_color_buffer
} tRenderer_flush_type;
typedef struct tRenderer {
void (*Init)(int width, int height, int pRender_width, int pRender_height);
void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer);
void (*EndScene)();
void (*SetPalette)(uint8_t* palette);
void (*FullScreenQuad)(uint8_t* src);
void (*Model)(br_actor* actor, br_model* model, br_material* material, br_token render_type, br_matrix34 model_matrix);
void (*ClearBuffers)();
void (*BufferTexture)(br_pixelmap* pm);
void (*BufferMaterial)(br_material* mat);
void (*BufferModel)(br_model* model);
void (*FlushBuffers)(tRenderer_flush_type);
void (*GetRenderSize)(int* width, int* height);
void (*GetWindowSize)(int* width, int* height);
void (*SetWindowSize)(int width, int height);
void (*GetViewport)(int* x, int* y, int* width, int* height);
} tRenderer;
#endif

View File

@ -11,5 +11,5 @@ layout (location = 0) out vec4 out_frag_color;
void main() { void main() {
uint palette_index = texture(u_pixels, v_tex_coord.xy).r; uint palette_index = texture(u_pixels, v_tex_coord.xy).r;
vec4 texel = texelFetch(u_palette, ivec2(palette_index, 0), 0); vec4 texel = texelFetch(u_palette, ivec2(palette_index, 0), 0);
out_frag_color = texel; out_frag_color = vec4(texel.bgra);
} }

View File

@ -0,0 +1,249 @@
#include "harness/hooks.h"
#include "harness/win95_polyfill.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_WIN32) || defined(_WIN64)
#include <direct.h>
#include <windows.h>
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getcwd-wgetcwd?view=msvc-170
#define getcwd _getcwd
#define chdir _chdir
#else
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#endif
// All functions have a "_" suffix to avoid collisions with <windows.h>-defined types
uint32_t GetFileAttributesA_(char* lpFileName) {
FILE* f = fopen(lpFileName, "r");
if (!f) {
return INVALID_FILE_ATTRIBUTES;
}
return FILE_ATTRIBUTE_NORMAL;
}
int SetFileAttributesA_(char* lpFileName, uint32_t dwFileAttributes) {
// no-op for now
return 0;
}
void* CreateFileA_(char* lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode, void* lpSecurityAttributes, uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes, void* hTemplateFile) {
assert(dwDesiredAccess == GENERIC_READ);
assert(lpSecurityAttributes == NULL);
assert(dwCreationDisposition == OPEN_EXISTING);
FILE* f = fopen(lpFileName, "r");
if (!f) {
return INVALID_HANDLE_VALUE;
}
return f;
}
uint32_t GetFileSize_(void* hFile, uint32_t* lpFileSizeHigh) {
assert(lpFileSizeHigh == NULL);
long current_offset = ftell(hFile);
fseek(hFile, 0, SEEK_END);
long size = ftell(hFile);
fseek(hFile, current_offset, SEEK_SET);
return size;
}
int CloseHandle_(void* hObject) {
fclose(hObject);
return 0;
}
void GlobalMemoryStatus_(MEMORYSTATUS_* lpBuffer) {
lpBuffer->dwTotalPhys = 64000000;
lpBuffer->dwAvailPhys = 64000000; // pretend we have a whole 64mb of ram!
lpBuffer->dwAvailPageFile = 0;
lpBuffer->dwTotalVirtual = 0;
lpBuffer->dwAvailVirtual = 0;
lpBuffer->dwMemoryLoad = 0;
lpBuffer->dwTotalPageFile = 0;
}
int GetCursorPos_(POINT_* lpPoint) {
int x, y;
gHarness_platform.GetMousePosition(&x, &y);
lpPoint->x = x;
lpPoint->y = y;
return 0;
}
int ScreenToClient_(void* hWnd, POINT_* lpPoint) {
// no-op, we assume the point is already relative to client
return 0;
}
uint32_t timeGetTime_() {
return gHarness_platform.GetTicks();
}
uint32_t GetCurrentDirectoryA_(uint32_t nBufferLength, char* lpBuffer) {
char* ret = getcwd(lpBuffer, nBufferLength);
if (ret == NULL) {
return 0;
}
return strlen(lpBuffer);
}
int SetCurrentDirectoryA_(char* lpPathName) {
int ret = chdir(lpPathName);
// chdir returning zero means success, SetCurrentDirectory returning non-zero means success
if (ret == 0) {
return 1;
} else {
return 0;
}
}
HANDLE_ FindFirstFileA_(char* lpFileName, WIN32_FIND_DATAA_* lpFindFileData) {
assert(strcmp(lpFileName, "*.???") == 0);
#if defined(_WIN32) || defined(_WIN64)
WIN32_FIND_DATA fd;
void* hFile = FindFirstFile(lpFileName, &fd);
if (hFile != INVALID_HANDLE_VALUE) {
strcpy(lpFindFileData->cFileName, fd.cFileName);
}
return hFile;
#else
DIR* dir;
strcpy(lpFileName, ".");
dir = opendir(lpFileName);
if (dir == NULL) {
return INVALID_HANDLE_VALUE;
}
if (FindNextFileA_(dir, lpFindFileData)) {
return dir;
} else {
closedir(dir);
return INVALID_HANDLE_VALUE;
}
#endif
}
int FindNextFileA_(HANDLE_ hFindFile, WIN32_FIND_DATAA_* lpFindFileData) {
#if defined(_WIN32) || defined(_WIN64)
WIN32_FIND_DATA fd;
int result = FindNextFile(hFindFile, &fd);
if (result) {
strcpy(lpFindFileData->cFileName, fd.cFileName);
}
return result;
#else
struct dirent* entry;
if (hFindFile == NULL) {
return 0;
}
while ((entry = readdir(hFindFile)) != NULL) {
if (entry->d_type == DT_REG) {
strcpy(lpFindFileData->cFileName, entry->d_name);
return 1;
}
}
return 0;
#endif
}
int FindClose_(HANDLE_ hFindFile) {
#if defined(_WIN32) || defined(_WIN64)
return FindClose(hFindFile);
#else
return closedir(hFindFile);
#endif
}
void* CreateWindowExA_(uint32_t dwExStyle, char* lpClassName, char* lpWindowName, uint32_t dwStyle, int X, int Y, int nWidth, int nHeight, void* hWndParent, void* hMenu, void* hInstance, void* lpParam) {
return gHarness_platform.CreateWindowAndRenderer(lpWindowName, X, Y, nWidth, nHeight);
}
int SetWindowPos_(void* hWnd, void* hWndInsertAfter, int X, int Y, int cx, int cy, unsigned int uFlags) {
return gHarness_platform.SetWindowPos(hWnd, X, Y, cx, cy);
}
int ShowCursor_(int bShow) {
gHarness_platform.ShowCursor(bShow);
return 0;
}
int SendMessageA_(void* hWnd, unsigned int Msg, unsigned int wParam, long lParam) {
return 0;
}
int MessageBoxA_(void* hWnd, char* lpText, char* lpCaption, unsigned int uType) {
return 0;
}
int DestroyWindow_(void* hWnd) {
gHarness_platform.DestroyWindow(hWnd);
return 0;
}
void ExitProcess_(unsigned int uExitCode) {
exit(uExitCode);
}
void TranslateMessage_(MSG_* lpMsg) {
// no-op
}
void DispatchMessageA_(MSG_* lpMsg) {
// no-op
}
int PeekMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax, unsigned int wRemoveMsg) {
return gHarness_platform.ProcessWindowMessages(lpMsg);
}
int GetMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax) {
return gHarness_platform.ProcessWindowMessages(lpMsg);
}
void Sleep_(uint32_t dwMilliseconds) {
gHarness_platform.Sleep(dwMilliseconds);
}
void DirectDraw_CreateSurface(int width, int height) {
// no-op
}
void DirectInputDevice_GetDeviceState(unsigned int count, uint8_t* buffer) {
gHarness_platform.GetKeyboardState(count, buffer);
}
void DirectDrawDevice_SetPaletteEntries(PALETTEENTRY_* palette, int pFirst_colour, int pCount) {
assert(pFirst_colour == 0);
assert(pCount == 256);
gHarness_platform.Renderer_SetPalette(palette);
Harness_RenderLastScreen();
}
void _splitpath_(char* path, char* drive, char* dir, char* fname, char* ext) {
#ifdef _WIN32
_splitpath(path, NULL, NULL, fname, NULL);
#else
char* base = basename(path);
strcpy(fname, base);
#endif
}
int _CrtDbgReport_(int reportType, const char* filename, int linenumber, const char* moduleName, const char* format, ...) {
printf("_CrtDbgReport: (TODO)\n");
return 1;
}

View File

@ -10,6 +10,7 @@
#include "common/input.h" #include "common/input.h"
#include "common/loading.h" #include "common/loading.h"
#include "common/utility.h" #include "common/utility.h"
#include "harness/hooks.h"
extern int _unittest_controls_lastGetPowerup; extern int _unittest_controls_lastGetPowerup;
@ -23,7 +24,8 @@ void test_controls_CheckKevKeys() {
gKeys_pressed = 0; gKeys_pressed = 0;
result = KevKeyService(); result = KevKeyService();
} }
OS_Sleep(2000); gHarness_platform.Sleep(2000);
gKeys_pressed = 0; gKeys_pressed = 0;
CheckKevKeys(); CheckKevKeys();

View File

@ -2,6 +2,7 @@
#include "common/globvars.h" #include "common/globvars.h"
#include "common/input.h" #include "common/input.h"
#include "harness/hooks.h"
#include <string.h> #include <string.h>
void test_input_KevKeyService() { void test_input_KevKeyService() {
@ -14,7 +15,7 @@ void test_input_KevKeyService() {
gKeys_pressed = 0; gKeys_pressed = 0;
result = KevKeyService(); result = KevKeyService();
} }
OS_Sleep(2000); gHarness_platform.Sleep(2000);
gKeys_pressed = 0; gKeys_pressed = 0;
result = KevKeyService(); result = KevKeyService();

View File

@ -183,9 +183,10 @@ void setup_global_vars(int argc, char* argv[]) {
if (getenv("NO_SIGNAL_HANDLER") != NULL) { if (getenv("NO_SIGNAL_HANDLER") != NULL) {
fake_argv[fake_argc++] = "--no-signal-handler"; fake_argv[fake_argc++] = "--no-signal-handler";
} }
Harness_Init(&fake_argc, fake_argv);
Harness_ForceNullRenderer(); Harness_ForceNullPlatform();
Harness_Init(&fake_argc, fake_argv);
} }
int has_data_directory() { int has_data_directory() {

View File

@ -11,6 +11,7 @@
#ifdef _WIN32 #ifdef _WIN32
#define HOST_NL "\r\n" #define HOST_NL "\r\n"
#include <windows.h>
#else #else
#define HOST_NL "\n" #define HOST_NL "\n"
#endif #endif