2014-03-15 16:59:03 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/// \file
|
|
|
|
/// \brief Win32 WinMain Entry Point
|
|
|
|
///
|
|
|
|
/// Win32 Sonic Robo Blast 2
|
|
|
|
///
|
|
|
|
/// NOTE:
|
|
|
|
/// To compile WINDOWS SRB2 version : define a '_WINDOWS' symbol.
|
|
|
|
/// to do this go to Project/Settings/ menu, click C/C++ tab, in
|
|
|
|
/// 'Preprocessor definitions:' add '_WINDOWS'
|
|
|
|
|
|
|
|
#include "../doomdef.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
|
|
|
|
#include "../doomstat.h" // netgame
|
|
|
|
#include "resource.h"
|
|
|
|
|
|
|
|
#include "../m_argv.h"
|
|
|
|
#include "../d_main.h"
|
|
|
|
#include "../i_system.h"
|
|
|
|
|
|
|
|
#include "../keys.h" //hack quick test
|
|
|
|
|
|
|
|
#include "../console.h"
|
|
|
|
|
|
|
|
#include "fabdxlib.h"
|
|
|
|
#include "win_main.h"
|
|
|
|
#include "win_dbg.h"
|
|
|
|
#include "../i_sound.h" // midi pause/unpause
|
|
|
|
#include "../g_input.h" // KEY_MOUSEWHEELxxx
|
|
|
|
#include "../screen.h" // for BASEVID*
|
|
|
|
|
|
|
|
// MSWheel support for Win95/NT3.51
|
|
|
|
#include <zmouse.h>
|
|
|
|
|
|
|
|
#ifndef WM_XBUTTONDOWN
|
|
|
|
#define WM_XBUTTONDOWN 523
|
|
|
|
#endif
|
|
|
|
#ifndef WM_XBUTTONUP
|
|
|
|
#define WM_XBUTTONUP 524
|
|
|
|
#endif
|
|
|
|
#ifndef MK_XBUTTON1
|
|
|
|
#define MK_XBUTTON1 32
|
|
|
|
#endif
|
|
|
|
#ifndef MK_XBUTTON2
|
|
|
|
#define MK_XBUTTON2 64
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef BOOL (WINAPI *p_IsDebuggerPresent)(VOID);
|
|
|
|
|
|
|
|
HWND hWndMain = NULL;
|
|
|
|
static HCURSOR windowCursor = NULL; // main window cursor
|
|
|
|
|
|
|
|
static LPCSTR wClassName = "SRB2WC";
|
|
|
|
|
|
|
|
boolean appActive = false; // app window is active
|
|
|
|
|
|
|
|
#ifdef LOGMESSAGES
|
|
|
|
FILE *logstream;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BOOL nodinput = FALSE;
|
|
|
|
|
|
|
|
static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
event_t ev; //Doom input event
|
|
|
|
int mouse_keys;
|
|
|
|
|
|
|
|
// judgecutor:
|
|
|
|
// Response MSH Mouse Wheel event
|
|
|
|
|
|
|
|
if (message == MSHWheelMessage)
|
|
|
|
{
|
|
|
|
message = WM_MOUSEWHEEL;
|
2016-05-22 03:53:04 +00:00
|
|
|
wParam <<= 16;
|
2014-03-15 16:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//I_OutputMsg("MainWndproc: %p,%i,%i,%i",hWnd, message, wParam, (UINT)lParam);
|
|
|
|
|
|
|
|
switch (message)
|
|
|
|
{
|
|
|
|
case WM_CREATE:
|
|
|
|
nodinput = M_CheckParm("-nodinput");
|
|
|
|
if (!nodinput && !LoadDirectInput())
|
|
|
|
nodinput = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_ACTIVATEAPP: // Handle task switching
|
|
|
|
appActive = (int)wParam;
|
|
|
|
|
|
|
|
//coming back from alt-tab? reset the palette.
|
|
|
|
if (appActive)
|
|
|
|
vid.recalc = true;
|
|
|
|
|
|
|
|
// pause music when alt-tab
|
|
|
|
if (appActive && !paused)
|
|
|
|
I_ResumeSong(0);
|
|
|
|
else if (!paused)
|
|
|
|
I_PauseSong(0);
|
|
|
|
{
|
|
|
|
HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
DWORD mode;
|
|
|
|
if (ci != INVALID_HANDLE_VALUE && GetFileType(ci) == FILE_TYPE_CHAR && GetConsoleMode(ci, &mode))
|
|
|
|
appActive = true;
|
|
|
|
}
|
|
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_PAINT:
|
|
|
|
if (!appActive && !bAppFullScreen && !netgame)
|
|
|
|
// app becomes inactive (if windowed)
|
|
|
|
{
|
|
|
|
// Paint "Game Paused" in the middle of the screen
|
|
|
|
PAINTSTRUCT ps;
|
|
|
|
RECT rect;
|
|
|
|
HDC hdc = BeginPaint (hWnd, &ps);
|
|
|
|
GetClientRect (hWnd, &rect);
|
|
|
|
DrawText (hdc, TEXT("Game Paused"), -1, &rect,
|
|
|
|
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
|
|
|
EndPaint (hWnd, &ps);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_QUERYNEWPALETTE:
|
|
|
|
RestoreDDPalette();
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case WM_PALETTECHANGED:
|
|
|
|
if((HWND)wParam != hWnd)
|
|
|
|
RestoreDDPalette();
|
|
|
|
break;
|
|
|
|
|
|
|
|
//case WM_RBUTTONDOWN:
|
|
|
|
//case WM_LBUTTONDOWN:
|
|
|
|
|
|
|
|
case WM_MOVE:
|
|
|
|
if (bAppFullScreen)
|
|
|
|
{
|
|
|
|
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
windowPosX = (SHORT) LOWORD(lParam); // horizontal position
|
|
|
|
windowPosY = (SHORT) HIWORD(lParam); // vertical position
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// This is where switching windowed/fullscreen is handled. DirectDraw
|
|
|
|
// objects must be destroyed, recreated, and artwork reloaded.
|
|
|
|
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
|
|
case WM_SIZE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SETCURSOR:
|
|
|
|
if (bAppFullScreen)
|
|
|
|
SetCursor(NULL);
|
|
|
|
else
|
|
|
|
SetCursor(windowCursor);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case WM_KEYUP:
|
|
|
|
ev.type = ev_keyup;
|
|
|
|
goto handleKeyDoom;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
ev.type = ev_keydown;
|
|
|
|
|
|
|
|
handleKeyDoom:
|
|
|
|
ev.data1 = 0;
|
|
|
|
if (wParam == VK_PAUSE)
|
|
|
|
// intercept PAUSE key
|
|
|
|
{
|
|
|
|
ev.data1 = KEY_PAUSE;
|
|
|
|
}
|
|
|
|
else if (!keyboard_started)
|
|
|
|
// post some keys during the game startup
|
|
|
|
// (allow escaping from network synchronization, or pressing enter after
|
|
|
|
// an error message in the console)
|
|
|
|
{
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case VK_ESCAPE: ev.data1 = KEY_ESCAPE; break;
|
|
|
|
case VK_RETURN: ev.data1 = KEY_ENTER; break;
|
|
|
|
case VK_SHIFT: ev.data1 = KEY_LSHIFT; break;
|
|
|
|
default: ev.data1 = MapVirtualKey((DWORD)wParam,2); // convert in to char
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev.data1)
|
|
|
|
D_PostEvent (&ev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// judgecutor:
|
|
|
|
// Handle mouse events
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
if (nodinput)
|
|
|
|
{
|
|
|
|
mouse_keys = 0;
|
|
|
|
if (wParam & MK_LBUTTON)
|
|
|
|
mouse_keys |= 1;
|
|
|
|
if (wParam & MK_RBUTTON)
|
|
|
|
mouse_keys |= 2;
|
|
|
|
if (wParam & MK_MBUTTON)
|
|
|
|
mouse_keys |= 4;
|
|
|
|
I_GetSysMouseEvents(mouse_keys);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_XBUTTONUP:
|
|
|
|
if (nodinput)
|
|
|
|
{
|
|
|
|
ev.type = ev_keyup;
|
|
|
|
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
|
|
|
D_PostEvent(&ev);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_XBUTTONDOWN:
|
|
|
|
if (nodinput)
|
|
|
|
{
|
|
|
|
ev.type = ev_keydown;
|
|
|
|
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
|
|
|
|
D_PostEvent(&ev);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
//I_OutputMsg("MW_WHEEL dispatched.\n");
|
|
|
|
ev.type = ev_keydown;
|
|
|
|
if ((INT16)HIWORD(wParam) > 0)
|
|
|
|
ev.data1 = KEY_MOUSEWHEELUP;
|
|
|
|
else
|
|
|
|
ev.data1 = KEY_MOUSEWHEELDOWN;
|
|
|
|
D_PostEvent(&ev);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SETTEXT:
|
|
|
|
COM_BufAddText((LPCSTR)lParam);
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
PostQuitMessage(0); //to quit while in-game
|
|
|
|
ev.data1 = KEY_ESCAPE; //to exit network synchronization
|
|
|
|
ev.type = ev_keydown;
|
|
|
|
D_PostEvent (&ev);
|
|
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
|
|
//faB: main app loop will exit the loop and proceed with I_Quit()
|
|
|
|
PostQuitMessage(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
// Don't allow the keyboard to activate the menu.
|
|
|
|
if(wParam == SC_KEYMENU)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline VOID OpenTextConsole(VOID)
|
|
|
|
{
|
|
|
|
HANDLE ci, co;
|
|
|
|
BOOL console;
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
console = M_CheckParm("-noconsole") == 0;
|
|
|
|
#else
|
|
|
|
console = M_CheckParm("-console") != 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dedicated = M_CheckParm("-dedicated") != 0;
|
|
|
|
|
|
|
|
if (M_CheckParm("-detachconsole"))
|
|
|
|
{
|
|
|
|
if (FreeConsole())
|
|
|
|
{
|
|
|
|
I_OutputMsg("Detatched console.\n");
|
|
|
|
console = TRUE; //lets get back a console
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
I_OutputMsg("No console to detatch.\n");
|
|
|
|
I_ShowLastError(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dedicated || console)
|
|
|
|
{
|
|
|
|
if (AllocConsole()) //Let get the real console HANDLEs, because Mingw's Bash is bad!
|
|
|
|
{
|
|
|
|
SetConsoleTitleA("SRB2 Console");
|
|
|
|
CONS_Printf(M_GetText("Hello, it's me, SRB2's Console Window\n"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
I_OutputMsg("We have a console already.\n");
|
|
|
|
I_ShowLastError(FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
ci = CreateFile(TEXT("CONIN$") , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (ci != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
HANDLE sih = GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
if (sih != ci)
|
|
|
|
{
|
|
|
|
I_OutputMsg("Old STD_INPUT_HANDLE: %p\nNew STD_INPUT_HANDLE: %p\n", sih, ci);
|
|
|
|
SetStdHandle(STD_INPUT_HANDLE,ci);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_OutputMsg("STD_INPUT_HANDLE already set at %p\n", ci);
|
|
|
|
|
|
|
|
if (GetFileType(ci) == FILE_TYPE_CHAR)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
const DWORD CM = ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT; //default mode but no ENABLE_MOUSE_INPUT
|
|
|
|
if (SetConsoleMode(ci,CM))
|
|
|
|
{
|
|
|
|
I_OutputMsg("Disabled mouse input on the console\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
I_OutputMsg("Could not disable mouse input on the console\n");
|
|
|
|
I_ShowLastError(FALSE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_OutputMsg("Handle CONIN$ in not a Console HANDLE\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
I_OutputMsg("Could not get a CONIN$ HANDLE\n");
|
|
|
|
I_ShowLastError(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
co = CreateFile(TEXT("CONOUT$"), GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (co != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
HANDLE soh = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
HANDLE seh = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
if (soh != co)
|
|
|
|
{
|
|
|
|
I_OutputMsg("Old STD_OUTPUT_HANDLE: %p\nNew STD_OUTPUT_HANDLE: %p\n", soh, co);
|
|
|
|
SetStdHandle(STD_OUTPUT_HANDLE,co);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_OutputMsg("STD_OUTPUT_HANDLE already set at %p\n", co);
|
|
|
|
if (seh != co)
|
|
|
|
{
|
|
|
|
I_OutputMsg("Old STD_ERROR_HANDLE: %p\nNew STD_ERROR_HANDLE: %p\n", seh, co);
|
|
|
|
SetStdHandle(STD_ERROR_HANDLE,co);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_OutputMsg("STD_ERROR_HANDLE already set at %p\n", co);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
I_OutputMsg("Could not get a CONOUT$ HANDLE\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Do that Windows initialization stuff...
|
|
|
|
//
|
|
|
|
static HWND OpenMainWindow (HINSTANCE hInstance, LPSTR wTitle)
|
|
|
|
{
|
|
|
|
const LONG styles = WS_CAPTION|WS_POPUP|WS_SYSMENU, exstyles = 0;
|
|
|
|
HWND hWnd;
|
|
|
|
WNDCLASSEXA wc;
|
|
|
|
RECT bounds;
|
|
|
|
|
|
|
|
// Set up and register window class
|
|
|
|
ZeroMemory(&wc, sizeof(wc));
|
|
|
|
wc.cbSize = sizeof(wc);
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW /*| CS_DBLCLKS*/;
|
|
|
|
wc.lpfnWndProc = MainWndproc;
|
|
|
|
wc.hInstance = hInstance;
|
|
|
|
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DLICON1));
|
|
|
|
windowCursor = LoadCursor(NULL, IDC_WAIT); //LoadCursor(hInstance, MAKEINTRESOURCE(IDC_DLCURSOR1));
|
|
|
|
wc.hCursor = windowCursor;
|
|
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
|
|
wc.lpszClassName = wClassName;
|
|
|
|
|
|
|
|
if (!RegisterClassExA(&wc))
|
|
|
|
{
|
|
|
|
I_OutputMsg("Error doing RegisterClassExA\n");
|
|
|
|
I_ShowLastError(TRUE);
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a window
|
|
|
|
// CreateWindowEx - seems to create just the interior, not the borders
|
|
|
|
|
|
|
|
bounds.left = 0;
|
|
|
|
bounds.right = dedicated ? 0 : specialmodes[0].width;
|
|
|
|
bounds.top = 0;
|
|
|
|
bounds.bottom = dedicated ? 0 : specialmodes[0].height;
|
|
|
|
|
|
|
|
AdjustWindowRectEx(&bounds, styles, FALSE, exstyles);
|
|
|
|
|
|
|
|
hWnd = CreateWindowExA(
|
|
|
|
exstyles, //ExStyle
|
|
|
|
wClassName, //Classname
|
|
|
|
wTitle, //Windowname
|
|
|
|
styles, //dwStyle //WS_VISIBLE|WS_POPUP for bAppFullScreen
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
bounds.right - bounds.left, //GetSystemMetrics(SM_CXSCREEN),
|
|
|
|
bounds.bottom - bounds.top, //GetSystemMetrics(SM_CYSCREEN),
|
|
|
|
NULL, //hWnd Parent
|
|
|
|
NULL, //hMenu Menu
|
|
|
|
hInstance,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (hWnd == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
I_OutputMsg("Error doing CreateWindowExA\n");
|
|
|
|
I_ShowLastError(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline BOOL tlErrorMessage(const TCHAR *err)
|
|
|
|
{
|
|
|
|
/* make the cursor visible */
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
|
|
|
|
//
|
|
|
|
// warn user if there is one
|
|
|
|
//
|
2016-05-22 03:53:04 +00:00
|
|
|
printf("Error %Ts..\n", err);
|
2014-03-15 16:59:03 +00:00
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
MessageBox(hWndMain, err, TEXT("ERROR"), MB_OK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------
|
|
|
|
// Command line stuff
|
|
|
|
// ------------------
|
|
|
|
#define MAXCMDLINEARGS 64
|
|
|
|
static char * myWargv[MAXCMDLINEARGS+1];
|
|
|
|
static char myCmdline[512];
|
|
|
|
|
|
|
|
static VOID GetArgcArgv (LPSTR cmdline)
|
|
|
|
{
|
|
|
|
LPSTR tokenstr;
|
|
|
|
size_t i = 0, len;
|
|
|
|
char cSep = ' ';
|
|
|
|
BOOL bCvar = FALSE, prevCvar = FALSE;
|
|
|
|
|
|
|
|
// split arguments of command line into argv
|
|
|
|
strlcpy (myCmdline, cmdline, sizeof(myCmdline)); // in case window's cmdline is in protected memory..for strtok
|
|
|
|
len = strlen (myCmdline);
|
|
|
|
|
|
|
|
myargc = 0;
|
|
|
|
while (myargc < MAXCMDLINEARGS)
|
|
|
|
{
|
|
|
|
// get token
|
|
|
|
while (myCmdline[i] == cSep)
|
|
|
|
i++;
|
|
|
|
if (i >= len)
|
|
|
|
break;
|
|
|
|
tokenstr = myCmdline + i;
|
|
|
|
if (myCmdline[i] == '"')
|
|
|
|
{
|
|
|
|
cSep = '"';
|
|
|
|
i++;
|
|
|
|
if (!prevCvar) //cvar leave the "" in
|
|
|
|
tokenstr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cSep = ' ';
|
|
|
|
|
|
|
|
//cvar
|
|
|
|
if (myCmdline[i] == '+' && cSep == ' ') //a + begins a cvarname, but not after quotes
|
|
|
|
bCvar = TRUE;
|
|
|
|
else
|
|
|
|
bCvar = FALSE;
|
|
|
|
|
|
|
|
while (myCmdline[i] &&
|
|
|
|
myCmdline[i] != cSep)
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if (myCmdline[i] == '"')
|
|
|
|
{
|
|
|
|
cSep = ' ';
|
|
|
|
if (prevCvar)
|
|
|
|
i++; // get ending " quote in arg
|
|
|
|
}
|
|
|
|
|
|
|
|
prevCvar = bCvar;
|
|
|
|
|
|
|
|
if (myCmdline + i > tokenstr)
|
|
|
|
{
|
|
|
|
myWargv[myargc++] = tokenstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!myCmdline[i] || i >= len)
|
|
|
|
break;
|
|
|
|
|
|
|
|
myCmdline[i++] = '\0';
|
|
|
|
}
|
|
|
|
myWargv[myargc] = NULL;
|
|
|
|
|
|
|
|
// m_argv.c uses myargv[], we used myWargv because we fill the arguments ourselves
|
|
|
|
// and myargv is just a pointer, so we set it to point myWargv
|
|
|
|
myargv = myWargv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline VOID MakeCodeWritable(VOID)
|
|
|
|
{
|
|
|
|
#ifdef USEASM // Disable write-protection of code segment
|
|
|
|
DWORD OldRights;
|
|
|
|
const DWORD NewRights = PAGE_EXECUTE_READWRITE;
|
|
|
|
PBYTE pBaseOfImage = (PBYTE)GetModuleHandle(NULL);
|
|
|
|
PIMAGE_DOS_HEADER dosH =(PIMAGE_DOS_HEADER)pBaseOfImage;
|
|
|
|
PIMAGE_NT_HEADERS ntH = (PIMAGE_NT_HEADERS)(pBaseOfImage + dosH->e_lfanew);
|
|
|
|
PIMAGE_OPTIONAL_HEADER oH = (PIMAGE_OPTIONAL_HEADER)
|
|
|
|
((PBYTE)ntH + sizeof (IMAGE_NT_SIGNATURE) + sizeof (IMAGE_FILE_HEADER));
|
|
|
|
LPVOID pA = pBaseOfImage+oH->BaseOfCode;
|
|
|
|
SIZE_T pS = oH->SizeOfCode;
|
|
|
|
#if 1 // try to find the text section
|
|
|
|
PIMAGE_SECTION_HEADER ntS = IMAGE_FIRST_SECTION (ntH);
|
|
|
|
WORD s;
|
|
|
|
for (s = 0; s < ntH->FileHeader.NumberOfSections; s++)
|
|
|
|
{
|
|
|
|
if (memcmp (ntS[s].Name, ".text\0\0", 8) == 0)
|
|
|
|
{
|
|
|
|
pA = pBaseOfImage+ntS[s].VirtualAddress;
|
|
|
|
pS = ntS[s].Misc.VirtualSize;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!VirtualProtect(pA,pS,NewRights,&OldRights))
|
|
|
|
I_Error("Could not make code writable\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// HandledWinMain : called by exception handler
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
static int WINAPI HandledWinMain(HINSTANCE hInstance)
|
|
|
|
{
|
|
|
|
LPSTR args;
|
|
|
|
|
|
|
|
#ifdef LOGMESSAGES
|
|
|
|
// DEBUG!!! - set logstream to NULL to disable debug log
|
|
|
|
// Replace WIN32 filehandle with standard C calls, because WIN32 doesn't handle \n properly.
|
|
|
|
logstream = fopen(va("%s"PATHSEP"%s", srb2home, "log.txt"), "wt");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// fill myargc,myargv for m_argv.c retrieval of cmdline arguments
|
|
|
|
args = GetCommandLineA();
|
|
|
|
CONS_Printf("Command line arguments: '%s'\n", args);
|
|
|
|
GetArgcArgv(args);
|
|
|
|
// Create a text console window
|
|
|
|
OpenTextConsole();
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
CONS_Printf("Myargc: %d\n", myargc);
|
|
|
|
for (i = 0; i < myargc; i++)
|
|
|
|
CONS_Printf("myargv[%d] : '%s'\n", i, myargv[i]);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// open a dummy window, both OpenGL and DirectX need one.
|
|
|
|
if ((hWndMain = OpenMainWindow(hInstance, va("SRB2 "VERSIONSTRING))) == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
tlErrorMessage(TEXT("Couldn't open window"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// currently starts DirectInput
|
|
|
|
CONS_Printf("I_StartupSystem() ...\n");
|
|
|
|
I_StartupSystem();
|
|
|
|
MakeCodeWritable();
|
|
|
|
|
|
|
|
// startup SRB2
|
|
|
|
CONS_Printf("Setting up SRB2...\n");
|
|
|
|
D_SRB2Main();
|
|
|
|
CONS_Printf("Entering main game loop...\n");
|
|
|
|
// never return
|
|
|
|
D_SRB2Loop();
|
|
|
|
|
|
|
|
// back to Windoze
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Exception handler calls WinMain for catching exceptions
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
int WINAPI WinMain (HINSTANCE hInstance,
|
|
|
|
HINSTANCE hPrevInstance,
|
|
|
|
LPSTR lpCmdLine,
|
|
|
|
int nCmdShow)
|
|
|
|
{
|
|
|
|
int Result = -1;
|
|
|
|
|
|
|
|
// Win95 and NT <4 don't have this, so link at runtime.
|
|
|
|
p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsDebuggerPresent");
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(hPrevInstance);
|
|
|
|
UNREFERENCED_PARAMETER(lpCmdLine);
|
|
|
|
UNREFERENCED_PARAMETER(nCmdShow);
|
|
|
|
|
|
|
|
#ifdef BUGTRAP
|
|
|
|
// Try BugTrap first.
|
|
|
|
if((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) && InitBugTrap())
|
|
|
|
Result = HandledWinMain(hInstance);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
// Try Dr MinGW's exception handler.
|
|
|
|
if (!pfnIsDebuggerPresent || !pfnIsDebuggerPresent())
|
|
|
|
LoadLibraryA("exchndl.dll");
|
|
|
|
|
|
|
|
prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo);
|
|
|
|
|
|
|
|
Result = HandledWinMain(hInstance);
|
|
|
|
#ifdef BUGTRAP
|
|
|
|
} // BT failure clause.
|
|
|
|
|
|
|
|
// This is safe even if BT didn't start.
|
|
|
|
ShutdownBugTrap();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
#endif //_WINDOWS
|