mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-10 11:59:58 -05:00
Quack 3: Arena
This commit is contained in:
committed by
GitHub
parent
0bf99969fd
commit
40035fa235
510
win32/cd_win.c
Normal file
510
win32/cd_win.c
Normal file
@ -0,0 +1,510 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
|
||||
// rights reserved.
|
||||
|
||||
#include <windows.h>
|
||||
#include "../client/client.h"
|
||||
|
||||
extern HWND cl_hwnd;
|
||||
|
||||
static qboolean cdValid = false;
|
||||
static qboolean playing = false;
|
||||
static qboolean wasPlaying = false;
|
||||
static qboolean initialized = false;
|
||||
static qboolean enabled = false;
|
||||
static qboolean playLooping = false;
|
||||
static byte remap[100];
|
||||
static byte cdrom;
|
||||
static byte playTrack;
|
||||
static byte maxTrack;
|
||||
|
||||
cvar_t *cd_nocd;
|
||||
cvar_t *cd_loopcount;
|
||||
cvar_t *cd_looptrack;
|
||||
|
||||
UINT wDeviceID;
|
||||
int loopcounter;
|
||||
|
||||
|
||||
void CDAudio_Pause(void);
|
||||
|
||||
static void CDAudio_Eject(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
|
||||
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL))
|
||||
Com_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn);
|
||||
}
|
||||
|
||||
|
||||
static void CDAudio_CloseDoor(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
|
||||
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL))
|
||||
Com_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn);
|
||||
}
|
||||
|
||||
|
||||
static int CDAudio_GetAudioDiskInfo(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
MCI_STATUS_PARMS mciStatusParms;
|
||||
|
||||
|
||||
cdValid = false;
|
||||
|
||||
mciStatusParms.dwItem = MCI_STATUS_READY;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("CDAudio: drive ready test - get status failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (!mciStatusParms.dwReturn)
|
||||
{
|
||||
Com_DPrintf("CDAudio: drive not ready\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("CDAudio: get tracks - status failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (mciStatusParms.dwReturn < 1)
|
||||
{
|
||||
Com_DPrintf("CDAudio: no music tracks\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cdValid = true;
|
||||
maxTrack = mciStatusParms.dwReturn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CDAudio_Play2(int track, qboolean looping)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
MCI_PLAY_PARMS mciPlayParms;
|
||||
MCI_STATUS_PARMS mciStatusParms;
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
if (!cdValid)
|
||||
{
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
if (!cdValid)
|
||||
return;
|
||||
}
|
||||
|
||||
track = remap[track];
|
||||
|
||||
if (track < 1 || track > maxTrack)
|
||||
{
|
||||
CDAudio_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't try to play a non-audio track
|
||||
mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
|
||||
mciStatusParms.dwTrack = track;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
|
||||
return;
|
||||
}
|
||||
if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
|
||||
{
|
||||
Com_Printf("CDAudio: track %i is not audio\n", track);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the length of the track to be played
|
||||
mciStatusParms.dwItem = MCI_STATUS_LENGTH;
|
||||
mciStatusParms.dwTrack = track;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("MCI_STATUS failed (%i)\n", dwReturn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (playing)
|
||||
{
|
||||
if (playTrack == track)
|
||||
return;
|
||||
CDAudio_Stop();
|
||||
}
|
||||
|
||||
mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
|
||||
mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
|
||||
mciPlayParms.dwCallback = (DWORD)cl_hwnd;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
|
||||
return;
|
||||
}
|
||||
|
||||
playLooping = looping;
|
||||
playTrack = track;
|
||||
playing = true;
|
||||
|
||||
if ( Cvar_VariableValue( "cd_nocd" ) )
|
||||
CDAudio_Pause ();
|
||||
}
|
||||
|
||||
|
||||
void CDAudio_Play(int track, qboolean looping)
|
||||
{
|
||||
// set a loop counter so that this track will change to the
|
||||
// looptrack later
|
||||
loopcounter = 0;
|
||||
CDAudio_Play2(track, looping);
|
||||
}
|
||||
|
||||
void CDAudio_Stop(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
if (!playing)
|
||||
return;
|
||||
|
||||
if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL))
|
||||
Com_DPrintf("MCI_STOP failed (%i)", dwReturn);
|
||||
|
||||
wasPlaying = false;
|
||||
playing = false;
|
||||
}
|
||||
|
||||
|
||||
void CDAudio_Pause(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
MCI_GENERIC_PARMS mciGenericParms;
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
if (!playing)
|
||||
return;
|
||||
|
||||
mciGenericParms.dwCallback = (DWORD)cl_hwnd;
|
||||
if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms))
|
||||
Com_DPrintf("MCI_PAUSE failed (%i)", dwReturn);
|
||||
|
||||
wasPlaying = playing;
|
||||
playing = false;
|
||||
}
|
||||
|
||||
|
||||
void CDAudio_Resume(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
MCI_PLAY_PARMS mciPlayParms;
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
if (!cdValid)
|
||||
return;
|
||||
|
||||
if (!wasPlaying)
|
||||
return;
|
||||
|
||||
mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
|
||||
mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
|
||||
mciPlayParms.dwCallback = (DWORD)cl_hwnd;
|
||||
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
|
||||
if (dwReturn)
|
||||
{
|
||||
Com_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn);
|
||||
return;
|
||||
}
|
||||
playing = true;
|
||||
}
|
||||
|
||||
|
||||
static void CD_f (void)
|
||||
{
|
||||
char *command;
|
||||
int ret;
|
||||
int n;
|
||||
|
||||
if (Cmd_Argc() < 2)
|
||||
return;
|
||||
|
||||
command = Cmd_Argv (1);
|
||||
|
||||
if (Q_strcasecmp(command, "on") == 0)
|
||||
{
|
||||
enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "off") == 0)
|
||||
{
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "reset") == 0)
|
||||
{
|
||||
enabled = true;
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
for (n = 0; n < 100; n++)
|
||||
remap[n] = n;
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "remap") == 0)
|
||||
{
|
||||
ret = Cmd_Argc() - 2;
|
||||
if (ret <= 0)
|
||||
{
|
||||
for (n = 1; n < 100; n++)
|
||||
if (remap[n] != n)
|
||||
Com_Printf(" %u -> %u\n", n, remap[n]);
|
||||
return;
|
||||
}
|
||||
for (n = 1; n <= ret; n++)
|
||||
remap[n] = atoi(Cmd_Argv (n+1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "close") == 0)
|
||||
{
|
||||
CDAudio_CloseDoor();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cdValid)
|
||||
{
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
if (!cdValid)
|
||||
{
|
||||
Com_Printf("No CD in player.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "play") == 0)
|
||||
{
|
||||
CDAudio_Play(atoi(Cmd_Argv (2)), false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "loop") == 0)
|
||||
{
|
||||
CDAudio_Play(atoi(Cmd_Argv (2)), true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "stop") == 0)
|
||||
{
|
||||
CDAudio_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "pause") == 0)
|
||||
{
|
||||
CDAudio_Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "resume") == 0)
|
||||
{
|
||||
CDAudio_Resume();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "eject") == 0)
|
||||
{
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
CDAudio_Eject();
|
||||
cdValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(command, "info") == 0)
|
||||
{
|
||||
Com_Printf("%u tracks\n", maxTrack);
|
||||
if (playing)
|
||||
Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
|
||||
else if (wasPlaying)
|
||||
Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (lParam != wDeviceID)
|
||||
return 1;
|
||||
|
||||
switch (wParam)
|
||||
{
|
||||
case MCI_NOTIFY_SUCCESSFUL:
|
||||
if (playing)
|
||||
{
|
||||
playing = false;
|
||||
if (playLooping)
|
||||
{
|
||||
// if the track has played the given number of times,
|
||||
// go to the ambient track
|
||||
if (++loopcounter >= cd_loopcount->value)
|
||||
CDAudio_Play2(cd_looptrack->value, true);
|
||||
else
|
||||
CDAudio_Play2(playTrack, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MCI_NOTIFY_ABORTED:
|
||||
case MCI_NOTIFY_SUPERSEDED:
|
||||
break;
|
||||
|
||||
case MCI_NOTIFY_FAILURE:
|
||||
Com_DPrintf("MCI_NOTIFY_FAILURE\n");
|
||||
CDAudio_Stop ();
|
||||
cdValid = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CDAudio_Update(void)
|
||||
{
|
||||
if ( cd_nocd->value != !enabled )
|
||||
{
|
||||
if ( cd_nocd->value )
|
||||
{
|
||||
CDAudio_Stop();
|
||||
enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
enabled = true;
|
||||
CDAudio_Resume ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CDAudio_Init(void)
|
||||
{
|
||||
DWORD dwReturn;
|
||||
MCI_OPEN_PARMS mciOpenParms;
|
||||
MCI_SET_PARMS mciSetParms;
|
||||
int n;
|
||||
|
||||
cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
|
||||
cd_loopcount = Cvar_Get ("cd_loopcount", "4", 0);
|
||||
cd_looptrack = Cvar_Get ("cd_looptrack", "11", 0);
|
||||
if ( cd_nocd->value)
|
||||
return -1;
|
||||
|
||||
mciOpenParms.lpstrDeviceType = "cdaudio";
|
||||
if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms))
|
||||
{
|
||||
Com_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn);
|
||||
return -1;
|
||||
}
|
||||
wDeviceID = mciOpenParms.wDeviceID;
|
||||
|
||||
// Set the time format to track/minute/second/frame (TMSF).
|
||||
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
|
||||
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
|
||||
{
|
||||
Com_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn);
|
||||
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (n = 0; n < 100; n++)
|
||||
remap[n] = n;
|
||||
initialized = true;
|
||||
enabled = true;
|
||||
|
||||
if (CDAudio_GetAudioDiskInfo())
|
||||
{
|
||||
// Com_Printf("CDAudio_Init: No CD in player.\n");
|
||||
cdValid = false;
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
Cmd_AddCommand ("cd", CD_f);
|
||||
|
||||
Com_Printf("CD Audio Initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CDAudio_Shutdown(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
CDAudio_Stop();
|
||||
if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL))
|
||||
Com_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
CDAudio_Activate
|
||||
|
||||
Called when the main window gains or loses focus.
|
||||
The window have been destroyed and recreated
|
||||
between a deactivate and an activate.
|
||||
===========
|
||||
*/
|
||||
void CDAudio_Activate (qboolean active)
|
||||
{
|
||||
if (active)
|
||||
CDAudio_Resume ();
|
||||
else
|
||||
CDAudio_Pause ();
|
||||
}
|
431
win32/conproc.c
Normal file
431
win32/conproc.c
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// conproc.c -- support for qhost
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include "conproc.h"
|
||||
|
||||
#define CCOM_WRITE_TEXT 0x2
|
||||
// Param1 : Text
|
||||
|
||||
#define CCOM_GET_TEXT 0x3
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
|
||||
#define CCOM_GET_SCR_LINES 0x4
|
||||
// No params
|
||||
|
||||
#define CCOM_SET_SCR_LINES 0x5
|
||||
// Param1 : Number of lines
|
||||
|
||||
|
||||
HANDLE heventDone;
|
||||
HANDLE hfileBuffer;
|
||||
HANDLE heventChildSend;
|
||||
HANDLE heventParentSend;
|
||||
HANDLE hStdout;
|
||||
HANDLE hStdin;
|
||||
|
||||
unsigned _stdcall RequestProc (void *arg);
|
||||
LPVOID GetMappedBuffer (HANDLE hfileBuffer);
|
||||
void ReleaseMappedBuffer (LPVOID pBuffer);
|
||||
BOOL GetScreenBufferLines (int *piLines);
|
||||
BOOL SetScreenBufferLines (int iLines);
|
||||
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
|
||||
BOOL WriteText (LPCTSTR szText);
|
||||
int CharToCode (char c);
|
||||
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
|
||||
|
||||
int ccom_argc;
|
||||
char **ccom_argv;
|
||||
|
||||
/*
|
||||
================
|
||||
CCheckParm
|
||||
|
||||
Returns the position (1 to argc-1) in the program's argument list
|
||||
where the given parameter apears, or 0 if not present
|
||||
================
|
||||
*/
|
||||
int CCheckParm (char *parm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1 ; i<ccom_argc ; i++)
|
||||
{
|
||||
if (!ccom_argv[i])
|
||||
continue;
|
||||
if (!strcmp (parm,ccom_argv[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void InitConProc (int argc, char **argv)
|
||||
{
|
||||
unsigned threadAddr;
|
||||
HANDLE hFile;
|
||||
HANDLE heventParent;
|
||||
HANDLE heventChild;
|
||||
int t;
|
||||
|
||||
ccom_argc = argc;
|
||||
ccom_argv = argv;
|
||||
|
||||
// give QHOST a chance to hook into the console
|
||||
if ((t = CCheckParm ("-HFILE")) > 0)
|
||||
{
|
||||
if (t < argc)
|
||||
hFile = (HANDLE)atoi (ccom_argv[t+1]);
|
||||
}
|
||||
|
||||
if ((t = CCheckParm ("-HPARENT")) > 0)
|
||||
{
|
||||
if (t < argc)
|
||||
heventParent = (HANDLE)atoi (ccom_argv[t+1]);
|
||||
}
|
||||
|
||||
if ((t = CCheckParm ("-HCHILD")) > 0)
|
||||
{
|
||||
if (t < argc)
|
||||
heventChild = (HANDLE)atoi (ccom_argv[t+1]);
|
||||
}
|
||||
|
||||
|
||||
// ignore if we don't have all the events.
|
||||
if (!hFile || !heventParent || !heventChild)
|
||||
{
|
||||
printf ("Qhost not present.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("Initializing for qhost.\n");
|
||||
|
||||
hfileBuffer = hFile;
|
||||
heventParentSend = heventParent;
|
||||
heventChildSend = heventChild;
|
||||
|
||||
// so we'll know when to go away.
|
||||
heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
|
||||
if (!heventDone)
|
||||
{
|
||||
printf ("Couldn't create heventDone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
|
||||
{
|
||||
CloseHandle (heventDone);
|
||||
printf ("Couldn't create QHOST thread\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// save off the input/output handles.
|
||||
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
hStdin = GetStdHandle (STD_INPUT_HANDLE);
|
||||
|
||||
// force 80 character width, at least 25 character height
|
||||
SetConsoleCXCY (hStdout, 80, 25);
|
||||
}
|
||||
|
||||
|
||||
void DeinitConProc (void)
|
||||
{
|
||||
if (heventDone)
|
||||
SetEvent (heventDone);
|
||||
}
|
||||
|
||||
|
||||
unsigned _stdcall RequestProc (void *arg)
|
||||
{
|
||||
int *pBuffer;
|
||||
DWORD dwRet;
|
||||
HANDLE heventWait[2];
|
||||
int iBeginLine, iEndLine;
|
||||
|
||||
heventWait[0] = heventParentSend;
|
||||
heventWait[1] = heventDone;
|
||||
|
||||
while (1)
|
||||
{
|
||||
dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
|
||||
|
||||
// heventDone fired, so we're exiting.
|
||||
if (dwRet == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
|
||||
pBuffer = (int *) GetMappedBuffer (hfileBuffer);
|
||||
|
||||
// hfileBuffer is invalid. Just leave.
|
||||
if (!pBuffer)
|
||||
{
|
||||
printf ("Invalid hfileBuffer\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pBuffer[0])
|
||||
{
|
||||
case CCOM_WRITE_TEXT:
|
||||
// Param1 : Text
|
||||
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
|
||||
break;
|
||||
|
||||
case CCOM_GET_TEXT:
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
iBeginLine = pBuffer[1];
|
||||
iEndLine = pBuffer[2];
|
||||
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
|
||||
iEndLine);
|
||||
break;
|
||||
|
||||
case CCOM_GET_SCR_LINES:
|
||||
// No params
|
||||
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
|
||||
break;
|
||||
|
||||
case CCOM_SET_SCR_LINES:
|
||||
// Param1 : Number of lines
|
||||
pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
ReleaseMappedBuffer (pBuffer);
|
||||
SetEvent (heventChildSend);
|
||||
}
|
||||
|
||||
_endthreadex (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LPVOID GetMappedBuffer (HANDLE hfileBuffer)
|
||||
{
|
||||
LPVOID pBuffer;
|
||||
|
||||
pBuffer = MapViewOfFile (hfileBuffer,
|
||||
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
||||
void ReleaseMappedBuffer (LPVOID pBuffer)
|
||||
{
|
||||
UnmapViewOfFile (pBuffer);
|
||||
}
|
||||
|
||||
|
||||
BOOL GetScreenBufferLines (int *piLines)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
BOOL bRet;
|
||||
|
||||
bRet = GetConsoleScreenBufferInfo (hStdout, &info);
|
||||
|
||||
if (bRet)
|
||||
*piLines = info.dwSize.Y;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
BOOL SetScreenBufferLines (int iLines)
|
||||
{
|
||||
|
||||
return SetConsoleCXCY (hStdout, 80, iLines);
|
||||
}
|
||||
|
||||
|
||||
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
|
||||
{
|
||||
COORD coord;
|
||||
DWORD dwRead;
|
||||
BOOL bRet;
|
||||
|
||||
coord.X = 0;
|
||||
coord.Y = iBeginLine;
|
||||
|
||||
bRet = ReadConsoleOutputCharacter(
|
||||
hStdout,
|
||||
pszText,
|
||||
80 * (iEndLine - iBeginLine + 1),
|
||||
coord,
|
||||
&dwRead);
|
||||
|
||||
// Make sure it's null terminated.
|
||||
if (bRet)
|
||||
pszText[dwRead] = '\0';
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
BOOL WriteText (LPCTSTR szText)
|
||||
{
|
||||
DWORD dwWritten;
|
||||
INPUT_RECORD rec;
|
||||
char upper, *sz;
|
||||
|
||||
sz = (LPTSTR) szText;
|
||||
|
||||
while (*sz)
|
||||
{
|
||||
// 13 is the code for a carriage return (\n) instead of 10.
|
||||
if (*sz == 10)
|
||||
*sz = 13;
|
||||
|
||||
upper = toupper(*sz);
|
||||
|
||||
rec.EventType = KEY_EVENT;
|
||||
rec.Event.KeyEvent.bKeyDown = TRUE;
|
||||
rec.Event.KeyEvent.wRepeatCount = 1;
|
||||
rec.Event.KeyEvent.wVirtualKeyCode = upper;
|
||||
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
|
||||
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
|
||||
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
|
||||
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
rec.Event.KeyEvent.bKeyDown = FALSE;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
sz++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int CharToCode (char c)
|
||||
{
|
||||
char upper;
|
||||
|
||||
upper = toupper(c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 13:
|
||||
return 28;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isalpha(c))
|
||||
return (30 + upper - 65);
|
||||
|
||||
if (isdigit(c))
|
||||
return (1 + upper - 47);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
COORD coordMax;
|
||||
|
||||
coordMax = GetLargestConsoleWindowSize(hStdout);
|
||||
|
||||
if (cy > coordMax.Y)
|
||||
cy = coordMax.Y;
|
||||
|
||||
if (cx > coordMax.X)
|
||||
cx = coordMax.X;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// height
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = info.dwSize.X - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = cy - 1;
|
||||
|
||||
if (cy < info.dwSize.Y)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cy > info.dwSize.Y)
|
||||
{
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// width
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = cx - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = info.dwSize.Y - 1;
|
||||
|
||||
if (cx < info.dwSize.X)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cx > info.dwSize.X)
|
||||
{
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
24
win32/conproc.h
Normal file
24
win32/conproc.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// conproc.h -- support for qhost
|
||||
|
||||
void InitConProc (int argc, char **argv);
|
||||
void DeinitConProc (void);
|
||||
|
616
win32/glw_imp.c
Normal file
616
win32/glw_imp.c
Normal file
@ -0,0 +1,616 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
** GLW_IMP.C
|
||||
**
|
||||
** This file contains ALL Win32 specific stuff having to do with the
|
||||
** OpenGL refresh. When a port is being made the following functions
|
||||
** must be implemented by the port:
|
||||
**
|
||||
** GLimp_EndFrame
|
||||
** GLimp_Init
|
||||
** GLimp_Shutdown
|
||||
** GLimp_SwitchFullscreen
|
||||
**
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include "../ref_gl/gl_local.h"
|
||||
#include "glw_win.h"
|
||||
#include "winquake.h"
|
||||
|
||||
static qboolean GLimp_SwitchFullscreen( int width, int height );
|
||||
qboolean GLimp_InitGL (void);
|
||||
|
||||
glwstate_t glw_state;
|
||||
|
||||
extern cvar_t *vid_fullscreen;
|
||||
extern cvar_t *vid_ref;
|
||||
|
||||
static qboolean VerifyDriver( void )
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strcpy( buffer, qglGetString( GL_RENDERER ) );
|
||||
strlwr( buffer );
|
||||
if ( strcmp( buffer, "gdi generic" ) == 0 )
|
||||
if ( !glw_state.mcd_accelerated )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** VID_CreateWindow
|
||||
*/
|
||||
#define WINDOW_CLASS_NAME "Quake 2"
|
||||
|
||||
qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
|
||||
{
|
||||
WNDCLASS wc;
|
||||
RECT r;
|
||||
cvar_t *vid_xpos, *vid_ypos;
|
||||
int stylebits;
|
||||
int x, y, w, h;
|
||||
int exstyle;
|
||||
|
||||
/* Register the frame class */
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = (WNDPROC)glw_state.wndproc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = glw_state.hInstance;
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
||||
wc.hbrBackground = (void *)COLOR_GRAYTEXT;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = WINDOW_CLASS_NAME;
|
||||
|
||||
if (!RegisterClass (&wc) )
|
||||
ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
exstyle = WS_EX_TOPMOST;
|
||||
stylebits = WS_POPUP|WS_VISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
exstyle = 0;
|
||||
stylebits = WINDOW_STYLE;
|
||||
}
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = width;
|
||||
r.bottom = height;
|
||||
|
||||
AdjustWindowRect (&r, stylebits, FALSE);
|
||||
|
||||
w = r.right - r.left;
|
||||
h = r.bottom - r.top;
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
|
||||
vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
|
||||
x = vid_xpos->value;
|
||||
y = vid_ypos->value;
|
||||
}
|
||||
|
||||
glw_state.hWnd = CreateWindowEx (
|
||||
exstyle,
|
||||
WINDOW_CLASS_NAME,
|
||||
"Quake 2",
|
||||
stylebits,
|
||||
x, y, w, h,
|
||||
NULL,
|
||||
NULL,
|
||||
glw_state.hInstance,
|
||||
NULL);
|
||||
|
||||
if (!glw_state.hWnd)
|
||||
ri.Sys_Error (ERR_FATAL, "Couldn't create window");
|
||||
|
||||
ShowWindow( glw_state.hWnd, SW_SHOW );
|
||||
UpdateWindow( glw_state.hWnd );
|
||||
|
||||
// init all the gl stuff for the window
|
||||
if (!GLimp_InitGL ())
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "VID_CreateWindow() - GLimp_InitGL failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetForegroundWindow( glw_state.hWnd );
|
||||
SetFocus( glw_state.hWnd );
|
||||
|
||||
// let the sound and input subsystems know about the new window
|
||||
ri.Vid_NewWindow (width, height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLimp_SetMode
|
||||
*/
|
||||
rserr_t GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
|
||||
{
|
||||
int width, height;
|
||||
const char *win_fs[] = { "W", "FS" };
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n");
|
||||
|
||||
ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode );
|
||||
|
||||
if ( !ri.Vid_GetModeInfo( &width, &height, mode ) )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
|
||||
return rserr_invalid_mode;
|
||||
}
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, " %d %d %s\n", width, height, win_fs[fullscreen] );
|
||||
|
||||
// destroy the existing window
|
||||
if (glw_state.hWnd)
|
||||
{
|
||||
GLimp_Shutdown ();
|
||||
}
|
||||
|
||||
// do a CDS if needed
|
||||
if ( fullscreen )
|
||||
{
|
||||
DEVMODE dm;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...attempting fullscreen\n" );
|
||||
|
||||
memset( &dm, 0, sizeof( dm ) );
|
||||
|
||||
dm.dmSize = sizeof( dm );
|
||||
|
||||
dm.dmPelsWidth = width;
|
||||
dm.dmPelsHeight = height;
|
||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||
|
||||
if ( gl_bitdepth->value != 0 )
|
||||
{
|
||||
dm.dmBitsPerPel = gl_bitdepth->value;
|
||||
dm.dmFields |= DM_BITSPERPEL;
|
||||
ri.Con_Printf( PRINT_ALL, "...using gl_bitdepth of %d\n", ( int ) gl_bitdepth->value );
|
||||
}
|
||||
else
|
||||
{
|
||||
HDC hdc = GetDC( NULL );
|
||||
int bitspixel = GetDeviceCaps( hdc, BITSPIXEL );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...using desktop display depth of %d\n", bitspixel );
|
||||
|
||||
ReleaseDC( 0, hdc );
|
||||
}
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...calling CDS: " );
|
||||
if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL )
|
||||
{
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
|
||||
gl_state.fullscreen = true;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
if ( !VID_CreateWindow (width, height, true) )
|
||||
return rserr_invalid_mode;
|
||||
|
||||
return rserr_ok;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "failed\n" );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...calling CDS assuming dual monitors:" );
|
||||
|
||||
dm.dmPelsWidth = width * 2;
|
||||
dm.dmPelsHeight = height;
|
||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||
|
||||
if ( gl_bitdepth->value != 0 )
|
||||
{
|
||||
dm.dmBitsPerPel = gl_bitdepth->value;
|
||||
dm.dmFields |= DM_BITSPERPEL;
|
||||
}
|
||||
|
||||
/*
|
||||
** our first CDS failed, so maybe we're running on some weird dual monitor
|
||||
** system
|
||||
*/
|
||||
if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, " failed\n" );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
|
||||
|
||||
ChangeDisplaySettings( 0, 0 );
|
||||
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
gl_state.fullscreen = false;
|
||||
if ( !VID_CreateWindow (width, height, false) )
|
||||
return rserr_invalid_mode;
|
||||
return rserr_invalid_fullscreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, " ok\n" );
|
||||
if ( !VID_CreateWindow (width, height, true) )
|
||||
return rserr_invalid_mode;
|
||||
|
||||
gl_state.fullscreen = true;
|
||||
return rserr_ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
|
||||
|
||||
ChangeDisplaySettings( 0, 0 );
|
||||
|
||||
*pwidth = width;
|
||||
*pheight = height;
|
||||
gl_state.fullscreen = false;
|
||||
if ( !VID_CreateWindow (width, height, false) )
|
||||
return rserr_invalid_mode;
|
||||
}
|
||||
|
||||
return rserr_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_Shutdown
|
||||
**
|
||||
** This routine does all OS specific shutdown procedures for the OpenGL
|
||||
** subsystem. Under OpenGL this means NULLing out the current DC and
|
||||
** HGLRC, deleting the rendering context, and releasing the DC acquired
|
||||
** for the window. The state structure is also nulled out.
|
||||
**
|
||||
*/
|
||||
void GLimp_Shutdown( void )
|
||||
{
|
||||
if ( qwglMakeCurrent && !qwglMakeCurrent( NULL, NULL ) )
|
||||
ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglMakeCurrent failed\n");
|
||||
if ( glw_state.hGLRC )
|
||||
{
|
||||
if ( qwglDeleteContext && !qwglDeleteContext( glw_state.hGLRC ) )
|
||||
ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglDeleteContext failed\n");
|
||||
glw_state.hGLRC = NULL;
|
||||
}
|
||||
if (glw_state.hDC)
|
||||
{
|
||||
if ( !ReleaseDC( glw_state.hWnd, glw_state.hDC ) )
|
||||
ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - ReleaseDC failed\n" );
|
||||
glw_state.hDC = NULL;
|
||||
}
|
||||
if (glw_state.hWnd)
|
||||
{
|
||||
DestroyWindow ( glw_state.hWnd );
|
||||
glw_state.hWnd = NULL;
|
||||
}
|
||||
|
||||
if ( glw_state.log_fp )
|
||||
{
|
||||
fclose( glw_state.log_fp );
|
||||
glw_state.log_fp = 0;
|
||||
}
|
||||
|
||||
UnregisterClass (WINDOW_CLASS_NAME, glw_state.hInstance);
|
||||
|
||||
if ( gl_state.fullscreen )
|
||||
{
|
||||
ChangeDisplaySettings( 0, 0 );
|
||||
gl_state.fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLimp_Init
|
||||
**
|
||||
** This routine is responsible for initializing the OS specific portions
|
||||
** of OpenGL. Under Win32 this means dealing with the pixelformats and
|
||||
** doing the wgl interface stuff.
|
||||
*/
|
||||
qboolean GLimp_Init( void *hinstance, void *wndproc )
|
||||
{
|
||||
#define OSR2_BUILD_NUMBER 1111
|
||||
|
||||
OSVERSIONINFO vinfo;
|
||||
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
|
||||
glw_state.allowdisplaydepthchange = false;
|
||||
|
||||
if ( GetVersionEx( &vinfo) )
|
||||
{
|
||||
if ( vinfo.dwMajorVersion > 4 )
|
||||
{
|
||||
glw_state.allowdisplaydepthchange = true;
|
||||
}
|
||||
else if ( vinfo.dwMajorVersion == 4 )
|
||||
{
|
||||
if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
||||
{
|
||||
glw_state.allowdisplaydepthchange = true;
|
||||
}
|
||||
else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
||||
{
|
||||
if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
|
||||
{
|
||||
glw_state.allowdisplaydepthchange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetVersionEx failed\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
glw_state.hInstance = ( HINSTANCE ) hinstance;
|
||||
glw_state.wndproc = wndproc;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean GLimp_InitGL (void)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
||||
1, // version number
|
||||
PFD_DRAW_TO_WINDOW | // support window
|
||||
PFD_SUPPORT_OPENGL | // support OpenGL
|
||||
PFD_DOUBLEBUFFER, // double buffered
|
||||
PFD_TYPE_RGBA, // RGBA type
|
||||
24, // 24-bit color depth
|
||||
0, 0, 0, 0, 0, 0, // color bits ignored
|
||||
0, // no alpha buffer
|
||||
0, // shift bit ignored
|
||||
0, // no accumulation buffer
|
||||
0, 0, 0, 0, // accum bits ignored
|
||||
32, // 32-bit z-buffer
|
||||
0, // no stencil buffer
|
||||
0, // no auxiliary buffer
|
||||
PFD_MAIN_PLANE, // main layer
|
||||
0, // reserved
|
||||
0, 0, 0 // layer masks ignored
|
||||
};
|
||||
int pixelformat;
|
||||
cvar_t *stereo;
|
||||
|
||||
stereo = ri.Cvar_Get( "cl_stereo", "0", 0 );
|
||||
|
||||
/*
|
||||
** set PFD_STEREO if necessary
|
||||
*/
|
||||
if ( stereo->value != 0 )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...attempting to use stereo\n" );
|
||||
pfd.dwFlags |= PFD_STEREO;
|
||||
gl_state.stereo_enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_state.stereo_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** figure out if we're running on a minidriver or not
|
||||
*/
|
||||
if ( strstr( gl_driver->string, "opengl32" ) != 0 )
|
||||
glw_state.minidriver = false;
|
||||
else
|
||||
glw_state.minidriver = true;
|
||||
|
||||
/*
|
||||
** Get a DC for the specified window
|
||||
*/
|
||||
if ( glw_state.hDC != NULL )
|
||||
ri.Con_Printf( PRINT_ALL, "GLimp_Init() - non-NULL DC exists\n" );
|
||||
|
||||
if ( ( glw_state.hDC = GetDC( glw_state.hWnd ) ) == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetDC failed\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( glw_state.minidriver )
|
||||
{
|
||||
if ( (pixelformat = qwglChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglChoosePixelFormat failed\n");
|
||||
return false;
|
||||
}
|
||||
if ( qwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglSetPixelFormat failed\n");
|
||||
return false;
|
||||
}
|
||||
qwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - ChoosePixelFormat failed\n");
|
||||
return false;
|
||||
}
|
||||
if ( SetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - SetPixelFormat failed\n");
|
||||
return false;
|
||||
}
|
||||
DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
||||
|
||||
if ( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) )
|
||||
{
|
||||
extern cvar_t *gl_allow_software;
|
||||
|
||||
if ( gl_allow_software->value )
|
||||
glw_state.mcd_accelerated = true;
|
||||
else
|
||||
glw_state.mcd_accelerated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
glw_state.mcd_accelerated = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** report if stereo is desired but unavailable
|
||||
*/
|
||||
if ( !( pfd.dwFlags & PFD_STEREO ) && ( stereo->value != 0 ) )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...failed to select stereo pixel format\n" );
|
||||
ri.Cvar_SetValue( "cl_stereo", 0 );
|
||||
gl_state.stereo_enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** startup the OpenGL subsystem by creating a context and making
|
||||
** it current
|
||||
*/
|
||||
if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglCreateContext failed\n");
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) )
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglMakeCurrent failed\n");
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !VerifyDriver() )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "GLimp_Init() - no hardware acceleration detected\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** print out PFD specifics
|
||||
*/
|
||||
ri.Con_Printf( PRINT_ALL, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int ) pfd.cColorBits, ( int ) pfd.cDepthBits );
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if ( glw_state.hGLRC )
|
||||
{
|
||||
qwglDeleteContext( glw_state.hGLRC );
|
||||
glw_state.hGLRC = NULL;
|
||||
}
|
||||
|
||||
if ( glw_state.hDC )
|
||||
{
|
||||
ReleaseDC( glw_state.hWnd, glw_state.hDC );
|
||||
glw_state.hDC = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_BeginFrame
|
||||
*/
|
||||
void GLimp_BeginFrame( float camera_separation )
|
||||
{
|
||||
if ( gl_bitdepth->modified )
|
||||
{
|
||||
if ( gl_bitdepth->value != 0 && !glw_state.allowdisplaydepthchange )
|
||||
{
|
||||
ri.Cvar_SetValue( "gl_bitdepth", 0 );
|
||||
ri.Con_Printf( PRINT_ALL, "gl_bitdepth requires Win95 OSR2.x or WinNT 4.x\n" );
|
||||
}
|
||||
gl_bitdepth->modified = false;
|
||||
}
|
||||
|
||||
if ( camera_separation < 0 && gl_state.stereo_enabled )
|
||||
{
|
||||
qglDrawBuffer( GL_BACK_LEFT );
|
||||
}
|
||||
else if ( camera_separation > 0 && gl_state.stereo_enabled )
|
||||
{
|
||||
qglDrawBuffer( GL_BACK_RIGHT );
|
||||
}
|
||||
else
|
||||
{
|
||||
qglDrawBuffer( GL_BACK );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_EndFrame
|
||||
**
|
||||
** Responsible for doing a swapbuffers and possibly for other stuff
|
||||
** as yet to be determined. Probably better not to make this a GLimp
|
||||
** function and instead do a call to GLimp_SwapBuffers.
|
||||
*/
|
||||
void GLimp_EndFrame (void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = qglGetError();
|
||||
assert( err == GL_NO_ERROR );
|
||||
|
||||
if ( stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 )
|
||||
{
|
||||
if ( !qwglSwapBuffers( glw_state.hDC ) )
|
||||
ri.Sys_Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_AppActivate
|
||||
*/
|
||||
void GLimp_AppActivate( qboolean active )
|
||||
{
|
||||
if ( active )
|
||||
{
|
||||
SetForegroundWindow( glw_state.hWnd );
|
||||
ShowWindow( glw_state.hWnd, SW_RESTORE );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( vid_fullscreen->value )
|
||||
ShowWindow( glw_state.hWnd, SW_MINIMIZE );
|
||||
}
|
||||
}
|
47
win32/glw_win.h
Normal file
47
win32/glw_win.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
# error You should not be including this file on this platform
|
||||
#endif
|
||||
|
||||
#ifndef __GLW_WIN_H__
|
||||
#define __GLW_WIN_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HINSTANCE hInstance;
|
||||
void *wndproc;
|
||||
|
||||
HDC hDC; // handle to device context
|
||||
HWND hWnd; // handle to window
|
||||
HGLRC hGLRC; // handle to GL rendering context
|
||||
|
||||
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
|
||||
|
||||
qboolean minidriver;
|
||||
qboolean allowdisplaydepthchange;
|
||||
qboolean mcd_accelerated;
|
||||
|
||||
FILE *log_fp;
|
||||
} glwstate_t;
|
||||
|
||||
extern glwstate_t glw_state;
|
||||
|
||||
#endif
|
889
win32/in_win.c
Normal file
889
win32/in_win.c
Normal file
@ -0,0 +1,889 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// in_win.c -- windows 95 mouse and joystick code
|
||||
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
|
||||
|
||||
#include "../client/client.h"
|
||||
#include "winquake.h"
|
||||
|
||||
extern unsigned sys_msg_time;
|
||||
|
||||
// joystick defines and variables
|
||||
// where should defines be moved?
|
||||
#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
|
||||
#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball
|
||||
#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
|
||||
#define JOY_AXIS_X 0
|
||||
#define JOY_AXIS_Y 1
|
||||
#define JOY_AXIS_Z 2
|
||||
#define JOY_AXIS_R 3
|
||||
#define JOY_AXIS_U 4
|
||||
#define JOY_AXIS_V 5
|
||||
|
||||
enum _ControlList
|
||||
{
|
||||
AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn, AxisUp
|
||||
};
|
||||
|
||||
DWORD dwAxisFlags[JOY_MAX_AXES] =
|
||||
{
|
||||
JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
|
||||
};
|
||||
|
||||
DWORD dwAxisMap[JOY_MAX_AXES];
|
||||
DWORD dwControlMap[JOY_MAX_AXES];
|
||||
PDWORD pdwRawValue[JOY_MAX_AXES];
|
||||
|
||||
cvar_t *in_mouse;
|
||||
cvar_t *in_joystick;
|
||||
|
||||
|
||||
// none of these cvars are saved over a session
|
||||
// this means that advanced controller configuration needs to be executed
|
||||
// each time. this avoids any problems with getting back to a default usage
|
||||
// or when changing from one controller to another. this way at least something
|
||||
// works.
|
||||
cvar_t *joy_name;
|
||||
cvar_t *joy_advanced;
|
||||
cvar_t *joy_advaxisx;
|
||||
cvar_t *joy_advaxisy;
|
||||
cvar_t *joy_advaxisz;
|
||||
cvar_t *joy_advaxisr;
|
||||
cvar_t *joy_advaxisu;
|
||||
cvar_t *joy_advaxisv;
|
||||
cvar_t *joy_forwardthreshold;
|
||||
cvar_t *joy_sidethreshold;
|
||||
cvar_t *joy_pitchthreshold;
|
||||
cvar_t *joy_yawthreshold;
|
||||
cvar_t *joy_forwardsensitivity;
|
||||
cvar_t *joy_sidesensitivity;
|
||||
cvar_t *joy_pitchsensitivity;
|
||||
cvar_t *joy_yawsensitivity;
|
||||
cvar_t *joy_upthreshold;
|
||||
cvar_t *joy_upsensitivity;
|
||||
|
||||
qboolean joy_avail, joy_advancedinit, joy_haspov;
|
||||
DWORD joy_oldbuttonstate, joy_oldpovstate;
|
||||
|
||||
int joy_id;
|
||||
DWORD joy_flags;
|
||||
DWORD joy_numbuttons;
|
||||
|
||||
static JOYINFOEX ji;
|
||||
|
||||
qboolean in_appactive;
|
||||
|
||||
// forward-referenced functions
|
||||
void IN_StartupJoystick (void);
|
||||
void Joy_AdvancedUpdate_f (void);
|
||||
void IN_JoyMove (usercmd_t *cmd);
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
MOUSE CONTROL
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
// mouse variables
|
||||
cvar_t *m_filter;
|
||||
|
||||
qboolean mlooking;
|
||||
|
||||
void IN_MLookDown (void) { mlooking = true; }
|
||||
void IN_MLookUp (void) {
|
||||
mlooking = false;
|
||||
if (!freelook->value && lookspring->value)
|
||||
IN_CenterView ();
|
||||
}
|
||||
|
||||
int mouse_buttons;
|
||||
int mouse_oldbuttonstate;
|
||||
POINT current_pos;
|
||||
int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
|
||||
|
||||
int old_x, old_y;
|
||||
|
||||
qboolean mouseactive; // false when not focus app
|
||||
|
||||
qboolean restore_spi;
|
||||
qboolean mouseinitialized;
|
||||
int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
|
||||
qboolean mouseparmsvalid;
|
||||
|
||||
int window_center_x, window_center_y;
|
||||
RECT window_rect;
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_ActivateMouse
|
||||
|
||||
Called when the window gains focus or changes in some way
|
||||
===========
|
||||
*/
|
||||
void IN_ActivateMouse (void)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
if (!mouseinitialized)
|
||||
return;
|
||||
if (!in_mouse->value)
|
||||
{
|
||||
mouseactive = false;
|
||||
return;
|
||||
}
|
||||
if (mouseactive)
|
||||
return;
|
||||
|
||||
mouseactive = true;
|
||||
|
||||
if (mouseparmsvalid)
|
||||
restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
|
||||
|
||||
width = GetSystemMetrics (SM_CXSCREEN);
|
||||
height = GetSystemMetrics (SM_CYSCREEN);
|
||||
|
||||
GetWindowRect ( cl_hwnd, &window_rect);
|
||||
if (window_rect.left < 0)
|
||||
window_rect.left = 0;
|
||||
if (window_rect.top < 0)
|
||||
window_rect.top = 0;
|
||||
if (window_rect.right >= width)
|
||||
window_rect.right = width-1;
|
||||
if (window_rect.bottom >= height-1)
|
||||
window_rect.bottom = height-1;
|
||||
|
||||
window_center_x = (window_rect.right + window_rect.left)/2;
|
||||
window_center_y = (window_rect.top + window_rect.bottom)/2;
|
||||
|
||||
SetCursorPos (window_center_x, window_center_y);
|
||||
|
||||
old_x = window_center_x;
|
||||
old_y = window_center_y;
|
||||
|
||||
SetCapture ( cl_hwnd );
|
||||
ClipCursor (&window_rect);
|
||||
while (ShowCursor (FALSE) >= 0)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_DeactivateMouse
|
||||
|
||||
Called when the window loses focus
|
||||
===========
|
||||
*/
|
||||
void IN_DeactivateMouse (void)
|
||||
{
|
||||
if (!mouseinitialized)
|
||||
return;
|
||||
if (!mouseactive)
|
||||
return;
|
||||
|
||||
if (restore_spi)
|
||||
SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
|
||||
|
||||
mouseactive = false;
|
||||
|
||||
ClipCursor (NULL);
|
||||
ReleaseCapture ();
|
||||
while (ShowCursor (TRUE) < 0)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_StartupMouse
|
||||
===========
|
||||
*/
|
||||
void IN_StartupMouse (void)
|
||||
{
|
||||
cvar_t *cv;
|
||||
|
||||
cv = Cvar_Get ("in_initmouse", "1", CVAR_NOSET);
|
||||
if ( !cv->value )
|
||||
return;
|
||||
|
||||
mouseinitialized = true;
|
||||
mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
|
||||
mouse_buttons = 3;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseEvent
|
||||
===========
|
||||
*/
|
||||
void IN_MouseEvent (int mstate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mouseinitialized)
|
||||
return;
|
||||
|
||||
// perform button actions
|
||||
for (i=0 ; i<mouse_buttons ; i++)
|
||||
{
|
||||
if ( (mstate & (1<<i)) &&
|
||||
!(mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_MOUSE1 + i, true, sys_msg_time);
|
||||
}
|
||||
|
||||
if ( !(mstate & (1<<i)) &&
|
||||
(mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_MOUSE1 + i, false, sys_msg_time);
|
||||
}
|
||||
}
|
||||
|
||||
mouse_oldbuttonstate = mstate;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseMove
|
||||
===========
|
||||
*/
|
||||
void IN_MouseMove (usercmd_t *cmd)
|
||||
{
|
||||
int mx, my;
|
||||
|
||||
if (!mouseactive)
|
||||
return;
|
||||
|
||||
// find mouse movement
|
||||
if (!GetCursorPos (¤t_pos))
|
||||
return;
|
||||
|
||||
mx = current_pos.x - window_center_x;
|
||||
my = current_pos.y - window_center_y;
|
||||
|
||||
#if 0
|
||||
if (!mx && !my)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (m_filter->value)
|
||||
{
|
||||
mouse_x = (mx + old_mouse_x) * 0.5;
|
||||
mouse_y = (my + old_mouse_y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_x = mx;
|
||||
mouse_y = my;
|
||||
}
|
||||
|
||||
old_mouse_x = mx;
|
||||
old_mouse_y = my;
|
||||
|
||||
mouse_x *= sensitivity->value;
|
||||
mouse_y *= sensitivity->value;
|
||||
|
||||
// add mouse X/Y movement to cmd
|
||||
if ( (in_strafe.state & 1) || (lookstrafe->value && mlooking ))
|
||||
cmd->sidemove += m_side->value * mouse_x;
|
||||
else
|
||||
cl.viewangles[YAW] -= m_yaw->value * mouse_x;
|
||||
|
||||
if ( (mlooking || freelook->value) && !(in_strafe.state & 1))
|
||||
{
|
||||
cl.viewangles[PITCH] += m_pitch->value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->forwardmove -= m_forward->value * mouse_y;
|
||||
}
|
||||
|
||||
// force the mouse to the center, so there's room to move
|
||||
if (mx || my)
|
||||
SetCursorPos (window_center_x, window_center_y);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
VIEW CENTERING
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
cvar_t *v_centermove;
|
||||
cvar_t *v_centerspeed;
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Init
|
||||
===========
|
||||
*/
|
||||
void IN_Init (void)
|
||||
{
|
||||
// mouse variables
|
||||
m_filter = Cvar_Get ("m_filter", "0", 0);
|
||||
in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
|
||||
|
||||
// joystick variables
|
||||
in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
|
||||
joy_name = Cvar_Get ("joy_name", "joystick", 0);
|
||||
joy_advanced = Cvar_Get ("joy_advanced", "0", 0);
|
||||
joy_advaxisx = Cvar_Get ("joy_advaxisx", "0", 0);
|
||||
joy_advaxisy = Cvar_Get ("joy_advaxisy", "0", 0);
|
||||
joy_advaxisz = Cvar_Get ("joy_advaxisz", "0", 0);
|
||||
joy_advaxisr = Cvar_Get ("joy_advaxisr", "0", 0);
|
||||
joy_advaxisu = Cvar_Get ("joy_advaxisu", "0", 0);
|
||||
joy_advaxisv = Cvar_Get ("joy_advaxisv", "0", 0);
|
||||
joy_forwardthreshold = Cvar_Get ("joy_forwardthreshold", "0.15", 0);
|
||||
joy_sidethreshold = Cvar_Get ("joy_sidethreshold", "0.15", 0);
|
||||
joy_upthreshold = Cvar_Get ("joy_upthreshold", "0.15", 0);
|
||||
joy_pitchthreshold = Cvar_Get ("joy_pitchthreshold", "0.15", 0);
|
||||
joy_yawthreshold = Cvar_Get ("joy_yawthreshold", "0.15", 0);
|
||||
joy_forwardsensitivity = Cvar_Get ("joy_forwardsensitivity", "-1", 0);
|
||||
joy_sidesensitivity = Cvar_Get ("joy_sidesensitivity", "-1", 0);
|
||||
joy_upsensitivity = Cvar_Get ("joy_upsensitivity", "-1", 0);
|
||||
joy_pitchsensitivity = Cvar_Get ("joy_pitchsensitivity", "1", 0);
|
||||
joy_yawsensitivity = Cvar_Get ("joy_yawsensitivity", "-1", 0);
|
||||
|
||||
// centering
|
||||
v_centermove = Cvar_Get ("v_centermove", "0.15", 0);
|
||||
v_centerspeed = Cvar_Get ("v_centerspeed", "500", 0);
|
||||
|
||||
Cmd_AddCommand ("+mlook", IN_MLookDown);
|
||||
Cmd_AddCommand ("-mlook", IN_MLookUp);
|
||||
|
||||
Cmd_AddCommand ("joy_advancedupdate", Joy_AdvancedUpdate_f);
|
||||
|
||||
IN_StartupMouse ();
|
||||
IN_StartupJoystick ();
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Shutdown
|
||||
===========
|
||||
*/
|
||||
void IN_Shutdown (void)
|
||||
{
|
||||
IN_DeactivateMouse ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Activate
|
||||
|
||||
Called when the main window gains or loses focus.
|
||||
The window may have been destroyed and recreated
|
||||
between a deactivate and an activate.
|
||||
===========
|
||||
*/
|
||||
void IN_Activate (qboolean active)
|
||||
{
|
||||
in_appactive = active;
|
||||
mouseactive = !active; // force a new window check or turn off
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_Frame
|
||||
|
||||
Called every frame, even if not generating commands
|
||||
==================
|
||||
*/
|
||||
void IN_Frame (void)
|
||||
{
|
||||
if (!mouseinitialized)
|
||||
return;
|
||||
|
||||
if (!in_mouse || !in_appactive)
|
||||
{
|
||||
IN_DeactivateMouse ();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !cl.refresh_prepped
|
||||
|| cls.key_dest == key_console
|
||||
|| cls.key_dest == key_menu)
|
||||
{
|
||||
// temporarily deactivate if in fullscreen
|
||||
if (Cvar_VariableValue ("vid_fullscreen") == 0)
|
||||
{
|
||||
IN_DeactivateMouse ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IN_ActivateMouse ();
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Move
|
||||
===========
|
||||
*/
|
||||
void IN_Move (usercmd_t *cmd)
|
||||
{
|
||||
IN_MouseMove (cmd);
|
||||
|
||||
if (ActiveApp)
|
||||
IN_JoyMove (cmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
IN_ClearStates
|
||||
===================
|
||||
*/
|
||||
void IN_ClearStates (void)
|
||||
{
|
||||
mx_accum = 0;
|
||||
my_accum = 0;
|
||||
mouse_oldbuttonstate = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
JOYSTICK
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============
|
||||
IN_StartupJoystick
|
||||
===============
|
||||
*/
|
||||
void IN_StartupJoystick (void)
|
||||
{
|
||||
int numdevs;
|
||||
JOYCAPS jc;
|
||||
MMRESULT mmr;
|
||||
cvar_t *cv;
|
||||
|
||||
// assume no joystick
|
||||
joy_avail = false;
|
||||
|
||||
// abort startup if user requests no joystick
|
||||
cv = Cvar_Get ("in_initjoy", "1", CVAR_NOSET);
|
||||
if ( !cv->value )
|
||||
return;
|
||||
|
||||
// verify joystick driver is present
|
||||
if ((numdevs = joyGetNumDevs ()) == 0)
|
||||
{
|
||||
// Com_Printf ("\njoystick not found -- driver not present\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// cycle through the joystick ids for the first valid one
|
||||
for (joy_id=0 ; joy_id<numdevs ; joy_id++)
|
||||
{
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = JOY_RETURNCENTERED;
|
||||
|
||||
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
|
||||
break;
|
||||
}
|
||||
|
||||
// abort startup if we didn't find a valid joystick
|
||||
if (mmr != JOYERR_NOERROR)
|
||||
{
|
||||
Com_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the capabilities of the selected joystick
|
||||
// abort startup if command fails
|
||||
memset (&jc, 0, sizeof(jc));
|
||||
if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
|
||||
{
|
||||
Com_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// save the joystick's number of buttons and POV status
|
||||
joy_numbuttons = jc.wNumButtons;
|
||||
joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
|
||||
|
||||
// old button and POV states default to no buttons pressed
|
||||
joy_oldbuttonstate = joy_oldpovstate = 0;
|
||||
|
||||
// mark the joystick as available and advanced initialization not completed
|
||||
// this is needed as cvars are not available during initialization
|
||||
|
||||
joy_avail = true;
|
||||
joy_advancedinit = false;
|
||||
|
||||
Com_Printf ("\njoystick detected\n\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
RawValuePointer
|
||||
===========
|
||||
*/
|
||||
PDWORD RawValuePointer (int axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case JOY_AXIS_X:
|
||||
return &ji.dwXpos;
|
||||
case JOY_AXIS_Y:
|
||||
return &ji.dwYpos;
|
||||
case JOY_AXIS_Z:
|
||||
return &ji.dwZpos;
|
||||
case JOY_AXIS_R:
|
||||
return &ji.dwRpos;
|
||||
case JOY_AXIS_U:
|
||||
return &ji.dwUpos;
|
||||
case JOY_AXIS_V:
|
||||
return &ji.dwVpos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_AdvancedUpdate_f
|
||||
===========
|
||||
*/
|
||||
void Joy_AdvancedUpdate_f (void)
|
||||
{
|
||||
|
||||
// called once by IN_ReadJoystick and by user whenever an update is needed
|
||||
// cvars are now available
|
||||
int i;
|
||||
DWORD dwTemp;
|
||||
|
||||
// initialize all the maps
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
dwAxisMap[i] = AxisNada;
|
||||
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
|
||||
pdwRawValue[i] = RawValuePointer(i);
|
||||
}
|
||||
|
||||
if( joy_advanced->value == 0.0)
|
||||
{
|
||||
// default joystick initialization
|
||||
// 2 axes only with joystick control
|
||||
dwAxisMap[JOY_AXIS_X] = AxisTurn;
|
||||
// dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
|
||||
dwAxisMap[JOY_AXIS_Y] = AxisForward;
|
||||
// dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp (joy_name->string, "joystick") != 0)
|
||||
{
|
||||
// notify user of advanced controller
|
||||
Com_Printf ("\n%s configured\n\n", joy_name->string);
|
||||
}
|
||||
|
||||
// advanced initialization here
|
||||
// data supplied by user via joy_axisn cvars
|
||||
dwTemp = (DWORD) joy_advaxisx->value;
|
||||
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisy->value;
|
||||
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisz->value;
|
||||
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisr->value;
|
||||
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisu->value;
|
||||
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisv->value;
|
||||
dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
}
|
||||
|
||||
// compute the axes to collect from DirectInput
|
||||
joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
if (dwAxisMap[i] != AxisNada)
|
||||
{
|
||||
joy_flags |= dwAxisFlags[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Commands
|
||||
===========
|
||||
*/
|
||||
void IN_Commands (void)
|
||||
{
|
||||
int i, key_index;
|
||||
DWORD buttonstate, povstate;
|
||||
|
||||
if (!joy_avail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// loop through the joystick buttons
|
||||
// key a joystick event or auxillary event for higher number buttons for each state change
|
||||
buttonstate = ji.dwButtons;
|
||||
for (i=0 ; i < joy_numbuttons ; i++)
|
||||
{
|
||||
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (key_index + i, true, 0);
|
||||
}
|
||||
|
||||
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (key_index + i, false, 0);
|
||||
}
|
||||
}
|
||||
joy_oldbuttonstate = buttonstate;
|
||||
|
||||
if (joy_haspov)
|
||||
{
|
||||
// convert POV information into 4 bits of state information
|
||||
// this avoids any potential problems related to moving from one
|
||||
// direction to another without going through the center position
|
||||
povstate = 0;
|
||||
if(ji.dwPOV != JOY_POVCENTERED)
|
||||
{
|
||||
if (ji.dwPOV == JOY_POVFORWARD)
|
||||
povstate |= 0x01;
|
||||
if (ji.dwPOV == JOY_POVRIGHT)
|
||||
povstate |= 0x02;
|
||||
if (ji.dwPOV == JOY_POVBACKWARD)
|
||||
povstate |= 0x04;
|
||||
if (ji.dwPOV == JOY_POVLEFT)
|
||||
povstate |= 0x08;
|
||||
}
|
||||
// determine which bits have changed and key an auxillary event for each change
|
||||
for (i=0 ; i < 4 ; i++)
|
||||
{
|
||||
if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_AUX29 + i, true, 0);
|
||||
}
|
||||
|
||||
if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_AUX29 + i, false, 0);
|
||||
}
|
||||
}
|
||||
joy_oldpovstate = povstate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
IN_ReadJoystick
|
||||
===============
|
||||
*/
|
||||
qboolean IN_ReadJoystick (void)
|
||||
{
|
||||
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = joy_flags;
|
||||
|
||||
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read error occurred
|
||||
// turning off the joystick seems too harsh for 1 read error,\
|
||||
// but what should be done?
|
||||
// Com_Printf ("IN_ReadJoystick: no response\n");
|
||||
// joy_avail = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_JoyMove
|
||||
===========
|
||||
*/
|
||||
void IN_JoyMove (usercmd_t *cmd)
|
||||
{
|
||||
float speed, aspeed;
|
||||
float fAxisValue;
|
||||
int i;
|
||||
|
||||
// complete initialization if first time in
|
||||
// this is needed as cvars are not available at initialization time
|
||||
if( joy_advancedinit != true )
|
||||
{
|
||||
Joy_AdvancedUpdate_f();
|
||||
joy_advancedinit = true;
|
||||
}
|
||||
|
||||
// verify joystick is available and that the user wants to use it
|
||||
if (!joy_avail || !in_joystick->value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// collect the joystick data, if possible
|
||||
if (IN_ReadJoystick () != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (in_speed.state & 1) ^ (int)cl_run->value)
|
||||
speed = 2;
|
||||
else
|
||||
speed = 1;
|
||||
aspeed = speed * cls.frametime;
|
||||
|
||||
// loop through the axes
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
// get the floating point zero-centered, potentially-inverted data for the current axis
|
||||
fAxisValue = (float) *pdwRawValue[i];
|
||||
// move centerpoint to zero
|
||||
fAxisValue -= 32768.0;
|
||||
|
||||
// convert range from -32768..32767 to -1..1
|
||||
fAxisValue /= 32768.0;
|
||||
|
||||
switch (dwAxisMap[i])
|
||||
{
|
||||
case AxisForward:
|
||||
if ((joy_advanced->value == 0.0) && mlooking)
|
||||
{
|
||||
// user wants forward control to become look control
|
||||
if (fabs(fAxisValue) > joy_pitchthreshold->value)
|
||||
{
|
||||
// if mouse invert is on, invert the joystick pitch value
|
||||
// only absolute control support here (joy_advanced is false)
|
||||
if (m_pitch->value < 0.0)
|
||||
{
|
||||
cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// user wants forward control to be forward control
|
||||
if (fabs(fAxisValue) > joy_forwardthreshold->value)
|
||||
{
|
||||
cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisSide:
|
||||
if (fabs(fAxisValue) > joy_sidethreshold->value)
|
||||
{
|
||||
cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisUp:
|
||||
if (fabs(fAxisValue) > joy_upthreshold->value)
|
||||
{
|
||||
cmd->upmove += (fAxisValue * joy_upsensitivity->value) * speed * cl_upspeed->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisTurn:
|
||||
if ((in_strafe.state & 1) || (lookstrafe->value && mlooking))
|
||||
{
|
||||
// user wants turn control to become side control
|
||||
if (fabs(fAxisValue) > joy_sidethreshold->value)
|
||||
{
|
||||
cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// user wants turn control to be turn control
|
||||
if (fabs(fAxisValue) > joy_yawthreshold->value)
|
||||
{
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisLook:
|
||||
if (mlooking)
|
||||
{
|
||||
if (fabs(fAxisValue) > joy_pitchthreshold->value)
|
||||
{
|
||||
// pitch movement detected and pitch movement desired by user
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
842
win32/net_wins.c
Normal file
842
win32/net_wins.c
Normal file
@ -0,0 +1,842 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// net_wins.c
|
||||
|
||||
#include "winsock.h"
|
||||
#include "wsipx.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
#define MAX_LOOPBACK 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte data[MAX_MSGLEN];
|
||||
int datalen;
|
||||
} loopmsg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
loopmsg_t msgs[MAX_LOOPBACK];
|
||||
int get, send;
|
||||
} loopback_t;
|
||||
|
||||
|
||||
cvar_t *net_shownet;
|
||||
static cvar_t *noudp;
|
||||
static cvar_t *noipx;
|
||||
|
||||
loopback_t loopbacks[2];
|
||||
int ip_sockets[2];
|
||||
int ipx_sockets[2];
|
||||
|
||||
char *NET_ErrorString (void);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void NetadrToSockadr (netadr_t *a, struct sockaddr *s)
|
||||
{
|
||||
memset (s, 0, sizeof(*s));
|
||||
|
||||
if (a->type == NA_BROADCAST)
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if (a->type == NA_IP)
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
}
|
||||
else if (a->type == NA_IPX)
|
||||
{
|
||||
((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
|
||||
memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4);
|
||||
memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6);
|
||||
((struct sockaddr_ipx *)s)->sa_socket = a->port;
|
||||
}
|
||||
else if (a->type == NA_BROADCAST_IPX)
|
||||
{
|
||||
((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
|
||||
memset(((struct sockaddr_ipx *)s)->sa_netnum, 0, 4);
|
||||
memset(((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6);
|
||||
((struct sockaddr_ipx *)s)->sa_socket = a->port;
|
||||
}
|
||||
}
|
||||
|
||||
void SockadrToNetadr (struct sockaddr *s, netadr_t *a)
|
||||
{
|
||||
if (s->sa_family == AF_INET)
|
||||
{
|
||||
a->type = NA_IP;
|
||||
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
else if (s->sa_family == AF_IPX)
|
||||
{
|
||||
a->type = NA_IPX;
|
||||
memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4);
|
||||
memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6);
|
||||
a->port = ((struct sockaddr_ipx *)s)->sa_socket;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
qboolean NET_CompareAdr (netadr_t a, netadr_t b)
|
||||
{
|
||||
if (a.type != b.type)
|
||||
return false;
|
||||
|
||||
if (a.type == NA_LOOPBACK)
|
||||
return TRUE;
|
||||
|
||||
if (a.type == NA_IP)
|
||||
{
|
||||
if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.type == NA_IPX)
|
||||
{
|
||||
if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
NET_CompareBaseAdr
|
||||
|
||||
Compares without the port
|
||||
===================
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
|
||||
{
|
||||
if (a.type != b.type)
|
||||
return false;
|
||||
|
||||
if (a.type == NA_LOOPBACK)
|
||||
return TRUE;
|
||||
|
||||
if (a.type == NA_IP)
|
||||
{
|
||||
if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.type == NA_IPX)
|
||||
{
|
||||
if ((memcmp(a.ipx, b.ipx, 10) == 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char *NET_AdrToString (netadr_t a)
|
||||
{
|
||||
static char s[64];
|
||||
|
||||
if (a.type == NA_LOOPBACK)
|
||||
Com_sprintf (s, sizeof(s), "loopback");
|
||||
else if (a.type == NA_IP)
|
||||
Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
|
||||
else
|
||||
Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], ntohs(a.port));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
NET_StringToAdr
|
||||
|
||||
localhost
|
||||
idnewt
|
||||
idnewt:28000
|
||||
192.246.40.70
|
||||
192.246.40.70:28000
|
||||
=============
|
||||
*/
|
||||
#define DO(src,dest) \
|
||||
copy[0] = s[src]; \
|
||||
copy[1] = s[src + 1]; \
|
||||
sscanf (copy, "%x", &val); \
|
||||
((struct sockaddr_ipx *)sadr)->dest = val
|
||||
|
||||
qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr)
|
||||
{
|
||||
struct hostent *h;
|
||||
char *colon;
|
||||
int val;
|
||||
char copy[128];
|
||||
|
||||
memset (sadr, 0, sizeof(*sadr));
|
||||
|
||||
if ((strlen(s) >= 23) && (s[8] == ':') && (s[21] == ':')) // check for an IPX address
|
||||
{
|
||||
((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX;
|
||||
copy[2] = 0;
|
||||
DO(0, sa_netnum[0]);
|
||||
DO(2, sa_netnum[1]);
|
||||
DO(4, sa_netnum[2]);
|
||||
DO(6, sa_netnum[3]);
|
||||
DO(9, sa_nodenum[0]);
|
||||
DO(11, sa_nodenum[1]);
|
||||
DO(13, sa_nodenum[2]);
|
||||
DO(15, sa_nodenum[3]);
|
||||
DO(17, sa_nodenum[4]);
|
||||
DO(19, sa_nodenum[5]);
|
||||
sscanf (&s[22], "%u", &val);
|
||||
((struct sockaddr_ipx *)sadr)->sa_socket = htons((unsigned short)val);
|
||||
}
|
||||
else
|
||||
{
|
||||
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
|
||||
|
||||
((struct sockaddr_in *)sadr)->sin_port = 0;
|
||||
|
||||
strcpy (copy, s);
|
||||
// strip off a trailing :port if present
|
||||
for (colon = copy ; *colon ; colon++)
|
||||
if (*colon == ':')
|
||||
{
|
||||
*colon = 0;
|
||||
((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
|
||||
}
|
||||
|
||||
if (copy[0] >= '0' && copy[0] <= '9')
|
||||
{
|
||||
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! (h = gethostbyname(copy)) )
|
||||
return 0;
|
||||
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef DO
|
||||
|
||||
/*
|
||||
=============
|
||||
NET_StringToAdr
|
||||
|
||||
localhost
|
||||
idnewt
|
||||
idnewt:28000
|
||||
192.246.40.70
|
||||
192.246.40.70:28000
|
||||
=============
|
||||
*/
|
||||
qboolean NET_StringToAdr (char *s, netadr_t *a)
|
||||
{
|
||||
struct sockaddr sadr;
|
||||
|
||||
if (!strcmp (s, "localhost"))
|
||||
{
|
||||
memset (a, 0, sizeof(*a));
|
||||
a->type = NA_LOOPBACK;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!NET_StringToSockaddr (s, &sadr))
|
||||
return false;
|
||||
|
||||
SockadrToNetadr (&sadr, a);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
qboolean NET_IsLocalAddress (netadr_t adr)
|
||||
{
|
||||
return adr.type == NA_LOOPBACK;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LOOPBACK BUFFERS FOR LOCAL PLAYER
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
|
||||
{
|
||||
int i;
|
||||
loopback_t *loop;
|
||||
|
||||
loop = &loopbacks[sock];
|
||||
|
||||
if (loop->send - loop->get > MAX_LOOPBACK)
|
||||
loop->get = loop->send - MAX_LOOPBACK;
|
||||
|
||||
if (loop->get >= loop->send)
|
||||
return false;
|
||||
|
||||
i = loop->get & (MAX_LOOPBACK-1);
|
||||
loop->get++;
|
||||
|
||||
memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
|
||||
net_message->cursize = loop->msgs[i].datalen;
|
||||
memset (net_from, 0, sizeof(*net_from));
|
||||
net_from->type = NA_LOOPBACK;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
|
||||
{
|
||||
int i;
|
||||
loopback_t *loop;
|
||||
|
||||
loop = &loopbacks[sock^1];
|
||||
|
||||
i = loop->send & (MAX_LOOPBACK-1);
|
||||
loop->send++;
|
||||
|
||||
memcpy (loop->msgs[i].data, data, length);
|
||||
loop->msgs[i].datalen = length;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
|
||||
{
|
||||
int ret;
|
||||
struct sockaddr from;
|
||||
int fromlen;
|
||||
int net_socket;
|
||||
int protocol;
|
||||
int err;
|
||||
|
||||
if (NET_GetLoopPacket (sock, net_from, net_message))
|
||||
return true;
|
||||
|
||||
for (protocol = 0 ; protocol < 2 ; protocol++)
|
||||
{
|
||||
if (protocol == 0)
|
||||
net_socket = ip_sockets[sock];
|
||||
else
|
||||
net_socket = ipx_sockets[sock];
|
||||
|
||||
if (!net_socket)
|
||||
continue;
|
||||
|
||||
fromlen = sizeof(from);
|
||||
ret = recvfrom (net_socket, net_message->data, net_message->maxsize
|
||||
, 0, (struct sockaddr *)&from, &fromlen);
|
||||
if (ret == -1)
|
||||
{
|
||||
err = WSAGetLastError();
|
||||
|
||||
if (err == WSAEWOULDBLOCK)
|
||||
continue;
|
||||
if (dedicated->value) // let dedicated servers continue after errors
|
||||
Com_Printf ("NET_GetPacket: %s", NET_ErrorString());
|
||||
else
|
||||
Com_Error (ERR_DROP, "NET_GetPacket: %s", NET_ErrorString());
|
||||
continue;
|
||||
}
|
||||
|
||||
SockadrToNetadr (&from, net_from);
|
||||
|
||||
if (ret == net_message->maxsize)
|
||||
{
|
||||
Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
|
||||
continue;
|
||||
}
|
||||
|
||||
net_message->cursize = ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
|
||||
{
|
||||
int ret;
|
||||
struct sockaddr addr;
|
||||
int net_socket;
|
||||
|
||||
if ( to.type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket (sock, length, data, to);
|
||||
return;
|
||||
}
|
||||
|
||||
if (to.type == NA_BROADCAST)
|
||||
{
|
||||
net_socket = ip_sockets[sock];
|
||||
if (!net_socket)
|
||||
return;
|
||||
}
|
||||
else if (to.type == NA_IP)
|
||||
{
|
||||
net_socket = ip_sockets[sock];
|
||||
if (!net_socket)
|
||||
return;
|
||||
}
|
||||
else if (to.type == NA_IPX)
|
||||
{
|
||||
net_socket = ipx_sockets[sock];
|
||||
if (!net_socket)
|
||||
return;
|
||||
}
|
||||
else if (to.type == NA_BROADCAST_IPX)
|
||||
{
|
||||
net_socket = ipx_sockets[sock];
|
||||
if (!net_socket)
|
||||
return;
|
||||
}
|
||||
else
|
||||
Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
|
||||
|
||||
NetadrToSockadr (&to, &addr);
|
||||
|
||||
ret = sendto (net_socket, data, length, 0, &addr, sizeof(addr) );
|
||||
if (ret == -1)
|
||||
{
|
||||
int err = WSAGetLastError();
|
||||
|
||||
// wouldblock is silent
|
||||
if (err == WSAEWOULDBLOCK)
|
||||
return;
|
||||
|
||||
// some PPP links dont allow broadcasts
|
||||
if ((err == WSAEADDRNOTAVAIL) && ((to.type == NA_BROADCAST) || (to.type == NA_BROADCAST_IPX)))
|
||||
return;
|
||||
|
||||
if (dedicated->value) // let dedicated servers continue after errors
|
||||
{
|
||||
Com_Printf ("NET_SendPacket ERROR: %s\n", NET_ErrorString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (err == WSAEADDRNOTAVAIL)
|
||||
{
|
||||
Com_DPrintf ("NET_SendPacket Warning: %s : %s\n", NET_ErrorString(), NET_AdrToString (to));
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Error (ERR_DROP, "NET_SendPacket ERROR: %s\n", NET_ErrorString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Socket
|
||||
====================
|
||||
*/
|
||||
int NET_IPSocket (char *net_interface, int port)
|
||||
{
|
||||
int newsocket;
|
||||
struct sockaddr_in address;
|
||||
qboolean _true = true;
|
||||
int i = 1;
|
||||
int err;
|
||||
|
||||
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
err = WSAGetLastError();
|
||||
if (err != WSAEAFNOSUPPORT)
|
||||
Com_Printf ("WARNING: UDP_OpenSocket: socket: %s", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it non-blocking
|
||||
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it broadcast capable
|
||||
if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
else
|
||||
NET_StringToSockaddr (net_interface, (struct sockaddr *)&address);
|
||||
|
||||
if (port == PORT_ANY)
|
||||
address.sin_port = 0;
|
||||
else
|
||||
address.sin_port = htons((short)port);
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
|
||||
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
|
||||
closesocket (newsocket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return newsocket;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_OpenIP
|
||||
====================
|
||||
*/
|
||||
void NET_OpenIP (void)
|
||||
{
|
||||
cvar_t *ip;
|
||||
int port;
|
||||
int dedicated;
|
||||
|
||||
ip = Cvar_Get ("ip", "localhost", CVAR_NOSET);
|
||||
|
||||
dedicated = Cvar_VariableValue ("dedicated");
|
||||
|
||||
if (!ip_sockets[NS_SERVER])
|
||||
{
|
||||
port = Cvar_Get("ip_hostport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("hostport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value;
|
||||
}
|
||||
}
|
||||
ip_sockets[NS_SERVER] = NET_IPSocket (ip->string, port);
|
||||
if (!ip_sockets[NS_SERVER] && dedicated)
|
||||
Com_Error (ERR_FATAL, "Couldn't allocate dedicated server IP port");
|
||||
}
|
||||
|
||||
|
||||
// dedicated servers don't need client ports
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
if (!ip_sockets[NS_CLIENT])
|
||||
{
|
||||
port = Cvar_Get("ip_clientport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
port = PORT_ANY;
|
||||
}
|
||||
ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, port);
|
||||
if (!ip_sockets[NS_CLIENT])
|
||||
ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, PORT_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
IPX_Socket
|
||||
====================
|
||||
*/
|
||||
int NET_IPXSocket (int port)
|
||||
{
|
||||
int newsocket;
|
||||
struct sockaddr_ipx address;
|
||||
int _true = 1;
|
||||
int err;
|
||||
|
||||
if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1)
|
||||
{
|
||||
err = WSAGetLastError();
|
||||
if (err != WSAEAFNOSUPPORT)
|
||||
Com_Printf ("WARNING: IPX_Socket: socket: %s\n", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it non-blocking
|
||||
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it broadcast capable
|
||||
if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
address.sa_family = AF_IPX;
|
||||
memset (address.sa_netnum, 0, 4);
|
||||
memset (address.sa_nodenum, 0, 6);
|
||||
if (port == PORT_ANY)
|
||||
address.sa_socket = 0;
|
||||
else
|
||||
address.sa_socket = htons((short)port);
|
||||
|
||||
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
|
||||
{
|
||||
Com_Printf ("WARNING: IPX_Socket: bind: %s\n", NET_ErrorString());
|
||||
closesocket (newsocket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return newsocket;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_OpenIPX
|
||||
====================
|
||||
*/
|
||||
void NET_OpenIPX (void)
|
||||
{
|
||||
int port;
|
||||
int dedicated;
|
||||
|
||||
dedicated = Cvar_VariableValue ("dedicated");
|
||||
|
||||
if (!ipx_sockets[NS_SERVER])
|
||||
{
|
||||
port = Cvar_Get("ipx_hostport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("hostport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_NOSET)->value;
|
||||
}
|
||||
}
|
||||
ipx_sockets[NS_SERVER] = NET_IPXSocket (port);
|
||||
}
|
||||
|
||||
// dedicated servers don't need client ports
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
if (!ipx_sockets[NS_CLIENT])
|
||||
{
|
||||
port = Cvar_Get("ipx_clientport", "0", CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
{
|
||||
port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_NOSET)->value;
|
||||
if (!port)
|
||||
port = PORT_ANY;
|
||||
}
|
||||
ipx_sockets[NS_CLIENT] = NET_IPXSocket (port);
|
||||
if (!ipx_sockets[NS_CLIENT])
|
||||
ipx_sockets[NS_CLIENT] = NET_IPXSocket (PORT_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Config
|
||||
|
||||
A single player game will only use the loopback code
|
||||
====================
|
||||
*/
|
||||
void NET_Config (qboolean multiplayer)
|
||||
{
|
||||
int i;
|
||||
static qboolean old_config;
|
||||
|
||||
if (old_config == multiplayer)
|
||||
return;
|
||||
|
||||
old_config = multiplayer;
|
||||
|
||||
if (!multiplayer)
|
||||
{ // shut down any existing sockets
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (ip_sockets[i])
|
||||
{
|
||||
closesocket (ip_sockets[i]);
|
||||
ip_sockets[i] = 0;
|
||||
}
|
||||
if (ipx_sockets[i])
|
||||
{
|
||||
closesocket (ipx_sockets[i]);
|
||||
ipx_sockets[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // open sockets
|
||||
if (! noudp->value)
|
||||
NET_OpenIP ();
|
||||
if (! noipx->value)
|
||||
NET_OpenIPX ();
|
||||
}
|
||||
}
|
||||
|
||||
// sleeps msec or until net socket is ready
|
||||
void NET_Sleep(int msec)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set fdset;
|
||||
extern cvar_t *dedicated;
|
||||
int i;
|
||||
|
||||
if (!dedicated || !dedicated->value)
|
||||
return; // we're not a server, just run full speed
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
i = 0;
|
||||
if (ip_sockets[NS_SERVER]) {
|
||||
FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
|
||||
i = ip_sockets[NS_SERVER];
|
||||
}
|
||||
if (ipx_sockets[NS_SERVER]) {
|
||||
FD_SET(ipx_sockets[NS_SERVER], &fdset); // network socket
|
||||
if (ipx_sockets[NS_SERVER] > i)
|
||||
i = ipx_sockets[NS_SERVER];
|
||||
}
|
||||
timeout.tv_sec = msec/1000;
|
||||
timeout.tv_usec = (msec%1000)*1000;
|
||||
select(i+1, &fdset, NULL, NULL, &timeout);
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
|
||||
static WSADATA winsockdata;
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Init
|
||||
====================
|
||||
*/
|
||||
void NET_Init (void)
|
||||
{
|
||||
WORD wVersionRequested;
|
||||
int r;
|
||||
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
|
||||
r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
|
||||
|
||||
if (r)
|
||||
Com_Error (ERR_FATAL,"Winsock initialization failed.");
|
||||
|
||||
Com_Printf("Winsock Initialized\n");
|
||||
|
||||
noudp = Cvar_Get ("noudp", "0", CVAR_NOSET);
|
||||
noipx = Cvar_Get ("noipx", "0", CVAR_NOSET);
|
||||
|
||||
net_shownet = Cvar_Get ("net_shownet", "0", 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Shutdown
|
||||
====================
|
||||
*/
|
||||
void NET_Shutdown (void)
|
||||
{
|
||||
NET_Config (false); // close sockets
|
||||
|
||||
WSACleanup ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_ErrorString
|
||||
====================
|
||||
*/
|
||||
char *NET_ErrorString (void)
|
||||
{
|
||||
int code;
|
||||
|
||||
code = WSAGetLastError ();
|
||||
switch (code)
|
||||
{
|
||||
case WSAEINTR: return "WSAEINTR";
|
||||
case WSAEBADF: return "WSAEBADF";
|
||||
case WSAEACCES: return "WSAEACCES";
|
||||
case WSAEDISCON: return "WSAEDISCON";
|
||||
case WSAEFAULT: return "WSAEFAULT";
|
||||
case WSAEINVAL: return "WSAEINVAL";
|
||||
case WSAEMFILE: return "WSAEMFILE";
|
||||
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
|
||||
case WSAEINPROGRESS: return "WSAEINPROGRESS";
|
||||
case WSAEALREADY: return "WSAEALREADY";
|
||||
case WSAENOTSOCK: return "WSAENOTSOCK";
|
||||
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
|
||||
case WSAEMSGSIZE: return "WSAEMSGSIZE";
|
||||
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
|
||||
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
|
||||
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
|
||||
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
|
||||
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
|
||||
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
|
||||
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
|
||||
case WSAEADDRINUSE: return "WSAEADDRINUSE";
|
||||
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
|
||||
case WSAENETDOWN: return "WSAENETDOWN";
|
||||
case WSAENETUNREACH: return "WSAENETUNREACH";
|
||||
case WSAENETRESET: return "WSAENETRESET";
|
||||
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
|
||||
case WSAECONNRESET: return "WSAECONNRESET";
|
||||
case WSAENOBUFS: return "WSAENOBUFS";
|
||||
case WSAEISCONN: return "WSAEISCONN";
|
||||
case WSAENOTCONN: return "WSAENOTCONN";
|
||||
case WSAESHUTDOWN: return "WSAESHUTDOWN";
|
||||
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
|
||||
case WSAETIMEDOUT: return "WSAETIMEDOUT";
|
||||
case WSAECONNREFUSED: return "WSAECONNREFUSED";
|
||||
case WSAELOOP: return "WSAELOOP";
|
||||
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
|
||||
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
|
||||
case WSASYSNOTREADY: return "WSASYSNOTREADY";
|
||||
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
|
||||
case WSANOTINITIALISED: return "WSANOTINITIALISED";
|
||||
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
|
||||
case WSATRY_AGAIN: return "WSATRY_AGAIN";
|
||||
case WSANO_RECOVERY: return "WSANO_RECOVERY";
|
||||
case WSANO_DATA: return "WSANO_DATA";
|
||||
default: return "NO ERROR";
|
||||
}
|
||||
}
|
BIN
win32/q2.aps
Normal file
BIN
win32/q2.aps
Normal file
Binary file not shown.
BIN
win32/q2.ico
Normal file
BIN
win32/q2.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 766 B |
72
win32/q2.rc
Normal file
72
win32/q2.rc
Normal file
@ -0,0 +1,72 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "q2.ico"
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
215
win32/q_shwin.c
Normal file
215
win32/q_shwin.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "winquake.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
|
||||
//===============================================================================
|
||||
|
||||
int hunkcount;
|
||||
|
||||
|
||||
byte *membase;
|
||||
int hunkmaxsize;
|
||||
int cursize;
|
||||
|
||||
#define VIRTUAL_ALLOC
|
||||
|
||||
void *Hunk_Begin (int maxsize)
|
||||
{
|
||||
// reserve a huge chunk of memory, but don't commit any yet
|
||||
cursize = 0;
|
||||
hunkmaxsize = maxsize;
|
||||
#ifdef VIRTUAL_ALLOC
|
||||
membase = VirtualAlloc (NULL, maxsize, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
membase = malloc (maxsize);
|
||||
memset (membase, 0, maxsize);
|
||||
#endif
|
||||
if (!membase)
|
||||
Sys_Error ("VirtualAlloc reserve failed");
|
||||
return (void *)membase;
|
||||
}
|
||||
|
||||
void *Hunk_Alloc (int size)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
// round to cacheline
|
||||
size = (size+31)&~31;
|
||||
|
||||
#ifdef VIRTUAL_ALLOC
|
||||
// commit pages as needed
|
||||
// buf = VirtualAlloc (membase+cursize, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
buf = VirtualAlloc (membase, cursize+size, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!buf)
|
||||
{
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, 0, NULL);
|
||||
Sys_Error ("VirtualAlloc commit failed.\n%s", buf);
|
||||
}
|
||||
#endif
|
||||
cursize += size;
|
||||
if (cursize > hunkmaxsize)
|
||||
Sys_Error ("Hunk_Alloc overflow");
|
||||
|
||||
return (void *)(membase+cursize-size);
|
||||
}
|
||||
|
||||
int Hunk_End (void)
|
||||
{
|
||||
|
||||
// free the remaining unused virtual memory
|
||||
#if 0
|
||||
void *buf;
|
||||
|
||||
// write protect it
|
||||
buf = VirtualAlloc (membase, cursize, MEM_COMMIT, PAGE_READONLY);
|
||||
if (!buf)
|
||||
Sys_Error ("VirtualAlloc commit failed");
|
||||
#endif
|
||||
|
||||
hunkcount++;
|
||||
//Com_Printf ("hunkcount: %i\n", hunkcount);
|
||||
return cursize;
|
||||
}
|
||||
|
||||
void Hunk_Free (void *base)
|
||||
{
|
||||
if ( base )
|
||||
#ifdef VIRTUAL_ALLOC
|
||||
VirtualFree (base, 0, MEM_RELEASE);
|
||||
#else
|
||||
free (base);
|
||||
#endif
|
||||
|
||||
hunkcount--;
|
||||
}
|
||||
|
||||
//===============================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
int curtime;
|
||||
int Sys_Milliseconds (void)
|
||||
{
|
||||
static int base;
|
||||
static qboolean initialized = false;
|
||||
|
||||
if (!initialized)
|
||||
{ // let base retain 16 bits of effectively random data
|
||||
base = timeGetTime() & 0xffff0000;
|
||||
initialized = true;
|
||||
}
|
||||
curtime = timeGetTime() - base;
|
||||
|
||||
return curtime;
|
||||
}
|
||||
|
||||
void Sys_Mkdir (char *path)
|
||||
{
|
||||
_mkdir (path);
|
||||
}
|
||||
|
||||
//============================================
|
||||
|
||||
char findbase[MAX_OSPATH];
|
||||
char findpath[MAX_OSPATH];
|
||||
int findhandle;
|
||||
|
||||
static qboolean CompareAttributes( unsigned found, unsigned musthave, unsigned canthave )
|
||||
{
|
||||
if ( ( found & _A_RDONLY ) && ( canthave & SFF_RDONLY ) )
|
||||
return false;
|
||||
if ( ( found & _A_HIDDEN ) && ( canthave & SFF_HIDDEN ) )
|
||||
return false;
|
||||
if ( ( found & _A_SYSTEM ) && ( canthave & SFF_SYSTEM ) )
|
||||
return false;
|
||||
if ( ( found & _A_SUBDIR ) && ( canthave & SFF_SUBDIR ) )
|
||||
return false;
|
||||
if ( ( found & _A_ARCH ) && ( canthave & SFF_ARCH ) )
|
||||
return false;
|
||||
|
||||
if ( ( musthave & SFF_RDONLY ) && !( found & _A_RDONLY ) )
|
||||
return false;
|
||||
if ( ( musthave & SFF_HIDDEN ) && !( found & _A_HIDDEN ) )
|
||||
return false;
|
||||
if ( ( musthave & SFF_SYSTEM ) && !( found & _A_SYSTEM ) )
|
||||
return false;
|
||||
if ( ( musthave & SFF_SUBDIR ) && !( found & _A_SUBDIR ) )
|
||||
return false;
|
||||
if ( ( musthave & SFF_ARCH ) && !( found & _A_ARCH ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave )
|
||||
{
|
||||
struct _finddata_t findinfo;
|
||||
|
||||
if (findhandle)
|
||||
Sys_Error ("Sys_BeginFind without close");
|
||||
findhandle = 0;
|
||||
|
||||
COM_FilePath (path, findbase);
|
||||
findhandle = _findfirst (path, &findinfo);
|
||||
if (findhandle == -1)
|
||||
return NULL;
|
||||
if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) )
|
||||
return NULL;
|
||||
Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name);
|
||||
return findpath;
|
||||
}
|
||||
|
||||
char *Sys_FindNext ( unsigned musthave, unsigned canthave )
|
||||
{
|
||||
struct _finddata_t findinfo;
|
||||
|
||||
if (findhandle == -1)
|
||||
return NULL;
|
||||
if (_findnext (findhandle, &findinfo) == -1)
|
||||
return NULL;
|
||||
if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) )
|
||||
return NULL;
|
||||
|
||||
Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name);
|
||||
return findpath;
|
||||
}
|
||||
|
||||
void Sys_FindClose (void)
|
||||
{
|
||||
if (findhandle != -1)
|
||||
_findclose (findhandle);
|
||||
findhandle = 0;
|
||||
}
|
||||
|
||||
|
||||
//============================================
|
||||
|
BIN
win32/qe3.ico
Normal file
BIN
win32/qe3.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 766 B |
4133
win32/qgl_win.c
Normal file
4133
win32/qgl_win.c
Normal file
File diff suppressed because it is too large
Load Diff
16
win32/resource.h
Normal file
16
win32/resource.h
Normal file
@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by q2.rc
|
||||
//
|
||||
#define IDI_ICON1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 103
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
556
win32/rw_ddraw.c
Normal file
556
win32/rw_ddraw.c
Normal file
@ -0,0 +1,556 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
** RW_DDRAW.C
|
||||
**
|
||||
** This handles DirecTDraw management under Windows.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
# error You should not be compiling this file on this platform
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "..\ref_soft\r_local.h"
|
||||
#define INITGUID
|
||||
#include "rw_win.h"
|
||||
|
||||
static const char *DDrawError( int code );
|
||||
|
||||
/*
|
||||
** DDRAW_Init
|
||||
**
|
||||
** Builds our DDRAW stuff
|
||||
*/
|
||||
qboolean DDRAW_Init( unsigned char **ppbuffer, int *ppitch )
|
||||
{
|
||||
HRESULT ddrval;
|
||||
DDSURFACEDESC ddsd;
|
||||
DDSCAPS ddscaps;
|
||||
PALETTEENTRY palentries[256];
|
||||
int i;
|
||||
extern cvar_t *sw_allow_modex;
|
||||
|
||||
HRESULT (WINAPI *QDirectDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR * lplpDDRAW, IUnknown FAR * pUnkOuter );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "Initializing DirectDraw\n");
|
||||
|
||||
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
palentries[i].peRed = ( d_8to24table[i] >> 0 ) & 0xff;
|
||||
palentries[i].peGreen = ( d_8to24table[i] >> 8 ) & 0xff;
|
||||
palentries[i].peBlue = ( d_8to24table[i] >> 16 ) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
** load DLL and fetch pointer to entry point
|
||||
*/
|
||||
if ( !sww_state.hinstDDRAW )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...loading DDRAW.DLL: ");
|
||||
if ( ( sww_state.hinstDDRAW = LoadLibrary( "ddraw.dll" ) ) == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
}
|
||||
|
||||
if ( ( QDirectDrawCreate = ( HRESULT (WINAPI *)( GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR * ) ) GetProcAddress( sww_state.hinstDDRAW, "DirectDrawCreate" ) ) == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "*** DirectDrawCreate == NULL ***\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** create the direct draw object
|
||||
*/
|
||||
ri.Con_Printf( PRINT_ALL, "...creating DirectDraw object: ");
|
||||
if ( ( ddrval = QDirectDrawCreate( NULL, &sww_state.lpDirectDraw, NULL ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
/*
|
||||
** see if linear modes exist first
|
||||
*/
|
||||
sww_state.modex = false;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...setting exclusive mode: ");
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw,
|
||||
sww_state.hWnd,
|
||||
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
/*
|
||||
** try changing the display mode normally
|
||||
*/
|
||||
ri.Con_Printf( PRINT_ALL, "...finding display mode\n" );
|
||||
ri.Con_Printf( PRINT_ALL, "...setting linear mode: " );
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetDisplayMode( sww_state.lpDirectDraw, vid.width, vid.height, 8 ) ) == DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
}
|
||||
/*
|
||||
** if no linear mode found, go for modex if we're trying 320x240
|
||||
*/
|
||||
else if ( ( sw_mode->value == 0 ) && sw_allow_modex->value )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed\n" );
|
||||
ri.Con_Printf( PRINT_ALL, "...attempting ModeX 320x240: ");
|
||||
|
||||
/*
|
||||
** reset to normal cooperative level
|
||||
*/
|
||||
sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw,
|
||||
sww_state.hWnd,
|
||||
DDSCL_NORMAL );
|
||||
|
||||
/*
|
||||
** set exclusive mode
|
||||
*/
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw,
|
||||
sww_state.hWnd,
|
||||
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES | DDSCL_ALLOWMODEX ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed SCL - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** change our display mode
|
||||
*/
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->SetDisplayMode( sww_state.lpDirectDraw, vid.width, vid.height, 8 ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed SDM - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
sww_state.modex = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** create our front buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...creating front buffer: ");
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreateSurface( sww_state.lpDirectDraw, &ddsd, &sww_state.lpddsFrontBuffer, NULL ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
/*
|
||||
** see if we're a ModeX mode
|
||||
*/
|
||||
sww_state.lpddsFrontBuffer->lpVtbl->GetCaps( sww_state.lpddsFrontBuffer, &ddscaps );
|
||||
if ( ddscaps.dwCaps & DDSCAPS_MODEX )
|
||||
ri.Con_Printf( PRINT_ALL, "...using ModeX\n" );
|
||||
|
||||
/*
|
||||
** create our back buffer
|
||||
*/
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...creating back buffer: " );
|
||||
if ( ( ddrval = sww_state.lpddsFrontBuffer->lpVtbl->GetAttachedSurface( sww_state.lpddsFrontBuffer, &ddsd.ddsCaps, &sww_state.lpddsBackBuffer ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
/*
|
||||
** create our rendering buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||||
ddsd.dwHeight = vid.height;
|
||||
ddsd.dwWidth = vid.width;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...creating offscreen buffer: " );
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreateSurface( sww_state.lpDirectDraw, &ddsd, &sww_state.lpddsOffScreenBuffer, NULL ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
/*
|
||||
** create our DIRECTDRAWPALETTE
|
||||
*/
|
||||
ri.Con_Printf( PRINT_ALL, "...creating palette: " );
|
||||
if ( ( ddrval = sww_state.lpDirectDraw->lpVtbl->CreatePalette( sww_state.lpDirectDraw,
|
||||
DDPCAPS_8BIT | DDPCAPS_ALLOW256,
|
||||
palentries,
|
||||
&sww_state.lpddpPalette,
|
||||
NULL ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...setting palette: " );
|
||||
if ( ( ddrval = sww_state.lpddsFrontBuffer->lpVtbl->SetPalette( sww_state.lpddsFrontBuffer,
|
||||
sww_state.lpddpPalette ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
DDRAW_SetPalette( ( const unsigned char * ) sw_state.currentpalette );
|
||||
|
||||
/*
|
||||
** lock the back buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, "...locking backbuffer: " );
|
||||
if ( ( ddrval = sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ) ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
ri.Con_Printf( PRINT_ALL, "ok\n" );
|
||||
|
||||
*ppbuffer = ddsd.lpSurface;
|
||||
*ppitch = ddsd.lPitch;
|
||||
|
||||
for ( i = 0; i < vid.height; i++ )
|
||||
{
|
||||
memset( *ppbuffer + i * *ppitch, 0, *ppitch );
|
||||
}
|
||||
|
||||
sww_state.palettized = true;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
ri.Con_Printf( PRINT_ALL, "*** DDraw init failure ***\n" );
|
||||
|
||||
DDRAW_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** DDRAW_SetPalette
|
||||
**
|
||||
** Sets the color table in our DIB section, and also sets the system palette
|
||||
** into an identity mode if we're running in an 8-bit palettized display mode.
|
||||
**
|
||||
** The palette is expected to be 1024 bytes, in the format:
|
||||
**
|
||||
** R = offset 0
|
||||
** G = offset 1
|
||||
** B = offset 2
|
||||
** A = offset 3
|
||||
*/
|
||||
void DDRAW_SetPalette( const unsigned char *pal )
|
||||
{
|
||||
PALETTEENTRY palentries[256];
|
||||
int i;
|
||||
|
||||
if (!sww_state.lpddpPalette)
|
||||
return;
|
||||
|
||||
for ( i = 0; i < 256; i++, pal += 4 )
|
||||
{
|
||||
palentries[i].peRed = pal[0];
|
||||
palentries[i].peGreen = pal[1];
|
||||
palentries[i].peBlue = pal[2];
|
||||
palentries[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
|
||||
}
|
||||
|
||||
if ( sww_state.lpddpPalette->lpVtbl->SetEntries( sww_state.lpddpPalette,
|
||||
0,
|
||||
0,
|
||||
256,
|
||||
palentries ) != DD_OK )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "DDRAW_SetPalette() - SetEntries failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** DDRAW_Shutdown
|
||||
*/
|
||||
void DDRAW_Shutdown( void )
|
||||
{
|
||||
if ( sww_state.lpddsOffScreenBuffer )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...releasing offscreen buffer\n");
|
||||
sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer );
|
||||
sww_state.lpddsOffScreenBuffer->lpVtbl->Release( sww_state.lpddsOffScreenBuffer );
|
||||
sww_state.lpddsOffScreenBuffer = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.lpddsBackBuffer )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...releasing back buffer\n");
|
||||
sww_state.lpddsBackBuffer->lpVtbl->Release( sww_state.lpddsBackBuffer );
|
||||
sww_state.lpddsBackBuffer = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.lpddsFrontBuffer )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...releasing front buffer\n");
|
||||
sww_state.lpddsFrontBuffer->lpVtbl->Release( sww_state.lpddsFrontBuffer );
|
||||
sww_state.lpddsFrontBuffer = NULL;
|
||||
}
|
||||
|
||||
if (sww_state.lpddpPalette)
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...releasing palette\n");
|
||||
sww_state.lpddpPalette->lpVtbl->Release ( sww_state.lpddpPalette );
|
||||
sww_state.lpddpPalette = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.lpDirectDraw )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...restoring display mode\n");
|
||||
sww_state.lpDirectDraw->lpVtbl->RestoreDisplayMode( sww_state.lpDirectDraw );
|
||||
ri.Con_Printf( PRINT_ALL, "...restoring normal coop mode\n");
|
||||
sww_state.lpDirectDraw->lpVtbl->SetCooperativeLevel( sww_state.lpDirectDraw, sww_state.hWnd, DDSCL_NORMAL );
|
||||
ri.Con_Printf( PRINT_ALL, "...releasing lpDirectDraw\n");
|
||||
sww_state.lpDirectDraw->lpVtbl->Release( sww_state.lpDirectDraw );
|
||||
sww_state.lpDirectDraw = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.hinstDDRAW )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...freeing library\n");
|
||||
FreeLibrary( sww_state.hinstDDRAW );
|
||||
sww_state.hinstDDRAW = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *DDrawError (int code)
|
||||
{
|
||||
switch(code) {
|
||||
case DD_OK:
|
||||
return "DD_OK";
|
||||
case DDERR_ALREADYINITIALIZED:
|
||||
return "DDERR_ALREADYINITIALIZED";
|
||||
case DDERR_BLTFASTCANTCLIP:
|
||||
return "DDERR_BLTFASTCANTCLIP";
|
||||
case DDERR_CANNOTATTACHSURFACE:
|
||||
return "DDER_CANNOTATTACHSURFACE";
|
||||
case DDERR_CANNOTDETACHSURFACE:
|
||||
return "DDERR_CANNOTDETACHSURFACE";
|
||||
case DDERR_CANTCREATEDC:
|
||||
return "DDERR_CANTCREATEDC";
|
||||
case DDERR_CANTDUPLICATE:
|
||||
return "DDER_CANTDUPLICATE";
|
||||
case DDERR_CLIPPERISUSINGHWND:
|
||||
return "DDER_CLIPPERUSINGHWND";
|
||||
case DDERR_COLORKEYNOTSET:
|
||||
return "DDERR_COLORKEYNOTSET";
|
||||
case DDERR_CURRENTLYNOTAVAIL:
|
||||
return "DDERR_CURRENTLYNOTAVAIL";
|
||||
case DDERR_DIRECTDRAWALREADYCREATED:
|
||||
return "DDERR_DIRECTDRAWALREADYCREATED";
|
||||
case DDERR_EXCEPTION:
|
||||
return "DDERR_EXCEPTION";
|
||||
case DDERR_EXCLUSIVEMODEALREADYSET:
|
||||
return "DDERR_EXCLUSIVEMODEALREADYSET";
|
||||
case DDERR_GENERIC:
|
||||
return "DDERR_GENERIC";
|
||||
case DDERR_HEIGHTALIGN:
|
||||
return "DDERR_HEIGHTALIGN";
|
||||
case DDERR_HWNDALREADYSET:
|
||||
return "DDERR_HWNDALREADYSET";
|
||||
case DDERR_HWNDSUBCLASSED:
|
||||
return "DDERR_HWNDSUBCLASSED";
|
||||
case DDERR_IMPLICITLYCREATED:
|
||||
return "DDERR_IMPLICITLYCREATED";
|
||||
case DDERR_INCOMPATIBLEPRIMARY:
|
||||
return "DDERR_INCOMPATIBLEPRIMARY";
|
||||
case DDERR_INVALIDCAPS:
|
||||
return "DDERR_INVALIDCAPS";
|
||||
case DDERR_INVALIDCLIPLIST:
|
||||
return "DDERR_INVALIDCLIPLIST";
|
||||
case DDERR_INVALIDDIRECTDRAWGUID:
|
||||
return "DDERR_INVALIDDIRECTDRAWGUID";
|
||||
case DDERR_INVALIDMODE:
|
||||
return "DDERR_INVALIDMODE";
|
||||
case DDERR_INVALIDOBJECT:
|
||||
return "DDERR_INVALIDOBJECT";
|
||||
case DDERR_INVALIDPARAMS:
|
||||
return "DDERR_INVALIDPARAMS";
|
||||
case DDERR_INVALIDPIXELFORMAT:
|
||||
return "DDERR_INVALIDPIXELFORMAT";
|
||||
case DDERR_INVALIDPOSITION:
|
||||
return "DDERR_INVALIDPOSITION";
|
||||
case DDERR_INVALIDRECT:
|
||||
return "DDERR_INVALIDRECT";
|
||||
case DDERR_LOCKEDSURFACES:
|
||||
return "DDERR_LOCKEDSURFACES";
|
||||
case DDERR_NO3D:
|
||||
return "DDERR_NO3D";
|
||||
case DDERR_NOALPHAHW:
|
||||
return "DDERR_NOALPHAHW";
|
||||
case DDERR_NOBLTHW:
|
||||
return "DDERR_NOBLTHW";
|
||||
case DDERR_NOCLIPLIST:
|
||||
return "DDERR_NOCLIPLIST";
|
||||
case DDERR_NOCLIPPERATTACHED:
|
||||
return "DDERR_NOCLIPPERATTACHED";
|
||||
case DDERR_NOCOLORCONVHW:
|
||||
return "DDERR_NOCOLORCONVHW";
|
||||
case DDERR_NOCOLORKEY:
|
||||
return "DDERR_NOCOLORKEY";
|
||||
case DDERR_NOCOLORKEYHW:
|
||||
return "DDERR_NOCOLORKEYHW";
|
||||
case DDERR_NOCOOPERATIVELEVELSET:
|
||||
return "DDERR_NOCOOPERATIVELEVELSET";
|
||||
case DDERR_NODC:
|
||||
return "DDERR_NODC";
|
||||
case DDERR_NODDROPSHW:
|
||||
return "DDERR_NODDROPSHW";
|
||||
case DDERR_NODIRECTDRAWHW:
|
||||
return "DDERR_NODIRECTDRAWHW";
|
||||
case DDERR_NOEMULATION:
|
||||
return "DDERR_NOEMULATION";
|
||||
case DDERR_NOEXCLUSIVEMODE:
|
||||
return "DDERR_NOEXCLUSIVEMODE";
|
||||
case DDERR_NOFLIPHW:
|
||||
return "DDERR_NOFLIPHW";
|
||||
case DDERR_NOGDI:
|
||||
return "DDERR_NOGDI";
|
||||
case DDERR_NOHWND:
|
||||
return "DDERR_NOHWND";
|
||||
case DDERR_NOMIRRORHW:
|
||||
return "DDERR_NOMIRRORHW";
|
||||
case DDERR_NOOVERLAYDEST:
|
||||
return "DDERR_NOOVERLAYDEST";
|
||||
case DDERR_NOOVERLAYHW:
|
||||
return "DDERR_NOOVERLAYHW";
|
||||
case DDERR_NOPALETTEATTACHED:
|
||||
return "DDERR_NOPALETTEATTACHED";
|
||||
case DDERR_NOPALETTEHW:
|
||||
return "DDERR_NOPALETTEHW";
|
||||
case DDERR_NORASTEROPHW:
|
||||
return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
|
||||
case DDERR_NOROTATIONHW:
|
||||
return "Operation could not be carried out because there is no rotation hardware present or available.\0";
|
||||
case DDERR_NOSTRETCHHW:
|
||||
return "Operation could not be carried out because there is no hardware support for stretching.\0";
|
||||
case DDERR_NOT4BITCOLOR:
|
||||
return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
|
||||
case DDERR_NOT4BITCOLORINDEX:
|
||||
return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
|
||||
case DDERR_NOT8BITCOLOR:
|
||||
return "DDERR_NOT8BITCOLOR";
|
||||
case DDERR_NOTAOVERLAYSURFACE:
|
||||
return "Returned when an overlay member is called for a non-overlay surface.\0";
|
||||
case DDERR_NOTEXTUREHW:
|
||||
return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
|
||||
case DDERR_NOTFLIPPABLE:
|
||||
return "DDERR_NOTFLIPPABLE";
|
||||
case DDERR_NOTFOUND:
|
||||
return "DDERR_NOTFOUND";
|
||||
case DDERR_NOTLOCKED:
|
||||
return "DDERR_NOTLOCKED";
|
||||
case DDERR_NOTPALETTIZED:
|
||||
return "DDERR_NOTPALETTIZED";
|
||||
case DDERR_NOVSYNCHW:
|
||||
return "DDERR_NOVSYNCHW";
|
||||
case DDERR_NOZBUFFERHW:
|
||||
return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
|
||||
case DDERR_NOZOVERLAYHW:
|
||||
return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
|
||||
case DDERR_OUTOFCAPS:
|
||||
return "The hardware needed for the requested operation has already been allocated.\0";
|
||||
case DDERR_OUTOFMEMORY:
|
||||
return "DDERR_OUTOFMEMORY";
|
||||
case DDERR_OUTOFVIDEOMEMORY:
|
||||
return "DDERR_OUTOFVIDEOMEMORY";
|
||||
case DDERR_OVERLAYCANTCLIP:
|
||||
return "The hardware does not support clipped overlays.\0";
|
||||
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
|
||||
return "Can only have ony color key active at one time for overlays.\0";
|
||||
case DDERR_OVERLAYNOTVISIBLE:
|
||||
return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
|
||||
case DDERR_PALETTEBUSY:
|
||||
return "DDERR_PALETTEBUSY";
|
||||
case DDERR_PRIMARYSURFACEALREADYEXISTS:
|
||||
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
|
||||
case DDERR_REGIONTOOSMALL:
|
||||
return "Region passed to Clipper::GetClipList is too small.\0";
|
||||
case DDERR_SURFACEALREADYATTACHED:
|
||||
return "DDERR_SURFACEALREADYATTACHED";
|
||||
case DDERR_SURFACEALREADYDEPENDENT:
|
||||
return "DDERR_SURFACEALREADYDEPENDENT";
|
||||
case DDERR_SURFACEBUSY:
|
||||
return "DDERR_SURFACEBUSY";
|
||||
case DDERR_SURFACEISOBSCURED:
|
||||
return "Access to surface refused because the surface is obscured.\0";
|
||||
case DDERR_SURFACELOST:
|
||||
return "DDERR_SURFACELOST";
|
||||
case DDERR_SURFACENOTATTACHED:
|
||||
return "DDERR_SURFACENOTATTACHED";
|
||||
case DDERR_TOOBIGHEIGHT:
|
||||
return "Height requested by DirectDraw is too large.\0";
|
||||
case DDERR_TOOBIGSIZE:
|
||||
return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
|
||||
case DDERR_TOOBIGWIDTH:
|
||||
return "Width requested by DirectDraw is too large.\0";
|
||||
case DDERR_UNSUPPORTED:
|
||||
return "DDERR_UNSUPPORTED";
|
||||
case DDERR_UNSUPPORTEDFORMAT:
|
||||
return "FOURCC format requested is unsupported by DirectDraw.\0";
|
||||
case DDERR_UNSUPPORTEDMASK:
|
||||
return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
|
||||
case DDERR_VERTICALBLANKINPROGRESS:
|
||||
return "Vertical blank is in progress.\0";
|
||||
case DDERR_WASSTILLDRAWING:
|
||||
return "DDERR_WASSTILLDRAWING";
|
||||
case DDERR_WRONGMODE:
|
||||
return "This surface can not be restored because it was created in a different mode.\0";
|
||||
case DDERR_XALIGN:
|
||||
return "Rectangle provided was not horizontally aligned on required boundary.\0";
|
||||
default:
|
||||
return "UNKNOWN\0";
|
||||
}
|
||||
}
|
||||
|
375
win32/rw_dib.c
Normal file
375
win32/rw_dib.c
Normal file
@ -0,0 +1,375 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
** RW_DIB.C
|
||||
**
|
||||
** This handles DIB section management under Windows.
|
||||
**
|
||||
*/
|
||||
#include "..\ref_soft\r_local.h"
|
||||
#include "rw_win.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
# error You should not be trying to compile this file on this platform
|
||||
#endif
|
||||
|
||||
static qboolean s_systemcolors_saved;
|
||||
|
||||
static HGDIOBJ previously_selected_GDI_obj;
|
||||
|
||||
static int s_syspalindices[] =
|
||||
{
|
||||
COLOR_ACTIVEBORDER,
|
||||
COLOR_ACTIVECAPTION,
|
||||
COLOR_APPWORKSPACE,
|
||||
COLOR_BACKGROUND,
|
||||
COLOR_BTNFACE,
|
||||
COLOR_BTNSHADOW,
|
||||
COLOR_BTNTEXT,
|
||||
COLOR_CAPTIONTEXT,
|
||||
COLOR_GRAYTEXT,
|
||||
COLOR_HIGHLIGHT,
|
||||
COLOR_HIGHLIGHTTEXT,
|
||||
COLOR_INACTIVEBORDER,
|
||||
|
||||
COLOR_INACTIVECAPTION,
|
||||
COLOR_MENU,
|
||||
COLOR_MENUTEXT,
|
||||
COLOR_SCROLLBAR,
|
||||
COLOR_WINDOW,
|
||||
COLOR_WINDOWFRAME,
|
||||
COLOR_WINDOWTEXT
|
||||
};
|
||||
|
||||
#define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) )
|
||||
|
||||
static int s_oldsyscolors[NUM_SYS_COLORS];
|
||||
|
||||
typedef struct dibinfo
|
||||
{
|
||||
BITMAPINFOHEADER header;
|
||||
RGBQUAD acolors[256];
|
||||
} dibinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD palVersion;
|
||||
WORD palNumEntries;
|
||||
PALETTEENTRY palEntries[256];
|
||||
} identitypalette_t;
|
||||
|
||||
static identitypalette_t s_ipal;
|
||||
|
||||
static void DIB_SaveSystemColors( void );
|
||||
static void DIB_RestoreSystemColors( void );
|
||||
|
||||
/*
|
||||
** DIB_Init
|
||||
**
|
||||
** Builds our DIB section
|
||||
*/
|
||||
qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch )
|
||||
{
|
||||
dibinfo_t dibheader;
|
||||
BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader;
|
||||
int i;
|
||||
|
||||
memset( &dibheader, 0, sizeof( dibheader ) );
|
||||
|
||||
/*
|
||||
** grab a DC
|
||||
*/
|
||||
if ( !sww_state.hDC )
|
||||
{
|
||||
if ( ( sww_state.hDC = GetDC( sww_state.hWnd ) ) == NULL )
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** figure out if we're running in an 8-bit display mode
|
||||
*/
|
||||
if ( GetDeviceCaps( sww_state.hDC, RASTERCAPS ) & RC_PALETTE )
|
||||
{
|
||||
sww_state.palettized = true;
|
||||
|
||||
// save system colors
|
||||
if ( !s_systemcolors_saved )
|
||||
{
|
||||
DIB_SaveSystemColors();
|
||||
s_systemcolors_saved = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sww_state.palettized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** fill in the BITMAPINFO struct
|
||||
*/
|
||||
pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmiDIB->bmiHeader.biWidth = vid.width;
|
||||
pbmiDIB->bmiHeader.biHeight = vid.height;
|
||||
pbmiDIB->bmiHeader.biPlanes = 1;
|
||||
pbmiDIB->bmiHeader.biBitCount = 8;
|
||||
pbmiDIB->bmiHeader.biCompression = BI_RGB;
|
||||
pbmiDIB->bmiHeader.biSizeImage = 0;
|
||||
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
|
||||
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
|
||||
pbmiDIB->bmiHeader.biClrUsed = 256;
|
||||
pbmiDIB->bmiHeader.biClrImportant = 256;
|
||||
|
||||
/*
|
||||
** fill in the palette
|
||||
*/
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
dibheader.acolors[i].rgbRed = ( d_8to24table[i] >> 0 ) & 0xff;
|
||||
dibheader.acolors[i].rgbGreen = ( d_8to24table[i] >> 8 ) & 0xff;
|
||||
dibheader.acolors[i].rgbBlue = ( d_8to24table[i] >> 16 ) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
** create the DIB section
|
||||
*/
|
||||
sww_state.hDIBSection = CreateDIBSection( sww_state.hDC,
|
||||
pbmiDIB,
|
||||
DIB_RGB_COLORS,
|
||||
&sww_state.pDIBBase,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if ( sww_state.hDIBSection == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( pbmiDIB->bmiHeader.biHeight > 0 )
|
||||
{
|
||||
// bottom up
|
||||
*ppbuffer = sww_state.pDIBBase + ( vid.height - 1 ) * vid.width;
|
||||
*ppitch = -vid.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
// top down
|
||||
*ppbuffer = sww_state.pDIBBase;
|
||||
*ppitch = vid.width;
|
||||
}
|
||||
|
||||
/*
|
||||
** clear the DIB memory buffer
|
||||
*/
|
||||
memset( sww_state.pDIBBase, 0xff, vid.width * vid.height );
|
||||
|
||||
if ( ( sww_state.hdcDIBSection = CreateCompatibleDC( sww_state.hDC ) ) == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
if ( ( previously_selected_GDI_obj = SelectObject( sww_state.hdcDIBSection, sww_state.hDIBSection ) ) == NULL )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "DIB_Init() - SelectObject failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
DIB_Shutdown();
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** DIB_SetPalette
|
||||
**
|
||||
** Sets the color table in our DIB section, and also sets the system palette
|
||||
** into an identity mode if we're running in an 8-bit palettized display mode.
|
||||
**
|
||||
** The palette is expected to be 1024 bytes, in the format:
|
||||
**
|
||||
** R = offset 0
|
||||
** G = offset 1
|
||||
** B = offset 2
|
||||
** A = offset 3
|
||||
*/
|
||||
void DIB_SetPalette( const unsigned char *_pal )
|
||||
{
|
||||
const unsigned char *pal = _pal;
|
||||
LOGPALETTE *pLogPal = ( LOGPALETTE * ) &s_ipal;
|
||||
RGBQUAD colors[256];
|
||||
int i;
|
||||
int ret;
|
||||
HDC hDC = sww_state.hDC;
|
||||
|
||||
/*
|
||||
** set the DIB color table
|
||||
*/
|
||||
if ( sww_state.hdcDIBSection )
|
||||
{
|
||||
for ( i = 0; i < 256; i++, pal += 4 )
|
||||
{
|
||||
colors[i].rgbRed = pal[0];
|
||||
colors[i].rgbGreen = pal[1];
|
||||
colors[i].rgbBlue = pal[2];
|
||||
colors[i].rgbReserved = 0;
|
||||
}
|
||||
|
||||
colors[0].rgbRed = 0;
|
||||
colors[0].rgbGreen = 0;
|
||||
colors[0].rgbBlue = 0;
|
||||
|
||||
colors[255].rgbRed = 0xff;
|
||||
colors[255].rgbGreen = 0xff;
|
||||
colors[255].rgbBlue = 0xff;
|
||||
|
||||
if ( SetDIBColorTable( sww_state.hdcDIBSection, 0, 256, colors ) == 0 )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "DIB_SetPalette() - SetDIBColorTable failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** for 8-bit color desktop modes we set up the palette for maximum
|
||||
** speed by going into an identity palette mode.
|
||||
*/
|
||||
if ( sww_state.palettized )
|
||||
{
|
||||
int i;
|
||||
HPALETTE hpalOld;
|
||||
|
||||
if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR )
|
||||
{
|
||||
ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
** destroy our old palette
|
||||
*/
|
||||
if ( sww_state.hPal )
|
||||
{
|
||||
DeleteObject( sww_state.hPal );
|
||||
sww_state.hPal = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** take up all physical palette entries to flush out anything that's currently
|
||||
** in the palette
|
||||
*/
|
||||
pLogPal->palVersion = 0x300;
|
||||
pLogPal->palNumEntries = 256;
|
||||
|
||||
for ( i = 0, pal = _pal; i < 256; i++, pal += 4 )
|
||||
{
|
||||
pLogPal->palPalEntry[i].peRed = pal[0];
|
||||
pLogPal->palPalEntry[i].peGreen = pal[1];
|
||||
pLogPal->palPalEntry[i].peBlue = pal[2];
|
||||
pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
|
||||
}
|
||||
pLogPal->palPalEntry[0].peRed = 0;
|
||||
pLogPal->palPalEntry[0].peGreen = 0;
|
||||
pLogPal->palPalEntry[0].peBlue = 0;
|
||||
pLogPal->palPalEntry[0].peFlags = 0;
|
||||
pLogPal->palPalEntry[255].peRed = 0xff;
|
||||
pLogPal->palPalEntry[255].peGreen = 0xff;
|
||||
pLogPal->palPalEntry[255].peBlue = 0xff;
|
||||
pLogPal->palPalEntry[255].peFlags = 0;
|
||||
|
||||
if ( ( sww_state.hPal = CreatePalette( pLogPal ) ) == NULL )
|
||||
{
|
||||
ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() );
|
||||
}
|
||||
|
||||
if ( ( hpalOld = SelectPalette( hDC, sww_state.hPal, FALSE ) ) == NULL )
|
||||
{
|
||||
ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() );
|
||||
}
|
||||
|
||||
if ( sww_state.hpalOld == NULL )
|
||||
sww_state.hpalOld = hpalOld;
|
||||
|
||||
if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries )
|
||||
{
|
||||
ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** DIB_Shutdown
|
||||
*/
|
||||
void DIB_Shutdown( void )
|
||||
{
|
||||
if ( sww_state.palettized && s_systemcolors_saved )
|
||||
DIB_RestoreSystemColors();
|
||||
|
||||
if ( sww_state.hPal )
|
||||
{
|
||||
DeleteObject( sww_state.hPal );
|
||||
sww_state.hPal = 0;
|
||||
}
|
||||
|
||||
if ( sww_state.hpalOld )
|
||||
{
|
||||
SelectPalette( sww_state.hDC, sww_state.hpalOld, FALSE );
|
||||
RealizePalette( sww_state.hDC );
|
||||
sww_state.hpalOld = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.hdcDIBSection )
|
||||
{
|
||||
SelectObject( sww_state.hdcDIBSection, previously_selected_GDI_obj );
|
||||
DeleteDC( sww_state.hdcDIBSection );
|
||||
sww_state.hdcDIBSection = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.hDIBSection )
|
||||
{
|
||||
DeleteObject( sww_state.hDIBSection );
|
||||
sww_state.hDIBSection = NULL;
|
||||
sww_state.pDIBBase = NULL;
|
||||
}
|
||||
|
||||
if ( sww_state.hDC )
|
||||
{
|
||||
ReleaseDC( sww_state.hWnd, sww_state.hDC );
|
||||
sww_state.hDC = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** DIB_Save/RestoreSystemColors
|
||||
*/
|
||||
static void DIB_RestoreSystemColors( void )
|
||||
{
|
||||
SetSystemPaletteUse( sww_state.hDC, SYSPAL_STATIC );
|
||||
SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors );
|
||||
}
|
||||
|
||||
static void DIB_SaveSystemColors( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < NUM_SYS_COLORS; i++ )
|
||||
s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] );
|
||||
}
|
471
win32/rw_imp.c
Normal file
471
win32/rw_imp.c
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
** RW_IMP.C
|
||||
**
|
||||
** This file contains ALL Win32 specific stuff having to do with the
|
||||
** software refresh. When a port is being made the following functions
|
||||
** must be implemented by the port:
|
||||
**
|
||||
** SWimp_EndFrame
|
||||
** SWimp_Init
|
||||
** SWimp_SetPalette
|
||||
** SWimp_Shutdown
|
||||
*/
|
||||
#include "..\ref_soft\r_local.h"
|
||||
#include "rw_win.h"
|
||||
#include "winquake.h"
|
||||
|
||||
// Console variables that we need to access from this module
|
||||
|
||||
swwstate_t sww_state;
|
||||
|
||||
/*
|
||||
** VID_CreateWindow
|
||||
*/
|
||||
#define WINDOW_CLASS_NAME "Quake 2"
|
||||
|
||||
void VID_CreateWindow( int width, int height, int stylebits )
|
||||
{
|
||||
WNDCLASS wc;
|
||||
RECT r;
|
||||
cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen;
|
||||
int x, y, w, h;
|
||||
int exstyle;
|
||||
|
||||
vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
|
||||
vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
|
||||
vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE );
|
||||
|
||||
if ( vid_fullscreen->value )
|
||||
exstyle = WS_EX_TOPMOST;
|
||||
else
|
||||
exstyle = 0;
|
||||
|
||||
/* Register the frame class */
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = (WNDPROC)sww_state.wndproc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = sww_state.hInstance;
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
||||
wc.hbrBackground = (void *)COLOR_GRAYTEXT;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = WINDOW_CLASS_NAME;
|
||||
|
||||
if (!RegisterClass (&wc) )
|
||||
ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = width;
|
||||
r.bottom = height;
|
||||
|
||||
AdjustWindowRect (&r, stylebits, FALSE);
|
||||
|
||||
w = r.right - r.left;
|
||||
h = r.bottom - r.top;
|
||||
x = vid_xpos->value;
|
||||
y = vid_ypos->value;
|
||||
|
||||
sww_state.hWnd = CreateWindowEx (
|
||||
exstyle,
|
||||
WINDOW_CLASS_NAME,
|
||||
"Quake 2",
|
||||
stylebits,
|
||||
x, y, w, h,
|
||||
NULL,
|
||||
NULL,
|
||||
sww_state.hInstance,
|
||||
NULL);
|
||||
|
||||
if (!sww_state.hWnd)
|
||||
ri.Sys_Error (ERR_FATAL, "Couldn't create window");
|
||||
|
||||
ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );
|
||||
UpdateWindow( sww_state.hWnd );
|
||||
SetForegroundWindow( sww_state.hWnd );
|
||||
SetFocus( sww_state.hWnd );
|
||||
|
||||
// let the sound and input subsystems know about the new window
|
||||
ri.Vid_NewWindow (width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_Init
|
||||
**
|
||||
** This routine is responsible for initializing the implementation
|
||||
** specific stuff in a software rendering subsystem.
|
||||
*/
|
||||
int SWimp_Init( void *hInstance, void *wndProc )
|
||||
{
|
||||
sww_state.hInstance = ( HINSTANCE ) hInstance;
|
||||
sww_state.wndproc = wndProc;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_InitGraphics
|
||||
**
|
||||
** This initializes the software refresh's implementation specific
|
||||
** graphics subsystem. In the case of Windows it creates DIB or
|
||||
** DDRAW surfaces.
|
||||
**
|
||||
** The necessary width and height parameters are grabbed from
|
||||
** vid.width and vid.height.
|
||||
*/
|
||||
static qboolean SWimp_InitGraphics( qboolean fullscreen )
|
||||
{
|
||||
// free resources in use
|
||||
SWimp_Shutdown ();
|
||||
|
||||
// create a new window
|
||||
VID_CreateWindow (vid.width, vid.height, WINDOW_STYLE);
|
||||
|
||||
// initialize the appropriate subsystem
|
||||
if ( !fullscreen )
|
||||
{
|
||||
if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) )
|
||||
{
|
||||
vid.buffer = 0;
|
||||
vid.rowbytes = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) )
|
||||
{
|
||||
vid.buffer = 0;
|
||||
vid.rowbytes = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_EndFrame
|
||||
**
|
||||
** This does an implementation specific copy from the backbuffer to the
|
||||
** front buffer. In the Win32 case it uses BitBlt or BltFast depending
|
||||
** on whether we're using DIB sections/GDI or DDRAW.
|
||||
*/
|
||||
void SWimp_EndFrame (void)
|
||||
{
|
||||
if ( !sw_state.fullscreen )
|
||||
{
|
||||
if ( sww_state.palettized )
|
||||
{
|
||||
// holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
|
||||
// RealizePalette(hdcScreen);
|
||||
}
|
||||
|
||||
|
||||
BitBlt( sww_state.hDC,
|
||||
0, 0,
|
||||
vid.width,
|
||||
vid.height,
|
||||
sww_state.hdcDIBSection,
|
||||
0, 0,
|
||||
SRCCOPY );
|
||||
|
||||
if ( sww_state.palettized )
|
||||
{
|
||||
// SelectPalette(hdcScreen, holdpal, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT r;
|
||||
HRESULT rval;
|
||||
DDSURFACEDESC ddsd;
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = vid.width;
|
||||
r.bottom = vid.height;
|
||||
|
||||
sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer );
|
||||
|
||||
if ( sww_state.modex )
|
||||
{
|
||||
if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
|
||||
0, 0,
|
||||
sww_state.lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsBackBuffer );
|
||||
sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
|
||||
0, 0,
|
||||
sww_state.lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT );
|
||||
}
|
||||
|
||||
if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer,
|
||||
NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
sww_state.lpddsFrontBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
|
||||
sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
|
||||
0, 0,
|
||||
sww_state.lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
|
||||
sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
|
||||
0, 0,
|
||||
sww_state.lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT );
|
||||
}
|
||||
}
|
||||
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
|
||||
sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL );
|
||||
|
||||
vid.buffer = ddsd.lpSurface;
|
||||
vid.rowbytes = ddsd.lPitch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_SetMode
|
||||
*/
|
||||
rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
|
||||
{
|
||||
const char *win_fs[] = { "W", "FS" };
|
||||
rserr_t retval = rserr_ok;
|
||||
|
||||
ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
|
||||
|
||||
if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
|
||||
return rserr_invalid_mode;
|
||||
}
|
||||
|
||||
ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
|
||||
|
||||
sww_state.initializing = true;
|
||||
if ( fullscreen )
|
||||
{
|
||||
if ( !SWimp_InitGraphics( 1 ) )
|
||||
{
|
||||
if ( SWimp_InitGraphics( 0 ) )
|
||||
{
|
||||
// mode is legal but not as fullscreen
|
||||
fullscreen = 0;
|
||||
retval = rserr_invalid_fullscreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to set a valid mode in windowed mode
|
||||
retval = rserr_unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// failure to set a valid mode in windowed mode
|
||||
if ( !SWimp_InitGraphics( fullscreen ) )
|
||||
{
|
||||
sww_state.initializing = true;
|
||||
return rserr_unknown;
|
||||
}
|
||||
}
|
||||
|
||||
sw_state.fullscreen = fullscreen;
|
||||
#if 0
|
||||
if ( retval != rserr_unknown )
|
||||
{
|
||||
if ( retval == rserr_invalid_fullscreen ||
|
||||
( retval == rserr_ok && !fullscreen ) )
|
||||
{
|
||||
SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
|
||||
sww_state.initializing = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_SetPalette
|
||||
**
|
||||
** System specific palette setting routine. A NULL palette means
|
||||
** to use the existing palette. The palette is expected to be in
|
||||
** a padded 4-byte xRGB format.
|
||||
*/
|
||||
void SWimp_SetPalette( const unsigned char *palette )
|
||||
{
|
||||
// MGL - what the fuck was kendall doing here?!
|
||||
// clear screen to black and change palette
|
||||
// for (i=0 ; i<vid.height ; i++)
|
||||
// memset (vid.buffer + i*vid.rowbytes, 0, vid.width);
|
||||
|
||||
if ( !palette )
|
||||
palette = ( const unsigned char * ) sw_state.currentpalette;
|
||||
|
||||
if ( !sw_state.fullscreen )
|
||||
{
|
||||
DIB_SetPalette( ( const unsigned char * ) palette );
|
||||
}
|
||||
else
|
||||
{
|
||||
DDRAW_SetPalette( ( const unsigned char * ) palette );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_Shutdown
|
||||
**
|
||||
** System specific graphics subsystem shutdown routine. Destroys
|
||||
** DIBs or DDRAW surfaces as appropriate.
|
||||
*/
|
||||
void SWimp_Shutdown( void )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" );
|
||||
DIB_Shutdown();
|
||||
DDRAW_Shutdown();
|
||||
|
||||
if ( sww_state.hWnd )
|
||||
{
|
||||
ri.Con_Printf( PRINT_ALL, "...destroying window\n" );
|
||||
ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); // prevents leaving empty slots in the taskbar
|
||||
DestroyWindow (sww_state.hWnd);
|
||||
sww_state.hWnd = NULL;
|
||||
UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SWimp_AppActivate
|
||||
*/
|
||||
void SWimp_AppActivate( qboolean active )
|
||||
{
|
||||
if ( active )
|
||||
{
|
||||
if ( sww_state.hWnd )
|
||||
{
|
||||
SetForegroundWindow( sww_state.hWnd );
|
||||
ShowWindow( sww_state.hWnd, SW_RESTORE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sww_state.hWnd )
|
||||
{
|
||||
if ( sww_state.initializing )
|
||||
return;
|
||||
if ( vid_fullscreen->value )
|
||||
ShowWindow( sww_state.hWnd, SW_MINIMIZE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_MakeCodeWriteable
|
||||
================
|
||||
*/
|
||||
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
|
||||
{
|
||||
DWORD flOldProtect;
|
||||
|
||||
if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
|
||||
ri.Sys_Error(ERR_FATAL, "Protection change failed\n");
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_SetFPCW
|
||||
**
|
||||
** For reference:
|
||||
**
|
||||
** 1
|
||||
** 5 0
|
||||
** xxxxRRPP.xxxxxxxx
|
||||
**
|
||||
** PP = 00 = 24-bit single precision
|
||||
** PP = 01 = reserved
|
||||
** PP = 10 = 53-bit double precision
|
||||
** PP = 11 = 64-bit extended precision
|
||||
**
|
||||
** RR = 00 = round to nearest
|
||||
** RR = 01 = round down (towards -inf, floor)
|
||||
** RR = 10 = round up (towards +inf, ceil)
|
||||
** RR = 11 = round to zero (truncate/towards 0)
|
||||
**
|
||||
*/
|
||||
#if !id386
|
||||
void Sys_SetFPCW (void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw;
|
||||
unsigned fpu_sp24_cw, fpu_sp24_ceil_cw;
|
||||
|
||||
void Sys_SetFPCW( void )
|
||||
{
|
||||
__asm xor eax, eax
|
||||
|
||||
__asm fnstcw word ptr fpu_cw
|
||||
__asm mov ax, word ptr fpu_cw
|
||||
|
||||
__asm and ah, 0f0h
|
||||
__asm or ah, 003h ; round to nearest mode, extended precision
|
||||
__asm mov fpu_full_cw, eax
|
||||
|
||||
__asm and ah, 0f0h
|
||||
__asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision
|
||||
__asm mov fpu_chop_cw, eax
|
||||
|
||||
__asm and ah, 0f0h
|
||||
__asm or ah, 00bh ; ceil mode, extended precision
|
||||
__asm mov fpu_ceil_cw, eax
|
||||
|
||||
__asm and ah, 0f0h ; round to nearest, 24-bit single precision
|
||||
__asm mov fpu_sp24_cw, eax
|
||||
|
||||
__asm and ah, 0f0h ; ceil mode, 24-bit single precision
|
||||
__asm or ah, 008h ;
|
||||
__asm mov fpu_sp24_ceil_cw, eax
|
||||
}
|
||||
#endif
|
||||
|
68
win32/rw_win.h
Normal file
68
win32/rw_win.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
#ifndef __RW_WIN_H__
|
||||
#define __RW_WIN_H__
|
||||
|
||||
#include <windows.h>
|
||||
#include <ddraw.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HINSTANCE hInstance;
|
||||
void *wndproc;
|
||||
HDC hDC; // global DC we're using
|
||||
HWND hWnd; // HWND of parent window
|
||||
|
||||
HDC hdcDIBSection; // DC compatible with DIB section
|
||||
HBITMAP hDIBSection; // DIB section
|
||||
unsigned char *pDIBBase; // DIB base pointer, NOT used directly for rendering!
|
||||
|
||||
HPALETTE hPal; // palette we're using
|
||||
HPALETTE hpalOld; // original system palette
|
||||
COLORREF oldsyscolors[20]; // original system colors
|
||||
|
||||
HINSTANCE hinstDDRAW; // library instance for DDRAW.DLL
|
||||
LPDIRECTDRAW lpDirectDraw; // pointer to DirectDraw object
|
||||
|
||||
LPDIRECTDRAWSURFACE lpddsFrontBuffer; // video card display memory front buffer
|
||||
LPDIRECTDRAWSURFACE lpddsBackBuffer; // system memory backbuffer
|
||||
LPDIRECTDRAWSURFACE lpddsOffScreenBuffer; // system memory backbuffer
|
||||
LPDIRECTDRAWPALETTE lpddpPalette; // DirectDraw palette
|
||||
|
||||
qboolean palettized; // true if desktop is paletted
|
||||
qboolean modex;
|
||||
|
||||
qboolean initializing;
|
||||
} swwstate_t;
|
||||
|
||||
extern swwstate_t sww_state;
|
||||
|
||||
/*
|
||||
** DIB code
|
||||
*/
|
||||
qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch );
|
||||
void DIB_Shutdown( void );
|
||||
void DIB_SetPalette( const unsigned char *palette );
|
||||
|
||||
qboolean DDRAW_Init( unsigned char **ppbuffer, int *ppitch );
|
||||
void DDRAW_Shutdown( void );
|
||||
void DDRAW_SetPalette( const unsigned char *palette );
|
||||
|
||||
#endif
|
861
win32/snd_win.c
Normal file
861
win32/snd_win.c
Normal file
@ -0,0 +1,861 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
#include <float.h>
|
||||
|
||||
#include "../client/client.h"
|
||||
#include "../client/snd_loc.h"
|
||||
#include "winquake.h"
|
||||
|
||||
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
|
||||
|
||||
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
|
||||
|
||||
// 64K is > 1 second at 16-bit, 22050 Hz
|
||||
#define WAV_BUFFERS 64
|
||||
#define WAV_MASK 0x3F
|
||||
#define WAV_BUFFER_SIZE 0x0400
|
||||
#define SECONDARY_BUFFER_SIZE 0x10000
|
||||
|
||||
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
|
||||
|
||||
cvar_t *s_wavonly;
|
||||
|
||||
static qboolean dsound_init;
|
||||
static qboolean wav_init;
|
||||
static qboolean snd_firsttime = true, snd_isdirect, snd_iswave;
|
||||
static qboolean primary_format_set;
|
||||
|
||||
// starts at 0 for disabled
|
||||
static int snd_buffer_count = 0;
|
||||
static int sample16;
|
||||
static int snd_sent, snd_completed;
|
||||
|
||||
/*
|
||||
* Global variables. Must be visible to window-procedure function
|
||||
* so it can unlock and free the data block after it has been played.
|
||||
*/
|
||||
|
||||
|
||||
HANDLE hData;
|
||||
HPSTR lpData, lpData2;
|
||||
|
||||
HGLOBAL hWaveHdr;
|
||||
LPWAVEHDR lpWaveHdr;
|
||||
|
||||
HWAVEOUT hWaveOut;
|
||||
|
||||
WAVEOUTCAPS wavecaps;
|
||||
|
||||
DWORD gSndBufSize;
|
||||
|
||||
MMTIME mmstarttime;
|
||||
|
||||
LPDIRECTSOUND pDS;
|
||||
LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
|
||||
|
||||
HINSTANCE hInstDS;
|
||||
|
||||
qboolean SNDDMA_InitDirect (void);
|
||||
qboolean SNDDMA_InitWav (void);
|
||||
|
||||
void FreeSound( void );
|
||||
|
||||
static const char *DSoundError( int error )
|
||||
{
|
||||
switch ( error )
|
||||
{
|
||||
case DSERR_BUFFERLOST:
|
||||
return "DSERR_BUFFERLOST";
|
||||
case DSERR_INVALIDCALL:
|
||||
return "DSERR_INVALIDCALLS";
|
||||
case DSERR_INVALIDPARAM:
|
||||
return "DSERR_INVALIDPARAM";
|
||||
case DSERR_PRIOLEVELNEEDED:
|
||||
return "DSERR_PRIOLEVELNEEDED";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
** DS_CreateBuffers
|
||||
*/
|
||||
static qboolean DS_CreateBuffers( void )
|
||||
{
|
||||
DSBUFFERDESC dsbuf;
|
||||
DSBCAPS dsbcaps;
|
||||
WAVEFORMATEX pformat, format;
|
||||
DWORD dwWrite;
|
||||
|
||||
memset (&format, 0, sizeof(format));
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.nChannels = dma.channels;
|
||||
format.wBitsPerSample = dma.samplebits;
|
||||
format.nSamplesPerSec = dma.speed;
|
||||
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
|
||||
format.cbSize = 0;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
|
||||
|
||||
Com_Printf( "Creating DS buffers\n" );
|
||||
|
||||
Com_DPrintf("...setting EXCLUSIVE coop level: " );
|
||||
if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_EXCLUSIVE ) )
|
||||
{
|
||||
Com_Printf ("failed\n");
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
Com_DPrintf("ok\n" );
|
||||
|
||||
// get access to the primary buffer, if possible, so we can set the
|
||||
// sound hardware format
|
||||
memset (&dsbuf, 0, sizeof(dsbuf));
|
||||
dsbuf.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||
dsbuf.dwBufferBytes = 0;
|
||||
dsbuf.lpwfxFormat = NULL;
|
||||
|
||||
memset(&dsbcaps, 0, sizeof(dsbcaps));
|
||||
dsbcaps.dwSize = sizeof(dsbcaps);
|
||||
primary_format_set = false;
|
||||
|
||||
Com_DPrintf( "...creating primary buffer: " );
|
||||
if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
|
||||
{
|
||||
pformat = format;
|
||||
|
||||
Com_DPrintf( "ok\n" );
|
||||
if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat))
|
||||
{
|
||||
if (snd_firsttime)
|
||||
Com_DPrintf ("...setting primary sound format: failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (snd_firsttime)
|
||||
Com_DPrintf ("...setting primary sound format: ok\n");
|
||||
|
||||
primary_format_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
Com_Printf( "failed\n" );
|
||||
|
||||
if ( !primary_format_set || !s_primary->value)
|
||||
{
|
||||
// create the secondary buffer we'll actually work with
|
||||
memset (&dsbuf, 0, sizeof(dsbuf));
|
||||
dsbuf.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
|
||||
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
|
||||
dsbuf.lpwfxFormat = &format;
|
||||
|
||||
memset(&dsbcaps, 0, sizeof(dsbcaps));
|
||||
dsbcaps.dwSize = sizeof(dsbcaps);
|
||||
|
||||
Com_DPrintf( "...creating secondary buffer: " );
|
||||
if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
|
||||
{
|
||||
Com_Printf( "failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
dma.channels = format.nChannels;
|
||||
dma.samplebits = format.wBitsPerSample;
|
||||
dma.speed = format.nSamplesPerSec;
|
||||
|
||||
if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps))
|
||||
{
|
||||
Com_Printf ("*** GetCaps failed ***\n");
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Com_Printf ("...using secondary sound buffer\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf( "...using primary buffer\n" );
|
||||
|
||||
Com_DPrintf( "...setting WRITEPRIMARY coop level: " );
|
||||
if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, cl_hwnd, DSSCL_WRITEPRIMARY))
|
||||
{
|
||||
Com_Printf( "failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps))
|
||||
{
|
||||
Com_Printf ("*** GetCaps failed ***\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
pDSBuf = pDSPBuf;
|
||||
}
|
||||
|
||||
// Make sure mixer is active
|
||||
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
if (snd_firsttime)
|
||||
Com_Printf(" %d channel(s)\n"
|
||||
" %d bits/sample\n"
|
||||
" %d bytes/sec\n",
|
||||
dma.channels, dma.samplebits, dma.speed);
|
||||
|
||||
gSndBufSize = dsbcaps.dwBufferBytes;
|
||||
|
||||
/* we don't want anyone to access the buffer directly w/o locking it first. */
|
||||
lpData = NULL;
|
||||
|
||||
pDSBuf->lpVtbl->Stop(pDSBuf);
|
||||
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
|
||||
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
dma.samples = gSndBufSize/(dma.samplebits/8);
|
||||
dma.samplepos = 0;
|
||||
dma.submission_chunk = 1;
|
||||
dma.buffer = (unsigned char *) lpData;
|
||||
sample16 = (dma.samplebits/8) - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** DS_DestroyBuffers
|
||||
*/
|
||||
static void DS_DestroyBuffers( void )
|
||||
{
|
||||
Com_DPrintf( "Destroying DS buffers\n" );
|
||||
if ( pDS )
|
||||
{
|
||||
Com_DPrintf( "...setting NORMAL coop level\n" );
|
||||
pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_NORMAL );
|
||||
}
|
||||
|
||||
if ( pDSBuf )
|
||||
{
|
||||
Com_DPrintf( "...stopping and releasing sound buffer\n" );
|
||||
pDSBuf->lpVtbl->Stop( pDSBuf );
|
||||
pDSBuf->lpVtbl->Release( pDSBuf );
|
||||
}
|
||||
|
||||
// only release primary buffer if it's not also the mixing buffer we just released
|
||||
if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
|
||||
{
|
||||
Com_DPrintf( "...releasing primary buffer\n" );
|
||||
pDSPBuf->lpVtbl->Release( pDSPBuf );
|
||||
}
|
||||
pDSBuf = NULL;
|
||||
pDSPBuf = NULL;
|
||||
|
||||
dma.buffer = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
FreeSound
|
||||
==================
|
||||
*/
|
||||
void FreeSound (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
Com_DPrintf( "Shutting down sound system\n" );
|
||||
|
||||
if ( pDS )
|
||||
DS_DestroyBuffers();
|
||||
|
||||
if ( hWaveOut )
|
||||
{
|
||||
Com_DPrintf( "...resetting waveOut\n" );
|
||||
waveOutReset (hWaveOut);
|
||||
|
||||
if (lpWaveHdr)
|
||||
{
|
||||
Com_DPrintf( "...unpreparing headers\n" );
|
||||
for (i=0 ; i< WAV_BUFFERS ; i++)
|
||||
waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
|
||||
}
|
||||
|
||||
Com_DPrintf( "...closing waveOut\n" );
|
||||
waveOutClose (hWaveOut);
|
||||
|
||||
if (hWaveHdr)
|
||||
{
|
||||
Com_DPrintf( "...freeing WAV header\n" );
|
||||
GlobalUnlock(hWaveHdr);
|
||||
GlobalFree(hWaveHdr);
|
||||
}
|
||||
|
||||
if (hData)
|
||||
{
|
||||
Com_DPrintf( "...freeing WAV buffer\n" );
|
||||
GlobalUnlock(hData);
|
||||
GlobalFree(hData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( pDS )
|
||||
{
|
||||
Com_DPrintf( "...releasing DS object\n" );
|
||||
pDS->lpVtbl->Release( pDS );
|
||||
}
|
||||
|
||||
if ( hInstDS )
|
||||
{
|
||||
Com_DPrintf( "...freeing DSOUND.DLL\n" );
|
||||
FreeLibrary( hInstDS );
|
||||
hInstDS = NULL;
|
||||
}
|
||||
|
||||
pDS = NULL;
|
||||
pDSBuf = NULL;
|
||||
pDSPBuf = NULL;
|
||||
hWaveOut = 0;
|
||||
hData = 0;
|
||||
hWaveHdr = 0;
|
||||
lpData = NULL;
|
||||
lpWaveHdr = NULL;
|
||||
dsound_init = false;
|
||||
wav_init = false;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_InitDirect
|
||||
|
||||
Direct-Sound support
|
||||
==================
|
||||
*/
|
||||
sndinitstat SNDDMA_InitDirect (void)
|
||||
{
|
||||
DSCAPS dscaps;
|
||||
HRESULT hresult;
|
||||
|
||||
dma.channels = 2;
|
||||
dma.samplebits = 16;
|
||||
|
||||
if (s_khz->value == 44)
|
||||
dma.speed = 44100;
|
||||
if (s_khz->value == 22)
|
||||
dma.speed = 22050;
|
||||
else
|
||||
dma.speed = 11025;
|
||||
|
||||
Com_Printf( "Initializing DirectSound\n");
|
||||
|
||||
if ( !hInstDS )
|
||||
{
|
||||
Com_DPrintf( "...loading dsound.dll: " );
|
||||
|
||||
hInstDS = LoadLibrary("dsound.dll");
|
||||
|
||||
if (hInstDS == NULL)
|
||||
{
|
||||
Com_Printf ("failed\n");
|
||||
return SIS_FAILURE;
|
||||
}
|
||||
|
||||
Com_DPrintf ("ok\n");
|
||||
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
|
||||
|
||||
if (!pDirectSoundCreate)
|
||||
{
|
||||
Com_Printf ("*** couldn't get DS proc addr ***\n");
|
||||
return SIS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
Com_DPrintf( "...creating DS object: " );
|
||||
while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK )
|
||||
{
|
||||
if (hresult != DSERR_ALLOCATED)
|
||||
{
|
||||
Com_Printf( "failed\n" );
|
||||
return SIS_FAILURE;
|
||||
}
|
||||
|
||||
if (MessageBox (NULL,
|
||||
"The sound hardware is in use by another app.\n\n"
|
||||
"Select Retry to try to start sound again or Cancel to run Quake with no sound.",
|
||||
"Sound not available",
|
||||
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
|
||||
{
|
||||
Com_Printf ("failed, hardware already in use\n" );
|
||||
return SIS_NOTAVAIL;
|
||||
}
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
dscaps.dwSize = sizeof(dscaps);
|
||||
|
||||
if ( DS_OK != pDS->lpVtbl->GetCaps( pDS, &dscaps ) )
|
||||
{
|
||||
Com_Printf ("*** couldn't get DS caps ***\n");
|
||||
}
|
||||
|
||||
if ( dscaps.dwFlags & DSCAPS_EMULDRIVER )
|
||||
{
|
||||
Com_DPrintf ("...no DSound driver found\n" );
|
||||
FreeSound();
|
||||
return SIS_FAILURE;
|
||||
}
|
||||
|
||||
if ( !DS_CreateBuffers() )
|
||||
return SIS_FAILURE;
|
||||
|
||||
dsound_init = true;
|
||||
|
||||
Com_DPrintf("...completed successfully\n" );
|
||||
|
||||
return SIS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDM_InitWav
|
||||
|
||||
Crappy windows multimedia base
|
||||
==================
|
||||
*/
|
||||
qboolean SNDDMA_InitWav (void)
|
||||
{
|
||||
WAVEFORMATEX format;
|
||||
int i;
|
||||
HRESULT hr;
|
||||
|
||||
Com_Printf( "Initializing wave sound\n" );
|
||||
|
||||
snd_sent = 0;
|
||||
snd_completed = 0;
|
||||
|
||||
dma.channels = 2;
|
||||
dma.samplebits = 16;
|
||||
|
||||
if (s_khz->value == 44)
|
||||
dma.speed = 44100;
|
||||
if (s_khz->value == 22)
|
||||
dma.speed = 22050;
|
||||
else
|
||||
dma.speed = 11025;
|
||||
|
||||
memset (&format, 0, sizeof(format));
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.nChannels = dma.channels;
|
||||
format.wBitsPerSample = dma.samplebits;
|
||||
format.nSamplesPerSec = dma.speed;
|
||||
format.nBlockAlign = format.nChannels
|
||||
*format.wBitsPerSample / 8;
|
||||
format.cbSize = 0;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec
|
||||
*format.nBlockAlign;
|
||||
|
||||
/* Open a waveform device for output using window callback. */
|
||||
Com_DPrintf ("...opening waveform device: ");
|
||||
while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
|
||||
&format,
|
||||
0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
if (hr != MMSYSERR_ALLOCATED)
|
||||
{
|
||||
Com_Printf ("failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MessageBox (NULL,
|
||||
"The sound hardware is in use by another app.\n\n"
|
||||
"Select Retry to try to start sound again or Cancel to run Quake 2 with no sound.",
|
||||
"Sound not available",
|
||||
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
|
||||
{
|
||||
Com_Printf ("hw in use\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
/*
|
||||
* Allocate and lock memory for the waveform data. The memory
|
||||
* for waveform data must be globally allocated with
|
||||
* GMEM_MOVEABLE and GMEM_SHARE flags.
|
||||
|
||||
*/
|
||||
Com_DPrintf ("...allocating waveform buffer: ");
|
||||
gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
|
||||
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
|
||||
if (!hData)
|
||||
{
|
||||
Com_Printf( " failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
Com_DPrintf ("...locking waveform buffer: ");
|
||||
lpData = GlobalLock(hData);
|
||||
if (!lpData)
|
||||
{
|
||||
Com_Printf( " failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
memset (lpData, 0, gSndBufSize);
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
/*
|
||||
* Allocate and lock memory for the header. This memory must
|
||||
* also be globally allocated with GMEM_MOVEABLE and
|
||||
* GMEM_SHARE flags.
|
||||
*/
|
||||
Com_DPrintf ("...allocating waveform header: ");
|
||||
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
|
||||
(DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
|
||||
|
||||
if (hWaveHdr == NULL)
|
||||
{
|
||||
Com_Printf( "failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
Com_DPrintf ("...locking waveform header: ");
|
||||
lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
|
||||
|
||||
if (lpWaveHdr == NULL)
|
||||
{
|
||||
Com_Printf( "failed\n" );
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
/* After allocation, set up and prepare headers. */
|
||||
Com_DPrintf ("...preparing headers: ");
|
||||
for (i=0 ; i<WAV_BUFFERS ; i++)
|
||||
{
|
||||
lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
|
||||
lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE;
|
||||
|
||||
if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) !=
|
||||
MMSYSERR_NOERROR)
|
||||
{
|
||||
Com_Printf ("failed\n");
|
||||
FreeSound ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Com_DPrintf ("ok\n");
|
||||
|
||||
dma.samples = gSndBufSize/(dma.samplebits/8);
|
||||
dma.samplepos = 0;
|
||||
dma.submission_chunk = 512;
|
||||
dma.buffer = (unsigned char *) lpData;
|
||||
sample16 = (dma.samplebits/8) - 1;
|
||||
|
||||
wav_init = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Init
|
||||
|
||||
Try to find a sound device to mix for.
|
||||
Returns false if nothing is found.
|
||||
==================
|
||||
*/
|
||||
int SNDDMA_Init(void)
|
||||
{
|
||||
sndinitstat stat;
|
||||
|
||||
memset ((void *)&dma, 0, sizeof (dma));
|
||||
|
||||
s_wavonly = Cvar_Get ("s_wavonly", "0", 0);
|
||||
|
||||
dsound_init = wav_init = 0;
|
||||
|
||||
stat = SIS_FAILURE; // assume DirectSound won't initialize
|
||||
|
||||
/* Init DirectSound */
|
||||
if (!s_wavonly->value)
|
||||
{
|
||||
if (snd_firsttime || snd_isdirect)
|
||||
{
|
||||
stat = SNDDMA_InitDirect ();
|
||||
|
||||
if (stat == SIS_SUCCESS)
|
||||
{
|
||||
snd_isdirect = true;
|
||||
|
||||
if (snd_firsttime)
|
||||
Com_Printf ("dsound init succeeded\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
snd_isdirect = false;
|
||||
Com_Printf ("*** dsound init failed ***\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if DirectSound didn't succeed in initializing, try to initialize
|
||||
// waveOut sound, unless DirectSound failed because the hardware is
|
||||
// already allocated (in which case the user has already chosen not
|
||||
// to have sound)
|
||||
if (!dsound_init && (stat != SIS_NOTAVAIL))
|
||||
{
|
||||
if (snd_firsttime || snd_iswave)
|
||||
{
|
||||
|
||||
snd_iswave = SNDDMA_InitWav ();
|
||||
|
||||
if (snd_iswave)
|
||||
{
|
||||
if (snd_firsttime)
|
||||
Com_Printf ("Wave sound init succeeded\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf ("Wave sound init failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snd_firsttime = false;
|
||||
|
||||
snd_buffer_count = 1;
|
||||
|
||||
if (!dsound_init && !wav_init)
|
||||
{
|
||||
if (snd_firsttime)
|
||||
Com_Printf ("*** No sound device initialized ***\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetDMAPos
|
||||
|
||||
return the current sample position (in mono samples read)
|
||||
inside the recirculating dma buffer, so the mixing code will know
|
||||
how many sample are required to fill it up.
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetDMAPos(void)
|
||||
{
|
||||
MMTIME mmtime;
|
||||
int s;
|
||||
DWORD dwWrite;
|
||||
|
||||
if (dsound_init)
|
||||
{
|
||||
mmtime.wType = TIME_SAMPLES;
|
||||
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
|
||||
s = mmtime.u.sample - mmstarttime.u.sample;
|
||||
}
|
||||
else if (wav_init)
|
||||
{
|
||||
s = snd_sent * WAV_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
s >>= sample16;
|
||||
|
||||
s &= (dma.samples-1);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_BeginPainting
|
||||
|
||||
Makes sure dma.buffer is valid
|
||||
===============
|
||||
*/
|
||||
DWORD locksize;
|
||||
void SNDDMA_BeginPainting (void)
|
||||
{
|
||||
int reps;
|
||||
DWORD dwSize2;
|
||||
DWORD *pbuf, *pbuf2;
|
||||
HRESULT hresult;
|
||||
DWORD dwStatus;
|
||||
|
||||
if (!pDSBuf)
|
||||
return;
|
||||
|
||||
// if the buffer was lost or stopped, restore it and/or restart it
|
||||
if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK)
|
||||
Com_Printf ("Couldn't get sound buffer status\n");
|
||||
|
||||
if (dwStatus & DSBSTATUS_BUFFERLOST)
|
||||
pDSBuf->lpVtbl->Restore (pDSBuf);
|
||||
|
||||
if (!(dwStatus & DSBSTATUS_PLAYING))
|
||||
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
// lock the dsound buffer
|
||||
|
||||
reps = 0;
|
||||
dma.buffer = NULL;
|
||||
|
||||
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize,
|
||||
&pbuf2, &dwSize2, 0)) != DS_OK)
|
||||
{
|
||||
if (hresult != DSERR_BUFFERLOST)
|
||||
{
|
||||
Com_Printf( "S_TransferStereo16: Lock failed with error '%s'\n", DSoundError( hresult ) );
|
||||
S_Shutdown ();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pDSBuf->lpVtbl->Restore( pDSBuf );
|
||||
}
|
||||
|
||||
if (++reps > 2)
|
||||
return;
|
||||
}
|
||||
dma.buffer = (unsigned char *)pbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
Also unlocks the dsound buffer
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Submit(void)
|
||||
{
|
||||
LPWAVEHDR h;
|
||||
int wResult;
|
||||
|
||||
if (!dma.buffer)
|
||||
return;
|
||||
|
||||
// unlock the dsound buffer
|
||||
if (pDSBuf)
|
||||
pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0);
|
||||
|
||||
if (!wav_init)
|
||||
return;
|
||||
|
||||
//
|
||||
// find which sound blocks have completed
|
||||
//
|
||||
while (1)
|
||||
{
|
||||
if ( snd_completed == snd_sent )
|
||||
{
|
||||
Com_DPrintf ("Sound overrun\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
snd_completed++; // this buffer has been played
|
||||
}
|
||||
|
||||
//Com_Printf ("completed %i\n", snd_completed);
|
||||
//
|
||||
// submit a few new sound blocks
|
||||
//
|
||||
while (((snd_sent - snd_completed) >> sample16) < 8)
|
||||
{
|
||||
h = lpWaveHdr + ( snd_sent&WAV_MASK );
|
||||
if (paintedtime/256 <= snd_sent)
|
||||
break; // Com_Printf ("submit overrun\n");
|
||||
//Com_Printf ("send %i\n", snd_sent);
|
||||
snd_sent++;
|
||||
/*
|
||||
* Now the data block can be sent to the output device. The
|
||||
* waveOutWrite function returns immediately and waveform
|
||||
* data is sent to the output device in the background.
|
||||
*/
|
||||
wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR));
|
||||
|
||||
if (wResult != MMSYSERR_NOERROR)
|
||||
{
|
||||
Com_Printf ("Failed to write block to device\n");
|
||||
FreeSound ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Shutdown
|
||||
|
||||
Reset the sound device for exiting
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Shutdown(void)
|
||||
{
|
||||
FreeSound ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
S_Activate
|
||||
|
||||
Called when the main window gains or loses focus.
|
||||
The window have been destroyed and recreated
|
||||
between a deactivate and an activate.
|
||||
===========
|
||||
*/
|
||||
void S_Activate (qboolean active)
|
||||
{
|
||||
if ( active )
|
||||
{
|
||||
if ( pDS && cl_hwnd && snd_isdirect )
|
||||
{
|
||||
DS_CreateBuffers();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pDS && cl_hwnd && snd_isdirect )
|
||||
{
|
||||
DS_DestroyBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
663
win32/sys_win.c
Normal file
663
win32/sys_win.c
Normal file
@ -0,0 +1,663 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// sys_win.h
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "winquake.h"
|
||||
#include "resource.h"
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#include "../win32/conproc.h"
|
||||
|
||||
#define MINIMUM_WIN_MEMORY 0x0a00000
|
||||
#define MAXIMUM_WIN_MEMORY 0x1000000
|
||||
|
||||
//#define DEMO
|
||||
|
||||
qboolean s_win95;
|
||||
|
||||
int starttime;
|
||||
int ActiveApp;
|
||||
qboolean 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];
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
SYSTEM IO
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
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 /* MB_OK */ );
|
||||
|
||||
if (qwclsemaphore)
|
||||
CloseHandle (qwclsemaphore);
|
||||
|
||||
// shut down QHOST hooks if necessary
|
||||
DeinitConProc ();
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void Sys_Quit (void)
|
||||
{
|
||||
timeEndPeriod( 1 );
|
||||
|
||||
CL_Shutdown();
|
||||
Qcommon_Shutdown ();
|
||||
CloseHandle (qwclsemaphore);
|
||||
if (dedicated && dedicated->value)
|
||||
FreeConsole ();
|
||||
|
||||
// shut down QHOST hooks if necessary
|
||||
DeinitConProc ();
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
void WinError (void)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Display the string.
|
||||
MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
|
||||
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
}
|
||||
|
||||
//================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ScanForCD
|
||||
|
||||
================
|
||||
*/
|
||||
char *Sys_ScanForCD (void)
|
||||
{
|
||||
static char cddir[MAX_OSPATH];
|
||||
static qboolean done;
|
||||
#ifndef DEMO
|
||||
char drive[4];
|
||||
FILE *f;
|
||||
char test[MAX_QPATH];
|
||||
|
||||
if (done) // don't re-check
|
||||
return cddir;
|
||||
|
||||
// no abort/retry/fail errors
|
||||
SetErrorMode (SEM_FAILCRITICALERRORS);
|
||||
|
||||
drive[0] = 'c';
|
||||
drive[1] = ':';
|
||||
drive[2] = '\\';
|
||||
drive[3] = 0;
|
||||
|
||||
done = true;
|
||||
|
||||
// scan the drives
|
||||
for (drive[0] = 'c' ; drive[0] <= 'z' ; drive[0]++)
|
||||
{
|
||||
// where activision put the stuff...
|
||||
sprintf (cddir, "%sinstall\\data", drive);
|
||||
sprintf (test, "%sinstall\\data\\quake2.exe", drive);
|
||||
f = fopen(test, "r");
|
||||
if (f)
|
||||
{
|
||||
fclose (f);
|
||||
if (GetDriveType (drive) == DRIVE_CDROM)
|
||||
return cddir;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cddir[0] = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_CopyProtect
|
||||
|
||||
================
|
||||
*/
|
||||
void Sys_CopyProtect (void)
|
||||
{
|
||||
#ifndef DEMO
|
||||
char *cddir;
|
||||
|
||||
cddir = Sys_ScanForCD();
|
||||
if (!cddir[0])
|
||||
Com_Error (ERR_FATAL, "You must have the Quake2 CD in the drive to play.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Init
|
||||
================
|
||||
*/
|
||||
void Sys_Init (void)
|
||||
{
|
||||
OSVERSIONINFO vinfo;
|
||||
|
||||
#if 0
|
||||
// allocate a named semaphore on the client so the
|
||||
// front end can tell if it is alive
|
||||
|
||||
// mutex will fail if semephore already exists
|
||||
qwclsemaphore = CreateMutex(
|
||||
NULL, /* Security attributes */
|
||||
0, /* owner */
|
||||
"qwcl"); /* Semaphore name */
|
||||
if (!qwclsemaphore)
|
||||
Sys_Error ("QWCL is already running on this system");
|
||||
CloseHandle (qwclsemaphore);
|
||||
|
||||
qwclsemaphore = CreateSemaphore(
|
||||
NULL, /* Security attributes */
|
||||
0, /* Initial count */
|
||||
1, /* Maximum count */
|
||||
"qwcl"); /* Semaphore name */
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
if (!AllocConsole ())
|
||||
Sys_Error ("Couldn't create dedicated server console");
|
||||
hinput = GetStdHandle (STD_INPUT_HANDLE);
|
||||
houtput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
|
||||
// let QHOST hook in
|
||||
InitConProc (argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char console_text[256];
|
||||
static int console_textlen;
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ConsoleInput
|
||||
================
|
||||
*/
|
||||
char *Sys_ConsoleInput (void)
|
||||
{
|
||||
INPUT_RECORD recs[1024];
|
||||
int dummy;
|
||||
int ch, numread, 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_ConsoleOutput
|
||||
|
||||
Print text to the dedicated console
|
||||
================
|
||||
*/
|
||||
void Sys_ConsoleOutput (char *string)
|
||||
{
|
||||
int 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_SendKeyEvents
|
||||
|
||||
Send Key_Event calls
|
||||
================
|
||||
*/
|
||||
void Sys_SendKeyEvents (void)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!GetMessage (&msg, NULL, 0, 0))
|
||||
Sys_Quit ();
|
||||
sys_msg_time = msg.time;
|
||||
TranslateMessage (&msg);
|
||||
DispatchMessage (&msg);
|
||||
}
|
||||
|
||||
// grab frame time
|
||||
sys_frame_time = timeGetTime(); // FIXME: should this be at start?
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetClipboardData
|
||||
|
||||
================
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
WINDOWS CRAP
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_AppActivate
|
||||
=================
|
||||
*/
|
||||
void Sys_AppActivate (void)
|
||||
{
|
||||
ShowWindow ( cl_hwnd, SW_RESTORE);
|
||||
SetForegroundWindow ( cl_hwnd );
|
||||
}
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
GAME DLL
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
static HINSTANCE game_library;
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_UnloadGame
|
||||
=================
|
||||
*/
|
||||
void Sys_UnloadGame (void)
|
||||
{
|
||||
if (!FreeLibrary (game_library))
|
||||
Com_Error (ERR_FATAL, "FreeLibrary failed for game library");
|
||||
game_library = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_GetGameAPI
|
||||
|
||||
Loads the game dll
|
||||
=================
|
||||
*/
|
||||
void *Sys_GetGameAPI (void *parms)
|
||||
{
|
||||
void *(*GetGameAPI) (void *);
|
||||
char name[MAX_OSPATH];
|
||||
char *path;
|
||||
char cwd[MAX_OSPATH];
|
||||
#if defined _M_IX86
|
||||
const char *gamename = "gamex86.dll";
|
||||
|
||||
#ifdef NDEBUG
|
||||
const char *debugdir = "release";
|
||||
#else
|
||||
const char *debugdir = "debug";
|
||||
#endif
|
||||
|
||||
#elif defined _M_ALPHA
|
||||
const char *gamename = "gameaxp.dll";
|
||||
|
||||
#ifdef NDEBUG
|
||||
const char *debugdir = "releaseaxp";
|
||||
#else
|
||||
const char *debugdir = "debugaxp";
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if (game_library)
|
||||
Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
|
||||
|
||||
// check the current debug directory first for development purposes
|
||||
_getcwd (cwd, sizeof(cwd));
|
||||
Com_sprintf (name, sizeof(name), "%s/%s/%s", cwd, debugdir, gamename);
|
||||
game_library = LoadLibrary ( name );
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check the current directory for other development purposes
|
||||
Com_sprintf (name, sizeof(name), "%s/%s", cwd, gamename);
|
||||
game_library = LoadLibrary ( name );
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// now run through the search paths
|
||||
path = NULL;
|
||||
while (1)
|
||||
{
|
||||
path = FS_NextPath (path);
|
||||
if (!path)
|
||||
return NULL; // couldn't find one anywhere
|
||||
Com_sprintf (name, sizeof(name), "%s/%s", path, gamename);
|
||||
game_library = LoadLibrary (name);
|
||||
if (game_library)
|
||||
{
|
||||
Com_DPrintf ("LoadLibrary (%s)\n",name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetGameAPI = (void *)GetProcAddress (game_library, "GetGameAPI");
|
||||
if (!GetGameAPI)
|
||||
{
|
||||
Sys_UnloadGame ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GetGameAPI (parms);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
ParseCommandLine
|
||||
|
||||
==================
|
||||
*/
|
||||
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++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
WinMain
|
||||
|
||||
==================
|
||||
*/
|
||||
HINSTANCE global_hInstance;
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
MSG msg;
|
||||
int time, oldtime, newtime;
|
||||
char *cddir;
|
||||
|
||||
/* previous instances do not exist in Win32 */
|
||||
if (hPrevInstance)
|
||||
return 0;
|
||||
|
||||
global_hInstance = hInstance;
|
||||
|
||||
ParseCommandLine (lpCmdLine);
|
||||
|
||||
// if we find the CD, add a +set cddir xxx command line
|
||||
cddir = Sys_ScanForCD ();
|
||||
if (cddir && argc < MAX_NUM_ARGVS - 3)
|
||||
{
|
||||
int i;
|
||||
|
||||
// don't override a cddir on the command line
|
||||
for (i=0 ; i<argc ; i++)
|
||||
if (!strcmp(argv[i], "cddir"))
|
||||
break;
|
||||
if (i == argc)
|
||||
{
|
||||
argv[argc++] = "+set";
|
||||
argv[argc++] = "cddir";
|
||||
argv[argc++] = cddir;
|
||||
}
|
||||
}
|
||||
|
||||
Qcommon_Init (argc, argv);
|
||||
oldtime = Sys_Milliseconds ();
|
||||
|
||||
/* main window message loop */
|
||||
while (1)
|
||||
{
|
||||
// if at a full screen console, don't update unless needed
|
||||
if (Minimized || (dedicated && dedicated->value) )
|
||||
{
|
||||
Sleep (1);
|
||||
}
|
||||
|
||||
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!GetMessage (&msg, NULL, 0, 0))
|
||||
Com_Quit ();
|
||||
sys_msg_time = msg.time;
|
||||
TranslateMessage (&msg);
|
||||
DispatchMessage (&msg);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
newtime = Sys_Milliseconds ();
|
||||
time = newtime - oldtime;
|
||||
} while (time < 1);
|
||||
// Con_Printf ("time:%5.2f - %5.2f = %5.2f\n", newtime, oldtime, time);
|
||||
|
||||
// _controlfp( ~( _EM_ZERODIVIDE /*| _EM_INVALID*/ ), _MCW_EM );
|
||||
_controlfp( _PC_24, _MCW_PC );
|
||||
Qcommon_Frame (time);
|
||||
|
||||
oldtime = newtime;
|
||||
}
|
||||
|
||||
// never gets here
|
||||
return TRUE;
|
||||
}
|
760
win32/vid_dll.c
Normal file
760
win32/vid_dll.c
Normal file
@ -0,0 +1,760 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// Main windowed and fullscreen graphics interface module. This module
|
||||
// is used for both the software and OpenGL rendering versions of the
|
||||
// Quake refresh engine.
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "..\client\client.h"
|
||||
#include "winquake.h"
|
||||
//#include "zmouse.h"
|
||||
|
||||
// Structure containing functions exported from refresh DLL
|
||||
refexport_t re;
|
||||
|
||||
cvar_t *win_noalttab;
|
||||
|
||||
#ifndef WM_MOUSEWHEEL
|
||||
#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS
|
||||
#endif
|
||||
|
||||
static UINT MSH_MOUSEWHEEL;
|
||||
|
||||
// Console variables that we need to access from this module
|
||||
cvar_t *vid_gamma;
|
||||
cvar_t *vid_ref; // Name of Refresh DLL loaded
|
||||
cvar_t *vid_xpos; // X coordinate of window position
|
||||
cvar_t *vid_ypos; // Y coordinate of window position
|
||||
cvar_t *vid_fullscreen;
|
||||
|
||||
// Global variables used internally by this module
|
||||
viddef_t viddef; // global video state; used by other modules
|
||||
HINSTANCE reflib_library; // Handle to refresh DLL
|
||||
qboolean reflib_active = 0;
|
||||
|
||||
HWND cl_hwnd; // Main window handle for life of program
|
||||
|
||||
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
|
||||
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
static qboolean s_alttab_disabled;
|
||||
|
||||
extern unsigned sys_msg_time;
|
||||
|
||||
/*
|
||||
** WIN32 helper functions
|
||||
*/
|
||||
extern qboolean s_win95;
|
||||
|
||||
static void WIN_DisableAltTab( void )
|
||||
{
|
||||
if ( s_alttab_disabled )
|
||||
return;
|
||||
|
||||
if ( s_win95 )
|
||||
{
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
|
||||
RegisterHotKey( 0, 1, MOD_ALT, VK_RETURN );
|
||||
}
|
||||
s_alttab_disabled = true;
|
||||
}
|
||||
|
||||
static void WIN_EnableAltTab( void )
|
||||
{
|
||||
if ( s_alttab_disabled )
|
||||
{
|
||||
if ( s_win95 )
|
||||
{
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
UnregisterHotKey( 0, 0 );
|
||||
UnregisterHotKey( 0, 1 );
|
||||
}
|
||||
|
||||
s_alttab_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================================================
|
||||
|
||||
DLL GLUE
|
||||
|
||||
==========================================================================
|
||||
*/
|
||||
|
||||
#define MAXPRINTMSG 4096
|
||||
void VID_Printf (int print_level, char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
static qboolean inupdate;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsprintf (msg,fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (print_level == PRINT_ALL)
|
||||
{
|
||||
Com_Printf ("%s", msg);
|
||||
}
|
||||
else if ( print_level == PRINT_DEVELOPER )
|
||||
{
|
||||
Com_DPrintf ("%s", msg);
|
||||
}
|
||||
else if ( print_level == PRINT_ALERT )
|
||||
{
|
||||
MessageBox( 0, msg, "PRINT_ALERT", MB_ICONWARNING );
|
||||
OutputDebugString( msg );
|
||||
}
|
||||
}
|
||||
|
||||
void VID_Error (int err_level, char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
static qboolean inupdate;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsprintf (msg,fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
Com_Error (err_level,"%s", msg);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
byte scantokey[128] =
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 8 9 A B C D E F
|
||||
0 , 27, '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
|
||||
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
'\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
|
||||
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
|
||||
K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
||||
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
|
||||
K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4
|
||||
K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11,
|
||||
K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
||||
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
|
||||
};
|
||||
|
||||
/*
|
||||
=======
|
||||
MapKey
|
||||
|
||||
Map from windows to quake keynums
|
||||
=======
|
||||
*/
|
||||
int MapKey (int key)
|
||||
{
|
||||
int result;
|
||||
int modified = ( key >> 16 ) & 255;
|
||||
qboolean is_extended = false;
|
||||
|
||||
if ( modified > 127)
|
||||
return 0;
|
||||
|
||||
if ( key & ( 1 << 24 ) )
|
||||
is_extended = true;
|
||||
|
||||
result = scantokey[modified];
|
||||
|
||||
if ( !is_extended )
|
||||
{
|
||||
switch ( result )
|
||||
{
|
||||
case K_HOME:
|
||||
return K_KP_HOME;
|
||||
case K_UPARROW:
|
||||
return K_KP_UPARROW;
|
||||
case K_PGUP:
|
||||
return K_KP_PGUP;
|
||||
case K_LEFTARROW:
|
||||
return K_KP_LEFTARROW;
|
||||
case K_RIGHTARROW:
|
||||
return K_KP_RIGHTARROW;
|
||||
case K_END:
|
||||
return K_KP_END;
|
||||
case K_DOWNARROW:
|
||||
return K_KP_DOWNARROW;
|
||||
case K_PGDN:
|
||||
return K_KP_PGDN;
|
||||
case K_INS:
|
||||
return K_KP_INS;
|
||||
case K_DEL:
|
||||
return K_KP_DEL;
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( result )
|
||||
{
|
||||
case 0x0D:
|
||||
return K_KP_ENTER;
|
||||
case 0x2F:
|
||||
return K_KP_SLASH;
|
||||
case 0xAF:
|
||||
return K_KP_PLUS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void AppActivate(BOOL fActive, BOOL minimize)
|
||||
{
|
||||
Minimized = minimize;
|
||||
|
||||
Key_ClearStates();
|
||||
|
||||
// we don't want to act like we're active if we're minimized
|
||||
if (fActive && !Minimized)
|
||||
ActiveApp = true;
|
||||
else
|
||||
ActiveApp = false;
|
||||
|
||||
// minimize/restore mouse-capture on demand
|
||||
if (!ActiveApp)
|
||||
{
|
||||
IN_Activate (false);
|
||||
CDAudio_Activate (false);
|
||||
S_Activate (false);
|
||||
|
||||
if ( win_noalttab->value )
|
||||
{
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_Activate (true);
|
||||
CDAudio_Activate (true);
|
||||
S_Activate (true);
|
||||
if ( win_noalttab->value )
|
||||
{
|
||||
WIN_DisableAltTab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
MainWndProc
|
||||
|
||||
main window procedure
|
||||
====================
|
||||
*/
|
||||
LONG WINAPI MainWndProc (
|
||||
HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
LONG lRet = 0;
|
||||
|
||||
if ( uMsg == MSH_MOUSEWHEEL )
|
||||
{
|
||||
if ( ( ( int ) wParam ) > 0 )
|
||||
{
|
||||
Key_Event( K_MWHEELUP, true, sys_msg_time );
|
||||
Key_Event( K_MWHEELUP, false, sys_msg_time );
|
||||
}
|
||||
else
|
||||
{
|
||||
Key_Event( K_MWHEELDOWN, true, sys_msg_time );
|
||||
Key_Event( K_MWHEELDOWN, false, sys_msg_time );
|
||||
}
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_MOUSEWHEEL:
|
||||
/*
|
||||
** this chunk of code theoretically only works under NT4 and Win98
|
||||
** since this message doesn't exist under Win95
|
||||
*/
|
||||
if ( ( short ) HIWORD( wParam ) > 0 )
|
||||
{
|
||||
Key_Event( K_MWHEELUP, true, sys_msg_time );
|
||||
Key_Event( K_MWHEELUP, false, sys_msg_time );
|
||||
}
|
||||
else
|
||||
{
|
||||
Key_Event( K_MWHEELDOWN, true, sys_msg_time );
|
||||
Key_Event( K_MWHEELDOWN, false, sys_msg_time );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HOTKEY:
|
||||
return 0;
|
||||
|
||||
case WM_CREATE:
|
||||
cl_hwnd = hWnd;
|
||||
|
||||
MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_PAINT:
|
||||
SCR_DirtyScreen (); // force entire screen to update next frame
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_DESTROY:
|
||||
// let sound and input know about this?
|
||||
cl_hwnd = NULL;
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
int fActive, fMinimized;
|
||||
|
||||
// KJB: Watch this for problems in fullscreen modes with Alt-tabbing.
|
||||
fActive = LOWORD(wParam);
|
||||
fMinimized = (BOOL) HIWORD(wParam);
|
||||
|
||||
AppActivate( fActive != WA_INACTIVE, fMinimized);
|
||||
|
||||
if ( reflib_active )
|
||||
re.AppActivate( !( fActive == WA_INACTIVE ) );
|
||||
}
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
|
||||
case WM_MOVE:
|
||||
{
|
||||
int xPos, yPos;
|
||||
RECT r;
|
||||
int style;
|
||||
|
||||
if (!vid_fullscreen->value)
|
||||
{
|
||||
xPos = (short) LOWORD(lParam); // horizontal position
|
||||
yPos = (short) HIWORD(lParam); // vertical position
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = 1;
|
||||
r.bottom = 1;
|
||||
|
||||
style = GetWindowLong( hWnd, GWL_STYLE );
|
||||
AdjustWindowRect( &r, style, FALSE );
|
||||
|
||||
Cvar_SetValue( "vid_xpos", xPos + r.left);
|
||||
Cvar_SetValue( "vid_ypos", yPos + r.top);
|
||||
vid_xpos->modified = false;
|
||||
vid_ypos->modified = false;
|
||||
if (ActiveApp)
|
||||
IN_Activate (true);
|
||||
}
|
||||
}
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
|
||||
// this is complicated because Win32 seems to pack multiple mouse events into
|
||||
// one update sometimes, so we always check all states and look for events
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
int temp;
|
||||
|
||||
temp = 0;
|
||||
|
||||
if (wParam & MK_LBUTTON)
|
||||
temp |= 1;
|
||||
|
||||
if (wParam & MK_RBUTTON)
|
||||
temp |= 2;
|
||||
|
||||
if (wParam & MK_MBUTTON)
|
||||
temp |= 4;
|
||||
|
||||
IN_MouseEvent (temp);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
if ( wParam == SC_SCREENSAVE )
|
||||
return 0;
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
case WM_SYSKEYDOWN:
|
||||
if ( wParam == 13 )
|
||||
{
|
||||
if ( vid_fullscreen )
|
||||
{
|
||||
Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// fall through
|
||||
case WM_KEYDOWN:
|
||||
Key_Event( MapKey( lParam ), true, sys_msg_time);
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP:
|
||||
Key_Event( MapKey( lParam ), false, sys_msg_time);
|
||||
break;
|
||||
|
||||
case MM_MCINOTIFY:
|
||||
{
|
||||
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
default: // pass all unhandled messages to DefWindowProc
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
/* return 0 if handled message, 1 if not */
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
VID_Restart_f
|
||||
|
||||
Console command to re-start the video mode and refresh DLL. We do this
|
||||
simply by setting the modified flag for the vid_ref variable, which will
|
||||
cause the entire video mode and refresh DLL to be reset on the next frame.
|
||||
============
|
||||
*/
|
||||
void VID_Restart_f (void)
|
||||
{
|
||||
vid_ref->modified = true;
|
||||
}
|
||||
|
||||
void VID_Front_f( void )
|
||||
{
|
||||
SetWindowLong( cl_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST );
|
||||
SetForegroundWindow( cl_hwnd );
|
||||
}
|
||||
|
||||
/*
|
||||
** VID_GetModeInfo
|
||||
*/
|
||||
typedef struct vidmode_s
|
||||
{
|
||||
const char *description;
|
||||
int width, height;
|
||||
int mode;
|
||||
} vidmode_t;
|
||||
|
||||
vidmode_t vid_modes[] =
|
||||
{
|
||||
{ "Mode 0: 320x240", 320, 240, 0 },
|
||||
{ "Mode 1: 400x300", 400, 300, 1 },
|
||||
{ "Mode 2: 512x384", 512, 384, 2 },
|
||||
{ "Mode 3: 640x480", 640, 480, 3 },
|
||||
{ "Mode 4: 800x600", 800, 600, 4 },
|
||||
{ "Mode 5: 960x720", 960, 720, 5 },
|
||||
{ "Mode 6: 1024x768", 1024, 768, 6 },
|
||||
{ "Mode 7: 1152x864", 1152, 864, 7 },
|
||||
{ "Mode 8: 1280x960", 1280, 960, 8 },
|
||||
{ "Mode 9: 1600x1200", 1600, 1200, 9 }
|
||||
};
|
||||
|
||||
qboolean VID_GetModeInfo( int *width, int *height, int mode )
|
||||
{
|
||||
if ( mode < 0 || mode >= VID_NUM_MODES )
|
||||
return false;
|
||||
|
||||
*width = vid_modes[mode].width;
|
||||
*height = vid_modes[mode].height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
** VID_UpdateWindowPosAndSize
|
||||
*/
|
||||
void VID_UpdateWindowPosAndSize( int x, int y )
|
||||
{
|
||||
RECT r;
|
||||
int style;
|
||||
int w, h;
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = viddef.width;
|
||||
r.bottom = viddef.height;
|
||||
|
||||
style = GetWindowLong( cl_hwnd, GWL_STYLE );
|
||||
AdjustWindowRect( &r, style, FALSE );
|
||||
|
||||
w = r.right - r.left;
|
||||
h = r.bottom - r.top;
|
||||
|
||||
MoveWindow( cl_hwnd, vid_xpos->value, vid_ypos->value, w, h, TRUE );
|
||||
}
|
||||
|
||||
/*
|
||||
** VID_NewWindow
|
||||
*/
|
||||
void VID_NewWindow ( int width, int height)
|
||||
{
|
||||
viddef.width = width;
|
||||
viddef.height = height;
|
||||
|
||||
cl.force_refdef = true; // can't use a paused refdef
|
||||
}
|
||||
|
||||
void VID_FreeReflib (void)
|
||||
{
|
||||
if ( !FreeLibrary( reflib_library ) )
|
||||
Com_Error( ERR_FATAL, "Reflib FreeLibrary failed" );
|
||||
memset (&re, 0, sizeof(re));
|
||||
reflib_library = NULL;
|
||||
reflib_active = false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
VID_LoadRefresh
|
||||
==============
|
||||
*/
|
||||
qboolean VID_LoadRefresh( char *name )
|
||||
{
|
||||
refimport_t ri;
|
||||
GetRefAPI_t GetRefAPI;
|
||||
|
||||
if ( reflib_active )
|
||||
{
|
||||
re.Shutdown();
|
||||
VID_FreeReflib ();
|
||||
}
|
||||
|
||||
Com_Printf( "------- Loading %s -------\n", name );
|
||||
|
||||
if ( ( reflib_library = LoadLibrary( name ) ) == 0 )
|
||||
{
|
||||
Com_Printf( "LoadLibrary(\"%s\") failed\n", name );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ri.Cmd_AddCommand = Cmd_AddCommand;
|
||||
ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
|
||||
ri.Cmd_Argc = Cmd_Argc;
|
||||
ri.Cmd_Argv = Cmd_Argv;
|
||||
ri.Cmd_ExecuteText = Cbuf_ExecuteText;
|
||||
ri.Con_Printf = VID_Printf;
|
||||
ri.Sys_Error = VID_Error;
|
||||
ri.FS_LoadFile = FS_LoadFile;
|
||||
ri.FS_FreeFile = FS_FreeFile;
|
||||
ri.FS_Gamedir = FS_Gamedir;
|
||||
ri.Cvar_Get = Cvar_Get;
|
||||
ri.Cvar_Set = Cvar_Set;
|
||||
ri.Cvar_SetValue = Cvar_SetValue;
|
||||
ri.Vid_GetModeInfo = VID_GetModeInfo;
|
||||
ri.Vid_MenuInit = VID_MenuInit;
|
||||
ri.Vid_NewWindow = VID_NewWindow;
|
||||
|
||||
if ( ( GetRefAPI = (void *) GetProcAddress( reflib_library, "GetRefAPI" ) ) == 0 )
|
||||
Com_Error( ERR_FATAL, "GetProcAddress failed on %s", name );
|
||||
|
||||
re = GetRefAPI( ri );
|
||||
|
||||
if (re.api_version != API_VERSION)
|
||||
{
|
||||
VID_FreeReflib ();
|
||||
Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
|
||||
}
|
||||
|
||||
if ( re.Init( global_hInstance, MainWndProc ) == -1 )
|
||||
{
|
||||
re.Shutdown();
|
||||
VID_FreeReflib ();
|
||||
return false;
|
||||
}
|
||||
|
||||
Com_Printf( "------------------------------------\n");
|
||||
reflib_active = true;
|
||||
|
||||
//======
|
||||
//PGM
|
||||
vidref_val = VIDREF_OTHER;
|
||||
if(vid_ref)
|
||||
{
|
||||
if(!strcmp (vid_ref->string, "gl"))
|
||||
vidref_val = VIDREF_GL;
|
||||
else if(!strcmp(vid_ref->string, "soft"))
|
||||
vidref_val = VIDREF_SOFT;
|
||||
}
|
||||
//PGM
|
||||
//======
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
VID_CheckChanges
|
||||
|
||||
This function gets called once just before drawing each frame, and it's sole purpose in life
|
||||
is to check to see if any of the video mode parameters have changed, and if they have to
|
||||
update the rendering DLL and/or video mode to match.
|
||||
============
|
||||
*/
|
||||
void VID_CheckChanges (void)
|
||||
{
|
||||
char name[100];
|
||||
|
||||
if ( win_noalttab->modified )
|
||||
{
|
||||
if ( win_noalttab->value )
|
||||
{
|
||||
WIN_DisableAltTab();
|
||||
}
|
||||
else
|
||||
{
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
win_noalttab->modified = false;
|
||||
}
|
||||
|
||||
if ( vid_ref->modified )
|
||||
{
|
||||
cl.force_refdef = true; // can't use a paused refdef
|
||||
S_StopAllSounds();
|
||||
}
|
||||
while (vid_ref->modified)
|
||||
{
|
||||
/*
|
||||
** refresh has changed
|
||||
*/
|
||||
vid_ref->modified = false;
|
||||
vid_fullscreen->modified = true;
|
||||
cl.refresh_prepped = false;
|
||||
cls.disable_screen = true;
|
||||
|
||||
Com_sprintf( name, sizeof(name), "ref_%s.dll", vid_ref->string );
|
||||
if ( !VID_LoadRefresh( name ) )
|
||||
{
|
||||
if ( strcmp (vid_ref->string, "soft") == 0 )
|
||||
Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
|
||||
Cvar_Set( "vid_ref", "soft" );
|
||||
|
||||
/*
|
||||
** drop the console if we fail to load a refresh
|
||||
*/
|
||||
if ( cls.key_dest != key_console )
|
||||
{
|
||||
Con_ToggleConsole_f();
|
||||
}
|
||||
}
|
||||
cls.disable_screen = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** update our window position
|
||||
*/
|
||||
if ( vid_xpos->modified || vid_ypos->modified )
|
||||
{
|
||||
if (!vid_fullscreen->value)
|
||||
VID_UpdateWindowPosAndSize( vid_xpos->value, vid_ypos->value );
|
||||
|
||||
vid_xpos->modified = false;
|
||||
vid_ypos->modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
VID_Init
|
||||
============
|
||||
*/
|
||||
void VID_Init (void)
|
||||
{
|
||||
/* Create the video variables so we know how to start the graphics drivers */
|
||||
vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
|
||||
vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
|
||||
vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
|
||||
vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
|
||||
vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
|
||||
win_noalttab = Cvar_Get( "win_noalttab", "0", CVAR_ARCHIVE );
|
||||
|
||||
/* Add some console commands that we want to handle */
|
||||
Cmd_AddCommand ("vid_restart", VID_Restart_f);
|
||||
Cmd_AddCommand ("vid_front", VID_Front_f);
|
||||
|
||||
/*
|
||||
** this is a gross hack but necessary to clamp the mode for 3Dfx
|
||||
*/
|
||||
#if 0
|
||||
{
|
||||
cvar_t *gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 );
|
||||
cvar_t *gl_mode = Cvar_Get( "gl_mode", "3", 0 );
|
||||
|
||||
if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 )
|
||||
{
|
||||
Cvar_SetValue( "gl_mode", 3 );
|
||||
viddef.width = 640;
|
||||
viddef.height = 480;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable the 3Dfx splash screen */
|
||||
putenv("FX_GLIDE_NO_SPLASH=0");
|
||||
|
||||
/* Start the graphics mode and load refresh DLL */
|
||||
VID_CheckChanges();
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
VID_Shutdown
|
||||
============
|
||||
*/
|
||||
void VID_Shutdown (void)
|
||||
{
|
||||
if ( reflib_active )
|
||||
{
|
||||
re.Shutdown ();
|
||||
VID_FreeReflib ();
|
||||
}
|
||||
}
|
||||
|
||||
|
473
win32/vid_menu.c
Normal file
473
win32/vid_menu.c
Normal file
@ -0,0 +1,473 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
#include "../client/client.h"
|
||||
#include "../client/qmenu.h"
|
||||
|
||||
#define REF_SOFT 0
|
||||
#define REF_OPENGL 1
|
||||
#define REF_3DFX 2
|
||||
#define REF_POWERVR 3
|
||||
#define REF_VERITE 4
|
||||
|
||||
extern cvar_t *vid_ref;
|
||||
extern cvar_t *vid_fullscreen;
|
||||
extern cvar_t *vid_gamma;
|
||||
extern cvar_t *scr_viewsize;
|
||||
|
||||
static cvar_t *gl_mode;
|
||||
static cvar_t *gl_driver;
|
||||
static cvar_t *gl_picmip;
|
||||
static cvar_t *gl_ext_palettedtexture;
|
||||
static cvar_t *gl_finish;
|
||||
|
||||
static cvar_t *sw_mode;
|
||||
static cvar_t *sw_stipplealpha;
|
||||
|
||||
extern void M_ForceMenuOff( void );
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
MENU INTERACTION
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
#define SOFTWARE_MENU 0
|
||||
#define OPENGL_MENU 1
|
||||
|
||||
static menuframework_s s_software_menu;
|
||||
static menuframework_s s_opengl_menu;
|
||||
static menuframework_s *s_current_menu;
|
||||
static int s_current_menu_index;
|
||||
|
||||
static menulist_s s_mode_list[2];
|
||||
static menulist_s s_ref_list[2];
|
||||
static menuslider_s s_tq_slider;
|
||||
static menuslider_s s_screensize_slider[2];
|
||||
static menuslider_s s_brightness_slider[2];
|
||||
static menulist_s s_fs_box[2];
|
||||
static menulist_s s_stipple_box;
|
||||
static menulist_s s_paletted_texture_box;
|
||||
static menulist_s s_finish_box;
|
||||
static menuaction_s s_cancel_action[2];
|
||||
static menuaction_s s_defaults_action[2];
|
||||
|
||||
static void DriverCallback( void *unused )
|
||||
{
|
||||
s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
|
||||
|
||||
if ( s_ref_list[s_current_menu_index].curvalue == 0 )
|
||||
{
|
||||
s_current_menu = &s_software_menu;
|
||||
s_current_menu_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_current_menu = &s_opengl_menu;
|
||||
s_current_menu_index = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ScreenSizeCallback( void *s )
|
||||
{
|
||||
menuslider_s *slider = ( menuslider_s * ) s;
|
||||
|
||||
Cvar_SetValue( "viewsize", slider->curvalue * 10 );
|
||||
}
|
||||
|
||||
static void BrightnessCallback( void *s )
|
||||
{
|
||||
menuslider_s *slider = ( menuslider_s * ) s;
|
||||
|
||||
if ( s_current_menu_index == SOFTWARE_MENU )
|
||||
s_brightness_slider[1].curvalue = s_brightness_slider[0].curvalue;
|
||||
else
|
||||
s_brightness_slider[0].curvalue = s_brightness_slider[1].curvalue;
|
||||
|
||||
if ( stricmp( vid_ref->string, "soft" ) == 0 )
|
||||
{
|
||||
float gamma = ( 0.8 - ( slider->curvalue/10.0 - 0.5 ) ) + 0.5;
|
||||
|
||||
Cvar_SetValue( "vid_gamma", gamma );
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetDefaults( void *unused )
|
||||
{
|
||||
VID_MenuInit();
|
||||
}
|
||||
|
||||
static void ApplyChanges( void *unused )
|
||||
{
|
||||
float gamma;
|
||||
|
||||
/*
|
||||
** make values consistent
|
||||
*/
|
||||
s_fs_box[!s_current_menu_index].curvalue = s_fs_box[s_current_menu_index].curvalue;
|
||||
s_brightness_slider[!s_current_menu_index].curvalue = s_brightness_slider[s_current_menu_index].curvalue;
|
||||
s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
|
||||
|
||||
/*
|
||||
** invert sense so greater = brighter, and scale to a range of 0.5 to 1.3
|
||||
*/
|
||||
gamma = ( 0.8 - ( s_brightness_slider[s_current_menu_index].curvalue/10.0 - 0.5 ) ) + 0.5;
|
||||
|
||||
Cvar_SetValue( "vid_gamma", gamma );
|
||||
Cvar_SetValue( "sw_stipplealpha", s_stipple_box.curvalue );
|
||||
Cvar_SetValue( "gl_picmip", 3 - s_tq_slider.curvalue );
|
||||
Cvar_SetValue( "vid_fullscreen", s_fs_box[s_current_menu_index].curvalue );
|
||||
Cvar_SetValue( "gl_ext_palettedtexture", s_paletted_texture_box.curvalue );
|
||||
Cvar_SetValue( "gl_finish", s_finish_box.curvalue );
|
||||
Cvar_SetValue( "sw_mode", s_mode_list[SOFTWARE_MENU].curvalue );
|
||||
Cvar_SetValue( "gl_mode", s_mode_list[OPENGL_MENU].curvalue );
|
||||
|
||||
switch ( s_ref_list[s_current_menu_index].curvalue )
|
||||
{
|
||||
case REF_SOFT:
|
||||
Cvar_Set( "vid_ref", "soft" );
|
||||
break;
|
||||
case REF_OPENGL:
|
||||
Cvar_Set( "vid_ref", "gl" );
|
||||
Cvar_Set( "gl_driver", "opengl32" );
|
||||
break;
|
||||
case REF_3DFX:
|
||||
Cvar_Set( "vid_ref", "gl" );
|
||||
Cvar_Set( "gl_driver", "3dfxgl" );
|
||||
break;
|
||||
case REF_POWERVR:
|
||||
Cvar_Set( "vid_ref", "gl" );
|
||||
Cvar_Set( "gl_driver", "pvrgl" );
|
||||
break;
|
||||
case REF_VERITE:
|
||||
Cvar_Set( "vid_ref", "gl" );
|
||||
Cvar_Set( "gl_driver", "veritegl" );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** update appropriate stuff if we're running OpenGL and gamma
|
||||
** has been modified
|
||||
*/
|
||||
if ( stricmp( vid_ref->string, "gl" ) == 0 )
|
||||
{
|
||||
if ( vid_gamma->modified )
|
||||
{
|
||||
vid_ref->modified = true;
|
||||
if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 )
|
||||
{
|
||||
char envbuffer[1024];
|
||||
float g;
|
||||
|
||||
vid_ref->modified = true;
|
||||
|
||||
g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
|
||||
Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g );
|
||||
putenv( envbuffer );
|
||||
Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
|
||||
putenv( envbuffer );
|
||||
|
||||
vid_gamma->modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( gl_driver->modified )
|
||||
vid_ref->modified = true;
|
||||
}
|
||||
|
||||
M_ForceMenuOff();
|
||||
}
|
||||
|
||||
static void CancelChanges( void *unused )
|
||||
{
|
||||
extern void M_PopMenu( void );
|
||||
|
||||
M_PopMenu();
|
||||
}
|
||||
|
||||
/*
|
||||
** VID_MenuInit
|
||||
*/
|
||||
void VID_MenuInit( void )
|
||||
{
|
||||
static const char *resolutions[] =
|
||||
{
|
||||
"[320 240 ]",
|
||||
"[400 300 ]",
|
||||
"[512 384 ]",
|
||||
"[640 480 ]",
|
||||
"[800 600 ]",
|
||||
"[960 720 ]",
|
||||
"[1024 768 ]",
|
||||
"[1152 864 ]",
|
||||
"[1280 960 ]",
|
||||
"[1600 1200]",
|
||||
0
|
||||
};
|
||||
static const char *refs[] =
|
||||
{
|
||||
"[software ]",
|
||||
"[default OpenGL]",
|
||||
"[3Dfx OpenGL ]",
|
||||
"[PowerVR OpenGL]",
|
||||
// "[Rendition OpenGL]",
|
||||
0
|
||||
};
|
||||
static const char *yesno_names[] =
|
||||
{
|
||||
"no",
|
||||
"yes",
|
||||
0
|
||||
};
|
||||
int i;
|
||||
|
||||
if ( !gl_driver )
|
||||
gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 );
|
||||
if ( !gl_picmip )
|
||||
gl_picmip = Cvar_Get( "gl_picmip", "0", 0 );
|
||||
if ( !gl_mode )
|
||||
gl_mode = Cvar_Get( "gl_mode", "3", 0 );
|
||||
if ( !sw_mode )
|
||||
sw_mode = Cvar_Get( "sw_mode", "0", 0 );
|
||||
if ( !gl_ext_palettedtexture )
|
||||
gl_ext_palettedtexture = Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE );
|
||||
if ( !gl_finish )
|
||||
gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE );
|
||||
|
||||
if ( !sw_stipplealpha )
|
||||
sw_stipplealpha = Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE );
|
||||
|
||||
s_mode_list[SOFTWARE_MENU].curvalue = sw_mode->value;
|
||||
s_mode_list[OPENGL_MENU].curvalue = gl_mode->value;
|
||||
|
||||
if ( !scr_viewsize )
|
||||
scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE);
|
||||
|
||||
s_screensize_slider[SOFTWARE_MENU].curvalue = scr_viewsize->value/10;
|
||||
s_screensize_slider[OPENGL_MENU].curvalue = scr_viewsize->value/10;
|
||||
|
||||
if ( strcmp( vid_ref->string, "soft" ) == 0 )
|
||||
{
|
||||
s_current_menu_index = SOFTWARE_MENU;
|
||||
s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_SOFT;
|
||||
}
|
||||
else if ( strcmp( vid_ref->string, "gl" ) == 0 )
|
||||
{
|
||||
s_current_menu_index = OPENGL_MENU;
|
||||
if ( strcmp( gl_driver->string, "3dfxgl" ) == 0 )
|
||||
s_ref_list[s_current_menu_index].curvalue = REF_3DFX;
|
||||
else if ( strcmp( gl_driver->string, "pvrgl" ) == 0 )
|
||||
s_ref_list[s_current_menu_index].curvalue = REF_POWERVR;
|
||||
else if ( strcmp( gl_driver->string, "opengl32" ) == 0 )
|
||||
s_ref_list[s_current_menu_index].curvalue = REF_OPENGL;
|
||||
else
|
||||
// s_ref_list[s_current_menu_index].curvalue = REF_VERITE;
|
||||
s_ref_list[s_current_menu_index].curvalue = REF_OPENGL;
|
||||
}
|
||||
|
||||
s_software_menu.x = viddef.width * 0.50;
|
||||
s_software_menu.nitems = 0;
|
||||
s_opengl_menu.x = viddef.width * 0.50;
|
||||
s_opengl_menu.nitems = 0;
|
||||
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
s_ref_list[i].generic.type = MTYPE_SPINCONTROL;
|
||||
s_ref_list[i].generic.name = "driver";
|
||||
s_ref_list[i].generic.x = 0;
|
||||
s_ref_list[i].generic.y = 0;
|
||||
s_ref_list[i].generic.callback = DriverCallback;
|
||||
s_ref_list[i].itemnames = refs;
|
||||
|
||||
s_mode_list[i].generic.type = MTYPE_SPINCONTROL;
|
||||
s_mode_list[i].generic.name = "video mode";
|
||||
s_mode_list[i].generic.x = 0;
|
||||
s_mode_list[i].generic.y = 10;
|
||||
s_mode_list[i].itemnames = resolutions;
|
||||
|
||||
s_screensize_slider[i].generic.type = MTYPE_SLIDER;
|
||||
s_screensize_slider[i].generic.x = 0;
|
||||
s_screensize_slider[i].generic.y = 20;
|
||||
s_screensize_slider[i].generic.name = "screen size";
|
||||
s_screensize_slider[i].minvalue = 3;
|
||||
s_screensize_slider[i].maxvalue = 12;
|
||||
s_screensize_slider[i].generic.callback = ScreenSizeCallback;
|
||||
|
||||
s_brightness_slider[i].generic.type = MTYPE_SLIDER;
|
||||
s_brightness_slider[i].generic.x = 0;
|
||||
s_brightness_slider[i].generic.y = 30;
|
||||
s_brightness_slider[i].generic.name = "brightness";
|
||||
s_brightness_slider[i].generic.callback = BrightnessCallback;
|
||||
s_brightness_slider[i].minvalue = 5;
|
||||
s_brightness_slider[i].maxvalue = 13;
|
||||
s_brightness_slider[i].curvalue = ( 1.3 - vid_gamma->value + 0.5 ) * 10;
|
||||
|
||||
s_fs_box[i].generic.type = MTYPE_SPINCONTROL;
|
||||
s_fs_box[i].generic.x = 0;
|
||||
s_fs_box[i].generic.y = 40;
|
||||
s_fs_box[i].generic.name = "fullscreen";
|
||||
s_fs_box[i].itemnames = yesno_names;
|
||||
s_fs_box[i].curvalue = vid_fullscreen->value;
|
||||
|
||||
s_defaults_action[i].generic.type = MTYPE_ACTION;
|
||||
s_defaults_action[i].generic.name = "reset to defaults";
|
||||
s_defaults_action[i].generic.x = 0;
|
||||
s_defaults_action[i].generic.y = 90;
|
||||
s_defaults_action[i].generic.callback = ResetDefaults;
|
||||
|
||||
s_cancel_action[i].generic.type = MTYPE_ACTION;
|
||||
s_cancel_action[i].generic.name = "cancel";
|
||||
s_cancel_action[i].generic.x = 0;
|
||||
s_cancel_action[i].generic.y = 100;
|
||||
s_cancel_action[i].generic.callback = CancelChanges;
|
||||
}
|
||||
|
||||
s_stipple_box.generic.type = MTYPE_SPINCONTROL;
|
||||
s_stipple_box.generic.x = 0;
|
||||
s_stipple_box.generic.y = 60;
|
||||
s_stipple_box.generic.name = "stipple alpha";
|
||||
s_stipple_box.curvalue = sw_stipplealpha->value;
|
||||
s_stipple_box.itemnames = yesno_names;
|
||||
|
||||
s_tq_slider.generic.type = MTYPE_SLIDER;
|
||||
s_tq_slider.generic.x = 0;
|
||||
s_tq_slider.generic.y = 60;
|
||||
s_tq_slider.generic.name = "texture quality";
|
||||
s_tq_slider.minvalue = 0;
|
||||
s_tq_slider.maxvalue = 3;
|
||||
s_tq_slider.curvalue = 3-gl_picmip->value;
|
||||
|
||||
s_paletted_texture_box.generic.type = MTYPE_SPINCONTROL;
|
||||
s_paletted_texture_box.generic.x = 0;
|
||||
s_paletted_texture_box.generic.y = 70;
|
||||
s_paletted_texture_box.generic.name = "8-bit textures";
|
||||
s_paletted_texture_box.itemnames = yesno_names;
|
||||
s_paletted_texture_box.curvalue = gl_ext_palettedtexture->value;
|
||||
|
||||
s_finish_box.generic.type = MTYPE_SPINCONTROL;
|
||||
s_finish_box.generic.x = 0;
|
||||
s_finish_box.generic.y = 80;
|
||||
s_finish_box.generic.name = "sync every frame";
|
||||
s_finish_box.curvalue = gl_finish->value;
|
||||
s_finish_box.itemnames = yesno_names;
|
||||
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_ref_list[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_mode_list[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_screensize_slider[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_brightness_slider[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_fs_box[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_stipple_box );
|
||||
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_ref_list[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_mode_list[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_screensize_slider[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_brightness_slider[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_fs_box[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_tq_slider );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_paletted_texture_box );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_finish_box );
|
||||
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_defaults_action[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_software_menu, ( void * ) &s_cancel_action[SOFTWARE_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_defaults_action[OPENGL_MENU] );
|
||||
Menu_AddItem( &s_opengl_menu, ( void * ) &s_cancel_action[OPENGL_MENU] );
|
||||
|
||||
Menu_Center( &s_software_menu );
|
||||
Menu_Center( &s_opengl_menu );
|
||||
s_opengl_menu.x -= 8;
|
||||
s_software_menu.x -= 8;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VID_MenuDraw
|
||||
================
|
||||
*/
|
||||
void VID_MenuDraw (void)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
if ( s_current_menu_index == 0 )
|
||||
s_current_menu = &s_software_menu;
|
||||
else
|
||||
s_current_menu = &s_opengl_menu;
|
||||
|
||||
/*
|
||||
** draw the banner
|
||||
*/
|
||||
re.DrawGetPicSize( &w, &h, "m_banner_video" );
|
||||
re.DrawPic( viddef.width / 2 - w / 2, viddef.height /2 - 110, "m_banner_video" );
|
||||
|
||||
/*
|
||||
** move cursor to a reasonable starting position
|
||||
*/
|
||||
Menu_AdjustCursor( s_current_menu, 1 );
|
||||
|
||||
/*
|
||||
** draw the menu
|
||||
*/
|
||||
Menu_Draw( s_current_menu );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VID_MenuKey
|
||||
================
|
||||
*/
|
||||
const char *VID_MenuKey( int key )
|
||||
{
|
||||
menuframework_s *m = s_current_menu;
|
||||
static const char *sound = "misc/menu1.wav";
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
case K_ESCAPE:
|
||||
ApplyChanges( 0 );
|
||||
return NULL;
|
||||
case K_KP_UPARROW:
|
||||
case K_UPARROW:
|
||||
m->cursor--;
|
||||
Menu_AdjustCursor( m, -1 );
|
||||
break;
|
||||
case K_KP_DOWNARROW:
|
||||
case K_DOWNARROW:
|
||||
m->cursor++;
|
||||
Menu_AdjustCursor( m, 1 );
|
||||
break;
|
||||
case K_KP_LEFTARROW:
|
||||
case K_LEFTARROW:
|
||||
Menu_SlideItem( m, -1 );
|
||||
break;
|
||||
case K_KP_RIGHTARROW:
|
||||
case K_RIGHTARROW:
|
||||
Menu_SlideItem( m, 1 );
|
||||
break;
|
||||
case K_KP_ENTER:
|
||||
case K_ENTER:
|
||||
if ( !Menu_SelectItem( m ) )
|
||||
ApplyChanges( NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
|
BIN
win32/winquake.aps
Normal file
BIN
win32/winquake.aps
Normal file
Binary file not shown.
44
win32/winquake.h
Normal file
44
win32/winquake.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// winquake.h: Win32-specific Quake header file
|
||||
|
||||
#pragma warning( disable : 4229 ) // mgraph gets this
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <dsound.h>
|
||||
|
||||
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE)
|
||||
|
||||
extern HINSTANCE global_hInstance;
|
||||
|
||||
extern LPDIRECTSOUND pDS;
|
||||
extern LPDIRECTSOUNDBUFFER pDSBuf;
|
||||
|
||||
extern DWORD gSndBufSize;
|
||||
|
||||
extern HWND cl_hwnd;
|
||||
extern qboolean ActiveApp, Minimized;
|
||||
|
||||
void IN_Activate (qboolean active);
|
||||
void IN_MouseEvent (int mstate);
|
||||
|
||||
extern int window_center_x, window_center_y;
|
||||
extern RECT window_rect;
|
98
win32/winquake.rc
Normal file
98
win32/winquake.rc
Normal file
@ -0,0 +1,98 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "q2.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DIALOG1 DIALOGEX 0, 0, 62, 21
|
||||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP |
|
||||
WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
|
||||
FONT 16, "Times New Roman", 0, 0, 0x1
|
||||
BEGIN
|
||||
CTEXT "Starting QW...",IDC_STATIC,4,6,54,8
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_STRING1 "WinQuake"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
Reference in New Issue
Block a user