#include "brender.h"
#include "car.h"
#include "dinput.h"
#include "errors.h"
#include "globvars.h"
#include "grafdata.h"
#include "graphics.h"
#include "harness/config.h"
#include "harness/hooks.h"
#include "harness/os.h"
#include "harness/trace.h"
#include "input.h"
#include "loadsave.h"
#include "main.h"
#include "pd/sys.h"
#include "sound.h"
#include "ssdx.h"
#include "utility.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "harness/win95_polyfill.h"
#define GFX_INIT_STRING_32X20X8 "320x200 init string"
#define GFX_INIT_STRING_64X48X8 "640x480 init string"
#define KEYDOWN(var, key) (var[key] & 0x80)
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, 480, 480, NULL } // Pierre-Marie Baty -- fixed yres (was: { 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;
int gGfx_initialized; // maybe renamed here
tU32 gUpper_loop_limit;
int gReal_back_screen_locked;
tU32 gScan_code[123]; // was tU8 [123][2] in symbol dump
// Added by dethrace. Windows-specific. Original variable names unknown.
int gWin32_fatal_error_exit_code;
int gWin32_show_fatal_error_message;
char gWin32_fatal_error_message[512];
int gWin32_action_replay_buffer_allocated;
void* gWin32_action_replay_buffer;
int gWin32_action_replay_buffer_size;
void* gWin32_hwnd;
int gWin32_lbutton_down;
int gWin32_rbutton_down;
PALETTEENTRY_ gWin32_palette[256];
br_diaghandler gWin32_br_diaghandler;
int gWin32_window_has_focus = 1;
int gNetwork_profile_file_exists = 0;
char* _unittest_last_fatal_error;
int original_main(int pArgc, char** pArgv);
/*static*/ void KeyboardHandler(void);
/*static*/ int KeyDown(tU8 pScan_code);
/*static*/ void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2);
/*static*/ void KeyBegin(void);
/*static*/ void KeyEnd(void);
/*static*/ int KeyDown22(int pKey_index);
static void Win32ReleaseInputDevice(void);
static void Win32PumpMessages(void);
static HARNESS_NORETURN void Win32FatalError(char* pStr_1, char* pStr_2);
static void Win32CreateWindow(void);
static void Win32InitScreen(void);
/*static*/ void Copy8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette);
/*static*/ void SwapBackScreen(void);
/*static*/ void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom);
/*static*/ void CopyBackScreen(int pRendering_area_only);
static void Win32SetPaletteEntries(uint8_t* entries, int pFirst_colour, int pCount);
static void Win32InitInputDevice(void);
static void Win32AllocateActionReplayBuffer(void);
static void Usage(char* pProgpath);
/*static*/ int OurGetChar(void);
/*static*/ int InitJoysticks(void);
/*static*/ tU32 ReadJoystickAxis(int pBit);
static void Win32BRenderWarningFunc(char* msg);
static void Win32BRenderFailureFunc(char* msg);
extern void QuitGame(void);
void KeyboardHandler(void) {
//tU8 scan_code; // Pierre-Marie Baty -- unused variable
//tU8 up; // Pierre-Marie Baty -- unused variable
//static tU8 extended; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int KeyDown(tU8 pScan_code) {
NOT_IMPLEMENTED();
}
void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2) {
LOG_TRACE("(%d, %d, %d)", pKey_index, pScan_code_1, pScan_code_2);
NOT_IMPLEMENTED();
}
void KeyBegin(void) {
gScan_code[KEY_0] = DIK_0;
gScan_code[KEY_1] = DIK_1;
gScan_code[KEY_2] = DIK_2;
gScan_code[KEY_3] = DIK_3;
gScan_code[KEY_4] = DIK_4;
gScan_code[KEY_5] = DIK_5;
gScan_code[KEY_6] = DIK_6;
gScan_code[KEY_7] = DIK_7;
gScan_code[KEY_8] = DIK_8;
gScan_code[KEY_9] = DIK_9;
gScan_code[KEY_A] = DIK_A;
gScan_code[KEY_B] = DIK_B;
gScan_code[KEY_C] = DIK_C;
gScan_code[KEY_D] = DIK_D;
gScan_code[KEY_E] = DIK_E;
gScan_code[KEY_F] = DIK_F;
gScan_code[KEY_G] = DIK_G;
gScan_code[KEY_H] = DIK_H;
gScan_code[KEY_I] = DIK_I;
gScan_code[KEY_J] = DIK_J;
gScan_code[KEY_K] = DIK_K;
gScan_code[KEY_L] = DIK_L;
gScan_code[KEY_M] = DIK_M;
gScan_code[KEY_N] = DIK_N;
gScan_code[KEY_O] = DIK_O;
gScan_code[KEY_P] = DIK_P;
gScan_code[KEY_Q] = DIK_Q;
gScan_code[KEY_R] = DIK_R;
gScan_code[KEY_S] = DIK_S;
gScan_code[KEY_T] = DIK_T;
gScan_code[KEY_U] = DIK_U;
gScan_code[KEY_V] = DIK_V;
gScan_code[KEY_W] = DIK_W;
gScan_code[KEY_X] = DIK_X;
gScan_code[KEY_Y] = DIK_Y;
gScan_code[KEY_Z] = DIK_Z;
gScan_code[KEY_GRAVE] = DIK_GRAVE;
gScan_code[KEY_MINUS] = DIK_MINUS;
gScan_code[KEY_EQUALS] = DIK_EQUALS;
gScan_code[KEY_BACKSPACE] = DIK_BACK;
gScan_code[KEY_RETURN] = DIK_RETURN;
gScan_code[KEY_KP_ENTER] = DIK_NUMPADENTER;
gScan_code[KEY_CAPSLOCK] = DIK_CAPSLOCK;
gScan_code[KEY_TAB] = DIK_TAB;
gScan_code[KEY_SLASH] = DIK_SLASH;
gScan_code[KEY_UNKNOWN_55] = 0;
gScan_code[KEY_SEMICOLON] = DIK_SEMICOLON;
gScan_code[KEY_APOSTROPHE] = DIK_APOSTROPHE;
gScan_code[KEY_PERIOD] = DIK_PERIOD;
gScan_code[KEY_COMMA] = DIK_COMMA;
gScan_code[KEY_LBRACKET] = DIK_LBRACKET;
gScan_code[KEY_RBRACKET] = DIK_RBRACKET;
gScan_code[KEY_ESCAPE] = DIK_ESCAPE;
gScan_code[KEY_INSERT] = DIK_INSERT;
gScan_code[KEY_DELETE] = DIK_DELETE;
gScan_code[KEY_HOME] = DIK_HOME;
gScan_code[KEY_END] = DIK_END;
gScan_code[KEY_PAGEUP] = DIK_PGUP;
gScan_code[KEY_PAGEDOWN] = DIK_PGDN;
gScan_code[KEY_LEFT] = DIK_LEFT;
gScan_code[KEY_RIGHT] = DIK_RIGHT;
gScan_code[KEY_UP] = DIK_UP;
gScan_code[KEY_DOWN] = DIK_DOWN;
gScan_code[KEY_KP_NUMLOCK] = DIK_NUMLOCK;
gScan_code[KEY_KP_DIVIDE] = DIK_DIVIDE;
gScan_code[KEY_KP_MULTIPLY] = DIK_MULTIPLY;
gScan_code[KEY_KP_MINUS] = DIK_SUBTRACT;
gScan_code[KEY_KP_PLUS] = DIK_ADD;
gScan_code[KEY_KP_PERIOD] = DIK_DECIMAL;
gScan_code[KEY_KP_0] = DIK_NUMPAD0;
gScan_code[KEY_KP_1] = DIK_NUMPAD1;
gScan_code[KEY_KP_2] = DIK_NUMPAD2;
gScan_code[KEY_KP_3] = DIK_NUMPAD3;
gScan_code[KEY_KP_4] = DIK_NUMPAD4;
gScan_code[KEY_KP_5] = DIK_NUMPAD5;
gScan_code[KEY_KP_6] = DIK_NUMPAD6;
gScan_code[KEY_KP_7] = DIK_NUMPAD7;
gScan_code[KEY_KP_8] = DIK_NUMPAD8;
gScan_code[KEY_KP_9] = DIK_NUMPAD9;
gScan_code[KEY_F1] = DIK_F1;
gScan_code[KEY_F2] = DIK_F2;
gScan_code[KEY_F3] = DIK_F3;
gScan_code[KEY_F4] = DIK_F4;
gScan_code[KEY_F5] = DIK_F5;
gScan_code[KEY_F6] = DIK_F6;
gScan_code[KEY_F7] = DIK_F7;
gScan_code[KEY_F8] = DIK_F8;
gScan_code[KEY_F9] = DIK_F9;
gScan_code[KEY_F10] = DIK_F10;
gScan_code[KEY_F11] = DIK_F11;
gScan_code[KEY_F12] = DIK_F12;
gScan_code[KEY_PRTSCN] = DIK_SYSRQ;
gScan_code[KEY_SCRLK] = DIK_SCROLL;
gScan_code[KEY_SPACE] = DIK_SPACE;
gScan_code[KEY_RSHIFT] = DIK_RSHIFT;
gScan_code[KEY_RALT] = DIK_RALT;
gScan_code[KEY_RCTRL] = DIK_RCONTROL;
gScan_code[KEY_LSHIFT] = DIK_LSHIFT;
gScan_code[KEY_LALT] = DIK_LALT;
gScan_code[KEY_LCTRL] = DIK_LCONTROL;
gScan_code[KEY_KP_EQUALS] = 0;
gScan_code[KEY_BACKSLASH] = DIK_BACKSLASH;
gScan_code[KEY_CTRL_ANY_2] = 0xff;
gScan_code[KEY_PAUSE] = 0xff;
gScan_code[KEY_SHIFT_ANY] = 0xff;
gScan_code[KEY_ALT_ANY] = 0xff;
gScan_code[KEY_CTRL_ANY] = 0xff;
}
void KeyEnd(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int KeyDown22(int pKey_index) {
LOG_TRACE("(%d)", pKey_index);
NOT_IMPLEMENTED();
}
void PDSetKeyArray(int* pKeys, int pMark) {
int i;
uint8_t keystate[256];
LOG_TRACE10("(%p, %d)", pKeys, pMark);
gKeys_pressed = 0;
Win32PumpMessages();
DirectInputDevice_GetDeviceState(COUNT_OF(keystate), keystate);
for (i = 0; i < COUNT_OF(gScan_code); i++) {
if (gScan_code[i] == 0) {
continue;
}
if (gScan_code[i] == 0xff) {
switch (i) {
case KEY_SHIFT_ANY:
if (KEYDOWN(keystate, gScan_code[KEY_LSHIFT]) || KEYDOWN(keystate, gScan_code[KEY_RSHIFT])) {
pKeys[KEY_SHIFT_ANY] = pMark;
} else {
if (pKeys[KEY_SHIFT_ANY] == pMark) {
pKeys[KEY_SHIFT_ANY] = 0;
}
}
break;
case KEY_ALT_ANY:
if (KEYDOWN(keystate, gScan_code[KEY_LALT]) || KEYDOWN(keystate, gScan_code[KEY_RALT])) {
pKeys[KEY_ALT_ANY] = pMark;
} else {
if (pKeys[KEY_ALT_ANY] == pMark) {
pKeys[KEY_ALT_ANY] = 0;
}
}
break;
case KEY_CTRL_ANY:
case KEY_CTRL_ANY_2:
if (KEYDOWN(keystate, gScan_code[KEY_LCTRL]) || KEYDOWN(keystate, gScan_code[KEY_RCTRL])) {
pKeys[KEY_CTRL_ANY] = pMark;
pKeys[KEY_CTRL_ANY_2] = pMark;
} else {
if (pKeys[KEY_CTRL_ANY] == pMark || pKeys[KEY_CTRL_ANY_2] == pMark) {
pKeys[KEY_CTRL_ANY] = 0;
pKeys[KEY_CTRL_ANY_2] = 0;
}
}
break;
default:
continue;
}
} else if (KEYDOWN(keystate, gScan_code[i])) {
pKeys[i] = pMark;
gKeys_pressed = i + (gKeys_pressed << 8) + 1;
} else {
if (pKeys[i] == pMark) {
pKeys[i] = 0;
}
}
}
}
void Win32ReleaseInputDevice(void) {
}
int PDGetASCIIFromKey(int pKey) {
LOG_TRACE("(%d)", pKey);
/* The Windows Carmageddon executable uses PDKeyDown here. The German DOS executable uses PDKeyDown3. */
if (PDKeyDown3(KEY_SHIFT_ANY)) {
return gASCII_shift_table[pKey];
} else {
return gASCII_table[pKey];
}
}
void Win32PumpMessages(void) {
MSG_ msg; // [esp+Ch] [ebp-20h] BYREF
PDUnlockRealBackScreen();
while ((!gWin32_window_has_focus || PeekMessageA_(&msg, 0, 0, 0, 1u)) && (gWin32_window_has_focus || GetMessageA_(&msg, 0, 0, 0) != -1)) {
if (msg.message == WM_QUIT) {
dr_dprintf("WM_QUIT received.");
if (gWin32_window_has_focus) {
dr_dprintf("Active, so lock the surface");
PDLockRealBackScreen();
dr_dprintf("QuitGame being called...");
QuitGame();
}
PDShutdownSystem();
}
TranslateMessage_(&msg);
DispatchMessageA_(&msg);
}
PDLockRealBackScreen();
}
void PDFatalError(char* pThe_str) {
LOG_TRACE("(\"%s\")", pThe_str);
dr_dprintf("FATAL ERROR: %s", pThe_str);
Win32FatalError(pThe_str, "");
}
void Win32FatalError(char* pStr_1, char* pStr_2) {
gWin32_show_fatal_error_message = 1;
sprintf(gWin32_fatal_error_message
, "%s\n%s", pStr_1
, pStr_2
);
gWin32_fatal_error_exit_code = 15;
PDShutdownSystem();
}
void PDNonFatalError(char* pThe_str) {
LOG_TRACE("(\"%s\")", pThe_str);
NOT_IMPLEMENTED();
}
void PDInitialiseSystem(void) {
tPath_name the_path;
FILE* f;
int len;
Win32AllocateActionReplayBuffer();
gBack_screen = NULL;
gScreen = NULL;
Win32CreateWindow();
ShowCursor_(0);
KeyBegin();
PathCat(the_path, gApplication_path, "KEYBOARD.COK");
f
= fopen(the_path
, "rb");
if (f == NULL) {
if (harness_game_info.defines.requires_ascii_table) {
#if !defined(DETHRACE_FIX_BUGS)
PDFatalError("This .exe must have KEYBOARD.COK in the DATA folder.");
#endif
}
// dethrace: demos do not ship with KEYBOARD.COK file
memcpy(gASCII_table
, harness_game_info.
defines.
ascii_table, sizeof(gASCII_table
));
memcpy(gASCII_shift_table
, harness_game_info.
defines.
ascii_shift_table, sizeof(gASCII_shift_table
));
} else {
PathCat(the_path, gApplication_path, "KEYBOARD.COK");
f
= fopen(the_path
, "rb");
if (f == NULL) {
PDFatalError("This .exe must have KEYBOARD.COK in the DATA folder.");
}
fread(gASCII_table
, len
, 1u
, f
);
fread(gASCII_shift_table
, len
, 1u
, f
);
}
Win32InitInputDevice();
}
void Win32CreateWindow(void) {
// wnd_class.style = 3;
// wnd_class.lpfnWndProc = window_proc;
// wnd_class.cbClsExtra = 0;
// wnd_class.cbWndExtra = 0;
// wnd_class.hInstance = gWin32_hinst;
// wnd_class.hIcon = LoadIconA(0, (LPCSTR)0x7F00);
// wnd_class.hCursor = LoadCursorA(0, (LPCSTR)0x7F00);
// wnd_class.hbrBackground = (HBRUSH)GetStockObject(4);
// wnd_class.lpszMenuName = 0;
// wnd_class.lpszClassName = "CarmageddonClass";
// LOWORD(v5) = RegisterClassA(&wnd_class);
// v5 = (unsigned __int16)v5;
// v2 = gWin32_hinst;
// int height = GetSystemMetrics(SM_CYSCREEN);
// int width = GetSystemMetrics(SM_CXSCREEN);
int width = gGraf_specs[gGraf_spec_index].total_width;
int height = gGraf_specs[gGraf_spec_index].total_height;
// WS_VISIBLE | WS_POPUP
gWin32_hwnd = CreateWindowExA_(0, "CarmageddonClass", "Carmageddon", 0x90000000, 0, 0, width, height, 0, NULL, NULL, NULL);
SSDXGetWindowRect(gWin32_hwnd);
// hdc = GetDC(gWin32_hwnd);
// GetSystemPaletteEntries(hdc, 0, 256u, &gWin32_palette);
// ReleaseDC(gWin32_hwnd, hdc);
// UpdateWindow(gWin32_hwnd);
// SetFocus(gWin32_hwnd);
}
void PDShutdownSystem(void) {
static int been_here = 0;
LOG_TRACE("()");
if (!been_here) {
been_here = 1;
dr_dprintf("PDShutdownSystem()...");
SSDXRelease();
Win32ReleaseInputDevice();
ShowCursor_(1);
if (gWin32_hwnd) {
dr_dprintf("Resizing main window...");
SetWindowPos_(gWin32_hwnd, 0, -100, -100, 64, 64, 0x414u);
}
dr_dprintf("Servicing messages...");
Win32PumpMessages();
dr_dprintf("Sending WM_SHOWWINDOW broadcast message...");
SendMessageA_(HWND_BROADCAST, 0x18u, 1u, 0);
if (gWin32_show_fatal_error_message) {
dr_dprintf("Displaying fatal error...");
MessageBoxA_(0, gWin32_fatal_error_message, "Carmageddon Fatal Error", MB_ICONERROR);
}
if (gWin32_hwnd) {
dr_dprintf("Destroying window...");
DestroyWindow_(gWin32_hwnd);
gWin32_hwnd = 0;
}
dr_dprintf("End of PDShutdownSystem().");
CloseDiagnostics();
ExitProcess_(gWin32_fatal_error_exit_code);
}
ExitProcess_(8u);
}
void PDSaveOriginalPalette(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
void PDRevertPalette(void) {
LOG_TRACE("()");
// empty function
}
int PDInitScreenVars(int pArgc, char** pArgv) {
// this codes from dossys
gGraf_specs[gGraf_spec_index].phys_width = gGraf_specs[gGraf_spec_index].total_width;
gGraf_specs[gGraf_spec_index].phys_height = gGraf_specs[gGraf_spec_index].total_height;
return 1;
}
void PDInitScreen(void) {
Win32InitScreen();
}
void Win32InitScreen(void) {
// SWP_NOSENDCHANGING | SWP_NOACTIVATE | SWP_NOZORDER
SetWindowPos_(gWin32_hwnd, 0, 0, 0, gGraf_specs[gReal_graf_data_index].total_width, gGraf_specs[gReal_graf_data_index].total_height, 0x414u);
// get_window_rect(gWin32_hwnd);
Win32PumpMessages();
}
void PDLockRealBackScreen(void) {
LOG_TRACE("()");
// no-op
}
void PDUnlockRealBackScreen(void) {
LOG_TRACE("()");
// no-op
}
void PDAllocateScreenAndBack(void) {
// this is a mix of windows and dos code
dr_dprintf("PDAllocateScreenAndBack() - START...");
BrMaterialFindHook(PDMissingMaterial);
BrTableFindHook(PDMissingTable);
BrModelFindHook(PDMissingModel);
BrMapFindHook(PDMissingMap);
int row_bytes;
SSDXInitDirectDraw(gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height, &row_bytes);
gScreen = BrPixelmapAllocate(BR_PMT_INDEX_8, gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height, NULL, BR_PMAF_NORMAL);
gScreen->origin_x = 0;
gGfx_initialized = 1;
gScreen->origin_y = 0;
gBack_screen = BrPixelmapMatch(gScreen, BR_PMMATCH_OFFSCREEN);
gBack_screen->origin_x = 0;
gBack_screen->origin_y = 0;
gTemp_screen = BrPixelmapMatch(gScreen, BR_PMMATCH_OFFSCREEN);
gTemp_screen->origin_x = 0;
gTemp_screen->origin_y = 0;
dr_dprintf("PDAllocateScreenAndBack() - END.");
// dr_dprintf("PDAllocateScreenAndBack() - START...");
// BrMaterialFindHook(PDMissingMaterial);
// BrTableFindHook(PDMissingTable);
// BrModelFindHook(PDMissingModel);
// BrMapFindHook(PDMissingMap);
// dr_dprintf("Setting up DirectDraw stuff...");
// SSDXStart(gWin32_hwnd, 0, 1);
// dr_dprintf("Setting up DirectSound stuff...");
// int result = SSDXStart(gWin32_hwnd, 0, 2);
// int row_bytes;
// if (result == 0) {
// result = SSDXInitDirectDraw(gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height, &row_bytes);
// }
// if (result) {
// SSDXHandleError(result);
// PDFatalError("Unable to setup DirectDraw - please check that DirectX is installed");
// }
// gGraf_specs[gGraf_spec_index].row_bytes = row_bytes;
// gGraf_specs[gGraf_spec_index].phys_width = gGraf_specs[gGraf_spec_index].row_bytes;
// gGraf_specs[gGraf_spec_index].phys_height = gGraf_specs[gGraf_spec_index].total_height;
// dr_dprintf(
// "Graf spec info after screen allocation:\n"
// " Total width: %d\n"
// " Total height: %d\n"
// " Phys width: %d\n"
// " Phys height: %d\n"
// " Row bytes: %d\n",
// gGraf_specs[gGraf_spec_index].total_width,
// gGraf_specs[gGraf_spec_index].total_height,
// gGraf_specs[gGraf_spec_index].phys_width,
// gGraf_specs[gGraf_spec_index].phys_height,
// gGraf_specs[gGraf_spec_index].row_bytes);
// dr_dprintf("First attempt at locking surface...");
// PDLockRealBackScreen();
// dr_dprintf("Done first surface lock; gOffscreen_pixels 0x%p", gOffscreen_pixels);
// gBack_screen = BrPixelmapAllocate(
// 3u,
// gGraf_specs[gGraf_spec_index].phys_width,
// gGraf_specs[gGraf_spec_index].phys_height,
// gOffscreen_pixels,
// 0);
// gScreen = gBack_screen;
// gBack_screen->origin_x = 0;
// gBack_screen->origin_y = 0;
// gBack_screen->base_x = 0;
// gBack_screen->base_y = 0;
// gBack_screen->row_bytes = gGraf_specs[gGraf_spec_index].row_bytes;
// gTemp_screen = (br_pixelmap*)BrPixelmapMatch(gBack_screen, 0);
// gGfx_initialized = 1;
// memset(gBack_screen->pixels, 0, gBack_screen->row_bytes * gBack_screen->height);
// PDScreenBufferSwap(0);
// dr_dprintf("PDAllocateScreenAndBack() - END.");
}
void Copy8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette) {
//int x; // Pierre-Marie Baty -- unused variable
//int y; // Pierre-Marie Baty -- unused variable
//tU8* src; // Pierre-Marie Baty -- unused variable
//tU8 value; // Pierre-Marie Baty -- unused variable
//tU8 red; // Pierre-Marie Baty -- unused variable
//tU8 green; // Pierre-Marie Baty -- unused variable
//tU8 blue; // Pierre-Marie Baty -- unused variable
//tU16* dst; // Pierre-Marie Baty -- unused variable
//tU16* palette_entry; // Pierre-Marie Baty -- unused variable
LOG_TRACE("(%p, %p, %p)", pDst, pSrc, pPalette);
NOT_IMPLEMENTED();
}
void Double8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette, tU16 pOff, tU16 pSrc_width, tU16 pSrc_height) {
//int x; // Pierre-Marie Baty -- unused variable
//int y; // Pierre-Marie Baty -- unused variable
//tU8* src; // Pierre-Marie Baty -- unused variable
//tU8 value; // Pierre-Marie Baty -- unused variable
//tU8 red; // Pierre-Marie Baty -- unused variable
//tU8 green; // Pierre-Marie Baty -- unused variable
//tU8 blue; // Pierre-Marie Baty -- unused variable
//tU16* dst0; // Pierre-Marie Baty -- unused variable
//tU16* dst1; // Pierre-Marie Baty -- unused variable
//tU16 sixteen; // Pierre-Marie Baty -- unused variable
//tU16* palette_entry; // Pierre-Marie Baty -- unused variable
LOG_TRACE("(%p, %p, %p, %d, %d, %d)", pDst, pSrc, pPalette, pOff, pSrc_width, pSrc_height);
NOT_IMPLEMENTED();
}
br_pixelmap* PDInterfacePixelmap(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
void SwapBackScreen(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom) {
LOG_TRACE("(%d, %d)", pRendering_area_only, pClear_top_and_bottom);
NOT_IMPLEMENTED();
}
void CopyBackScreen(int pRendering_area_only) {
LOG_TRACE("(%d)", pRendering_area_only);
NOT_IMPLEMENTED();
}
void PDScreenBufferSwap(int pRendering_area_only) {
// taken from dossys
if (pRendering_area_only) {
BrPixelmapRectangleCopy(gScreen, gY_offset, gX_offset, gRender_screen, 0, 0, gWidth, gHeight);
} else {
if (gReal_graf_data_index == gGraf_data_index) {
// BrPixelmapDoubleBuffer(gScreen, gBack_screen);
gHarness_platform.Renderer_Present(gBack_screen);
} else {
DRPixelmapDoubledCopy(gTemp_screen, gBack_screen, 320, 200, 0, 40);
// BrPixelmapDoubleBuffer(gScreen, gTemp_screen);
gHarness_platform.Renderer_Present(gTemp_screen);
}
}
}
void PDPixelmapToScreenRectangleCopy(br_pixelmap* dst, br_int_16 dx, br_int_16 dy, br_pixelmap* src, br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h) {
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", dst, dx, dy, src, sx, sy, w, h);
NOT_IMPLEMENTED();
}
void PDPixelmapHLineOnScreen(br_pixelmap* dst, br_int_16 x1, br_int_16 y1, br_int_16 x2, br_int_16 y2, br_uint_32 colour) {
LOG_TRACE("(%p, %d, %d, %d, %d, %d)", dst, x1, y1, x2, y2, colour);
NOT_IMPLEMENTED();
}
void PDPixelmapVLineOnScreen(br_pixelmap* dst, br_int_16 x1, br_int_16 y1, br_int_16 x2, br_int_16 y2, br_uint_32 colour) {
LOG_TRACE("(%p, %d, %d, %d, %d, %d)", dst, x1, y1, x2, y2, colour);
NOT_IMPLEMENTED();
}
void PDInstallErrorHandlers(void) {
LOG_TRACE("()");
gWin32_br_diaghandler.identifier = "LlantisilioBlahBlahBlahOgOgOch";
gWin32_br_diaghandler.warning = Win32BRenderWarningFunc;
gWin32_br_diaghandler.failure = Win32BRenderFailureFunc;
BrDiagHandlerSet(&gWin32_br_diaghandler);
}
void PDSetFileVariables(void) {
// Changed by dethrace for cross-platform
// strcpy(gDir_separator, "\\");
}
void PDBuildAppPath(char* pThe_path) {
GetCurrentDirectoryA_(253, pThe_path);
// GetShortPathNameA(pThe_path, pThe_path, 253);
strcat(pThe_path
, "/"); // original: strcat(pThe_path, "\\")
dr_dprintf("Application path '%s'", pThe_path);
}
void PDForEveryFile(char* pThe_path, void (*pAction_routine)(char*)) {
char found_path[256]; // [esp+Ch] [ebp-448h] BYREF
WIN32_FIND_DATAA_ find_data; // [esp+10Ch] [ebp-348h] BYREF
HANDLE_ hFindFile; // [esp+24Ch] [ebp-208h]
char file_filter[256]; // [esp+250h] [ebp-204h] BYREF
char current_dir[260]; // [esp+350h] [ebp-104h] BYREF
GetCurrentDirectoryA_(sizeof(current_dir), current_dir);
if (SetCurrentDirectoryA_(pThe_path)) {
hFindFile = FindFirstFileA_(file_filter, &find_data);
if (hFindFile != INVALID_HANDLE_VALUE) {
do {
PathCat(found_path, pThe_path, find_data.cFileName);
pAction_routine(found_path);
} while (FindNextFileA_(hFindFile, &find_data));
FindClose_(hFindFile);
}
SetCurrentDirectoryA_(current_dir);
}
}
void PDSetPalette(br_pixelmap* pThe_palette) {
PDSetPaletteEntries(pThe_palette, 0, 256);
}
void Win32SetPaletteEntries(uint8_t* entries, int pFirst_colour, int pCount) {
int i; // [esp+Ch] [ebp-Ch]
int last_colour; // [esp+14h] [ebp-4h]
last_colour = pFirst_colour + pCount - 1;
if (last_colour > 255) {
last_colour = 255;
}
for (i = pFirst_colour; i <= last_colour; i++) {
gWin32_palette[i].peFlags = 0;
gWin32_palette[i].peRed = entries[i * 4 + 2];
gWin32_palette[i].peGreen = entries[i * 4 + 1];
gWin32_palette[i].peBlue = entries[i * 4];
}
SSDXSetPaleeteEntries(gWin32_palette, 0, 256);
}
void PDSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) {
Win32SetPaletteEntries(pPalette->pixels, pFirst_colour, pCount);
}
void PDSwitchToRealResolution(void) {
LOG_TRACE("()");
}
void PDSwitchToLoresMode(void) {
LOG_TRACE("()");
}
void PDMouseButtons(int* pButton_1, int* pButton_2) {
//br_uint_32 mouse_buttons; // Pierre-Marie Baty -- unused variable
//br_int_32 mouse_x; // Pierre-Marie Baty -- unused variable
//br_int_32 mouse_y; // Pierre-Marie Baty -- unused variable
LOG_TRACE("(%p, %p)", pButton_1, pButton_2);
// added by dethrace
gHarness_platform.GetMouseButtons(pButton_1, pButton_2);
}
void PDGetMousePosition(int* pX_coord, int* pY_coord) {
POINT_ p;
LOG_TRACE("(%p, %p)", pX_coord, pY_coord);
GetCursorPos_(&p);
ScreenToClient_(gWin32_hwnd, &p);
*pX_coord = p.x;
*pY_coord = p.y;
}
int PDGetTotalTime(void) {
return timeGetTime_();
}
int PDServiceSystem(tU32 pTime_since_last_call) {
Win32PumpMessages();
return 0;
}
void Win32InitInputDevice(void) {
// do directinput stuff
gJoystick_deadzone = 8000;
}
void Win32AllocateActionReplayBuffer(void) {
MEMORYSTATUS_ mem_status; // [esp+Ch] [ebp-28h] BYREF
size_t buf_size; // [esp+2Ch] [ebp-8h]
void* buf; // [esp+30h] [ebp-4h]
buf = 0;
if (gWin32_action_replay_buffer_allocated) {
return;
}
gWin32_action_replay_buffer_allocated = 1;
mem_status.dwLength = sizeof(mem_status);
GlobalMemoryStatus_(&mem_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",
mem_status.dwLength,
mem_status.dwMemoryLoad,
mem_status.dwTotalPhys,
mem_status.dwAvailPhys,
mem_status.dwTotalPageFile,
mem_status.dwAvailPageFile,
mem_status.dwTotalVirtual,
mem_status.dwAvailVirtual);
buf_size = 20000000;
if (mem_status.dwTotalPhys < 16000000) {
buf_size = 500000;
}
if (mem_status.dwTotalPhys < 24000000) {
buf_size = 4000000;
}
if (mem_status.dwTotalPhys < 32000000) {
buf_size = 6000000;
}
if (mem_status.dwTotalPhys < 48000000) {
buf_size = 12000000;
}
dr_dprintf("Win32AllocateActionReplayBuffer(): We want %d bytes...", buf_size);
if (mem_status.dwAvailPhys + mem_status.dwAvailPageFile < buf_size) {
buf_size = mem_status.dwAvailPhys + mem_status.dwAvailPageFile - 1048576;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but there's only %d bytes available...", buf_size);
}
if (buf_size < 65536) {
buf_size = 65536;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but we have to have a minimum size of %d bytes...", 65536);
}
while (buf_size >= 65536) {
if (buf) {
break;
}
buf_size -= 65536;
}
gWin32_action_replay_buffer = buf;
if (buf) {
gWin32_action_replay_buffer_size = buf_size;
Sleep_(1000u);
} else {
gWin32_action_replay_buffer_size = 0;
}
dr_dprintf("Win32AllocateActionReplayBuffer(): Actually allocated %d bytes.", buf_size);
GlobalMemoryStatus_(&mem_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",
mem_status.dwLength,
mem_status.dwMemoryLoad,
mem_status.dwTotalPhys,
mem_status.dwAvailPhys,
mem_status.dwTotalPageFile,
mem_status.dwAvailPageFile,
mem_status.dwTotalVirtual,
mem_status.dwAvailVirtual);
}
void PDAllocateActionReplayBuffer(char** pBuffer, tU32* pBuffer_size) {
LOG_TRACE("(%p, %p)", pBuffer, pBuffer_size);
if (gReplay_override) {
*pBuffer = NULL;
*pBuffer_size = 0;
return;
}
Win32AllocateActionReplayBuffer();
*pBuffer = gWin32_action_replay_buffer;
*pBuffer_size = gWin32_action_replay_buffer_size;
}
void PDDisposeActionReplayBuffer(char* pBuffer) {
LOG_TRACE("(\"%s\")", pBuffer);
}
// this function is taken from dossys
void Usage(char* pProgpath) {
char base_name[256]; // fix: changed from 9 to avoid overflow on longer filenames
_splitpath_(pProgpath, NULL, NULL, base_name, NULL);
"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",
base_name,
"-hires",
"-yon",
"-simple",
"-sound",
"-robots",
"-lomem",
"-nosound",
"-spamfritter",
"-nocutscenes",
"-noreplay",
CAR_MAX_SIMPLIFICATION_LEVEL);
}
// Renamed from "main" to "original_main" to allow for harness + unit testing
int original_main(int pArgc, char** pArgv) {
int arg;
int i;
float f;
for (i = 1; i < pArgc; i++) {
if (strcasecmp(pArgv[i], "-hires") == 0) {
gGraf_spec_index = 1;
} else if (strcasecmp(pArgv[i], "-yon") == 0 && i < pArgc - 1) {
i++;
if (f >= 0.0 && f <= 1.0f) {
gYon_multiplier = f;
}
} else if (strcasecmp(pArgv[i], "-simple") == 0 && i < pArgc - 1) {
i++;
if (arg >= 0 && arg < 5) {
gCar_simplification_level = arg;
}
} else if (strcasecmp(pArgv[i], "-sound") == 0 && i < pArgc - 1) {
i++;
gSound_detail_level = arg;
} else if (strcasecmp(pArgv[i], "-robots") == 0 || strcasecmp(pArgv[i], "-german") == 0) {
gSausage_override = 1;
} else if (strcasecmp(pArgv[i], "-lomem") == 0) {
gAustere_override = 1;
} else if (strcasecmp(pArgv[i], "-nosound") == 0) {
gSound_override = 1;
} else if (strcasecmp(pArgv[i], "-spamfritter") == 0) {
gExtra_mem = 2000000;
} else if (strcasecmp(pArgv[i], "-nocutscenes") == 0) {
gCut_scene_override = 1;
} else if (strcasecmp(pArgv[i], "-noreplay") == 0) {
gReplay_override = 1;
} else {
Usage(pArgv[0]);
}
}
gNetwork_profile_fname[0] = 0;
uint32_t len = GetCurrentDirectoryA_(240, gNetwork_profile_fname);
if (len
> 0 && len
== strlen(gNetwork_profile_fname
)) {
gNetwork_profile_file_exists = 1;
strcat(gNetwork_profile_fname
, "/");
strcat(gNetwork_profile_fname
, "NETWORK.INI");
}
GameMain(pArgc, pArgv);
return 0;
}
int OurGetChar(void) {
//int key; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
void PDEnterDebugger(char* pStr) {
//static unsigned char* save_it; // Pierre-Marie Baty -- unused variable
LOG_TRACE("(\"%s\")", pStr);
dr_dprintf("PDEnterDebugger(): %s", pStr);
ShowCursor_(1);
#ifdef DETHRACE_FIX_BUGS
if (strcmp(pStr
, "Bet you weren't expecting this") != 0
#else
if (pStr != "Bet you weren't expecting this"
#endif
&& _CrtDbgReport_(_CRT_ASSERT, "C:\\Msdev\\Projects\\DethRace\\Win95sys.c", 437, 0, 0) == 1) {
abort(); // original: __debugbreak();
}
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;
}
void PDEndItAllAndReRunTheBastard(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int InitJoysticks(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
tU32 ReadJoystickAxis(int pBit) {
//tU32 val; // Pierre-Marie Baty -- unused variable
//tU32 count; // Pierre-Marie Baty -- unused variable
LOG_TRACE("(%d)", pBit);
NOT_IMPLEMENTED();
}
void PDReadJoySticks(void) {
//tU32 temp1x; // Pierre-Marie Baty -- unused variable
//tU32 temp1y; // Pierre-Marie Baty -- unused variable
//tU32 temp2x; // Pierre-Marie Baty -- unused variable
//tU32 temp2y; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
tS32 PDGetJoy1X(void) {
//tS32 joy; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
tS32 PDGetJoy1Y(void) {
//tS32 joy; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
tS32 PDGetJoy2X(void) {
//tS32 joy; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
tS32 PDGetJoy2Y(void) {
//tS32 joy; // Pierre-Marie Baty -- unused variable
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy1Button1(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy1Button2(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy1Button3(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy1Button4(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy2Button1(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy2Button2(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy2Button3(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDGetJoy2Button4(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
int PDFileUnlock(char* pThe_path) {
uint32_t dwFileAttributes; // [esp+Ch] [ebp-4h]
LOG_TRACE("(\"%s\")", pThe_path);
dwFileAttributes = GetFileAttributesA_(pThe_path);
return dwFileAttributes != INVALID_FILE_ATTRIBUTES && SetFileAttributesA_(pThe_path, dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
}
int PDCheckDriveExists2(char* pThe_path, char* pFile_name, tU32 pMin_size) {
char the_path[256]; // [esp+Ch] [ebp-108h] BYREF
tU32 file_size; // [esp+10Ch] [ebp-8h]
HANDLE_ hFile; // [esp+110h] [ebp-4h]
LOG_TRACE("(\"%s\", \"%s\", %d)", pThe_path, pFile_name, pMin_size);
file_size = 0;
if (pFile_name) {
PathCat(the_path, pThe_path, pFile_name);
} else {
}
if (the_path[0] && the_path[1] == ':' && !the_path[2]) {
strcat(the_path
, gDir_separator
);
}
if (GetFileAttributesA_(pThe_path) == INVALID_FILE_ATTRIBUTES) {
return 0;
}
hFile = CreateFileA_(the_path, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
file_size = GetFileSize_(hFile, 0);
CloseHandle_(hFile);
}
return file_size >= pMin_size;
}
int PDDoWeLeadAnAustereExistance(void) {
return 0;
}
// Windows-specific functions. The only name we know for sure is "Win32AllocateReplayBuffer".
void Win32BRenderWarningFunc(char* msg) {
dr_dprintf("*******************************************************************************");
dr_dprintf("BRender WARNING: '%s'", msg);
dr_dprintf("*******************************************************************************");
}
void Win32BRenderFailureFunc(char* msg) {
dr_dprintf("*******************************************************************************");
dr_dprintf("BRender FAILURE: '%s'", msg);
dr_dprintf("*******************************************************************************");
Win32FatalError("BRender error detected:", msg);
}