#include "../qcommon/qcommon.h"
#include <uv.h>
#include "../win32/conproc.h"
#include "resource.h"
#include "winquake.h"
#include <conio.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <float.h>
#include <io.h>
#include <stdio.h>
#include <GLFW/glfw3.h>
#define MINIMUM_WIN_MEMORY 0x0a00000
#define MAXIMUM_WIN_MEMORY 0x1000000
bool s_win95;
int starttime;
int ActiveApp;
bool Minimized;
static HANDLE hinput, houtput;
unsigned sys_msg_time;
unsigned sys_frame_time;
static HANDLE qwclsemaphore;
#define MAX_NUM_ARGVS 128
int argc;
char *argv[MAX_NUM_ARGVS];
void Sys_Error(char *error, ...) {
va_list argptr;
char text[1024];
CL_Shutdown();
Qcommon_Shutdown();
va_start(argptr, error);
vsprintf(text, error, argptr);
va_end(argptr);
MessageBox(NULL, text, "Error", 0 );
if(qwclsemaphore)
CloseHandle(qwclsemaphore);
DeinitConProc();
exit(1);
}
void Sys_Quit(void) {
timeEndPeriod(1);
CL_Shutdown();
Qcommon_Shutdown();
CloseHandle(qwclsemaphore);
if(dedicated && dedicated->value)
FreeConsole();
DeinitConProc();
exit(0);
}
void WinError(void) {
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, lpMsgBuf, "GetLastError", MB_OK | MB_ICONINFORMATION);
LocalFree(lpMsgBuf);
}
static void windows_uv_idle_cb(uv_idle_t *handle) {
extern GLFWwindow *glfw_window;
if(glfw_window != NULL && glfwWindowShouldClose(glfw_window)) {
Com_Quit();
}
sys_msg_time = Sys_Milliseconds();
glfwPollEvents();
}
void Sys_Init(void) {
static uv_idle_t windows_uv_idle;
uv_idle_init(global_uv_loop(), &windows_uv_idle);
uv_idle_start(&windows_uv_idle, windows_uv_idle_cb);
OSVERSIONINFO vinfo;
timeBeginPeriod(1);
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
if(!GetVersionEx(&vinfo))
Sys_Error("Couldn't get OS info");
if(vinfo.dwMajorVersion < 4)
Sys_Error("Quake2 requires windows version 4 or greater");
if(vinfo.dwPlatformId == VER_PLATFORM_WIN32s)
Sys_Error("Quake2 doesn't run on Win32s");
else if(vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
s_win95 = true;
if(dedicated->value) {
AllocConsole();
hinput = GetStdHandle(STD_INPUT_HANDLE);
houtput = GetStdHandle(STD_OUTPUT_HANDLE);
InitConProc(argc, argv);
}
}
static char console_text[256];
static int console_textlen;
char *Sys_ConsoleInput(void) {
INPUT_RECORD recs[1024];
DWORD dummy;
int ch;
DWORD numread;
DWORD numevents;
if(!dedicated || !dedicated->value)
return NULL;
for(;;) {
if(!GetNumberOfConsoleInputEvents(hinput, &numevents))
Sys_Error("Error getting # of console events");
if(numevents <= 0)
break;
if(!ReadConsoleInput(hinput, recs, 1, &numread))
Sys_Error("Error reading console input");
if(numread != 1)
Sys_Error("Couldn't read console input");
if(recs[0].EventType == KEY_EVENT) {
if(!recs[0].Event.KeyEvent.bKeyDown) {
ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
switch(ch) {
case '\r':
WriteFile(houtput, "\r\n", 2, &dummy, NULL);
if(console_textlen) {
console_text[console_textlen] = 0;
console_textlen = 0;
return console_text;
}
break;
case '\b':
if(console_textlen) {
console_textlen--;
WriteFile(houtput, "\b \b", 3, &dummy, NULL);
}
break;
default:
if(ch >= ' ') {
if(console_textlen < sizeof(console_text) - 2) {
WriteFile(houtput, &ch, 1, &dummy, NULL);
console_text[console_textlen] = ch;
console_textlen++;
}
}
break;
}
}
}
}
return NULL;
}
void Sys_ConsoleOutput(char *string) {
DWORD dummy;
char text[256];
if(!dedicated || !dedicated->value)
return;
if(console_textlen) {
text[0] = '\r';
memset(&text[1], ' ', console_textlen);
text[console_textlen + 1] = '\r';
text[console_textlen + 2] = 0;
WriteFile(houtput, text, console_textlen + 2, &dummy, NULL);
}
WriteFile(houtput, string, strlen(string), &dummy, NULL);
if(console_textlen)
WriteFile(houtput, console_text, console_textlen, &dummy, NULL);
}
void Sys_SendKeyEvents(void) {
extern GLFWwindow *glfw_window;
if(glfw_window != NULL && glfwWindowShouldClose(glfw_window)) {
Com_Quit();
}
glfwPollEvents();
sys_frame_time = Sys_Milliseconds(); }
char *Sys_GetClipboardData(void) {
char *data = NULL;
char *cliptext;
if(OpenClipboard(NULL) != 0) {
HANDLE hClipboardData;
if((hClipboardData = GetClipboardData(CF_TEXT)) != 0) {
if((cliptext = GlobalLock(hClipboardData)) != 0) {
data = malloc(GlobalSize(hClipboardData) + 1);
strcpy(data, cliptext);
GlobalUnlock(hClipboardData);
}
}
CloseClipboard();
}
return data;
}
void Sys_AppActivate(void) {
}
void Sys_UnloadGame(void) {}
void *Sys_GetGameAPI(void *parms) {
extern void *GetGameAPI(void *);
return GetGameAPI(parms);
}
void ParseCommandLine(LPSTR lpCmdLine) {
argc = 1;
argv[0] = "exe";
while(*lpCmdLine && (argc < MAX_NUM_ARGVS)) {
while(*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
lpCmdLine++;
if(*lpCmdLine) {
argv[argc] = lpCmdLine;
argc++;
while(*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
lpCmdLine++;
if(*lpCmdLine) {
*lpCmdLine = 0;
lpCmdLine++;
}
}
}
}
HINSTANCE global_hInstance;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if(hPrevInstance)
return 0;
global_hInstance = hInstance;
ParseCommandLine(lpCmdLine);
Qcommon_Init(argc, argv);
return Qcommon_RunFrames();
}