From b139acafc2bf5e6b2335f51b35cf90d647ab09b5 Mon Sep 17 00:00:00 2001 From: Dan Olson Date: Wed, 10 May 2000 20:33:16 +0000 Subject: [PATCH] ^M cleanup, and qw-server compiles with -Werror --- source/Makefile | 6 +- source/buildnum.c | 152 +- source/cd_linux.c | 38 +- source/cd_win.c | 958 +++--- source/cl_cam.c | 38 +- source/cl_demo.c | 38 +- source/cl_ents.c | 2166 ++++++------ source/cl_input.c | 54 +- source/cl_main.c | 44 +- source/cl_parse.c | 38 +- source/cl_pred.c | 94 +- source/cl_tent.c | 98 +- source/cmd.c | 1496 ++++---- source/common.c | 42 +- source/console.c | 38 +- source/crc.c | 42 +- source/cvar.c | 50 +- source/d_edge.c | 58 +- source/d_fill.c | 38 +- source/d_init.c | 46 +- source/d_modech.c | 38 +- source/d_part.c | 38 +- source/d_polyse.c | 38 +- source/d_scan.c | 46 +- source/d_sky.c | 38 +- source/d_sprite.c | 38 +- source/d_surf.c | 676 ++-- source/d_vars.c | 38 +- source/d_zpoint.c | 38 +- source/draw.c | 38 +- source/gl_draw.c | 38 +- source/gl_mesh.c | 718 ++-- source/gl_model.c | 50 +- source/gl_ngraph.c | 38 +- source/gl_refrag.c | 40 +- source/gl_rlight.c | 38 +- source/gl_rmain.c | 38 +- source/gl_rmisc.c | 44 +- source/gl_rsurf.c | 38 +- source/gl_screen.c | 2376 ++++++------- source/gl_test.c | 364 +- source/gl_vidlinux.c | 38 +- source/gl_vidlinux_svga.c | 38 +- source/gl_vidlinux_x11.c | 38 +- source/gl_vidlinuxglx.c | 38 +- source/gl_vidnt.c | 3898 ++++++++++----------- source/gl_warp.c | 2174 ++++++------ source/in_null.c | 18 +- source/in_win.c | 2464 +++++++------- source/keys.c | 1678 ++++----- source/mathlib.c | 38 +- source/menu.c | 38 +- source/model.c | 80 +- source/model.c.client | 38 +- source/net_chan.c | 40 +- source/net_udp.c | 41 +- source/net_wins.c | 38 +- source/nonintel.c | 38 +- source/pmove.c | 40 +- source/pmovetst.c | 828 ++--- source/pr_cmds.c | 40 +- source/pr_edict.c | 164 +- source/pr_exec.c | 52 +- source/r_aclip.c | 38 +- source/r_alias.c | 68 +- source/r_bsp.c | 40 +- source/r_draw.c | 38 +- source/r_edge.c | 46 +- source/r_efrag.c | 38 +- source/r_light.c | 38 +- source/r_main.c | 38 +- source/r_misc.c | 38 +- source/r_part.c | 164 +- source/r_sky.c | 38 +- source/r_sprite.c | 38 +- source/r_surf.c | 38 +- source/r_vars.c | 38 +- source/sbar.c | 38 +- source/screen.c | 2352 ++++++------- source/skin.c | 92 +- source/snd_dma.c | 2034 +++++------ source/snd_mem.c | 686 ++-- source/snd_mix.c | 796 ++--- source/snd_win.c | 1454 ++++---- source/sv_ccmds.c | 426 +-- source/sv_ents.c | 48 +- source/sv_init.c | 42 +- source/sv_main.c | 43 +- source/sv_move.c | 40 +- source/sv_nchan.c | 38 +- source/sv_phys.c | 444 +-- source/sv_send.c | 38 +- source/sv_user.c | 341 +- source/sys_linux.c | 856 ++--- source/sys_unix.c | 41 +- source/sys_win.c | 38 +- source/sys_win.c.server | 508 +-- source/vid_svgalib.c | 38 +- source/vid_win.c | 6782 ++++++++++++++++++------------------- source/vid_x.c | 2232 ++++++------ source/view.c | 64 +- source/wad.c | 38 +- source/world.c | 40 +- source/zone.c | 70 +- 104 files changed, 21255 insertions(+), 21263 deletions(-) diff --git a/source/Makefile b/source/Makefile index 3a775c4..867ebc5 100644 --- a/source/Makefile +++ b/source/Makefile @@ -6,9 +6,9 @@ EXE_libs= DIRECTORIES= vpath %.a $(patsubst @%,%,$(DIRECTORIES)) /usr/lib -CPPFLAGS=-I . -I ../include -DELF -Did386=1 -Dstricmp=strcasecmp -MMD -DSERVERONLY -CFLAGS=-Wall #-Werror -CXXFLAGS=-Wall #-Werror +CPPFLAGS=-I . -I ../include -DELF -Did386=1 -MMD -Dstricmp=strcasecmp -DSERVERONLY +CFLAGS=-Wall -Werror +CXXFLAGS=-Wall -Werror LDFLAGS= CC=gcc diff --git a/source/buildnum.c b/source/buildnum.c index dd20f13..eac7d49 100644 --- a/source/buildnum.c +++ b/source/buildnum.c @@ -1,76 +1,76 @@ -/* -Copyright (C) 1996-1997 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 included (GNU.txt) 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 -#include - -#include - -// char *date = "Oct 24 1996"; -// char *time = "13:22:52"; -char *date = __DATE__ ; -char *time = __TIME__ ; - -char *mon[12] = -{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -char mond[12] = -{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -// returns days since Oct 24 1996 -int build_number( void ) -{ - int m = 0; - int d = 0; - int y = 0; - int hr, min; - static int b = 0; - - if (b != 0) - return b; - - for (m = 0; m < 11; m++) - { - if (_strnicmp( &date[0], mon[m], 3 ) == 0) - break; - d += mond[m]; - } - - d += atoi( &date[4] ) - 1; - - y = atoi( &date[7] ) - 1900; - - b = d + (int)((y - 1) * 365.25); - - if (((y % 4) == 0) && m > 1) - { - b += 1; - } - - b -= 34995; // Oct 24 1996 - - hr = (time[0] - '0') * 10 + (time[1] - '0'); - min = (time[3] - '0') * 10 + (time[4] - '0'); -// sec = (time[6] - '0') * 10 + (time[7] - '0'); - - b *= 60*24; - b += hr * 60 + min; - - return b; -} - +/* +Copyright (C) 1996-1997 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 included (GNU.txt) 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 +#include + +#include + +// char *date = "Oct 24 1996"; +// char *time = "13:22:52"; +char *date = __DATE__ ; +char *time = __TIME__ ; + +char *mon[12] = +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +char mond[12] = +{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +// returns days since Oct 24 1996 +int build_number( void ) +{ + int m = 0; + int d = 0; + int y = 0; + int hr, min; + static int b = 0; + + if (b != 0) + return b; + + for (m = 0; m < 11; m++) + { + if (_strnicmp( &date[0], mon[m], 3 ) == 0) + break; + d += mond[m]; + } + + d += atoi( &date[4] ) - 1; + + y = atoi( &date[7] ) - 1900; + + b = d + (int)((y - 1) * 365.25); + + if (((y % 4) == 0) && m > 1) + { + b += 1; + } + + b -= 34995; // Oct 24 1996 + + hr = (time[0] - '0') * 10 + (time[1] - '0'); + min = (time[3] - '0') * 10 + (time[4] - '0'); +// sec = (time[6] - '0') * 10 + (time[7] - '0'); + + b *= 60*24; + b += hr * 60 + min; + + return b; +} + diff --git a/source/cd_linux.c b/source/cd_linux.c index 3b1c471..2bf8409 100644 --- a/source/cd_linux.c +++ b/source/cd_linux.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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 included (GNU.txt) 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. - -*/ +/* +Copyright (C) 1996-1997 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 included (GNU.txt) 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. diff --git a/source/cd_win.c b/source/cd_win.c index 14f093f..6956f5a 100644 --- a/source/cd_win.c +++ b/source/cd_win.c @@ -1,479 +1,479 @@ -/* -Copyright (C) 1996-1997 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 included (GNU.txt) 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 -#include "quakedef.h" - -extern HWND mainwindow; -extern cvar_t bgmvolume; - -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 float cdvolume; -static byte remap[100]; -static byte cdrom; -static byte playTrack; -static byte maxTrack; - -UINT wDeviceID; - - -static void CDAudio_Eject(void) -{ - DWORD dwReturn; - - if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) - Con_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)) - Con_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) - { - Con_DPrintf("CDAudio: drive ready test - get status failed\n"); - return -1; - } - if (!mciStatusParms.dwReturn) - { - Con_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) - { - Con_DPrintf("CDAudio: get tracks - status failed\n"); - return -1; - } - if (mciStatusParms.dwReturn < 1) - { - Con_DPrintf("CDAudio: no music tracks\n"); - return -1; - } - - cdValid = true; - maxTrack = mciStatusParms.dwReturn; - - return 0; -} - - -void CDAudio_Play(byte 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) - { - Con_DPrintf("CDAudio: Bad track number %u.\n", track); - 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) - { - Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); - return; - } - if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) - { - Con_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) - { - Con_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)mainwindow; - dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); - return; - } - - playLooping = looping; - playTrack = track; - playing = true; - - if (cdvolume == 0.0) - CDAudio_Pause (); -} - - -void CDAudio_Stop(void) -{ - DWORD dwReturn; - - if (!enabled) - return; - - if (!playing) - return; - - if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) - Con_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)mainwindow; - if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) - Con_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)mainwindow; - dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); - return; - } - playing = true; -} - - -static void CD_f (void) -{ - char *command; - int ret; - int n; - int startAddress; - - 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) - Con_Printf(" %u -> %u\n", n, remap[n]); - return; - } - for (n = 1; n <= ret; n++) - remap[n] = Q_atoi(Cmd_Argv (n+1)); - return; - } - - if (Q_strcasecmp(command, "close") == 0) - { - CDAudio_CloseDoor(); - return; - } - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - { - Con_Printf("No CD in player.\n"); - return; - } - } - - if (Q_strcasecmp(command, "play") == 0) - { - CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); - return; - } - - if (Q_strcasecmp(command, "loop") == 0) - { - CDAudio_Play((byte)Q_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) - { - Con_Printf("%u tracks\n", maxTrack); - if (playing) - Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); - else if (wasPlaying) - Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); - Con_Printf("Volume is %f\n", cdvolume); - 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) - CDAudio_Play(playTrack, true); - } - break; - - case MCI_NOTIFY_ABORTED: - case MCI_NOTIFY_SUPERSEDED: - break; - - case MCI_NOTIFY_FAILURE: - Con_DPrintf("MCI_NOTIFY_FAILURE\n"); - CDAudio_Stop (); - cdValid = false; - break; - - default: - Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); - return 1; - } - - return 0; -} - - -void CDAudio_Update(void) -{ - if (!enabled) - return; - - if (bgmvolume.value != cdvolume) - { - if (cdvolume) - { - Cvar_SetValue ("bgmvolume", 0.0); - cdvolume = bgmvolume.value; - CDAudio_Pause (); - } - else - { - Cvar_SetValue ("bgmvolume", 1.0); - cdvolume = bgmvolume.value; - CDAudio_Resume (); - } - } -} - - -int CDAudio_Init(void) -{ - DWORD dwReturn; - MCI_OPEN_PARMS mciOpenParms; - MCI_SET_PARMS mciSetParms; - int n; - -#if 0 // QW - if (cls.state == ca_dedicated) - return -1; -#endif - if (COM_CheckParm("-nocdaudio")) - return -1; - - mciOpenParms.lpstrDeviceType = "cdaudio"; - if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) - { - Con_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)) - { - Con_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()) - { - Con_Printf("CDAudio_Init: No CD in player.\n"); - cdValid = false; - enabled = false; - } - - Cmd_AddCommand ("cd", CD_f); - -// Con_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)) - Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); -} +/* +Copyright (C) 1996-1997 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 included (GNU.txt) 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 +#include "quakedef.h" + +extern HWND mainwindow; +extern cvar_t bgmvolume; + +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 float cdvolume; +static byte remap[100]; +static byte cdrom; +static byte playTrack; +static byte maxTrack; + +UINT wDeviceID; + + +static void CDAudio_Eject(void) +{ + DWORD dwReturn; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) + Con_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)) + Con_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) + { + Con_DPrintf("CDAudio: drive ready test - get status failed\n"); + return -1; + } + if (!mciStatusParms.dwReturn) + { + Con_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) + { + Con_DPrintf("CDAudio: get tracks - status failed\n"); + return -1; + } + if (mciStatusParms.dwReturn < 1) + { + Con_DPrintf("CDAudio: no music tracks\n"); + return -1; + } + + cdValid = true; + maxTrack = mciStatusParms.dwReturn; + + return 0; +} + + +void CDAudio_Play(byte 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) + { + Con_DPrintf("CDAudio: Bad track number %u.\n", track); + 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) + { + Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); + return; + } + if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) + { + Con_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) + { + Con_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)mainwindow; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + + playLooping = looping; + playTrack = track; + playing = true; + + if (cdvolume == 0.0) + CDAudio_Pause (); +} + + +void CDAudio_Stop(void) +{ + DWORD dwReturn; + + if (!enabled) + return; + + if (!playing) + return; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) + Con_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)mainwindow; + if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) + Con_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)mainwindow; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + playing = true; +} + + +static void CD_f (void) +{ + char *command; + int ret; + int n; + int startAddress; + + 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) + Con_Printf(" %u -> %u\n", n, remap[n]); + return; + } + for (n = 1; n <= ret; n++) + remap[n] = Q_atoi(Cmd_Argv (n+1)); + return; + } + + if (Q_strcasecmp(command, "close") == 0) + { + CDAudio_CloseDoor(); + return; + } + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + { + Con_Printf("No CD in player.\n"); + return; + } + } + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play((byte)Q_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) + { + Con_Printf("%u tracks\n", maxTrack); + if (playing) + Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); + else if (wasPlaying) + Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); + Con_Printf("Volume is %f\n", cdvolume); + 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) + CDAudio_Play(playTrack, true); + } + break; + + case MCI_NOTIFY_ABORTED: + case MCI_NOTIFY_SUPERSEDED: + break; + + case MCI_NOTIFY_FAILURE: + Con_DPrintf("MCI_NOTIFY_FAILURE\n"); + CDAudio_Stop (); + cdValid = false; + break; + + default: + Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); + return 1; + } + + return 0; +} + + +void CDAudio_Update(void) +{ + if (!enabled) + return; + + if (bgmvolume.value != cdvolume) + { + if (cdvolume) + { + Cvar_SetValue ("bgmvolume", 0.0); + cdvolume = bgmvolume.value; + CDAudio_Pause (); + } + else + { + Cvar_SetValue ("bgmvolume", 1.0); + cdvolume = bgmvolume.value; + CDAudio_Resume (); + } + } +} + + +int CDAudio_Init(void) +{ + DWORD dwReturn; + MCI_OPEN_PARMS mciOpenParms; + MCI_SET_PARMS mciSetParms; + int n; + +#if 0 // QW + if (cls.state == ca_dedicated) + return -1; +#endif + if (COM_CheckParm("-nocdaudio")) + return -1; + + mciOpenParms.lpstrDeviceType = "cdaudio"; + if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) + { + Con_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)) + { + Con_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()) + { + Con_Printf("CDAudio_Init: No CD in player.\n"); + cdValid = false; + enabled = false; + } + + Cmd_AddCommand ("cd", CD_f); + +// Con_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)) + Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); +} diff --git a/source/cl_cam.c b/source/cl_cam.c index 4be041b..41704f9 100644 --- a/source/cl_cam.c +++ b/source/cl_cam.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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 included (GNU.txt) 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. - -*/ +/* +Copyright (C) 1996-1997 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 included (GNU.txt) 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. + +*/ /* ZOID * * Player camera tracking in Spectator mode diff --git a/source/cl_demo.c b/source/cl_demo.c index 3f8d360..683e8ab 100644 --- a/source/cl_demo.c +++ b/source/cl_demo.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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 included (GNU.txt) 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. - -*/ +/* +Copyright (C) 1996-1997 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 included (GNU.txt) 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 "quakedef.h" diff --git a/source/cl_ents.c b/source/cl_ents.c index 8f156eb..80d28c4 100644 --- a/source/cl_ents.c +++ b/source/cl_ents.c @@ -1,1083 +1,1083 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// cl_ents.c -- entity parsing and management - -#include "quakedef.h" - -extern cvar_t cl_predict_players; -extern cvar_t cl_predict_players2; -extern cvar_t cl_solid_players; - -static struct predicted_player { - int flags; - qboolean active; - vec3_t origin; // predicted origin -} predicted_players[MAX_CLIENTS]; - -//============================================================ - -/* -=============== -CL_AllocDlight - -=============== -*/ -dlight_t *CL_AllocDlight (int key) -{ - int i; - dlight_t *dl; - -// first look for an exact key match - if (key) - { - dl = cl_dlights; - for (i=0 ; ikey == key) - { - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; - } - } - } - -// then look for anything else - dl = cl_dlights; - for (i=0 ; idie < cl.time) - { - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; - } - } - - dl = &cl_dlights[0]; - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; -} - -/* -=============== -CL_NewDlight -=============== -*/ -void CL_NewDlight (int key, float x, float y, float z, float radius, float time, - int type) -{ - dlight_t *dl; - - dl = CL_AllocDlight (key); - dl->origin[0] = x; - dl->origin[1] = y; - dl->origin[2] = z; - dl->radius = radius; - dl->die = cl.time + time; - if (type == 0) { - dl->color[0] = 0.2; - dl->color[1] = 0.1; - dl->color[2] = 0.05; - dl->color[3] = 0.7; - } else if (type == 1) { - dl->color[0] = 0.05; - dl->color[1] = 0.05; - dl->color[2] = 0.3; - dl->color[3] = 0.7; - } else if (type == 2) { - dl->color[0] = 0.5; - dl->color[1] = 0.05; - dl->color[2] = 0.05; - dl->color[3] = 0.7; - } else if (type == 3) { - dl->color[0]=0.5; - dl->color[1] = 0.05; - dl->color[2] = 0.4; - dl->color[3] = 0.7; - } -} - - -/* -=============== -CL_DecayLights - -=============== -*/ -void CL_DecayLights (void) -{ - int i; - dlight_t *dl; - - dl = cl_dlights; - for (i=0 ; idie < cl.time || !dl->radius) - continue; - - dl->radius -= host_frametime*dl->decay; - if (dl->radius < 0) - dl->radius = 0; - } -} - - -/* -========================================================================= - -PACKET ENTITY PARSING / LINKING - -========================================================================= -*/ - -/* -================== -CL_ParseDelta - -Can go from either a baseline or a previous packet_entity -================== -*/ -int bitcounts[32]; /// just for protocol profiling -void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) -{ - int i; - - // set everything to the state we are delta'ing from - *to = *from; - - to->number = bits & 511; - bits &= ~511; - - if (bits & U_MOREBITS) - { // read in the low order bits - i = MSG_ReadByte (); - bits |= i; - } - - // count the bits for net profiling - for (i=0 ; i<16 ; i++) - if (bits&(1<flags = bits; - - if (bits & U_MODEL) - to->modelindex = MSG_ReadByte (); - - if (bits & U_FRAME) - to->frame = MSG_ReadByte (); - - if (bits & U_COLORMAP) - to->colormap = MSG_ReadByte(); - - if (bits & U_SKIN) - to->skinnum = MSG_ReadByte(); - - if (bits & U_EFFECTS) - to->effects = MSG_ReadByte(); - - if (bits & U_ORIGIN1) - to->origin[0] = MSG_ReadCoord (); - - if (bits & U_ANGLE1) - to->angles[0] = MSG_ReadAngle(); - - if (bits & U_ORIGIN2) - to->origin[1] = MSG_ReadCoord (); - - if (bits & U_ANGLE2) - to->angles[1] = MSG_ReadAngle(); - - if (bits & U_ORIGIN3) - to->origin[2] = MSG_ReadCoord (); - - if (bits & U_ANGLE3) - to->angles[2] = MSG_ReadAngle(); - - if (bits & U_SOLID) - { - // FIXME - } -} - - -/* -================= -FlushEntityPacket -================= -*/ -void FlushEntityPacket (void) -{ - int word; - entity_state_t olde, newe; - - Con_DPrintf ("FlushEntityPacket\n"); - - memset (&olde, 0, sizeof(olde)); - - cl.validsequence = 0; // can't render a frame - cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true; - - // read it all, but ignore it - while (1) - { - word = (unsigned short)MSG_ReadShort (); - if (msg_badread) - { // something didn't parse right... - Host_EndGame ("msg_badread in packetentities"); - return; - } - - if (!word) - break; // done - - CL_ParseDelta (&olde, &newe, word); - } -} - -/* -================== -CL_ParsePacketEntities - -An svc_packetentities has just been parsed, deal with the -rest of the data stream. -================== -*/ -void CL_ParsePacketEntities (qboolean delta) -{ - int oldpacket, newpacket; - packet_entities_t *oldp, *newp, dummy; - int oldindex, newindex; - int word, newnum, oldnum; - qboolean full; - byte from; - - newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; - newp = &cl.frames[newpacket].packet_entities; - cl.frames[newpacket].invalid = false; - - if (delta) - { - from = MSG_ReadByte (); - - oldpacket = cl.frames[newpacket].delta_sequence; - - if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) ) - Con_DPrintf ("WARNING: from mismatch\n"); - } - else - oldpacket = -1; - - full = false; - if (oldpacket != -1) - { - if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1) - { // we can't use this, it is too old - FlushEntityPacket (); - return; - } - cl.validsequence = cls.netchan.incoming_sequence; - oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities; - } - else - { // this is a full update that we can start delta compressing from now - oldp = &dummy; - dummy.num_entities = 0; - cl.validsequence = cls.netchan.incoming_sequence; - full = true; - } - - oldindex = 0; - newindex = 0; - newp->num_entities = 0; - - while (1) - { - word = (unsigned short)MSG_ReadShort (); - if (msg_badread) - { // something didn't parse right... - Host_EndGame ("msg_badread in packetentities"); - return; - } - - if (!word) - { - while (oldindex < oldp->num_entities) - { // copy all the rest of the entities from the old packet -//Con_Printf ("copy %i\n", oldp->entities[oldindex].number); - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); - newp->entities[newindex] = oldp->entities[oldindex]; - newindex++; - oldindex++; - } - break; - } - newnum = word&511; - oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; - - while (newnum > oldnum) - { - if (full) - { - Con_Printf ("WARNING: oldcopy on full update"); - FlushEntityPacket (); - return; - } - -//Con_Printf ("copy %i\n", oldnum); - // copy one of the old entities over to the new packet unchanged - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); - newp->entities[newindex] = oldp->entities[oldindex]; - newindex++; - oldindex++; - oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; - } - - if (newnum < oldnum) - { // new from baseline -//Con_Printf ("baseline %i\n", newnum); - if (word & U_REMOVE) - { - if (full) - { - cl.validsequence = 0; - Con_Printf ("WARNING: U_REMOVE on full update\n"); - FlushEntityPacket (); - return; - } - continue; - } - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); - CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word); - newindex++; - continue; - } - - if (newnum == oldnum) - { // delta from previous - if (full) - { - cl.validsequence = 0; - Con_Printf ("WARNING: delta on full update"); - } - if (word & U_REMOVE) - { - oldindex++; - continue; - } -//Con_Printf ("delta %i\n",newnum); - CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word); - newindex++; - oldindex++; - } - - } - - newp->num_entities = newindex; -} - - -/* -=============== -CL_LinkPacketEntities - -=============== -*/ -void CL_LinkPacketEntities (void) -{ - entity_t *ent; - packet_entities_t *pack; - entity_state_t *s1, *s2; - float f; - model_t *model; - vec3_t old_origin; - float autorotate; - int i; - int pnum; - dlight_t *dl; - - pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; - - autorotate = anglemod(100*cl.time); - - f = 0; // FIXME: no interpolation right now - - for (pnum=0 ; pnumnum_entities ; pnum++) - { - s1 = &pack->entities[pnum]; - s2 = s1; // FIXME: no interpolation right now - - // spawn light flashes, even ones coming from invisible objects - if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3); - else if (s1->effects & EF_BLUE) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1); - else if (s1->effects & EF_RED) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2); - else if (s1->effects & EF_BRIGHTLIGHT) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0); - else if (s1->effects & EF_DIMLIGHT) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0); - - // if set to invisible, skip - if (!s1->modelindex) - continue; - - // create a new entity - if (cl_numvisedicts == MAX_VISEDICTS) - break; // object list is full - - ent = &cl_visedicts[cl_numvisedicts]; - cl_numvisedicts++; - - ent->keynum = s1->number; - ent->model = model = cl.model_precache[s1->modelindex]; - - // set colormap - if (s1->colormap && (s1->colormap < MAX_CLIENTS) - && !strcmp(ent->model->name,"progs/player.mdl") ) - { - ent->colormap = cl.players[s1->colormap-1].translations; - ent->scoreboard = &cl.players[s1->colormap-1]; - } - else - { - ent->colormap = vid.colormap; - ent->scoreboard = NULL; - } - - // set skin - ent->skinnum = s1->skinnum; - - // set frame - ent->frame = s1->frame; - - // rotate binary objects locally - if (model->flags & EF_ROTATE) - { - ent->angles[0] = 0; - ent->angles[1] = autorotate; - ent->angles[2] = 0; - } - else - { - float a1, a2; - - for (i=0 ; i<3 ; i++) - { - a1 = s1->angles[i]; - a2 = s2->angles[i]; - if (a1 - a2 > 180) - a1 -= 360; - if (a1 - a2 < -180) - a1 += 360; - ent->angles[i] = a2 + f * (a1 - a2); - } - } - - // calculate origin - for (i=0 ; i<3 ; i++) - ent->origin[i] = s2->origin[i] + - f * (s1->origin[i] - s2->origin[i]); - - // add automatic particle trails - if (!model->flags) - continue; - - // scan the old entity display list for a matching - for (i=0 ; ikeynum) - { - VectorCopy (cl_oldvisedicts[i].origin, old_origin); - break; - } - } - if (i == cl_oldnumvisedicts) - continue; // not in last message - - for (i=0 ; i<3 ; i++) - if ( abs(old_origin[i] - ent->origin[i]) > 128) - { // no trail if too far - VectorCopy (ent->origin, old_origin); - break; - } - if (model->flags & EF_ROCKET) - { - R_RocketTrail (old_origin, ent->origin, 0); - dl = CL_AllocDlight (s1->number); - VectorCopy (ent->origin, dl->origin); - dl->radius = 200; - dl->die = cl.time + 0.1; - } - else if (model->flags & EF_GRENADE) - R_RocketTrail (old_origin, ent->origin, 1); - else if (model->flags & EF_GIB) - R_RocketTrail (old_origin, ent->origin, 2); - else if (model->flags & EF_ZOMGIB) - R_RocketTrail (old_origin, ent->origin, 4); - else if (model->flags & EF_TRACER) - R_RocketTrail (old_origin, ent->origin, 3); - else if (model->flags & EF_TRACER2) - R_RocketTrail (old_origin, ent->origin, 5); - else if (model->flags & EF_TRACER3) - R_RocketTrail (old_origin, ent->origin, 6); - } -} - - -/* -========================================================================= - -PROJECTILE PARSING / LINKING - -========================================================================= -*/ - -typedef struct -{ - int modelindex; - vec3_t origin; - vec3_t angles; -} projectile_t; - -#define MAX_PROJECTILES 32 -projectile_t cl_projectiles[MAX_PROJECTILES]; -int cl_num_projectiles; - -extern int cl_spikeindex; - -void CL_ClearProjectiles (void) -{ - cl_num_projectiles = 0; -} - -/* -===================== -CL_ParseProjectiles - -Nails are passed as efficient temporary entities -===================== -*/ -void CL_ParseProjectiles (void) -{ - int i, c, j; - byte bits[6]; - projectile_t *pr; - - c = MSG_ReadByte (); - for (i=0 ; imodelindex = cl_spikeindex; - pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096; - pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096; - pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096; - pr->angles[0] = 360*(bits[4]>>4)/16; - pr->angles[1] = 360*bits[5]/256; - } -} - -/* -============= -CL_LinkProjectiles - -============= -*/ -void CL_LinkProjectiles (void) -{ - int i; - projectile_t *pr; - entity_t *ent; - - for (i=0, pr=cl_projectiles ; ikeynum = 0; - - if (pr->modelindex < 1) - continue; - ent->model = cl.model_precache[pr->modelindex]; - ent->skinnum = 0; - ent->frame = 0; - ent->colormap = vid.colormap; - ent->scoreboard = NULL; - VectorCopy (pr->origin, ent->origin); - VectorCopy (pr->angles, ent->angles); - } -} - -//======================================== - -extern int cl_spikeindex, cl_playerindex, cl_flagindex; - -entity_t *CL_NewTempEntity (void); - -/* -=================== -CL_ParsePlayerinfo -=================== -*/ -extern int parsecountmod; -extern double parsecounttime; -void CL_ParsePlayerinfo (void) -{ - int msec; - int flags; - player_info_t *info; - player_state_t *state; - int num; - int i; - - num = MSG_ReadByte (); - if (num > MAX_CLIENTS) - Sys_Error ("CL_ParsePlayerinfo: bad num"); - - info = &cl.players[num]; - - state = &cl.frames[parsecountmod].playerstate[num]; - - flags = state->flags = MSG_ReadShort (); - - state->messagenum = cl.parsecount; - state->origin[0] = MSG_ReadCoord (); - state->origin[1] = MSG_ReadCoord (); - state->origin[2] = MSG_ReadCoord (); - - state->frame = MSG_ReadByte (); - - // the other player's last move was likely some time - // before the packet was sent out, so accurately track - // the exact time it was valid at - if (flags & PF_MSEC) - { - msec = MSG_ReadByte (); - state->state_time = parsecounttime - msec*0.001; - } - else - state->state_time = parsecounttime; - - if (flags & PF_COMMAND) - MSG_ReadDeltaUsercmd (&nullcmd, &state->command); - - for (i=0 ; i<3 ; i++) - { - if (flags & (PF_VELOCITY1<velocity[i] = MSG_ReadShort(); - else - state->velocity[i] = 0; - } - if (flags & PF_MODEL) - state->modelindex = MSG_ReadByte (); - else - state->modelindex = cl_playerindex; - - if (flags & PF_SKINNUM) - state->skinnum = MSG_ReadByte (); - else - state->skinnum = 0; - - if (flags & PF_EFFECTS) - state->effects = MSG_ReadByte (); - else - state->effects = 0; - - if (flags & PF_WEAPONFRAME) - state->weaponframe = MSG_ReadByte (); - else - state->weaponframe = 0; - - VectorCopy (state->command.angles, state->viewangles); -} - - -/* -================ -CL_AddFlagModels - -Called when the CTF flags are set -================ -*/ -void CL_AddFlagModels (entity_t *ent, int team) -{ - int i; - float f; - vec3_t v_forward, v_right, v_up; - entity_t *newent; - - if (cl_flagindex == -1) - return; - - f = 14; - if (ent->frame >= 29 && ent->frame <= 40) { - if (ent->frame >= 29 && ent->frame <= 34) { //axpain - if (ent->frame == 29) f = f + 2; - else if (ent->frame == 30) f = f + 8; - else if (ent->frame == 31) f = f + 12; - else if (ent->frame == 32) f = f + 11; - else if (ent->frame == 33) f = f + 10; - else if (ent->frame == 34) f = f + 4; - } else if (ent->frame >= 35 && ent->frame <= 40) { // pain - if (ent->frame == 35) f = f + 2; - else if (ent->frame == 36) f = f + 10; - else if (ent->frame == 37) f = f + 10; - else if (ent->frame == 38) f = f + 8; - else if (ent->frame == 39) f = f + 4; - else if (ent->frame == 40) f = f + 2; - } - } else if (ent->frame >= 103 && ent->frame <= 118) { - if (ent->frame >= 103 && ent->frame <= 104) f = f + 6; //nailattack - else if (ent->frame >= 105 && ent->frame <= 106) f = f + 6; //light - else if (ent->frame >= 107 && ent->frame <= 112) f = f + 7; //rocketattack - else if (ent->frame >= 112 && ent->frame <= 118) f = f + 7; //shotattack - } - - newent = CL_NewTempEntity (); - newent->model = cl.model_precache[cl_flagindex]; - newent->skinnum = team; - - AngleVectors (ent->angles, v_forward, v_right, v_up); - v_forward[2] = -v_forward[2]; // reverse z component - for (i=0 ; i<3 ; i++) - newent->origin[i] = ent->origin[i] - f*v_forward[i] + 22*v_right[i]; - newent->origin[2] -= 16; - - VectorCopy (ent->angles, newent->angles) - newent->angles[2] -= 45; -} - -/* -============= -CL_LinkPlayers - -Create visible entities in the correct position -for all current players -============= -*/ -void CL_LinkPlayers (void) -{ - int j; - player_info_t *info; - player_state_t *state; - player_state_t exact; - double playertime; - entity_t *ent; - int msec; - frame_t *frame; - int oldphysent; - - playertime = realtime - cls.latency + 0.02; - if (playertime > realtime) - playertime = realtime; - - frame = &cl.frames[cl.parsecount&UPDATE_MASK]; - - for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS - ; j++, info++, state++) - { - if (state->messagenum != cl.parsecount) - continue; // not present this frame - - // spawn light flashes, even ones coming from invisible objects -#ifdef GLQUAKE - if (!gl_flashblend.value || j != cl.playernum) { -#endif - if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) - CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3); - else if (state->effects & EF_BLUE) - CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1); - else if (state->effects & EF_RED) - CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2); - else if (state->effects & EF_BRIGHTLIGHT) - CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0); - else if (state->effects & EF_DIMLIGHT) - CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0); -#ifdef GLQUAKE - } -#endif - - // the player object never gets added - if (j == cl.playernum) - continue; - - if (!state->modelindex) - continue; - - if (!Cam_DrawPlayer(j)) - continue; - - // grab an entity to fill in - if (cl_numvisedicts == MAX_VISEDICTS) - break; // object list is full - ent = &cl_visedicts[cl_numvisedicts]; - cl_numvisedicts++; - ent->keynum = 0; - - ent->model = cl.model_precache[state->modelindex]; - ent->skinnum = state->skinnum; - ent->frame = state->frame; - ent->colormap = info->translations; - if (state->modelindex == cl_playerindex) - ent->scoreboard = info; // use custom skin - else - ent->scoreboard = NULL; - - // - // angles - // - ent->angles[PITCH] = -state->viewangles[PITCH]/3; - ent->angles[YAW] = state->viewangles[YAW]; - ent->angles[ROLL] = 0; - ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4; - - // only predict half the move to minimize overruns - msec = 500*(playertime - state->state_time); - if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value)) - { - VectorCopy (state->origin, ent->origin); -//Con_DPrintf ("nopredict\n"); - } - else - { - // predict players movement - if (msec > 255) - msec = 255; - state->command.msec = msec; -//Con_DPrintf ("predict: %i\n", msec); - - oldphysent = pmove.numphysent; - CL_SetSolidPlayers (j); - CL_PredictUsercmd (state, &exact, &state->command, false); - pmove.numphysent = oldphysent; - VectorCopy (exact.origin, ent->origin); - } - - if (state->effects & EF_FLAG1) - CL_AddFlagModels (ent, 0); - else if (state->effects & EF_FLAG2) - CL_AddFlagModels (ent, 1); - - } -} - -//====================================================================== - -/* -=============== -CL_SetSolid - -Builds all the pmove physents for the current frame -=============== -*/ -void CL_SetSolidEntities (void) -{ - int i; - frame_t *frame; - packet_entities_t *pak; - entity_state_t *state; - - pmove.physents[0].model = cl.worldmodel; - VectorCopy (vec3_origin, pmove.physents[0].origin); - pmove.physents[0].info = 0; - pmove.numphysent = 1; - - frame = &cl.frames[parsecountmod]; - pak = &frame->packet_entities; - - for (i=0 ; inum_entities ; i++) - { - state = &pak->entities[i]; - - if (!state->modelindex) - continue; - if (!cl.model_precache[state->modelindex]) - continue; - if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode - || cl.model_precache[state->modelindex]->clipbox ) - { - pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex]; - VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin); - pmove.numphysent++; - } - } - -} - -/* -=== -Calculate the new position of players, without other player clipping - -We do this to set up real player prediction. -Players are predicted twice, first without clipping other players, -then with clipping against them. -This sets up the first phase. -=== -*/ -void CL_SetUpPlayerPrediction(qboolean dopred) -{ - int j; - player_state_t *state; - player_state_t exact; - double playertime; - int msec; - frame_t *frame; - struct predicted_player *pplayer; - - playertime = realtime - cls.latency + 0.02; - if (playertime > realtime) - playertime = realtime; - - frame = &cl.frames[cl.parsecount&UPDATE_MASK]; - - for (j=0, pplayer = predicted_players, state=frame->playerstate; - j < MAX_CLIENTS; - j++, pplayer++, state++) { - - pplayer->active = false; - - if (state->messagenum != cl.parsecount) - continue; // not present this frame - - if (!state->modelindex) - continue; - - pplayer->active = true; - pplayer->flags = state->flags; - - // note that the local player is special, since he moves locally - // we use his last predicted postition - if (j == cl.playernum) { - VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin, - pplayer->origin); - } else { - // only predict half the move to minimize overruns - msec = 500*(playertime - state->state_time); - if (msec <= 0 || - (!cl_predict_players.value && !cl_predict_players2.value) || - !dopred) - { - VectorCopy (state->origin, pplayer->origin); - //Con_DPrintf ("nopredict\n"); - } - else - { - // predict players movement - if (msec > 255) - msec = 255; - state->command.msec = msec; - //Con_DPrintf ("predict: %i\n", msec); - - CL_PredictUsercmd (state, &exact, &state->command, false); - VectorCopy (exact.origin, pplayer->origin); - } - } - } -} - -/* -=============== -CL_SetSolid - -Builds all the pmove physents for the current frame -Note that CL_SetUpPlayerPrediction() must be called first! -pmove must be setup with world and solid entity hulls before calling -(via CL_PredictMove) -=============== -*/ -void CL_SetSolidPlayers (int playernum) -{ - int j; - extern vec3_t player_mins; - extern vec3_t player_maxs; - struct predicted_player *pplayer; - physent_t *pent; - - if (!cl_solid_players.value) - return; - - pent = pmove.physents + pmove.numphysent; - - for (j=0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++) { - - if (!pplayer->active) - continue; // not present this frame - - // the player object never gets added - if (j == playernum) - continue; - - if (pplayer->flags & PF_DEAD) - continue; // dead players aren't solid - - pent->model = 0; - VectorCopy(pplayer->origin, pent->origin); - VectorCopy(player_mins, pent->mins); - VectorCopy(player_maxs, pent->maxs); - pmove.numphysent++; - pent++; - } -} - - -/* -=============== -CL_EmitEntities - -Builds the visedicts array for cl.time - -Made up of: clients, packet_entities, nails, and tents -=============== -*/ -void CL_EmitEntities (void) -{ - if (cls.state != ca_active) - return; - if (!cl.validsequence) - return; - - cl_oldnumvisedicts = cl_numvisedicts; - cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1]; - cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1]; - - cl_numvisedicts = 0; - - CL_LinkPlayers (); - CL_LinkPacketEntities (); - CL_LinkProjectiles (); - CL_UpdateTEnts (); -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// cl_ents.c -- entity parsing and management + +#include "quakedef.h" + +extern cvar_t cl_predict_players; +extern cvar_t cl_predict_players2; +extern cvar_t cl_solid_players; + +static struct predicted_player { + int flags; + qboolean active; + vec3_t origin; // predicted origin +} predicted_players[MAX_CLIENTS]; + +//============================================================ + +/* +=============== +CL_AllocDlight + +=============== +*/ +dlight_t *CL_AllocDlight (int key) +{ + int i; + dlight_t *dl; + +// first look for an exact key match + if (key) + { + dl = cl_dlights; + for (i=0 ; ikey == key) + { + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; + } + } + } + +// then look for anything else + dl = cl_dlights; + for (i=0 ; idie < cl.time) + { + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; + } + } + + dl = &cl_dlights[0]; + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; +} + +/* +=============== +CL_NewDlight +=============== +*/ +void CL_NewDlight (int key, float x, float y, float z, float radius, float time, + int type) +{ + dlight_t *dl; + + dl = CL_AllocDlight (key); + dl->origin[0] = x; + dl->origin[1] = y; + dl->origin[2] = z; + dl->radius = radius; + dl->die = cl.time + time; + if (type == 0) { + dl->color[0] = 0.2; + dl->color[1] = 0.1; + dl->color[2] = 0.05; + dl->color[3] = 0.7; + } else if (type == 1) { + dl->color[0] = 0.05; + dl->color[1] = 0.05; + dl->color[2] = 0.3; + dl->color[3] = 0.7; + } else if (type == 2) { + dl->color[0] = 0.5; + dl->color[1] = 0.05; + dl->color[2] = 0.05; + dl->color[3] = 0.7; + } else if (type == 3) { + dl->color[0]=0.5; + dl->color[1] = 0.05; + dl->color[2] = 0.4; + dl->color[3] = 0.7; + } +} + + +/* +=============== +CL_DecayLights + +=============== +*/ +void CL_DecayLights (void) +{ + int i; + dlight_t *dl; + + dl = cl_dlights; + for (i=0 ; idie < cl.time || !dl->radius) + continue; + + dl->radius -= host_frametime*dl->decay; + if (dl->radius < 0) + dl->radius = 0; + } +} + + +/* +========================================================================= + +PACKET ENTITY PARSING / LINKING + +========================================================================= +*/ + +/* +================== +CL_ParseDelta + +Can go from either a baseline or a previous packet_entity +================== +*/ +int bitcounts[32]; /// just for protocol profiling +void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) +{ + int i; + + // set everything to the state we are delta'ing from + *to = *from; + + to->number = bits & 511; + bits &= ~511; + + if (bits & U_MOREBITS) + { // read in the low order bits + i = MSG_ReadByte (); + bits |= i; + } + + // count the bits for net profiling + for (i=0 ; i<16 ; i++) + if (bits&(1<flags = bits; + + if (bits & U_MODEL) + to->modelindex = MSG_ReadByte (); + + if (bits & U_FRAME) + to->frame = MSG_ReadByte (); + + if (bits & U_COLORMAP) + to->colormap = MSG_ReadByte(); + + if (bits & U_SKIN) + to->skinnum = MSG_ReadByte(); + + if (bits & U_EFFECTS) + to->effects = MSG_ReadByte(); + + if (bits & U_ORIGIN1) + to->origin[0] = MSG_ReadCoord (); + + if (bits & U_ANGLE1) + to->angles[0] = MSG_ReadAngle(); + + if (bits & U_ORIGIN2) + to->origin[1] = MSG_ReadCoord (); + + if (bits & U_ANGLE2) + to->angles[1] = MSG_ReadAngle(); + + if (bits & U_ORIGIN3) + to->origin[2] = MSG_ReadCoord (); + + if (bits & U_ANGLE3) + to->angles[2] = MSG_ReadAngle(); + + if (bits & U_SOLID) + { + // FIXME + } +} + + +/* +================= +FlushEntityPacket +================= +*/ +void FlushEntityPacket (void) +{ + int word; + entity_state_t olde, newe; + + Con_DPrintf ("FlushEntityPacket\n"); + + memset (&olde, 0, sizeof(olde)); + + cl.validsequence = 0; // can't render a frame + cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true; + + // read it all, but ignore it + while (1) + { + word = (unsigned short)MSG_ReadShort (); + if (msg_badread) + { // something didn't parse right... + Host_EndGame ("msg_badread in packetentities"); + return; + } + + if (!word) + break; // done + + CL_ParseDelta (&olde, &newe, word); + } +} + +/* +================== +CL_ParsePacketEntities + +An svc_packetentities has just been parsed, deal with the +rest of the data stream. +================== +*/ +void CL_ParsePacketEntities (qboolean delta) +{ + int oldpacket, newpacket; + packet_entities_t *oldp, *newp, dummy; + int oldindex, newindex; + int word, newnum, oldnum; + qboolean full; + byte from; + + newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; + newp = &cl.frames[newpacket].packet_entities; + cl.frames[newpacket].invalid = false; + + if (delta) + { + from = MSG_ReadByte (); + + oldpacket = cl.frames[newpacket].delta_sequence; + + if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) ) + Con_DPrintf ("WARNING: from mismatch\n"); + } + else + oldpacket = -1; + + full = false; + if (oldpacket != -1) + { + if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1) + { // we can't use this, it is too old + FlushEntityPacket (); + return; + } + cl.validsequence = cls.netchan.incoming_sequence; + oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities; + } + else + { // this is a full update that we can start delta compressing from now + oldp = &dummy; + dummy.num_entities = 0; + cl.validsequence = cls.netchan.incoming_sequence; + full = true; + } + + oldindex = 0; + newindex = 0; + newp->num_entities = 0; + + while (1) + { + word = (unsigned short)MSG_ReadShort (); + if (msg_badread) + { // something didn't parse right... + Host_EndGame ("msg_badread in packetentities"); + return; + } + + if (!word) + { + while (oldindex < oldp->num_entities) + { // copy all the rest of the entities from the old packet +//Con_Printf ("copy %i\n", oldp->entities[oldindex].number); + if (newindex >= MAX_PACKET_ENTITIES) + Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); + newp->entities[newindex] = oldp->entities[oldindex]; + newindex++; + oldindex++; + } + break; + } + newnum = word&511; + oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; + + while (newnum > oldnum) + { + if (full) + { + Con_Printf ("WARNING: oldcopy on full update"); + FlushEntityPacket (); + return; + } + +//Con_Printf ("copy %i\n", oldnum); + // copy one of the old entities over to the new packet unchanged + if (newindex >= MAX_PACKET_ENTITIES) + Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); + newp->entities[newindex] = oldp->entities[oldindex]; + newindex++; + oldindex++; + oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; + } + + if (newnum < oldnum) + { // new from baseline +//Con_Printf ("baseline %i\n", newnum); + if (word & U_REMOVE) + { + if (full) + { + cl.validsequence = 0; + Con_Printf ("WARNING: U_REMOVE on full update\n"); + FlushEntityPacket (); + return; + } + continue; + } + if (newindex >= MAX_PACKET_ENTITIES) + Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); + CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word); + newindex++; + continue; + } + + if (newnum == oldnum) + { // delta from previous + if (full) + { + cl.validsequence = 0; + Con_Printf ("WARNING: delta on full update"); + } + if (word & U_REMOVE) + { + oldindex++; + continue; + } +//Con_Printf ("delta %i\n",newnum); + CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word); + newindex++; + oldindex++; + } + + } + + newp->num_entities = newindex; +} + + +/* +=============== +CL_LinkPacketEntities + +=============== +*/ +void CL_LinkPacketEntities (void) +{ + entity_t *ent; + packet_entities_t *pack; + entity_state_t *s1, *s2; + float f; + model_t *model; + vec3_t old_origin; + float autorotate; + int i; + int pnum; + dlight_t *dl; + + pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; + + autorotate = anglemod(100*cl.time); + + f = 0; // FIXME: no interpolation right now + + for (pnum=0 ; pnumnum_entities ; pnum++) + { + s1 = &pack->entities[pnum]; + s2 = s1; // FIXME: no interpolation right now + + // spawn light flashes, even ones coming from invisible objects + if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3); + else if (s1->effects & EF_BLUE) + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1); + else if (s1->effects & EF_RED) + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2); + else if (s1->effects & EF_BRIGHTLIGHT) + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0); + else if (s1->effects & EF_DIMLIGHT) + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0); + + // if set to invisible, skip + if (!s1->modelindex) + continue; + + // create a new entity + if (cl_numvisedicts == MAX_VISEDICTS) + break; // object list is full + + ent = &cl_visedicts[cl_numvisedicts]; + cl_numvisedicts++; + + ent->keynum = s1->number; + ent->model = model = cl.model_precache[s1->modelindex]; + + // set colormap + if (s1->colormap && (s1->colormap < MAX_CLIENTS) + && !strcmp(ent->model->name,"progs/player.mdl") ) + { + ent->colormap = cl.players[s1->colormap-1].translations; + ent->scoreboard = &cl.players[s1->colormap-1]; + } + else + { + ent->colormap = vid.colormap; + ent->scoreboard = NULL; + } + + // set skin + ent->skinnum = s1->skinnum; + + // set frame + ent->frame = s1->frame; + + // rotate binary objects locally + if (model->flags & EF_ROTATE) + { + ent->angles[0] = 0; + ent->angles[1] = autorotate; + ent->angles[2] = 0; + } + else + { + float a1, a2; + + for (i=0 ; i<3 ; i++) + { + a1 = s1->angles[i]; + a2 = s2->angles[i]; + if (a1 - a2 > 180) + a1 -= 360; + if (a1 - a2 < -180) + a1 += 360; + ent->angles[i] = a2 + f * (a1 - a2); + } + } + + // calculate origin + for (i=0 ; i<3 ; i++) + ent->origin[i] = s2->origin[i] + + f * (s1->origin[i] - s2->origin[i]); + + // add automatic particle trails + if (!model->flags) + continue; + + // scan the old entity display list for a matching + for (i=0 ; ikeynum) + { + VectorCopy (cl_oldvisedicts[i].origin, old_origin); + break; + } + } + if (i == cl_oldnumvisedicts) + continue; // not in last message + + for (i=0 ; i<3 ; i++) + if ( abs(old_origin[i] - ent->origin[i]) > 128) + { // no trail if too far + VectorCopy (ent->origin, old_origin); + break; + } + if (model->flags & EF_ROCKET) + { + R_RocketTrail (old_origin, ent->origin, 0); + dl = CL_AllocDlight (s1->number); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200; + dl->die = cl.time + 0.1; + } + else if (model->flags & EF_GRENADE) + R_RocketTrail (old_origin, ent->origin, 1); + else if (model->flags & EF_GIB) + R_RocketTrail (old_origin, ent->origin, 2); + else if (model->flags & EF_ZOMGIB) + R_RocketTrail (old_origin, ent->origin, 4); + else if (model->flags & EF_TRACER) + R_RocketTrail (old_origin, ent->origin, 3); + else if (model->flags & EF_TRACER2) + R_RocketTrail (old_origin, ent->origin, 5); + else if (model->flags & EF_TRACER3) + R_RocketTrail (old_origin, ent->origin, 6); + } +} + + +/* +========================================================================= + +PROJECTILE PARSING / LINKING + +========================================================================= +*/ + +typedef struct +{ + int modelindex; + vec3_t origin; + vec3_t angles; +} projectile_t; + +#define MAX_PROJECTILES 32 +projectile_t cl_projectiles[MAX_PROJECTILES]; +int cl_num_projectiles; + +extern int cl_spikeindex; + +void CL_ClearProjectiles (void) +{ + cl_num_projectiles = 0; +} + +/* +===================== +CL_ParseProjectiles + +Nails are passed as efficient temporary entities +===================== +*/ +void CL_ParseProjectiles (void) +{ + int i, c, j; + byte bits[6]; + projectile_t *pr; + + c = MSG_ReadByte (); + for (i=0 ; imodelindex = cl_spikeindex; + pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096; + pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096; + pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096; + pr->angles[0] = 360*(bits[4]>>4)/16; + pr->angles[1] = 360*bits[5]/256; + } +} + +/* +============= +CL_LinkProjectiles + +============= +*/ +void CL_LinkProjectiles (void) +{ + int i; + projectile_t *pr; + entity_t *ent; + + for (i=0, pr=cl_projectiles ; ikeynum = 0; + + if (pr->modelindex < 1) + continue; + ent->model = cl.model_precache[pr->modelindex]; + ent->skinnum = 0; + ent->frame = 0; + ent->colormap = vid.colormap; + ent->scoreboard = NULL; + VectorCopy (pr->origin, ent->origin); + VectorCopy (pr->angles, ent->angles); + } +} + +//======================================== + +extern int cl_spikeindex, cl_playerindex, cl_flagindex; + +entity_t *CL_NewTempEntity (void); + +/* +=================== +CL_ParsePlayerinfo +=================== +*/ +extern int parsecountmod; +extern double parsecounttime; +void CL_ParsePlayerinfo (void) +{ + int msec; + int flags; + player_info_t *info; + player_state_t *state; + int num; + int i; + + num = MSG_ReadByte (); + if (num > MAX_CLIENTS) + Sys_Error ("CL_ParsePlayerinfo: bad num"); + + info = &cl.players[num]; + + state = &cl.frames[parsecountmod].playerstate[num]; + + flags = state->flags = MSG_ReadShort (); + + state->messagenum = cl.parsecount; + state->origin[0] = MSG_ReadCoord (); + state->origin[1] = MSG_ReadCoord (); + state->origin[2] = MSG_ReadCoord (); + + state->frame = MSG_ReadByte (); + + // the other player's last move was likely some time + // before the packet was sent out, so accurately track + // the exact time it was valid at + if (flags & PF_MSEC) + { + msec = MSG_ReadByte (); + state->state_time = parsecounttime - msec*0.001; + } + else + state->state_time = parsecounttime; + + if (flags & PF_COMMAND) + MSG_ReadDeltaUsercmd (&nullcmd, &state->command); + + for (i=0 ; i<3 ; i++) + { + if (flags & (PF_VELOCITY1<velocity[i] = MSG_ReadShort(); + else + state->velocity[i] = 0; + } + if (flags & PF_MODEL) + state->modelindex = MSG_ReadByte (); + else + state->modelindex = cl_playerindex; + + if (flags & PF_SKINNUM) + state->skinnum = MSG_ReadByte (); + else + state->skinnum = 0; + + if (flags & PF_EFFECTS) + state->effects = MSG_ReadByte (); + else + state->effects = 0; + + if (flags & PF_WEAPONFRAME) + state->weaponframe = MSG_ReadByte (); + else + state->weaponframe = 0; + + VectorCopy (state->command.angles, state->viewangles); +} + + +/* +================ +CL_AddFlagModels + +Called when the CTF flags are set +================ +*/ +void CL_AddFlagModels (entity_t *ent, int team) +{ + int i; + float f; + vec3_t v_forward, v_right, v_up; + entity_t *newent; + + if (cl_flagindex == -1) + return; + + f = 14; + if (ent->frame >= 29 && ent->frame <= 40) { + if (ent->frame >= 29 && ent->frame <= 34) { //axpain + if (ent->frame == 29) f = f + 2; + else if (ent->frame == 30) f = f + 8; + else if (ent->frame == 31) f = f + 12; + else if (ent->frame == 32) f = f + 11; + else if (ent->frame == 33) f = f + 10; + else if (ent->frame == 34) f = f + 4; + } else if (ent->frame >= 35 && ent->frame <= 40) { // pain + if (ent->frame == 35) f = f + 2; + else if (ent->frame == 36) f = f + 10; + else if (ent->frame == 37) f = f + 10; + else if (ent->frame == 38) f = f + 8; + else if (ent->frame == 39) f = f + 4; + else if (ent->frame == 40) f = f + 2; + } + } else if (ent->frame >= 103 && ent->frame <= 118) { + if (ent->frame >= 103 && ent->frame <= 104) f = f + 6; //nailattack + else if (ent->frame >= 105 && ent->frame <= 106) f = f + 6; //light + else if (ent->frame >= 107 && ent->frame <= 112) f = f + 7; //rocketattack + else if (ent->frame >= 112 && ent->frame <= 118) f = f + 7; //shotattack + } + + newent = CL_NewTempEntity (); + newent->model = cl.model_precache[cl_flagindex]; + newent->skinnum = team; + + AngleVectors (ent->angles, v_forward, v_right, v_up); + v_forward[2] = -v_forward[2]; // reverse z component + for (i=0 ; i<3 ; i++) + newent->origin[i] = ent->origin[i] - f*v_forward[i] + 22*v_right[i]; + newent->origin[2] -= 16; + + VectorCopy (ent->angles, newent->angles) + newent->angles[2] -= 45; +} + +/* +============= +CL_LinkPlayers + +Create visible entities in the correct position +for all current players +============= +*/ +void CL_LinkPlayers (void) +{ + int j; + player_info_t *info; + player_state_t *state; + player_state_t exact; + double playertime; + entity_t *ent; + int msec; + frame_t *frame; + int oldphysent; + + playertime = realtime - cls.latency + 0.02; + if (playertime > realtime) + playertime = realtime; + + frame = &cl.frames[cl.parsecount&UPDATE_MASK]; + + for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS + ; j++, info++, state++) + { + if (state->messagenum != cl.parsecount) + continue; // not present this frame + + // spawn light flashes, even ones coming from invisible objects +#ifdef GLQUAKE + if (!gl_flashblend.value || j != cl.playernum) { +#endif + if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) + CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3); + else if (state->effects & EF_BLUE) + CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1); + else if (state->effects & EF_RED) + CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2); + else if (state->effects & EF_BRIGHTLIGHT) + CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0); + else if (state->effects & EF_DIMLIGHT) + CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0); +#ifdef GLQUAKE + } +#endif + + // the player object never gets added + if (j == cl.playernum) + continue; + + if (!state->modelindex) + continue; + + if (!Cam_DrawPlayer(j)) + continue; + + // grab an entity to fill in + if (cl_numvisedicts == MAX_VISEDICTS) + break; // object list is full + ent = &cl_visedicts[cl_numvisedicts]; + cl_numvisedicts++; + ent->keynum = 0; + + ent->model = cl.model_precache[state->modelindex]; + ent->skinnum = state->skinnum; + ent->frame = state->frame; + ent->colormap = info->translations; + if (state->modelindex == cl_playerindex) + ent->scoreboard = info; // use custom skin + else + ent->scoreboard = NULL; + + // + // angles + // + ent->angles[PITCH] = -state->viewangles[PITCH]/3; + ent->angles[YAW] = state->viewangles[YAW]; + ent->angles[ROLL] = 0; + ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4; + + // only predict half the move to minimize overruns + msec = 500*(playertime - state->state_time); + if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value)) + { + VectorCopy (state->origin, ent->origin); +//Con_DPrintf ("nopredict\n"); + } + else + { + // predict players movement + if (msec > 255) + msec = 255; + state->command.msec = msec; +//Con_DPrintf ("predict: %i\n", msec); + + oldphysent = pmove.numphysent; + CL_SetSolidPlayers (j); + CL_PredictUsercmd (state, &exact, &state->command, false); + pmove.numphysent = oldphysent; + VectorCopy (exact.origin, ent->origin); + } + + if (state->effects & EF_FLAG1) + CL_AddFlagModels (ent, 0); + else if (state->effects & EF_FLAG2) + CL_AddFlagModels (ent, 1); + + } +} + +//====================================================================== + +/* +=============== +CL_SetSolid + +Builds all the pmove physents for the current frame +=============== +*/ +void CL_SetSolidEntities (void) +{ + int i; + frame_t *frame; + packet_entities_t *pak; + entity_state_t *state; + + pmove.physents[0].model = cl.worldmodel; + VectorCopy (vec3_origin, pmove.physents[0].origin); + pmove.physents[0].info = 0; + pmove.numphysent = 1; + + frame = &cl.frames[parsecountmod]; + pak = &frame->packet_entities; + + for (i=0 ; inum_entities ; i++) + { + state = &pak->entities[i]; + + if (!state->modelindex) + continue; + if (!cl.model_precache[state->modelindex]) + continue; + if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode + || cl.model_precache[state->modelindex]->clipbox ) + { + pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex]; + VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin); + pmove.numphysent++; + } + } + +} + +/* +=== +Calculate the new position of players, without other player clipping + +We do this to set up real player prediction. +Players are predicted twice, first without clipping other players, +then with clipping against them. +This sets up the first phase. +=== +*/ +void CL_SetUpPlayerPrediction(qboolean dopred) +{ + int j; + player_state_t *state; + player_state_t exact; + double playertime; + int msec; + frame_t *frame; + struct predicted_player *pplayer; + + playertime = realtime - cls.latency + 0.02; + if (playertime > realtime) + playertime = realtime; + + frame = &cl.frames[cl.parsecount&UPDATE_MASK]; + + for (j=0, pplayer = predicted_players, state=frame->playerstate; + j < MAX_CLIENTS; + j++, pplayer++, state++) { + + pplayer->active = false; + + if (state->messagenum != cl.parsecount) + continue; // not present this frame + + if (!state->modelindex) + continue; + + pplayer->active = true; + pplayer->flags = state->flags; + + // note that the local player is special, since he moves locally + // we use his last predicted postition + if (j == cl.playernum) { + VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin, + pplayer->origin); + } else { + // only predict half the move to minimize overruns + msec = 500*(playertime - state->state_time); + if (msec <= 0 || + (!cl_predict_players.value && !cl_predict_players2.value) || + !dopred) + { + VectorCopy (state->origin, pplayer->origin); + //Con_DPrintf ("nopredict\n"); + } + else + { + // predict players movement + if (msec > 255) + msec = 255; + state->command.msec = msec; + //Con_DPrintf ("predict: %i\n", msec); + + CL_PredictUsercmd (state, &exact, &state->command, false); + VectorCopy (exact.origin, pplayer->origin); + } + } + } +} + +/* +=============== +CL_SetSolid + +Builds all the pmove physents for the current frame +Note that CL_SetUpPlayerPrediction() must be called first! +pmove must be setup with world and solid entity hulls before calling +(via CL_PredictMove) +=============== +*/ +void CL_SetSolidPlayers (int playernum) +{ + int j; + extern vec3_t player_mins; + extern vec3_t player_maxs; + struct predicted_player *pplayer; + physent_t *pent; + + if (!cl_solid_players.value) + return; + + pent = pmove.physents + pmove.numphysent; + + for (j=0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++) { + + if (!pplayer->active) + continue; // not present this frame + + // the player object never gets added + if (j == playernum) + continue; + + if (pplayer->flags & PF_DEAD) + continue; // dead players aren't solid + + pent->model = 0; + VectorCopy(pplayer->origin, pent->origin); + VectorCopy(player_mins, pent->mins); + VectorCopy(player_maxs, pent->maxs); + pmove.numphysent++; + pent++; + } +} + + +/* +=============== +CL_EmitEntities + +Builds the visedicts array for cl.time + +Made up of: clients, packet_entities, nails, and tents +=============== +*/ +void CL_EmitEntities (void) +{ + if (cls.state != ca_active) + return; + if (!cl.validsequence) + return; + + cl_oldnumvisedicts = cl_numvisedicts; + cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1]; + cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1]; + + cl_numvisedicts = 0; + + CL_LinkPlayers (); + CL_LinkPacketEntities (); + CL_LinkProjectiles (); + CL_UpdateTEnts (); +} + diff --git a/source/cl_input.c b/source/cl_input.c index a92563f..bfff293 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // cl.input.c -- builds an intended movement command to send to the server #include "quakedef.h" @@ -387,7 +387,7 @@ void CL_SendCmd (void) int i; usercmd_t *cmd, *oldcmd; int checksumIndex; - int lost; + int lost; int seq_hash; if (cls.demoplayback) @@ -398,9 +398,9 @@ void CL_SendCmd (void) cmd = &cl.frames[i].cmd; cl.frames[i].senttime = realtime; cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet - -// seq_hash = (cls.netchan.outgoing_sequence & 0xffff) ; // ^ QW_CHECK_HASH; - seq_hash = cls.netchan.outgoing_sequence; + +// seq_hash = (cls.netchan.outgoing_sequence & 0xffff) ; // ^ QW_CHECK_HASH; + seq_hash = cls.netchan.outgoing_sequence; // get basic movement from keyboard CL_BaseMove (cmd); @@ -446,10 +446,10 @@ void CL_SendCmd (void) cmd = &cl.frames[i].cmd; MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd); - // calculate a checksum over the move commands - buf.data[checksumIndex] = COM_BlockSequenceCRCByte( - buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1, - seq_hash); + // calculate a checksum over the move commands + buf.data[checksumIndex] = COM_BlockSequenceCRCByte( + buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1, + seq_hash); // request delta compression of entities if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1) diff --git a/source/cl_main.c b/source/cl_main.c index 0e6e2a4..dfe7653 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // cl_main.c -- client main loop #include "quakedef.h" @@ -212,8 +212,8 @@ void CL_SendConnectPacket (void) connect_time = realtime+t2-t1; // for retransmit requests cls.qport = Cvar_VariableValue("qport"); - - Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING); + + Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING); // Con_Printf ("Connecting to %s...\n", cls.servername); sprintf (data, "%c%c%c%cconnect %i %i %i \"%s\"\n", @@ -1061,7 +1061,7 @@ void CL_Init (void) Info_SetValueForKey (cls.userinfo, "rate", "2500", MAX_INFO_STRING); Info_SetValueForKey (cls.userinfo, "msg", "1", MAX_INFO_STRING); sprintf (st, "%4.2f-%04d", VERSION, build_number()); - Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING); + Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING); CL_InitInput (); CL_InitTEnts (); diff --git a/source/cl_parse.c b/source/cl_parse.c index f6e28f5..267e523 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // cl_parse.c -- parse a message received from the server #include "quakedef.h" diff --git a/source/cl_pred.c b/source/cl_pred.c index eff2871..2b3d3d4 100644 --- a/source/cl_pred.c +++ b/source/cl_pred.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" #include "winquake.h" @@ -114,21 +114,21 @@ void CL_PredictMove (void) int i; float f; frame_t *from, *to = NULL; - int oldphysent; - + int oldphysent; + if (cl_pushlatency.value > 0) Cvar_Set ("pushlatency", "0"); - if (cl.paused) - return; - + if (cl.paused) + return; + cl.time = realtime - cls.latency - cl_pushlatency.value*0.001; if (cl.time > realtime) cl.time = realtime; if (cl.intermission) - return; - + return; + if (!cl.validsequence) return; @@ -140,18 +140,18 @@ void CL_PredictMove (void) // this is the last frame received from the server from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; - // we can now render a frame - if (cls.state == ca_onserver) - { // first update is the final signon stage - char text[1024]; - - cls.state = ca_active; - sprintf (text, "QuakeWorld: %s", cls.servername); -#ifdef _WIN32 - SetWindowText (mainwindow, text); -#endif - } - + // we can now render a frame + if (cls.state == ca_onserver) + { // first update is the final signon stage + char text[1024]; + + cls.state = ca_active; + sprintf (text, "QuakeWorld: %s", cls.servername); +#ifdef _WIN32 + SetWindowText (mainwindow, text); +#endif + } + if (cl_nopred.value) { VectorCopy (from->playerstate[cl.playernum].velocity, cl.simvel); @@ -160,24 +160,24 @@ void CL_PredictMove (void) } // predict forward until cl.time <= to->senttime - oldphysent = pmove.numphysent; - CL_SetSolidPlayers (cl.playernum); - -// to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; - + oldphysent = pmove.numphysent; + CL_SetSolidPlayers (cl.playernum); + +// to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; + for (i=1 ; iplayerstate[cl.playernum] - , &to->playerstate[cl.playernum], &to->cmd, cl.spectator); + , &to->playerstate[cl.playernum], &to->cmd, cl.spectator); if (to->senttime >= cl.time) break; from = to; } - - pmove.numphysent = oldphysent; - + + pmove.numphysent = oldphysent; + if (i == UPDATE_BACKUP-1 || !to) return; // net hasn't deliver packets in a long time... diff --git a/source/cl_tent.c b/source/cl_tent.c index 85b16db..2941c2f 100644 --- a/source/cl_tent.c +++ b/source/cl_tent.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // cl_tent.c -- client side temporary entities #include "quakedef.h" @@ -168,7 +168,7 @@ void CL_ParseTEnt (void) dlight_t *dl; int rnd; explosion_t *ex; - int cnt; + int cnt; type = MSG_ReadByte (); switch (type) @@ -241,10 +241,10 @@ void CL_ParseTEnt (void) dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; - dl->color[0] = 0.2; - dl->color[1] = 0.1; - dl->color[2] = 0.05; - dl->color[3] = 0.7; + dl->color[0] = 0.2; + dl->color[1] = 0.1; + dl->color[2] = 0.05; + dl->color[3] = 0.7; // sound S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); @@ -290,30 +290,30 @@ void CL_ParseTEnt (void) pos[2] = MSG_ReadCoord (); R_TeleportSplash (pos); break; - - case TE_GUNSHOT: // bullet hitting wall - cnt = MSG_ReadByte (); - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 0, 20*cnt); - break; - - case TE_BLOOD: // bullets hitting body - cnt = MSG_ReadByte (); - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 73, 20*cnt); - break; - - case TE_LIGHTNINGBLOOD: // lightning hitting body - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 225, 50); - break; - + + case TE_GUNSHOT: // bullet hitting wall + cnt = MSG_ReadByte (); + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 0, 20*cnt); + break; + + case TE_BLOOD: // bullets hitting body + cnt = MSG_ReadByte (); + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 73, 20*cnt); + break; + + case TE_LIGHTNINGBLOOD: // lightning hitting body + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 225, 50); + break; + default: Sys_Error ("CL_ParseTEnt: bad type"); } @@ -333,7 +333,7 @@ entity_t *CL_NewTempEntity (void) return NULL; ent = &cl_visedicts[cl_numvisedicts]; cl_numvisedicts++; - ent->keynum = 0; + ent->keynum = 0; memset (ent, 0, sizeof(*ent)); diff --git a/source/cmd.c b/source/cmd.c index b17520c..ab6330c 100644 --- a/source/cmd.c +++ b/source/cmd.c @@ -1,748 +1,748 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// cmd.c -- Quake script command processing module - -#include "quakedef.h" - -void Cmd_ForwardToServer (void); - -#define MAX_ALIAS_NAME 32 - -typedef struct cmdalias_s -{ - struct cmdalias_s *next; - char name[MAX_ALIAS_NAME]; - char *value; -} cmdalias_t; - -cmdalias_t *cmd_alias; - -qboolean cmd_wait; - -cvar_t cl_warncmd = {"cl_warncmd", "0"}; - -//============================================================================= - -/* -============ -Cmd_Wait_f - -Causes execution of the remainder of the command buffer to be delayed until -next frame. This allows commands like: -bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" -============ -*/ -void Cmd_Wait_f (void) -{ - cmd_wait = true; -} - -/* -============================================================================= - - COMMAND BUFFER - -============================================================================= -*/ - -sizebuf_t cmd_text; -byte cmd_text_buf[8192]; - -/* -============ -Cbuf_Init -============ -*/ -void Cbuf_Init (void) -{ - cmd_text.data = cmd_text_buf; - cmd_text.maxsize = sizeof(cmd_text_buf); -} - -/* -============ -Cbuf_AddText - -Adds command text at the end of the buffer -============ -*/ -void Cbuf_AddText (char *text) -{ - int l; - - l = Q_strlen (text); - - if (cmd_text.cursize + l >= cmd_text.maxsize) - { - Con_Printf ("Cbuf_AddText: overflow\n"); - return; - } - SZ_Write (&cmd_text, text, Q_strlen (text)); -} - - -/* -============ -Cbuf_InsertText - -Adds command text immediately after the current command -Adds a \n to the text -FIXME: actually change the command buffer to do less copying -============ -*/ -void Cbuf_InsertText (char *text) -{ - char *temp; - int templen; - -// copy off any commands still remaining in the exec buffer - templen = cmd_text.cursize; - if (templen) - { - temp = Z_Malloc (templen); - Q_memcpy (temp, cmd_text.data, templen); - SZ_Clear (&cmd_text); - } - else - temp = NULL; // shut up compiler - -// add the entire text of the file - Cbuf_AddText (text); - SZ_Write (&cmd_text, "\n", 1); -// add the copied off data - if (templen) - { - SZ_Write (&cmd_text, temp, templen); - Z_Free (temp); - } -} - -/* -============ -Cbuf_Execute -============ -*/ -void Cbuf_Execute (void) -{ - int i; - char *text; - char line[1024]; - int quotes; - - while (cmd_text.cursize) - { -// find a \n or ; line break - text = (char *)cmd_text.data; - - quotes = 0; - for (i=0 ; i< cmd_text.cursize ; i++) - { - if (text[i] == '"') - quotes++; - if ( !(quotes&1) && text[i] == ';') - break; // don't break if inside a quoted string - if (text[i] == '\n') - break; - } - - - memcpy (line, text, i); - line[i] = 0; - -// delete the text from the command buffer and move remaining commands down -// this is necessary because commands (exec, alias) can insert data at the -// beginning of the text buffer - - if (i == cmd_text.cursize) - cmd_text.cursize = 0; - else - { - i++; - cmd_text.cursize -= i; - Q_memcpy (text, text+i, cmd_text.cursize); - } - -// execute the command line - Cmd_ExecuteString (line); - - if (cmd_wait) - { // skip out while text still remains in buffer, leaving it - // for next frame - cmd_wait = false; - break; - } - } -} - -/* -============================================================================== - - SCRIPT COMMANDS - -============================================================================== -*/ - -/* -=============== -Cmd_StuffCmds_f - -Adds command line parameters as script statements -Commands lead with a +, and continue until a - or another + -quake +prog jctest.qp +cmd amlev1 -quake -nosound +cmd amlev1 -=============== -*/ -void Cmd_StuffCmds_f (void) -{ - int i, j; - int s; - char *text, *build, c; - -// build the combined string to parse from - s = 0; - for (i=1 ; i : execute a script file\n"); - return; - } - - // FIXME: is this safe freeing the hunk here??? - mark = Hunk_LowMark (); - f = (char *)COM_LoadHunkFile (Cmd_Argv(1)); - if (!f) - { - Con_Printf ("couldn't exec %s\n",Cmd_Argv(1)); - return; - } - if (!Cvar_Command () && (cl_warncmd.value || developer.value)) - Con_Printf ("execing %s\n",Cmd_Argv(1)); - - Cbuf_InsertText (f); - Hunk_FreeToLowMark (mark); -} - - -/* -=============== -Cmd_Echo_f - -Just prints the rest of the line to the console -=============== -*/ -void Cmd_Echo_f (void) -{ - int i; - - for (i=1 ; inext) - Con_Printf ("%s : %s\n", a->name, a->value); - return; - } - - s = Cmd_Argv(1); - if (strlen(s) >= MAX_ALIAS_NAME) - { - Con_Printf ("Alias name is too long\n"); - return; - } - - // if the alias allready exists, reuse it - for (a = cmd_alias ; a ; a=a->next) - { - if (!strcmp(s, a->name)) - { - Z_Free (a->value); - break; - } - } - - if (!a) - { - a = Z_Malloc (sizeof(cmdalias_t)); - a->next = cmd_alias; - cmd_alias = a; - } - strcpy (a->name, s); - -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - c = Cmd_Argc(); - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != c) - strcat (cmd, " "); - } - strcat (cmd, "\n"); - - a->value = CopyString (cmd); -} - -/* -============================================================================= - - COMMAND EXECUTION - -============================================================================= -*/ - -typedef struct cmd_function_s -{ - struct cmd_function_s *next; - char *name; - xcommand_t function; -} cmd_function_t; - - -#define MAX_ARGS 80 - -static int cmd_argc; -static char *cmd_argv[MAX_ARGS]; -static char *cmd_null_string = ""; -static char *cmd_args = NULL; - - - -static cmd_function_t *cmd_functions; // possible commands to execute - -/* -============ -Cmd_Argc -============ -*/ -int Cmd_Argc (void) -{ - return cmd_argc; -} - -/* -============ -Cmd_Argv -============ -*/ -char *Cmd_Argv (int arg) -{ - if ( arg >= cmd_argc ) - return cmd_null_string; - return cmd_argv[arg]; -} - -/* -============ -Cmd_Args - -Returns a single string containing argv(1) to argv(argc()-1) -============ -*/ -char *Cmd_Args (void) -{ - if (!cmd_args) - return ""; - return cmd_args; -} - - -/* -============ -Cmd_TokenizeString - -Parses the given string into command line tokens. -============ -*/ -void Cmd_TokenizeString (char *text) -{ - int i; - -// clear the args from the last string - for (i=0 ; inext) - { - if (!Q_strcmp (cmd_name, cmd->name)) - { - Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); - return; - } - } - - cmd = Hunk_Alloc (sizeof(cmd_function_t)); - cmd->name = cmd_name; - cmd->function = function; - cmd->next = cmd_functions; - cmd_functions = cmd; -} - -/* -============ -Cmd_Exists -============ -*/ -qboolean Cmd_Exists (char *cmd_name) -{ - cmd_function_t *cmd; - - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - { - if (!Q_strcmp (cmd_name,cmd->name)) - return true; - } - - return false; -} - - - -/* -============ -Cmd_CompleteCommand -============ -*/ -char *Cmd_CompleteCommand (char *partial) -{ - cmd_function_t *cmd; - int len; - cmdalias_t *a; - - len = Q_strlen(partial); - - if (!len) - return NULL; - -// check for exact match - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - if (!strcmp (partial,cmd->name)) - return cmd->name; - for (a=cmd_alias ; a ; a=a->next) - if (!strcmp (partial, a->name)) - return a->name; - -// check for partial match - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - if (!strncmp (partial,cmd->name, len)) - return cmd->name; - for (a=cmd_alias ; a ; a=a->next) - if (!strncmp (partial, a->name, len)) - return a->name; - - return NULL; -} - -#ifndef SERVERONLY // FIXME -/* -=================== -Cmd_ForwardToServer - -adds the current command line as a clc_stringcmd to the client message. -things like godmode, noclip, etc, are commands directed to the server, -so when they are typed in at the console, they will need to be forwarded. -=================== -*/ -void Cmd_ForwardToServer (void) -{ - if (cls.state == ca_disconnected) - { - Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); - return; - } - - if (cls.demoplayback) - return; // not really connected - - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, Cmd_Argv(0)); - if (Cmd_Argc() > 1) - { - SZ_Print (&cls.netchan.message, " "); - SZ_Print (&cls.netchan.message, Cmd_Args()); - } -} - -// don't forward the first argument -void Cmd_ForwardToServer_f (void) -{ - if (cls.state == ca_disconnected) - { - Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); - return; - } - - if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0) { - Cbuf_InsertText ("snap\n"); - return; - } - - if (cls.demoplayback) - return; // not really connected - - if (Cmd_Argc() > 1) - { - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, Cmd_Args()); - } -} -#else -void Cmd_ForwardToServer (void) -{ -} -#endif - -/* -============ -Cmd_ExecuteString - -A complete command line has been parsed, so try to execute it -FIXME: lookupnoadd the token to speed search? -============ -*/ -void Cmd_ExecuteString (char *text) -{ - cmd_function_t *cmd; - cmdalias_t *a; - - Cmd_TokenizeString (text); - -// execute the command line - if (!Cmd_Argc()) - return; // no tokens - -// check functions - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - { - if (!Q_strcasecmp (cmd_argv[0],cmd->name)) - { - if (!cmd->function) - Cmd_ForwardToServer (); - else - cmd->function (); - return; - } - } - -// check alias - for (a=cmd_alias ; a ; a=a->next) - { - if (!Q_strcasecmp (cmd_argv[0], a->name)) - { - Cbuf_InsertText (a->value); - return; - } - } - -// check cvars - if (!Cvar_Command () && (cl_warncmd.value || developer.value)) - Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); - -} - - - -/* -================ -Cmd_CheckParm - -Returns the position (1 to argc-1) in the command's argument list -where the given parameter apears, or 0 if not present -================ -*/ -int Cmd_CheckParm (char *parm) -{ - int i; - - if (!parm) - Sys_Error ("Cmd_CheckParm: NULL"); - - for (i = 1; i < Cmd_Argc (); i++) - if (! Q_strcasecmp (parm, Cmd_Argv (i))) - return i; - - return 0; -} - -/* -============ -Cmd_Init -============ -*/ -void Cmd_Init (void) -{ -// -// register our commands -// - Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f); - Cmd_AddCommand ("exec",Cmd_Exec_f); - Cmd_AddCommand ("echo",Cmd_Echo_f); - Cmd_AddCommand ("alias",Cmd_Alias_f); - Cmd_AddCommand ("wait", Cmd_Wait_f); -#ifndef SERVERONLY - Cmd_AddCommand ("cmd", Cmd_ForwardToServer_f); -#endif -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// cmd.c -- Quake script command processing module + +#include "quakedef.h" + +void Cmd_ForwardToServer (void); + +#define MAX_ALIAS_NAME 32 + +typedef struct cmdalias_s +{ + struct cmdalias_s *next; + char name[MAX_ALIAS_NAME]; + char *value; +} cmdalias_t; + +cmdalias_t *cmd_alias; + +qboolean cmd_wait; + +cvar_t cl_warncmd = {"cl_warncmd", "0"}; + +//============================================================================= + +/* +============ +Cmd_Wait_f + +Causes execution of the remainder of the command buffer to be delayed until +next frame. This allows commands like: +bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" +============ +*/ +void Cmd_Wait_f (void) +{ + cmd_wait = true; +} + +/* +============================================================================= + + COMMAND BUFFER + +============================================================================= +*/ + +sizebuf_t cmd_text; +byte cmd_text_buf[8192]; + +/* +============ +Cbuf_Init +============ +*/ +void Cbuf_Init (void) +{ + cmd_text.data = cmd_text_buf; + cmd_text.maxsize = sizeof(cmd_text_buf); +} + +/* +============ +Cbuf_AddText + +Adds command text at the end of the buffer +============ +*/ +void Cbuf_AddText (char *text) +{ + int l; + + l = Q_strlen (text); + + if (cmd_text.cursize + l >= cmd_text.maxsize) + { + Con_Printf ("Cbuf_AddText: overflow\n"); + return; + } + SZ_Write (&cmd_text, text, Q_strlen (text)); +} + + +/* +============ +Cbuf_InsertText + +Adds command text immediately after the current command +Adds a \n to the text +FIXME: actually change the command buffer to do less copying +============ +*/ +void Cbuf_InsertText (char *text) +{ + char *temp; + int templen; + +// copy off any commands still remaining in the exec buffer + templen = cmd_text.cursize; + if (templen) + { + temp = Z_Malloc (templen); + Q_memcpy (temp, cmd_text.data, templen); + SZ_Clear (&cmd_text); + } + else + temp = NULL; // shut up compiler + +// add the entire text of the file + Cbuf_AddText (text); + SZ_Write (&cmd_text, "\n", 1); +// add the copied off data + if (templen) + { + SZ_Write (&cmd_text, temp, templen); + Z_Free (temp); + } +} + +/* +============ +Cbuf_Execute +============ +*/ +void Cbuf_Execute (void) +{ + int i; + char *text; + char line[1024]; + int quotes; + + while (cmd_text.cursize) + { +// find a \n or ; line break + text = (char *)cmd_text.data; + + quotes = 0; + for (i=0 ; i< cmd_text.cursize ; i++) + { + if (text[i] == '"') + quotes++; + if ( !(quotes&1) && text[i] == ';') + break; // don't break if inside a quoted string + if (text[i] == '\n') + break; + } + + + memcpy (line, text, i); + line[i] = 0; + +// delete the text from the command buffer and move remaining commands down +// this is necessary because commands (exec, alias) can insert data at the +// beginning of the text buffer + + if (i == cmd_text.cursize) + cmd_text.cursize = 0; + else + { + i++; + cmd_text.cursize -= i; + Q_memcpy (text, text+i, cmd_text.cursize); + } + +// execute the command line + Cmd_ExecuteString (line); + + if (cmd_wait) + { // skip out while text still remains in buffer, leaving it + // for next frame + cmd_wait = false; + break; + } + } +} + +/* +============================================================================== + + SCRIPT COMMANDS + +============================================================================== +*/ + +/* +=============== +Cmd_StuffCmds_f + +Adds command line parameters as script statements +Commands lead with a +, and continue until a - or another + +quake +prog jctest.qp +cmd amlev1 +quake -nosound +cmd amlev1 +=============== +*/ +void Cmd_StuffCmds_f (void) +{ + int i, j; + int s; + char *text, *build, c; + +// build the combined string to parse from + s = 0; + for (i=1 ; i : execute a script file\n"); + return; + } + + // FIXME: is this safe freeing the hunk here??? + mark = Hunk_LowMark (); + f = (char *)COM_LoadHunkFile (Cmd_Argv(1)); + if (!f) + { + Con_Printf ("couldn't exec %s\n",Cmd_Argv(1)); + return; + } + if (!Cvar_Command () && (cl_warncmd.value || developer.value)) + Con_Printf ("execing %s\n",Cmd_Argv(1)); + + Cbuf_InsertText (f); + Hunk_FreeToLowMark (mark); +} + + +/* +=============== +Cmd_Echo_f + +Just prints the rest of the line to the console +=============== +*/ +void Cmd_Echo_f (void) +{ + int i; + + for (i=1 ; inext) + Con_Printf ("%s : %s\n", a->name, a->value); + return; + } + + s = Cmd_Argv(1); + if (strlen(s) >= MAX_ALIAS_NAME) + { + Con_Printf ("Alias name is too long\n"); + return; + } + + // if the alias allready exists, reuse it + for (a = cmd_alias ; a ; a=a->next) + { + if (!strcmp(s, a->name)) + { + Z_Free (a->value); + break; + } + } + + if (!a) + { + a = Z_Malloc (sizeof(cmdalias_t)); + a->next = cmd_alias; + cmd_alias = a; + } + strcpy (a->name, s); + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + c = Cmd_Argc(); + for (i=2 ; i< c ; i++) + { + strcat (cmd, Cmd_Argv(i)); + if (i != c) + strcat (cmd, " "); + } + strcat (cmd, "\n"); + + a->value = CopyString (cmd); +} + +/* +============================================================================= + + COMMAND EXECUTION + +============================================================================= +*/ + +typedef struct cmd_function_s +{ + struct cmd_function_s *next; + char *name; + xcommand_t function; +} cmd_function_t; + + +#define MAX_ARGS 80 + +static int cmd_argc; +static char *cmd_argv[MAX_ARGS]; +static char *cmd_null_string = ""; +static char *cmd_args = NULL; + + + +static cmd_function_t *cmd_functions; // possible commands to execute + +/* +============ +Cmd_Argc +============ +*/ +int Cmd_Argc (void) +{ + return cmd_argc; +} + +/* +============ +Cmd_Argv +============ +*/ +char *Cmd_Argv (int arg) +{ + if ( arg >= cmd_argc ) + return cmd_null_string; + return cmd_argv[arg]; +} + +/* +============ +Cmd_Args + +Returns a single string containing argv(1) to argv(argc()-1) +============ +*/ +char *Cmd_Args (void) +{ + if (!cmd_args) + return ""; + return cmd_args; +} + + +/* +============ +Cmd_TokenizeString + +Parses the given string into command line tokens. +============ +*/ +void Cmd_TokenizeString (char *text) +{ + int i; + +// clear the args from the last string + for (i=0 ; inext) + { + if (!Q_strcmp (cmd_name, cmd->name)) + { + Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); + return; + } + } + + cmd = Hunk_Alloc (sizeof(cmd_function_t)); + cmd->name = cmd_name; + cmd->function = function; + cmd->next = cmd_functions; + cmd_functions = cmd; +} + +/* +============ +Cmd_Exists +============ +*/ +qboolean Cmd_Exists (char *cmd_name) +{ + cmd_function_t *cmd; + + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + { + if (!Q_strcmp (cmd_name,cmd->name)) + return true; + } + + return false; +} + + + +/* +============ +Cmd_CompleteCommand +============ +*/ +char *Cmd_CompleteCommand (char *partial) +{ + cmd_function_t *cmd; + int len; + cmdalias_t *a; + + len = Q_strlen(partial); + + if (!len) + return NULL; + +// check for exact match + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + if (!strcmp (partial,cmd->name)) + return cmd->name; + for (a=cmd_alias ; a ; a=a->next) + if (!strcmp (partial, a->name)) + return a->name; + +// check for partial match + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + if (!strncmp (partial,cmd->name, len)) + return cmd->name; + for (a=cmd_alias ; a ; a=a->next) + if (!strncmp (partial, a->name, len)) + return a->name; + + return NULL; +} + +#ifndef SERVERONLY // FIXME +/* +=================== +Cmd_ForwardToServer + +adds the current command line as a clc_stringcmd to the client message. +things like godmode, noclip, etc, are commands directed to the server, +so when they are typed in at the console, they will need to be forwarded. +=================== +*/ +void Cmd_ForwardToServer (void) +{ + if (cls.state == ca_disconnected) + { + Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); + return; + } + + if (cls.demoplayback) + return; // not really connected + + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, Cmd_Argv(0)); + if (Cmd_Argc() > 1) + { + SZ_Print (&cls.netchan.message, " "); + SZ_Print (&cls.netchan.message, Cmd_Args()); + } +} + +// don't forward the first argument +void Cmd_ForwardToServer_f (void) +{ + if (cls.state == ca_disconnected) + { + Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); + return; + } + + if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0) { + Cbuf_InsertText ("snap\n"); + return; + } + + if (cls.demoplayback) + return; // not really connected + + if (Cmd_Argc() > 1) + { + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, Cmd_Args()); + } +} +#else +void Cmd_ForwardToServer (void) +{ +} +#endif + +/* +============ +Cmd_ExecuteString + +A complete command line has been parsed, so try to execute it +FIXME: lookupnoadd the token to speed search? +============ +*/ +void Cmd_ExecuteString (char *text) +{ + cmd_function_t *cmd; + cmdalias_t *a; + + Cmd_TokenizeString (text); + +// execute the command line + if (!Cmd_Argc()) + return; // no tokens + +// check functions + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + { + if (!Q_strcasecmp (cmd_argv[0],cmd->name)) + { + if (!cmd->function) + Cmd_ForwardToServer (); + else + cmd->function (); + return; + } + } + +// check alias + for (a=cmd_alias ; a ; a=a->next) + { + if (!Q_strcasecmp (cmd_argv[0], a->name)) + { + Cbuf_InsertText (a->value); + return; + } + } + +// check cvars + if (!Cvar_Command () && (cl_warncmd.value || developer.value)) + Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); + +} + + + +/* +================ +Cmd_CheckParm + +Returns the position (1 to argc-1) in the command's argument list +where the given parameter apears, or 0 if not present +================ +*/ +int Cmd_CheckParm (char *parm) +{ + int i; + + if (!parm) + Sys_Error ("Cmd_CheckParm: NULL"); + + for (i = 1; i < Cmd_Argc (); i++) + if (! Q_strcasecmp (parm, Cmd_Argv (i))) + return i; + + return 0; +} + +/* +============ +Cmd_Init +============ +*/ +void Cmd_Init (void) +{ +// +// register our commands +// + Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f); + Cmd_AddCommand ("exec",Cmd_Exec_f); + Cmd_AddCommand ("echo",Cmd_Echo_f); + Cmd_AddCommand ("alias",Cmd_Alias_f); + Cmd_AddCommand ("wait", Cmd_Wait_f); +#ifndef SERVERONLY + Cmd_AddCommand ("cmd", Cmd_ForwardToServer_f); +#endif +} + diff --git a/source/common.c b/source/common.c index 8fcf5d4..28f3066 100644 --- a/source/common.c +++ b/source/common.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // common.c -- misc functions used in client and server #include @@ -2173,10 +2173,6 @@ static byte chktbl[1024 + 4] = { 0x00,0x00,0x00,0x00 }; -static byte chkbuf[16 + 60 + 4]; - -static unsigned last_mapchecksum = 0; - #if 0 /* ==================== diff --git a/source/console.c b/source/console.c index ab4c402..bb8083f 100644 --- a/source/console.c +++ b/source/console.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // console.c #include "quakedef.h" diff --git a/source/crc.c b/source/crc.c index 0ce2130..a43712e 100644 --- a/source/crc.c +++ b/source/crc.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ /* crc.c */ #include "quakedef.h" @@ -85,8 +85,8 @@ unsigned short CRC_Block (byte *start, int count) unsigned short crc; CRC_Init (&crc); - while (count--) - crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++]; + while (count--) + crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++]; return crc; } diff --git a/source/cvar.c b/source/cvar.c index 96cf13b..99a9821 100644 --- a/source/cvar.c +++ b/source/cvar.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // cvar.c -- dynamic variable tracking #ifdef SERVERONLY @@ -104,10 +104,10 @@ char *Cvar_CompleteVariable (char *partial) return NULL; } - -#ifdef SERVERONLY -void SV_SendServerInfoChange(char *key, char *value); -#endif + +#ifdef SERVERONLY +void SV_SendServerInfoChange(char *key, char *value); +#endif /* ============ @@ -128,8 +128,8 @@ void Cvar_Set (char *var_name, char *value) #ifdef SERVERONLY if (var->info) { - Info_SetValueForKey (svs.info, var_name, value, MAX_SERVERINFO_STRING); - SV_SendServerInfoChange(var_name, value); + Info_SetValueForKey (svs.info, var_name, value, MAX_SERVERINFO_STRING); + SV_SendServerInfoChange(var_name, value); // SV_BroadcastCommand ("fullserverinfo \"%s\"\n", svs.info); } #else diff --git a/source/d_edge.c b/source/d_edge.c index 3c2dee8..7bd3c75 100644 --- a/source/d_edge.c +++ b/source/d_edge.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_edge.c #include "quakedef.h" @@ -34,7 +34,7 @@ extern void R_RotateBmodel (void); extern void R_TransformFrustum (void); vec3_t transformed_modelorg; - + /* ============== D_DrawPoly @@ -185,7 +185,7 @@ void D_DrawSurfaces (void) // TODO: could preset a lot of this at mode set time if (r_drawflat.value) - { + { for (s = &surfaces[1] ; sspans) @@ -201,7 +201,7 @@ void D_DrawSurfaces (void) D_DrawSolidSurface (s, (int)s->data & 0xFF); #endif D_DrawZSpans (s->spans); - } + } } else { @@ -238,7 +238,7 @@ void D_DrawSurfaces (void) D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWTURB) - { + { pface = s->data; miplevel = 0; cacheblock = (pixel_t *) @@ -260,10 +260,10 @@ void D_DrawSurfaces (void) // make entity passed in } - D_CalcGradients (pface); - - Turbulent8 (s->spans); - D_DrawZSpans (s->spans); + D_CalcGradients (pface); + + Turbulent8 (s->spans); + D_DrawZSpans (s->spans); if (s->insubmodel) { @@ -277,7 +277,7 @@ void D_DrawSurfaces (void) transformed_modelorg); VectorCopy (base_vpn, vpn); VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); + VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); R_TransformFrustum (); } @@ -325,7 +325,7 @@ void D_DrawSurfaces (void) VectorCopy (base_vpn, vpn); VectorCopy (base_vup, vup); VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); + VectorCopy (base_modelorg, modelorg); R_TransformFrustum (); currententity = &r_worldentity; } diff --git a/source/d_fill.c b/source/d_fill.c index d02a264..e6c1473 100644 --- a/source/d_fill.c +++ b/source/d_fill.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_clear: clears a specified rectangle to the specified color #include "quakedef.h" diff --git a/source/d_init.c b/source/d_init.c index 05b67f3..0d08392 100644 --- a/source/d_init.c +++ b/source/d_init.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_init.c: rasterization driver initialization #include "quakedef.h" @@ -89,7 +89,7 @@ D_EnableBackBufferAccess void D_EnableBackBufferAccess (void) { - VID_LockBuffer (); + VID_LockBuffer (); } @@ -111,7 +111,7 @@ D_DisableBackBufferAccess */ void D_DisableBackBufferAccess (void) { - VID_UnlockBuffer (); + VID_UnlockBuffer (); } @@ -127,8 +127,8 @@ void D_SetupFrame (void) if (r_dowarp) d_viewbuffer = r_warpbuffer; else - d_viewbuffer = (void *)(byte *)vid.buffer; - + d_viewbuffer = (void *)(byte *)vid.buffer; + if (r_dowarp) screenwidth = WARP_WIDTH; else diff --git a/source/d_modech.c b/source/d_modech.c index 538a737..75c188e 100644 --- a/source/d_modech.c +++ b/source/d_modech.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_modech.c: called when mode has just changed #include "quakedef.h" diff --git a/source/d_part.c b/source/d_part.c index 29755c3..176b76b 100644 --- a/source/d_part.c +++ b/source/d_part.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_part.c: software driver module for drawing particles #include "quakedef.h" diff --git a/source/d_polyse.c b/source/d_polyse.c index 4ab1674..1923968 100644 --- a/source/d_polyse.c +++ b/source/d_polyse.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_polyset.c: routines for drawing sets of polygons sharing the same // texture (used for Alias models) diff --git a/source/d_scan.c b/source/d_scan.c index 349791b..292bb56 100644 --- a/source/d_scan.c +++ b/source/d_scan.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_scan.c // // Portable C scan-level rasterization code, all pixel depths. @@ -29,7 +29,7 @@ unsigned char *r_turb_pbase, *r_turb_pdest; fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; int *r_turb_turb; int r_turb_spancount; - + void D_DrawTurbulent8Span (void); @@ -111,7 +111,7 @@ void D_DrawTurbulent8Span (void) } #endif // !id386 - + /* ============= Turbulent8 @@ -138,7 +138,7 @@ void Turbulent8 (espan_t *pspan) do { r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); + (screenwidth * pspan->v) + pspan->u); count = pspan->count; @@ -233,7 +233,7 @@ void Turbulent8 (espan_t *pspan) r_turb_s = r_turb_s & ((CYCLE<<16)-1); r_turb_t = r_turb_t & ((CYCLE<<16)-1); - + D_DrawTurbulent8Span (); r_turb_s = snext; diff --git a/source/d_sky.c b/source/d_sky.c index 2b10aed..2f77d93 100644 --- a/source/d_sky.c +++ b/source/d_sky.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_sky.c #include "quakedef.h" diff --git a/source/d_sprite.c b/source/d_sprite.c index 50d3ab6..2f02ad2 100644 --- a/source/d_sprite.c +++ b/source/d_sprite.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_sprite.c: software top-level rasterization driver module for drawing // sprites diff --git a/source/d_surf.c b/source/d_surf.c index 78a3d6e..6d8d1f7 100644 --- a/source/d_surf.c +++ b/source/d_surf.c @@ -1,338 +1,338 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// d_surf.c: rasterization driver surface heap manager - -#include "quakedef.h" -#include "d_local.h" -#include "r_local.h" - -float surfscale; -qboolean r_cache_thrash; // set if surface cache is thrashing - -int sc_size; -surfcache_t *sc_rover, *sc_base; - -#define GUARDSIZE 4 - - -int D_SurfaceCacheForRes (int width, int height) -{ - int size, pix; - - if (COM_CheckParm ("-surfcachesize")) - { - size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024; - return size; - } - - size = SURFCACHE_SIZE_AT_320X200; - - pix = width*height; - if (pix > 64000) - size += (pix-64000)*3; - - - return size; -} - -void D_CheckCacheGuard (void) -{ - byte *s; - int i; - - s = (byte *)sc_base + sc_size; - for (i=0 ; inext = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; - - D_ClearCacheGuard (); -} - - -/* -================== -D_FlushCaches -================== -*/ -void D_FlushCaches (void) -{ - surfcache_t *c; - - if (!sc_base) - return; - - for (c = sc_base ; c ; c = c->next) - { - if (c->owner) - *c->owner = NULL; - } - - sc_rover = sc_base; - sc_base->next = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; -} - -/* -================= -D_SCAlloc -================= -*/ -surfcache_t *D_SCAlloc (int width, int size) -{ - surfcache_t *new; - qboolean wrapped_this_time; - - if ((width < 0) || (width > 256)) - Sys_Error ("D_SCAlloc: bad cache width %d\n", width); - - if ((size <= 0) || (size > 0x10000)) - Sys_Error ("D_SCAlloc: bad cache size %d\n", size); - -#ifdef __alpha__ - size = (int)((long)&((surfcache_t *)0)->data[size]); -#else - size = (int)&((surfcache_t *)0)->data[size]; -#endif - size = (size + 3) & ~3; - if (size > sc_size) - Sys_Error ("D_SCAlloc: %i > cache size",size); - -// if there is not size bytes after the rover, reset to the start - wrapped_this_time = false; - - if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) - { - if (sc_rover) - { - wrapped_this_time = true; - } - sc_rover = sc_base; - } - -// colect and free surfcache_t blocks until the rover block is large enough - new = sc_rover; - if (sc_rover->owner) - *sc_rover->owner = NULL; - - while (new->size < size) - { - // free another - sc_rover = sc_rover->next; - if (!sc_rover) - Sys_Error ("D_SCAlloc: hit the end of memory"); - if (sc_rover->owner) - *sc_rover->owner = NULL; - - new->size += sc_rover->size; - new->next = sc_rover->next; - } - -// create a fragment out of any leftovers - if (new->size - size > 256) - { - sc_rover = (surfcache_t *)( (byte *)new + size); - sc_rover->size = new->size - size; - sc_rover->next = new->next; - sc_rover->width = 0; - sc_rover->owner = NULL; - new->next = sc_rover; - new->size = size; - } - else - sc_rover = new->next; - - new->width = width; -// DEBUG - if (width > 0) - new->height = (size - sizeof(*new) + sizeof(new->data)) / width; - - new->owner = NULL; // should be set properly after return - - if (d_roverwrapped) - { - if (wrapped_this_time || (sc_rover >= d_initial_rover)) - r_cache_thrash = true; - } - else if (wrapped_this_time) - { - d_roverwrapped = true; - } - -D_CheckCacheGuard (); // DEBUG - return new; -} - - -/* -================= -D_SCDump -================= -*/ -void D_SCDump (void) -{ - surfcache_t *test; - - for (test = sc_base ; test ; test = test->next) - { - if (test == sc_rover) - Sys_Printf ("ROVER:\n"); - printf ("%p : %i bytes %i width\n",test, test->size, test->width); - } -} - -//============================================================================= - -// if the num is not a power of 2, assume it will not repeat - -int MaskForNum (int num) -{ - if (num==128) - return 127; - if (num==64) - return 63; - if (num==32) - return 31; - if (num==16) - return 15; - return 255; -} - -int D_log2 (int num) -{ - int c; - - c = 0; - - while (num>>=1) - c++; - return c; -} - -//============================================================================= - -/* -================ -D_CacheSurface -================ -*/ -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) -{ - surfcache_t *cache; - -// -// if the surface is animating or flashing, flush the cache -// - r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture); - r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; - r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; - r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; - r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; - -// -// see if the cache holds apropriate data -// - cache = surface->cachespots[miplevel]; - - if (cache && !cache->dlight && surface->dlightframe != r_framecount - && cache->texture == r_drawsurf.texture - && cache->lightadj[0] == r_drawsurf.lightadj[0] - && cache->lightadj[1] == r_drawsurf.lightadj[1] - && cache->lightadj[2] == r_drawsurf.lightadj[2] - && cache->lightadj[3] == r_drawsurf.lightadj[3] ) - return cache; - -// -// determine shape of surface -// - surfscale = 1.0 / (1<extents[0] >> miplevel; - r_drawsurf.rowbytes = r_drawsurf.surfwidth; - r_drawsurf.surfheight = surface->extents[1] >> miplevel; - -// -// allocate memory if needed -// - if (!cache) // if a texture just animated, don't reallocate it - { - cache = D_SCAlloc (r_drawsurf.surfwidth, - r_drawsurf.surfwidth * r_drawsurf.surfheight); - surface->cachespots[miplevel] = cache; - cache->owner = &surface->cachespots[miplevel]; - cache->mipscale = surfscale; - } - - if (surface->dlightframe == r_framecount) - cache->dlight = 1; - else - cache->dlight = 0; - - r_drawsurf.surfdat = (pixel_t *)cache->data; - - cache->texture = r_drawsurf.texture; - cache->lightadj[0] = r_drawsurf.lightadj[0]; - cache->lightadj[1] = r_drawsurf.lightadj[1]; - cache->lightadj[2] = r_drawsurf.lightadj[2]; - cache->lightadj[3] = r_drawsurf.lightadj[3]; - -// -// draw and light the surface texture -// - r_drawsurf.surf = surface; - - c_surf++; - R_DrawSurface (); - - return surface->cachespots[miplevel]; -} - - +/* +Copyright (C) 1996-1997 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. + +*/ +// d_surf.c: rasterization driver surface heap manager + +#include "quakedef.h" +#include "d_local.h" +#include "r_local.h" + +float surfscale; +qboolean r_cache_thrash; // set if surface cache is thrashing + +int sc_size; +surfcache_t *sc_rover, *sc_base; + +#define GUARDSIZE 4 + + +int D_SurfaceCacheForRes (int width, int height) +{ + int size, pix; + + if (COM_CheckParm ("-surfcachesize")) + { + size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024; + return size; + } + + size = SURFCACHE_SIZE_AT_320X200; + + pix = width*height; + if (pix > 64000) + size += (pix-64000)*3; + + + return size; +} + +void D_CheckCacheGuard (void) +{ + byte *s; + int i; + + s = (byte *)sc_base + sc_size; + for (i=0 ; inext = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; + + D_ClearCacheGuard (); +} + + +/* +================== +D_FlushCaches +================== +*/ +void D_FlushCaches (void) +{ + surfcache_t *c; + + if (!sc_base) + return; + + for (c = sc_base ; c ; c = c->next) + { + if (c->owner) + *c->owner = NULL; + } + + sc_rover = sc_base; + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + +/* +================= +D_SCAlloc +================= +*/ +surfcache_t *D_SCAlloc (int width, int size) +{ + surfcache_t *new; + qboolean wrapped_this_time; + + if ((width < 0) || (width > 256)) + Sys_Error ("D_SCAlloc: bad cache width %d\n", width); + + if ((size <= 0) || (size > 0x10000)) + Sys_Error ("D_SCAlloc: bad cache size %d\n", size); + +#ifdef __alpha__ + size = (int)((long)&((surfcache_t *)0)->data[size]); +#else + size = (int)&((surfcache_t *)0)->data[size]; +#endif + size = (size + 3) & ~3; + if (size > sc_size) + Sys_Error ("D_SCAlloc: %i > cache size",size); + +// if there is not size bytes after the rover, reset to the start + wrapped_this_time = false; + + if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) + { + if (sc_rover) + { + wrapped_this_time = true; + } + sc_rover = sc_base; + } + +// colect and free surfcache_t blocks until the rover block is large enough + new = sc_rover; + if (sc_rover->owner) + *sc_rover->owner = NULL; + + while (new->size < size) + { + // free another + sc_rover = sc_rover->next; + if (!sc_rover) + Sys_Error ("D_SCAlloc: hit the end of memory"); + if (sc_rover->owner) + *sc_rover->owner = NULL; + + new->size += sc_rover->size; + new->next = sc_rover->next; + } + +// create a fragment out of any leftovers + if (new->size - size > 256) + { + sc_rover = (surfcache_t *)( (byte *)new + size); + sc_rover->size = new->size - size; + sc_rover->next = new->next; + sc_rover->width = 0; + sc_rover->owner = NULL; + new->next = sc_rover; + new->size = size; + } + else + sc_rover = new->next; + + new->width = width; +// DEBUG + if (width > 0) + new->height = (size - sizeof(*new) + sizeof(new->data)) / width; + + new->owner = NULL; // should be set properly after return + + if (d_roverwrapped) + { + if (wrapped_this_time || (sc_rover >= d_initial_rover)) + r_cache_thrash = true; + } + else if (wrapped_this_time) + { + d_roverwrapped = true; + } + +D_CheckCacheGuard (); // DEBUG + return new; +} + + +/* +================= +D_SCDump +================= +*/ +void D_SCDump (void) +{ + surfcache_t *test; + + for (test = sc_base ; test ; test = test->next) + { + if (test == sc_rover) + Sys_Printf ("ROVER:\n"); + printf ("%p : %i bytes %i width\n",test, test->size, test->width); + } +} + +//============================================================================= + +// if the num is not a power of 2, assume it will not repeat + +int MaskForNum (int num) +{ + if (num==128) + return 127; + if (num==64) + return 63; + if (num==32) + return 31; + if (num==16) + return 15; + return 255; +} + +int D_log2 (int num) +{ + int c; + + c = 0; + + while (num>>=1) + c++; + return c; +} + +//============================================================================= + +/* +================ +D_CacheSurface +================ +*/ +surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) +{ + surfcache_t *cache; + +// +// if the surface is animating or flashing, flush the cache +// + r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture); + r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; + r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; + r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; + r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; + +// +// see if the cache holds apropriate data +// + cache = surface->cachespots[miplevel]; + + if (cache && !cache->dlight && surface->dlightframe != r_framecount + && cache->texture == r_drawsurf.texture + && cache->lightadj[0] == r_drawsurf.lightadj[0] + && cache->lightadj[1] == r_drawsurf.lightadj[1] + && cache->lightadj[2] == r_drawsurf.lightadj[2] + && cache->lightadj[3] == r_drawsurf.lightadj[3] ) + return cache; + +// +// determine shape of surface +// + surfscale = 1.0 / (1<extents[0] >> miplevel; + r_drawsurf.rowbytes = r_drawsurf.surfwidth; + r_drawsurf.surfheight = surface->extents[1] >> miplevel; + +// +// allocate memory if needed +// + if (!cache) // if a texture just animated, don't reallocate it + { + cache = D_SCAlloc (r_drawsurf.surfwidth, + r_drawsurf.surfwidth * r_drawsurf.surfheight); + surface->cachespots[miplevel] = cache; + cache->owner = &surface->cachespots[miplevel]; + cache->mipscale = surfscale; + } + + if (surface->dlightframe == r_framecount) + cache->dlight = 1; + else + cache->dlight = 0; + + r_drawsurf.surfdat = (pixel_t *)cache->data; + + cache->texture = r_drawsurf.texture; + cache->lightadj[0] = r_drawsurf.lightadj[0]; + cache->lightadj[1] = r_drawsurf.lightadj[1]; + cache->lightadj[2] = r_drawsurf.lightadj[2]; + cache->lightadj[3] = r_drawsurf.lightadj[3]; + +// +// draw and light the surface texture +// + r_drawsurf.surf = surface; + + c_surf++; + R_DrawSurface (); + + return surface->cachespots[miplevel]; +} + + diff --git a/source/d_vars.c b/source/d_vars.c index 9769ccd..9c9805d 100644 --- a/source/d_vars.c +++ b/source/d_vars.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_vars.c: global refresh variables #if !id386 diff --git a/source/d_zpoint.c b/source/d_zpoint.c index e69ea38..909f250 100644 --- a/source/d_zpoint.c +++ b/source/d_zpoint.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // d_zpoint.c: software driver module for drawing z-buffered points #include "quakedef.h" diff --git a/source/draw.c b/source/draw.c index 3b42b67..5580214 100644 --- a/source/draw.c +++ b/source/draw.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // draw.c -- this is the only file outside the refresh that touches the // vid buffer diff --git a/source/gl_draw.c b/source/gl_draw.c index ec435ae..07d8411 100644 --- a/source/gl_draw.c +++ b/source/gl_draw.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // draw.c -- this is the only file outside the refresh that touches the // vid buffer diff --git a/source/gl_mesh.c b/source/gl_mesh.c index 6622057..553ce78 100644 --- a/source/gl_mesh.c +++ b/source/gl_mesh.c @@ -1,359 +1,359 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// gl_mesh.c: triangle model functions - -#include "quakedef.h" - -/* -================================================================= - -ALIAS MODEL DISPLAY LIST GENERATION - -================================================================= -*/ - -model_t *aliasmodel; -aliashdr_t *paliashdr; - -qboolean used[8192]; - -// the command list holds counts and s/t values that are valid for -// every frame -int commands[8192]; -int numcommands; - -// all frames will have their vertexes rearranged and expanded -// so they are in the order expected by the command list -int vertexorder[8192]; -int numorder; - -int allverts, alltris; - -int stripverts[128]; -int striptris[128]; -int stripcount; - -/* -================ -StripLength -================ -*/ -int StripLength (int starttri, int startv) -{ - int m1, m2; - int j; - mtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - stripverts[0] = last->vertindex[(startv)%3]; - stripverts[1] = last->vertindex[(startv+1)%3]; - stripverts[2] = last->vertindex[(startv+2)%3]; - - striptris[0] = starttri; - stripcount = 1; - - m1 = last->vertindex[(startv+2)%3]; - m2 = last->vertindex[(startv+1)%3]; - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) - { - if (check->facesfront != last->facesfront) - continue; - for (k=0 ; k<3 ; k++) - { - if (check->vertindex[k] != m1) - continue; - if (check->vertindex[ (k+1)%3 ] != m2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - if (stripcount & 1) - m2 = check->vertindex[ (k+2)%3 ]; - else - m1 = check->vertindex[ (k+2)%3 ]; - - stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; - striptris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) - if (used[j] == 2) - used[j] = 0; - - return stripcount; -} - -/* -=========== -FanLength -=========== -*/ -int FanLength (int starttri, int startv) -{ - int m1, m2; - int j; - mtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - stripverts[0] = last->vertindex[(startv)%3]; - stripverts[1] = last->vertindex[(startv+1)%3]; - stripverts[2] = last->vertindex[(startv+2)%3]; - - striptris[0] = starttri; - stripcount = 1; - - m1 = last->vertindex[(startv+0)%3]; - m2 = last->vertindex[(startv+2)%3]; - - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) - { - if (check->facesfront != last->facesfront) - continue; - for (k=0 ; k<3 ; k++) - { - if (check->vertindex[k] != m1) - continue; - if (check->vertindex[ (k+1)%3 ] != m2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - m2 = check->vertindex[ (k+2)%3 ]; - - stripverts[stripcount+2] = m2; - striptris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) - if (used[j] == 2) - used[j] = 0; - - return stripcount; -} - - -/* -================ -BuildTris - -Generate a list of trifans or strips -for the model, which holds for all frames -================ -*/ -void BuildTris (void) -{ - int i, j, k; - int startv; - float s, t; - int len, bestlen, besttype; - int bestverts[1024]; - int besttris[1024]; - int type; - - // - // build tristrips - // - numorder = 0; - numcommands = 0; - memset (used, 0, sizeof(used)); - for (i=0 ; inumtris ; i++) - { - // pick an unused triangle and start the trifan - if (used[i]) - continue; - - bestlen = 0; - for (type = 0 ; type < 2 ; type++) -// type = 1; - { - for (startv =0 ; startv < 3 ; startv++) - { - if (type == 1) - len = StripLength (i, startv); - else - len = FanLength (i, startv); - if (len > bestlen) - { - besttype = type; - bestlen = len; - for (j=0 ; jskinwidth / 2; // on back side - s = (s + 0.5) / pheader->skinwidth; - t = (t + 0.5) / pheader->skinheight; - - *(float *)&commands[numcommands++] = s; - *(float *)&commands[numcommands++] = t; - } - } - - commands[numcommands++] = 0; // end of list marker - - Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); - - allverts += numorder; - alltris += pheader->numtris; -} - - -/* -================ -GL_MakeAliasModelDisplayLists -================ -*/ -void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) -{ - int i, j; - int *cmds; - trivertx_t *verts; - char cache[MAX_QPATH], fullpath[MAX_OSPATH]; - FILE *f; - - aliasmodel = m; - paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); - - // - // look for a cached version - // - strcpy (cache, "glquake/"); - COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); - strcat (cache, ".ms2"); - - COM_FOpenFile (cache, &f); - if (f) - { - fread (&numcommands, 4, 1, f); - fread (&numorder, 4, 1, f); - fread (&commands, numcommands * sizeof(commands[0]), 1, f); - fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); - fclose (f); - } - else - { - // - // build it from scratch - // - Con_Printf ("meshing %s...\n",m->name); - - BuildTris (); // trifans or lists - - // - // save out the cached version - // - sprintf (fullpath, "%s/%s", com_gamedir, cache); - f = fopen (fullpath, "wb"); - if (!f) { - char gldir[MAX_OSPATH]; - - sprintf (gldir, "%s/glquake", com_gamedir); - Sys_mkdir (gldir); - f = fopen (fullpath, "wb"); - } - - if (f) - { - fwrite (&numcommands, 4, 1, f); - fwrite (&numorder, 4, 1, f); - fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); - fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); - fclose (f); - } - } - - - // save the data out - - paliashdr->poseverts = numorder; - - cmds = Hunk_Alloc (numcommands * 4); - paliashdr->commands = (byte *)cmds - (byte *)paliashdr; - memcpy (cmds, commands, numcommands * 4); - - verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts - * sizeof(trivertx_t) ); - paliashdr->posedata = (byte *)verts - (byte *)paliashdr; - for (i=0 ; inumposes ; i++) - for (j=0 ; jvertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+2)%3]; + m2 = last->vertindex[(startv+1)%3]; + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + if (stripcount & 1) + m2 = check->vertindex[ (k+2)%3 ]; + else + m1 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + +/* +=========== +FanLength +=========== +*/ +int FanLength (int starttri, int startv) +{ + int m1, m2; + int j; + mtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + stripverts[0] = last->vertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+0)%3]; + m2 = last->vertindex[(startv+2)%3]; + + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + m2 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = m2; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + + +/* +================ +BuildTris + +Generate a list of trifans or strips +for the model, which holds for all frames +================ +*/ +void BuildTris (void) +{ + int i, j, k; + int startv; + float s, t; + int len, bestlen, besttype; + int bestverts[1024]; + int besttris[1024]; + int type; + + // + // build tristrips + // + numorder = 0; + numcommands = 0; + memset (used, 0, sizeof(used)); + for (i=0 ; inumtris ; i++) + { + // pick an unused triangle and start the trifan + if (used[i]) + continue; + + bestlen = 0; + for (type = 0 ; type < 2 ; type++) +// type = 1; + { + for (startv =0 ; startv < 3 ; startv++) + { + if (type == 1) + len = StripLength (i, startv); + else + len = FanLength (i, startv); + if (len > bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; jskinwidth / 2; // on back side + s = (s + 0.5) / pheader->skinwidth; + t = (t + 0.5) / pheader->skinheight; + + *(float *)&commands[numcommands++] = s; + *(float *)&commands[numcommands++] = t; + } + } + + commands[numcommands++] = 0; // end of list marker + + Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); + + allverts += numorder; + alltris += pheader->numtris; +} + + +/* +================ +GL_MakeAliasModelDisplayLists +================ +*/ +void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) +{ + int i, j; + int *cmds; + trivertx_t *verts; + char cache[MAX_QPATH], fullpath[MAX_OSPATH]; + FILE *f; + + aliasmodel = m; + paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); + + // + // look for a cached version + // + strcpy (cache, "glquake/"); + COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); + strcat (cache, ".ms2"); + + COM_FOpenFile (cache, &f); + if (f) + { + fread (&numcommands, 4, 1, f); + fread (&numorder, 4, 1, f); + fread (&commands, numcommands * sizeof(commands[0]), 1, f); + fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); + fclose (f); + } + else + { + // + // build it from scratch + // + Con_Printf ("meshing %s...\n",m->name); + + BuildTris (); // trifans or lists + + // + // save out the cached version + // + sprintf (fullpath, "%s/%s", com_gamedir, cache); + f = fopen (fullpath, "wb"); + if (!f) { + char gldir[MAX_OSPATH]; + + sprintf (gldir, "%s/glquake", com_gamedir); + Sys_mkdir (gldir); + f = fopen (fullpath, "wb"); + } + + if (f) + { + fwrite (&numcommands, 4, 1, f); + fwrite (&numorder, 4, 1, f); + fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); + fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); + fclose (f); + } + } + + + // save the data out + + paliashdr->poseverts = numorder; + + cmds = Hunk_Alloc (numcommands * 4); + paliashdr->commands = (byte *)cmds - (byte *)paliashdr; + memcpy (cmds, commands, numcommands * 4); + + verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts + * sizeof(trivertx_t) ); + paliashdr->posedata = (byte *)verts - (byte *)paliashdr; + for (i=0 ; inumposes ; i++) + for (j=0 ; jchecksum = 0; + mod->checksum = 0; mod->checksum2 = 0; for (i = 0; i < HEADER_LUMPS; i++) { @@ -1182,11 +1182,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) continue; mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, header->lumps[i].filelen); - - if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) - continue; - mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, - header->lumps[i].filelen); + + if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) + continue; + mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, + header->lumps[i].filelen); } diff --git a/source/gl_ngraph.c b/source/gl_ngraph.c index 21e541e..29d1096 100644 --- a/source/gl_ngraph.c +++ b/source/gl_ngraph.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // gl_ngraph.c #include "quakedef.h" diff --git a/source/gl_refrag.c b/source/gl_refrag.c index c00b340..6e2e2f0 100644 --- a/source/gl_refrag.c +++ b/source/gl_refrag.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_efrag.c -#include "quakedef.h" +#include "quakedef.h" mnode_t *r_pefragtopnode; diff --git a/source/gl_rlight.c b/source/gl_rlight.c index f74a345..b2e4aff 100644 --- a/source/gl_rlight.c +++ b/source/gl_rlight.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_light.c #include "quakedef.h" diff --git a/source/gl_rmain.c b/source/gl_rmain.c index 3294abe..48a5a54 100644 --- a/source/gl_rmain.c +++ b/source/gl_rmain.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_main.c #include "quakedef.h" diff --git a/source/gl_rmisc.c b/source/gl_rmisc.c index 96798b3..e9907dd 100644 --- a/source/gl_rmisc.c +++ b/source/gl_rmisc.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_misc.c #include "quakedef.h" @@ -241,7 +241,7 @@ void R_TranslatePlayerSkin (int playernum) byte *inrow; unsigned frac, fracstep; player_info_t *player; - extern byte player_8bit_texels[320*200]; + extern byte player_8bit_texels[320*200]; char s[512]; GL_DisableMultitexture(); @@ -250,8 +250,8 @@ void R_TranslatePlayerSkin (int playernum) if (!player->name[0]) return; - strcpy(s, Info_ValueForKey(player->userinfo, "skin")); - COM_StripExtension(s, s); + strcpy(s, Info_ValueForKey(player->userinfo, "skin")); + COM_StripExtension(s, s); if (player->skin && !stricmp(s, player->skin->name)) player->skin = NULL; diff --git a/source/gl_rsurf.c b/source/gl_rsurf.c index c50aa09..c75f0d7 100644 --- a/source/gl_rsurf.c +++ b/source/gl_rsurf.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_surf.c: surface-related refresh code #include "quakedef.h" diff --git a/source/gl_screen.c b/source/gl_screen.c index df055bd..fd62cba 100644 --- a/source/gl_screen.c +++ b/source/gl_screen.c @@ -1,1188 +1,1188 @@ -/* -Copyright (C) 1996-1997 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. - -*/ - -// screen.c -- master for refresh, status bar, console, chat, notify, etc - -#include "quakedef.h" - -#include - -/* - -background clear -rendering -turtle/net/ram icons -sbar -centerprint / slow centerprint -notify lines -intermission / finale overlay -loading plaque -console -menu - -required background clears -required update regions - - -syncronous draw mode or async -One off screen buffer, with updates either copied or xblited -Need to double buffer? - - -async draw will require the refresh area to be cleared, because it will be -xblited, but sync draw can just ignore it. - -sync -draw - -CenterPrint () -SlowPrint () -Screen_Update (); -Con_Printf (); - -net -turn off messages option - -the refresh is allways rendered, unless the console is full screen - - -console is: - notify lines - half - full - - -*/ - - -int glx, gly, glwidth, glheight; - -// only the refresh window will be updated unless these variables are flagged -int scr_copytop; -int scr_copyeverything; - -float scr_con_current; -float scr_conlines; // lines of console to display - -float oldscreensize, oldfov; -cvar_t scr_viewsize = {"viewsize","100", true}; -cvar_t scr_fov = {"fov","90"}; // 10 - 170 -cvar_t scr_conspeed = {"scr_conspeed","300"}; -cvar_t scr_centertime = {"scr_centertime","2"}; -cvar_t scr_showram = {"showram","1"}; -cvar_t scr_showturtle = {"showturtle","0"}; -cvar_t scr_showpause = {"showpause","1"}; -cvar_t scr_printspeed = {"scr_printspeed","8"}; -cvar_t scr_allowsnap = {"scr_allowsnap", "1"}; -cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; -extern cvar_t crosshair; - -qboolean scr_initialized; // ready to draw - -qpic_t *scr_ram; -qpic_t *scr_net; -qpic_t *scr_turtle; - -int scr_fullupdate; - -int clearconsole; -int clearnotify; - -int sb_lines; - -viddef_t vid; // global video state - -vrect_t scr_vrect; - -qboolean scr_disabled_for_loading; -qboolean scr_drawloading; -float scr_disabled_time; - -qboolean block_drawing; - -void SCR_ScreenShot_f (void); -void SCR_RSShot_f (void); - -/* -=============================================================================== - -CENTER PRINTING - -=============================================================================== -*/ - -char scr_centerstring[1024]; -float scr_centertime_start; // for slow victory printing -float scr_centertime_off; -int scr_center_lines; -int scr_erase_lines; -int scr_erase_center; - -/* -============== -SCR_CenterPrint - -Called for important messages that should stay in the center of the screen -for a few moments -============== -*/ -void SCR_CenterPrint (char *str) -{ - strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); - scr_centertime_off = scr_centertime.value; - scr_centertime_start = cl.time; - -// count the number of lines for centering - scr_center_lines = 1; - while (*str) - { - if (*str == '\n') - scr_center_lines++; - str++; - } -} - - -void SCR_DrawCenterString (void) -{ - char *start; - int l; - int j; - int x, y; - int remaining; - -// the finale prints the characters one at a time - if (cl.intermission) - remaining = scr_printspeed.value * (cl.time - scr_centertime_start); - else - remaining = 9999; - - scr_erase_center = 0; - start = scr_centerstring; - - if (scr_center_lines <= 4) - y = vid.height*0.35; - else - y = 48; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.width - l*8)/2; - for (j=0 ; j scr_erase_lines) - scr_erase_lines = scr_center_lines; - - scr_centertime_off -= host_frametime; - - if (scr_centertime_off <= 0 && !cl.intermission) - return; - if (key_dest != key_game) - return; - - SCR_DrawCenterString (); -} - -//============================================================================= - -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) -{ - float a; - float x; - - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width/tan(fov_x/360*M_PI); - - a = atan (height/x); - - a = a*360/M_PI; - - return a; -} - -/* -================= -SCR_CalcRefdef - -Must be called whenever vid changes -Internal use only -================= -*/ -static void SCR_CalcRefdef (void) -{ - float size; - int h; - qboolean full = false; - - - scr_fullupdate = 0; // force a background redraw - vid.recalc_refdef = 0; - -// force the status bar to redraw - Sbar_Changed (); - -//======================================== - -// bound viewsize - if (scr_viewsize.value < 30) - Cvar_Set ("viewsize","30"); - if (scr_viewsize.value > 120) - Cvar_Set ("viewsize","120"); - -// bound field of view - if (scr_fov.value < 10) - Cvar_Set ("fov","10"); - if (scr_fov.value > 170) - Cvar_Set ("fov","170"); - -// intermission is always full screen - if (cl.intermission) - size = 120; - else - size = scr_viewsize.value; - - if (size >= 120) - sb_lines = 0; // no status bar at all - else if (size >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - - if (scr_viewsize.value >= 100.0) { - full = true; - size = 100.0; - } else - size = scr_viewsize.value; - if (cl.intermission) - { - full = true; - size = 100.0; - sb_lines = 0; - } - size /= 100.0; - - if (!cl_sbar.value && full) - h = vid.height; - else - h = vid.height - sb_lines; - - r_refdef.vrect.width = vid.width * size; - if (r_refdef.vrect.width < 96) - { - size = 96.0 / r_refdef.vrect.width; - r_refdef.vrect.width = 96; // min for icons - } - - r_refdef.vrect.height = vid.height * size; - if (cl_sbar.value || !full) { - if (r_refdef.vrect.height > vid.height - sb_lines) - r_refdef.vrect.height = vid.height - sb_lines; - } else if (r_refdef.vrect.height > vid.height) - r_refdef.vrect.height = vid.height; - r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; - if (full) - r_refdef.vrect.y = 0; - else - r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; - - r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); - - scr_vrect = r_refdef.vrect; -} - - -/* -================= -SCR_SizeUp_f - -Keybinding command -================= -*/ -void SCR_SizeUp_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value+10); - vid.recalc_refdef = 1; -} - - -/* -================= -SCR_SizeDown_f - -Keybinding command -================= -*/ -void SCR_SizeDown_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value-10); - vid.recalc_refdef = 1; -} - -//============================================================================ - -/* -================== -SCR_Init -================== -*/ -void SCR_Init (void) -{ - Cvar_RegisterVariable (&scr_fov); - Cvar_RegisterVariable (&scr_viewsize); - Cvar_RegisterVariable (&scr_conspeed); - Cvar_RegisterVariable (&scr_showram); - Cvar_RegisterVariable (&scr_showturtle); - Cvar_RegisterVariable (&scr_showpause); - Cvar_RegisterVariable (&scr_centertime); - Cvar_RegisterVariable (&scr_printspeed); - Cvar_RegisterVariable (&scr_allowsnap); - Cvar_RegisterVariable (&gl_triplebuffer); - -// -// register our commands -// - Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddCommand ("snap",SCR_RSShot_f); - Cmd_AddCommand ("sizeup",SCR_SizeUp_f); - Cmd_AddCommand ("sizedown",SCR_SizeDown_f); - - scr_ram = Draw_PicFromWad ("ram"); - scr_net = Draw_PicFromWad ("net"); - scr_turtle = Draw_PicFromWad ("turtle"); - - scr_initialized = true; -} - - - -/* -============== -SCR_DrawRam -============== -*/ -void SCR_DrawRam (void) -{ - if (!scr_showram.value) - return; - - if (!r_cache_thrash) - return; - - Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); -} - -/* -============== -SCR_DrawTurtle -============== -*/ -void SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle.value) - return; - - if (host_frametime < 0.1) - { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); -} - -/* -============== -SCR_DrawNet -============== -*/ -void SCR_DrawNet (void) -{ - if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) - return; - if (cls.demoplayback) - return; - - Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); -} - -void SCR_DrawFPS (void) -{ - extern cvar_t show_fps; - static double lastframetime; - double t; - extern int fps_count; - static lastfps; - int x, y; - char st[80]; - - if (!show_fps.value) - return; - - t = Sys_DoubleTime(); - if ((t - lastframetime) >= 1.0) { - lastfps = fps_count; - fps_count = 0; - lastframetime = t; - } - - sprintf(st, "%3d FPS", lastfps); - x = vid.width - strlen(st) * 8 - 8; - y = vid.height - sb_lines - 8; -// Draw_TileClear(x, y, strlen(st) * 8, 8); - Draw_String(x, y, st); -} - - -/* -============== -DrawPause -============== -*/ -void SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause.value) // turn off for screenshots - return; - - if (!cl.paused) - return; - - pic = Draw_CachePic ("gfx/pause.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); -} - - - -/* -============== -SCR_DrawLoading -============== -*/ -void SCR_DrawLoading (void) -{ - qpic_t *pic; - - if (!scr_drawloading) - return; - - pic = Draw_CachePic ("gfx/loading.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); -} - - - -//============================================================================= - - -/* -================== -SCR_SetUpToDrawConsole -================== -*/ -void SCR_SetUpToDrawConsole (void) -{ - Con_CheckResize (); - - if (scr_drawloading) - return; // never a console with loading plaque - -// decide on the height of the console - if (cls.state != ca_active) - { - scr_conlines = vid.height; // full screen - scr_con_current = scr_conlines; - } - else if (key_dest == key_console) - scr_conlines = vid.height/2; // half screen - else - scr_conlines = 0; // none visible - - if (scr_conlines < scr_con_current) - { - scr_con_current -= scr_conspeed.value*host_frametime; - if (scr_conlines > scr_con_current) - scr_con_current = scr_conlines; - - } - else if (scr_conlines > scr_con_current) - { - scr_con_current += scr_conspeed.value*host_frametime; - if (scr_conlines < scr_con_current) - scr_con_current = scr_conlines; - } - - if (clearconsole++ < vid.numpages) - { - Sbar_Changed (); - } - else if (clearnotify++ < vid.numpages) - { - } - else - con_notifylines = 0; -} - -/* -================== -SCR_DrawConsole -================== -*/ -void SCR_DrawConsole (void) -{ - if (scr_con_current) - { - scr_copyeverything = 1; - Con_DrawConsole (scr_con_current); - clearconsole = 0; - } - else - { - if (key_dest == key_game || key_dest == key_message) - Con_DrawNotify (); // only draw notify in game - } -} - - -/* -============================================================================== - - SCREEN SHOTS - -============================================================================== -*/ - -typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; -} TargaHeader; - - -/* -================== -SCR_ScreenShot_f -================== -*/ -void SCR_ScreenShot_f (void) -{ - byte *buffer; - char pcxname[80]; - char checkname[MAX_OSPATH]; - int i, c, temp; -// -// find a file name to save it to -// - strcpy(pcxname,"quake00.tga"); - - for (i=0 ; i<=99 ; i++) - { - pcxname[5] = i/10 + '0'; - pcxname[6] = i%10 + '0'; - sprintf (checkname, "%s/%s", com_gamedir, pcxname); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==100) - { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); - return; - } - - - buffer = malloc(glwidth*glheight*3 + 18); - memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type - buffer[12] = glwidth&255; - buffer[13] = glwidth>>8; - buffer[14] = glheight&255; - buffer[15] = glheight>>8; - buffer[16] = 24; // pixel size - - glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); - - // swap rgb to bgr - c = 18+glwidth*glheight*3; - for (i=18 ; imanufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = LittleShort((short)(width-1)); - pcx->ymax = LittleShort((short)(height-1)); - pcx->hres = LittleShort((short)width); - pcx->vres = LittleShort((short)height); - Q_memset (pcx->palette,0,sizeof(pcx->palette)); - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = LittleShort((short)width); - pcx->palette_type = LittleShort(2); // not a grey scale - Q_memset (pcx->filler,0,sizeof(pcx->filler)); - -// pack the image - pack = &pcx->data; - - data += rowbytes * (height - 1); - - for (i=0 ; i>4; - col = num&15; - source = draw_chars + (row<<10) + (col<<3); - - drawline = 8; - - while (drawline--) - { - for (x=0 ; x<8 ; x++) - if (source[x]) - dest[x] = source[x]; - else - dest[x] = 98; - source += 128; - dest -= width; - } - -} - -void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width) -{ - byte *dest; - const unsigned char *p; - - dest = buf + ((y * width) + x); - - p = (const unsigned char *)s; - while (*p) { - SCR_DrawCharToSnap(*p++, dest, width); - dest += 8; - } -} - - -/* -================== -SCR_RSShot_f -================== -*/ -void SCR_RSShot_f (void) -{ - int i, x, y; - unsigned char *src, *dest; - char pcxname[80]; - char checkname[MAX_OSPATH]; - unsigned char *newbuf, *srcbuf; - int srcrowbytes; - int w, h; - int dx, dy, dex, dey, nx; - int r, b, g; - int count; - float fracw, frach; - char st[80]; - time_t now; - - if (CL_IsUploading()) - return; // already one pending - - if (cls.state < ca_onserver) - return; // gotta be connected - - Con_Printf("Remote screen shot requested.\n"); - -#if 0 -// -// find a file name to save it to -// - strcpy(pcxname,"mquake00.pcx"); - - for (i=0 ; i<=99 ; i++) - { - pcxname[6] = i/10 + '0'; - pcxname[7] = i%10 + '0'; - sprintf (checkname, "%s/%s", com_gamedir, pcxname); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==100) - { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); - return; - } -#endif - -// -// save the pcx file -// - newbuf = malloc(glheight * glwidth * 3); - - glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, newbuf ); - - w = (vid.width < RSSHOT_WIDTH) ? glwidth : RSSHOT_WIDTH; - h = (vid.height < RSSHOT_HEIGHT) ? glheight : RSSHOT_HEIGHT; - - fracw = (float)glwidth / (float)w; - frach = (float)glheight / (float)h; - - for (y = 0; y < h; y++) { - dest = newbuf + (w*3 * y); - - for (x = 0; x < w; x++) { - r = g = b = 0; - - dx = x * fracw; - dex = (x + 1) * fracw; - if (dex == dx) dex++; // at least one - dy = y * frach; - dey = (y + 1) * frach; - if (dey == dy) dey++; // at least one - - count = 0; - for (/* */; dy < dey; dy++) { - src = newbuf + (glwidth * 3 * dy) + dx * 3; - for (nx = dx; nx < dex; nx++) { - r += *src++; - g += *src++; - b += *src++; - count++; - } - } - r /= count; - g /= count; - b /= count; - *dest++ = r; - *dest++ = b; - *dest++ = g; - } - } - - // convert to eight bit - for (y = 0; y < h; y++) { - src = newbuf + (w * 3 * y); - dest = newbuf + (w * y); - - for (x = 0; x < w; x++) { - *dest++ = MipColor(src[0], src[1], src[2]); - src += 3; - } - } - - time(&now); - strcpy(st, ctime(&now)); - st[strlen(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 1, w); - - strncpy(st, cls.servername, sizeof(st)); - st[sizeof(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 11, w); - - strncpy(st, name.string, sizeof(st)); - st[sizeof(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w); - - WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true); - - free(newbuf); - - Con_Printf ("Wrote %s\n", pcxname); -} - - - - -//============================================================================= - - -//============================================================================= - -char *scr_notifystring; -qboolean scr_drawdialog; - -void SCR_DrawNotifyString (void) -{ - char *start; - int l; - int j; - int x, y; - - start = scr_notifystring; - - y = vid.height*0.35; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.width - l*8)/2; - for (j=0 ; j 0) { - // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); - // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - sb_lines); - } - if (r_refdef.vrect.y > 0) { - // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); - // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - sb_lines - - (r_refdef.vrect.height + r_refdef.vrect.y)); - } -} - -float oldsbar = 0; - -/* -================== -SCR_UpdateScreen - -This is called every frame, and can also be called explicitly to flush -text to the screen. - -WARNING: be very careful calling this from elsewhere, because the refresh -needs almost the entire 256k of stack space! -================== -*/ -void SCR_UpdateScreen (void) -{ - if (block_drawing) - return; - - vid.numpages = 2 + gl_triplebuffer.value; - - scr_copytop = 0; - scr_copyeverything = 0; - - if (scr_disabled_for_loading) - { - if (realtime - scr_disabled_time > 60) - { - scr_disabled_for_loading = false; - Con_Printf ("load failed.\n"); - } - else - return; - } - - if (!scr_initialized || !con_initialized) - return; // not initialized yet - - - if (oldsbar != cl_sbar.value) { - oldsbar = cl_sbar.value; - vid.recalc_refdef = true; - } - - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); - - // - // determine size of refresh window - // - if (oldfov != scr_fov.value) - { - oldfov = scr_fov.value; - vid.recalc_refdef = true; - } - - if (vid.recalc_refdef) - SCR_CalcRefdef (); - -// -// do 3D refresh drawing, and then update the screen -// - SCR_SetUpToDrawConsole (); - - V_RenderView (); - - GL_Set2D (); - - // - // draw any areas not covered by the refresh - // - SCR_TileClear (); - - if (r_netgraph.value) - R_NetGraph (); - - if (scr_drawdialog) - { - Sbar_Draw (); - Draw_FadeScreen (); - SCR_DrawNotifyString (); - scr_copyeverything = true; - } - else if (scr_drawloading) - { - SCR_DrawLoading (); - Sbar_Draw (); - } - else if (cl.intermission == 1 && key_dest == key_game) - { - Sbar_IntermissionOverlay (); - } - else if (cl.intermission == 2 && key_dest == key_game) - { - Sbar_FinaleOverlay (); - SCR_CheckDrawCenterString (); - } - else - { - if (crosshair.value) - Draw_Crosshair(); - - SCR_DrawRam (); - SCR_DrawNet (); - SCR_DrawFPS (); - SCR_DrawTurtle (); - SCR_DrawPause (); - SCR_CheckDrawCenterString (); - Sbar_Draw (); - SCR_DrawConsole (); - M_Draw (); - } - - V_UpdatePalette (); - - GL_EndRendering (); -} +/* +Copyright (C) 1996-1997 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. + +*/ + +// screen.c -- master for refresh, status bar, console, chat, notify, etc + +#include "quakedef.h" + +#include + +/* + +background clear +rendering +turtle/net/ram icons +sbar +centerprint / slow centerprint +notify lines +intermission / finale overlay +loading plaque +console +menu + +required background clears +required update regions + + +syncronous draw mode or async +One off screen buffer, with updates either copied or xblited +Need to double buffer? + + +async draw will require the refresh area to be cleared, because it will be +xblited, but sync draw can just ignore it. + +sync +draw + +CenterPrint () +SlowPrint () +Screen_Update (); +Con_Printf (); + +net +turn off messages option + +the refresh is allways rendered, unless the console is full screen + + +console is: + notify lines + half + full + + +*/ + + +int glx, gly, glwidth, glheight; + +// only the refresh window will be updated unless these variables are flagged +int scr_copytop; +int scr_copyeverything; + +float scr_con_current; +float scr_conlines; // lines of console to display + +float oldscreensize, oldfov; +cvar_t scr_viewsize = {"viewsize","100", true}; +cvar_t scr_fov = {"fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {"scr_conspeed","300"}; +cvar_t scr_centertime = {"scr_centertime","2"}; +cvar_t scr_showram = {"showram","1"}; +cvar_t scr_showturtle = {"showturtle","0"}; +cvar_t scr_showpause = {"showpause","1"}; +cvar_t scr_printspeed = {"scr_printspeed","8"}; +cvar_t scr_allowsnap = {"scr_allowsnap", "1"}; +cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; +extern cvar_t crosshair; + +qboolean scr_initialized; // ready to draw + +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; + +int scr_fullupdate; + +int clearconsole; +int clearnotify; + +int sb_lines; + +viddef_t vid; // global video state + +vrect_t scr_vrect; + +qboolean scr_disabled_for_loading; +qboolean scr_drawloading; +float scr_disabled_time; + +qboolean block_drawing; + +void SCR_ScreenShot_f (void); +void SCR_RSShot_f (void); + +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int j; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.height*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l*8)/2; + for (j=0 ; j scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +//============================================================================= + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width/tan(fov_x/360*M_PI); + + a = atan (height/x); + + a = a*360/M_PI; + + return a; +} + +/* +================= +SCR_CalcRefdef + +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + float size; + int h; + qboolean full = false; + + + scr_fullupdate = 0; // force a background redraw + vid.recalc_refdef = 0; + +// force the status bar to redraw + Sbar_Changed (); + +//======================================== + +// bound viewsize + if (scr_viewsize.value < 30) + Cvar_Set ("viewsize","30"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + +// bound field of view + if (scr_fov.value < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + +// intermission is always full screen + if (cl.intermission) + size = 120; + else + size = scr_viewsize.value; + + if (size >= 120) + sb_lines = 0; // no status bar at all + else if (size >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + + if (scr_viewsize.value >= 100.0) { + full = true; + size = 100.0; + } else + size = scr_viewsize.value; + if (cl.intermission) + { + full = true; + size = 100.0; + sb_lines = 0; + } + size /= 100.0; + + if (!cl_sbar.value && full) + h = vid.height; + else + h = vid.height - sb_lines; + + r_refdef.vrect.width = vid.width * size; + if (r_refdef.vrect.width < 96) + { + size = 96.0 / r_refdef.vrect.width; + r_refdef.vrect.width = 96; // min for icons + } + + r_refdef.vrect.height = vid.height * size; + if (cl_sbar.value || !full) { + if (r_refdef.vrect.height > vid.height - sb_lines) + r_refdef.vrect.height = vid.height - sb_lines; + } else if (r_refdef.vrect.height > vid.height) + r_refdef.vrect.height = vid.height; + r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; + if (full) + r_refdef.vrect.y = 0; + else + r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; + + r_refdef.fov_x = scr_fov.value; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + + scr_vrect = r_refdef.vrect; +} + + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value+10); + vid.recalc_refdef = 1; +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); + vid.recalc_refdef = 1; +} + +//============================================================================ + +/* +================== +SCR_Init +================== +*/ +void SCR_Init (void) +{ + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + Cvar_RegisterVariable (&scr_allowsnap); + Cvar_RegisterVariable (&gl_triplebuffer); + +// +// register our commands +// + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("snap",SCR_RSShot_f); + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + scr_ram = Draw_PicFromWad ("ram"); + scr_net = Draw_PicFromWad ("net"); + scr_turtle = Draw_PicFromWad ("turtle"); + + scr_initialized = true; +} + + + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ + if (!scr_showram.value) + return; + + if (!r_cache_thrash) + return; + + Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle.value) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) + return; + if (cls.demoplayback) + return; + + Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); +} + +void SCR_DrawFPS (void) +{ + extern cvar_t show_fps; + static double lastframetime; + double t; + extern int fps_count; + static lastfps; + int x, y; + char st[80]; + + if (!show_fps.value) + return; + + t = Sys_DoubleTime(); + if ((t - lastframetime) >= 1.0) { + lastfps = fps_count; + fps_count = 0; + lastframetime = t; + } + + sprintf(st, "%3d FPS", lastfps); + x = vid.width - strlen(st) * 8 - 8; + y = vid.height - sb_lines - 8; +// Draw_TileClear(x, y, strlen(st) * 8, 8); + Draw_String(x, y, st); +} + + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + qpic_t *pic; + + if (!scr_showpause.value) // turn off for screenshots + return; + + if (!cl.paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp"); + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); +} + + + +/* +============== +SCR_DrawLoading +============== +*/ +void SCR_DrawLoading (void) +{ + qpic_t *pic; + + if (!scr_drawloading) + return; + + pic = Draw_CachePic ("gfx/loading.lmp"); + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); +} + + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + + if (scr_drawloading) + return; // never a console with loading plaque + +// decide on the height of the console + if (cls.state != ca_active) + { + scr_conlines = vid.height; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.height/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_frametime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_frametime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } + + if (clearconsole++ < vid.numpages) + { + Sbar_Changed (); + } + else if (clearnotify++ < vid.numpages) + { + } + else + con_notifylines = 0; +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + scr_copyeverything = 1; + Con_DrawConsole (scr_con_current); + clearconsole = 0; + } + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + +typedef struct _TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; +} TargaHeader; + + +/* +================== +SCR_ScreenShot_f +================== +*/ +void SCR_ScreenShot_f (void) +{ + byte *buffer; + char pcxname[80]; + char checkname[MAX_OSPATH]; + int i, c, temp; +// +// find a file name to save it to +// + strcpy(pcxname,"quake00.tga"); + + for (i=0 ; i<=99 ; i++) + { + pcxname[5] = i/10 + '0'; + pcxname[6] = i%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, pcxname); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==100) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); + return; + } + + + buffer = malloc(glwidth*glheight*3 + 18); + memset (buffer, 0, 18); + buffer[2] = 2; // uncompressed type + buffer[12] = glwidth&255; + buffer[13] = glwidth>>8; + buffer[14] = glheight&255; + buffer[15] = glheight>>8; + buffer[16] = 24; // pixel size + + glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); + + // swap rgb to bgr + c = 18+glwidth*glheight*3; + for (i=18 ; imanufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort((short)(width-1)); + pcx->ymax = LittleShort((short)(height-1)); + pcx->hres = LittleShort((short)width); + pcx->vres = LittleShort((short)height); + Q_memset (pcx->palette,0,sizeof(pcx->palette)); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort((short)width); + pcx->palette_type = LittleShort(2); // not a grey scale + Q_memset (pcx->filler,0,sizeof(pcx->filler)); + +// pack the image + pack = &pcx->data; + + data += rowbytes * (height - 1); + + for (i=0 ; i>4; + col = num&15; + source = draw_chars + (row<<10) + (col<<3); + + drawline = 8; + + while (drawline--) + { + for (x=0 ; x<8 ; x++) + if (source[x]) + dest[x] = source[x]; + else + dest[x] = 98; + source += 128; + dest -= width; + } + +} + +void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width) +{ + byte *dest; + const unsigned char *p; + + dest = buf + ((y * width) + x); + + p = (const unsigned char *)s; + while (*p) { + SCR_DrawCharToSnap(*p++, dest, width); + dest += 8; + } +} + + +/* +================== +SCR_RSShot_f +================== +*/ +void SCR_RSShot_f (void) +{ + int i, x, y; + unsigned char *src, *dest; + char pcxname[80]; + char checkname[MAX_OSPATH]; + unsigned char *newbuf, *srcbuf; + int srcrowbytes; + int w, h; + int dx, dy, dex, dey, nx; + int r, b, g; + int count; + float fracw, frach; + char st[80]; + time_t now; + + if (CL_IsUploading()) + return; // already one pending + + if (cls.state < ca_onserver) + return; // gotta be connected + + Con_Printf("Remote screen shot requested.\n"); + +#if 0 +// +// find a file name to save it to +// + strcpy(pcxname,"mquake00.pcx"); + + for (i=0 ; i<=99 ; i++) + { + pcxname[6] = i/10 + '0'; + pcxname[7] = i%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, pcxname); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==100) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); + return; + } +#endif + +// +// save the pcx file +// + newbuf = malloc(glheight * glwidth * 3); + + glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, newbuf ); + + w = (vid.width < RSSHOT_WIDTH) ? glwidth : RSSHOT_WIDTH; + h = (vid.height < RSSHOT_HEIGHT) ? glheight : RSSHOT_HEIGHT; + + fracw = (float)glwidth / (float)w; + frach = (float)glheight / (float)h; + + for (y = 0; y < h; y++) { + dest = newbuf + (w*3 * y); + + for (x = 0; x < w; x++) { + r = g = b = 0; + + dx = x * fracw; + dex = (x + 1) * fracw; + if (dex == dx) dex++; // at least one + dy = y * frach; + dey = (y + 1) * frach; + if (dey == dy) dey++; // at least one + + count = 0; + for (/* */; dy < dey; dy++) { + src = newbuf + (glwidth * 3 * dy) + dx * 3; + for (nx = dx; nx < dex; nx++) { + r += *src++; + g += *src++; + b += *src++; + count++; + } + } + r /= count; + g /= count; + b /= count; + *dest++ = r; + *dest++ = b; + *dest++ = g; + } + } + + // convert to eight bit + for (y = 0; y < h; y++) { + src = newbuf + (w * 3 * y); + dest = newbuf + (w * y); + + for (x = 0; x < w; x++) { + *dest++ = MipColor(src[0], src[1], src[2]); + src += 3; + } + } + + time(&now); + strcpy(st, ctime(&now)); + st[strlen(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 1, w); + + strncpy(st, cls.servername, sizeof(st)); + st[sizeof(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 11, w); + + strncpy(st, name.string, sizeof(st)); + st[sizeof(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w); + + WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true); + + free(newbuf); + + Con_Printf ("Wrote %s\n", pcxname); +} + + + + +//============================================================================= + + +//============================================================================= + +char *scr_notifystring; +qboolean scr_drawdialog; + +void SCR_DrawNotifyString (void) +{ + char *start; + int l; + int j; + int x, y; + + start = scr_notifystring; + + y = vid.height*0.35; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l*8)/2; + for (j=0 ; j 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - sb_lines); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - sb_lines - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } +} + +float oldsbar = 0; + +/* +================== +SCR_UpdateScreen + +This is called every frame, and can also be called explicitly to flush +text to the screen. + +WARNING: be very careful calling this from elsewhere, because the refresh +needs almost the entire 256k of stack space! +================== +*/ +void SCR_UpdateScreen (void) +{ + if (block_drawing) + return; + + vid.numpages = 2 + gl_triplebuffer.value; + + scr_copytop = 0; + scr_copyeverything = 0; + + if (scr_disabled_for_loading) + { + if (realtime - scr_disabled_time > 60) + { + scr_disabled_for_loading = false; + Con_Printf ("load failed.\n"); + } + else + return; + } + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + + if (oldsbar != cl_sbar.value) { + oldsbar = cl_sbar.value; + vid.recalc_refdef = true; + } + + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + + // + // determine size of refresh window + // + if (oldfov != scr_fov.value) + { + oldfov = scr_fov.value; + vid.recalc_refdef = true; + } + + if (vid.recalc_refdef) + SCR_CalcRefdef (); + +// +// do 3D refresh drawing, and then update the screen +// + SCR_SetUpToDrawConsole (); + + V_RenderView (); + + GL_Set2D (); + + // + // draw any areas not covered by the refresh + // + SCR_TileClear (); + + if (r_netgraph.value) + R_NetGraph (); + + if (scr_drawdialog) + { + Sbar_Draw (); + Draw_FadeScreen (); + SCR_DrawNotifyString (); + scr_copyeverything = true; + } + else if (scr_drawloading) + { + SCR_DrawLoading (); + Sbar_Draw (); + } + else if (cl.intermission == 1 && key_dest == key_game) + { + Sbar_IntermissionOverlay (); + } + else if (cl.intermission == 2 && key_dest == key_game) + { + Sbar_FinaleOverlay (); + SCR_CheckDrawCenterString (); + } + else + { + if (crosshair.value) + Draw_Crosshair(); + + SCR_DrawRam (); + SCR_DrawNet (); + SCR_DrawFPS (); + SCR_DrawTurtle (); + SCR_DrawPause (); + SCR_CheckDrawCenterString (); + Sbar_Draw (); + SCR_DrawConsole (); + M_Draw (); + } + + V_UpdatePalette (); + + GL_EndRendering (); +} diff --git a/source/gl_test.c b/source/gl_test.c index c646a7b..a3b1027 100644 --- a/source/gl_test.c +++ b/source/gl_test.c @@ -1,182 +1,182 @@ -/* -Copyright (C) 1996-1997 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 "quakedef.h" - -#ifdef GLTEST - -typedef struct -{ - plane_t *plane; - vec3_t origin; - vec3_t normal; - vec3_t up; - vec3_t right; - vec3_t reflect; - float length; -} puff_t; - -#define MAX_PUFFS 64 - -puff_t puffs[MAX_PUFFS]; - - -void Test_Init (void) -{ -} - - - -plane_t junk; -plane_t *HitPlane (vec3_t start, vec3_t end) -{ - trace_t trace; - -// fill in a default trace - memset (&trace, 0, sizeof(trace_t)); - trace.fraction = 1; - trace.allsolid = true; - VectorCopy (end, trace.endpos); - - SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); - - junk = trace.plane; - return &junk; -} - -void Test_Spawn (vec3_t origin) -{ - int i; - puff_t *p; - vec3_t temp; - vec3_t normal; - vec3_t incoming; - plane_t *plane; - float d; - - for (i=0,p=puffs ; ilength <= 0) - break; - } - if (i == MAX_PUFFS) - return; - - VectorSubtract (r_refdef.vieworg, origin, incoming); - VectorSubtract (origin, incoming, temp); - plane = HitPlane (r_refdef.vieworg, temp); - - VectorNormalize (incoming); - d = DotProduct (incoming, plane->normal); - VectorSubtract (vec3_origin, incoming, p->reflect); - VectorMA (p->reflect, d*2, plane->normal, p->reflect); - - VectorCopy (origin, p->origin); - VectorCopy (plane->normal, p->normal); - - CrossProduct (incoming, p->normal, p->up); - - CrossProduct (p->up, p->normal, p->right); - - p->length = 8; -} - -void DrawPuff (puff_t *p) -{ - vec3_t pts[2][3]; - int i, j; - float s, d; - - for (i=0 ; i<2 ; i++) - { - if (i == 1) - { - s = 6; - d = p->length; - } - else - { - s = 2; - d = 0; - } - - for (j=0 ; j<3 ; j++) - { - pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d; - pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d; - pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d; - } - } - - glColor3f (1, 0, 0); - -#if 0 - glBegin (GL_LINES); - glVertex3fv (p->origin); - glVertex3f (p->origin[0] + p->length*p->reflect[0], - p->origin[1] + p->length*p->reflect[1], - p->origin[2] + p->length*p->reflect[2]); - - glVertex3fv (pts[0][0]); - glVertex3fv (pts[1][0]); - - glVertex3fv (pts[0][1]); - glVertex3fv (pts[1][1]); - - glVertex3fv (pts[0][2]); - glVertex3fv (pts[1][2]); - - glEnd (); -#endif - - glBegin (GL_QUADS); - for (i=0 ; i<3 ; i++) - { - j = (i+1)%3; - glVertex3fv (pts[0][j]); - glVertex3fv (pts[1][j]); - glVertex3fv (pts[1][i]); - glVertex3fv (pts[0][i]); - } - glEnd (); - - glBegin (GL_TRIANGLES); - glVertex3fv (pts[1][0]); - glVertex3fv (pts[1][1]); - glVertex3fv (pts[1][2]); - glEnd (); - - p->length -= host_frametime*2; -} - - -void Test_Draw (void) -{ - int i; - puff_t *p; - - for (i=0, p=puffs ; ilength > 0) - DrawPuff (p); - } -} - -#endif +/* +Copyright (C) 1996-1997 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 "quakedef.h" + +#ifdef GLTEST + +typedef struct +{ + plane_t *plane; + vec3_t origin; + vec3_t normal; + vec3_t up; + vec3_t right; + vec3_t reflect; + float length; +} puff_t; + +#define MAX_PUFFS 64 + +puff_t puffs[MAX_PUFFS]; + + +void Test_Init (void) +{ +} + + + +plane_t junk; +plane_t *HitPlane (vec3_t start, vec3_t end) +{ + trace_t trace; + +// fill in a default trace + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + trace.allsolid = true; + VectorCopy (end, trace.endpos); + + SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); + + junk = trace.plane; + return &junk; +} + +void Test_Spawn (vec3_t origin) +{ + int i; + puff_t *p; + vec3_t temp; + vec3_t normal; + vec3_t incoming; + plane_t *plane; + float d; + + for (i=0,p=puffs ; ilength <= 0) + break; + } + if (i == MAX_PUFFS) + return; + + VectorSubtract (r_refdef.vieworg, origin, incoming); + VectorSubtract (origin, incoming, temp); + plane = HitPlane (r_refdef.vieworg, temp); + + VectorNormalize (incoming); + d = DotProduct (incoming, plane->normal); + VectorSubtract (vec3_origin, incoming, p->reflect); + VectorMA (p->reflect, d*2, plane->normal, p->reflect); + + VectorCopy (origin, p->origin); + VectorCopy (plane->normal, p->normal); + + CrossProduct (incoming, p->normal, p->up); + + CrossProduct (p->up, p->normal, p->right); + + p->length = 8; +} + +void DrawPuff (puff_t *p) +{ + vec3_t pts[2][3]; + int i, j; + float s, d; + + for (i=0 ; i<2 ; i++) + { + if (i == 1) + { + s = 6; + d = p->length; + } + else + { + s = 2; + d = 0; + } + + for (j=0 ; j<3 ; j++) + { + pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d; + pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d; + pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d; + } + } + + glColor3f (1, 0, 0); + +#if 0 + glBegin (GL_LINES); + glVertex3fv (p->origin); + glVertex3f (p->origin[0] + p->length*p->reflect[0], + p->origin[1] + p->length*p->reflect[1], + p->origin[2] + p->length*p->reflect[2]); + + glVertex3fv (pts[0][0]); + glVertex3fv (pts[1][0]); + + glVertex3fv (pts[0][1]); + glVertex3fv (pts[1][1]); + + glVertex3fv (pts[0][2]); + glVertex3fv (pts[1][2]); + + glEnd (); +#endif + + glBegin (GL_QUADS); + for (i=0 ; i<3 ; i++) + { + j = (i+1)%3; + glVertex3fv (pts[0][j]); + glVertex3fv (pts[1][j]); + glVertex3fv (pts[1][i]); + glVertex3fv (pts[0][i]); + } + glEnd (); + + glBegin (GL_TRIANGLES); + glVertex3fv (pts[1][0]); + glVertex3fv (pts[1][1]); + glVertex3fv (pts[1][2]); + glEnd (); + + p->length -= host_frametime*2; +} + + +void Test_Draw (void) +{ + int i; + puff_t *p; + + for (i=0, p=puffs ; ilength > 0) + DrawPuff (p); + } +} + +#endif diff --git a/source/gl_vidlinux.c b/source/gl_vidlinux.c index 6f6e966..b3f38fe 100644 --- a/source/gl_vidlinux.c +++ b/source/gl_vidlinux.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include #include diff --git a/source/gl_vidlinux_svga.c b/source/gl_vidlinux_svga.c index 783fbf2..697ef02 100644 --- a/source/gl_vidlinux_svga.c +++ b/source/gl_vidlinux_svga.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include #include diff --git a/source/gl_vidlinux_x11.c b/source/gl_vidlinux_x11.c index 6dd7e3e..f885381 100644 --- a/source/gl_vidlinux_x11.c +++ b/source/gl_vidlinux_x11.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include #include diff --git a/source/gl_vidlinuxglx.c b/source/gl_vidlinuxglx.c index e3a7cd2..96da029 100644 --- a/source/gl_vidlinuxglx.c +++ b/source/gl_vidlinuxglx.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include #include diff --git a/source/gl_vidnt.c b/source/gl_vidnt.c index 4516e1e..932a68d 100644 --- a/source/gl_vidnt.c +++ b/source/gl_vidnt.c @@ -1,1949 +1,1949 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// gl_vidnt.c -- NT GL vid component - -#include "quakedef.h" -#include "winquake.h" -#include "resource.h" -#include - -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 -#define WARP_WIDTH 320 -#define WARP_HEIGHT 200 -#define MAXWIDTH 10000 -#define MAXHEIGHT 10000 -#define BASEWIDTH 320 -#define BASEHEIGHT 200 - -#define MODE_WINDOWED 0 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1) - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int dib; - int fullscreen; - int bpp; - int halfscreen; - char modedesc[17]; -} vmode_t; - -typedef struct { - int width; - int height; -} lmode_t; - -lmode_t lowresmodes[] = { - {320, 200}, - {320, 240}, - {400, 300}, - {512, 384}, -}; - -const char *gl_vendor; -const char *gl_renderer; -const char *gl_version; -const char *gl_extensions; - -qboolean DDActive; -qboolean scr_skipupdate; - -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; -static vmode_t *pcurrentmode; -static vmode_t badmode; - -static DEVMODE gdevmode; -static qboolean vid_initialized = false; -static qboolean windowed, leavecurrentmode; -static qboolean vid_canalttab = false; -static qboolean vid_wassuspended = false; -static int windowed_mouse; -extern qboolean mouseactive; // from in_win.c -static HICON hIcon; - -int DIBWidth, DIBHeight; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -HWND mainwindow, dibwindow; - -int vid_modenum = NO_MODE; -int vid_realmode; -int vid_default = MODE_WINDOWED; -static int windowed_default; -unsigned char vid_curpal[256*3]; -static qboolean fullsbardraw = false; - -static float vid_gamma = 1.0; - -HGLRC baseRC; -HDC maindc; - -glvert_t glv; - -cvar_t gl_ztrick = {"gl_ztrick","1"}; - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -viddef_t vid; // global video state - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; -unsigned char d_15to8table[65536]; - -float gldepthmin, gldepthmax; - -modestate_t modestate = MS_UNINIT; - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate(BOOL fActive, BOOL minimize); -char *VID_GetModeDescription (int mode); -void ClearAllStates (void); -void VID_UpdateWindowStatus (void); -void GL_Init (void); - -PROC glArrayElementEXT; -PROC glColorPointerEXT; -PROC glTexCoordPointerEXT; -PROC glVertexPointerEXT; - -typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*); -lp3DFXFUNC glColorTableEXT; -qboolean is8bit = false; -qboolean isPermedia = false; -qboolean gl_mtexable = false; - -//==================================== - -cvar_t vid_mode = {"vid_mode","0", false}; -// Note that 0 is MODE_WINDOWED -cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; -// Note that 3 is MODE_FULLSCREEN_DEFAULT -cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; -cvar_t vid_wait = {"vid_wait","0"}; -cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; -cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; -cvar_t vid_config_x = {"vid_config_x","800", true}; -cvar_t vid_config_y = {"vid_config_y","600", true}; -cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; -cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; - -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -// direct draw software compatability stuff - -void VID_HandlePause (qboolean pause) -{ -} - -void VID_ForceLockState (int lk) -{ -} - -void VID_LockBuffer (void) -{ -} - -void VID_UnlockBuffer (void) -{ -} - -int VID_ForceUnlockedAndReturnState (void) -{ - return 0; -} - -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ -} - -void D_EndDirectRect (int x, int y, int width, int height) -{ -} - - -void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify) -{ - RECT rect; - int CenterX, CenterY; - - CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; - CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; - if (CenterX > CenterY*2) - CenterX >>= 1; // dual screens - CenterX = (CenterX < 0) ? 0: CenterX; - CenterY = (CenterY < 0) ? 0: CenterY; - SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); -} - -qboolean VID_SetWindowedMode (int modenum) -{ - HDC hdc; - int lastmodestate, width, height; - RECT rect; - - lastmodestate = modestate; - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX; - ExWindowStyle = 0; - - rect = WindowRect; - AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the DIB window - dibwindow = CreateWindowEx ( - ExWindowStyle, - "WinQuake", - "GLQuake", - WindowStyle, - rect.left, rect.top, - width, - height, - NULL, - NULL, - global_hInstance, - NULL); - - if (!dibwindow) - Sys_Error ("Couldn't create DIB window"); - - // Center and show the DIB window - CenterWindow(dibwindow, WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, false); - - ShowWindow (dibwindow, SW_SHOWDEFAULT); - UpdateWindow (dibwindow); - - modestate = MS_WINDOWED; - -// because we have set the background brush for the window to NULL -// (to avoid flickering when re-sizing the window on the desktop), -// we clear the window to black when created, otherwise it will be -// empty while Quake starts up. - hdc = GetDC(dibwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(dibwindow, hdc); - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.numpages = 2; - - mainwindow = dibwindow; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -qboolean VID_SetFullDIBMode (int modenum) -{ - HDC hdc; - int lastmodestate, width, height; - RECT rect; - - if (!leavecurrentmode) - { - gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - gdevmode.dmBitsPerPel = modelist[modenum].bpp; - gdevmode.dmPelsWidth = modelist[modenum].width << - modelist[modenum].halfscreen; - gdevmode.dmPelsHeight = modelist[modenum].height; - gdevmode.dmSize = sizeof (gdevmode); - - if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode"); - } - - lastmodestate = modestate; - modestate = MS_FULLDIB; - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP; - ExWindowStyle = 0; - - rect = WindowRect; - AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the DIB window - dibwindow = CreateWindowEx ( - ExWindowStyle, - "WinQuake", - "GLQuake", - WindowStyle, - rect.left, rect.top, - width, - height, - NULL, - NULL, - global_hInstance, - NULL); - - if (!dibwindow) - Sys_Error ("Couldn't create DIB window"); - - ShowWindow (dibwindow, SW_SHOWDEFAULT); - UpdateWindow (dibwindow); - - // Because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), we - // clear the window to black when created, otherwise it will be - // empty while Quake starts up. - hdc = GetDC(dibwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(dibwindow, hdc); - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.numpages = 2; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - mainwindow = dibwindow; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -int VID_SetMode (int modenum, unsigned char *palette) -{ - int original_mode, temp; - qboolean stat; - MSG msg; - HDC hdc; - - if ((windowed && (modenum != 0)) || - (!windowed && (modenum < 1)) || - (!windowed && (modenum >= nummodes))) - { - Sys_Error ("Bad video mode\n"); - } - -// so Con_Printfs don't mess us up by forcing vid and snd updates - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - - CDAudio_Pause (); - - if (vid_modenum == NO_MODE) - original_mode = windowed_default; - else - original_mode = vid_modenum; - - // Set either the fullscreen or windowed mode - if (modelist[modenum].type == MS_WINDOWED) - { - if (_windowed_mouse.value && key_dest == key_game) - { - stat = VID_SetWindowedMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode(modenum); - } - } - else if (modelist[modenum].type == MS_FULLDIB) - { - stat = VID_SetFullDIBMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - Sys_Error ("VID_SetMode: Bad mode type in modelist"); - } - - window_width = DIBWidth; - window_height = DIBHeight; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - scr_disabled_for_loading = temp; - - if (!stat) - { - Sys_Error ("Couldn't set video mode"); - } - -// now we try to make sure we get the focus on the mode switch, because -// sometimes in some systems we don't. We grab the foreground, then -// finish setting up, pump all our messages, and sleep for a little while -// to let messages finish bouncing around the system, then we put -// ourselves at the top of the z order, then grab the foreground again, -// Who knows if it helps, but it probably doesn't hurt - SetForegroundWindow (mainwindow); - VID_SetPalette (palette); - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (mainwindow); - -// fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - if (!msg_suppress_1) - Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); - - VID_SetPalette (palette); - - vid.recalc_refdef = 1; - - return true; -} - - -/* -================ -VID_UpdateWindowStatus -================ -*/ -void VID_UpdateWindowStatus (void) -{ - - window_rect.left = window_x; - window_rect.top = window_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; - - IN_UpdateClipCursor (); -} - - -//==================================== - -BINDTEXFUNCPTR bindTexFunc; - -#define TEXTURE_EXT_STRING "GL_EXT_texture_object" - - -void CheckTextureExtensions (void) -{ - char *tmp; - qboolean texture_ext; - HINSTANCE hInstGL; - - texture_ext = FALSE; - /* check for texture extension */ - tmp = (unsigned char *)glGetString(GL_EXTENSIONS); - while (*tmp) - { - if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0) - texture_ext = TRUE; - tmp++; - } - - if (!texture_ext || COM_CheckParm ("-gl11") ) - { - hInstGL = LoadLibrary("opengl32.dll"); - - if (hInstGL == NULL) - Sys_Error ("Couldn't load opengl32.dll\n"); - - bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture"); - - if (!bindTexFunc) - Sys_Error ("No texture objects!"); - return; - } - -/* load library and get procedure adresses for texture extension API */ - if ((bindTexFunc = (BINDTEXFUNCPTR) - wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL) - { - Sys_Error ("GetProcAddress for BindTextureEXT failed"); - return; - } -} - -void CheckArrayExtensions (void) -{ - char *tmp; - - /* check for texture extension */ - tmp = (unsigned char *)glGetString(GL_EXTENSIONS); - while (*tmp) - { - if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0) - { - if ( -((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) || -((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) || -((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) || -((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) ) - { - Sys_Error ("GetProcAddress for vertex extension failed"); - return; - } - return; - } - tmp++; - } - - Sys_Error ("Vertex array extension not present"); -} - -//int texture_mode = GL_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; -int texture_mode = GL_LINEAR; -//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; -//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; - -int texture_extension_number = 1; - -#ifdef _WIN32 -void CheckMultiTextureExtensions(void) -{ - if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { - Con_Printf("Multitexture extensions found.\n"); - qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS"); - qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS"); - gl_mtexable = true; - } -} -#else -void CheckMultiTextureExtensions(void) -{ - gl_mtexable = true; -} -#endif - -/* -=============== -GL_Init -=============== -*/ -void GL_Init (void) -{ - gl_vendor = glGetString (GL_VENDOR); - Con_Printf ("GL_VENDOR: %s\n", gl_vendor); - gl_renderer = glGetString (GL_RENDERER); - Con_Printf ("GL_RENDERER: %s\n", gl_renderer); - - gl_version = glGetString (GL_VERSION); - Con_Printf ("GL_VERSION: %s\n", gl_version); - gl_extensions = glGetString (GL_EXTENSIONS); - Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); - -// Con_Printf ("%s %s\n", gl_renderer, gl_version); - - if (strnicmp(gl_renderer,"PowerVR",7)==0) - fullsbardraw = true; - - if (strnicmp(gl_renderer,"Permedia",8)==0) - isPermedia = true; - - CheckTextureExtensions (); - CheckMultiTextureExtensions (); - - glClearColor (1,0,0,0); - glCullFace(GL_FRONT); - glEnable(GL_TEXTURE_2D); - - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.666); - - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glShadeModel (GL_FLAT); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - -#if 0 - CheckArrayExtensions (); - - glEnable (GL_VERTEX_ARRAY_EXT); - glEnable (GL_TEXTURE_COORD_ARRAY_EXT); - glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x); - glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s); - glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r); -#endif -} - -/* -================= -GL_BeginRendering - -================= -*/ -void GL_BeginRendering (int *x, int *y, int *width, int *height) -{ - extern cvar_t gl_clear; - - *x = *y = 0; - *width = WindowRect.right - WindowRect.left; - *height = WindowRect.bottom - WindowRect.top; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); -} - - -void GL_EndRendering (void) -{ - if (!scr_skipupdate || block_drawing) - SwapBuffers(maindc); - -// handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) - { - if (!_windowed_mouse.value) { - if (windowed_mouse) { - IN_DeactivateMouse (); - IN_ShowMouse (); - windowed_mouse = false; - } - } else { - windowed_mouse = true; - if (key_dest == key_game && !mouseactive && ActiveApp) { - IN_ActivateMouse (); - IN_HideMouse (); - } else if (mouseactive && key_dest != key_game) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } - if (fullsbardraw) - Sbar_Changed(); -} - -void VID_SetPalette (unsigned char *palette) -{ - byte *pal; - unsigned r,g,b; - unsigned v; - int r1,g1,b1; - int j,k,l,m; - unsigned short i; - unsigned *table; - FILE *f; - char s[255]; - HWND hDlg, hProgress; - float gamma; - -// -// 8 8 8 encoding -// - pal = palette; - table = d_8to24table; - for (i=0 ; i<256 ; i++) - { - r = pal[0]; - g = pal[1]; - b = pal[2]; - pal += 3; - -// v = (255<<24) + (r<<16) + (g<<8) + (b<<0); -// v = (255<<0) + (r<<8) + (g<<16) + (b<<24); - v = (255<<24) + (r<<0) + (g<<8) + (b<<16); - *table++ = v; - } - d_8to24table[255] &= 0xffffff; // 255 is transparent - - // JACK: 3D distance calcs - k is last closest, l is the distance. - // FIXME: Precalculate this and cache to disk. - for (i=0; i < (1<<15); i++) { - /* Maps - 000000000000000 - 000000000011111 = Red = 0x1F - 000001111100000 = Blue = 0x03E0 - 111110000000000 = Grn = 0x7C00 - */ - r = ((i & 0x1F) << 3)+4; - g = ((i & 0x03E0) >> 2)+4; - b = ((i & 0x7C00) >> 7)+4; - pal = (unsigned char *)d_8to24table; - for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) { - r1 = r-pal[0]; - g1 = g-pal[1]; - b1 = b-pal[2]; - j = (r1*r1)+(g1*g1)+(b1*b1); - if (j', '?', 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_LEFTARROW,'%',K_RIGHTARROW,'+',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) -{ - key = (key>>16)&255; - if (key > 127) - return 0; - if (scantokey[key] == 0) - Con_DPrintf("key 0x%02x has no translation\n", key); - return scantokey[key]; -} - -/* -=================================================================== - -MAIN WINDOW - -=================================================================== -*/ - -/* -================ -ClearAllStates -================ -*/ -void ClearAllStates (void) -{ - int i; - -// send an up event for each key, to make sure the server clears them all - for (i=0 ; i<256 ; i++) - { - Key_Event (i, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - -void AppActivate(BOOL fActive, BOOL minimize) -/**************************************************************************** -* -* Function: AppActivate -* Parameters: fActive - True if app is activating -* -* Description: If the application is activating, then swap the system -* into SYSPAL_NOSTATIC mode so that our palettes will display -* correctly. -* -****************************************************************************/ -{ - MSG msg; - HDC hdc; - int i, t; - static BOOL sound_active; - - ActiveApp = fActive; - Minimized = minimize; - -// enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) - { - S_BlockSound (); - sound_active = false; - } - else if (ActiveApp && !sound_active) - { - S_UnblockSound (); - sound_active = true; - } - - if (fActive) - { - if (modestate == MS_FULLDIB) - { - IN_ActivateMouse (); - IN_HideMouse (); - if (vid_canalttab && vid_wassuspended) { - vid_wassuspended = false; - ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); - ShowWindow(mainwindow, SW_SHOWNORMAL); - } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } - - if (!fActive) - { - if (modestate == MS_FULLDIB) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - if (vid_canalttab) { - ChangeDisplaySettings (NULL, 0); - vid_wassuspended = true; - } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } -} - - -/* main window procedure */ -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LONG lRet = 1; - int fwKeys, xPos, yPos, fActive, fMinimized, temp; - extern unsigned int uiWheelMessage; - - if ( uMsg == uiWheelMessage ) - uMsg = WM_MOUSEWHEEL; - - switch (uMsg) - { - case WM_KILLFOCUS: - if (modestate == MS_FULLDIB) - ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); - break; - - case WM_CREATE: - break; - - case WM_MOVE: - window_x = (int) LOWORD(lParam); - window_y = (int) HIWORD(lParam); - VID_UpdateWindowStatus (); - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - Key_Event (MapKey(lParam), true); - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - Key_Event (MapKey(lParam), false); - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening - break; - - // 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: - temp = 0; - - if (wParam & MK_LBUTTON) - temp |= 1; - - if (wParam & MK_RBUTTON) - temp |= 2; - - if (wParam & MK_MBUTTON) - temp |= 4; - - IN_MouseEvent (temp); - - break; - - // JACK: This is the mouse wheel with the Intellimouse - // Its delta is either positive or neg, and we generate the proper - // Event. - case WM_MOUSEWHEEL: - if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); - } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); - } - break; - - case WM_SIZE: - break; - - case WM_CLOSE: - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - { - Sys_Quit (); - } - - break; - - case WM_ACTIVATE: - fActive = LOWORD(wParam); - fMinimized = (BOOL) HIWORD(wParam); - AppActivate(!(fActive == WA_INACTIVE), fMinimized); - - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - break; - - case WM_DESTROY: - { - if (dibwindow) - DestroyWindow (dibwindow); - - PostQuitMessage (0); - } - break; - - case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); - break; - - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - break; - } - - /* return 1 if handled message, 0 if not */ - return lRet; -} - - -/* -================= -VID_NumModes -================= -*/ -int VID_NumModes (void) -{ - return nummodes; -} - - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) -{ - - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) -{ - char *pinfo; - vmode_t *pv; - static char temp[100]; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - if (!leavecurrentmode) - { - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - } - else - { - sprintf (temp, "Desktop resolution (%dx%d)", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - pinfo = temp; - } - - return pinfo; -} - - -// KJB: Added this to return the mode driver name in description for console - -char *VID_GetExtModeDescription (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLDIB) - { - if (!leavecurrentmode) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else - { - sprintf (pinfo, "Desktop resolution (%dx%d)", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - } - } - else - { - if (modestate == MS_WINDOWED) - sprintf(pinfo, "%s windowed", pv->modedesc); - else - sprintf(pinfo, "windowed"); - } - - return pinfo; -} - - -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void VID_DescribeCurrentMode_f (void) -{ - Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); -} - - -/* -================= -VID_NumModes_f -================= -*/ -void VID_NumModes_f (void) -{ - - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", nummodes); - else - Con_Printf ("%d video modes are available\n", nummodes); -} - - -/* -================= -VID_DescribeMode_f -================= -*/ -void VID_DescribeMode_f (void) -{ - int t, modenum; - - modenum = Q_atoi (Cmd_Argv(1)); - - t = leavecurrentmode; - leavecurrentmode = 0; - - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); - - leavecurrentmode = t; -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, lnummodes, t; - char *pinfo; - vmode_t *pv; - - lnummodes = VID_NumModes (); - - t = leavecurrentmode; - leavecurrentmode = 0; - - for (i=1 ; i8 bpp modes - originalnummodes = nummodes; - modenum = 0; - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((devmode.dmBitsPerPel >= 15) && - (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight, - devmode.dmBitsPerPel); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height << 1)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", - modelist[nummodes].width, - modelist[nummodes].height, - modelist[nummodes].bpp); - } - } - - for (i=originalnummodes, existingmode = 0 ; i 255) - inf = 255; - palette[i] = inf; - } - - memcpy (pal, palette, sizeof(palette)); -} - -/* -=================== -VID_Init -=================== -*/ -void VID_Init (unsigned char *palette) -{ - int i, existingmode; - int basenummodes, width, height, bpp, findbpp, done; - byte *ptmp; - char gldir[MAX_OSPATH]; - HDC hdc; - DEVMODE devmode; - - memset(&devmode, 0, sizeof(devmode)); - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_wait); - Cvar_RegisterVariable (&vid_nopageflip); - Cvar_RegisterVariable (&_vid_wait_override); - Cvar_RegisterVariable (&_vid_default_mode); - Cvar_RegisterVariable (&_vid_default_mode_win); - Cvar_RegisterVariable (&vid_config_x); - Cvar_RegisterVariable (&vid_config_y); - Cvar_RegisterVariable (&vid_stretch_by_2); - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&gl_ztrick); - - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); - - hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); - - InitCommonControls(); - - VID_InitDIB (global_hInstance); - basenummodes = nummodes = 1; - - VID_InitFullDIB (global_hInstance); - - if (COM_CheckParm("-window")) - { - hdc = GetDC (NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - { - Sys_Error ("Can't run in non-RGB mode"); - } - - ReleaseDC (NULL, hdc); - - windowed = true; - - vid_default = MODE_WINDOWED; - } - else - { - if (nummodes == 1) - Sys_Error ("No RGB fullscreen modes available"); - - windowed = false; - - if (COM_CheckParm("-mode")) - { - vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]); - } - else - { - if (COM_CheckParm("-current")) - { - modelist[MODE_FULLSCREEN_DEFAULT].width = - GetSystemMetrics (SM_CXSCREEN); - modelist[MODE_FULLSCREEN_DEFAULT].height = - GetSystemMetrics (SM_CYSCREEN); - vid_default = MODE_FULLSCREEN_DEFAULT; - leavecurrentmode = 1; - } - else - { - if (COM_CheckParm("-width")) - { - width = Q_atoi(com_argv[COM_CheckParm("-width")+1]); - } - else - { - width = 640; - } - - if (COM_CheckParm("-bpp")) - { - bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]); - findbpp = 0; - } - else - { - bpp = 15; - findbpp = 1; - } - - if (COM_CheckParm("-height")) - height = Q_atoi(com_argv[COM_CheckParm("-height")+1]); - - // if they want to force it, add the specified mode to the list - if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST)) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = width; - modelist[nummodes].height = height; - modelist[nummodes].modenum = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = bpp; - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight, - devmode.dmBitsPerPel); - - for (i=nummodes, existingmode = 0 ; iwidth)/2, 4, p); - - vid_wmodes = 0; - lnummodes = VID_NumModes (); - - for (i=1 ; (i 0) - { - M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)"); - - column = 8; - row = 36+2*8; - - for (i=0 ; i"); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, - "and -bpp "); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, - "Select windowed mode with -window"); -} - - -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) -{ - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; - - default: - break; - } -} +/* +Copyright (C) 1996-1997 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. + +*/ +// gl_vidnt.c -- NT GL vid component + +#include "quakedef.h" +#include "winquake.h" +#include "resource.h" +#include + +#define MAX_MODE_LIST 30 +#define VID_ROW_SIZE 3 +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 +#define MAXWIDTH 10000 +#define MAXHEIGHT 10000 +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +#define MODE_WINDOWED 0 +#define NO_MODE (MODE_WINDOWED - 1) +#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1) + +typedef struct { + modestate_t type; + int width; + int height; + int modenum; + int dib; + int fullscreen; + int bpp; + int halfscreen; + char modedesc[17]; +} vmode_t; + +typedef struct { + int width; + int height; +} lmode_t; + +lmode_t lowresmodes[] = { + {320, 200}, + {320, 240}, + {400, 300}, + {512, 384}, +}; + +const char *gl_vendor; +const char *gl_renderer; +const char *gl_version; +const char *gl_extensions; + +qboolean DDActive; +qboolean scr_skipupdate; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; +static vmode_t *pcurrentmode; +static vmode_t badmode; + +static DEVMODE gdevmode; +static qboolean vid_initialized = false; +static qboolean windowed, leavecurrentmode; +static qboolean vid_canalttab = false; +static qboolean vid_wassuspended = false; +static int windowed_mouse; +extern qboolean mouseactive; // from in_win.c +static HICON hIcon; + +int DIBWidth, DIBHeight; +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +HWND mainwindow, dibwindow; + +int vid_modenum = NO_MODE; +int vid_realmode; +int vid_default = MODE_WINDOWED; +static int windowed_default; +unsigned char vid_curpal[256*3]; +static qboolean fullsbardraw = false; + +static float vid_gamma = 1.0; + +HGLRC baseRC; +HDC maindc; + +glvert_t glv; + +cvar_t gl_ztrick = {"gl_ztrick","1"}; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); + +viddef_t vid; // global video state + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; +unsigned char d_15to8table[65536]; + +float gldepthmin, gldepthmax; + +modestate_t modestate = MS_UNINIT; + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void AppActivate(BOOL fActive, BOOL minimize); +char *VID_GetModeDescription (int mode); +void ClearAllStates (void); +void VID_UpdateWindowStatus (void); +void GL_Init (void); + +PROC glArrayElementEXT; +PROC glColorPointerEXT; +PROC glTexCoordPointerEXT; +PROC glVertexPointerEXT; + +typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*); +lp3DFXFUNC glColorTableEXT; +qboolean is8bit = false; +qboolean isPermedia = false; +qboolean gl_mtexable = false; + +//==================================== + +cvar_t vid_mode = {"vid_mode","0", false}; +// Note that 0 is MODE_WINDOWED +cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; +// Note that 3 is MODE_FULLSCREEN_DEFAULT +cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; +cvar_t vid_wait = {"vid_wait","0"}; +cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; +cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; +cvar_t vid_config_x = {"vid_config_x","800", true}; +cvar_t vid_config_y = {"vid_config_y","600", true}; +cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; +cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; + +int window_center_x, window_center_y, window_x, window_y, window_width, window_height; +RECT window_rect; + +// direct draw software compatability stuff + +void VID_HandlePause (qboolean pause) +{ +} + +void VID_ForceLockState (int lk) +{ +} + +void VID_LockBuffer (void) +{ +} + +void VID_UnlockBuffer (void) +{ +} + +int VID_ForceUnlockedAndReturnState (void) +{ + return 0; +} + +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + +void D_EndDirectRect (int x, int y, int width, int height) +{ +} + + +void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify) +{ + RECT rect; + int CenterX, CenterY; + + CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; + CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; + if (CenterX > CenterY*2) + CenterX >>= 1; // dual screens + CenterX = (CenterX < 0) ? 0: CenterX; + CenterY = (CenterY < 0) ? 0: CenterY; + SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); +} + +qboolean VID_SetWindowedMode (int modenum) +{ + HDC hdc; + int lastmodestate, width, height; + RECT rect; + + lastmodestate = modestate; + + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX; + ExWindowStyle = 0; + + rect = WindowRect; + AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + // Create the DIB window + dibwindow = CreateWindowEx ( + ExWindowStyle, + "WinQuake", + "GLQuake", + WindowStyle, + rect.left, rect.top, + width, + height, + NULL, + NULL, + global_hInstance, + NULL); + + if (!dibwindow) + Sys_Error ("Couldn't create DIB window"); + + // Center and show the DIB window + CenterWindow(dibwindow, WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, false); + + ShowWindow (dibwindow, SW_SHOWDEFAULT); + UpdateWindow (dibwindow); + + modestate = MS_WINDOWED; + +// because we have set the background brush for the window to NULL +// (to avoid flickering when re-sizing the window on the desktop), +// we clear the window to black when created, otherwise it will be +// empty while Quake starts up. + hdc = GetDC(dibwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(dibwindow, hdc); + + if (vid.conheight > modelist[modenum].height) + vid.conheight = modelist[modenum].height; + if (vid.conwidth > modelist[modenum].width) + vid.conwidth = modelist[modenum].width; + vid.width = vid.conwidth; + vid.height = vid.conheight; + + vid.numpages = 2; + + mainwindow = dibwindow; + + SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + + return true; +} + + +qboolean VID_SetFullDIBMode (int modenum) +{ + HDC hdc; + int lastmodestate, width, height; + RECT rect; + + if (!leavecurrentmode) + { + gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + gdevmode.dmBitsPerPel = modelist[modenum].bpp; + gdevmode.dmPelsWidth = modelist[modenum].width << + modelist[modenum].halfscreen; + gdevmode.dmPelsHeight = modelist[modenum].height; + gdevmode.dmSize = sizeof (gdevmode); + + if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + Sys_Error ("Couldn't set fullscreen DIB mode"); + } + + lastmodestate = modestate; + modestate = MS_FULLDIB; + + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_POPUP; + ExWindowStyle = 0; + + rect = WindowRect; + AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + // Create the DIB window + dibwindow = CreateWindowEx ( + ExWindowStyle, + "WinQuake", + "GLQuake", + WindowStyle, + rect.left, rect.top, + width, + height, + NULL, + NULL, + global_hInstance, + NULL); + + if (!dibwindow) + Sys_Error ("Couldn't create DIB window"); + + ShowWindow (dibwindow, SW_SHOWDEFAULT); + UpdateWindow (dibwindow); + + // Because we have set the background brush for the window to NULL + // (to avoid flickering when re-sizing the window on the desktop), we + // clear the window to black when created, otherwise it will be + // empty while Quake starts up. + hdc = GetDC(dibwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(dibwindow, hdc); + + if (vid.conheight > modelist[modenum].height) + vid.conheight = modelist[modenum].height; + if (vid.conwidth > modelist[modenum].width) + vid.conwidth = modelist[modenum].width; + vid.width = vid.conwidth; + vid.height = vid.conheight; + + vid.numpages = 2; + +// needed because we're not getting WM_MOVE messages fullscreen on NT + window_x = 0; + window_y = 0; + + mainwindow = dibwindow; + + SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + + return true; +} + + +int VID_SetMode (int modenum, unsigned char *palette) +{ + int original_mode, temp; + qboolean stat; + MSG msg; + HDC hdc; + + if ((windowed && (modenum != 0)) || + (!windowed && (modenum < 1)) || + (!windowed && (modenum >= nummodes))) + { + Sys_Error ("Bad video mode\n"); + } + +// so Con_Printfs don't mess us up by forcing vid and snd updates + temp = scr_disabled_for_loading; + scr_disabled_for_loading = true; + + CDAudio_Pause (); + + if (vid_modenum == NO_MODE) + original_mode = windowed_default; + else + original_mode = vid_modenum; + + // Set either the fullscreen or windowed mode + if (modelist[modenum].type == MS_WINDOWED) + { + if (_windowed_mouse.value && key_dest == key_game) + { + stat = VID_SetWindowedMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + IN_DeactivateMouse (); + IN_ShowMouse (); + stat = VID_SetWindowedMode(modenum); + } + } + else if (modelist[modenum].type == MS_FULLDIB) + { + stat = VID_SetFullDIBMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + Sys_Error ("VID_SetMode: Bad mode type in modelist"); + } + + window_width = DIBWidth; + window_height = DIBHeight; + VID_UpdateWindowStatus (); + + CDAudio_Resume (); + scr_disabled_for_loading = temp; + + if (!stat) + { + Sys_Error ("Couldn't set video mode"); + } + +// now we try to make sure we get the focus on the mode switch, because +// sometimes in some systems we don't. We grab the foreground, then +// finish setting up, pump all our messages, and sleep for a little while +// to let messages finish bouncing around the system, then we put +// ourselves at the top of the z order, then grab the foreground again, +// Who knows if it helps, but it probably doesn't hurt + SetForegroundWindow (mainwindow); + VID_SetPalette (palette); + vid_modenum = modenum; + Cvar_SetValue ("vid_mode", (float)vid_modenum); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (mainwindow); + +// fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!msg_suppress_1) + Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); + + VID_SetPalette (palette); + + vid.recalc_refdef = 1; + + return true; +} + + +/* +================ +VID_UpdateWindowStatus +================ +*/ +void VID_UpdateWindowStatus (void) +{ + + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + + IN_UpdateClipCursor (); +} + + +//==================================== + +BINDTEXFUNCPTR bindTexFunc; + +#define TEXTURE_EXT_STRING "GL_EXT_texture_object" + + +void CheckTextureExtensions (void) +{ + char *tmp; + qboolean texture_ext; + HINSTANCE hInstGL; + + texture_ext = FALSE; + /* check for texture extension */ + tmp = (unsigned char *)glGetString(GL_EXTENSIONS); + while (*tmp) + { + if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0) + texture_ext = TRUE; + tmp++; + } + + if (!texture_ext || COM_CheckParm ("-gl11") ) + { + hInstGL = LoadLibrary("opengl32.dll"); + + if (hInstGL == NULL) + Sys_Error ("Couldn't load opengl32.dll\n"); + + bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture"); + + if (!bindTexFunc) + Sys_Error ("No texture objects!"); + return; + } + +/* load library and get procedure adresses for texture extension API */ + if ((bindTexFunc = (BINDTEXFUNCPTR) + wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL) + { + Sys_Error ("GetProcAddress for BindTextureEXT failed"); + return; + } +} + +void CheckArrayExtensions (void) +{ + char *tmp; + + /* check for texture extension */ + tmp = (unsigned char *)glGetString(GL_EXTENSIONS); + while (*tmp) + { + if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0) + { + if ( +((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) || +((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) || +((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) || +((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) ) + { + Sys_Error ("GetProcAddress for vertex extension failed"); + return; + } + return; + } + tmp++; + } + + Sys_Error ("Vertex array extension not present"); +} + +//int texture_mode = GL_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; +int texture_mode = GL_LINEAR; +//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; +//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; + +int texture_extension_number = 1; + +#ifdef _WIN32 +void CheckMultiTextureExtensions(void) +{ + if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { + Con_Printf("Multitexture extensions found.\n"); + qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS"); + qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS"); + gl_mtexable = true; + } +} +#else +void CheckMultiTextureExtensions(void) +{ + gl_mtexable = true; +} +#endif + +/* +=============== +GL_Init +=============== +*/ +void GL_Init (void) +{ + gl_vendor = glGetString (GL_VENDOR); + Con_Printf ("GL_VENDOR: %s\n", gl_vendor); + gl_renderer = glGetString (GL_RENDERER); + Con_Printf ("GL_RENDERER: %s\n", gl_renderer); + + gl_version = glGetString (GL_VERSION); + Con_Printf ("GL_VERSION: %s\n", gl_version); + gl_extensions = glGetString (GL_EXTENSIONS); + Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); + +// Con_Printf ("%s %s\n", gl_renderer, gl_version); + + if (strnicmp(gl_renderer,"PowerVR",7)==0) + fullsbardraw = true; + + if (strnicmp(gl_renderer,"Permedia",8)==0) + isPermedia = true; + + CheckTextureExtensions (); + CheckMultiTextureExtensions (); + + glClearColor (1,0,0,0); + glCullFace(GL_FRONT); + glEnable(GL_TEXTURE_2D); + + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.666); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glShadeModel (GL_FLAT); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + +#if 0 + CheckArrayExtensions (); + + glEnable (GL_VERTEX_ARRAY_EXT); + glEnable (GL_TEXTURE_COORD_ARRAY_EXT); + glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x); + glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s); + glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r); +#endif +} + +/* +================= +GL_BeginRendering + +================= +*/ +void GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + extern cvar_t gl_clear; + + *x = *y = 0; + *width = WindowRect.right - WindowRect.left; + *height = WindowRect.bottom - WindowRect.top; + +// if (!wglMakeCurrent( maindc, baseRC )) +// Sys_Error ("wglMakeCurrent failed"); + +// glViewport (*x, *y, *width, *height); +} + + +void GL_EndRendering (void) +{ + if (!scr_skipupdate || block_drawing) + SwapBuffers(maindc); + +// handle the mouse state when windowed if that's changed + if (modestate == MS_WINDOWED) + { + if (!_windowed_mouse.value) { + if (windowed_mouse) { + IN_DeactivateMouse (); + IN_ShowMouse (); + windowed_mouse = false; + } + } else { + windowed_mouse = true; + if (key_dest == key_game && !mouseactive && ActiveApp) { + IN_ActivateMouse (); + IN_HideMouse (); + } else if (mouseactive && key_dest != key_game) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } + } + if (fullsbardraw) + Sbar_Changed(); +} + +void VID_SetPalette (unsigned char *palette) +{ + byte *pal; + unsigned r,g,b; + unsigned v; + int r1,g1,b1; + int j,k,l,m; + unsigned short i; + unsigned *table; + FILE *f; + char s[255]; + HWND hDlg, hProgress; + float gamma; + +// +// 8 8 8 encoding +// + pal = palette; + table = d_8to24table; + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + +// v = (255<<24) + (r<<16) + (g<<8) + (b<<0); +// v = (255<<0) + (r<<8) + (g<<16) + (b<<24); + v = (255<<24) + (r<<0) + (g<<8) + (b<<16); + *table++ = v; + } + d_8to24table[255] &= 0xffffff; // 255 is transparent + + // JACK: 3D distance calcs - k is last closest, l is the distance. + // FIXME: Precalculate this and cache to disk. + for (i=0; i < (1<<15); i++) { + /* Maps + 000000000000000 + 000000000011111 = Red = 0x1F + 000001111100000 = Blue = 0x03E0 + 111110000000000 = Grn = 0x7C00 + */ + r = ((i & 0x1F) << 3)+4; + g = ((i & 0x03E0) >> 2)+4; + b = ((i & 0x7C00) >> 7)+4; + pal = (unsigned char *)d_8to24table; + for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) { + r1 = r-pal[0]; + g1 = g-pal[1]; + b1 = b-pal[2]; + j = (r1*r1)+(g1*g1)+(b1*b1); + if (j', '?', 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_LEFTARROW,'%',K_RIGHTARROW,'+',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) +{ + key = (key>>16)&255; + if (key > 127) + return 0; + if (scantokey[key] == 0) + Con_DPrintf("key 0x%02x has no translation\n", key); + return scantokey[key]; +} + +/* +=================================================================== + +MAIN WINDOW + +=================================================================== +*/ + +/* +================ +ClearAllStates +================ +*/ +void ClearAllStates (void) +{ + int i; + +// send an up event for each key, to make sure the server clears them all + for (i=0 ; i<256 ; i++) + { + Key_Event (i, false); + } + + Key_ClearStates (); + IN_ClearStates (); +} + +void AppActivate(BOOL fActive, BOOL minimize) +/**************************************************************************** +* +* Function: AppActivate +* Parameters: fActive - True if app is activating +* +* Description: If the application is activating, then swap the system +* into SYSPAL_NOSTATIC mode so that our palettes will display +* correctly. +* +****************************************************************************/ +{ + MSG msg; + HDC hdc; + int i, t; + static BOOL sound_active; + + ActiveApp = fActive; + Minimized = minimize; + +// enable/disable sound on focus gain/loss + if (!ActiveApp && sound_active) + { + S_BlockSound (); + sound_active = false; + } + else if (ActiveApp && !sound_active) + { + S_UnblockSound (); + sound_active = true; + } + + if (fActive) + { + if (modestate == MS_FULLDIB) + { + IN_ActivateMouse (); + IN_HideMouse (); + if (vid_canalttab && vid_wassuspended) { + vid_wassuspended = false; + ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); + ShowWindow(mainwindow, SW_SHOWNORMAL); + } + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) + { + IN_ActivateMouse (); + IN_HideMouse (); + } + } + + if (!fActive) + { + if (modestate == MS_FULLDIB) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + if (vid_canalttab) { + ChangeDisplaySettings (NULL, 0); + vid_wassuspended = true; + } + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } +} + + +/* main window procedure */ +LONG WINAPI MainWndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 1; + int fwKeys, xPos, yPos, fActive, fMinimized, temp; + extern unsigned int uiWheelMessage; + + if ( uMsg == uiWheelMessage ) + uMsg = WM_MOUSEWHEEL; + + switch (uMsg) + { + case WM_KILLFOCUS: + if (modestate == MS_FULLDIB) + ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); + break; + + case WM_CREATE: + break; + + case WM_MOVE: + window_x = (int) LOWORD(lParam); + window_y = (int) HIWORD(lParam); + VID_UpdateWindowStatus (); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + Key_Event (MapKey(lParam), true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + Key_Event (MapKey(lParam), false); + break; + + case WM_SYSCHAR: + // keep Alt-Space from happening + break; + + // 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: + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + IN_MouseEvent (temp); + + break; + + // JACK: This is the mouse wheel with the Intellimouse + // Its delta is either positive or neg, and we generate the proper + // Event. + case WM_MOUSEWHEEL: + if ((short) HIWORD(wParam) > 0) { + Key_Event(K_MWHEELUP, true); + Key_Event(K_MWHEELUP, false); + } else { + Key_Event(K_MWHEELDOWN, true); + Key_Event(K_MWHEELDOWN, false); + } + break; + + case WM_SIZE: + break; + + case WM_CLOSE: + if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) + { + Sys_Quit (); + } + + break; + + case WM_ACTIVATE: + fActive = LOWORD(wParam); + fMinimized = (BOOL) HIWORD(wParam); + AppActivate(!(fActive == WA_INACTIVE), fMinimized); + + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + break; + + case WM_DESTROY: + { + if (dibwindow) + DestroyWindow (dibwindow); + + PostQuitMessage (0); + } + break; + + case MM_MCINOTIFY: + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 1 if handled message, 0 if not */ + return lRet; +} + + +/* +================= +VID_NumModes +================= +*/ +int VID_NumModes (void) +{ + return nummodes; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t *VID_GetModePtr (int modenum) +{ + + if ((modenum >= 0) && (modenum < nummodes)) + return &modelist[modenum]; + else + return &badmode; +} + + +/* +================= +VID_GetModeDescription +================= +*/ +char *VID_GetModeDescription (int mode) +{ + char *pinfo; + vmode_t *pv; + static char temp[100]; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + if (!leavecurrentmode) + { + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + } + else + { + sprintf (temp, "Desktop resolution (%dx%d)", + modelist[MODE_FULLSCREEN_DEFAULT].width, + modelist[MODE_FULLSCREEN_DEFAULT].height); + pinfo = temp; + } + + return pinfo; +} + + +// KJB: Added this to return the mode driver name in description for console + +char *VID_GetExtModeDescription (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + pv = VID_GetModePtr (mode); + if (modelist[mode].type == MS_FULLDIB) + { + if (!leavecurrentmode) + { + sprintf(pinfo,"%s fullscreen", pv->modedesc); + } + else + { + sprintf (pinfo, "Desktop resolution (%dx%d)", + modelist[MODE_FULLSCREEN_DEFAULT].width, + modelist[MODE_FULLSCREEN_DEFAULT].height); + } + } + else + { + if (modestate == MS_WINDOWED) + sprintf(pinfo, "%s windowed", pv->modedesc); + else + sprintf(pinfo, "windowed"); + } + + return pinfo; +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void VID_DescribeCurrentMode_f (void) +{ + Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); +} + + +/* +================= +VID_NumModes_f +================= +*/ +void VID_NumModes_f (void) +{ + + if (nummodes == 1) + Con_Printf ("%d video mode is available\n", nummodes); + else + Con_Printf ("%d video modes are available\n", nummodes); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void VID_DescribeMode_f (void) +{ + int t, modenum; + + modenum = Q_atoi (Cmd_Argv(1)); + + t = leavecurrentmode; + leavecurrentmode = 0; + + Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); + + leavecurrentmode = t; +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void VID_DescribeModes_f (void) +{ + int i, lnummodes, t; + char *pinfo; + vmode_t *pv; + + lnummodes = VID_NumModes (); + + t = leavecurrentmode; + leavecurrentmode = 0; + + for (i=1 ; i8 bpp modes + originalnummodes = nummodes; + modenum = 0; + + do + { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((devmode.dmBitsPerPel >= 15) && + (devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) + { + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = devmode.dmBitsPerPel; + sprintf (modelist[nummodes].modedesc, "%dx%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight, + devmode.dmBitsPerPel); + + // if the width is more than twice the height, reduce it by half because this + // is probably a dual-screen monitor + if (!COM_CheckParm("-noadjustaspect")) + { + if (modelist[nummodes].width > (modelist[nummodes].height << 1)) + { + modelist[nummodes].width >>= 1; + modelist[nummodes].halfscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%dx%d", + modelist[nummodes].width, + modelist[nummodes].height, + modelist[nummodes].bpp); + } + } + + for (i=originalnummodes, existingmode = 0 ; i 255) + inf = 255; + palette[i] = inf; + } + + memcpy (pal, palette, sizeof(palette)); +} + +/* +=================== +VID_Init +=================== +*/ +void VID_Init (unsigned char *palette) +{ + int i, existingmode; + int basenummodes, width, height, bpp, findbpp, done; + byte *ptmp; + char gldir[MAX_OSPATH]; + HDC hdc; + DEVMODE devmode; + + memset(&devmode, 0, sizeof(devmode)); + + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&vid_wait); + Cvar_RegisterVariable (&vid_nopageflip); + Cvar_RegisterVariable (&_vid_wait_override); + Cvar_RegisterVariable (&_vid_default_mode); + Cvar_RegisterVariable (&_vid_default_mode_win); + Cvar_RegisterVariable (&vid_config_x); + Cvar_RegisterVariable (&vid_config_y); + Cvar_RegisterVariable (&vid_stretch_by_2); + Cvar_RegisterVariable (&_windowed_mouse); + Cvar_RegisterVariable (&gl_ztrick); + + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); + + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + InitCommonControls(); + + VID_InitDIB (global_hInstance); + basenummodes = nummodes = 1; + + VID_InitFullDIB (global_hInstance); + + if (COM_CheckParm("-window")) + { + hdc = GetDC (NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + { + Sys_Error ("Can't run in non-RGB mode"); + } + + ReleaseDC (NULL, hdc); + + windowed = true; + + vid_default = MODE_WINDOWED; + } + else + { + if (nummodes == 1) + Sys_Error ("No RGB fullscreen modes available"); + + windowed = false; + + if (COM_CheckParm("-mode")) + { + vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]); + } + else + { + if (COM_CheckParm("-current")) + { + modelist[MODE_FULLSCREEN_DEFAULT].width = + GetSystemMetrics (SM_CXSCREEN); + modelist[MODE_FULLSCREEN_DEFAULT].height = + GetSystemMetrics (SM_CYSCREEN); + vid_default = MODE_FULLSCREEN_DEFAULT; + leavecurrentmode = 1; + } + else + { + if (COM_CheckParm("-width")) + { + width = Q_atoi(com_argv[COM_CheckParm("-width")+1]); + } + else + { + width = 640; + } + + if (COM_CheckParm("-bpp")) + { + bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]); + findbpp = 0; + } + else + { + bpp = 15; + findbpp = 1; + } + + if (COM_CheckParm("-height")) + height = Q_atoi(com_argv[COM_CheckParm("-height")+1]); + + // if they want to force it, add the specified mode to the list + if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST)) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = width; + modelist[nummodes].height = height; + modelist[nummodes].modenum = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = bpp; + sprintf (modelist[nummodes].modedesc, "%dx%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight, + devmode.dmBitsPerPel); + + for (i=nummodes, existingmode = 0 ; iwidth)/2, 4, p); + + vid_wmodes = 0; + lnummodes = VID_NumModes (); + + for (i=1 ; (i 0) + { + M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)"); + + column = 8; + row = 36+2*8; + + for (i=0 ; i"); + M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, + "and -bpp "); + M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, + "Select windowed mode with -window"); +} + + +/* +================ +VID_MenuKey +================ +*/ +void VID_MenuKey (int key) +{ + switch (key) + { + case K_ESCAPE: + S_LocalSound ("misc/menu1.wav"); + M_Menu_Options_f (); + break; + + default: + break; + } +} diff --git a/source/gl_warp.c b/source/gl_warp.c index f4344c6..a7ac7f9 100644 --- a/source/gl_warp.c +++ b/source/gl_warp.c @@ -1,1087 +1,1087 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// gl_warp.c -- sky and water polygons - -#include "quakedef.h" - -extern model_t *loadmodel; - -int skytexturenum; - -int solidskytexture; -int alphaskytexture; -float speedscale; // for top sky and bottom sky - -msurface_t *warpface; - -extern cvar_t gl_subdivide_size; - -void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) -{ - int i, j; - float *v; - - mins[0] = mins[1] = mins[2] = 9999; - maxs[0] = maxs[1] = maxs[2] = -9999; - v = verts; - for (i=0 ; i maxs[j]) - maxs[j] = *v; - } -} - -void SubdividePolygon (int numverts, float *verts) -{ - int i, j, k; - vec3_t mins, maxs; - float m; - float *v; - vec3_t front[64], back[64]; - int f, b; - float dist[64]; - float frac; - glpoly_t *poly; - float s, t; - - if (numverts > 60) - Sys_Error ("numverts = %i", numverts); - - BoundPoly (numverts, verts, mins, maxs); - - for (i=0 ; i<3 ; i++) - { - m = (mins[i] + maxs[i]) * 0.5; - m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5); - if (maxs[i] - m < 8) - continue; - if (m - mins[i] < 8) - continue; - - // cut it - v = verts + i; - for (j=0 ; j= 0) - { - VectorCopy (v, front[f]); - f++; - } - if (dist[j] <= 0) - { - VectorCopy (v, back[b]); - b++; - } - if (dist[j] == 0 || dist[j+1] == 0) - continue; - if ( (dist[j] > 0) != (dist[j+1] > 0) ) - { - // clip point - frac = dist[j] / (dist[j] - dist[j+1]); - for (k=0 ; k<3 ; k++) - front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); - f++; - b++; - } - } - - SubdividePolygon (f, front[0]); - SubdividePolygon (b, back[0]); - return; - } - - poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); - poly->next = warpface->polys; - warpface->polys = poly; - poly->numverts = numverts; - for (i=0 ; iverts[i]); - s = DotProduct (verts, warpface->texinfo->vecs[0]); - t = DotProduct (verts, warpface->texinfo->vecs[1]); - poly->verts[i][3] = s; - poly->verts[i][4] = t; - } -} - -/* -================ -GL_SubdivideSurface - -Breaks a polygon up along axial 64 unit -boundaries so that turbulent and sky warps -can be done reasonably. -================ -*/ -void GL_SubdivideSurface (msurface_t *fa) -{ - vec3_t verts[64]; - int numverts; - int i; - int lindex; - float *vec; - - warpface = fa; - - // - // convert edges back to a normal polygon - // - numverts = 0; - for (i=0 ; inumedges ; i++) - { - lindex = loadmodel->surfedges[fa->firstedge + i]; - - if (lindex > 0) - vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; - else - vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; - VectorCopy (vec, verts[numverts]); - numverts++; - } - - SubdividePolygon (numverts, verts[0]); -} - -//========================================================= - - - -// speed up sin calculations - Ed -float turbsin[] = -{ - #include "gl_warp_sin.h" -}; -#define TURBSCALE (256.0 / (2 * M_PI)) - -/* -============= -EmitWaterPolys - -Does a water warp on the pre-fragmented glpoly_t chain -============= -*/ -void EmitWaterPolys (msurface_t *fa) -{ - glpoly_t *p; - float *v; - int i; - float s, t, os, ot; - - - for (p=fa->polys ; p ; p=p->next) - { - glBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - os = v[3]; - ot = v[4]; - - s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; - s *= (1.0/64); - - t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; - t *= (1.0/64); - - glTexCoord2f (s, t); - glVertex3fv (v); - } - glEnd (); - } -} - - - - -/* -============= -EmitSkyPolys -============= -*/ -void EmitSkyPolys (msurface_t *fa) -{ - glpoly_t *p; - float *v; - int i; - float s, t; - vec3_t dir; - float length; - - for (p=fa->polys ; p ; p=p->next) - { - glBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - VectorSubtract (v, r_origin, dir); - dir[2] *= 3; // flatten the sphere - - length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; - length = sqrt (length); - length = 6*63/length; - - dir[0] *= length; - dir[1] *= length; - - s = (speedscale + dir[0]) * (1.0/128); - t = (speedscale + dir[1]) * (1.0/128); - - glTexCoord2f (s, t); - glVertex3fv (v); - } - glEnd (); - } -} - -/* -=============== -EmitBothSkyLayers - -Does a sky warp on the pre-fragmented glpoly_t chain -This will be called for brushmodels, the world -will have them chained together. -=============== -*/ -void EmitBothSkyLayers (msurface_t *fa) -{ - GL_DisableMultitexture(); - - GL_Bind (solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale & ~127 ; - - EmitSkyPolys (fa); - - glEnable (GL_BLEND); - GL_Bind (alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale & ~127 ; - - EmitSkyPolys (fa); - - glDisable (GL_BLEND); -} - -#ifndef QUAKE2 -/* -================= -R_DrawSkyChain -================= -*/ -void R_DrawSkyChain (msurface_t *s) -{ - msurface_t *fa; - - GL_DisableMultitexture(); - - // used when gl_texsort is on - GL_Bind(solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale & ~127 ; - - for (fa=s ; fa ; fa=fa->texturechain) - EmitSkyPolys (fa); - - glEnable (GL_BLEND); - GL_Bind (alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale & ~127 ; - - for (fa=s ; fa ; fa=fa->texturechain) - EmitSkyPolys (fa); - - glDisable (GL_BLEND); -} - -#endif - -/* -================================================================= - - Quake 2 environment sky - -================================================================= -*/ - -#ifdef QUAKE2 - - -#define SKY_TEX 2000 - -/* -================================================================= - - PCX Loading - -================================================================= -*/ - -typedef struct -{ - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short hres,vres; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned data; // unbounded -} pcx_t; - -byte *pcx_rgb; - -/* -============ -LoadPCX -============ -*/ -void LoadPCX (FILE *f) -{ - pcx_t *pcx, pcxbuf; - byte palette[768]; - byte *pix; - int x, y; - int dataByte, runLength; - int count; - -// -// parse the PCX file -// - fread (&pcxbuf, 1, sizeof(pcxbuf), f); - - pcx = &pcxbuf; - - if (pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 - || pcx->xmax >= 320 - || pcx->ymax >= 256) - { - Con_Printf ("Bad pcx file\n"); - return; - } - - // seek to palette - fseek (f, -768, SEEK_END); - fread (palette, 1, 768, f); - - fseek (f, sizeof(pcxbuf) - 4, SEEK_SET); - - count = (pcx->xmax+1) * (pcx->ymax+1); - pcx_rgb = malloc( count * 4); - - for (y=0 ; y<=pcx->ymax ; y++) - { - pix = pcx_rgb + 4*y*(pcx->xmax+1); - for (x=0 ; x<=pcx->ymax ; ) - { - dataByte = fgetc(f); - - if((dataByte & 0xC0) == 0xC0) - { - runLength = dataByte & 0x3F; - dataByte = fgetc(f); - } - else - runLength = 1; - - while(runLength-- > 0) - { - pix[0] = palette[dataByte*3]; - pix[1] = palette[dataByte*3+1]; - pix[2] = palette[dataByte*3+2]; - pix[3] = 255; - pix += 4; - x++; - } - } - } -} - -/* -========================================================= - -TARGA LOADING - -========================================================= -*/ - -typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; -} TargaHeader; - - -TargaHeader targa_header; -byte *targa_rgba; - -int fgetLittleShort (FILE *f) -{ - byte b1, b2; - - b1 = fgetc(f); - b2 = fgetc(f); - - return (short)(b1 + b2*256); -} - -int fgetLittleLong (FILE *f) -{ - byte b1, b2, b3, b4; - - b1 = fgetc(f); - b2 = fgetc(f); - b3 = fgetc(f); - b4 = fgetc(f); - - return b1 + (b2<<8) + (b3<<16) + (b4<<24); -} - - -/* -============= -LoadTGA -============= -*/ -void LoadTGA (FILE *fin) -{ - int columns, rows, numPixels; - byte *pixbuf; - int row, column; - - targa_header.id_length = fgetc(fin); - targa_header.colormap_type = fgetc(fin); - targa_header.image_type = fgetc(fin); - - targa_header.colormap_index = fgetLittleShort(fin); - targa_header.colormap_length = fgetLittleShort(fin); - targa_header.colormap_size = fgetc(fin); - targa_header.x_origin = fgetLittleShort(fin); - targa_header.y_origin = fgetLittleShort(fin); - targa_header.width = fgetLittleShort(fin); - targa_header.height = fgetLittleShort(fin); - targa_header.pixel_size = fgetc(fin); - targa_header.attributes = fgetc(fin); - - if (targa_header.image_type!=2 - && targa_header.image_type!=10) - Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); - - if (targa_header.colormap_type !=0 - || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) - Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); - - columns = targa_header.width; - rows = targa_header.height; - numPixels = columns * rows; - - targa_rgba = malloc (numPixels*4); - - if (targa_header.id_length != 0) - fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment - - if (targa_header.image_type==2) { // Uncompressed, RGB images - for(row=rows-1; row>=0; row--) { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column=0; row--) { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - else { // non run-length packet - for(j=0;j0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - } - breakOut:; - } - } - - fclose(fin); -} - -/* -================== -R_LoadSkys -================== -*/ -char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; -void R_LoadSkys (void) -{ - int i; - FILE *f; - char name[64]; - - for (i=0 ; i<6 ; i++) - { - GL_Bind (SKY_TEX + i); - sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]); - COM_FOpenFile (name, &f); - if (!f) - { - Con_Printf ("Couldn't load %s\n", name); - continue; - } - LoadTGA (f); -// LoadPCX (f); - - glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba); -// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb); - - free (targa_rgba); -// free (pcx_rgb); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } -} - - -vec3_t skyclip[6] = { - {1,1,0}, - {1,-1,0}, - {0,-1,1}, - {0,1,1}, - {1,0,1}, - {-1,0,1} -}; -int c_sky; - -// 1 = s, 2 = t, 3 = 2048 -int st_to_vec[6][3] = -{ - {3,-1,2}, - {-3,1,2}, - - {1,3,2}, - {-1,-3,2}, - - {-2,-1,3}, // 0 degrees yaw, look straight up - {2,-1,-3} // look straight down - -// {-1,2,3}, -// {1,2,-3} -}; - -// s = [0]/[2], t = [1]/[2] -int vec_to_st[6][3] = -{ - {-2,3,1}, - {2,3,-1}, - - {1,3,2}, - {-1,3,-2}, - - {-2,-1,3}, - {-2,1,-3} - -// {-1,2,3}, -// {1,2,-3} -}; - -float skymins[2][6], skymaxs[2][6]; - -void DrawSkyPolygon (int nump, vec3_t vecs) -{ - int i,j; - vec3_t v, av; - float s, t, dv; - int axis; - float *vp; - - c_sky++; -#if 0 -glBegin (GL_POLYGON); -for (i=0 ; i av[1] && av[0] > av[2]) - { - if (v[0] < 0) - axis = 1; - else - axis = 0; - } - else if (av[1] > av[2] && av[1] > av[0]) - { - if (v[1] < 0) - axis = 3; - else - axis = 2; - } - else - { - if (v[2] < 0) - axis = 5; - else - axis = 4; - } - - // project new texture coords - for (i=0 ; i 0) - dv = vecs[j - 1]; - else - dv = -vecs[-j - 1]; - - j = vec_to_st[axis][0]; - if (j < 0) - s = -vecs[-j -1] / dv; - else - s = vecs[j-1] / dv; - j = vec_to_st[axis][1]; - if (j < 0) - t = -vecs[-j -1] / dv; - else - t = vecs[j-1] / dv; - - if (s < skymins[0][axis]) - skymins[0][axis] = s; - if (t < skymins[1][axis]) - skymins[1][axis] = t; - if (s > skymaxs[0][axis]) - skymaxs[0][axis] = s; - if (t > skymaxs[1][axis]) - skymaxs[1][axis] = t; - } -} - -#define MAX_CLIP_VERTS 64 -void ClipSkyPolygon (int nump, vec3_t vecs, int stage) -{ - float *norm; - float *v; - qboolean front, back; - float d, e; - float dists[MAX_CLIP_VERTS]; - int sides[MAX_CLIP_VERTS]; - vec3_t newv[2][MAX_CLIP_VERTS]; - int newc[2]; - int i, j; - - if (nump > MAX_CLIP_VERTS-2) - Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS"); - if (stage == 6) - { // fully clipped, so draw it - DrawSkyPolygon (nump, vecs); - return; - } - - front = back = false; - norm = skyclip[stage]; - for (i=0, v = vecs ; i ON_EPSILON) - { - front = true; - sides[i] = SIDE_FRONT; - } - else if (d < ON_EPSILON) - { - back = true; - sides[i] = SIDE_BACK; - } - else - sides[i] = SIDE_ON; - dists[i] = d; - } - - if (!front || !back) - { // not clipped - ClipSkyPolygon (nump, vecs, stage+1); - return; - } - - // clip it - sides[i] = sides[0]; - dists[i] = dists[0]; - VectorCopy (vecs, (vecs+(i*3)) ); - newc[0] = newc[1] = 0; - - for (i=0, v = vecs ; itexturechain) - { - for (p=fa->polys ; p ; p=p->next) - { - for (i=0 ; inumverts ; i++) - { - VectorSubtract (p->verts[i], r_origin, verts[i]); - } - ClipSkyPolygon (p->numverts, verts[0], 0); - } - } -} - - -/* -============== -R_ClearSkyBox -============== -*/ -void R_ClearSkyBox (void) -{ - int i; - - for (i=0 ; i<6 ; i++) - { - skymins[0][i] = skymins[1][i] = 9999; - skymaxs[0][i] = skymaxs[1][i] = -9999; - } -} - - -void MakeSkyVec (float s, float t, int axis) -{ - vec3_t v, b; - int j, k; - - b[0] = s*2048; - b[1] = t*2048; - b[2] = 2048; - - for (j=0 ; j<3 ; j++) - { - k = st_to_vec[axis][j]; - if (k < 0) - v[j] = -b[-k - 1]; - else - v[j] = b[k - 1]; - v[j] += r_origin[j]; - } - - // avoid bilerp seam - s = (s+1)*0.5; - t = (t+1)*0.5; - - if (s < 1.0/512) - s = 1.0/512; - else if (s > 511.0/512) - s = 511.0/512; - if (t < 1.0/512) - t = 1.0/512; - else if (t > 511.0/512) - t = 511.0/512; - - t = 1.0 - t; - glTexCoord2f (s, t); - glVertex3fv (v); -} - -/* -============== -R_DrawSkyBox -============== -*/ -int skytexorder[6] = {0,2,1,3,4,5}; -void R_DrawSkyBox (void) -{ - int i, j, k; - vec3_t v; - float s, t; - -#if 0 -glEnable (GL_BLEND); -glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -glColor4f (1,1,1,0.5); -glDisable (GL_DEPTH_TEST); -#endif - for (i=0 ; i<6 ; i++) - { - if (skymins[0][i] >= skymaxs[0][i] - || skymins[1][i] >= skymaxs[1][i]) - continue; - - GL_Bind (SKY_TEX+skytexorder[i]); -#if 0 -skymins[0][i] = -1; -skymins[1][i] = -1; -skymaxs[0][i] = 1; -skymaxs[1][i] = 1; -#endif - glBegin (GL_QUADS); - MakeSkyVec (skymins[0][i], skymins[1][i], i); - MakeSkyVec (skymins[0][i], skymaxs[1][i], i); - MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); - MakeSkyVec (skymaxs[0][i], skymins[1][i], i); - glEnd (); - } -#if 0 -glDisable (GL_BLEND); -glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -glColor4f (1,1,1,0.5); -glEnable (GL_DEPTH_TEST); -#endif -} - - -#endif - -//=============================================================== - -/* -============= -R_InitSky - -A sky texture is 256*128, with the right side being a masked overlay -============== -*/ -void R_InitSky (texture_t *mt) -{ - int i, j, p; - byte *src; - unsigned trans[128*128]; - unsigned transpix; - int r, g, b; - unsigned *rgba; - extern int skytexturenum; - - src = (byte *)mt + mt->offsets[0]; - - // make an average value for the back to avoid - // a fringe on the top level - - r = g = b = 0; - for (i=0 ; i<128 ; i++) - for (j=0 ; j<128 ; j++) - { - p = src[i*256 + j + 128]; - rgba = &d_8to24table[p]; - trans[(i*128) + j] = *rgba; - r += ((byte *)rgba)[0]; - g += ((byte *)rgba)[1]; - b += ((byte *)rgba)[2]; - } - - ((byte *)&transpix)[0] = r/(128*128); - ((byte *)&transpix)[1] = g/(128*128); - ((byte *)&transpix)[2] = b/(128*128); - ((byte *)&transpix)[3] = 0; - - - if (!solidskytexture) - solidskytexture = texture_extension_number++; - GL_Bind (solidskytexture ); - glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - - for (i=0 ; i<128 ; i++) - for (j=0 ; j<128 ; j++) - { - p = src[i*256 + j]; - if (p == 0) - trans[(i*128) + j] = transpix; - else - trans[(i*128) + j] = d_8to24table[p]; - } - - if (!alphaskytexture) - alphaskytexture = texture_extension_number++; - GL_Bind(alphaskytexture); - glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// gl_warp.c -- sky and water polygons + +#include "quakedef.h" + +extern model_t *loadmodel; + +int skytexturenum; + +int solidskytexture; +int alphaskytexture; +float speedscale; // for top sky and bottom sky + +msurface_t *warpface; + +extern cvar_t gl_subdivide_size; + +void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) +{ + int i, j; + float *v; + + mins[0] = mins[1] = mins[2] = 9999; + maxs[0] = maxs[1] = maxs[2] = -9999; + v = verts; + for (i=0 ; i maxs[j]) + maxs[j] = *v; + } +} + +void SubdividePolygon (int numverts, float *verts) +{ + int i, j, k; + vec3_t mins, maxs; + float m; + float *v; + vec3_t front[64], back[64]; + int f, b; + float dist[64]; + float frac; + glpoly_t *poly; + float s, t; + + if (numverts > 60) + Sys_Error ("numverts = %i", numverts); + + BoundPoly (numverts, verts, mins, maxs); + + for (i=0 ; i<3 ; i++) + { + m = (mins[i] + maxs[i]) * 0.5; + m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5); + if (maxs[i] - m < 8) + continue; + if (m - mins[i] < 8) + continue; + + // cut it + v = verts + i; + for (j=0 ; j= 0) + { + VectorCopy (v, front[f]); + f++; + } + if (dist[j] <= 0) + { + VectorCopy (v, back[b]); + b++; + } + if (dist[j] == 0 || dist[j+1] == 0) + continue; + if ( (dist[j] > 0) != (dist[j+1] > 0) ) + { + // clip point + frac = dist[j] / (dist[j] - dist[j+1]); + for (k=0 ; k<3 ; k++) + front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); + f++; + b++; + } + } + + SubdividePolygon (f, front[0]); + SubdividePolygon (b, back[0]); + return; + } + + poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); + poly->next = warpface->polys; + warpface->polys = poly; + poly->numverts = numverts; + for (i=0 ; iverts[i]); + s = DotProduct (verts, warpface->texinfo->vecs[0]); + t = DotProduct (verts, warpface->texinfo->vecs[1]); + poly->verts[i][3] = s; + poly->verts[i][4] = t; + } +} + +/* +================ +GL_SubdivideSurface + +Breaks a polygon up along axial 64 unit +boundaries so that turbulent and sky warps +can be done reasonably. +================ +*/ +void GL_SubdivideSurface (msurface_t *fa) +{ + vec3_t verts[64]; + int numverts; + int i; + int lindex; + float *vec; + + warpface = fa; + + // + // convert edges back to a normal polygon + // + numverts = 0; + for (i=0 ; inumedges ; i++) + { + lindex = loadmodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; + else + vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; + VectorCopy (vec, verts[numverts]); + numverts++; + } + + SubdividePolygon (numverts, verts[0]); +} + +//========================================================= + + + +// speed up sin calculations - Ed +float turbsin[] = +{ + #include "gl_warp_sin.h" +}; +#define TURBSCALE (256.0 / (2 * M_PI)) + +/* +============= +EmitWaterPolys + +Does a water warp on the pre-fragmented glpoly_t chain +============= +*/ +void EmitWaterPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t, os, ot; + + + for (p=fa->polys ; p ; p=p->next) + { + glBegin (GL_POLYGON); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + os = v[3]; + ot = v[4]; + + s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; + s *= (1.0/64); + + t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; + t *= (1.0/64); + + glTexCoord2f (s, t); + glVertex3fv (v); + } + glEnd (); + } +} + + + + +/* +============= +EmitSkyPolys +============= +*/ +void EmitSkyPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t; + vec3_t dir; + float length; + + for (p=fa->polys ; p ; p=p->next) + { + glBegin (GL_POLYGON); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + VectorSubtract (v, r_origin, dir); + dir[2] *= 3; // flatten the sphere + + length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; + length = sqrt (length); + length = 6*63/length; + + dir[0] *= length; + dir[1] *= length; + + s = (speedscale + dir[0]) * (1.0/128); + t = (speedscale + dir[1]) * (1.0/128); + + glTexCoord2f (s, t); + glVertex3fv (v); + } + glEnd (); + } +} + +/* +=============== +EmitBothSkyLayers + +Does a sky warp on the pre-fragmented glpoly_t chain +This will be called for brushmodels, the world +will have them chained together. +=============== +*/ +void EmitBothSkyLayers (msurface_t *fa) +{ + GL_DisableMultitexture(); + + GL_Bind (solidskytexture); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + glEnable (GL_BLEND); + GL_Bind (alphaskytexture); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + glDisable (GL_BLEND); +} + +#ifndef QUAKE2 +/* +================= +R_DrawSkyChain +================= +*/ +void R_DrawSkyChain (msurface_t *s) +{ + msurface_t *fa; + + GL_DisableMultitexture(); + + // used when gl_texsort is on + GL_Bind(solidskytexture); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + glEnable (GL_BLEND); + GL_Bind (alphaskytexture); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + glDisable (GL_BLEND); +} + +#endif + +/* +================================================================= + + Quake 2 environment sky + +================================================================= +*/ + +#ifdef QUAKE2 + + +#define SKY_TEX 2000 + +/* +================================================================= + + PCX Loading + +================================================================= +*/ + +typedef struct +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + unsigned short xmin,ymin,xmax,ymax; + unsigned short hres,vres; + unsigned char palette[48]; + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + char filler[58]; + unsigned data; // unbounded +} pcx_t; + +byte *pcx_rgb; + +/* +============ +LoadPCX +============ +*/ +void LoadPCX (FILE *f) +{ + pcx_t *pcx, pcxbuf; + byte palette[768]; + byte *pix; + int x, y; + int dataByte, runLength; + int count; + +// +// parse the PCX file +// + fread (&pcxbuf, 1, sizeof(pcxbuf), f); + + pcx = &pcxbuf; + + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8 + || pcx->xmax >= 320 + || pcx->ymax >= 256) + { + Con_Printf ("Bad pcx file\n"); + return; + } + + // seek to palette + fseek (f, -768, SEEK_END); + fread (palette, 1, 768, f); + + fseek (f, sizeof(pcxbuf) - 4, SEEK_SET); + + count = (pcx->xmax+1) * (pcx->ymax+1); + pcx_rgb = malloc( count * 4); + + for (y=0 ; y<=pcx->ymax ; y++) + { + pix = pcx_rgb + 4*y*(pcx->xmax+1); + for (x=0 ; x<=pcx->ymax ; ) + { + dataByte = fgetc(f); + + if((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = fgetc(f); + } + else + runLength = 1; + + while(runLength-- > 0) + { + pix[0] = palette[dataByte*3]; + pix[1] = palette[dataByte*3+1]; + pix[2] = palette[dataByte*3+2]; + pix[3] = 255; + pix += 4; + x++; + } + } + } +} + +/* +========================================================= + +TARGA LOADING + +========================================================= +*/ + +typedef struct _TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; +} TargaHeader; + + +TargaHeader targa_header; +byte *targa_rgba; + +int fgetLittleShort (FILE *f) +{ + byte b1, b2; + + b1 = fgetc(f); + b2 = fgetc(f); + + return (short)(b1 + b2*256); +} + +int fgetLittleLong (FILE *f) +{ + byte b1, b2, b3, b4; + + b1 = fgetc(f); + b2 = fgetc(f); + b3 = fgetc(f); + b4 = fgetc(f); + + return b1 + (b2<<8) + (b3<<16) + (b4<<24); +} + + +/* +============= +LoadTGA +============= +*/ +void LoadTGA (FILE *fin) +{ + int columns, rows, numPixels; + byte *pixbuf; + int row, column; + + targa_header.id_length = fgetc(fin); + targa_header.colormap_type = fgetc(fin); + targa_header.image_type = fgetc(fin); + + targa_header.colormap_index = fgetLittleShort(fin); + targa_header.colormap_length = fgetLittleShort(fin); + targa_header.colormap_size = fgetc(fin); + targa_header.x_origin = fgetLittleShort(fin); + targa_header.y_origin = fgetLittleShort(fin); + targa_header.width = fgetLittleShort(fin); + targa_header.height = fgetLittleShort(fin); + targa_header.pixel_size = fgetc(fin); + targa_header.attributes = fgetc(fin); + + if (targa_header.image_type!=2 + && targa_header.image_type!=10) + Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); + + if (targa_header.colormap_type !=0 + || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) + Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); + + columns = targa_header.width; + rows = targa_header.height; + numPixels = columns * rows; + + targa_rgba = malloc (numPixels*4); + + if (targa_header.id_length != 0) + fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment + + if (targa_header.image_type==2) { // Uncompressed, RGB images + for(row=rows-1; row>=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + else { // non run-length packet + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + } + breakOut:; + } + } + + fclose(fin); +} + +/* +================== +R_LoadSkys +================== +*/ +char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; +void R_LoadSkys (void) +{ + int i; + FILE *f; + char name[64]; + + for (i=0 ; i<6 ; i++) + { + GL_Bind (SKY_TEX + i); + sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]); + COM_FOpenFile (name, &f); + if (!f) + { + Con_Printf ("Couldn't load %s\n", name); + continue; + } + LoadTGA (f); +// LoadPCX (f); + + glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba); +// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb); + + free (targa_rgba); +// free (pcx_rgb); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } +} + + +vec3_t skyclip[6] = { + {1,1,0}, + {1,-1,0}, + {0,-1,1}, + {0,1,1}, + {1,0,1}, + {-1,0,1} +}; +int c_sky; + +// 1 = s, 2 = t, 3 = 2048 +int st_to_vec[6][3] = +{ + {3,-1,2}, + {-3,1,2}, + + {1,3,2}, + {-1,-3,2}, + + {-2,-1,3}, // 0 degrees yaw, look straight up + {2,-1,-3} // look straight down + +// {-1,2,3}, +// {1,2,-3} +}; + +// s = [0]/[2], t = [1]/[2] +int vec_to_st[6][3] = +{ + {-2,3,1}, + {2,3,-1}, + + {1,3,2}, + {-1,3,-2}, + + {-2,-1,3}, + {-2,1,-3} + +// {-1,2,3}, +// {1,2,-3} +}; + +float skymins[2][6], skymaxs[2][6]; + +void DrawSkyPolygon (int nump, vec3_t vecs) +{ + int i,j; + vec3_t v, av; + float s, t, dv; + int axis; + float *vp; + + c_sky++; +#if 0 +glBegin (GL_POLYGON); +for (i=0 ; i av[1] && av[0] > av[2]) + { + if (v[0] < 0) + axis = 1; + else + axis = 0; + } + else if (av[1] > av[2] && av[1] > av[0]) + { + if (v[1] < 0) + axis = 3; + else + axis = 2; + } + else + { + if (v[2] < 0) + axis = 5; + else + axis = 4; + } + + // project new texture coords + for (i=0 ; i 0) + dv = vecs[j - 1]; + else + dv = -vecs[-j - 1]; + + j = vec_to_st[axis][0]; + if (j < 0) + s = -vecs[-j -1] / dv; + else + s = vecs[j-1] / dv; + j = vec_to_st[axis][1]; + if (j < 0) + t = -vecs[-j -1] / dv; + else + t = vecs[j-1] / dv; + + if (s < skymins[0][axis]) + skymins[0][axis] = s; + if (t < skymins[1][axis]) + skymins[1][axis] = t; + if (s > skymaxs[0][axis]) + skymaxs[0][axis] = s; + if (t > skymaxs[1][axis]) + skymaxs[1][axis] = t; + } +} + +#define MAX_CLIP_VERTS 64 +void ClipSkyPolygon (int nump, vec3_t vecs, int stage) +{ + float *norm; + float *v; + qboolean front, back; + float d, e; + float dists[MAX_CLIP_VERTS]; + int sides[MAX_CLIP_VERTS]; + vec3_t newv[2][MAX_CLIP_VERTS]; + int newc[2]; + int i, j; + + if (nump > MAX_CLIP_VERTS-2) + Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS"); + if (stage == 6) + { // fully clipped, so draw it + DrawSkyPolygon (nump, vecs); + return; + } + + front = back = false; + norm = skyclip[stage]; + for (i=0, v = vecs ; i ON_EPSILON) + { + front = true; + sides[i] = SIDE_FRONT; + } + else if (d < ON_EPSILON) + { + back = true; + sides[i] = SIDE_BACK; + } + else + sides[i] = SIDE_ON; + dists[i] = d; + } + + if (!front || !back) + { // not clipped + ClipSkyPolygon (nump, vecs, stage+1); + return; + } + + // clip it + sides[i] = sides[0]; + dists[i] = dists[0]; + VectorCopy (vecs, (vecs+(i*3)) ); + newc[0] = newc[1] = 0; + + for (i=0, v = vecs ; itexturechain) + { + for (p=fa->polys ; p ; p=p->next) + { + for (i=0 ; inumverts ; i++) + { + VectorSubtract (p->verts[i], r_origin, verts[i]); + } + ClipSkyPolygon (p->numverts, verts[0], 0); + } + } +} + + +/* +============== +R_ClearSkyBox +============== +*/ +void R_ClearSkyBox (void) +{ + int i; + + for (i=0 ; i<6 ; i++) + { + skymins[0][i] = skymins[1][i] = 9999; + skymaxs[0][i] = skymaxs[1][i] = -9999; + } +} + + +void MakeSkyVec (float s, float t, int axis) +{ + vec3_t v, b; + int j, k; + + b[0] = s*2048; + b[1] = t*2048; + b[2] = 2048; + + for (j=0 ; j<3 ; j++) + { + k = st_to_vec[axis][j]; + if (k < 0) + v[j] = -b[-k - 1]; + else + v[j] = b[k - 1]; + v[j] += r_origin[j]; + } + + // avoid bilerp seam + s = (s+1)*0.5; + t = (t+1)*0.5; + + if (s < 1.0/512) + s = 1.0/512; + else if (s > 511.0/512) + s = 511.0/512; + if (t < 1.0/512) + t = 1.0/512; + else if (t > 511.0/512) + t = 511.0/512; + + t = 1.0 - t; + glTexCoord2f (s, t); + glVertex3fv (v); +} + +/* +============== +R_DrawSkyBox +============== +*/ +int skytexorder[6] = {0,2,1,3,4,5}; +void R_DrawSkyBox (void) +{ + int i, j, k; + vec3_t v; + float s, t; + +#if 0 +glEnable (GL_BLEND); +glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +glColor4f (1,1,1,0.5); +glDisable (GL_DEPTH_TEST); +#endif + for (i=0 ; i<6 ; i++) + { + if (skymins[0][i] >= skymaxs[0][i] + || skymins[1][i] >= skymaxs[1][i]) + continue; + + GL_Bind (SKY_TEX+skytexorder[i]); +#if 0 +skymins[0][i] = -1; +skymins[1][i] = -1; +skymaxs[0][i] = 1; +skymaxs[1][i] = 1; +#endif + glBegin (GL_QUADS); + MakeSkyVec (skymins[0][i], skymins[1][i], i); + MakeSkyVec (skymins[0][i], skymaxs[1][i], i); + MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); + MakeSkyVec (skymaxs[0][i], skymins[1][i], i); + glEnd (); + } +#if 0 +glDisable (GL_BLEND); +glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +glColor4f (1,1,1,0.5); +glEnable (GL_DEPTH_TEST); +#endif +} + + +#endif + +//=============================================================== + +/* +============= +R_InitSky + +A sky texture is 256*128, with the right side being a masked overlay +============== +*/ +void R_InitSky (texture_t *mt) +{ + int i, j, p; + byte *src; + unsigned trans[128*128]; + unsigned transpix; + int r, g, b; + unsigned *rgba; + extern int skytexturenum; + + src = (byte *)mt + mt->offsets[0]; + + // make an average value for the back to avoid + // a fringe on the top level + + r = g = b = 0; + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + { + p = src[i*256 + j + 128]; + rgba = &d_8to24table[p]; + trans[(i*128) + j] = *rgba; + r += ((byte *)rgba)[0]; + g += ((byte *)rgba)[1]; + b += ((byte *)rgba)[2]; + } + + ((byte *)&transpix)[0] = r/(128*128); + ((byte *)&transpix)[1] = g/(128*128); + ((byte *)&transpix)[2] = b/(128*128); + ((byte *)&transpix)[3] = 0; + + + if (!solidskytexture) + solidskytexture = texture_extension_number++; + GL_Bind (solidskytexture ); + glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + { + p = src[i*256 + j]; + if (p == 0) + trans[(i*128) + j] = transpix; + else + trans[(i*128) + j] = d_8to24table[p]; + } + + if (!alphaskytexture) + alphaskytexture = texture_extension_number++; + GL_Bind(alphaskytexture); + glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +} + diff --git a/source/in_null.c b/source/in_null.c index 5749539..33b09b7 100644 --- a/source/in_null.c +++ b/source/in_null.c @@ -18,12 +18,12 @@ void IN_Move (usercmd_t *cmd) { } -/* -=========== -IN_ModeChanged -=========== -*/ -void IN_ModeChanged (void) -{ -} - +/* +=========== +IN_ModeChanged +=========== +*/ +void IN_ModeChanged (void) +{ +} + diff --git a/source/in_win.c b/source/in_win.c index ecbb22c..ca7d0a1 100644 --- a/source/in_win.c +++ b/source/in_win.c @@ -1,1232 +1,1232 @@ -/* -Copyright (C) 1996-1997 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 -#include "quakedef.h" -#include "winquake.h" -//#include "dosisms.h" - -#define DINPUT_BUFFERSIZE 16 -#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) - -HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, - LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); - -// mouse variables -cvar_t m_filter = {"m_filter","0"}; - -int mouse_buttons; -int mouse_oldbuttonstate; -POINT current_pos; -int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; - -static qboolean restore_spi; -static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; -qboolean mouseinitialized; -static qboolean mouseparmsvalid, mouseactivatetoggle; -static qboolean mouseshowtoggle = 1; -static qboolean dinput_acquired; -static unsigned int mstate_di; -unsigned int uiWheelMessage; - -qboolean mouseactive; - -// 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 -}; - -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]; - -// 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 in_joystick = {"joystick","0", true}; -cvar_t joy_name = {"joyname", "joystick"}; -cvar_t joy_advanced = {"joyadvanced", "0"}; -cvar_t joy_advaxisx = {"joyadvaxisx", "0"}; -cvar_t joy_advaxisy = {"joyadvaxisy", "0"}; -cvar_t joy_advaxisz = {"joyadvaxisz", "0"}; -cvar_t joy_advaxisr = {"joyadvaxisr", "0"}; -cvar_t joy_advaxisu = {"joyadvaxisu", "0"}; -cvar_t joy_advaxisv = {"joyadvaxisv", "0"}; -cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"}; -cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"}; -cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"}; -cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"}; -cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"}; -cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"}; -cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"}; -cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"}; -cvar_t joy_wwhack1 = {"joywwhack1", "0.0"}; -cvar_t joy_wwhack2 = {"joywwhack2", "0.0"}; - -qboolean joy_avail, joy_advancedinit, joy_haspov; -DWORD joy_oldbuttonstate, joy_oldpovstate; - -int joy_id; -DWORD joy_flags; -DWORD joy_numbuttons; - -static LPDIRECTINPUT g_pdi; -static LPDIRECTINPUTDEVICE g_pMouse; - -static JOYINFOEX ji; - -static HINSTANCE hInstDI; - -static qboolean dinput; - -typedef struct MYDATA { - LONG lX; // X axis goes here - LONG lY; // Y axis goes here - LONG lZ; // Z axis goes here - BYTE bButtonA; // One button goes here - BYTE bButtonB; // Another button goes here - BYTE bButtonC; // Another button goes here - BYTE bButtonD; // Another button goes here -} MYDATA; - -static DIOBJECTDATAFORMAT rgodf[] = { - { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, -}; - -#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) - -static DIDATAFORMAT df = { - sizeof(DIDATAFORMAT), // this structure - sizeof(DIOBJECTDATAFORMAT), // size of object data format - DIDF_RELAXIS, // absolute axis coordinates - sizeof(MYDATA), // device data size - NUM_OBJECTS, // number of objects - rgodf, // and here they are -}; - -// forward-referenced functions -void IN_StartupJoystick (void); -void Joy_AdvancedUpdate_f (void); -void IN_JoyMove (usercmd_t *cmd); - - -/* -=========== -Force_CenterView_f -=========== -*/ -void Force_CenterView_f (void) -{ - cl.viewangles[PITCH] = 0; -} - - -/* -=========== -IN_UpdateClipCursor -=========== -*/ -void IN_UpdateClipCursor (void) -{ - - if (mouseinitialized && mouseactive && !dinput) - { - ClipCursor (&window_rect); - } -} - - -/* -=========== -IN_ShowMouse -=========== -*/ -void IN_ShowMouse (void) -{ - - if (!mouseshowtoggle) - { - ShowCursor (TRUE); - mouseshowtoggle = 1; - } -} - - -/* -=========== -IN_HideMouse -=========== -*/ -void IN_HideMouse (void) -{ - - if (mouseshowtoggle) - { - ShowCursor (FALSE); - mouseshowtoggle = 0; - } -} - - -/* -=========== -IN_ActivateMouse -=========== -*/ -void IN_ActivateMouse (void) -{ - - mouseactivatetoggle = true; - - if (mouseinitialized) - { - if (dinput) - { - if (g_pMouse) - { - if (!dinput_acquired) - { - IDirectInputDevice_Acquire(g_pMouse); - dinput_acquired = true; - } - } - else - { - return; - } - } - else - { - if (mouseparmsvalid) - restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); - - SetCursorPos (window_center_x, window_center_y); - SetCapture (mainwindow); - ClipCursor (&window_rect); - } - - mouseactive = true; - } -} - - -/* -=========== -IN_SetQuakeMouseState -=========== -*/ -void IN_SetQuakeMouseState (void) -{ - if (mouseactivatetoggle) - IN_ActivateMouse (); -} - - -/* -=========== -IN_DeactivateMouse -=========== -*/ -void IN_DeactivateMouse (void) -{ - - mouseactivatetoggle = false; - - if (mouseinitialized) - { - if (dinput) - { - if (g_pMouse) - { - if (dinput_acquired) - { - IDirectInputDevice_Unacquire(g_pMouse); - dinput_acquired = false; - } - } - } - else - { - if (restore_spi) - SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); - - ClipCursor (NULL); - ReleaseCapture (); - } - - mouseactive = false; - } -} - - -/* -=========== -IN_RestoreOriginalMouseState -=========== -*/ -void IN_RestoreOriginalMouseState (void) -{ - if (mouseactivatetoggle) - { - IN_DeactivateMouse (); - mouseactivatetoggle = true; - } - -// try to redraw the cursor so it gets reinitialized, because sometimes it -// has garbage after the mode switch - ShowCursor (TRUE); - ShowCursor (FALSE); -} - - -/* -=========== -IN_InitDInput -=========== -*/ -qboolean IN_InitDInput (void) -{ - HRESULT hr; - DIPROPDWORD dipdw = { - { - sizeof(DIPROPDWORD), // diph.dwSize - sizeof(DIPROPHEADER), // diph.dwHeaderSize - 0, // diph.dwObj - DIPH_DEVICE, // diph.dwHow - }, - DINPUT_BUFFERSIZE, // dwData - }; - - if (!hInstDI) - { - hInstDI = LoadLibrary("dinput.dll"); - - if (hInstDI == NULL) - { - Con_SafePrintf ("Couldn't load dinput.dll\n"); - return false; - } - } - - if (!pDirectInputCreate) - { - pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA"); - - if (!pDirectInputCreate) - { - Con_SafePrintf ("Couldn't get DI proc addr\n"); - return false; - } - } - -// register with DirectInput and get an IDirectInput to play with. - hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); - - if (FAILED(hr)) - { - return false; - } - -// obtain an interface to the system mouse device. - hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't open DI mouse device\n"); - return false; - } - -// set the data format to "mouse format". - hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI mouse format\n"); - return false; - } - -// set the cooperativity level. - hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, - DISCL_EXCLUSIVE | DISCL_FOREGROUND); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI coop level\n"); - return false; - } - - -// set the buffer size to DINPUT_BUFFERSIZE elements. -// the buffer size is a DWORD property associated with the device - hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI buffersize\n"); - return false; - } - - return true; -} - - -/* -=========== -IN_StartupMouse -=========== -*/ -void IN_StartupMouse (void) -{ - HDC hdc; - - if ( COM_CheckParm ("-nomouse") ) - return; - - mouseinitialized = true; - - if (COM_CheckParm ("-dinput")) - { - dinput = IN_InitDInput (); - - if (dinput) - { - Con_SafePrintf ("DirectInput initialized\n"); - } - else - { - Con_SafePrintf ("DirectInput not initialized\n"); - } - } - - if (!dinput) - { - mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); - - if (mouseparmsvalid) - { - if ( COM_CheckParm ("-noforcemspd") ) - newmouseparms[2] = originalmouseparms[2]; - - if ( COM_CheckParm ("-noforcemaccel") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - } - - if ( COM_CheckParm ("-noforcemparms") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - newmouseparms[2] = originalmouseparms[2]; - } - } - } - - mouse_buttons = 3; - -// if a fullscreen video mode was set before the mouse was initialized, -// set the mouse state appropriately - if (mouseactivatetoggle) - IN_ActivateMouse (); -} - - -/* -=========== -IN_Init -=========== -*/ -void IN_Init (void) -{ - // mouse variables - Cvar_RegisterVariable (&m_filter); - - // joystick variables - Cvar_RegisterVariable (&in_joystick); - Cvar_RegisterVariable (&joy_name); - Cvar_RegisterVariable (&joy_advanced); - Cvar_RegisterVariable (&joy_advaxisx); - Cvar_RegisterVariable (&joy_advaxisy); - Cvar_RegisterVariable (&joy_advaxisz); - Cvar_RegisterVariable (&joy_advaxisr); - Cvar_RegisterVariable (&joy_advaxisu); - Cvar_RegisterVariable (&joy_advaxisv); - Cvar_RegisterVariable (&joy_forwardthreshold); - Cvar_RegisterVariable (&joy_sidethreshold); - Cvar_RegisterVariable (&joy_pitchthreshold); - Cvar_RegisterVariable (&joy_yawthreshold); - Cvar_RegisterVariable (&joy_forwardsensitivity); - Cvar_RegisterVariable (&joy_sidesensitivity); - Cvar_RegisterVariable (&joy_pitchsensitivity); - Cvar_RegisterVariable (&joy_yawsensitivity); - Cvar_RegisterVariable (&joy_wwhack1); - Cvar_RegisterVariable (&joy_wwhack2); - - Cmd_AddCommand ("force_centerview", Force_CenterView_f); - Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); - - uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); - - IN_StartupMouse (); - IN_StartupJoystick (); -} - -/* -=========== -IN_Shutdown -=========== -*/ -void IN_Shutdown (void) -{ - - IN_DeactivateMouse (); - IN_ShowMouse (); - - if (g_pMouse) - { - IDirectInputDevice_Release(g_pMouse); - g_pMouse = NULL; - } - - if (g_pdi) - { - IDirectInput_Release(g_pdi); - g_pdi = NULL; - } -} - - -/* -=========== -IN_MouseEvent -=========== -*/ -void IN_MouseEvent (int mstate) -{ - int i; - - if (mouseactive && !dinput) - { - // perform button actions - for (i=0 ; isidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) - { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } - else - { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } - -// if the mouse has moved, force it to the center, so there's room to move - if (mx || my) - { - SetCursorPos (window_center_x, window_center_y); - } -} - - -/* -=========== -IN_Move -=========== -*/ -void IN_Move (usercmd_t *cmd) -{ - - if (ActiveApp && !Minimized) - { - IN_MouseMove (cmd); - IN_JoyMove (cmd); - } -} - - -/* -=========== -IN_Accumulate -=========== -*/ -void IN_Accumulate (void) -{ - int mx, my; - HDC hdc; - - if (mouseactive) - { - GetCursorPos (¤t_pos); - - mx_accum += current_pos.x - window_center_x; - my_accum += current_pos.y - window_center_y; - - // force the mouse to the center, so there's room to move - SetCursorPos (window_center_x, window_center_y); - } -} - - -/* -=================== -IN_ClearStates -=================== -*/ -void IN_ClearStates (void) -{ - - if (mouseactive) - { - mx_accum = 0; - my_accum = 0; - mouse_oldbuttonstate = 0; - } -} - - -/* -=============== -IN_StartupJoystick -=============== -*/ -void IN_StartupJoystick (void) -{ - int i, numdevs; - JOYCAPS jc; - MMRESULT mmr; - - // assume no joystick - joy_avail = false; - - // abort startup if user requests no joystick - if ( COM_CheckParm ("-nojoy") ) - return; - - // verify joystick driver is present - if ((numdevs = joyGetNumDevs ()) == 0) - { - Con_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 14000.0) - fTemp = 14000.0; - // restore direction information - fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; - } - } - - // convert range from -32768..32767 to -1..1 - fAxisValue /= 32768.0; - - switch (dwAxisMap[i]) - { - case AxisForward: - if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) - { - // 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; - } - V_StopPitchDrift(); - } - else - { - // no pitch movement - // disable pitch return-to-center unless requested by user - // *** this code can be removed when the lookspring bug is fixed - // *** the bug always has the lookspring feature on - if(lookspring.value == 0.0) - V_StopPitchDrift(); - } - } - 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 AxisTurn: - if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) - { - // 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 (in_mlook.state & 1) - { - 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; - } - V_StopPitchDrift(); - } - else - { - // no pitch movement - // disable pitch return-to-center unless requested by user - // *** this code can be removed when the lookspring bug is fixed - // *** the bug always has the lookspring feature on - if(lookspring.value == 0.0) - V_StopPitchDrift(); - } - } - break; - - default: - break; - } - } - - // bounds check pitch - if (cl.viewangles[PITCH] > 80.0) - cl.viewangles[PITCH] = 80.0; - if (cl.viewangles[PITCH] < -70.0) - cl.viewangles[PITCH] = -70.0; -} +/* +Copyright (C) 1996-1997 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 +#include "quakedef.h" +#include "winquake.h" +//#include "dosisms.h" + +#define DINPUT_BUFFERSIZE 16 +#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) + +HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, + LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); + +// mouse variables +cvar_t m_filter = {"m_filter","0"}; + +int mouse_buttons; +int mouse_oldbuttonstate; +POINT current_pos; +int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; + +static qboolean restore_spi; +static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; +qboolean mouseinitialized; +static qboolean mouseparmsvalid, mouseactivatetoggle; +static qboolean mouseshowtoggle = 1; +static qboolean dinput_acquired; +static unsigned int mstate_di; +unsigned int uiWheelMessage; + +qboolean mouseactive; + +// 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 +}; + +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]; + +// 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 in_joystick = {"joystick","0", true}; +cvar_t joy_name = {"joyname", "joystick"}; +cvar_t joy_advanced = {"joyadvanced", "0"}; +cvar_t joy_advaxisx = {"joyadvaxisx", "0"}; +cvar_t joy_advaxisy = {"joyadvaxisy", "0"}; +cvar_t joy_advaxisz = {"joyadvaxisz", "0"}; +cvar_t joy_advaxisr = {"joyadvaxisr", "0"}; +cvar_t joy_advaxisu = {"joyadvaxisu", "0"}; +cvar_t joy_advaxisv = {"joyadvaxisv", "0"}; +cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"}; +cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"}; +cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"}; +cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"}; +cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"}; +cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"}; +cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"}; +cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"}; +cvar_t joy_wwhack1 = {"joywwhack1", "0.0"}; +cvar_t joy_wwhack2 = {"joywwhack2", "0.0"}; + +qboolean joy_avail, joy_advancedinit, joy_haspov; +DWORD joy_oldbuttonstate, joy_oldpovstate; + +int joy_id; +DWORD joy_flags; +DWORD joy_numbuttons; + +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; + +static JOYINFOEX ji; + +static HINSTANCE hInstDI; + +static qboolean dinput; + +typedef struct MYDATA { + LONG lX; // X axis goes here + LONG lY; // Y axis goes here + LONG lZ; // Z axis goes here + BYTE bButtonA; // One button goes here + BYTE bButtonB; // Another button goes here + BYTE bButtonC; // Another button goes here + BYTE bButtonD; // Another button goes here +} MYDATA; + +static DIOBJECTDATAFORMAT rgodf[] = { + { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, +}; + +#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) + +static DIDATAFORMAT df = { + sizeof(DIDATAFORMAT), // this structure + sizeof(DIOBJECTDATAFORMAT), // size of object data format + DIDF_RELAXIS, // absolute axis coordinates + sizeof(MYDATA), // device data size + NUM_OBJECTS, // number of objects + rgodf, // and here they are +}; + +// forward-referenced functions +void IN_StartupJoystick (void); +void Joy_AdvancedUpdate_f (void); +void IN_JoyMove (usercmd_t *cmd); + + +/* +=========== +Force_CenterView_f +=========== +*/ +void Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + + +/* +=========== +IN_UpdateClipCursor +=========== +*/ +void IN_UpdateClipCursor (void) +{ + + if (mouseinitialized && mouseactive && !dinput) + { + ClipCursor (&window_rect); + } +} + + +/* +=========== +IN_ShowMouse +=========== +*/ +void IN_ShowMouse (void) +{ + + if (!mouseshowtoggle) + { + ShowCursor (TRUE); + mouseshowtoggle = 1; + } +} + + +/* +=========== +IN_HideMouse +=========== +*/ +void IN_HideMouse (void) +{ + + if (mouseshowtoggle) + { + ShowCursor (FALSE); + mouseshowtoggle = 0; + } +} + + +/* +=========== +IN_ActivateMouse +=========== +*/ +void IN_ActivateMouse (void) +{ + + mouseactivatetoggle = true; + + if (mouseinitialized) + { + if (dinput) + { + if (g_pMouse) + { + if (!dinput_acquired) + { + IDirectInputDevice_Acquire(g_pMouse); + dinput_acquired = true; + } + } + else + { + return; + } + } + else + { + if (mouseparmsvalid) + restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); + + SetCursorPos (window_center_x, window_center_y); + SetCapture (mainwindow); + ClipCursor (&window_rect); + } + + mouseactive = true; + } +} + + +/* +=========== +IN_SetQuakeMouseState +=========== +*/ +void IN_SetQuakeMouseState (void) +{ + if (mouseactivatetoggle) + IN_ActivateMouse (); +} + + +/* +=========== +IN_DeactivateMouse +=========== +*/ +void IN_DeactivateMouse (void) +{ + + mouseactivatetoggle = false; + + if (mouseinitialized) + { + if (dinput) + { + if (g_pMouse) + { + if (dinput_acquired) + { + IDirectInputDevice_Unacquire(g_pMouse); + dinput_acquired = false; + } + } + } + else + { + if (restore_spi) + SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); + + ClipCursor (NULL); + ReleaseCapture (); + } + + mouseactive = false; + } +} + + +/* +=========== +IN_RestoreOriginalMouseState +=========== +*/ +void IN_RestoreOriginalMouseState (void) +{ + if (mouseactivatetoggle) + { + IN_DeactivateMouse (); + mouseactivatetoggle = true; + } + +// try to redraw the cursor so it gets reinitialized, because sometimes it +// has garbage after the mode switch + ShowCursor (TRUE); + ShowCursor (FALSE); +} + + +/* +=========== +IN_InitDInput +=========== +*/ +qboolean IN_InitDInput (void) +{ + HRESULT hr; + DIPROPDWORD dipdw = { + { + sizeof(DIPROPDWORD), // diph.dwSize + sizeof(DIPROPHEADER), // diph.dwHeaderSize + 0, // diph.dwObj + DIPH_DEVICE, // diph.dwHow + }, + DINPUT_BUFFERSIZE, // dwData + }; + + if (!hInstDI) + { + hInstDI = LoadLibrary("dinput.dll"); + + if (hInstDI == NULL) + { + Con_SafePrintf ("Couldn't load dinput.dll\n"); + return false; + } + } + + if (!pDirectInputCreate) + { + pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA"); + + if (!pDirectInputCreate) + { + Con_SafePrintf ("Couldn't get DI proc addr\n"); + return false; + } + } + +// register with DirectInput and get an IDirectInput to play with. + hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); + + if (FAILED(hr)) + { + return false; + } + +// obtain an interface to the system mouse device. + hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't open DI mouse device\n"); + return false; + } + +// set the data format to "mouse format". + hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI mouse format\n"); + return false; + } + +// set the cooperativity level. + hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, + DISCL_EXCLUSIVE | DISCL_FOREGROUND); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI coop level\n"); + return false; + } + + +// set the buffer size to DINPUT_BUFFERSIZE elements. +// the buffer size is a DWORD property associated with the device + hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI buffersize\n"); + return false; + } + + return true; +} + + +/* +=========== +IN_StartupMouse +=========== +*/ +void IN_StartupMouse (void) +{ + HDC hdc; + + if ( COM_CheckParm ("-nomouse") ) + return; + + mouseinitialized = true; + + if (COM_CheckParm ("-dinput")) + { + dinput = IN_InitDInput (); + + if (dinput) + { + Con_SafePrintf ("DirectInput initialized\n"); + } + else + { + Con_SafePrintf ("DirectInput not initialized\n"); + } + } + + if (!dinput) + { + mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); + + if (mouseparmsvalid) + { + if ( COM_CheckParm ("-noforcemspd") ) + newmouseparms[2] = originalmouseparms[2]; + + if ( COM_CheckParm ("-noforcemaccel") ) + { + newmouseparms[0] = originalmouseparms[0]; + newmouseparms[1] = originalmouseparms[1]; + } + + if ( COM_CheckParm ("-noforcemparms") ) + { + newmouseparms[0] = originalmouseparms[0]; + newmouseparms[1] = originalmouseparms[1]; + newmouseparms[2] = originalmouseparms[2]; + } + } + } + + mouse_buttons = 3; + +// if a fullscreen video mode was set before the mouse was initialized, +// set the mouse state appropriately + if (mouseactivatetoggle) + IN_ActivateMouse (); +} + + +/* +=========== +IN_Init +=========== +*/ +void IN_Init (void) +{ + // mouse variables + Cvar_RegisterVariable (&m_filter); + + // joystick variables + Cvar_RegisterVariable (&in_joystick); + Cvar_RegisterVariable (&joy_name); + Cvar_RegisterVariable (&joy_advanced); + Cvar_RegisterVariable (&joy_advaxisx); + Cvar_RegisterVariable (&joy_advaxisy); + Cvar_RegisterVariable (&joy_advaxisz); + Cvar_RegisterVariable (&joy_advaxisr); + Cvar_RegisterVariable (&joy_advaxisu); + Cvar_RegisterVariable (&joy_advaxisv); + Cvar_RegisterVariable (&joy_forwardthreshold); + Cvar_RegisterVariable (&joy_sidethreshold); + Cvar_RegisterVariable (&joy_pitchthreshold); + Cvar_RegisterVariable (&joy_yawthreshold); + Cvar_RegisterVariable (&joy_forwardsensitivity); + Cvar_RegisterVariable (&joy_sidesensitivity); + Cvar_RegisterVariable (&joy_pitchsensitivity); + Cvar_RegisterVariable (&joy_yawsensitivity); + Cvar_RegisterVariable (&joy_wwhack1); + Cvar_RegisterVariable (&joy_wwhack2); + + Cmd_AddCommand ("force_centerview", Force_CenterView_f); + Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); + + uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); + + IN_StartupMouse (); + IN_StartupJoystick (); +} + +/* +=========== +IN_Shutdown +=========== +*/ +void IN_Shutdown (void) +{ + + IN_DeactivateMouse (); + IN_ShowMouse (); + + if (g_pMouse) + { + IDirectInputDevice_Release(g_pMouse); + g_pMouse = NULL; + } + + if (g_pdi) + { + IDirectInput_Release(g_pdi); + g_pdi = NULL; + } +} + + +/* +=========== +IN_MouseEvent +=========== +*/ +void IN_MouseEvent (int mstate) +{ + int i; + + if (mouseactive && !dinput) + { + // perform button actions + for (i=0 ; isidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } + +// if the mouse has moved, force it to the center, so there's room to move + if (mx || my) + { + SetCursorPos (window_center_x, window_center_y); + } +} + + +/* +=========== +IN_Move +=========== +*/ +void IN_Move (usercmd_t *cmd) +{ + + if (ActiveApp && !Minimized) + { + IN_MouseMove (cmd); + IN_JoyMove (cmd); + } +} + + +/* +=========== +IN_Accumulate +=========== +*/ +void IN_Accumulate (void) +{ + int mx, my; + HDC hdc; + + if (mouseactive) + { + GetCursorPos (¤t_pos); + + mx_accum += current_pos.x - window_center_x; + my_accum += current_pos.y - window_center_y; + + // force the mouse to the center, so there's room to move + SetCursorPos (window_center_x, window_center_y); + } +} + + +/* +=================== +IN_ClearStates +=================== +*/ +void IN_ClearStates (void) +{ + + if (mouseactive) + { + mx_accum = 0; + my_accum = 0; + mouse_oldbuttonstate = 0; + } +} + + +/* +=============== +IN_StartupJoystick +=============== +*/ +void IN_StartupJoystick (void) +{ + int i, numdevs; + JOYCAPS jc; + MMRESULT mmr; + + // assume no joystick + joy_avail = false; + + // abort startup if user requests no joystick + if ( COM_CheckParm ("-nojoy") ) + return; + + // verify joystick driver is present + if ((numdevs = joyGetNumDevs ()) == 0) + { + Con_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 14000.0) + fTemp = 14000.0; + // restore direction information + fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; + } + } + + // convert range from -32768..32767 to -1..1 + fAxisValue /= 32768.0; + + switch (dwAxisMap[i]) + { + case AxisForward: + if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) + { + // 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; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.value == 0.0) + V_StopPitchDrift(); + } + } + 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 AxisTurn: + if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) + { + // 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 (in_mlook.state & 1) + { + 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; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.value == 0.0) + V_StopPitchDrift(); + } + } + break; + + default: + break; + } + } + + // bounds check pitch + if (cl.viewangles[PITCH] > 80.0) + cl.viewangles[PITCH] = 80.0; + if (cl.viewangles[PITCH] < -70.0) + cl.viewangles[PITCH] = -70.0; +} diff --git a/source/keys.c b/source/keys.c index 291aeea..572a7cc 100644 --- a/source/keys.c +++ b/source/keys.c @@ -1,839 +1,839 @@ -/* -Copyright (C) 1996-1997 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 "quakedef.h" -#ifdef _WINDOWS -#include -#endif -/* - -key up events are sent even if in console mode - -*/ - - -#define MAXCMDLINE 256 -char key_lines[32][MAXCMDLINE]; -int key_linepos; -int shift_down=false; -int key_lastpress; - -int edit_line=0; -int history_line=0; - -keydest_t key_dest; - -int key_count; // incremented every key event - -char *keybindings[256]; -qboolean consolekeys[256]; // if true, can't be rebound while in console -qboolean menubound[256]; // if true, can't be rebound while in menu -int keyshift[256]; // key to map to if shift held down in console -int key_repeats[256]; // if > 1, it is autorepeating -qboolean keydown[256]; - -typedef struct -{ - char *name; - int keynum; -} keyname_t; - -keyname_t keynames[] = -{ - {"TAB", K_TAB}, - {"ENTER", K_ENTER}, - {"ESCAPE", K_ESCAPE}, - {"SPACE", K_SPACE}, - {"BACKSPACE", K_BACKSPACE}, - {"UPARROW", K_UPARROW}, - {"DOWNARROW", K_DOWNARROW}, - {"LEFTARROW", K_LEFTARROW}, - {"RIGHTARROW", K_RIGHTARROW}, - - {"ALT", K_ALT}, - {"CTRL", K_CTRL}, - {"SHIFT", K_SHIFT}, - - {"F1", K_F1}, - {"F2", K_F2}, - {"F3", K_F3}, - {"F4", K_F4}, - {"F5", K_F5}, - {"F6", K_F6}, - {"F7", K_F7}, - {"F8", K_F8}, - {"F9", K_F9}, - {"F10", K_F10}, - {"F11", K_F11}, - {"F12", K_F12}, - - {"INS", K_INS}, - {"DEL", K_DEL}, - {"PGDN", K_PGDN}, - {"PGUP", K_PGUP}, - {"HOME", K_HOME}, - {"END", K_END}, - - {"MOUSE1", K_MOUSE1}, - {"MOUSE2", K_MOUSE2}, - {"MOUSE3", K_MOUSE3}, - - {"JOY1", K_JOY1}, - {"JOY2", K_JOY2}, - {"JOY3", K_JOY3}, - {"JOY4", K_JOY4}, - - {"AUX1", K_AUX1}, - {"AUX2", K_AUX2}, - {"AUX3", K_AUX3}, - {"AUX4", K_AUX4}, - {"AUX5", K_AUX5}, - {"AUX6", K_AUX6}, - {"AUX7", K_AUX7}, - {"AUX8", K_AUX8}, - {"AUX9", K_AUX9}, - {"AUX10", K_AUX10}, - {"AUX11", K_AUX11}, - {"AUX12", K_AUX12}, - {"AUX13", K_AUX13}, - {"AUX14", K_AUX14}, - {"AUX15", K_AUX15}, - {"AUX16", K_AUX16}, - {"AUX17", K_AUX17}, - {"AUX18", K_AUX18}, - {"AUX19", K_AUX19}, - {"AUX20", K_AUX20}, - {"AUX21", K_AUX21}, - {"AUX22", K_AUX22}, - {"AUX23", K_AUX23}, - {"AUX24", K_AUX24}, - {"AUX25", K_AUX25}, - {"AUX26", K_AUX26}, - {"AUX27", K_AUX27}, - {"AUX28", K_AUX28}, - {"AUX29", K_AUX29}, - {"AUX30", K_AUX30}, - {"AUX31", K_AUX31}, - {"AUX32", K_AUX32}, - - {"PAUSE", K_PAUSE}, - - {"MWHEELUP", K_MWHEELUP}, - {"MWHEELDOWN", K_MWHEELDOWN}, - - {"SEMICOLON", ';'}, // because a raw semicolon seperates commands - - {NULL,0} -}; - -/* -============================================================================== - - LINE TYPING INTO THE CONSOLE - -============================================================================== -*/ - -qboolean CheckForCommand (void) -{ - char command[128]; - char *cmd, *s; - int i; - - s = key_lines[edit_line]+1; - - for (i=0 ; i<127 ; i++) - if (s[i] <= ' ') - break; - else - command[i] = s[i]; - command[i] = 0; - - cmd = Cmd_CompleteCommand (command); - if (!cmd || strcmp (cmd, command)) - cmd = Cvar_CompleteVariable (command); - if (!cmd || strcmp (cmd, command) ) - return false; // just a chat message - return true; -} - -void CompleteCommand (void) -{ - char *cmd, *s; - - s = key_lines[edit_line]+1; - if (*s == '\\' || *s == '/') - s++; - - cmd = Cmd_CompleteCommand (s); - if (!cmd) - cmd = Cvar_CompleteVariable (s); - if (cmd) - { - key_lines[edit_line][1] = '/'; - Q_strcpy (key_lines[edit_line]+2, cmd); - key_linepos = Q_strlen(cmd)+2; - key_lines[edit_line][key_linepos] = ' '; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - return; - } -} - -/* -==================== -Key_Console - -Interactive line editing and console scrollback -==================== -*/ -void Key_Console (int key) -{ -#ifdef _WIN32 - char *cmd, *s; - int i; - HANDLE th; - char *clipText, *textCopied; -#endif - - if (key == K_ENTER) - { // backslash text are commands, else chat - if (key_lines[edit_line][1] == '\\' || key_lines[edit_line][1] == '/') - Cbuf_AddText (key_lines[edit_line]+2); // skip the > - else if (CheckForCommand()) - Cbuf_AddText (key_lines[edit_line]+1); // valid command - else - { // convert to a chat message - if (cls.state >= ca_connected) - Cbuf_AddText ("say "); - Cbuf_AddText (key_lines[edit_line]+1); // skip the > - } - - Cbuf_AddText ("\n"); - Con_Printf ("%s\n",key_lines[edit_line]); - edit_line = (edit_line + 1) & 31; - history_line = edit_line; - key_lines[edit_line][0] = ']'; - key_linepos = 1; - if (cls.state == ca_disconnected) - SCR_UpdateScreen (); // force an update, because the command - // may take some time - return; - } - - if (key == K_TAB) - { // command completion - CompleteCommand (); - return; - } - - if (key == K_BACKSPACE || key == K_LEFTARROW) - { - if (key_linepos > 1) - key_linepos--; - return; - } - - if (key == K_UPARROW) - { - do - { - history_line = (history_line - 1) & 31; - } while (history_line != edit_line - && !key_lines[history_line][1]); - if (history_line == edit_line) - history_line = (edit_line+1)&31; - Q_strcpy(key_lines[edit_line], key_lines[history_line]); - key_linepos = Q_strlen(key_lines[edit_line]); - return; - } - - if (key == K_DOWNARROW) - { - if (history_line == edit_line) return; - do - { - history_line = (history_line + 1) & 31; - } - while (history_line != edit_line - && !key_lines[history_line][1]); - if (history_line == edit_line) - { - key_lines[edit_line][0] = ']'; - key_linepos = 1; - } - else - { - Q_strcpy(key_lines[edit_line], key_lines[history_line]); - key_linepos = Q_strlen(key_lines[edit_line]); - } - return; - } - - if (key == K_PGUP || key==K_MWHEELUP) - { - con->display -= 2; - return; - } - - if (key == K_PGDN || key==K_MWHEELDOWN) - { - con->display += 2; - if (con->display > con->current) - con->display = con->current; - return; - } - - if (key == K_HOME) - { - con->display = con->current - con_totallines + 10; - return; - } - - if (key == K_END) - { - con->display = con->current; - return; - } - -#ifdef _WIN32 - if ((key=='V' || key=='v') && GetKeyState(VK_CONTROL)<0) { - if (OpenClipboard(NULL)) { - th = GetClipboardData(CF_TEXT); - if (th) { - clipText = GlobalLock(th); - if (clipText) { - textCopied = malloc(GlobalSize(th)+1); - strcpy(textCopied, clipText); - /* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b"); - i = strlen(textCopied); - if (i+key_linepos>=MAXCMDLINE) - i=MAXCMDLINE-key_linepos; - if (i>0) { - textCopied[i]=0; - strcat(key_lines[edit_line], textCopied); - key_linepos+=i;; - } - free(textCopied); - } - GlobalUnlock(th); - } - CloseClipboard(); - return; - } - } -#endif - - if (key < 32 || key > 127) - return; // non printable - - if (key_linepos < MAXCMDLINE-1) - { - key_lines[edit_line][key_linepos] = key; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - } - -} - -//============================================================================ - -qboolean chat_team; -char chat_buffer[MAXCMDLINE]; -int chat_bufferlen = 0; - -void Key_Message (int key) -{ - - if (key == K_ENTER) - { - if (chat_team) - Cbuf_AddText ("say_team \""); - else - Cbuf_AddText ("say \""); - Cbuf_AddText(chat_buffer); - Cbuf_AddText("\"\n"); - - key_dest = key_game; - chat_bufferlen = 0; - chat_buffer[0] = 0; - return; - } - - if (key == K_ESCAPE) - { - key_dest = key_game; - chat_bufferlen = 0; - chat_buffer[0] = 0; - return; - } - - if (key < 32 || key > 127) - return; // non printable - - if (key == K_BACKSPACE) - { - if (chat_bufferlen) - { - chat_bufferlen--; - chat_buffer[chat_bufferlen] = 0; - } - return; - } - - if (chat_bufferlen == sizeof(chat_buffer)-1) - return; // all full - - chat_buffer[chat_bufferlen++] = key; - chat_buffer[chat_bufferlen] = 0; -} - -//============================================================================ - - -/* -=================== -Key_StringToKeynum - -Returns a key number to be used to index keybindings[] by looking at -the given string. Single ascii characters return themselves, while -the K_* names are matched up. -=================== -*/ -int Key_StringToKeynum (char *str) -{ - keyname_t *kn; - - if (!str || !str[0]) - return -1; - if (!str[1]) - return str[0]; - - for (kn=keynames ; kn->name ; kn++) - { - if (!Q_strcasecmp(str,kn->name)) - return kn->keynum; - } - return -1; -} - -/* -=================== -Key_KeynumToString - -Returns a string (either a single ascii char, or a K_* name) for the -given keynum. -FIXME: handle quote special (general escape sequence?) -=================== -*/ -char *Key_KeynumToString (int keynum) -{ - keyname_t *kn; - static char tinystr[2]; - - if (keynum == -1) - return ""; - if (keynum > 32 && keynum < 127) - { // printable ascii - tinystr[0] = keynum; - tinystr[1] = 0; - return tinystr; - } - - for (kn=keynames ; kn->name ; kn++) - if (keynum == kn->keynum) - return kn->name; - - return ""; -} - - -/* -=================== -Key_SetBinding -=================== -*/ -void Key_SetBinding (int keynum, char *binding) -{ - char *new; - int l; - - if (keynum == -1) - return; - -// free old bindings - if (keybindings[keynum]) - { - Z_Free (keybindings[keynum]); - keybindings[keynum] = NULL; - } - -// allocate memory for new binding - l = Q_strlen (binding); - new = Z_Malloc (l+1); - Q_strcpy (new, binding); - new[l] = 0; - keybindings[keynum] = new; -} - -/* -=================== -Key_Unbind_f -=================== -*/ -void Key_Unbind_f (void) -{ - int b; - - if (Cmd_Argc() != 2) - { - Con_Printf ("unbind : remove commands from a key\n"); - return; - } - - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } - - Key_SetBinding (b, ""); -} - -void Key_Unbindall_f (void) -{ - int i; - - for (i=0 ; i<256 ; i++) - if (keybindings[i]) - Key_SetBinding (i, ""); -} - - -/* -=================== -Key_Bind_f -=================== -*/ -void Key_Bind_f (void) -{ - int i, c, b; - char cmd[1024]; - - c = Cmd_Argc(); - - if (c != 2 && c != 3) - { - Con_Printf ("bind [command] : attach a command to a key\n"); - return; - } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } - - if (c == 2) - { - if (keybindings[b]) - Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); - else - Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); - return; - } - -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != (c-1)) - strcat (cmd, " "); - } - - Key_SetBinding (b, cmd); -} - -/* -============ -Key_WriteBindings - -Writes lines containing "bind key value" -============ -*/ -void Key_WriteBindings (FILE *f) -{ - int i; - - for (i=0 ; i<256 ; i++) - if (keybindings[i]) - fprintf (f, "bind %s \"%s\"\n", Key_KeynumToString(i), keybindings[i]); -} - - -/* -=================== -Key_Init -=================== -*/ -void Key_Init (void) -{ - int i; - - for (i=0 ; i<32 ; i++) - { - key_lines[i][0] = ']'; - key_lines[i][1] = 0; - } - key_linepos = 1; - -// -// init ascii characters in console mode -// - for (i=32 ; i<128 ; i++) - consolekeys[i] = true; - consolekeys[K_ENTER] = true; - consolekeys[K_TAB] = true; - consolekeys[K_LEFTARROW] = true; - consolekeys[K_RIGHTARROW] = true; - consolekeys[K_UPARROW] = true; - consolekeys[K_DOWNARROW] = true; - consolekeys[K_BACKSPACE] = true; - consolekeys[K_HOME] = true; - consolekeys[K_END] = true; - consolekeys[K_PGUP] = true; - consolekeys[K_PGDN] = true; - consolekeys[K_SHIFT] = true; - consolekeys[K_MWHEELUP] = true; - consolekeys[K_MWHEELDOWN] = true; - consolekeys['`'] = false; - consolekeys['~'] = false; - - for (i=0 ; i<256 ; i++) - keyshift[i] = i; - for (i='a' ; i<='z' ; i++) - keyshift[i] = i - 'a' + 'A'; - keyshift['1'] = '!'; - keyshift['2'] = '@'; - keyshift['3'] = '#'; - keyshift['4'] = '$'; - keyshift['5'] = '%'; - keyshift['6'] = '^'; - keyshift['7'] = '&'; - keyshift['8'] = '*'; - keyshift['9'] = '('; - keyshift['0'] = ')'; - keyshift['-'] = '_'; - keyshift['='] = '+'; - keyshift[','] = '<'; - keyshift['.'] = '>'; - keyshift['/'] = '?'; - keyshift[';'] = ':'; - keyshift['\''] = '"'; - keyshift['['] = '{'; - keyshift[']'] = '}'; - keyshift['`'] = '~'; - keyshift['\\'] = '|'; - - menubound[K_ESCAPE] = true; - for (i=0 ; i<12 ; i++) - menubound[K_F1+i] = true; - -// -// register our functions -// - Cmd_AddCommand ("bind",Key_Bind_f); - Cmd_AddCommand ("unbind",Key_Unbind_f); - Cmd_AddCommand ("unbindall",Key_Unbindall_f); - - -} - -/* -=================== -Key_Event - -Called by the system between frames for both key up and key down events -Should NOT be called during an interrupt! -=================== -*/ -void Key_Event (int key, qboolean down) -{ - char *kb; - char cmd[1024]; - -// Con_Printf ("%i : %i\n", key, down); //@@@ - - keydown[key] = down; - - if (!down) - key_repeats[key] = 0; - - key_lastpress = key; - key_count++; - if (key_count <= 0) - { - return; // just catching keys for Con_NotifyBox - } - -// update auto-repeat status - if (down) - { - key_repeats[key]++; - if (key != K_BACKSPACE - && key != K_PAUSE - && key != K_PGUP - && key != K_PGDN - && key_repeats[key] > 1) - return; // ignore most autorepeats - - if (key >= 200 && !keybindings[key]) - Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); - } - - if (key == K_SHIFT) - shift_down = down; - -// -// handle escape specialy, so the user can never unbind it -// - if (key == K_ESCAPE) - { - if (!down) - return; - switch (key_dest) - { - case key_message: - Key_Message (key); - break; - case key_menu: - M_Keydown (key); - break; - case key_game: - case key_console: - M_ToggleMenu_f (); - break; - default: - Sys_Error ("Bad key_dest"); - } - return; - } - -// -// key up events only generate commands if the game key binding is -// a button command (leading + sign). These will occur even in console mode, -// to keep the character from continuing an action started before a console -// switch. Button commands include the kenum as a parameter, so multiple -// downs can be matched with ups -// - if (!down) - { - kb = keybindings[key]; - if (kb && kb[0] == '+') - { - sprintf (cmd, "-%s %i\n", kb+1, key); - Cbuf_AddText (cmd); - } - if (keyshift[key] != key) - { - kb = keybindings[keyshift[key]]; - if (kb && kb[0] == '+') - { - sprintf (cmd, "-%s %i\n", kb+1, key); - Cbuf_AddText (cmd); - } - } - return; - } - -// -// during demo playback, most keys bring up the main menu -// - if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) - { - M_ToggleMenu_f (); - return; - } - -// -// if not a consolekey, send to the interpreter no matter what mode is -// - if ( (key_dest == key_menu && menubound[key]) - || (key_dest == key_console && !consolekeys[key]) - || (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ) ) - { - kb = keybindings[key]; - if (kb) - { - if (kb[0] == '+') - { // button commands add keynum as a parm - sprintf (cmd, "%s %i\n", kb, key); - Cbuf_AddText (cmd); - } - else - { - Cbuf_AddText (kb); - Cbuf_AddText ("\n"); - } - } - return; - } - - if (!down) - return; // other systems only care about key down events - - if (shift_down) - key = keyshift[key]; - - switch (key_dest) - { - case key_message: - Key_Message (key); - break; - case key_menu: - M_Keydown (key); - break; - - case key_game: - case key_console: - Key_Console (key); - break; - default: - Sys_Error ("Bad key_dest"); - } -} - -/* -=================== -Key_ClearStates -=================== -*/ -void Key_ClearStates (void) -{ - int i; - - for (i=0 ; i<256 ; i++) - { - keydown[i] = false; - key_repeats[i] = false; - } -} - +/* +Copyright (C) 1996-1997 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 "quakedef.h" +#ifdef _WINDOWS +#include +#endif +/* + +key up events are sent even if in console mode + +*/ + + +#define MAXCMDLINE 256 +char key_lines[32][MAXCMDLINE]; +int key_linepos; +int shift_down=false; +int key_lastpress; + +int edit_line=0; +int history_line=0; + +keydest_t key_dest; + +int key_count; // incremented every key event + +char *keybindings[256]; +qboolean consolekeys[256]; // if true, can't be rebound while in console +qboolean menubound[256]; // if true, can't be rebound while in menu +int keyshift[256]; // key to map to if shift held down in console +int key_repeats[256]; // if > 1, it is autorepeating +qboolean keydown[256]; + +typedef struct +{ + char *name; + int keynum; +} keyname_t; + +keyname_t keynames[] = +{ + {"TAB", K_TAB}, + {"ENTER", K_ENTER}, + {"ESCAPE", K_ESCAPE}, + {"SPACE", K_SPACE}, + {"BACKSPACE", K_BACKSPACE}, + {"UPARROW", K_UPARROW}, + {"DOWNARROW", K_DOWNARROW}, + {"LEFTARROW", K_LEFTARROW}, + {"RIGHTARROW", K_RIGHTARROW}, + + {"ALT", K_ALT}, + {"CTRL", K_CTRL}, + {"SHIFT", K_SHIFT}, + + {"F1", K_F1}, + {"F2", K_F2}, + {"F3", K_F3}, + {"F4", K_F4}, + {"F5", K_F5}, + {"F6", K_F6}, + {"F7", K_F7}, + {"F8", K_F8}, + {"F9", K_F9}, + {"F10", K_F10}, + {"F11", K_F11}, + {"F12", K_F12}, + + {"INS", K_INS}, + {"DEL", K_DEL}, + {"PGDN", K_PGDN}, + {"PGUP", K_PGUP}, + {"HOME", K_HOME}, + {"END", K_END}, + + {"MOUSE1", K_MOUSE1}, + {"MOUSE2", K_MOUSE2}, + {"MOUSE3", K_MOUSE3}, + + {"JOY1", K_JOY1}, + {"JOY2", K_JOY2}, + {"JOY3", K_JOY3}, + {"JOY4", K_JOY4}, + + {"AUX1", K_AUX1}, + {"AUX2", K_AUX2}, + {"AUX3", K_AUX3}, + {"AUX4", K_AUX4}, + {"AUX5", K_AUX5}, + {"AUX6", K_AUX6}, + {"AUX7", K_AUX7}, + {"AUX8", K_AUX8}, + {"AUX9", K_AUX9}, + {"AUX10", K_AUX10}, + {"AUX11", K_AUX11}, + {"AUX12", K_AUX12}, + {"AUX13", K_AUX13}, + {"AUX14", K_AUX14}, + {"AUX15", K_AUX15}, + {"AUX16", K_AUX16}, + {"AUX17", K_AUX17}, + {"AUX18", K_AUX18}, + {"AUX19", K_AUX19}, + {"AUX20", K_AUX20}, + {"AUX21", K_AUX21}, + {"AUX22", K_AUX22}, + {"AUX23", K_AUX23}, + {"AUX24", K_AUX24}, + {"AUX25", K_AUX25}, + {"AUX26", K_AUX26}, + {"AUX27", K_AUX27}, + {"AUX28", K_AUX28}, + {"AUX29", K_AUX29}, + {"AUX30", K_AUX30}, + {"AUX31", K_AUX31}, + {"AUX32", K_AUX32}, + + {"PAUSE", K_PAUSE}, + + {"MWHEELUP", K_MWHEELUP}, + {"MWHEELDOWN", K_MWHEELDOWN}, + + {"SEMICOLON", ';'}, // because a raw semicolon seperates commands + + {NULL,0} +}; + +/* +============================================================================== + + LINE TYPING INTO THE CONSOLE + +============================================================================== +*/ + +qboolean CheckForCommand (void) +{ + char command[128]; + char *cmd, *s; + int i; + + s = key_lines[edit_line]+1; + + for (i=0 ; i<127 ; i++) + if (s[i] <= ' ') + break; + else + command[i] = s[i]; + command[i] = 0; + + cmd = Cmd_CompleteCommand (command); + if (!cmd || strcmp (cmd, command)) + cmd = Cvar_CompleteVariable (command); + if (!cmd || strcmp (cmd, command) ) + return false; // just a chat message + return true; +} + +void CompleteCommand (void) +{ + char *cmd, *s; + + s = key_lines[edit_line]+1; + if (*s == '\\' || *s == '/') + s++; + + cmd = Cmd_CompleteCommand (s); + if (!cmd) + cmd = Cvar_CompleteVariable (s); + if (cmd) + { + key_lines[edit_line][1] = '/'; + Q_strcpy (key_lines[edit_line]+2, cmd); + key_linepos = Q_strlen(cmd)+2; + key_lines[edit_line][key_linepos] = ' '; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + return; + } +} + +/* +==================== +Key_Console + +Interactive line editing and console scrollback +==================== +*/ +void Key_Console (int key) +{ +#ifdef _WIN32 + char *cmd, *s; + int i; + HANDLE th; + char *clipText, *textCopied; +#endif + + if (key == K_ENTER) + { // backslash text are commands, else chat + if (key_lines[edit_line][1] == '\\' || key_lines[edit_line][1] == '/') + Cbuf_AddText (key_lines[edit_line]+2); // skip the > + else if (CheckForCommand()) + Cbuf_AddText (key_lines[edit_line]+1); // valid command + else + { // convert to a chat message + if (cls.state >= ca_connected) + Cbuf_AddText ("say "); + Cbuf_AddText (key_lines[edit_line]+1); // skip the > + } + + Cbuf_AddText ("\n"); + Con_Printf ("%s\n",key_lines[edit_line]); + edit_line = (edit_line + 1) & 31; + history_line = edit_line; + key_lines[edit_line][0] = ']'; + key_linepos = 1; + if (cls.state == ca_disconnected) + SCR_UpdateScreen (); // force an update, because the command + // may take some time + return; + } + + if (key == K_TAB) + { // command completion + CompleteCommand (); + return; + } + + if (key == K_BACKSPACE || key == K_LEFTARROW) + { + if (key_linepos > 1) + key_linepos--; + return; + } + + if (key == K_UPARROW) + { + do + { + history_line = (history_line - 1) & 31; + } while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + history_line = (edit_line+1)&31; + Q_strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + return; + } + + if (key == K_DOWNARROW) + { + if (history_line == edit_line) return; + do + { + history_line = (history_line + 1) & 31; + } + while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + { + key_lines[edit_line][0] = ']'; + key_linepos = 1; + } + else + { + Q_strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + } + return; + } + + if (key == K_PGUP || key==K_MWHEELUP) + { + con->display -= 2; + return; + } + + if (key == K_PGDN || key==K_MWHEELDOWN) + { + con->display += 2; + if (con->display > con->current) + con->display = con->current; + return; + } + + if (key == K_HOME) + { + con->display = con->current - con_totallines + 10; + return; + } + + if (key == K_END) + { + con->display = con->current; + return; + } + +#ifdef _WIN32 + if ((key=='V' || key=='v') && GetKeyState(VK_CONTROL)<0) { + if (OpenClipboard(NULL)) { + th = GetClipboardData(CF_TEXT); + if (th) { + clipText = GlobalLock(th); + if (clipText) { + textCopied = malloc(GlobalSize(th)+1); + strcpy(textCopied, clipText); + /* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b"); + i = strlen(textCopied); + if (i+key_linepos>=MAXCMDLINE) + i=MAXCMDLINE-key_linepos; + if (i>0) { + textCopied[i]=0; + strcat(key_lines[edit_line], textCopied); + key_linepos+=i;; + } + free(textCopied); + } + GlobalUnlock(th); + } + CloseClipboard(); + return; + } + } +#endif + + if (key < 32 || key > 127) + return; // non printable + + if (key_linepos < MAXCMDLINE-1) + { + key_lines[edit_line][key_linepos] = key; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + } + +} + +//============================================================================ + +qboolean chat_team; +char chat_buffer[MAXCMDLINE]; +int chat_bufferlen = 0; + +void Key_Message (int key) +{ + + if (key == K_ENTER) + { + if (chat_team) + Cbuf_AddText ("say_team \""); + else + Cbuf_AddText ("say \""); + Cbuf_AddText(chat_buffer); + Cbuf_AddText("\"\n"); + + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key == K_ESCAPE) + { + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key < 32 || key > 127) + return; // non printable + + if (key == K_BACKSPACE) + { + if (chat_bufferlen) + { + chat_bufferlen--; + chat_buffer[chat_bufferlen] = 0; + } + return; + } + + if (chat_bufferlen == sizeof(chat_buffer)-1) + return; // all full + + chat_buffer[chat_bufferlen++] = key; + chat_buffer[chat_bufferlen] = 0; +} + +//============================================================================ + + +/* +=================== +Key_StringToKeynum + +Returns a key number to be used to index keybindings[] by looking at +the given string. Single ascii characters return themselves, while +the K_* names are matched up. +=================== +*/ +int Key_StringToKeynum (char *str) +{ + keyname_t *kn; + + if (!str || !str[0]) + return -1; + if (!str[1]) + return str[0]; + + for (kn=keynames ; kn->name ; kn++) + { + if (!Q_strcasecmp(str,kn->name)) + return kn->keynum; + } + return -1; +} + +/* +=================== +Key_KeynumToString + +Returns a string (either a single ascii char, or a K_* name) for the +given keynum. +FIXME: handle quote special (general escape sequence?) +=================== +*/ +char *Key_KeynumToString (int keynum) +{ + keyname_t *kn; + static char tinystr[2]; + + if (keynum == -1) + return ""; + if (keynum > 32 && keynum < 127) + { // printable ascii + tinystr[0] = keynum; + tinystr[1] = 0; + return tinystr; + } + + for (kn=keynames ; kn->name ; kn++) + if (keynum == kn->keynum) + return kn->name; + + return ""; +} + + +/* +=================== +Key_SetBinding +=================== +*/ +void Key_SetBinding (int keynum, char *binding) +{ + char *new; + int l; + + if (keynum == -1) + return; + +// free old bindings + if (keybindings[keynum]) + { + Z_Free (keybindings[keynum]); + keybindings[keynum] = NULL; + } + +// allocate memory for new binding + l = Q_strlen (binding); + new = Z_Malloc (l+1); + Q_strcpy (new, binding); + new[l] = 0; + keybindings[keynum] = new; +} + +/* +=================== +Key_Unbind_f +=================== +*/ +void Key_Unbind_f (void) +{ + int b; + + if (Cmd_Argc() != 2) + { + Con_Printf ("unbind : remove commands from a key\n"); + return; + } + + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + Key_SetBinding (b, ""); +} + +void Key_Unbindall_f (void) +{ + int i; + + for (i=0 ; i<256 ; i++) + if (keybindings[i]) + Key_SetBinding (i, ""); +} + + +/* +=================== +Key_Bind_f +=================== +*/ +void Key_Bind_f (void) +{ + int i, c, b; + char cmd[1024]; + + c = Cmd_Argc(); + + if (c != 2 && c != 3) + { + Con_Printf ("bind [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + if (c == 2) + { + if (keybindings[b]) + Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); + else + Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); + return; + } + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i=2 ; i< c ; i++) + { + strcat (cmd, Cmd_Argv(i)); + if (i != (c-1)) + strcat (cmd, " "); + } + + Key_SetBinding (b, cmd); +} + +/* +============ +Key_WriteBindings + +Writes lines containing "bind key value" +============ +*/ +void Key_WriteBindings (FILE *f) +{ + int i; + + for (i=0 ; i<256 ; i++) + if (keybindings[i]) + fprintf (f, "bind %s \"%s\"\n", Key_KeynumToString(i), keybindings[i]); +} + + +/* +=================== +Key_Init +=================== +*/ +void Key_Init (void) +{ + int i; + + for (i=0 ; i<32 ; i++) + { + key_lines[i][0] = ']'; + key_lines[i][1] = 0; + } + key_linepos = 1; + +// +// init ascii characters in console mode +// + for (i=32 ; i<128 ; i++) + consolekeys[i] = true; + consolekeys[K_ENTER] = true; + consolekeys[K_TAB] = true; + consolekeys[K_LEFTARROW] = true; + consolekeys[K_RIGHTARROW] = true; + consolekeys[K_UPARROW] = true; + consolekeys[K_DOWNARROW] = true; + consolekeys[K_BACKSPACE] = true; + consolekeys[K_HOME] = true; + consolekeys[K_END] = true; + consolekeys[K_PGUP] = true; + consolekeys[K_PGDN] = true; + consolekeys[K_SHIFT] = true; + consolekeys[K_MWHEELUP] = true; + consolekeys[K_MWHEELDOWN] = true; + consolekeys['`'] = false; + consolekeys['~'] = false; + + for (i=0 ; i<256 ; i++) + keyshift[i] = i; + for (i='a' ; i<='z' ; i++) + keyshift[i] = i - 'a' + 'A'; + keyshift['1'] = '!'; + keyshift['2'] = '@'; + keyshift['3'] = '#'; + keyshift['4'] = '$'; + keyshift['5'] = '%'; + keyshift['6'] = '^'; + keyshift['7'] = '&'; + keyshift['8'] = '*'; + keyshift['9'] = '('; + keyshift['0'] = ')'; + keyshift['-'] = '_'; + keyshift['='] = '+'; + keyshift[','] = '<'; + keyshift['.'] = '>'; + keyshift['/'] = '?'; + keyshift[';'] = ':'; + keyshift['\''] = '"'; + keyshift['['] = '{'; + keyshift[']'] = '}'; + keyshift['`'] = '~'; + keyshift['\\'] = '|'; + + menubound[K_ESCAPE] = true; + for (i=0 ; i<12 ; i++) + menubound[K_F1+i] = true; + +// +// register our functions +// + Cmd_AddCommand ("bind",Key_Bind_f); + Cmd_AddCommand ("unbind",Key_Unbind_f); + Cmd_AddCommand ("unbindall",Key_Unbindall_f); + + +} + +/* +=================== +Key_Event + +Called by the system between frames for both key up and key down events +Should NOT be called during an interrupt! +=================== +*/ +void Key_Event (int key, qboolean down) +{ + char *kb; + char cmd[1024]; + +// Con_Printf ("%i : %i\n", key, down); //@@@ + + keydown[key] = down; + + if (!down) + key_repeats[key] = 0; + + key_lastpress = key; + key_count++; + if (key_count <= 0) + { + return; // just catching keys for Con_NotifyBox + } + +// update auto-repeat status + if (down) + { + key_repeats[key]++; + if (key != K_BACKSPACE + && key != K_PAUSE + && key != K_PGUP + && key != K_PGDN + && key_repeats[key] > 1) + return; // ignore most autorepeats + + if (key >= 200 && !keybindings[key]) + Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); + } + + if (key == K_SHIFT) + shift_down = down; + +// +// handle escape specialy, so the user can never unbind it +// + if (key == K_ESCAPE) + { + if (!down) + return; + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + M_Keydown (key); + break; + case key_game: + case key_console: + M_ToggleMenu_f (); + break; + default: + Sys_Error ("Bad key_dest"); + } + return; + } + +// +// key up events only generate commands if the game key binding is +// a button command (leading + sign). These will occur even in console mode, +// to keep the character from continuing an action started before a console +// switch. Button commands include the kenum as a parameter, so multiple +// downs can be matched with ups +// + if (!down) + { + kb = keybindings[key]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + if (keyshift[key] != key) + { + kb = keybindings[keyshift[key]]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + } + return; + } + +// +// during demo playback, most keys bring up the main menu +// + if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) + { + M_ToggleMenu_f (); + return; + } + +// +// if not a consolekey, send to the interpreter no matter what mode is +// + if ( (key_dest == key_menu && menubound[key]) + || (key_dest == key_console && !consolekeys[key]) + || (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ) ) + { + kb = keybindings[key]; + if (kb) + { + if (kb[0] == '+') + { // button commands add keynum as a parm + sprintf (cmd, "%s %i\n", kb, key); + Cbuf_AddText (cmd); + } + else + { + Cbuf_AddText (kb); + Cbuf_AddText ("\n"); + } + } + return; + } + + if (!down) + return; // other systems only care about key down events + + if (shift_down) + key = keyshift[key]; + + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + M_Keydown (key); + break; + + case key_game: + case key_console: + Key_Console (key); + break; + default: + Sys_Error ("Bad key_dest"); + } +} + +/* +=================== +Key_ClearStates +=================== +*/ +void Key_ClearStates (void) +{ + int i; + + for (i=0 ; i<256 ; i++) + { + keydown[i] = false; + key_repeats[i] = false; + } +} + diff --git a/source/mathlib.c b/source/mathlib.c index 630ae19..cebdaf5 100644 --- a/source/mathlib.c +++ b/source/mathlib.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // mathlib.c -- math primitives #include diff --git a/source/menu.c b/source/menu.c index e9a7126..a356a19 100644 --- a/source/menu.c +++ b/source/menu.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" #include "winquake.h" diff --git a/source/model.c b/source/model.c index e486920..bb24c8d 100644 --- a/source/model.c +++ b/source/model.c @@ -1,28 +1,28 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // models.c -- model loading and caching // models are the only shared resource between a client and server running // on the same machine. -#include "qwsvdef.h" +#include "qwsvdef.h" model_t *loadmodel; char loadname[32]; // for hunk tags @@ -37,10 +37,10 @@ byte mod_novis[MAX_MAP_LEAFS/8]; #define MAX_MOD_KNOWN 256 model_t mod_known[MAX_MOD_KNOWN]; int mod_numknown; - -texture_t r_notexture_mip; - -unsigned *model_checksum; + +texture_t r_notexture_mip; + +unsigned *model_checksum; /* =============== @@ -1063,22 +1063,22 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) ((int *)header)[i] = LittleLong ( ((int *)header)[i]); // load into heap - - mod->checksum = 0; - mod->checksum2 = 0; - - // checksum all of the map, except for entities - for (i = 0; i < HEADER_LUMPS; i++) { - if (i == LUMP_ENTITIES) - continue; - mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, - header->lumps[i].filelen)); - - if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) - continue; - mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, - header->lumps[i].filelen)); - } + + mod->checksum = 0; + mod->checksum2 = 0; + + // checksum all of the map, except for entities + for (i = 0; i < HEADER_LUMPS; i++) { + if (i == LUMP_ENTITIES) + continue; + mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, + header->lumps[i].filelen)); + + if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) + continue; + mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, + header->lumps[i].filelen)); + } Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); Mod_LoadEdges (&header->lumps[LUMP_EDGES]); diff --git a/source/model.c.client b/source/model.c.client index 5b3b31c..5ec926c 100644 --- a/source/model.c.client +++ b/source/model.c.client @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // models.c -- model loading and caching // models are the only shared resource between a client and server running diff --git a/source/net_chan.c b/source/net_chan.c index ea17a0b..278c8f4 100644 --- a/source/net_chan.c +++ b/source/net_chan.c @@ -1,23 +1,24 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include "quakedef.h" #ifdef _WIN32 @@ -328,7 +329,6 @@ qboolean Netchan_Process (netchan_t *chan) #ifdef SERVERONLY int qport; #endif - int i; if ( #ifndef SERVERONLY diff --git a/source/net_udp.c b/source/net_udp.c index 4c76b9c..80abe05 100644 --- a/source/net_udp.c +++ b/source/net_udp.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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_main.c #include "quakedef.h" @@ -158,9 +158,6 @@ qboolean NET_StringToAdr (char *s, netadr_t *a) // the IP is NOT one of our interfaces. qboolean NET_IsClientLegal(netadr_t *adr) { - struct sockaddr_in sadr; - int newsocket; - #if 0 if (adr->ip[0] == 127) return false; // no local connections period diff --git a/source/net_wins.c b/source/net_wins.c index a4c9e7b..85a14a9 100644 --- a/source/net_wins.c +++ b/source/net_wins.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" diff --git a/source/nonintel.c b/source/nonintel.c index b53fcbd..9163ee5 100644 --- a/source/nonintel.c +++ b/source/nonintel.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // // nonintel.c: code for non-Intel processors only // diff --git a/source/pmove.c b/source/pmove.c index 8bc1483..7be5c70 100644 --- a/source/pmove.c +++ b/source/pmove.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" @@ -775,7 +775,7 @@ SpectatorMove */ void SpectatorMove (void) { - float speed, drop, friction, control, newspeed, accel; + float speed, drop, friction, control, newspeed; float currentspeed, addspeed, accelspeed; int i; vec3_t wishvel; diff --git a/source/pmovetst.c b/source/pmovetst.c index e442f28..763e341 100644 --- a/source/pmovetst.c +++ b/source/pmovetst.c @@ -1,414 +1,414 @@ -/* -Copyright (C) 1996-1997 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 "quakedef.h" - -static hull_t box_hull; -static dclipnode_t box_clipnodes[6]; -static mplane_t box_planes[6]; - -extern vec3_t player_mins; -extern vec3_t player_maxs; - -/* -=================== -PM_InitBoxHull - -Set up the planes and clipnodes so that the six floats of a bounding box -can just be stored out and get a proper hull_t structure. -=================== -*/ -void PM_InitBoxHull (void) -{ - int i; - int side; - - box_hull.clipnodes = box_clipnodes; - box_hull.planes = box_planes; - box_hull.firstclipnode = 0; - box_hull.lastclipnode = 5; - - for (i=0 ; i<6 ; i++) - { - box_clipnodes[i].planenum = i; - - side = i&1; - - box_clipnodes[i].children[side] = CONTENTS_EMPTY; - if (i != 5) - box_clipnodes[i].children[side^1] = i + 1; - else - box_clipnodes[i].children[side^1] = CONTENTS_SOLID; - - box_planes[i].type = i>>1; - box_planes[i].normal[i>>1] = 1; - } - -} - - -/* -=================== -PM_HullForBox - -To keep everything totally uniform, bounding boxes are turned into small -BSP trees instead of being compared directly. -=================== -*/ -hull_t *PM_HullForBox (vec3_t mins, vec3_t maxs) -{ - box_planes[0].dist = maxs[0]; - box_planes[1].dist = mins[0]; - box_planes[2].dist = maxs[1]; - box_planes[3].dist = mins[1]; - box_planes[4].dist = maxs[2]; - box_planes[5].dist = mins[2]; - - return &box_hull; -} - - -/* -================== -PM_HullPointContents - -================== -*/ -int PM_HullPointContents (hull_t *hull, int num, vec3_t p) -{ - float d; - dclipnode_t *node; - mplane_t *plane; - - while (num >= 0) - { - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("PM_HullPointContents: bad node number"); - - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; - - if (plane->type < 3) - d = p[plane->type] - plane->dist; - else - d = DotProduct (plane->normal, p) - plane->dist; - if (d < 0) - num = node->children[1]; - else - num = node->children[0]; - } - - return num; -} - -/* -================== -PM_PointContents - -================== -*/ -int PM_PointContents (vec3_t p) -{ - float d; - dclipnode_t *node; - mplane_t *plane; - hull_t *hull; - int num; - - hull = &pmove.physents[0].model->hulls[0]; - - num = hull->firstclipnode; - - while (num >= 0) - { - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("PM_HullPointContents: bad node number"); - - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; - - if (plane->type < 3) - d = p[plane->type] - plane->dist; - else - d = DotProduct (plane->normal, p) - plane->dist; - if (d < 0) - num = node->children[1]; - else - num = node->children[0]; - } - - return num; -} - -/* -=============================================================================== - -LINE TESTING IN HULLS - -=============================================================================== -*/ - -// 1/32 epsilon to keep floating point happy -#define DIST_EPSILON (0.03125) - -/* -================== -PM_RecursiveHullCheck - -================== -*/ -qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace) -{ - dclipnode_t *node; - mplane_t *plane; - float t1, t2; - float frac; - int i; - vec3_t mid; - int side; - float midf; - -// check for empty - if (num < 0) - { - if (num != CONTENTS_SOLID) - { - trace->allsolid = false; - if (num == CONTENTS_EMPTY) - trace->inopen = true; - else - trace->inwater = true; - } - else - trace->startsolid = true; - return true; // empty - } - - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("PM_RecursiveHullCheck: bad node number"); - -// -// find the point distances -// - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; - - if (plane->type < 3) - { - t1 = p1[plane->type] - plane->dist; - t2 = p2[plane->type] - plane->dist; - } - else - { - t1 = DotProduct (plane->normal, p1) - plane->dist; - t2 = DotProduct (plane->normal, p2) - plane->dist; - } - -#if 1 - if (t1 >= 0 && t2 >= 0) - return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - if (t1 < 0 && t2 < 0) - return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); -#else - if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) - return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) - return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); -#endif - -// put the crosspoint DIST_EPSILON pixels on the near side - if (t1 < 0) - frac = (t1 + DIST_EPSILON)/(t1-t2); - else - frac = (t1 - DIST_EPSILON)/(t1-t2); - if (frac < 0) - frac = 0; - if (frac > 1) - frac = 1; - - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); - - side = (t1 < 0); - -// move up to the node - if (!PM_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) - return false; - -#ifdef PARANOID - if (PM_HullPointContents (pm_hullmodel, mid, node->children[side]) - == CONTENTS_SOLID) - { - Con_Printf ("mid PointInHullSolid\n"); - return false; - } -#endif - - if (PM_HullPointContents (hull, node->children[side^1], mid) - != CONTENTS_SOLID) -// go past the node - return PM_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); - - if (trace->allsolid) - return false; // never got out of the solid area - -//================== -// the other side of the node is solid, this is the impact point -//================== - if (!side) - { - VectorCopy (plane->normal, trace->plane.normal); - trace->plane.dist = plane->dist; - } - else - { - VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); - trace->plane.dist = -plane->dist; - } - - while (PM_HullPointContents (hull, hull->firstclipnode, mid) - == CONTENTS_SOLID) - { // shouldn't really happen, but does occasionally - frac -= 0.1; - if (frac < 0) - { - trace->fraction = midf; - VectorCopy (mid, trace->endpos); - Con_DPrintf ("backup past 0\n"); - return false; - } - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); - } - - trace->fraction = midf; - VectorCopy (mid, trace->endpos); - - return false; -} - - -/* -================ -PM_TestPlayerPosition - -Returns false if the given player position is not valid (in solid) -================ -*/ -qboolean PM_TestPlayerPosition (vec3_t pos) -{ - int i; - physent_t *pe; - vec3_t mins, maxs, test; - hull_t *hull; - - for (i=0 ; i< pmove.numphysent ; i++) - { - pe = &pmove.physents[i]; - // get the clipping hull - if (pe->model) - hull = &pmove.physents[i].model->hulls[1]; - else - { - VectorSubtract (pe->mins, player_maxs, mins); - VectorSubtract (pe->maxs, player_mins, maxs); - hull = PM_HullForBox (mins, maxs); - } - - VectorSubtract (pos, pe->origin, test); - - if (PM_HullPointContents (hull, hull->firstclipnode, test) == CONTENTS_SOLID) - return false; - } - - return true; -} - -/* -================ -PM_PlayerMove -================ -*/ -pmtrace_t PM_PlayerMove (vec3_t start, vec3_t end) -{ - pmtrace_t trace, total; - vec3_t offset; - vec3_t start_l, end_l; - hull_t *hull; - int i; - physent_t *pe; - vec3_t mins, maxs; - -// fill in a default trace - memset (&total, 0, sizeof(pmtrace_t)); - total.fraction = 1; - total.ent = -1; - VectorCopy (end, total.endpos); - - for (i=0 ; i< pmove.numphysent ; i++) - { - pe = &pmove.physents[i]; - // get the clipping hull - if (pe->model) - hull = &pmove.physents[i].model->hulls[1]; - else - { - VectorSubtract (pe->mins, player_maxs, mins); - VectorSubtract (pe->maxs, player_mins, maxs); - hull = PM_HullForBox (mins, maxs); - } - - // PM_HullForEntity (ent, mins, maxs, offset); - VectorCopy (pe->origin, offset); - - VectorSubtract (start, offset, start_l); - VectorSubtract (end, offset, end_l); - - // fill in a default trace - memset (&trace, 0, sizeof(pmtrace_t)); - trace.fraction = 1; - trace.allsolid = true; -// trace.startsolid = true; - VectorCopy (end, trace.endpos); - - // trace a line through the apropriate clipping hull - PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); - - if (trace.allsolid) - trace.startsolid = true; - if (trace.startsolid) - trace.fraction = 0; - - // did we clip the move? - if (trace.fraction < total.fraction) - { - // fix trace up by the offset - VectorAdd (trace.endpos, offset, trace.endpos); - total = trace; - total.ent = i; - } - - } - - return total; -} - - +/* +Copyright (C) 1996-1997 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 "quakedef.h" + +static hull_t box_hull; +static dclipnode_t box_clipnodes[6]; +static mplane_t box_planes[6]; + +extern vec3_t player_mins; +extern vec3_t player_maxs; + +/* +=================== +PM_InitBoxHull + +Set up the planes and clipnodes so that the six floats of a bounding box +can just be stored out and get a proper hull_t structure. +=================== +*/ +void PM_InitBoxHull (void) +{ + int i; + int side; + + box_hull.clipnodes = box_clipnodes; + box_hull.planes = box_planes; + box_hull.firstclipnode = 0; + box_hull.lastclipnode = 5; + + for (i=0 ; i<6 ; i++) + { + box_clipnodes[i].planenum = i; + + side = i&1; + + box_clipnodes[i].children[side] = CONTENTS_EMPTY; + if (i != 5) + box_clipnodes[i].children[side^1] = i + 1; + else + box_clipnodes[i].children[side^1] = CONTENTS_SOLID; + + box_planes[i].type = i>>1; + box_planes[i].normal[i>>1] = 1; + } + +} + + +/* +=================== +PM_HullForBox + +To keep everything totally uniform, bounding boxes are turned into small +BSP trees instead of being compared directly. +=================== +*/ +hull_t *PM_HullForBox (vec3_t mins, vec3_t maxs) +{ + box_planes[0].dist = maxs[0]; + box_planes[1].dist = mins[0]; + box_planes[2].dist = maxs[1]; + box_planes[3].dist = mins[1]; + box_planes[4].dist = maxs[2]; + box_planes[5].dist = mins[2]; + + return &box_hull; +} + + +/* +================== +PM_HullPointContents + +================== +*/ +int PM_HullPointContents (hull_t *hull, int num, vec3_t p) +{ + float d; + dclipnode_t *node; + mplane_t *plane; + + while (num >= 0) + { + if (num < hull->firstclipnode || num > hull->lastclipnode) + Sys_Error ("PM_HullPointContents: bad node number"); + + node = hull->clipnodes + num; + plane = hull->planes + node->planenum; + + if (plane->type < 3) + d = p[plane->type] - plane->dist; + else + d = DotProduct (plane->normal, p) - plane->dist; + if (d < 0) + num = node->children[1]; + else + num = node->children[0]; + } + + return num; +} + +/* +================== +PM_PointContents + +================== +*/ +int PM_PointContents (vec3_t p) +{ + float d; + dclipnode_t *node; + mplane_t *plane; + hull_t *hull; + int num; + + hull = &pmove.physents[0].model->hulls[0]; + + num = hull->firstclipnode; + + while (num >= 0) + { + if (num < hull->firstclipnode || num > hull->lastclipnode) + Sys_Error ("PM_HullPointContents: bad node number"); + + node = hull->clipnodes + num; + plane = hull->planes + node->planenum; + + if (plane->type < 3) + d = p[plane->type] - plane->dist; + else + d = DotProduct (plane->normal, p) - plane->dist; + if (d < 0) + num = node->children[1]; + else + num = node->children[0]; + } + + return num; +} + +/* +=============================================================================== + +LINE TESTING IN HULLS + +=============================================================================== +*/ + +// 1/32 epsilon to keep floating point happy +#define DIST_EPSILON (0.03125) + +/* +================== +PM_RecursiveHullCheck + +================== +*/ +qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace) +{ + dclipnode_t *node; + mplane_t *plane; + float t1, t2; + float frac; + int i; + vec3_t mid; + int side; + float midf; + +// check for empty + if (num < 0) + { + if (num != CONTENTS_SOLID) + { + trace->allsolid = false; + if (num == CONTENTS_EMPTY) + trace->inopen = true; + else + trace->inwater = true; + } + else + trace->startsolid = true; + return true; // empty + } + + if (num < hull->firstclipnode || num > hull->lastclipnode) + Sys_Error ("PM_RecursiveHullCheck: bad node number"); + +// +// find the point distances +// + node = hull->clipnodes + num; + plane = hull->planes + node->planenum; + + if (plane->type < 3) + { + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; + } + else + { + t1 = DotProduct (plane->normal, p1) - plane->dist; + t2 = DotProduct (plane->normal, p2) - plane->dist; + } + +#if 1 + if (t1 >= 0 && t2 >= 0) + return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); + if (t1 < 0 && t2 < 0) + return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); +#else + if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) + return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); + if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) + return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); +#endif + +// put the crosspoint DIST_EPSILON pixels on the near side + if (t1 < 0) + frac = (t1 + DIST_EPSILON)/(t1-t2); + else + frac = (t1 - DIST_EPSILON)/(t1-t2); + if (frac < 0) + frac = 0; + if (frac > 1) + frac = 1; + + midf = p1f + (p2f - p1f)*frac; + for (i=0 ; i<3 ; i++) + mid[i] = p1[i] + frac*(p2[i] - p1[i]); + + side = (t1 < 0); + +// move up to the node + if (!PM_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) + return false; + +#ifdef PARANOID + if (PM_HullPointContents (pm_hullmodel, mid, node->children[side]) + == CONTENTS_SOLID) + { + Con_Printf ("mid PointInHullSolid\n"); + return false; + } +#endif + + if (PM_HullPointContents (hull, node->children[side^1], mid) + != CONTENTS_SOLID) +// go past the node + return PM_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); + + if (trace->allsolid) + return false; // never got out of the solid area + +//================== +// the other side of the node is solid, this is the impact point +//================== + if (!side) + { + VectorCopy (plane->normal, trace->plane.normal); + trace->plane.dist = plane->dist; + } + else + { + VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); + trace->plane.dist = -plane->dist; + } + + while (PM_HullPointContents (hull, hull->firstclipnode, mid) + == CONTENTS_SOLID) + { // shouldn't really happen, but does occasionally + frac -= 0.1; + if (frac < 0) + { + trace->fraction = midf; + VectorCopy (mid, trace->endpos); + Con_DPrintf ("backup past 0\n"); + return false; + } + midf = p1f + (p2f - p1f)*frac; + for (i=0 ; i<3 ; i++) + mid[i] = p1[i] + frac*(p2[i] - p1[i]); + } + + trace->fraction = midf; + VectorCopy (mid, trace->endpos); + + return false; +} + + +/* +================ +PM_TestPlayerPosition + +Returns false if the given player position is not valid (in solid) +================ +*/ +qboolean PM_TestPlayerPosition (vec3_t pos) +{ + int i; + physent_t *pe; + vec3_t mins, maxs, test; + hull_t *hull; + + for (i=0 ; i< pmove.numphysent ; i++) + { + pe = &pmove.physents[i]; + // get the clipping hull + if (pe->model) + hull = &pmove.physents[i].model->hulls[1]; + else + { + VectorSubtract (pe->mins, player_maxs, mins); + VectorSubtract (pe->maxs, player_mins, maxs); + hull = PM_HullForBox (mins, maxs); + } + + VectorSubtract (pos, pe->origin, test); + + if (PM_HullPointContents (hull, hull->firstclipnode, test) == CONTENTS_SOLID) + return false; + } + + return true; +} + +/* +================ +PM_PlayerMove +================ +*/ +pmtrace_t PM_PlayerMove (vec3_t start, vec3_t end) +{ + pmtrace_t trace, total; + vec3_t offset; + vec3_t start_l, end_l; + hull_t *hull; + int i; + physent_t *pe; + vec3_t mins, maxs; + +// fill in a default trace + memset (&total, 0, sizeof(pmtrace_t)); + total.fraction = 1; + total.ent = -1; + VectorCopy (end, total.endpos); + + for (i=0 ; i< pmove.numphysent ; i++) + { + pe = &pmove.physents[i]; + // get the clipping hull + if (pe->model) + hull = &pmove.physents[i].model->hulls[1]; + else + { + VectorSubtract (pe->mins, player_maxs, mins); + VectorSubtract (pe->maxs, player_mins, maxs); + hull = PM_HullForBox (mins, maxs); + } + + // PM_HullForEntity (ent, mins, maxs, offset); + VectorCopy (pe->origin, offset); + + VectorSubtract (start, offset, start_l); + VectorSubtract (end, offset, end_l); + + // fill in a default trace + memset (&trace, 0, sizeof(pmtrace_t)); + trace.fraction = 1; + trace.allsolid = true; +// trace.startsolid = true; + VectorCopy (end, trace.endpos); + + // trace a line through the apropriate clipping hull + PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); + + if (trace.allsolid) + trace.startsolid = true; + if (trace.startsolid) + trace.fraction = 0; + + // did we clip the move? + if (trace.fraction < total.fraction) + { + // fix trace up by the offset + VectorAdd (trace.endpos, offset, trace.endpos); + total = trace; + total.ent = i; + } + + } + + return total; +} + + diff --git a/source/pr_cmds.c b/source/pr_cmds.c index 15a5ef8..20d2f40 100644 --- a/source/pr_cmds.c +++ b/source/pr_cmds.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "qwsvdef.h" @@ -1300,9 +1300,7 @@ MESSAGE WRITING sizebuf_t *WriteDest (void) { - int entnum; int dest; - edict_t *ent; dest = G_FLOAT(OFS_PARM0); switch (dest) diff --git a/source/pr_edict.c b/source/pr_edict.c index af25896..f5db256 100644 --- a/source/pr_edict.c +++ b/source/pr_edict.c @@ -1,26 +1,26 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_edict.c -- entity dictionary #include "qwsvdef.h" - + dprograms_t *progs; dfunction_t *pr_functions; char *pr_strings; @@ -35,21 +35,21 @@ int type_size[8] = {1,sizeof(void *)/4,1,3,1,1,sizeof(void *)/4,sizeof(void *)/ ddef_t *ED_FieldAtOfs (int ofs); qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); - -#define MAX_FIELD_LEN 64 -#define GEFV_CACHESIZE 2 - -typedef struct { - ddef_t *pcache; - char field[MAX_FIELD_LEN]; -} gefv_cache; - -static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; - -func_t SpectatorConnect; -func_t SpectatorThink; -func_t SpectatorDisconnect; - + +#define MAX_FIELD_LEN 64 +#define GEFV_CACHESIZE 2 + +typedef struct { + ddef_t *pcache; + char field[MAX_FIELD_LEN]; +} gefv_cache; + +static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; + +func_t SpectatorConnect; +func_t SpectatorThink; +func_t SpectatorDisconnect; + /* ================= @@ -233,37 +233,37 @@ dfunction_t *ED_FindFunction (char *name) return NULL; } -eval_t *GetEdictFieldValue(edict_t *ed, char *field) -{ - ddef_t *def = NULL; - int i; - static int rep = 0; - - for (i=0 ; iv + def->ofs*4); -} - +eval_t *GetEdictFieldValue(edict_t *ed, char *field) +{ + ddef_t *def = NULL; + int i; + static int rep = 0; + + for (i=0 ; iv + def->ofs*4); +} + /* ============ PR_ValueString @@ -958,13 +958,13 @@ PR_LoadProgs void PR_LoadProgs (void) { int i; - char num[32]; + char num[32]; dfunction_t *f; -// flush the non-C variable lookup cache - for (i=0 ; inumglobals ; i++) - ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); - - // Zoid, find the spectator functions - SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0; - - if ((f = ED_FindFunction ("SpectatorConnect")) != NULL) - SpectatorConnect = (func_t)(f - pr_functions); - if ((f = ED_FindFunction ("SpectatorThink")) != NULL) - SpectatorThink = (func_t)(f - pr_functions); - if ((f = ED_FindFunction ("SpectatorDisconnect")) != NULL) - SpectatorDisconnect = (func_t)(f - pr_functions); + ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); + + // Zoid, find the spectator functions + SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0; + + if ((f = ED_FindFunction ("SpectatorConnect")) != NULL) + SpectatorConnect = (func_t)(f - pr_functions); + if ((f = ED_FindFunction ("SpectatorThink")) != NULL) + SpectatorThink = (func_t)(f - pr_functions); + if ((f = ED_FindFunction ("SpectatorDisconnect")) != NULL) + SpectatorDisconnect = (func_t)(f - pr_functions); } diff --git a/source/pr_exec.c b/source/pr_exec.c index 7b04bd3..8f5c351 100644 --- a/source/pr_exec.c +++ b/source/pr_exec.c @@ -1,24 +1,24 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. -#include "qwsvdef.h" +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 "qwsvdef.h" /* @@ -500,7 +500,7 @@ while (1) (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; - case OP_EQ_S: + case OP_EQ_S: c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_EQ_E: @@ -670,9 +670,9 @@ int num_prstr; char *PR_GetString(int num) { - if (num < 0) { -//Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]); - return pr_strtbl[-num]; + if (num < 0) { +//Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]); + return pr_strtbl[-num]; } return pr_strings + num; } @@ -681,7 +681,7 @@ int PR_SetString(char *s) { int i; - if (s - pr_strings < 0) { + if (s - pr_strings < 0) { for (i = 0; i <= num_prstr; i++) if (pr_strtbl[i] == s) break; @@ -690,7 +690,7 @@ int PR_SetString(char *s) if (num_prstr == MAX_PRSTR - 1) Sys_Error("MAX_PRSTR"); num_prstr++; - pr_strtbl[num_prstr] = s; + pr_strtbl[num_prstr] = s; //Con_DPrintf("SET:%d == %s\n", -num_prstr, s); return -num_prstr; } diff --git a/source/r_aclip.c b/source/r_aclip.c index 63c1a3d..61fef0c 100644 --- a/source/r_aclip.c +++ b/source/r_aclip.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_aclip.c: clip routines for drawing Alias models directly to the screen #include "quakedef.h" diff --git a/source/r_alias.c b/source/r_alias.c index fc55fd9..6100b23 100644 --- a/source/r_alias.c +++ b/source/r_alias.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_alias.c: routines for setting up to draw alias models #include "quakedef.h" @@ -607,21 +607,21 @@ void R_AliasSetupSkin (void) r_affinetridesc.skinwidth = a_skinwidth; r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; r_affinetridesc.skinheight = pmdl->skinheight; - - if (currententity->scoreboard) - { - byte *base; - - if (!currententity->scoreboard->skin) - Skin_Find (currententity->scoreboard); - base = Skin_Cache (currententity->scoreboard->skin); - if (base) - { - r_affinetridesc.pskin = base; - r_affinetridesc.skinwidth = 320; - r_affinetridesc.skinheight = 200; - } - } + + if (currententity->scoreboard) + { + byte *base; + + if (!currententity->scoreboard->skin) + Skin_Find (currententity->scoreboard); + base = Skin_Cache (currententity->scoreboard->skin); + if (base) + { + r_affinetridesc.pskin = base; + r_affinetridesc.skinwidth = 320; + r_affinetridesc.skinheight = 200; + } + } } /* diff --git a/source/r_bsp.c b/source/r_bsp.c index b1980ae..ca94eb6 100644 --- a/source/r_bsp.c +++ b/source/r_bsp.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_bsp.c #include "quakedef.h" @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // qboolean insubmodel; entity_t *currententity; -vec3_t modelorg, base_modelorg; +vec3_t modelorg, base_modelorg; // modelorg is the viewpoint reletive to // the currently rendering entity vec3_t r_entorigin; // the currently rendering entity in world diff --git a/source/r_draw.c b/source/r_draw.c index c6bfc6e..81262f7 100644 --- a/source/r_draw.c +++ b/source/r_draw.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_draw.c diff --git a/source/r_edge.c b/source/r_edge.c index 06083f6..2d1d9f4 100644 --- a/source/r_edge.c +++ b/source/r_edge.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_edge.c #include "quakedef.h" @@ -440,7 +440,7 @@ void R_TrailingEdge (surf_t *surf, edge_t *edge) surf->spans = span; } - // set last_u on the surface below + // set last_u on the surface below surf->next->last_u = iu; } @@ -724,9 +724,9 @@ void R_ScanEdges (void) // the next scan if (span_p > max_span_p) { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); if (r_drawculledpolys) R_DrawCulledPolys (); diff --git a/source/r_efrag.c b/source/r_efrag.c index a031d94..203380f 100644 --- a/source/r_efrag.c +++ b/source/r_efrag.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_efrag.c #include "quakedef.h" diff --git a/source/r_light.c b/source/r_light.c index 3b008b4..f735d50 100644 --- a/source/r_light.c +++ b/source/r_light.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_light.c #include "quakedef.h" diff --git a/source/r_main.c b/source/r_main.c index a61ad26..3f59588 100644 --- a/source/r_main.c +++ b/source/r_main.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_main.c #include "quakedef.h" diff --git a/source/r_misc.c b/source/r_misc.c index 231662a..eee93d3 100644 --- a/source/r_misc.c +++ b/source/r_misc.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_misc.c #include "quakedef.h" diff --git a/source/r_part.c b/source/r_part.c index 096ade2..615e0cb 100644 --- a/source/r_part.c +++ b/source/r_part.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" #include "r_local.h" @@ -230,14 +230,14 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) { int i, j; particle_t *p; - int scale; - - if (count > 130) - scale = 3; - else if (count > 20) - scale = 2; - else - scale = 1; + int scale; + + if (count > 130) + scale = 3; + else if (count > 20) + scale = 2; + else + scale = 1; for (i=0 ; iorg[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - if (scale < 20) - scale = 1; - else - scale = 1 + scale * 0.004; - at = (byte *)&d_8to24table[(int)p->color]; - if (p->type==pt_fire) - theAlpha = 255*(6-p->ramp)/6; -// theAlpha = 192; -// else if (p->type==pt_explode || p->type==pt_explode2) -// theAlpha = 255*(8-p->ramp)/8; - else - theAlpha = 255; - glColor4ub (*at, *(at+1), *(at+2), theAlpha); -// glColor3ubv (at); -// glColor3ubv ((byte *)&d_8to24table[(int)p->color]); - glTexCoord2f (0,0); - glVertex3fv (p->org); - glTexCoord2f (1,0); - glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); - glTexCoord2f (0,1); - glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); - -#else +#ifdef GLQUAKE + // hack a scale up to keep particles from disapearing + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + if (scale < 20) + scale = 1; + else + scale = 1 + scale * 0.004; + at = (byte *)&d_8to24table[(int)p->color]; + if (p->type==pt_fire) + theAlpha = 255*(6-p->ramp)/6; +// theAlpha = 192; +// else if (p->type==pt_explode || p->type==pt_explode2) +// theAlpha = 255*(8-p->ramp)/8; + else + theAlpha = 255; + glColor4ub (*at, *(at+1), *(at+2), theAlpha); +// glColor3ubv (at); +// glColor3ubv ((byte *)&d_8to24table[(int)p->color]); + glTexCoord2f (0,0); + glVertex3fv (p->org); + glTexCoord2f (1,0); + glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); + glTexCoord2f (0,1); + glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); + +#else D_DrawParticle (p); -#endif +#endif p->org[0] += p->vel[0]*frametime; p->org[1] += p->vel[1]*frametime; @@ -602,14 +602,14 @@ void R_DrawParticles (void) } } -#ifdef GLQUAKE - glEnd (); - glDisable (GL_BLEND); - if (alphaTestEnabled) - glEnable(GL_ALPHA_TEST); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -#else - D_EndParticles (); +#ifdef GLQUAKE + glEnd (); + glDisable (GL_BLEND); + if (alphaTestEnabled) + glEnable(GL_ALPHA_TEST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +#else + D_EndParticles (); #endif } diff --git a/source/r_sky.c b/source/r_sky.c index b01e29a..c8bfffd 100644 --- a/source/r_sky.c +++ b/source/r_sky.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_sky.c #include "quakedef.h" diff --git a/source/r_sprite.c b/source/r_sprite.c index 96d939e..5362835 100644 --- a/source/r_sprite.c +++ b/source/r_sprite.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_sprite.c #include "quakedef.h" diff --git a/source/r_surf.c b/source/r_surf.c index 1fd64d8..15b03ec 100644 --- a/source/r_surf.c +++ b/source/r_surf.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_surf.c: surface-related refresh code #include "quakedef.h" diff --git a/source/r_vars.c b/source/r_vars.c index 73cc0a1..eb41290 100644 --- a/source/r_vars.c +++ b/source/r_vars.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // r_vars.c: global refresh variables #include "quakedef.h" diff --git a/source/sbar.c b/source/sbar.c index c36fdf7..c9e6d6d 100644 --- a/source/sbar.c +++ b/source/sbar.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sbar.c -- status bar code #include "quakedef.h" diff --git a/source/screen.c b/source/screen.c index ccdc8c2..7f5d470 100644 --- a/source/screen.c +++ b/source/screen.c @@ -1,1176 +1,1176 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// screen.c -- master for refresh, status bar, console, chat, notify, etc - -#include "quakedef.h" -#include "r_local.h" - -#include - -/* - -background clear -rendering -turtle/net/ram icons -sbar -centerprint / slow centerprint -notify lines -intermission / finale overlay -loading plaque -console -menu - -required background clears -required update regions - - -syncronous draw mode or async -One off screen buffer, with updates either copied or xblited -Need to double buffer? - - -async draw will require the refresh area to be cleared, because it will be -xblited, but sync draw can just ignore it. - -sync -draw - -CenterPrint () -SlowPrint () -Screen_Update (); -Con_Printf (); - -net -turn off messages option - -the refresh is allways rendered, unless the console is full screen - - -console is: - notify lines - half - full - - -*/ - - -// only the refresh window will be updated unless these variables are flagged -int scr_copytop; -int scr_copyeverything; - -float scr_con_current; -float scr_conlines; // lines of console to display - -float oldscreensize, oldfov; -float oldsbar; -cvar_t scr_viewsize = {"viewsize","100", true}; -cvar_t scr_fov = {"fov","90"}; // 10 - 170 -cvar_t scr_conspeed = {"scr_conspeed","300"}; -cvar_t scr_centertime = {"scr_centertime","2"}; -cvar_t scr_showram = {"showram","1"}; -cvar_t scr_showturtle = {"showturtle","0"}; -cvar_t scr_showpause = {"showpause","1"}; -cvar_t scr_printspeed = {"scr_printspeed","8"}; -cvar_t scr_allowsnap = {"scr_allowsnap", "1"}; - -qboolean scr_initialized; // ready to draw - -qpic_t *scr_ram; -qpic_t *scr_net; -qpic_t *scr_turtle; - -int scr_fullupdate; - -int clearconsole; -int clearnotify; - -int sb_lines; - -viddef_t vid; // global video state - -vrect_t *pconupdate; -vrect_t scr_vrect; - -qboolean scr_disabled_for_loading; - -qboolean scr_skipupdate; - -qboolean block_drawing; - -void SCR_ScreenShot_f (void); -void SCR_RSShot_f (void); - -/* -=============================================================================== - -CENTER PRINTING - -=============================================================================== -*/ - -char scr_centerstring[1024]; -float scr_centertime_start; // for slow victory printing -float scr_centertime_off; -int scr_center_lines; -int scr_erase_lines; -int scr_erase_center; - -/* -============== -SCR_CenterPrint - -Called for important messages that should stay in the center of the screen -for a few moments -============== -*/ -void SCR_CenterPrint (char *str) -{ - strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); - scr_centertime_off = scr_centertime.value; - scr_centertime_start = cl.time; - -// count the number of lines for centering - scr_center_lines = 1; - while (*str) - { - if (*str == '\n') - scr_center_lines++; - str++; - } -} - -void SCR_EraseCenterString (void) -{ - int y; - - if (scr_erase_center++ > vid.numpages) - { - scr_erase_lines = 0; - return; - } - - if (scr_center_lines <= 4) - y = vid.height*0.35; - else - y = 48; - - scr_copytop = 1; - Draw_TileClear (0, y, vid.width, min(8*scr_erase_lines, vid.height - y - 1)); -} - -void SCR_DrawCenterString (void) -{ - char *start; - int l; - int j; - int x, y; - int remaining; - -// the finale prints the characters one at a time - if (cl.intermission) - remaining = scr_printspeed.value * (cl.time - scr_centertime_start); - else - remaining = 9999; - - scr_erase_center = 0; - start = scr_centerstring; - - if (scr_center_lines <= 4) - y = vid.height*0.35; - else - y = 48; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.width - l*8)/2; - for (j=0 ; j scr_erase_lines) - scr_erase_lines = scr_center_lines; - - scr_centertime_off -= host_frametime; - - if (scr_centertime_off <= 0 && !cl.intermission) - return; - if (key_dest != key_game) - return; - - SCR_DrawCenterString (); -} - -//============================================================================= - -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) -{ - float a; - float x; - - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width/tan(fov_x/360*M_PI); - - a = atan (height/x); - - a = a*360/M_PI; - - return a; -} - -/* -================= -SCR_CalcRefdef - -Must be called whenever vid changes -Internal use only -================= -*/ -static void SCR_CalcRefdef (void) -{ - vrect_t vrect; - float size; - - scr_fullupdate = 0; // force a background redraw - vid.recalc_refdef = 0; - -// force the status bar to redraw - Sbar_Changed (); - -//======================================== - -// bound viewsize - if (scr_viewsize.value < 30) - Cvar_Set ("viewsize","30"); - if (scr_viewsize.value > 120) - Cvar_Set ("viewsize","120"); - -// bound field of view - if (scr_fov.value < 10) - Cvar_Set ("fov","10"); - if (scr_fov.value > 170) - Cvar_Set ("fov","170"); - - r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); - -// intermission is always full screen - if (cl.intermission) - size = 120; - else - size = scr_viewsize.value; - - if (size >= 120) - sb_lines = 0; // no status bar at all - else if (size >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - -// these calculations mirror those in R_Init() for r_refdef, but take no -// account of water warping - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_SetVrect (&vrect, &scr_vrect, sb_lines); - -// guard against going from one mode to another that's less than half the -// vertical resolution - if (scr_con_current > vid.height) - scr_con_current = vid.height; - -// notify the refresh of the change - R_ViewChanged (&vrect, sb_lines, vid.aspect); -} - - -/* -================= -SCR_SizeUp_f - -Keybinding command -================= -*/ -void SCR_SizeUp_f (void) -{ - if (scr_viewsize.value < 120) { - Cvar_SetValue ("viewsize",scr_viewsize.value+10); - vid.recalc_refdef = 1; - } -} - - -/* -================= -SCR_SizeDown_f - -Keybinding command -================= -*/ -void SCR_SizeDown_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value-10); - vid.recalc_refdef = 1; -} - -//============================================================================ - -/* -================== -SCR_Init -================== -*/ -void SCR_Init (void) -{ - Cvar_RegisterVariable (&scr_fov); - Cvar_RegisterVariable (&scr_viewsize); - Cvar_RegisterVariable (&scr_conspeed); - Cvar_RegisterVariable (&scr_showram); - Cvar_RegisterVariable (&scr_showturtle); - Cvar_RegisterVariable (&scr_showpause); - Cvar_RegisterVariable (&scr_centertime); - Cvar_RegisterVariable (&scr_printspeed); - Cvar_RegisterVariable (&scr_allowsnap); - -// -// register our commands -// - Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddCommand ("snap",SCR_RSShot_f); - Cmd_AddCommand ("sizeup",SCR_SizeUp_f); - Cmd_AddCommand ("sizedown",SCR_SizeDown_f); - - scr_ram = W_GetLumpName ("ram"); - scr_net = W_GetLumpName ("net"); - scr_turtle = W_GetLumpName ("turtle"); - - scr_initialized = true; -} - - - -/* -============== -SCR_DrawRam -============== -*/ -void SCR_DrawRam (void) -{ - if (!scr_showram.value) - return; - - if (!r_cache_thrash) - return; - - Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); -} - -/* -============== -SCR_DrawTurtle -============== -*/ -void SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle.value) - return; - - if (host_frametime < 0.1) - { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); -} - -/* -============== -SCR_DrawNet -============== -*/ -void SCR_DrawNet (void) -{ - if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) - return; - if (cls.demoplayback) - return; - - Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); -} - -void SCR_DrawFPS (void) -{ - extern cvar_t show_fps; - static double lastframetime; - double t; - extern int fps_count; - static lastfps; - int x, y; - char st[80]; - - if (!show_fps.value) - return; - - t = Sys_DoubleTime(); - if ((t - lastframetime) >= 1.0) { - lastfps = fps_count; - fps_count = 0; - lastframetime = t; - } - - sprintf(st, "%3d FPS", lastfps); - x = vid.width - strlen(st) * 8 - 8; - y = vid.height - sb_lines - 8; -// Draw_TileClear(x, y, strlen(st) * 8, 8); - Draw_String(x, y, st); -} - -/* -============== -DrawPause -============== -*/ -void SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause.value) // turn off for screenshots - return; - - if (!cl.paused) - return; - - pic = Draw_CachePic ("gfx/pause.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); -} - - -//============================================================================= - - -/* -================== -SCR_SetUpToDrawConsole -================== -*/ -void SCR_SetUpToDrawConsole (void) -{ - Con_CheckResize (); - -// decide on the height of the console - if (cls.state != ca_active) - { - scr_conlines = vid.height; // full screen - scr_con_current = scr_conlines; - } - else if (key_dest == key_console) - scr_conlines = vid.height/2; // half screen - else - scr_conlines = 0; // none visible - - if (scr_conlines < scr_con_current) - { - scr_con_current -= scr_conspeed.value*host_frametime; - if (scr_conlines > scr_con_current) - scr_con_current = scr_conlines; - - } - else if (scr_conlines > scr_con_current) - { - scr_con_current += scr_conspeed.value*host_frametime; - if (scr_conlines < scr_con_current) - scr_con_current = scr_conlines; - } - - if (clearconsole++ < vid.numpages) - { - scr_copytop = 1; - Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); - Sbar_Changed (); - } - else if (clearnotify++ < vid.numpages) - { - scr_copytop = 1; - Draw_TileClear (0,0,vid.width, con_notifylines); - } - else - con_notifylines = 0; -} - -/* -================== -SCR_DrawConsole -================== -*/ -void SCR_DrawConsole (void) -{ - if (scr_con_current) - { - scr_copyeverything = 1; - Con_DrawConsole (scr_con_current); - clearconsole = 0; - } - else - { - if (key_dest == key_game || key_dest == key_message) - Con_DrawNotify (); // only draw notify in game - } -} - - -/* -============================================================================== - - SCREEN SHOTS - -============================================================================== -*/ - - -/* -============== -WritePCXfile -============== -*/ -void WritePCXfile (char *filename, byte *data, int width, int height, - int rowbytes, byte *palette, qboolean upload) -{ - int i, j, length; - pcx_t *pcx; - byte *pack; - - pcx = Hunk_TempAlloc (width*height*2+1000); - if (pcx == NULL) - { - Con_Printf("SCR_ScreenShot_f: not enough memory\n"); - return; - } - - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = LittleShort((short)(width-1)); - pcx->ymax = LittleShort((short)(height-1)); - pcx->hres = LittleShort((short)width); - pcx->vres = LittleShort((short)height); - Q_memset (pcx->palette,0,sizeof(pcx->palette)); - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = LittleShort((short)width); - pcx->palette_type = LittleShort(2); // not a grey scale - Q_memset (pcx->filler,0,sizeof(pcx->filler)); - -// pack the image - pack = &pcx->data; - - for (i=0 ; i>4; - col = num&15; - source = draw_chars + (row<<10) + (col<<3); - - drawline = 8; - - while (drawline--) - { - for (x=0 ; x<8 ; x++) - if (source[x]) - dest[x] = source[x]; - else - dest[x] = 98; - source += 128; - dest += width; - } - -} - -void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width) -{ - byte *dest; - const unsigned char *p; - - dest = buf + ((y * width) + x); - - p = (const unsigned char *)s; - while (*p) { - SCR_DrawCharToSnap(*p++, dest, width); - dest += 8; - } -} - - -/* -================== -SCR_RSShot_f -================== -*/ -void SCR_RSShot_f (void) -{ - int i, x, y; - unsigned char *src, *dest; - char pcxname[80]; - char checkname[MAX_OSPATH]; - unsigned char *newbuf, *srcbuf; - int srcrowbytes; - int w, h; - int dx, dy, dex, dey, nx; - int r, b, g; - int count; - float fracw, frach; - char st[80]; - time_t now; - - if (CL_IsUploading()) - return; // already one pending - - if (cls.state < ca_onserver) - return; // gotta be connected - - if (!scr_allowsnap.value) { - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, "snap\n"); - Con_Printf("Refusing remote screen shot request.\n"); - return; - } - - Con_Printf("Remote screen shot requested.\n"); - -#if 0 -// -// find a file name to save it to -// - strcpy(pcxname,"mquake00.pcx"); - - for (i=0 ; i<=99 ; i++) - { - pcxname[6] = i/10 + '0'; - pcxname[7] = i%10 + '0'; - sprintf (checkname, "%s/%s", com_gamedir, pcxname); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==100) - { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); - return; - } -#endif - -// -// save the pcx file -// - D_EnableBackBufferAccess (); // enable direct drawing of console to back - // buffer - - w = (vid.width < RSSHOT_WIDTH) ? vid.width : RSSHOT_WIDTH; - h = (vid.height < RSSHOT_HEIGHT) ? vid.height : RSSHOT_HEIGHT; - - fracw = (float)vid.width / (float)w; - frach = (float)vid.height / (float)h; - - newbuf = malloc(w*h); - - for (y = 0; y < h; y++) { - dest = newbuf + (w * y); - - for (x = 0; x < w; x++) { - r = g = b = 0; - - dx = x * fracw; - dex = (x + 1) * fracw; - if (dex == dx) dex++; // at least one - dy = y * frach; - dey = (y + 1) * frach; - if (dey == dy) dey++; // at least one - - count = 0; - for (/* */; dy < dey; dy++) { - src = vid.buffer + (vid.rowbytes * dy) + dx; - for (nx = dx; nx < dex; nx++) { - r += host_basepal[*src * 3]; - g += host_basepal[*src * 3+1]; - b += host_basepal[*src * 3+2]; - src++; - count++; - } - } - r /= count; - g /= count; - b /= count; - *dest++ = MipColor(r, g, b); - } - } - - time(&now); - strcpy(st, ctime(&now)); - st[strlen(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 0, w); - - strncpy(st, cls.servername, sizeof(st)); - st[sizeof(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 10, w); - - strncpy(st, name.string, sizeof(st)); - st[sizeof(st) - 1] = 0; - SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 20, w); - - WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true); - - free(newbuf); - - D_DisableBackBufferAccess (); // for adapters that can't stay mapped in - // for linear writes all the time - -// Con_Printf ("Wrote %s\n", pcxname); - Con_Printf ("Sending shot to server...\n"); -} - - -//============================================================================= - -char *scr_notifystring; -qboolean scr_drawdialog; - -void SCR_DrawNotifyString (void) -{ - char *start; - int l; - int j; - int x, y; - - start = scr_notifystring; - - y = vid.height*0.35; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.width - l*8)/2; - for (j=0 ; j + +/* + +background clear +rendering +turtle/net/ram icons +sbar +centerprint / slow centerprint +notify lines +intermission / finale overlay +loading plaque +console +menu + +required background clears +required update regions + + +syncronous draw mode or async +One off screen buffer, with updates either copied or xblited +Need to double buffer? + + +async draw will require the refresh area to be cleared, because it will be +xblited, but sync draw can just ignore it. + +sync +draw + +CenterPrint () +SlowPrint () +Screen_Update (); +Con_Printf (); + +net +turn off messages option + +the refresh is allways rendered, unless the console is full screen + + +console is: + notify lines + half + full + + +*/ + + +// only the refresh window will be updated unless these variables are flagged +int scr_copytop; +int scr_copyeverything; + +float scr_con_current; +float scr_conlines; // lines of console to display + +float oldscreensize, oldfov; +float oldsbar; +cvar_t scr_viewsize = {"viewsize","100", true}; +cvar_t scr_fov = {"fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {"scr_conspeed","300"}; +cvar_t scr_centertime = {"scr_centertime","2"}; +cvar_t scr_showram = {"showram","1"}; +cvar_t scr_showturtle = {"showturtle","0"}; +cvar_t scr_showpause = {"showpause","1"}; +cvar_t scr_printspeed = {"scr_printspeed","8"}; +cvar_t scr_allowsnap = {"scr_allowsnap", "1"}; + +qboolean scr_initialized; // ready to draw + +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; + +int scr_fullupdate; + +int clearconsole; +int clearnotify; + +int sb_lines; + +viddef_t vid; // global video state + +vrect_t *pconupdate; +vrect_t scr_vrect; + +qboolean scr_disabled_for_loading; + +qboolean scr_skipupdate; + +qboolean block_drawing; + +void SCR_ScreenShot_f (void); +void SCR_RSShot_f (void); + +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + +void SCR_EraseCenterString (void) +{ + int y; + + if (scr_erase_center++ > vid.numpages) + { + scr_erase_lines = 0; + return; + } + + if (scr_center_lines <= 4) + y = vid.height*0.35; + else + y = 48; + + scr_copytop = 1; + Draw_TileClear (0, y, vid.width, min(8*scr_erase_lines, vid.height - y - 1)); +} + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int j; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.height*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l*8)/2; + for (j=0 ; j scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +//============================================================================= + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width/tan(fov_x/360*M_PI); + + a = atan (height/x); + + a = a*360/M_PI; + + return a; +} + +/* +================= +SCR_CalcRefdef + +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + vrect_t vrect; + float size; + + scr_fullupdate = 0; // force a background redraw + vid.recalc_refdef = 0; + +// force the status bar to redraw + Sbar_Changed (); + +//======================================== + +// bound viewsize + if (scr_viewsize.value < 30) + Cvar_Set ("viewsize","30"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + +// bound field of view + if (scr_fov.value < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + + r_refdef.fov_x = scr_fov.value; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + +// intermission is always full screen + if (cl.intermission) + size = 120; + else + size = scr_viewsize.value; + + if (size >= 120) + sb_lines = 0; // no status bar at all + else if (size >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + +// these calculations mirror those in R_Init() for r_refdef, but take no +// account of water warping + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_SetVrect (&vrect, &scr_vrect, sb_lines); + +// guard against going from one mode to another that's less than half the +// vertical resolution + if (scr_con_current > vid.height) + scr_con_current = vid.height; + +// notify the refresh of the change + R_ViewChanged (&vrect, sb_lines, vid.aspect); +} + + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + if (scr_viewsize.value < 120) { + Cvar_SetValue ("viewsize",scr_viewsize.value+10); + vid.recalc_refdef = 1; + } +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); + vid.recalc_refdef = 1; +} + +//============================================================================ + +/* +================== +SCR_Init +================== +*/ +void SCR_Init (void) +{ + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + Cvar_RegisterVariable (&scr_allowsnap); + +// +// register our commands +// + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("snap",SCR_RSShot_f); + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + scr_ram = W_GetLumpName ("ram"); + scr_net = W_GetLumpName ("net"); + scr_turtle = W_GetLumpName ("turtle"); + + scr_initialized = true; +} + + + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ + if (!scr_showram.value) + return; + + if (!r_cache_thrash) + return; + + Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle.value) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) + return; + if (cls.demoplayback) + return; + + Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); +} + +void SCR_DrawFPS (void) +{ + extern cvar_t show_fps; + static double lastframetime; + double t; + extern int fps_count; + static lastfps; + int x, y; + char st[80]; + + if (!show_fps.value) + return; + + t = Sys_DoubleTime(); + if ((t - lastframetime) >= 1.0) { + lastfps = fps_count; + fps_count = 0; + lastframetime = t; + } + + sprintf(st, "%3d FPS", lastfps); + x = vid.width - strlen(st) * 8 - 8; + y = vid.height - sb_lines - 8; +// Draw_TileClear(x, y, strlen(st) * 8, 8); + Draw_String(x, y, st); +} + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + qpic_t *pic; + + if (!scr_showpause.value) // turn off for screenshots + return; + + if (!cl.paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp"); + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); +} + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + +// decide on the height of the console + if (cls.state != ca_active) + { + scr_conlines = vid.height; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.height/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_frametime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_frametime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } + + if (clearconsole++ < vid.numpages) + { + scr_copytop = 1; + Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); + Sbar_Changed (); + } + else if (clearnotify++ < vid.numpages) + { + scr_copytop = 1; + Draw_TileClear (0,0,vid.width, con_notifylines); + } + else + con_notifylines = 0; +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + scr_copyeverything = 1; + Con_DrawConsole (scr_con_current); + clearconsole = 0; + } + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + + +/* +============== +WritePCXfile +============== +*/ +void WritePCXfile (char *filename, byte *data, int width, int height, + int rowbytes, byte *palette, qboolean upload) +{ + int i, j, length; + pcx_t *pcx; + byte *pack; + + pcx = Hunk_TempAlloc (width*height*2+1000); + if (pcx == NULL) + { + Con_Printf("SCR_ScreenShot_f: not enough memory\n"); + return; + } + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort((short)(width-1)); + pcx->ymax = LittleShort((short)(height-1)); + pcx->hres = LittleShort((short)width); + pcx->vres = LittleShort((short)height); + Q_memset (pcx->palette,0,sizeof(pcx->palette)); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort((short)width); + pcx->palette_type = LittleShort(2); // not a grey scale + Q_memset (pcx->filler,0,sizeof(pcx->filler)); + +// pack the image + pack = &pcx->data; + + for (i=0 ; i>4; + col = num&15; + source = draw_chars + (row<<10) + (col<<3); + + drawline = 8; + + while (drawline--) + { + for (x=0 ; x<8 ; x++) + if (source[x]) + dest[x] = source[x]; + else + dest[x] = 98; + source += 128; + dest += width; + } + +} + +void SCR_DrawStringToSnap (const char *s, byte *buf, int x, int y, int width) +{ + byte *dest; + const unsigned char *p; + + dest = buf + ((y * width) + x); + + p = (const unsigned char *)s; + while (*p) { + SCR_DrawCharToSnap(*p++, dest, width); + dest += 8; + } +} + + +/* +================== +SCR_RSShot_f +================== +*/ +void SCR_RSShot_f (void) +{ + int i, x, y; + unsigned char *src, *dest; + char pcxname[80]; + char checkname[MAX_OSPATH]; + unsigned char *newbuf, *srcbuf; + int srcrowbytes; + int w, h; + int dx, dy, dex, dey, nx; + int r, b, g; + int count; + float fracw, frach; + char st[80]; + time_t now; + + if (CL_IsUploading()) + return; // already one pending + + if (cls.state < ca_onserver) + return; // gotta be connected + + if (!scr_allowsnap.value) { + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "snap\n"); + Con_Printf("Refusing remote screen shot request.\n"); + return; + } + + Con_Printf("Remote screen shot requested.\n"); + +#if 0 +// +// find a file name to save it to +// + strcpy(pcxname,"mquake00.pcx"); + + for (i=0 ; i<=99 ; i++) + { + pcxname[6] = i/10 + '0'; + pcxname[7] = i%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, pcxname); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==100) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); + return; + } +#endif + +// +// save the pcx file +// + D_EnableBackBufferAccess (); // enable direct drawing of console to back + // buffer + + w = (vid.width < RSSHOT_WIDTH) ? vid.width : RSSHOT_WIDTH; + h = (vid.height < RSSHOT_HEIGHT) ? vid.height : RSSHOT_HEIGHT; + + fracw = (float)vid.width / (float)w; + frach = (float)vid.height / (float)h; + + newbuf = malloc(w*h); + + for (y = 0; y < h; y++) { + dest = newbuf + (w * y); + + for (x = 0; x < w; x++) { + r = g = b = 0; + + dx = x * fracw; + dex = (x + 1) * fracw; + if (dex == dx) dex++; // at least one + dy = y * frach; + dey = (y + 1) * frach; + if (dey == dy) dey++; // at least one + + count = 0; + for (/* */; dy < dey; dy++) { + src = vid.buffer + (vid.rowbytes * dy) + dx; + for (nx = dx; nx < dex; nx++) { + r += host_basepal[*src * 3]; + g += host_basepal[*src * 3+1]; + b += host_basepal[*src * 3+2]; + src++; + count++; + } + } + r /= count; + g /= count; + b /= count; + *dest++ = MipColor(r, g, b); + } + } + + time(&now); + strcpy(st, ctime(&now)); + st[strlen(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 0, w); + + strncpy(st, cls.servername, sizeof(st)); + st[sizeof(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 10, w); + + strncpy(st, name.string, sizeof(st)); + st[sizeof(st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, 20, w); + + WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true); + + free(newbuf); + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped in + // for linear writes all the time + +// Con_Printf ("Wrote %s\n", pcxname); + Con_Printf ("Sending shot to server...\n"); +} + + +//============================================================================= + +char *scr_notifystring; +qboolean scr_drawdialog; + +void SCR_DrawNotifyString (void) +{ + char *start; + int l; + int j; + int x, y; + + start = scr_notifystring; + + y = vid.height*0.35; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l*8)/2; + for (j=0 ; jskin = skin; numskins++; - memset (skin, 0, sizeof(*skin)); - strncpy(skin->name, name, sizeof(skin->name) - 1); + memset (skin, 0, sizeof(*skin)); + strncpy(skin->name, name, sizeof(skin->name) - 1); } @@ -160,36 +160,36 @@ byte *Skin_Cache (skin_t *skin) { for (x=0 ; x<=pcx->xmax ; ) { - if (raw - (byte*)pcx > com_filesize) - { - Cache_Free (&skin->cache); - skin->failedload = true; - Con_Printf ("Skin %s was malformed. You should delete it.\n", name); - return NULL; - } + if (raw - (byte*)pcx > com_filesize) + { + Cache_Free (&skin->cache); + skin->failedload = true; + Con_Printf ("Skin %s was malformed. You should delete it.\n", name); + return NULL; + } dataByte = *raw++; if((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; - if (raw - (byte*)pcx > com_filesize) - { - Cache_Free (&skin->cache); - skin->failedload = true; - Con_Printf ("Skin %s was malformed. You should delete it.\n", name); - return NULL; - } + if (raw - (byte*)pcx > com_filesize) + { + Cache_Free (&skin->cache); + skin->failedload = true; + Con_Printf ("Skin %s was malformed. You should delete it.\n", name); + return NULL; + } dataByte = *raw++; } else runLength = 1; - - // skin sanity check - if (runLength + x > pcx->xmax + 2) { - Cache_Free (&skin->cache); - skin->failedload = true; - Con_Printf ("Skin %s was malformed. You should delete it.\n", name); - return NULL; + + // skin sanity check + if (runLength + x > pcx->xmax + 2) { + Cache_Free (&skin->cache); + skin->failedload = true; + Con_Printf ("Skin %s was malformed. You should delete it.\n", name); + return NULL; } while(runLength-- > 0) pix[x++] = dataByte; @@ -247,9 +247,9 @@ void Skin_NextDownload (void) sc = &cl.players[i]; if (!sc->name[0]) continue; - Skin_Cache (sc->skin); -#ifdef GLQUAKE - sc->skin = NULL; + Skin_Cache (sc->skin); +#ifdef GLQUAKE + sc->skin = NULL; #endif } @@ -257,7 +257,7 @@ void Skin_NextDownload (void) { // get next signon phase MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va("begin %i", cl.servercount)); + va("begin %i", cl.servercount)); Cache_Report (); // print remaining memory } } diff --git a/source/snd_dma.c b/source/snd_dma.c index e3ee7e8..4168315 100644 --- a/source/snd_dma.c +++ b/source/snd_dma.c @@ -1,1017 +1,1017 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// snd_dma.c -- main control for any streaming sound output device - -#include "quakedef.h" - -#ifdef _WIN32 -#include "winquake.h" -#endif - -void S_Play(void); -void S_PlayVol(void); -void S_SoundList(void); -void S_Update_(); -void S_StopAllSounds(qboolean clear); -void S_StopAllSoundsC(void); - -// QuakeWorld hack... -#define viewentity playernum+1 - -// ======================================================================= -// Internal sound data & structures -// ======================================================================= - -channel_t channels[MAX_CHANNELS]; -int total_channels; - -int snd_blocked = 0; -static qboolean snd_ambient = 1; -qboolean snd_initialized = false; - -// pointer should go away -volatile dma_t *shm = 0; -volatile dma_t sn; - -vec3_t listener_origin; -vec3_t listener_forward; -vec3_t listener_right; -vec3_t listener_up; -vec_t sound_nominal_clip_dist=1000.0; - -int soundtime; // sample PAIRS -int paintedtime; // sample PAIRS - - -#define MAX_SFX 512 -sfx_t *known_sfx; // hunk allocated [MAX_SFX] -int num_sfx; - -sfx_t *ambient_sfx[NUM_AMBIENTS]; - -int desired_speed = 11025; -int desired_bits = 16; - -int sound_started=0; - -cvar_t bgmvolume = {"bgmvolume", "1", true}; -cvar_t volume = {"volume", "0.7", true}; - -cvar_t nosound = {"nosound", "0"}; -cvar_t precache = {"precache", "1"}; -cvar_t loadas8bit = {"loadas8bit", "0"}; -cvar_t bgmbuffer = {"bgmbuffer", "4096"}; -cvar_t ambient_level = {"ambient_level", "0.3"}; -cvar_t ambient_fade = {"ambient_fade", "100"}; -cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"}; -cvar_t snd_show = {"snd_show", "0"}; -cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true}; - - -// ==================================================================== -// User-setable variables -// ==================================================================== - - -// -// Fake dma is a synchronous faking of the DMA progress used for -// isolating performance in the renderer. The fakedma_updates is -// number of times S_Update() is called per second. -// - -qboolean fakedma = false; -int fakedma_updates = 15; - - -void S_AmbientOff (void) -{ - snd_ambient = false; -} - - -void S_AmbientOn (void) -{ - snd_ambient = true; -} - - -void S_SoundInfo_f(void) -{ - if (!sound_started || !shm) - { - Con_Printf ("sound system not started\n"); - return; - } - - Con_Printf("%5d stereo\n", shm->channels - 1); - Con_Printf("%5d samples\n", shm->samples); - Con_Printf("%5d samplepos\n", shm->samplepos); - Con_Printf("%5d samplebits\n", shm->samplebits); - Con_Printf("%5d submission_chunk\n", shm->submission_chunk); - Con_Printf("%5d speed\n", shm->speed); - Con_Printf("0x%x dma buffer\n", shm->buffer); - Con_Printf("%5d total_channels\n", total_channels); -} - - -/* -================ -S_Startup -================ -*/ - -void S_Startup (void) -{ - int rc; - - if (!snd_initialized) - return; - - if (!fakedma) - { - rc = SNDDMA_Init(); - - if (!rc) - { -#ifndef _WIN32 - Con_Printf("S_Startup: SNDDMA_Init failed.\n"); -#endif - sound_started = 0; - return; - } - } - - sound_started = 1; -} - - -/* -================ -S_Init -================ -*/ -void S_Init (void) -{ - -// Con_Printf("\nSound Initialization\n"); - - if (COM_CheckParm("-nosound")) - return; - - if (COM_CheckParm("-simsound")) - fakedma = true; - - Cmd_AddCommand("play", S_Play); - Cmd_AddCommand("playvol", S_PlayVol); - Cmd_AddCommand("stopsound", S_StopAllSoundsC); - Cmd_AddCommand("soundlist", S_SoundList); - Cmd_AddCommand("soundinfo", S_SoundInfo_f); - - Cvar_RegisterVariable(&nosound); - Cvar_RegisterVariable(&volume); - Cvar_RegisterVariable(&precache); - Cvar_RegisterVariable(&loadas8bit); - Cvar_RegisterVariable(&bgmvolume); - Cvar_RegisterVariable(&bgmbuffer); - Cvar_RegisterVariable(&ambient_level); - Cvar_RegisterVariable(&ambient_fade); - Cvar_RegisterVariable(&snd_noextraupdate); - Cvar_RegisterVariable(&snd_show); - Cvar_RegisterVariable(&_snd_mixahead); - - if (host_parms.memsize < 0x800000) - { - Cvar_Set ("loadas8bit", "1"); - Con_Printf ("loading all sounds as 8bit\n"); - } - - - - snd_initialized = true; - - S_Startup (); - - SND_InitScaletable (); - - known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t"); - num_sfx = 0; - -// create a piece of DMA memory - - if (fakedma) - { - shm = (void *) Hunk_AllocName(sizeof(*shm), "shm"); - shm->splitbuffer = 0; - shm->samplebits = 16; - shm->speed = 22050; - shm->channels = 2; - shm->samples = 32768; - shm->samplepos = 0; - shm->soundalive = true; - shm->gamealive = true; - shm->submission_chunk = 1; - shm->buffer = Hunk_AllocName(1<<16, "shmbuf"); - } - -// Con_Printf ("Sound sampling rate: %i\n", shm->speed); - - // provides a tick sound until washed clean - -// if (shm->buffer) -// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging - - ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); - ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); - - S_StopAllSounds (true); -} - - -// ======================================================================= -// Shutdown sound engine -// ======================================================================= - -void S_Shutdown(void) -{ - - if (!sound_started) - return; - - if (shm) - shm->gamealive = 0; - - shm = 0; - sound_started = 0; - - if (!fakedma) - { - SNDDMA_Shutdown(); - } -} - - -// ======================================================================= -// Load a sound -// ======================================================================= - -/* -================== -S_FindName - -================== -*/ -sfx_t *S_FindName (char *name) -{ - int i; - sfx_t *sfx; - - if (!name) - Sys_Error ("S_FindName: NULL\n"); - - if (Q_strlen(name) >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", name); - -// see if already loaded - for (i=0 ; i < num_sfx ; i++) - if (!Q_strcmp(known_sfx[i].name, name)) - { - return &known_sfx[i]; - } - - if (num_sfx == MAX_SFX) - Sys_Error ("S_FindName: out of sfx_t"); - - sfx = &known_sfx[i]; - strcpy (sfx->name, name); - - num_sfx++; - - return sfx; -} - - -/* -================== -S_TouchSound - -================== -*/ -void S_TouchSound (char *name) -{ - sfx_t *sfx; - - if (!sound_started) - return; - - sfx = S_FindName (name); - Cache_Check (&sfx->cache); -} - -/* -================== -S_PrecacheSound - -================== -*/ -sfx_t *S_PrecacheSound (char *name) -{ - sfx_t *sfx; - - if (!sound_started || nosound.value) - return NULL; - - sfx = S_FindName (name); - -// cache it in - if (precache.value) - S_LoadSound (sfx); - - return sfx; -} - - -//============================================================================= - -/* -================= -SND_PickChannel -================= -*/ -channel_t *SND_PickChannel(int entnum, int entchannel) -{ - int ch_idx; - int first_to_die; - int life_left; - -// Check for replacement sound, or find the best one to replace - first_to_die = -1; - life_left = 0x7fffffff; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) - { - if (entchannel != 0 // channel 0 never overrides - && channels[ch_idx].entnum == entnum - && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) - { // allways override sound from same entity - first_to_die = ch_idx; - break; - } - - // don't let monster sounds override player sounds - if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx) - continue; - - if (channels[ch_idx].end - paintedtime < life_left) - { - life_left = channels[ch_idx].end - paintedtime; - first_to_die = ch_idx; - } - } - - if (first_to_die == -1) - return NULL; - - if (channels[first_to_die].sfx) - channels[first_to_die].sfx = NULL; - - return &channels[first_to_die]; -} - -/* -================= -SND_Spatialize -================= -*/ -void SND_Spatialize(channel_t *ch) -{ - vec_t dot; - vec_t dist; - vec_t lscale, rscale, scale; - vec3_t source_vec; - sfx_t *snd; - -// anything coming from the view entity will allways be full volume - if (ch->entnum == cl.viewentity) - { - ch->leftvol = ch->master_vol; - ch->rightvol = ch->master_vol; - return; - } - -// calculate stereo seperation and distance attenuation - - snd = ch->sfx; - VectorSubtract(ch->origin, listener_origin, source_vec); - - dist = VectorNormalize(source_vec) * ch->dist_mult; - - dot = DotProduct(listener_right, source_vec); - - if (shm->channels == 1) - { - rscale = 1.0; - lscale = 1.0; - } - else - { - rscale = 1.0 + dot; - lscale = 1.0 - dot; - } - -// add in distance effect - scale = (1.0 - dist) * rscale; - ch->rightvol = (int) (ch->master_vol * scale); - if (ch->rightvol < 0) - ch->rightvol = 0; - - scale = (1.0 - dist) * lscale; - ch->leftvol = (int) (ch->master_vol * scale); - if (ch->leftvol < 0) - ch->leftvol = 0; -} - - -// ======================================================================= -// Start a sound effect -// ======================================================================= - -void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) -{ - channel_t *target_chan, *check; - sfxcache_t *sc; - int vol; - int ch_idx; - int skip; - - if (!sound_started) - return; - - if (!sfx) - return; - - if (nosound.value) - return; - - vol = fvol*255; - -// pick a channel to play on - target_chan = SND_PickChannel(entnum, entchannel); - if (!target_chan) - return; - -// spatialize - memset (target_chan, 0, sizeof(*target_chan)); - VectorCopy(origin, target_chan->origin); - target_chan->dist_mult = attenuation / sound_nominal_clip_dist; - target_chan->master_vol = vol; - target_chan->entnum = entnum; - target_chan->entchannel = entchannel; - SND_Spatialize(target_chan); - - if (!target_chan->leftvol && !target_chan->rightvol) - return; // not audible at all - -// new channel - sc = S_LoadSound (sfx); - if (!sc) - { - target_chan->sfx = NULL; - return; // couldn't load the sound's data - } - - target_chan->sfx = sfx; - target_chan->pos = 0.0; - target_chan->end = paintedtime + sc->length; - -// if an identical sound has also been started this frame, offset the pos -// a bit to keep it from just making the first one louder - check = &channels[NUM_AMBIENTS]; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) - { - if (check == target_chan) - continue; - if (check->sfx == sfx && !check->pos) - { - skip = rand () % (int)(0.1*shm->speed); - if (skip >= target_chan->end) - skip = target_chan->end - 1; - target_chan->pos += skip; - target_chan->end -= skip; - break; - } - - } -} - -void S_StopSound(int entnum, int entchannel) -{ - int i; - - for (i=0 ; ibuffer && !pDSBuf)) -#else - if (!sound_started || !shm || !shm->buffer) -#endif - return; - - if (shm->samplebits == 8) - clear = 0x80; - else - clear = 0; - -#ifdef _WIN32 - if (pDSBuf) - { - DWORD dwSize; - DWORD *pData; - int reps; - HRESULT hresult; - - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n"); - S_Shutdown (); - return; - } - } - - Q_memset(pData, clear, shm->samples * shm->samplebits/8); - - pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0); - - } - else -#endif - { - Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8); - } -} - - -/* -================= -S_StaticSound -================= -*/ -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) -{ - channel_t *ss; - sfxcache_t *sc; - - if (!sfx) - return; - - if (total_channels == MAX_CHANNELS) - { - Con_Printf ("total_channels == MAX_CHANNELS\n"); - return; - } - - ss = &channels[total_channels]; - total_channels++; - - sc = S_LoadSound (sfx); - if (!sc) - return; - - if (sc->loopstart == -1) - { - Con_Printf ("Sound %s not looped\n", sfx->name); - return; - } - - ss->sfx = sfx; - VectorCopy (origin, ss->origin); - ss->master_vol = vol; - ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; - ss->end = paintedtime + sc->length; - - SND_Spatialize (ss); -} - - -//============================================================================= - -/* -=================== -S_UpdateAmbientSounds -=================== -*/ -void S_UpdateAmbientSounds (void) -{ - mleaf_t *l; - float vol; - int ambient_channel; - channel_t *chan; - - if (!snd_ambient) - return; - -// calc ambient sound levels - if (!cl.worldmodel) - return; - - l = Mod_PointInLeaf (listener_origin, cl.worldmodel); - if (!l || !ambient_level.value) - { - for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) - channels[ambient_channel].sfx = NULL; - return; - } - - for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) - { - chan = &channels[ambient_channel]; - chan->sfx = ambient_sfx[ambient_channel]; - - vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; - if (vol < 8) - vol = 0; - - // don't adjust volume too fast - if (chan->master_vol < vol) - { - chan->master_vol += host_frametime * ambient_fade.value; - if (chan->master_vol > vol) - chan->master_vol = vol; - } - else if (chan->master_vol > vol) - { - chan->master_vol -= host_frametime * ambient_fade.value; - if (chan->master_vol < vol) - chan->master_vol = vol; - } - - chan->leftvol = chan->rightvol = chan->master_vol; - } -} - - -/* -============ -S_Update - -Called once each time through the main loop -============ -*/ -void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) -{ - int i, j; - int total; - channel_t *ch; - channel_t *combine; - - if (!sound_started || (snd_blocked > 0)) - return; - - VectorCopy(origin, listener_origin); - VectorCopy(forward, listener_forward); - VectorCopy(right, listener_right); - VectorCopy(up, listener_up); - -// update general area ambient sound sources - S_UpdateAmbientSounds (); - - combine = NULL; - -// update spatialization for static and dynamic sounds - ch = channels+NUM_AMBIENTS; - for (i=NUM_AMBIENTS ; isfx) - continue; - SND_Spatialize(ch); // respatialize channel - if (!ch->leftvol && !ch->rightvol) - continue; - - // try to combine static sounds with a previous channel of the same - // sound effect so we don't mix five torches every frame - - if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) - { - // see if it can just use the last one - if (combine && combine->sfx == ch->sfx) - { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; - continue; - } - // search for one - combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; - for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; jsfx == ch->sfx) - break; - - if (j == total_channels) - { - combine = NULL; - } - else - { - if (combine != ch) - { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; - } - continue; - } - } - - - } - -// -// debugging output -// - if (snd_show.value) - { - total = 0; - ch = channels; - for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) - { - //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); - total++; - } - - Con_Printf ("----(%i)----\n", total); - } - -// mix some sound - S_Update_(); -} - -void GetSoundtime(void) -{ - int samplepos; - static int buffers; - static int oldsamplepos; - int fullsamples; - - fullsamples = shm->samples / shm->channels; - -// it is possible to miscount buffers if it has wrapped twice between -// calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos(); - - if (samplepos < oldsamplepos) - { - buffers++; // buffer wrapped - - if (paintedtime > 0x40000000) - { // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds (true); - } - } - oldsamplepos = samplepos; - - soundtime = buffers*fullsamples + samplepos/shm->channels; -} - -void S_ExtraUpdate (void) -{ - -#ifdef _WIN32 - IN_Accumulate (); -#endif - - if (snd_noextraupdate.value) - return; // don't pollute timings - S_Update_(); -} - - - -void S_Update_(void) -{ - unsigned endtime; - int samps; - - if (!sound_started || (snd_blocked > 0)) - return; - -// Updates DMA time - GetSoundtime(); - -// check to make sure that we haven't overshot - if (paintedtime < soundtime) - { - //Con_Printf ("S_Update_ : overflow\n"); - paintedtime = soundtime; - } - -// mix ahead of current position - endtime = soundtime + _snd_mixahead.value * shm->speed; - samps = shm->samples >> (shm->channels-1); - if (endtime - soundtime > samps) - endtime = soundtime + samps; - -#ifdef _WIN32 -// if the buffer was lost or stopped, restore it and/or restart it - { - DWORD dwStatus; - - if (pDSBuf) - { - if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK) - Con_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); - } - } -#endif - - S_PaintChannels (endtime); - - SNDDMA_Submit (); -} - -/* -=============================================================================== - -console functions - -=============================================================================== -*/ - -void S_Play(void) -{ - static int hash=345; - int i; - char name[256]; - sfx_t *sfx; - - i = 1; - while (icache); - if (!sc) - continue; - size = sc->length*sc->width*(sc->stereo+1); - total += size; - if (sc->loopstart >= 0) - Con_Printf ("L"); - else - Con_Printf (" "); - Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name); - } - Con_Printf ("Total resident: %i\n", total); -} - - -void S_LocalSound (char *sound) -{ - sfx_t *sfx; - - if (nosound.value) - return; - if (!sound_started) - return; - - sfx = S_PrecacheSound (sound); - if (!sfx) - { - Con_Printf ("S_LocalSound: can't cache %s\n", sound); - return; - } - S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); -} - - -void S_ClearPrecache (void) -{ -} - - -void S_BeginPrecaching (void) -{ -} - - -void S_EndPrecaching (void) -{ -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// snd_dma.c -- main control for any streaming sound output device + +#include "quakedef.h" + +#ifdef _WIN32 +#include "winquake.h" +#endif + +void S_Play(void); +void S_PlayVol(void); +void S_SoundList(void); +void S_Update_(); +void S_StopAllSounds(qboolean clear); +void S_StopAllSoundsC(void); + +// QuakeWorld hack... +#define viewentity playernum+1 + +// ======================================================================= +// Internal sound data & structures +// ======================================================================= + +channel_t channels[MAX_CHANNELS]; +int total_channels; + +int snd_blocked = 0; +static qboolean snd_ambient = 1; +qboolean snd_initialized = false; + +// pointer should go away +volatile dma_t *shm = 0; +volatile dma_t sn; + +vec3_t listener_origin; +vec3_t listener_forward; +vec3_t listener_right; +vec3_t listener_up; +vec_t sound_nominal_clip_dist=1000.0; + +int soundtime; // sample PAIRS +int paintedtime; // sample PAIRS + + +#define MAX_SFX 512 +sfx_t *known_sfx; // hunk allocated [MAX_SFX] +int num_sfx; + +sfx_t *ambient_sfx[NUM_AMBIENTS]; + +int desired_speed = 11025; +int desired_bits = 16; + +int sound_started=0; + +cvar_t bgmvolume = {"bgmvolume", "1", true}; +cvar_t volume = {"volume", "0.7", true}; + +cvar_t nosound = {"nosound", "0"}; +cvar_t precache = {"precache", "1"}; +cvar_t loadas8bit = {"loadas8bit", "0"}; +cvar_t bgmbuffer = {"bgmbuffer", "4096"}; +cvar_t ambient_level = {"ambient_level", "0.3"}; +cvar_t ambient_fade = {"ambient_fade", "100"}; +cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"}; +cvar_t snd_show = {"snd_show", "0"}; +cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true}; + + +// ==================================================================== +// User-setable variables +// ==================================================================== + + +// +// Fake dma is a synchronous faking of the DMA progress used for +// isolating performance in the renderer. The fakedma_updates is +// number of times S_Update() is called per second. +// + +qboolean fakedma = false; +int fakedma_updates = 15; + + +void S_AmbientOff (void) +{ + snd_ambient = false; +} + + +void S_AmbientOn (void) +{ + snd_ambient = true; +} + + +void S_SoundInfo_f(void) +{ + if (!sound_started || !shm) + { + Con_Printf ("sound system not started\n"); + return; + } + + Con_Printf("%5d stereo\n", shm->channels - 1); + Con_Printf("%5d samples\n", shm->samples); + Con_Printf("%5d samplepos\n", shm->samplepos); + Con_Printf("%5d samplebits\n", shm->samplebits); + Con_Printf("%5d submission_chunk\n", shm->submission_chunk); + Con_Printf("%5d speed\n", shm->speed); + Con_Printf("0x%x dma buffer\n", shm->buffer); + Con_Printf("%5d total_channels\n", total_channels); +} + + +/* +================ +S_Startup +================ +*/ + +void S_Startup (void) +{ + int rc; + + if (!snd_initialized) + return; + + if (!fakedma) + { + rc = SNDDMA_Init(); + + if (!rc) + { +#ifndef _WIN32 + Con_Printf("S_Startup: SNDDMA_Init failed.\n"); +#endif + sound_started = 0; + return; + } + } + + sound_started = 1; +} + + +/* +================ +S_Init +================ +*/ +void S_Init (void) +{ + +// Con_Printf("\nSound Initialization\n"); + + if (COM_CheckParm("-nosound")) + return; + + if (COM_CheckParm("-simsound")) + fakedma = true; + + Cmd_AddCommand("play", S_Play); + Cmd_AddCommand("playvol", S_PlayVol); + Cmd_AddCommand("stopsound", S_StopAllSoundsC); + Cmd_AddCommand("soundlist", S_SoundList); + Cmd_AddCommand("soundinfo", S_SoundInfo_f); + + Cvar_RegisterVariable(&nosound); + Cvar_RegisterVariable(&volume); + Cvar_RegisterVariable(&precache); + Cvar_RegisterVariable(&loadas8bit); + Cvar_RegisterVariable(&bgmvolume); + Cvar_RegisterVariable(&bgmbuffer); + Cvar_RegisterVariable(&ambient_level); + Cvar_RegisterVariable(&ambient_fade); + Cvar_RegisterVariable(&snd_noextraupdate); + Cvar_RegisterVariable(&snd_show); + Cvar_RegisterVariable(&_snd_mixahead); + + if (host_parms.memsize < 0x800000) + { + Cvar_Set ("loadas8bit", "1"); + Con_Printf ("loading all sounds as 8bit\n"); + } + + + + snd_initialized = true; + + S_Startup (); + + SND_InitScaletable (); + + known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t"); + num_sfx = 0; + +// create a piece of DMA memory + + if (fakedma) + { + shm = (void *) Hunk_AllocName(sizeof(*shm), "shm"); + shm->splitbuffer = 0; + shm->samplebits = 16; + shm->speed = 22050; + shm->channels = 2; + shm->samples = 32768; + shm->samplepos = 0; + shm->soundalive = true; + shm->gamealive = true; + shm->submission_chunk = 1; + shm->buffer = Hunk_AllocName(1<<16, "shmbuf"); + } + +// Con_Printf ("Sound sampling rate: %i\n", shm->speed); + + // provides a tick sound until washed clean + +// if (shm->buffer) +// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging + + ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); + ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); + + S_StopAllSounds (true); +} + + +// ======================================================================= +// Shutdown sound engine +// ======================================================================= + +void S_Shutdown(void) +{ + + if (!sound_started) + return; + + if (shm) + shm->gamealive = 0; + + shm = 0; + sound_started = 0; + + if (!fakedma) + { + SNDDMA_Shutdown(); + } +} + + +// ======================================================================= +// Load a sound +// ======================================================================= + +/* +================== +S_FindName + +================== +*/ +sfx_t *S_FindName (char *name) +{ + int i; + sfx_t *sfx; + + if (!name) + Sys_Error ("S_FindName: NULL\n"); + + if (Q_strlen(name) >= MAX_QPATH) + Sys_Error ("Sound name too long: %s", name); + +// see if already loaded + for (i=0 ; i < num_sfx ; i++) + if (!Q_strcmp(known_sfx[i].name, name)) + { + return &known_sfx[i]; + } + + if (num_sfx == MAX_SFX) + Sys_Error ("S_FindName: out of sfx_t"); + + sfx = &known_sfx[i]; + strcpy (sfx->name, name); + + num_sfx++; + + return sfx; +} + + +/* +================== +S_TouchSound + +================== +*/ +void S_TouchSound (char *name) +{ + sfx_t *sfx; + + if (!sound_started) + return; + + sfx = S_FindName (name); + Cache_Check (&sfx->cache); +} + +/* +================== +S_PrecacheSound + +================== +*/ +sfx_t *S_PrecacheSound (char *name) +{ + sfx_t *sfx; + + if (!sound_started || nosound.value) + return NULL; + + sfx = S_FindName (name); + +// cache it in + if (precache.value) + S_LoadSound (sfx); + + return sfx; +} + + +//============================================================================= + +/* +================= +SND_PickChannel +================= +*/ +channel_t *SND_PickChannel(int entnum, int entchannel) +{ + int ch_idx; + int first_to_die; + int life_left; + +// Check for replacement sound, or find the best one to replace + first_to_die = -1; + life_left = 0x7fffffff; + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) + { + if (entchannel != 0 // channel 0 never overrides + && channels[ch_idx].entnum == entnum + && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) + { // allways override sound from same entity + first_to_die = ch_idx; + break; + } + + // don't let monster sounds override player sounds + if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx) + continue; + + if (channels[ch_idx].end - paintedtime < life_left) + { + life_left = channels[ch_idx].end - paintedtime; + first_to_die = ch_idx; + } + } + + if (first_to_die == -1) + return NULL; + + if (channels[first_to_die].sfx) + channels[first_to_die].sfx = NULL; + + return &channels[first_to_die]; +} + +/* +================= +SND_Spatialize +================= +*/ +void SND_Spatialize(channel_t *ch) +{ + vec_t dot; + vec_t dist; + vec_t lscale, rscale, scale; + vec3_t source_vec; + sfx_t *snd; + +// anything coming from the view entity will allways be full volume + if (ch->entnum == cl.viewentity) + { + ch->leftvol = ch->master_vol; + ch->rightvol = ch->master_vol; + return; + } + +// calculate stereo seperation and distance attenuation + + snd = ch->sfx; + VectorSubtract(ch->origin, listener_origin, source_vec); + + dist = VectorNormalize(source_vec) * ch->dist_mult; + + dot = DotProduct(listener_right, source_vec); + + if (shm->channels == 1) + { + rscale = 1.0; + lscale = 1.0; + } + else + { + rscale = 1.0 + dot; + lscale = 1.0 - dot; + } + +// add in distance effect + scale = (1.0 - dist) * rscale; + ch->rightvol = (int) (ch->master_vol * scale); + if (ch->rightvol < 0) + ch->rightvol = 0; + + scale = (1.0 - dist) * lscale; + ch->leftvol = (int) (ch->master_vol * scale); + if (ch->leftvol < 0) + ch->leftvol = 0; +} + + +// ======================================================================= +// Start a sound effect +// ======================================================================= + +void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +{ + channel_t *target_chan, *check; + sfxcache_t *sc; + int vol; + int ch_idx; + int skip; + + if (!sound_started) + return; + + if (!sfx) + return; + + if (nosound.value) + return; + + vol = fvol*255; + +// pick a channel to play on + target_chan = SND_PickChannel(entnum, entchannel); + if (!target_chan) + return; + +// spatialize + memset (target_chan, 0, sizeof(*target_chan)); + VectorCopy(origin, target_chan->origin); + target_chan->dist_mult = attenuation / sound_nominal_clip_dist; + target_chan->master_vol = vol; + target_chan->entnum = entnum; + target_chan->entchannel = entchannel; + SND_Spatialize(target_chan); + + if (!target_chan->leftvol && !target_chan->rightvol) + return; // not audible at all + +// new channel + sc = S_LoadSound (sfx); + if (!sc) + { + target_chan->sfx = NULL; + return; // couldn't load the sound's data + } + + target_chan->sfx = sfx; + target_chan->pos = 0.0; + target_chan->end = paintedtime + sc->length; + +// if an identical sound has also been started this frame, offset the pos +// a bit to keep it from just making the first one louder + check = &channels[NUM_AMBIENTS]; + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) + { + if (check == target_chan) + continue; + if (check->sfx == sfx && !check->pos) + { + skip = rand () % (int)(0.1*shm->speed); + if (skip >= target_chan->end) + skip = target_chan->end - 1; + target_chan->pos += skip; + target_chan->end -= skip; + break; + } + + } +} + +void S_StopSound(int entnum, int entchannel) +{ + int i; + + for (i=0 ; ibuffer && !pDSBuf)) +#else + if (!sound_started || !shm || !shm->buffer) +#endif + return; + + if (shm->samplebits == 8) + clear = 0x80; + else + clear = 0; + +#ifdef _WIN32 + if (pDSBuf) + { + DWORD dwSize; + DWORD *pData; + int reps; + HRESULT hresult; + + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n"); + S_Shutdown (); + return; + } + } + + Q_memset(pData, clear, shm->samples * shm->samplebits/8); + + pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0); + + } + else +#endif + { + Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8); + } +} + + +/* +================= +S_StaticSound +================= +*/ +void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) +{ + channel_t *ss; + sfxcache_t *sc; + + if (!sfx) + return; + + if (total_channels == MAX_CHANNELS) + { + Con_Printf ("total_channels == MAX_CHANNELS\n"); + return; + } + + ss = &channels[total_channels]; + total_channels++; + + sc = S_LoadSound (sfx); + if (!sc) + return; + + if (sc->loopstart == -1) + { + Con_Printf ("Sound %s not looped\n", sfx->name); + return; + } + + ss->sfx = sfx; + VectorCopy (origin, ss->origin); + ss->master_vol = vol; + ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; + ss->end = paintedtime + sc->length; + + SND_Spatialize (ss); +} + + +//============================================================================= + +/* +=================== +S_UpdateAmbientSounds +=================== +*/ +void S_UpdateAmbientSounds (void) +{ + mleaf_t *l; + float vol; + int ambient_channel; + channel_t *chan; + + if (!snd_ambient) + return; + +// calc ambient sound levels + if (!cl.worldmodel) + return; + + l = Mod_PointInLeaf (listener_origin, cl.worldmodel); + if (!l || !ambient_level.value) + { + for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) + channels[ambient_channel].sfx = NULL; + return; + } + + for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) + { + chan = &channels[ambient_channel]; + chan->sfx = ambient_sfx[ambient_channel]; + + vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; + if (vol < 8) + vol = 0; + + // don't adjust volume too fast + if (chan->master_vol < vol) + { + chan->master_vol += host_frametime * ambient_fade.value; + if (chan->master_vol > vol) + chan->master_vol = vol; + } + else if (chan->master_vol > vol) + { + chan->master_vol -= host_frametime * ambient_fade.value; + if (chan->master_vol < vol) + chan->master_vol = vol; + } + + chan->leftvol = chan->rightvol = chan->master_vol; + } +} + + +/* +============ +S_Update + +Called once each time through the main loop +============ +*/ +void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) +{ + int i, j; + int total; + channel_t *ch; + channel_t *combine; + + if (!sound_started || (snd_blocked > 0)) + return; + + VectorCopy(origin, listener_origin); + VectorCopy(forward, listener_forward); + VectorCopy(right, listener_right); + VectorCopy(up, listener_up); + +// update general area ambient sound sources + S_UpdateAmbientSounds (); + + combine = NULL; + +// update spatialization for static and dynamic sounds + ch = channels+NUM_AMBIENTS; + for (i=NUM_AMBIENTS ; isfx) + continue; + SND_Spatialize(ch); // respatialize channel + if (!ch->leftvol && !ch->rightvol) + continue; + + // try to combine static sounds with a previous channel of the same + // sound effect so we don't mix five torches every frame + + if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) + { + // see if it can just use the last one + if (combine && combine->sfx == ch->sfx) + { + combine->leftvol += ch->leftvol; + combine->rightvol += ch->rightvol; + ch->leftvol = ch->rightvol = 0; + continue; + } + // search for one + combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; + for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; jsfx == ch->sfx) + break; + + if (j == total_channels) + { + combine = NULL; + } + else + { + if (combine != ch) + { + combine->leftvol += ch->leftvol; + combine->rightvol += ch->rightvol; + ch->leftvol = ch->rightvol = 0; + } + continue; + } + } + + + } + +// +// debugging output +// + if (snd_show.value) + { + total = 0; + ch = channels; + for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) + { + //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); + total++; + } + + Con_Printf ("----(%i)----\n", total); + } + +// mix some sound + S_Update_(); +} + +void GetSoundtime(void) +{ + int samplepos; + static int buffers; + static int oldsamplepos; + int fullsamples; + + fullsamples = shm->samples / shm->channels; + +// it is possible to miscount buffers if it has wrapped twice between +// calls to S_Update. Oh well. + samplepos = SNDDMA_GetDMAPos(); + + if (samplepos < oldsamplepos) + { + buffers++; // buffer wrapped + + if (paintedtime > 0x40000000) + { // time to chop things off to avoid 32 bit limits + buffers = 0; + paintedtime = fullsamples; + S_StopAllSounds (true); + } + } + oldsamplepos = samplepos; + + soundtime = buffers*fullsamples + samplepos/shm->channels; +} + +void S_ExtraUpdate (void) +{ + +#ifdef _WIN32 + IN_Accumulate (); +#endif + + if (snd_noextraupdate.value) + return; // don't pollute timings + S_Update_(); +} + + + +void S_Update_(void) +{ + unsigned endtime; + int samps; + + if (!sound_started || (snd_blocked > 0)) + return; + +// Updates DMA time + GetSoundtime(); + +// check to make sure that we haven't overshot + if (paintedtime < soundtime) + { + //Con_Printf ("S_Update_ : overflow\n"); + paintedtime = soundtime; + } + +// mix ahead of current position + endtime = soundtime + _snd_mixahead.value * shm->speed; + samps = shm->samples >> (shm->channels-1); + if (endtime - soundtime > samps) + endtime = soundtime + samps; + +#ifdef _WIN32 +// if the buffer was lost or stopped, restore it and/or restart it + { + DWORD dwStatus; + + if (pDSBuf) + { + if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK) + Con_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); + } + } +#endif + + S_PaintChannels (endtime); + + SNDDMA_Submit (); +} + +/* +=============================================================================== + +console functions + +=============================================================================== +*/ + +void S_Play(void) +{ + static int hash=345; + int i; + char name[256]; + sfx_t *sfx; + + i = 1; + while (icache); + if (!sc) + continue; + size = sc->length*sc->width*(sc->stereo+1); + total += size; + if (sc->loopstart >= 0) + Con_Printf ("L"); + else + Con_Printf (" "); + Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name); + } + Con_Printf ("Total resident: %i\n", total); +} + + +void S_LocalSound (char *sound) +{ + sfx_t *sfx; + + if (nosound.value) + return; + if (!sound_started) + return; + + sfx = S_PrecacheSound (sound); + if (!sfx) + { + Con_Printf ("S_LocalSound: can't cache %s\n", sound); + return; + } + S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); +} + + +void S_ClearPrecache (void) +{ +} + + +void S_BeginPrecaching (void) +{ +} + + +void S_EndPrecaching (void) +{ +} + diff --git a/source/snd_mem.c b/source/snd_mem.c index e385137..bdf10fd 100644 --- a/source/snd_mem.c +++ b/source/snd_mem.c @@ -1,343 +1,343 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// snd_mem.c: sound caching - -#include "quakedef.h" - -int cache_full_cycle; - -byte *S_Alloc (int size); - -/* -================ -ResampleSfx -================ -*/ -void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) -{ - int outcount; - int srcsample; - float stepscale; - int i; - int sample, samplefrac, fracstep; - sfxcache_t *sc; - - sc = Cache_Check (&sfx->cache); - if (!sc) - return; - - stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 - - outcount = sc->length / stepscale; - sc->length = outcount; - if (sc->loopstart != -1) - sc->loopstart = sc->loopstart / stepscale; - - sc->speed = shm->speed; - if (loadas8bit.value) - sc->width = 1; - else - sc->width = inwidth; - sc->stereo = 0; - -// resample / decimate to the current source rate - - if (stepscale == 1 && inwidth == 1 && sc->width == 1) - { -// fast special case - for (i=0 ; idata)[i] - = (int)( (unsigned char)(data[i]) - 128); - } - else - { -// general case - samplefrac = 0; - fracstep = stepscale*256; - for (i=0 ; i> 8; - samplefrac += fracstep; - if (inwidth == 2) - sample = LittleShort ( ((short *)data)[srcsample] ); - else - sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; - if (sc->width == 2) - ((short *)sc->data)[i] = sample; - else - ((signed char *)sc->data)[i] = sample >> 8; - } - } -} - -//============================================================================= - -/* -============== -S_LoadSound -============== -*/ -sfxcache_t *S_LoadSound (sfx_t *s) -{ - char namebuffer[256]; - byte *data; - wavinfo_t info; - int len; - float stepscale; - sfxcache_t *sc; - byte stackbuf[1*1024]; // avoid dirtying the cache heap - -// see if still in memory - sc = Cache_Check (&s->cache); - if (sc) - return sc; - -//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); -// load it in - Q_strcpy(namebuffer, "sound/"); - Q_strcat(namebuffer, s->name); - -// Con_Printf ("loading %s\n",namebuffer); - - data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); - - if (!data) - { - Con_Printf ("Couldn't load %s\n", namebuffer); - return NULL; - } - - info = GetWavinfo (s->name, data, com_filesize); - if (info.channels != 1) - { - Con_Printf ("%s is a stereo sample\n",s->name); - return NULL; - } - - stepscale = (float)info.rate / shm->speed; - len = info.samples / stepscale; - - len = len * info.width * info.channels; - - sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); - if (!sc) - return NULL; - - sc->length = info.samples; - sc->loopstart = info.loopstart; - sc->speed = info.rate; - sc->width = info.width; - sc->stereo = info.channels; - - ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); - - return sc; -} - - - -/* -=============================================================================== - -WAV loading - -=============================================================================== -*/ - - -byte *data_p; -byte *iff_end; -byte *last_chunk; -byte *iff_data; -int iff_chunk_len; - - -short GetLittleShort(void) -{ - short val = 0; - val = *data_p; - val = val + (*(data_p+1)<<8); - data_p += 2; - return val; -} - -int GetLittleLong(void) -{ - int val = 0; - val = *data_p; - val = val + (*(data_p+1)<<8); - val = val + (*(data_p+2)<<16); - val = val + (*(data_p+3)<<24); - data_p += 4; - return val; -} - -void FindNextChunk(char *name) -{ - while (1) - { - data_p=last_chunk; - - if (data_p >= iff_end) - { // didn't find the chunk - data_p = NULL; - return; - } - - data_p += 4; - iff_chunk_len = GetLittleLong(); - if (iff_chunk_len < 0) - { - data_p = NULL; - return; - } -// if (iff_chunk_len > 1024*1024) -// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); - data_p -= 8; - last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); - if (!Q_strncmp(data_p, name, 4)) - return; - } -} - -void FindChunk(char *name) -{ - last_chunk = iff_data; - FindNextChunk (name); -} - - -#if 0 -void DumpChunks(void) -{ - char str[5]; - - str[4] = 0; - data_p=iff_data; - do - { - memcpy (str, data_p, 4); - data_p += 4; - iff_chunk_len = GetLittleLong(); - Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); - data_p += (iff_chunk_len + 1) & ~1; - } while (data_p < iff_end); -} -#endif - -/* -============ -GetWavinfo -============ -*/ -wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) -{ - wavinfo_t info; - int i; - int format; - int samples; - - memset (&info, 0, sizeof(info)); - - if (!wav) - return info; - - iff_data = wav; - iff_end = wav + wavlength; - -// find "RIFF" chunk - FindChunk("RIFF"); - if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) - { - Con_Printf("Missing RIFF/WAVE chunks\n"); - return info; - } - -// get "fmt " chunk - iff_data = data_p + 12; -// DumpChunks (); - - FindChunk("fmt "); - if (!data_p) - { - Con_Printf("Missing fmt chunk\n"); - return info; - } - data_p += 8; - format = GetLittleShort(); - if (format != 1) - { - Con_Printf("Microsoft PCM format only\n"); - return info; - } - - info.channels = GetLittleShort(); - info.rate = GetLittleLong(); - data_p += 4+2; - info.width = GetLittleShort() / 8; - -// get cue chunk - FindChunk("cue "); - if (data_p) - { - data_p += 32; - info.loopstart = GetLittleLong(); -// Con_Printf("loopstart=%d\n", sfx->loopstart); - - // if the next chunk is a LIST chunk, look for a cue length marker - FindNextChunk ("LIST"); - if (data_p) - { - if (!strncmp (data_p + 28, "mark", 4)) - { // this is not a proper parse, but it works with cooledit... - data_p += 24; - i = GetLittleLong (); // samples in loop - info.samples = info.loopstart + i; -// Con_Printf("looped length: %i\n", i); - } - } - } - else - info.loopstart = -1; - -// find data chunk - FindChunk("data"); - if (!data_p) - { - Con_Printf("Missing data chunk\n"); - return info; - } - - data_p += 4; - samples = GetLittleLong () / info.width; - - if (info.samples) - { - if (samples < info.samples) - Sys_Error ("Sound %s has a bad loop length", name); - } - else - info.samples = samples; - - info.dataofs = data_p - wav; - - return info; -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// snd_mem.c: sound caching + +#include "quakedef.h" + +int cache_full_cycle; + +byte *S_Alloc (int size); + +/* +================ +ResampleSfx +================ +*/ +void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) +{ + int outcount; + int srcsample; + float stepscale; + int i; + int sample, samplefrac, fracstep; + sfxcache_t *sc; + + sc = Cache_Check (&sfx->cache); + if (!sc) + return; + + stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 + + outcount = sc->length / stepscale; + sc->length = outcount; + if (sc->loopstart != -1) + sc->loopstart = sc->loopstart / stepscale; + + sc->speed = shm->speed; + if (loadas8bit.value) + sc->width = 1; + else + sc->width = inwidth; + sc->stereo = 0; + +// resample / decimate to the current source rate + + if (stepscale == 1 && inwidth == 1 && sc->width == 1) + { +// fast special case + for (i=0 ; idata)[i] + = (int)( (unsigned char)(data[i]) - 128); + } + else + { +// general case + samplefrac = 0; + fracstep = stepscale*256; + for (i=0 ; i> 8; + samplefrac += fracstep; + if (inwidth == 2) + sample = LittleShort ( ((short *)data)[srcsample] ); + else + sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; + if (sc->width == 2) + ((short *)sc->data)[i] = sample; + else + ((signed char *)sc->data)[i] = sample >> 8; + } + } +} + +//============================================================================= + +/* +============== +S_LoadSound +============== +*/ +sfxcache_t *S_LoadSound (sfx_t *s) +{ + char namebuffer[256]; + byte *data; + wavinfo_t info; + int len; + float stepscale; + sfxcache_t *sc; + byte stackbuf[1*1024]; // avoid dirtying the cache heap + +// see if still in memory + sc = Cache_Check (&s->cache); + if (sc) + return sc; + +//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); +// load it in + Q_strcpy(namebuffer, "sound/"); + Q_strcat(namebuffer, s->name); + +// Con_Printf ("loading %s\n",namebuffer); + + data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); + + if (!data) + { + Con_Printf ("Couldn't load %s\n", namebuffer); + return NULL; + } + + info = GetWavinfo (s->name, data, com_filesize); + if (info.channels != 1) + { + Con_Printf ("%s is a stereo sample\n",s->name); + return NULL; + } + + stepscale = (float)info.rate / shm->speed; + len = info.samples / stepscale; + + len = len * info.width * info.channels; + + sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); + if (!sc) + return NULL; + + sc->length = info.samples; + sc->loopstart = info.loopstart; + sc->speed = info.rate; + sc->width = info.width; + sc->stereo = info.channels; + + ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); + + return sc; +} + + + +/* +=============================================================================== + +WAV loading + +=============================================================================== +*/ + + +byte *data_p; +byte *iff_end; +byte *last_chunk; +byte *iff_data; +int iff_chunk_len; + + +short GetLittleShort(void) +{ + short val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + data_p += 2; + return val; +} + +int GetLittleLong(void) +{ + int val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + val = val + (*(data_p+2)<<16); + val = val + (*(data_p+3)<<24); + data_p += 4; + return val; +} + +void FindNextChunk(char *name) +{ + while (1) + { + data_p=last_chunk; + + if (data_p >= iff_end) + { // didn't find the chunk + data_p = NULL; + return; + } + + data_p += 4; + iff_chunk_len = GetLittleLong(); + if (iff_chunk_len < 0) + { + data_p = NULL; + return; + } +// if (iff_chunk_len > 1024*1024) +// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); + data_p -= 8; + last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); + if (!Q_strncmp(data_p, name, 4)) + return; + } +} + +void FindChunk(char *name) +{ + last_chunk = iff_data; + FindNextChunk (name); +} + + +#if 0 +void DumpChunks(void) +{ + char str[5]; + + str[4] = 0; + data_p=iff_data; + do + { + memcpy (str, data_p, 4); + data_p += 4; + iff_chunk_len = GetLittleLong(); + Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); + data_p += (iff_chunk_len + 1) & ~1; + } while (data_p < iff_end); +} +#endif + +/* +============ +GetWavinfo +============ +*/ +wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) +{ + wavinfo_t info; + int i; + int format; + int samples; + + memset (&info, 0, sizeof(info)); + + if (!wav) + return info; + + iff_data = wav; + iff_end = wav + wavlength; + +// find "RIFF" chunk + FindChunk("RIFF"); + if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) + { + Con_Printf("Missing RIFF/WAVE chunks\n"); + return info; + } + +// get "fmt " chunk + iff_data = data_p + 12; +// DumpChunks (); + + FindChunk("fmt "); + if (!data_p) + { + Con_Printf("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) + { + Con_Printf("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4+2; + info.width = GetLittleShort() / 8; + +// get cue chunk + FindChunk("cue "); + if (data_p) + { + data_p += 32; + info.loopstart = GetLittleLong(); +// Con_Printf("loopstart=%d\n", sfx->loopstart); + + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk ("LIST"); + if (data_p) + { + if (!strncmp (data_p + 28, "mark", 4)) + { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong (); // samples in loop + info.samples = info.loopstart + i; +// Con_Printf("looped length: %i\n", i); + } + } + } + else + info.loopstart = -1; + +// find data chunk + FindChunk("data"); + if (!data_p) + { + Con_Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong () / info.width; + + if (info.samples) + { + if (samples < info.samples) + Sys_Error ("Sound %s has a bad loop length", name); + } + else + info.samples = samples; + + info.dataofs = data_p - wav; + + return info; +} + diff --git a/source/snd_mix.c b/source/snd_mix.c index c040494..d31f6c9 100644 --- a/source/snd_mix.c +++ b/source/snd_mix.c @@ -1,398 +1,398 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// snd_mix.c -- portable code to mix sounds for snd_dma.c - -#include "quakedef.h" - -#ifdef _WIN32 -#include "winquake.h" -#else -#define DWORD unsigned long -#endif - -#define PAINTBUFFER_SIZE 512 -portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; -int snd_scaletable[32][256]; -int *snd_p, snd_linear_count, snd_vol; -short *snd_out; - -void Snd_WriteLinearBlastStereo16 (void); - -#if !id386 -void Snd_WriteLinearBlastStereo16 (void) -{ - int i; - int val; - - for (i=0 ; i>8; - if (val > 0x7fff) - snd_out[i] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i] = (short)0x8000; - else - snd_out[i] = val; - - val = (snd_p[i+1]*snd_vol)>>8; - if (val > 0x7fff) - snd_out[i+1] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i+1] = (short)0x8000; - else - snd_out[i+1] = val; - } -} -#endif - -void S_TransferStereo16 (int endtime) -{ - int lpos; - int lpaintedtime; - DWORD *pbuf; -#ifdef _WIN32 - int reps; - DWORD dwSize,dwSize2; - DWORD *pbuf2; - HRESULT hresult; -#endif - - snd_vol = volume.value*256; - - snd_p = (int *) paintbuffer; - lpaintedtime = paintedtime; - -#ifdef _WIN32 - if (pDSBuf) - { - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - S_Startup (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - S_Shutdown (); - S_Startup (); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)shm->buffer; - } - - while (lpaintedtime < endtime) - { - // handle recirculating buffer issues - lpos = lpaintedtime & ((shm->samples>>1)-1); - - snd_out = (short *) pbuf + (lpos<<1); - - snd_linear_count = (shm->samples>>1) - lpos; - if (lpaintedtime + snd_linear_count > endtime) - snd_linear_count = endtime - lpaintedtime; - - snd_linear_count <<= 1; - - // write a linear blast of samples - Snd_WriteLinearBlastStereo16 (); - - snd_p += snd_linear_count; - lpaintedtime += (snd_linear_count>>1); - } - -#ifdef _WIN32 - if (pDSBuf) - pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); -#endif -} - -void S_TransferPaintBuffer(int endtime) -{ - int out_idx; - int count; - int out_mask; - int *p; - int step; - int val; - int snd_vol; - DWORD *pbuf; -#ifdef _WIN32 - int reps; - DWORD dwSize,dwSize2; - DWORD *pbuf2; - HRESULT hresult; -#endif - - if (shm->samplebits == 16 && shm->channels == 2) - { - S_TransferStereo16 (endtime); - return; - } - - p = (int *) paintbuffer; - count = (endtime - paintedtime) * shm->channels; - out_mask = shm->samples - 1; - out_idx = paintedtime * shm->channels & out_mask; - step = 3 - shm->channels; - snd_vol = volume.value*256; - -#ifdef _WIN32 - if (pDSBuf) - { - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2,&dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - S_Startup (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); - S_Shutdown (); - S_Startup (); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)shm->buffer; - } - - if (shm->samplebits == 16) - { - short *out = (short *) pbuf; - while (count--) - { - val = (*p * snd_vol) >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = val; - out_idx = (out_idx + 1) & out_mask; - } - } - else if (shm->samplebits == 8) - { - unsigned char *out = (unsigned char *) pbuf; - while (count--) - { - val = (*p * snd_vol) >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = (val>>8) + 128; - out_idx = (out_idx + 1) & out_mask; - } - } - -#ifdef _WIN32 - if (pDSBuf) { - DWORD dwNewpos, dwWrite; - int il = paintedtime; - int ir = endtime - paintedtime; - - ir += il; - - pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); - - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite); - -// if ((dwNewpos >= il) && (dwNewpos <= ir)) -// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); - } -#endif -} - - -/* -=============================================================================== - -CHANNEL MIXING - -=============================================================================== -*/ - -void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime); -void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime); - -void S_PaintChannels(int endtime) -{ - int i; - int end; - channel_t *ch; - sfxcache_t *sc; - int ltime, count; - - while (paintedtime < endtime) - { - // if paintbuffer is smaller than DMA buffer - end = endtime; - if (endtime - paintedtime > PAINTBUFFER_SIZE) - end = paintedtime + PAINTBUFFER_SIZE; - - // clear the paint buffer - Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); - - // paint in the channels. - ch = channels; - for (i=0; isfx) - continue; - if (!ch->leftvol && !ch->rightvol) - continue; - sc = S_LoadSound (ch->sfx); - if (!sc) - continue; - - ltime = paintedtime; - - while (ltime < end) - { // paint up to end - if (ch->end < end) - count = ch->end - ltime; - else - count = end - ltime; - - if (count > 0) - { - if (sc->width == 1) - SND_PaintChannelFrom8(ch, sc, count); - else - SND_PaintChannelFrom16(ch, sc, count); - - ltime += count; - } - - // if at end of loop, restart - if (ltime >= ch->end) - { - if (sc->loopstart >= 0) - { - ch->pos = sc->loopstart; - ch->end = ltime + sc->length - ch->pos; - } - else - { // channel just stopped - ch->sfx = NULL; - break; - } - } - } - - } - - // transfer out according to DMA format - S_TransferPaintBuffer(end); - paintedtime = end; - } -} - -void SND_InitScaletable (void) -{ - int i, j; - - for (i=0 ; i<32 ; i++) - for (j=0 ; j<256 ; j++) - snd_scaletable[i][j] = ((signed char)j) * i * 8; -} - - -#if !id386 - -void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) -{ - int data; - int *lscale, *rscale; - unsigned char *sfx; - int i; - - if (ch->leftvol > 255) - ch->leftvol = 255; - if (ch->rightvol > 255) - ch->rightvol = 255; - - lscale = snd_scaletable[ch->leftvol >> 3]; - rscale = snd_scaletable[ch->rightvol >> 3]; - sfx = (signed char *)sc->data + ch->pos; - - for (i=0 ; ipos += count; -} - -#endif // !id386 - - -void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) -{ - int data; - int left, right; - int leftvol, rightvol; - signed short *sfx; - int i; - - leftvol = ch->leftvol; - rightvol = ch->rightvol; - sfx = (signed short *)sc->data + ch->pos; - - for (i=0 ; i> 8; - right = (data * rightvol) >> 8; - paintbuffer[i].left += left; - paintbuffer[i].right += right; - } - - ch->pos += count; -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// snd_mix.c -- portable code to mix sounds for snd_dma.c + +#include "quakedef.h" + +#ifdef _WIN32 +#include "winquake.h" +#else +#define DWORD unsigned long +#endif + +#define PAINTBUFFER_SIZE 512 +portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; +int snd_scaletable[32][256]; +int *snd_p, snd_linear_count, snd_vol; +short *snd_out; + +void Snd_WriteLinearBlastStereo16 (void); + +#if !id386 +void Snd_WriteLinearBlastStereo16 (void) +{ + int i; + int val; + + for (i=0 ; i>8; + if (val > 0x7fff) + snd_out[i] = 0x7fff; + else if (val < (short)0x8000) + snd_out[i] = (short)0x8000; + else + snd_out[i] = val; + + val = (snd_p[i+1]*snd_vol)>>8; + if (val > 0x7fff) + snd_out[i+1] = 0x7fff; + else if (val < (short)0x8000) + snd_out[i+1] = (short)0x8000; + else + snd_out[i+1] = val; + } +} +#endif + +void S_TransferStereo16 (int endtime) +{ + int lpos; + int lpaintedtime; + DWORD *pbuf; +#ifdef _WIN32 + int reps; + DWORD dwSize,dwSize2; + DWORD *pbuf2; + HRESULT hresult; +#endif + + snd_vol = volume.value*256; + + snd_p = (int *) paintbuffer; + lpaintedtime = paintedtime; + +#ifdef _WIN32 + if (pDSBuf) + { + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, + &pbuf2, &dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + S_Startup (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); + S_Shutdown (); + S_Startup (); + return; + } + } + } + else +#endif + { + pbuf = (DWORD *)shm->buffer; + } + + while (lpaintedtime < endtime) + { + // handle recirculating buffer issues + lpos = lpaintedtime & ((shm->samples>>1)-1); + + snd_out = (short *) pbuf + (lpos<<1); + + snd_linear_count = (shm->samples>>1) - lpos; + if (lpaintedtime + snd_linear_count > endtime) + snd_linear_count = endtime - lpaintedtime; + + snd_linear_count <<= 1; + + // write a linear blast of samples + Snd_WriteLinearBlastStereo16 (); + + snd_p += snd_linear_count; + lpaintedtime += (snd_linear_count>>1); + } + +#ifdef _WIN32 + if (pDSBuf) + pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); +#endif +} + +void S_TransferPaintBuffer(int endtime) +{ + int out_idx; + int count; + int out_mask; + int *p; + int step; + int val; + int snd_vol; + DWORD *pbuf; +#ifdef _WIN32 + int reps; + DWORD dwSize,dwSize2; + DWORD *pbuf2; + HRESULT hresult; +#endif + + if (shm->samplebits == 16 && shm->channels == 2) + { + S_TransferStereo16 (endtime); + return; + } + + p = (int *) paintbuffer; + count = (endtime - paintedtime) * shm->channels; + out_mask = shm->samples - 1; + out_idx = paintedtime * shm->channels & out_mask; + step = 3 - shm->channels; + snd_vol = volume.value*256; + +#ifdef _WIN32 + if (pDSBuf) + { + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, + &pbuf2,&dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + S_Startup (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); + S_Shutdown (); + S_Startup (); + return; + } + } + } + else +#endif + { + pbuf = (DWORD *)shm->buffer; + } + + if (shm->samplebits == 16) + { + short *out = (short *) pbuf; + while (count--) + { + val = (*p * snd_vol) >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = val; + out_idx = (out_idx + 1) & out_mask; + } + } + else if (shm->samplebits == 8) + { + unsigned char *out = (unsigned char *) pbuf; + while (count--) + { + val = (*p * snd_vol) >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = (val>>8) + 128; + out_idx = (out_idx + 1) & out_mask; + } + } + +#ifdef _WIN32 + if (pDSBuf) { + DWORD dwNewpos, dwWrite; + int il = paintedtime; + int ir = endtime - paintedtime; + + ir += il; + + pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); + + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite); + +// if ((dwNewpos >= il) && (dwNewpos <= ir)) +// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); + } +#endif +} + + +/* +=============================================================================== + +CHANNEL MIXING + +=============================================================================== +*/ + +void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime); +void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime); + +void S_PaintChannels(int endtime) +{ + int i; + int end; + channel_t *ch; + sfxcache_t *sc; + int ltime, count; + + while (paintedtime < endtime) + { + // if paintbuffer is smaller than DMA buffer + end = endtime; + if (endtime - paintedtime > PAINTBUFFER_SIZE) + end = paintedtime + PAINTBUFFER_SIZE; + + // clear the paint buffer + Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); + + // paint in the channels. + ch = channels; + for (i=0; isfx) + continue; + if (!ch->leftvol && !ch->rightvol) + continue; + sc = S_LoadSound (ch->sfx); + if (!sc) + continue; + + ltime = paintedtime; + + while (ltime < end) + { // paint up to end + if (ch->end < end) + count = ch->end - ltime; + else + count = end - ltime; + + if (count > 0) + { + if (sc->width == 1) + SND_PaintChannelFrom8(ch, sc, count); + else + SND_PaintChannelFrom16(ch, sc, count); + + ltime += count; + } + + // if at end of loop, restart + if (ltime >= ch->end) + { + if (sc->loopstart >= 0) + { + ch->pos = sc->loopstart; + ch->end = ltime + sc->length - ch->pos; + } + else + { // channel just stopped + ch->sfx = NULL; + break; + } + } + } + + } + + // transfer out according to DMA format + S_TransferPaintBuffer(end); + paintedtime = end; + } +} + +void SND_InitScaletable (void) +{ + int i, j; + + for (i=0 ; i<32 ; i++) + for (j=0 ; j<256 ; j++) + snd_scaletable[i][j] = ((signed char)j) * i * 8; +} + + +#if !id386 + +void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) +{ + int data; + int *lscale, *rscale; + unsigned char *sfx; + int i; + + if (ch->leftvol > 255) + ch->leftvol = 255; + if (ch->rightvol > 255) + ch->rightvol = 255; + + lscale = snd_scaletable[ch->leftvol >> 3]; + rscale = snd_scaletable[ch->rightvol >> 3]; + sfx = (signed char *)sc->data + ch->pos; + + for (i=0 ; ipos += count; +} + +#endif // !id386 + + +void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) +{ + int data; + int left, right; + int leftvol, rightvol; + signed short *sfx; + int i; + + leftvol = ch->leftvol; + rightvol = ch->rightvol; + sfx = (signed short *)sc->data + ch->pos; + + for (i=0 ; i> 8; + right = (data * rightvol) >> 8; + paintbuffer[i].left += left; + paintbuffer[i].right += right; + } + + ch->pos += count; +} + diff --git a/source/snd_win.c b/source/snd_win.c index a31905e..f75db02 100644 --- a/source/snd_win.c +++ b/source/snd_win.c @@ -1,727 +1,727 @@ -/* -Copyright (C) 1996-1997 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 "quakedef.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; - -static qboolean wavonly; -static qboolean dsound_init; -static qboolean wav_init; -static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; -static qboolean primary_format_set; - -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); - - -/* -================== -S_BlockSound -================== -*/ -void S_BlockSound (void) -{ - -// DirectSound takes care of blocking itself - if (snd_iswave) - { - snd_blocked++; - - if (snd_blocked == 1) - waveOutReset (hWaveOut); - } -} - - -/* -================== -S_UnblockSound -================== -*/ -void S_UnblockSound (void) -{ - -// DirectSound takes care of blocking itself - if (snd_iswave) - { - snd_blocked--; - } -} - - -/* -================== -FreeSound -================== -*/ -void FreeSound (void) -{ - int i; - - if (pDSBuf) - { - 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)) - { - pDSPBuf->lpVtbl->Release(pDSPBuf); - } - - if (pDS) - { - pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); - pDS->lpVtbl->Release(pDS); - } - - if (hWaveOut) - { - waveOutReset (hWaveOut); - - if (lpWaveHdr) - { - for (i=0 ; i< WAV_BUFFERS ; i++) - waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); - } - - waveOutClose (hWaveOut); - - if (hWaveHdr) - { - GlobalUnlock(hWaveHdr); - GlobalFree(hWaveHdr); - } - - if (hData) - { - GlobalUnlock(hData); - GlobalFree(hData); - } - - } - - 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) -{ - DSBUFFERDESC dsbuf; - DSBCAPS dsbcaps; - DWORD dwSize, dwWrite; - DSCAPS dscaps; - WAVEFORMATEX format, pformat; - HRESULT hresult; - int reps; - - memset ((void *)&sn, 0, sizeof (sn)); - - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - shm->speed = 11025; - - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->speed; - format.nBlockAlign = format.nChannels - *format.wBitsPerSample / 8; - format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec - *format.nBlockAlign; - - if (!hInstDS) - { - hInstDS = LoadLibrary("dsound.dll"); - - if (hInstDS == NULL) - { - Con_SafePrintf ("Couldn't load dsound.dll\n"); - return SIS_FAILURE; - } - - pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); - - if (!pDirectSoundCreate) - { - Con_SafePrintf ("Couldn't get DS proc addr\n"); - return SIS_FAILURE; - } - } - - while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK) - { - if (hresult != DSERR_ALLOCATED) - { - Con_SafePrintf ("DirectSound create 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) - { - Con_SafePrintf ("DirectSoundCreate failure\n" - " hardware already in use\n"); - return SIS_NOTAVAIL; - } - } - - dscaps.dwSize = sizeof(dscaps); - - if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) - { - Con_SafePrintf ("Couldn't get DS caps\n"); - } - - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) - { - Con_SafePrintf ("No DirectSound driver installed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (); - return SIS_FAILURE; - } - -// 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; - - if (!COM_CheckParm ("-snoforceformat")) - { - if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) - { - pformat = format; - - if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) - { -// if (snd_firsttime) -// Con_SafePrintf ("Set primary sound buffer format: no\n"); - } - else -// { -// if (snd_firsttime) -// Con_SafePrintf ("Set primary sound buffer format: yes\n"); - - primary_format_set = true; -// } - } - } - - if (!primary_format_set || !COM_CheckParm ("-primarysound")) - { - // 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); - - if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) - { - Con_SafePrintf ("DS:CreateSoundBuffer Failed"); - FreeSound (); - return SIS_FAILURE; - } - - shm->channels = format.nChannels; - shm->samplebits = format.wBitsPerSample; - shm->speed = format.nSamplesPerSec; - - if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) - { - Con_SafePrintf ("DS:GetCaps failed\n"); - FreeSound (); - return SIS_FAILURE; - } - -// if (snd_firsttime) -// Con_SafePrintf ("Using secondary sound buffer\n"); - } - else - { - if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) - { - Con_Printf ("DS:GetCaps failed\n"); - return SIS_FAILURE; - } - - pDSBuf = pDSPBuf; -// Con_SafePrintf ("Using primary sound buffer\n"); - } - - // Make sure mixer is active - pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - -/* if (snd_firsttime) - Con_SafePrintf(" %d channel(s)\n" - " %d bits/sample\n" - " %d bytes/sec\n", - shm->channels, shm->samplebits, shm->speed);*/ - - gSndBufSize = dsbcaps.dwBufferBytes; - -// initialize the buffer - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (++reps > 10000) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); - FreeSound (); - return SIS_FAILURE; - } - - } - - memset(lpData, 0, dwSize); -// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging - - pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); - - /* 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); - - shm->soundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) lpData; - sample16 = (shm->samplebits/8) - 1; - - dsound_init = true; - - return SIS_SUCCESS; -} - - -/* -================== -SNDDM_InitWav - -Crappy windows multimedia base -================== -*/ -qboolean SNDDMA_InitWav (void) -{ - WAVEFORMATEX format; - int i; - HRESULT hr; - - snd_sent = 0; - snd_completed = 0; - - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - shm->speed = 11025; - - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->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. */ - while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, - &format, - 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) - { - if (hr != MMSYSERR_ALLOCATED) - { - Con_SafePrintf ("waveOutOpen 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 with no sound.", - "Sound not available", - MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) - { - Con_SafePrintf ("waveOutOpen failure;\n" - " hardware already in use\n"); - return false; - } - } - - /* - * Allocate and lock memory for the waveform data. The memory - * for waveform data must be globally allocated with - * GMEM_MOVEABLE and GMEM_SHARE flags. - - */ - gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; - hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); - if (!hData) - { - Con_SafePrintf ("Sound: Out of memory.\n"); - FreeSound (); - return false; - } - lpData = GlobalLock(hData); - if (!lpData) - { - Con_SafePrintf ("Sound: Failed to lock.\n"); - FreeSound (); - return false; - } - memset (lpData, 0, gSndBufSize); - - /* - * Allocate and lock memory for the header. This memory must - * also be globally allocated with GMEM_MOVEABLE and - * GMEM_SHARE flags. - */ - hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, - (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); - - if (hWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to Alloc header.\n"); - FreeSound (); - return false; - } - - lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); - - if (lpWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to lock header.\n"); - FreeSound (); - return false; - } - - memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); - - /* After allocation, set up and prepare headers. */ - for (i=0 ; isoundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) lpData; - sample16 = (shm->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; - - if (COM_CheckParm ("-wavonly")) - wavonly = true; - - dsound_init = wav_init = 0; - - stat = SIS_FAILURE; // assume DirectSound won't initialize - - /* Init DirectSound */ - if (!wavonly) - { - if (snd_firsttime || snd_isdirect) - { - stat = SNDDMA_InitDirect ();; - - if (stat == SIS_SUCCESS) - { - snd_isdirect = true; - - if (snd_firsttime) - Con_SafePrintf ("DirectSound initialized\n"); - } - else - { - snd_isdirect = false; - Con_SafePrintf ("DirectSound failed to init\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) - Con_SafePrintf ("Wave sound initialized\n"); - } - else - { - Con_SafePrintf ("Wave sound failed to init\n"); - } - } - } - - snd_firsttime = false; - - if (!dsound_init && !wav_init) - { - if (snd_firsttime) - Con_SafePrintf ("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 &= (shm->samples-1); - - return s; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -=============== -*/ -void SNDDMA_Submit(void) -{ - LPWAVEHDR h; - int wResult; - - if (!wav_init) - return; - - // - // find which sound blocks have completed - // - while (1) - { - if ( snd_completed == snd_sent ) - { - Con_DPrintf ("Sound overrun\n"); - break; - } - - if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) - { - break; - } - - snd_completed++; // this buffer has been played - } - - // - // submit two new sound blocks - // - while (((snd_sent - snd_completed) >> sample16) < 4) - { - h = lpWaveHdr + ( snd_sent&WAV_MASK ); - - 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) - { - Con_SafePrintf ("Failed to write block to device\n"); - FreeSound (); - return; - } - } -} - -/* -============== -SNDDMA_Shutdown - -Reset the sound device for exiting -=============== -*/ -void SNDDMA_Shutdown(void) -{ - FreeSound (); -} - +/* +Copyright (C) 1996-1997 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 "quakedef.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; + +static qboolean wavonly; +static qboolean dsound_init; +static qboolean wav_init; +static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; +static qboolean primary_format_set; + +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); + + +/* +================== +S_BlockSound +================== +*/ +void S_BlockSound (void) +{ + +// DirectSound takes care of blocking itself + if (snd_iswave) + { + snd_blocked++; + + if (snd_blocked == 1) + waveOutReset (hWaveOut); + } +} + + +/* +================== +S_UnblockSound +================== +*/ +void S_UnblockSound (void) +{ + +// DirectSound takes care of blocking itself + if (snd_iswave) + { + snd_blocked--; + } +} + + +/* +================== +FreeSound +================== +*/ +void FreeSound (void) +{ + int i; + + if (pDSBuf) + { + 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)) + { + pDSPBuf->lpVtbl->Release(pDSPBuf); + } + + if (pDS) + { + pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); + pDS->lpVtbl->Release(pDS); + } + + if (hWaveOut) + { + waveOutReset (hWaveOut); + + if (lpWaveHdr) + { + for (i=0 ; i< WAV_BUFFERS ; i++) + waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); + } + + waveOutClose (hWaveOut); + + if (hWaveHdr) + { + GlobalUnlock(hWaveHdr); + GlobalFree(hWaveHdr); + } + + if (hData) + { + GlobalUnlock(hData); + GlobalFree(hData); + } + + } + + 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) +{ + DSBUFFERDESC dsbuf; + DSBCAPS dsbcaps; + DWORD dwSize, dwWrite; + DSCAPS dscaps; + WAVEFORMATEX format, pformat; + HRESULT hresult; + int reps; + + memset ((void *)&sn, 0, sizeof (sn)); + + shm = &sn; + + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 11025; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = shm->channels; + format.wBitsPerSample = shm->samplebits; + format.nSamplesPerSec = shm->speed; + format.nBlockAlign = format.nChannels + *format.wBitsPerSample / 8; + format.cbSize = 0; + format.nAvgBytesPerSec = format.nSamplesPerSec + *format.nBlockAlign; + + if (!hInstDS) + { + hInstDS = LoadLibrary("dsound.dll"); + + if (hInstDS == NULL) + { + Con_SafePrintf ("Couldn't load dsound.dll\n"); + return SIS_FAILURE; + } + + pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); + + if (!pDirectSoundCreate) + { + Con_SafePrintf ("Couldn't get DS proc addr\n"); + return SIS_FAILURE; + } + } + + while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK) + { + if (hresult != DSERR_ALLOCATED) + { + Con_SafePrintf ("DirectSound create 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) + { + Con_SafePrintf ("DirectSoundCreate failure\n" + " hardware already in use\n"); + return SIS_NOTAVAIL; + } + } + + dscaps.dwSize = sizeof(dscaps); + + if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) + { + Con_SafePrintf ("Couldn't get DS caps\n"); + } + + if (dscaps.dwFlags & DSCAPS_EMULDRIVER) + { + Con_SafePrintf ("No DirectSound driver installed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) + { + Con_SafePrintf ("Set coop level failed\n"); + FreeSound (); + return SIS_FAILURE; + } + +// 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; + + if (!COM_CheckParm ("-snoforceformat")) + { + if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) + { + pformat = format; + + if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) + { +// if (snd_firsttime) +// Con_SafePrintf ("Set primary sound buffer format: no\n"); + } + else +// { +// if (snd_firsttime) +// Con_SafePrintf ("Set primary sound buffer format: yes\n"); + + primary_format_set = true; +// } + } + } + + if (!primary_format_set || !COM_CheckParm ("-primarysound")) + { + // 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); + + if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) + { + Con_SafePrintf ("DS:CreateSoundBuffer Failed"); + FreeSound (); + return SIS_FAILURE; + } + + shm->channels = format.nChannels; + shm->samplebits = format.wBitsPerSample; + shm->speed = format.nSamplesPerSec; + + if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) + { + Con_SafePrintf ("DS:GetCaps failed\n"); + FreeSound (); + return SIS_FAILURE; + } + +// if (snd_firsttime) +// Con_SafePrintf ("Using secondary sound buffer\n"); + } + else + { + if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) + { + Con_SafePrintf ("Set coop level failed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) + { + Con_Printf ("DS:GetCaps failed\n"); + return SIS_FAILURE; + } + + pDSBuf = pDSPBuf; +// Con_SafePrintf ("Using primary sound buffer\n"); + } + + // Make sure mixer is active + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + +/* if (snd_firsttime) + Con_SafePrintf(" %d channel(s)\n" + " %d bits/sample\n" + " %d bytes/sec\n", + shm->channels, shm->samplebits, shm->speed);*/ + + gSndBufSize = dsbcaps.dwBufferBytes; + +// initialize the buffer + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (++reps > 10000) + { + Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); + FreeSound (); + return SIS_FAILURE; + } + + } + + memset(lpData, 0, dwSize); +// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging + + pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); + + /* 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); + + shm->soundalive = true; + shm->splitbuffer = false; + shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) lpData; + sample16 = (shm->samplebits/8) - 1; + + dsound_init = true; + + return SIS_SUCCESS; +} + + +/* +================== +SNDDM_InitWav + +Crappy windows multimedia base +================== +*/ +qboolean SNDDMA_InitWav (void) +{ + WAVEFORMATEX format; + int i; + HRESULT hr; + + snd_sent = 0; + snd_completed = 0; + + shm = &sn; + + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 11025; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = shm->channels; + format.wBitsPerSample = shm->samplebits; + format.nSamplesPerSec = shm->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. */ + while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, + &format, + 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) + { + if (hr != MMSYSERR_ALLOCATED) + { + Con_SafePrintf ("waveOutOpen 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 with no sound.", + "Sound not available", + MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) + { + Con_SafePrintf ("waveOutOpen failure;\n" + " hardware already in use\n"); + return false; + } + } + + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + + */ + gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; + hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); + if (!hData) + { + Con_SafePrintf ("Sound: Out of memory.\n"); + FreeSound (); + return false; + } + lpData = GlobalLock(hData); + if (!lpData) + { + Con_SafePrintf ("Sound: Failed to lock.\n"); + FreeSound (); + return false; + } + memset (lpData, 0, gSndBufSize); + + /* + * Allocate and lock memory for the header. This memory must + * also be globally allocated with GMEM_MOVEABLE and + * GMEM_SHARE flags. + */ + hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); + + if (hWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to Alloc header.\n"); + FreeSound (); + return false; + } + + lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); + + if (lpWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to lock header.\n"); + FreeSound (); + return false; + } + + memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); + + /* After allocation, set up and prepare headers. */ + for (i=0 ; isoundalive = true; + shm->splitbuffer = false; + shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) lpData; + sample16 = (shm->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; + + if (COM_CheckParm ("-wavonly")) + wavonly = true; + + dsound_init = wav_init = 0; + + stat = SIS_FAILURE; // assume DirectSound won't initialize + + /* Init DirectSound */ + if (!wavonly) + { + if (snd_firsttime || snd_isdirect) + { + stat = SNDDMA_InitDirect ();; + + if (stat == SIS_SUCCESS) + { + snd_isdirect = true; + + if (snd_firsttime) + Con_SafePrintf ("DirectSound initialized\n"); + } + else + { + snd_isdirect = false; + Con_SafePrintf ("DirectSound failed to init\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) + Con_SafePrintf ("Wave sound initialized\n"); + } + else + { + Con_SafePrintf ("Wave sound failed to init\n"); + } + } + } + + snd_firsttime = false; + + if (!dsound_init && !wav_init) + { + if (snd_firsttime) + Con_SafePrintf ("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 &= (shm->samples-1); + + return s; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(void) +{ + LPWAVEHDR h; + int wResult; + + if (!wav_init) + return; + + // + // find which sound blocks have completed + // + while (1) + { + if ( snd_completed == snd_sent ) + { + Con_DPrintf ("Sound overrun\n"); + break; + } + + if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) + { + break; + } + + snd_completed++; // this buffer has been played + } + + // + // submit two new sound blocks + // + while (((snd_sent - snd_completed) >> sample16) < 4) + { + h = lpWaveHdr + ( snd_sent&WAV_MASK ); + + 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) + { + Con_SafePrintf ("Failed to write block to device\n"); + FreeSound (); + return; + } + } +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + FreeSound (); +} + diff --git a/source/sv_ccmds.c b/source/sv_ccmds.c index f8263fc..14cec5d 100644 --- a/source/sv_ccmds.c +++ b/source/sv_ccmds.c @@ -1,32 +1,32 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "qwsvdef.h" - + qboolean sv_allow_cheats; int fp_messages=4, fp_persecond=4, fp_secondsdead=10; char fp_msg[255] = { 0 }; -extern cvar_t cl_warncmd; - extern redirect_t sv_redirected; - +extern cvar_t cl_warncmd; + extern redirect_t sv_redirected; + /* =============================================================================== @@ -311,13 +311,13 @@ void SV_Map_f (void) return; } strcpy (level, Cmd_Argv(1)); - + #if 0 if (!strcmp (level, "e1m8")) { // QuakeWorld can't go to e1m8 SV_BroadcastPrintf (PRINT_HIGH, "can't go to low grav level in QuakeWorld...\n"); strcpy (level, "e1m5"); - } + } #endif // check to make sure the level exists @@ -383,7 +383,7 @@ void SV_Status_f (void) int i, j, l; client_t *cl; float cpu, avg, pak; - char *s; + char *s; cpu = (svs.stats.latched_active+svs.stats.latched_idle); @@ -397,44 +397,44 @@ void SV_Status_f (void) Con_Printf ("avg response time: %i ms\n",(int)avg); Con_Printf ("packets/frame : %5.2f (%d)\n", pak, num_prstr); -// min fps lat drp - if (sv_redirected != RD_NONE) { - // most remote clients are 40 columns - // 0123456789012345678901234567890123456789 - Con_Printf ("name userid frags\n"); - Con_Printf (" address rate ping drop\n"); - Con_Printf (" ---------------- ---- ---- -----\n"); - for (i=0,cl=svs.clients ; istate) - continue; - - Con_Printf ("%-16.16s ", cl->name); - - Con_Printf ("%6i %5i", cl->userid, (int)cl->edict->v.frags); - if (cl->spectator) - Con_Printf(" (s)\n"); - else - Con_Printf("\n"); - - s = NET_BaseAdrToString ( cl->netchan.remote_address); - Con_Printf (" %-16.16s", s); - if (cl->state == cs_connected) - { - Con_Printf ("CONNECTING\n"); - continue; - } - if (cl->state == cs_zombie) - { - Con_Printf ("ZOMBIE\n"); - continue; - } - Con_Printf ("%4i %4i %5.2f\n" - , (int)(1000*cl->netchan.frame_rate) - , (int)SV_CalcPing (cl) - , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence); - } - } else { +// min fps lat drp + if (sv_redirected != RD_NONE) { + // most remote clients are 40 columns + // 0123456789012345678901234567890123456789 + Con_Printf ("name userid frags\n"); + Con_Printf (" address rate ping drop\n"); + Con_Printf (" ---------------- ---- ---- -----\n"); + for (i=0,cl=svs.clients ; istate) + continue; + + Con_Printf ("%-16.16s ", cl->name); + + Con_Printf ("%6i %5i", cl->userid, (int)cl->edict->v.frags); + if (cl->spectator) + Con_Printf(" (s)\n"); + else + Con_Printf("\n"); + + s = NET_BaseAdrToString ( cl->netchan.remote_address); + Con_Printf (" %-16.16s", s); + if (cl->state == cs_connected) + { + Con_Printf ("CONNECTING\n"); + continue; + } + if (cl->state == cs_zombie) + { + Con_Printf ("ZOMBIE\n"); + continue; + } + Con_Printf ("%4i %4i %5.2f\n" + , (int)(1000*cl->netchan.frame_rate) + , (int)SV_CalcPing (cl) + , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence); + } + } else { Con_Printf ("frags userid address name rate ping drop qport\n"); Con_Printf ("----- ------ --------------- --------------- ---- ---- ----- -----\n"); for (i=0,cl=svs.clients ; inetchan.frame_rate) , (int)SV_CalcPing (cl) - , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence + , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence , cl->netchan.qport); - if (cl->spectator) - Con_Printf(" (s)\n"); - else - Con_Printf("\n"); - + if (cl->spectator) + Con_Printf(" (s)\n"); + else + Con_Printf("\n"); + - } + } } Con_Printf ("\n"); } @@ -523,15 +523,15 @@ void SV_Heartbeat_f (void) { svs.last_heartbeat = -9999; } - -void SV_SendServerInfoChange(char *key, char *value) -{ - if (!sv.state) - return; - - MSG_WriteByte (&sv.reliable_datagram, svc_serverinfo); - MSG_WriteString (&sv.reliable_datagram, key); - MSG_WriteString (&sv.reliable_datagram, value); + +void SV_SendServerInfoChange(char *key, char *value) +{ + if (!sv.state) + return; + + MSG_WriteByte (&sv.reliable_datagram, svc_serverinfo); + MSG_WriteString (&sv.reliable_datagram, key); + MSG_WriteString (&sv.reliable_datagram, value); } /* @@ -574,43 +574,43 @@ void SV_Serverinfo_f (void) var->string = CopyString (Cmd_Argv(2)); var->value = Q_atof (var->string); } - - SV_SendServerInfoChange(Cmd_Argv(1), Cmd_Argv(2)); + + SV_SendServerInfoChange(Cmd_Argv(1), Cmd_Argv(2)); +} + + +/* +=========== +SV_Serverinfo_f + + Examine or change the serverinfo string +=========== +*/ +char *CopyString(char *s); +void SV_Localinfo_f (void) +{ + if (Cmd_Argc() == 1) + { + Con_Printf ("Local info settings:\n"); + Info_Print (localinfo); + return; + } + + if (Cmd_Argc() != 3) + { + Con_Printf ("usage: localinfo [ ]\n"); + return; + } + + if (Cmd_Argv(1)[0] == '*') + { + Con_Printf ("Star variables cannot be changed.\n"); + return; + } + Info_SetValueForKey (localinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_LOCALINFO_STRING); } -/* -=========== -SV_Serverinfo_f - - Examine or change the serverinfo string -=========== -*/ -char *CopyString(char *s); -void SV_Localinfo_f (void) -{ - if (Cmd_Argc() == 1) - { - Con_Printf ("Local info settings:\n"); - Info_Print (localinfo); - return; - } - - if (Cmd_Argc() != 3) - { - Con_Printf ("usage: localinfo [ ]\n"); - return; - } - - if (Cmd_Argv(1)[0] == '*') - { - Con_Printf ("Star variables cannot be changed.\n"); - return; - } - Info_SetValueForKey (localinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_LOCALINFO_STRING); -} - - /* =========== SV_User_f @@ -763,100 +763,100 @@ void SV_Gamedir_f (void) COM_Gamedir (dir); Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING); } - -/* -================ -SV_Snap -================ -*/ -void SV_Snap (int uid) -{ - client_t *cl; - char pcxname[80]; - char checkname[MAX_OSPATH]; - int i; - - for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) - { - if (!cl->state) - continue; - if (cl->userid == uid) - break; - } - if (i >= MAX_CLIENTS) { - Con_Printf ("userid not found\n"); - return; - } - - sprintf(pcxname, "%d-00.pcx", uid); - - sprintf(checkname, "%s/snap", gamedirfile); - Sys_mkdir(gamedirfile); - Sys_mkdir(checkname); - - for (i=0 ; i<=99 ; i++) - { - pcxname[strlen(pcxname) - 6] = i/10 + '0'; - pcxname[strlen(pcxname) - 5] = i%10 + '0'; - sprintf (checkname, "%s/snap/%s", gamedirfile, pcxname); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==100) - { - Con_Printf ("Snap: Couldn't create a file, clean some out.\n"); - return; - } - strcpy(cl->uploadfn, checkname); - - memcpy(&cl->snap_from, &net_from, sizeof(net_from)); - if (sv_redirected != RD_NONE) - cl->remote_snap = true; - else - cl->remote_snap = false; - - ClientReliableWrite_Begin (cl, svc_stufftext, 24); - ClientReliableWrite_String (cl, "cmd snap"); - Con_Printf ("Requesting snap from user %d...\n", uid); -} - -/* -================ -SV_Snap_f -================ -*/ -void SV_Snap_f (void) -{ - int uid; - - if (Cmd_Argc() != 2) - { - Con_Printf ("Usage: snap \n"); - return; - } - - uid = atoi(Cmd_Argv(1)); - - SV_Snap(uid); -} - -/* -================ -SV_Snap -================ -*/ -void SV_SnapAll_f (void) -{ - client_t *cl; - int i; - - for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) - { - if (cl->state < cs_connected || cl->spectator) - continue; - SV_Snap(cl->userid); - } -} + +/* +================ +SV_Snap +================ +*/ +void SV_Snap (int uid) +{ + client_t *cl; + char pcxname[80]; + char checkname[MAX_OSPATH]; + int i; + + for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) + { + if (!cl->state) + continue; + if (cl->userid == uid) + break; + } + if (i >= MAX_CLIENTS) { + Con_Printf ("userid not found\n"); + return; + } + + sprintf(pcxname, "%d-00.pcx", uid); + + sprintf(checkname, "%s/snap", gamedirfile); + Sys_mkdir(gamedirfile); + Sys_mkdir(checkname); + + for (i=0 ; i<=99 ; i++) + { + pcxname[strlen(pcxname) - 6] = i/10 + '0'; + pcxname[strlen(pcxname) - 5] = i%10 + '0'; + sprintf (checkname, "%s/snap/%s", gamedirfile, pcxname); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==100) + { + Con_Printf ("Snap: Couldn't create a file, clean some out.\n"); + return; + } + strcpy(cl->uploadfn, checkname); + + memcpy(&cl->snap_from, &net_from, sizeof(net_from)); + if (sv_redirected != RD_NONE) + cl->remote_snap = true; + else + cl->remote_snap = false; + + ClientReliableWrite_Begin (cl, svc_stufftext, 24); + ClientReliableWrite_String (cl, "cmd snap"); + Con_Printf ("Requesting snap from user %d...\n", uid); +} + +/* +================ +SV_Snap_f +================ +*/ +void SV_Snap_f (void) +{ + int uid; + + if (Cmd_Argc() != 2) + { + Con_Printf ("Usage: snap \n"); + return; + } + + uid = atoi(Cmd_Argv(1)); + + SV_Snap(uid); +} + +/* +================ +SV_Snap +================ +*/ +void SV_SnapAll_f (void) +{ + client_t *cl; + int i; + + for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) + { + if (cl->state < cs_connected || cl->spectator) + continue; + SV_Snap(cl->userid); + } +} /* ================== @@ -874,8 +874,8 @@ void SV_InitOperatorCommands (void) Cmd_AddCommand ("logfile", SV_Logfile_f); Cmd_AddCommand ("fraglogfile", SV_Fraglogfile_f); - Cmd_AddCommand ("snap", SV_Snap_f); - Cmd_AddCommand ("snapall", SV_SnapAll_f); + Cmd_AddCommand ("snap", SV_Snap_f); + Cmd_AddCommand ("snapall", SV_SnapAll_f); Cmd_AddCommand ("kick", SV_Kick_f); Cmd_AddCommand ("status", SV_Status_f); @@ -888,13 +888,13 @@ void SV_InitOperatorCommands (void) Cmd_AddCommand ("god", SV_God_f); Cmd_AddCommand ("give", SV_Give_f); Cmd_AddCommand ("noclip", SV_Noclip_f); - Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); + Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); Cmd_AddCommand ("localinfo", SV_Localinfo_f); Cmd_AddCommand ("user", SV_User_f); Cmd_AddCommand ("gamedir", SV_Gamedir_f); Cmd_AddCommand ("sv_gamedir", SV_Gamedir); Cmd_AddCommand ("floodprot", SV_Floodprot_f); - Cmd_AddCommand ("floodprotmsg", SV_Floodprotmsg_f); - + Cmd_AddCommand ("floodprotmsg", SV_Floodprotmsg_f); + cl_warncmd.value = 1; } diff --git a/source/sv_ents.c b/source/sv_ents.c index 69dc0fc..055a9a9 100644 --- a/source/sv_ents.c +++ b/source/sv_ents.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "qwsvdef.h" @@ -375,11 +375,11 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, byte *pvs, sizeb pflags &= ~(PF_MSEC|PF_COMMAND); if (ent->v.weaponframe) pflags |= PF_WEAPONFRAME; - } - - if (client->spec_track && client->spec_track - 1 == j && - ent->v.weaponframe) - pflags |= PF_WEAPONFRAME; + } + + if (client->spec_track && client->spec_track - 1 == j && + ent->v.weaponframe) + pflags |= PF_WEAPONFRAME; MSG_WriteByte (msg, svc_playerinfo); MSG_WriteByte (msg, j); diff --git a/source/sv_init.c b/source/sv_init.c index 8a6289f..cd58d23 100644 --- a/source/sv_init.c +++ b/source/sv_init.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "qwsvdef.h" @@ -260,8 +260,8 @@ unsigned SV_CheckModel(char *mdl) unsigned short crc; // int len; - buf = (byte *)COM_LoadStackFile (mdl, stackbuf, sizeof(stackbuf)); - crc = CRC_Block(buf, com_filesize); + buf = (byte *)COM_LoadStackFile (mdl, stackbuf, sizeof(stackbuf)); + crc = CRC_Block(buf, com_filesize); // for (len = com_filesize; len; len--, buf++) // CRC_ProcessByte(&crc, *buf); diff --git a/source/sv_main.c b/source/sv_main.c index 8a953b1..946afc3 100644 --- a/source/sv_main.c +++ b/source/sv_main.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "qwsvdef.h" @@ -186,6 +186,7 @@ void SV_DropClient (client_t *drop) MSG_WriteByte (&drop->netchan.message, svc_disconnect); if (drop->state == cs_spawned) + { if (!drop->spectator) { // call the prog function for removing a client @@ -200,7 +201,7 @@ void SV_DropClient (client_t *drop) pr_global_struct->self = EDICT_TO_PROG(drop->edict); PR_ExecuteProgram (SpectatorDisconnect); } - + } if (drop->spectator) Con_Printf ("Spectator %s removed\n",drop->name); else @@ -1515,10 +1516,12 @@ void SV_ExtractFromUserinfo (client_t *cl) p = val; if (val[0] == '(') + { if (val[2] == ')') p = val + 3; else if (val[3] == ')') p = val + 4; + } sprintf(newname, "(%d)%-.40s", dupc++, p); Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING); diff --git a/source/sv_move.c b/source/sv_move.c index 8359a4a..e9324bb 100644 --- a/source/sv_move.c +++ b/source/sv_move.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_move.c -- monster movement -#include "qwsvdef.h" +#include "qwsvdef.h" #define STEPSIZE 18 diff --git a/source/sv_nchan.c b/source/sv_nchan.c index 4b0609a..e201e93 100644 --- a/source/sv_nchan.c +++ b/source/sv_nchan.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_nchan.c, user reliable data stream writes #include "qwsvdef.h" diff --git a/source/sv_phys.c b/source/sv_phys.c index bccfdeb..70db5af 100644 --- a/source/sv_phys.c +++ b/source/sv_phys.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_phys.c -#include "qwsvdef.h" +#include "qwsvdef.h" /* @@ -40,17 +40,17 @@ solid_edge items only clip against bsp models. */ cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"}; - -cvar_t sv_gravity = { "sv_gravity", "800"}; -cvar_t sv_stopspeed = { "sv_stopspeed", "100"}; -cvar_t sv_maxspeed = { "sv_maxspeed", "320"}; -cvar_t sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"}; -cvar_t sv_accelerate = { "sv_accelerate", "10"}; -cvar_t sv_airaccelerate = { "sv_airaccelerate", "0.7"}; -cvar_t sv_wateraccelerate = { "sv_wateraccelerate", "10"}; -cvar_t sv_friction = { "sv_friction", "4"}; -cvar_t sv_waterfriction = { "sv_waterfriction", "4"}; - + +cvar_t sv_gravity = { "sv_gravity", "800"}; +cvar_t sv_stopspeed = { "sv_stopspeed", "100"}; +cvar_t sv_maxspeed = { "sv_maxspeed", "320"}; +cvar_t sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"}; +cvar_t sv_accelerate = { "sv_accelerate", "10"}; +cvar_t sv_airaccelerate = { "sv_airaccelerate", "0.7"}; +cvar_t sv_wateraccelerate = { "sv_wateraccelerate", "10"}; +cvar_t sv_friction = { "sv_friction", "4"}; +cvar_t sv_waterfriction = { "sv_waterfriction", "4"}; + #define MOVE_EPSILON 0.01 @@ -126,14 +126,14 @@ Returns false if the entity removed itself. qboolean SV_RunThink (edict_t *ent) { float thinktime; - - do + + do { thinktime = ent->v.nextthink; - if (thinktime <= 0) + if (thinktime <= 0) + return true; + if (thinktime > sv.time + host_frametime) return true; - if (thinktime > sv.time + host_frametime) - return true; if (thinktime < sv.time) thinktime = sv.time; // don't let things stay in the past. @@ -143,11 +143,11 @@ qboolean SV_RunThink (edict_t *ent) pr_global_struct->time = thinktime; pr_global_struct->self = EDICT_TO_PROG(ent); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - PR_ExecuteProgram (ent->v.think); - - if (ent->free) - return false; - } while (1); + PR_ExecuteProgram (ent->v.think); + + if (ent->free) + return false; + } while (1); return true; } @@ -419,154 +419,154 @@ trace_t SV_PushEntity (edict_t *ent, vec3_t push) } -/* -============ -SV_Push - -============ -*/ -qboolean SV_Push (edict_t *pusher, vec3_t move) -{ - int i, e; - edict_t *check, *block; - vec3_t mins, maxs; - vec3_t pushorig; - int num_moved; - edict_t *moved_edict[MAX_EDICTS]; - vec3_t moved_from[MAX_EDICTS]; - - for (i=0 ; i<3 ; i++) - { - mins[i] = pusher->v.absmin[i] + move[i]; - maxs[i] = pusher->v.absmax[i] + move[i]; - } - - VectorCopy (pusher->v.origin, pushorig); - -// move the pusher to it's final position - - VectorAdd (pusher->v.origin, move, pusher->v.origin); - SV_LinkEdict (pusher, false); - -// see if any solid entities are inside the final position - num_moved = 0; - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - pusher->v.solid = SOLID_NOT; - block = SV_TestEntityPosition (check); - pusher->v.solid = SOLID_BSP; - if (block) - continue; - - // if the entity is standing on the pusher, it will definately be moved - if ( ! ( ((int)check->v.flags & FL_ONGROUND) - && PROG_TO_EDICT(check->v.groundentity) == pusher) ) - { - if ( check->v.absmin[0] >= maxs[0] - || check->v.absmin[1] >= maxs[1] - || check->v.absmin[2] >= maxs[2] - || check->v.absmax[0] <= mins[0] - || check->v.absmax[1] <= mins[1] - || check->v.absmax[2] <= mins[2] ) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - VectorCopy (check->v.origin, moved_from[num_moved]); - moved_edict[num_moved] = check; - num_moved++; - - // try moving the contacted entity - VectorAdd (check->v.origin, move, check->v.origin); - block = SV_TestEntityPosition (check); - if (!block) - { // pushed ok - SV_LinkEdict (check, false); - continue; - } - - // if it is ok to leave in the old position, do it - VectorSubtract (check->v.origin, move, check->v.origin); - block = SV_TestEntityPosition (check); - if (!block) - { - num_moved--; - continue; - } - - // if it is still inside the pusher, block - if (check->v.mins[0] == check->v.maxs[0]) - { - SV_LinkEdict (check, false); - continue; - } - if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) - { // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy (check->v.mins, check->v.maxs); - SV_LinkEdict (check, false); - continue; - } - - VectorCopy (pushorig, pusher->v.origin); - SV_LinkEdict (pusher, false); - - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - if (pusher->v.blocked) - { - pr_global_struct->self = EDICT_TO_PROG(pusher); - pr_global_struct->other = EDICT_TO_PROG(check); - PR_ExecuteProgram (pusher->v.blocked); - } - - // move back any entities we already moved - for (i=0 ; iv.origin); - SV_LinkEdict (moved_edict[i], false); - } - return false; - } - - return true; -} - -/* -============ -SV_PushMove - -============ -*/ -void SV_PushMove (edict_t *pusher, float movetime) -{ - int i; - vec3_t move; - - if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) - { - pusher->v.ltime += movetime; - return; - } - - for (i=0 ; i<3 ; i++) - move[i] = pusher->v.velocity[i] * movetime; - - if (SV_Push (pusher, move)) - pusher->v.ltime += movetime; -} - +/* +============ +SV_Push + +============ +*/ +qboolean SV_Push (edict_t *pusher, vec3_t move) +{ + int i, e; + edict_t *check, *block; + vec3_t mins, maxs; + vec3_t pushorig; + int num_moved; + edict_t *moved_edict[MAX_EDICTS]; + vec3_t moved_from[MAX_EDICTS]; + + for (i=0 ; i<3 ; i++) + { + mins[i] = pusher->v.absmin[i] + move[i]; + maxs[i] = pusher->v.absmax[i] + move[i]; + } + + VectorCopy (pusher->v.origin, pushorig); + +// move the pusher to it's final position + + VectorAdd (pusher->v.origin, move, pusher->v.origin); + SV_LinkEdict (pusher, false); + +// see if any solid entities are inside the final position + num_moved = 0; + check = NEXT_EDICT(sv.edicts); + for (e=1 ; efree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + pusher->v.solid = SOLID_NOT; + block = SV_TestEntityPosition (check); + pusher->v.solid = SOLID_BSP; + if (block) + continue; + + // if the entity is standing on the pusher, it will definately be moved + if ( ! ( ((int)check->v.flags & FL_ONGROUND) + && PROG_TO_EDICT(check->v.groundentity) == pusher) ) + { + if ( check->v.absmin[0] >= maxs[0] + || check->v.absmin[1] >= maxs[1] + || check->v.absmin[2] >= maxs[2] + || check->v.absmax[0] <= mins[0] + || check->v.absmax[1] <= mins[1] + || check->v.absmax[2] <= mins[2] ) + continue; + + // see if the ent's bbox is inside the pusher's final position + if (!SV_TestEntityPosition (check)) + continue; + } + + VectorCopy (check->v.origin, moved_from[num_moved]); + moved_edict[num_moved] = check; + num_moved++; + + // try moving the contacted entity + VectorAdd (check->v.origin, move, check->v.origin); + block = SV_TestEntityPosition (check); + if (!block) + { // pushed ok + SV_LinkEdict (check, false); + continue; + } + + // if it is ok to leave in the old position, do it + VectorSubtract (check->v.origin, move, check->v.origin); + block = SV_TestEntityPosition (check); + if (!block) + { + num_moved--; + continue; + } + + // if it is still inside the pusher, block + if (check->v.mins[0] == check->v.maxs[0]) + { + SV_LinkEdict (check, false); + continue; + } + if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) + { // corpse + check->v.mins[0] = check->v.mins[1] = 0; + VectorCopy (check->v.mins, check->v.maxs); + SV_LinkEdict (check, false); + continue; + } + + VectorCopy (pushorig, pusher->v.origin); + SV_LinkEdict (pusher, false); + + // if the pusher has a "blocked" function, call it + // otherwise, just stay in place until the obstacle is gone + if (pusher->v.blocked) + { + pr_global_struct->self = EDICT_TO_PROG(pusher); + pr_global_struct->other = EDICT_TO_PROG(check); + PR_ExecuteProgram (pusher->v.blocked); + } + + // move back any entities we already moved + for (i=0 ; iv.origin); + SV_LinkEdict (moved_edict[i], false); + } + return false; + } + + return true; +} + +/* +============ +SV_PushMove + +============ +*/ +void SV_PushMove (edict_t *pusher, float movetime) +{ + int i; + vec3_t move; + + if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) + { + pusher->v.ltime += movetime; + return; + } + + for (i=0 ; i<3 ; i++) + move[i] = pusher->v.velocity[i] * movetime; + + if (SV_Push (pusher, move)) + pusher->v.ltime += movetime; +} + /* ================ @@ -579,8 +579,8 @@ void SV_Physics_Pusher (edict_t *ent) float thinktime; float oldltime; float movetime; -vec3_t oldorg, move; -float l; +vec3_t oldorg, move; +float l; oldltime = ent->v.ltime; @@ -601,23 +601,23 @@ float l; if (thinktime > oldltime && thinktime <= ent->v.ltime) { -VectorCopy (ent->v.origin, oldorg); +VectorCopy (ent->v.origin, oldorg); ent->v.nextthink = 0; pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(ent); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); PR_ExecuteProgram (ent->v.think); if (ent->free) - return; -VectorSubtract (ent->v.origin, oldorg, move); - -l = Length(move); -if (l > 1.0/64) -{ -// Con_Printf ("**** snap: %f\n", Length (l)); - VectorCopy (oldorg, ent->v.origin); - SV_Push (ent, move); -} + return; +VectorSubtract (ent->v.origin, oldorg, move); + +l = Length(move); +if (l > 1.0/64) +{ +// Con_Printf ("**** snap: %f\n", Length (l)); + VectorCopy (oldorg, ent->v.origin); + SV_Push (ent, move); +} } @@ -718,10 +718,10 @@ void SV_Physics_Toss (edict_t *ent) // regular thinking if (!SV_RunThink (ent)) return; - + if (ent->v.velocity[2] > 0) - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + // if onground, return without moving if ( ((int)ent->v.flags & FL_ONGROUND) ) return; @@ -739,8 +739,8 @@ void SV_Physics_Toss (edict_t *ent) // move origin VectorScale (ent->v.velocity, host_frametime, move); trace = SV_PushEntity (ent, move); - if (trace.fraction == 1) - return; + if (trace.fraction == 1) + return; if (ent->free) return; @@ -877,7 +877,7 @@ void SV_RunNewmis (void) if (!pr_global_struct->newmis) return; - ent = PROG_TO_EDICT(pr_global_struct->newmis); + ent = PROG_TO_EDICT(pr_global_struct->newmis); host_frametime = 0.05; pr_global_struct->newmis = 0; @@ -931,17 +931,17 @@ void SV_Physics (void) if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; } - -void SV_SetMoveVars(void) -{ - movevars.gravity = sv_gravity.value; - movevars.stopspeed = sv_stopspeed.value; - movevars.maxspeed = sv_maxspeed.value; - movevars.spectatormaxspeed = sv_spectatormaxspeed.value; - movevars.accelerate = sv_accelerate.value; - movevars.airaccelerate = sv_airaccelerate.value; - movevars.wateraccelerate = sv_wateraccelerate.value; - movevars.friction = sv_friction.value; - movevars.waterfriction = sv_waterfriction.value; - movevars.entgravity = 1.0; -} + +void SV_SetMoveVars(void) +{ + movevars.gravity = sv_gravity.value; + movevars.stopspeed = sv_stopspeed.value; + movevars.maxspeed = sv_maxspeed.value; + movevars.spectatormaxspeed = sv_spectatormaxspeed.value; + movevars.accelerate = sv_accelerate.value; + movevars.airaccelerate = sv_airaccelerate.value; + movevars.wateraccelerate = sv_wateraccelerate.value; + movevars.friction = sv_friction.value; + movevars.waterfriction = sv_waterfriction.value; + movevars.entgravity = 1.0; +} diff --git a/source/sv_send.c b/source/sv_send.c index 13afaac..6d0172b 100644 --- a/source/sv_send.c +++ b/source/sv_send.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_main.c -- server main program #include "qwsvdef.h" diff --git a/source/sv_user.c b/source/sv_user.c index 2b4a77c..6d04cce 100644 --- a/source/sv_user.c +++ b/source/sv_user.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // sv_user.c -- server code for moving users #include "qwsvdef.h" @@ -37,6 +37,8 @@ extern int fp_messages, fp_persecond, fp_secondsdead; extern char fp_msg[]; extern cvar_t pausable; +void SV_FullClientUpdateToClient (client_t *client, client_t *cl); + /* ============================================================ @@ -314,16 +316,16 @@ void SV_Spawn_f (void) return; } - n = atoi(Cmd_Argv(2)); - - // make sure n is valid - if ( n < 0 || n > MAX_CLIENTS ) - { - Con_Printf ("SV_Spawn_f invalid client start\n"); - SV_New_f (); - return; - } - + n = atoi(Cmd_Argv(2)); + + // make sure n is valid + if ( n < 0 || n > MAX_CLIENTS ) + { + Con_Printf ("SV_Spawn_f invalid client start\n"); + SV_New_f (); + return; + } + // send all current names, colors, and frag counts @@ -548,94 +550,91 @@ void SV_NextDownload_f (void) host_client->download = NULL; } - -void OutofBandPrintf(netadr_t where, char *fmt, ...) -{ - va_list argptr; - char send[1024]; - - send[0] = 0xff; - send[1] = 0xff; - send[2] = 0xff; - send[3] = 0xff; - send[4] = A2C_PRINT; - va_start (argptr, fmt); - vsprintf (send+5, fmt, argptr); - va_end (argptr); - - NET_SendPacket (strlen(send)+1, send, where); -} -/* -================== -SV_NextUpload -================== -*/ -void SV_NextUpload (void) -{ - byte buffer[1024]; - int r; - int percent; - int size; - client_t *client; - - if (!*host_client->uploadfn) { - SV_ClientPrintf(host_client, PRINT_HIGH, "Upload denied\n"); - ClientReliableWrite_Begin (host_client, svc_stufftext, 8); - ClientReliableWrite_String (host_client, "stopul"); - - // suck out rest of packet - size = MSG_ReadShort (); MSG_ReadByte (); - msg_readcount += size; - return; - } - - size = MSG_ReadShort (); - percent = MSG_ReadByte (); - - if (!host_client->upload) - { - host_client->upload = fopen(host_client->uploadfn, "wb"); - if (!host_client->upload) { - Sys_Printf("Can't create %s\n", host_client->uploadfn); - ClientReliableWrite_Begin (host_client, svc_stufftext, 8); - ClientReliableWrite_String (host_client, "stopul"); - *host_client->uploadfn = 0; - return; - } - Sys_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid); - if (host_client->remote_snap) - OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid); - } - - fwrite (net_message.data + msg_readcount, 1, size, host_client->upload); - msg_readcount += size; - -Con_DPrintf ("UPLOAD: %d received\n", size); - - if (percent != 100) { - ClientReliableWrite_Begin (host_client, svc_stufftext, 8); - ClientReliableWrite_String (host_client, "nextul\n"); - } else { - fclose (host_client->upload); - host_client->upload = NULL; - - Sys_Printf("%s upload completed.\n", host_client->uploadfn); - - if (host_client->remote_snap) { - char *p; - - if ((p = strchr(host_client->uploadfn, '/')) != NULL) - p++; - else - p = host_client->uploadfn; - OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", - host_client->uploadfn, p); - } - } - -} - +void OutofBandPrintf(netadr_t where, char *fmt, ...) +{ + va_list argptr; + char send[1024]; + + send[0] = 0xff; + send[1] = 0xff; + send[2] = 0xff; + send[3] = 0xff; + send[4] = A2C_PRINT; + va_start (argptr, fmt); + vsprintf (send+5, fmt, argptr); + va_end (argptr); + + NET_SendPacket (strlen(send)+1, send, where); +} + +/* +================== +SV_NextUpload +================== +*/ +void SV_NextUpload (void) +{ + int percent; + int size; + + if (!*host_client->uploadfn) { + SV_ClientPrintf(host_client, PRINT_HIGH, "Upload denied\n"); + ClientReliableWrite_Begin (host_client, svc_stufftext, 8); + ClientReliableWrite_String (host_client, "stopul"); + + // suck out rest of packet + size = MSG_ReadShort (); MSG_ReadByte (); + msg_readcount += size; + return; + } + + size = MSG_ReadShort (); + percent = MSG_ReadByte (); + + if (!host_client->upload) + { + host_client->upload = fopen(host_client->uploadfn, "wb"); + if (!host_client->upload) { + Sys_Printf("Can't create %s\n", host_client->uploadfn); + ClientReliableWrite_Begin (host_client, svc_stufftext, 8); + ClientReliableWrite_String (host_client, "stopul"); + *host_client->uploadfn = 0; + return; + } + Sys_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid); + if (host_client->remote_snap) + OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid); + } + + fwrite (net_message.data + msg_readcount, 1, size, host_client->upload); + msg_readcount += size; + +Con_DPrintf ("UPLOAD: %d received\n", size); + + if (percent != 100) { + ClientReliableWrite_Begin (host_client, svc_stufftext, 8); + ClientReliableWrite_String (host_client, "nextul\n"); + } else { + fclose (host_client->upload); + host_client->upload = NULL; + + Sys_Printf("%s upload completed.\n", host_client->uploadfn); + + if (host_client->remote_snap) { + char *p; + + if ((p = strchr(host_client->uploadfn, '/')) != NULL) + p++; + else + p = host_client->uploadfn; + OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", + host_client->uploadfn, p); + } + } + +} + /* ================== SV_BeginDownload_f @@ -881,32 +880,32 @@ void SV_Kill_f (void) PR_ExecuteProgram (pr_global_struct->ClientKill); } -/* -================== -SV_TogglePause -================== -*/ -void SV_TogglePause (const char *msg) -{ - int i; - client_t *cl; - - sv.paused ^= 1; - - if (msg) - SV_BroadcastPrintf (PRINT_HIGH, "%s", msg); - - // send notification to all clients - for (i=0, cl = svs.clients ; istate) - continue; - ClientReliableWrite_Begin (cl, svc_setpause, 2); - ClientReliableWrite_Byte (cl, sv.paused); - } -} - - +/* +================== +SV_TogglePause +================== +*/ +void SV_TogglePause (const char *msg) +{ + int i; + client_t *cl; + + sv.paused ^= 1; + + if (msg) + SV_BroadcastPrintf (PRINT_HIGH, "%s", msg); + + // send notification to all clients + for (i=0, cl = svs.clients ; istate) + continue; + ClientReliableWrite_Begin (cl, svc_setpause, 2); + ClientReliableWrite_Byte (cl, sv.paused); + } +} + + /* ================== SV_Pause_f @@ -914,8 +913,6 @@ SV_Pause_f */ void SV_Pause_f (void) { - int i; - client_t *cl; char st[sizeof(host_client->name) + 32]; if (!pausable.value) { @@ -926,13 +923,13 @@ void SV_Pause_f (void) if (host_client->spectator) { SV_ClientPrintf (host_client, PRINT_HIGH, "Spectators can not pause.\n"); return; - } - - if (sv.paused) - sprintf (st, "%s paused the game\n", host_client->name); - else - sprintf (st, "%s unpaused the game\n", host_client->name); - + } + + if (sv.paused) + sprintf (st, "%s paused the game\n", host_client->name); + else + sprintf (st, "%s unpaused the game\n", host_client->name); + SV_TogglePause(st); } @@ -1106,15 +1103,15 @@ Dumps the serverinfo info string void SV_ShowServerinfo_f (void) { Info_Print (svs.info); -} - -void SV_NoSnap_f(void) -{ - if (*host_client->uploadfn) { - *host_client->uploadfn = 0; - SV_BroadcastPrintf (PRINT_HIGH, "%s refused remote screenshot\n", host_client->name); - } -} +} + +void SV_NoSnap_f(void) +{ + if (*host_client->uploadfn) { + *host_client->uploadfn = 0; + SV_BroadcastPrintf (PRINT_HIGH, "%s refused remote screenshot\n", host_client->name); + } +} typedef struct { @@ -1148,10 +1145,10 @@ ucmd_t ucmds[] = {"serverinfo", SV_ShowServerinfo_f}, {"download", SV_BeginDownload_f}, - {"nextdl", SV_NextDownload_f}, - - {"ptrack", SV_PTrack_f}, //ZOID - used with autocam - + {"nextdl", SV_NextDownload_f}, + + {"ptrack", SV_PTrack_f}, //ZOID - used with autocam + {"snap", SV_NoSnap_f}, {NULL, NULL} @@ -1550,7 +1547,7 @@ void SV_ExecuteClientMessage (client_t *cl) vec3_t o; qboolean move_issued = false; //only allow one move command int checksumIndex; - byte checksum, calculatedChecksum; + byte checksum, calculatedChecksum; int seq_hash; // calc ping time @@ -1570,9 +1567,9 @@ void SV_ExecuteClientMessage (client_t *cl) host_client = cl; sv_player = host_client->edict; - -// seq_hash = (cl->netchan.incoming_sequence & 0xffff) ; // ^ QW_CHECK_HASH; - seq_hash = cl->netchan.incoming_sequence; + +// seq_hash = (cl->netchan.incoming_sequence & 0xffff) ; // ^ QW_CHECK_HASH; + seq_hash = cl->netchan.incoming_sequence; // mark time so clients will know how much to predict // other players @@ -1676,10 +1673,10 @@ void SV_ExecuteClientMessage (client_t *cl) VectorCopy(o, sv_player->v.origin); SV_LinkEdict(sv_player, false); } - break; - - case clc_upload: - SV_NextUpload(); + break; + + case clc_upload: + SV_NextUpload(); break; } diff --git a/source/sys_linux.c b/source/sys_linux.c index 9ff8a8b..e54b11c 100644 --- a/source/sys_linux.c +++ b/source/sys_linux.c @@ -1,428 +1,428 @@ -/* -Copyright (C) 1996-1997 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "quakedef.h" - -int noconinput = 0; -int nostdout = 0; - -char *basedir = "."; -char *cachedir = "/tmp"; - -cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display - -// ======================================================================= -// General routines -// ======================================================================= - -void Sys_DebugNumber(int y, int val) -{ -} - -/* -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - char text[1024]; - - va_start (argptr,fmt); - vsprintf (text,fmt,argptr); - va_end (argptr); - fprintf(stderr, "%s", text); - - Con_Print (text); -} - -void Sys_Printf (char *fmt, ...) -{ - - va_list argptr; - char text[1024], *t_p; - int l, r; - - if (nostdout) - return; - - va_start (argptr,fmt); - vsprintf (text,fmt,argptr); - va_end (argptr); - - l = strlen(text); - t_p = text; - -// make sure everything goes through, even though we are non-blocking - while (l) - { - r = write (1, text, l); - if (r != l) - sleep (0); - if (r > 0) - { - t_p += r; - l -= r; - } - } - -} -*/ - -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - char text[2048]; - unsigned char *p; - - va_start (argptr,fmt); - vsprintf (text,fmt,argptr); - va_end (argptr); - - if (strlen(text) > sizeof(text)) - Sys_Error("memory overwrite in Sys_Printf"); - - if (nostdout) - return; - - for (p = (unsigned char *)text; *p; p++) - if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) - printf("[%02x]", *p); - else - putc(*p, stdout); -} - -void Sys_Quit (void) -{ - Host_Shutdown(); - fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); - exit(0); -} - -void Sys_Init(void) -{ -#if id386 - Sys_SetFPCW(); -#endif -} - -void Sys_Error (char *error, ...) -{ - va_list argptr; - char string[1024]; - -// change stdin to non blocking - fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); - - va_start (argptr,error); - vsprintf (string,error,argptr); - va_end (argptr); - fprintf(stderr, "Error: %s\n", string); - - Host_Shutdown (); - exit (1); - -} - -void Sys_Warn (char *warning, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr,warning); - vsprintf (string,warning,argptr); - va_end (argptr); - fprintf(stderr, "Warning: %s", string); -} - -/* -============ -Sys_FileTime - -returns -1 if not present -============ -*/ -int Sys_FileTime (char *path) -{ - struct stat buf; - - if (stat (path,&buf) == -1) - return -1; - - return buf.st_mtime; -} - - -void Sys_mkdir (char *path) -{ - mkdir (path, 0777); -} - -int Sys_FileOpenRead (char *path, int *handle) -{ - int h; - struct stat fileinfo; - - - h = open (path, O_RDONLY, 0666); - *handle = h; - if (h == -1) - return -1; - - if (fstat (h,&fileinfo) == -1) - Sys_Error ("Error fstating %s", path); - - return fileinfo.st_size; -} - -int Sys_FileOpenWrite (char *path) -{ - int handle; - - umask (0); - - handle = open(path,O_RDWR | O_CREAT | O_TRUNC - , 0666); - - if (handle == -1) - Sys_Error ("Error opening %s: %s", path,strerror(errno)); - - return handle; -} - -int Sys_FileWrite (int handle, void *src, int count) -{ - return write (handle, src, count); -} - -void Sys_FileClose (int handle) -{ - close (handle); -} - -void Sys_FileSeek (int handle, int position) -{ - lseek (handle, position, SEEK_SET); -} - -int Sys_FileRead (int handle, void *dest, int count) -{ - return read (handle, dest, count); -} - -void Sys_DebugLog(char *file, char *fmt, ...) -{ - va_list argptr; - static char data[1024]; - int fd; - - va_start(argptr, fmt); - vsprintf(data, fmt, argptr); - va_end(argptr); -// fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666); - fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); - write(fd, data, strlen(data)); - close(fd); -} - -void Sys_EditFile(char *filename) -{ - - char cmd[256]; - char *term; - char *editor; - - term = getenv("TERM"); - if (term && !strcmp(term, "xterm")) - { - editor = getenv("VISUAL"); - if (!editor) - editor = getenv("EDITOR"); - if (!editor) - editor = getenv("EDIT"); - if (!editor) - editor = "vi"; - sprintf(cmd, "xterm -e %s %s", editor, filename); - system(cmd); - } - -} - -double Sys_DoubleTime (void) -{ - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday(&tp, &tzp); - - if (!secbase) - { - secbase = tp.tv_sec; - return tp.tv_usec/1000000.0; - } - - return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; -} - -// ======================================================================= -// Sleeps for microseconds -// ======================================================================= - -static volatile int oktogo; - -void alarm_handler(int x) -{ - oktogo=1; -} - -void Sys_LineRefresh(void) -{ -} - -void floating_point_exception_handler(int whatever) -{ -// Sys_Warn("floating point exception\n"); - signal(SIGFPE, floating_point_exception_handler); -} - -char *Sys_ConsoleInput(void) -{ -#if 0 - static char text[256]; - int len; - - if (cls.state == ca_dedicated) { - len = read (0, text, sizeof(text)); - if (len < 1) - return NULL; - text[len-1] = 0; // rip off the /n and terminate - - return text; - } -#endif - return NULL; -} - -#if !id386 -void Sys_HighFPPrecision (void) -{ -} - -void Sys_LowFPPrecision (void) -{ -} -#endif - -int skipframes; - -int main (int c, char **v) -{ - - double time, oldtime, newtime; - quakeparms_t parms; - int j; - -// static char cwd[1024]; - -// signal(SIGFPE, floating_point_exception_handler); - signal(SIGFPE, SIG_IGN); - - memset(&parms, 0, sizeof(parms)); - - COM_InitArgv(c, v); - parms.argc = com_argc; - parms.argv = com_argv; - - parms.memsize = 16*1024*1024; - - j = COM_CheckParm("-mem"); - if (j) - parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024); - parms.membase = malloc (parms.memsize); - - parms.basedir = basedir; -// caching is disabled by default, use -cachedir to enable -// parms.cachedir = cachedir; - - noconinput = COM_CheckParm("-noconinput"); - if (!noconinput) - fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); - - if (COM_CheckParm("-nostdout")) - nostdout = 1; - - Sys_Init(); - - Host_Init(&parms); - - oldtime = Sys_DoubleTime (); - while (1) - { -// find time spent rendering last frame - newtime = Sys_DoubleTime (); - time = newtime - oldtime; - - Host_Frame(time); - oldtime = newtime; - } - -} - - -/* -================ -Sys_MakeCodeWriteable -================ -*/ -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) -{ - - int r; - unsigned long addr; - int psize = getpagesize(); - - addr = (startaddr & ~(psize-1)) - psize; - -// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, -// addr, startaddr+length, length); - - r = mprotect((char*)addr, length + startaddr - addr + psize, 7); - - if (r < 0) - Sys_Error("Protection change failed\n"); - -} - +/* +Copyright (C) 1996-1997 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "quakedef.h" + +int noconinput = 0; +int nostdout = 0; + +char *basedir = "."; +char *cachedir = "/tmp"; + +cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display + +// ======================================================================= +// General routines +// ======================================================================= + +void Sys_DebugNumber(int y, int val) +{ +} + +/* +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[1024]; + + va_start (argptr,fmt); + vsprintf (text,fmt,argptr); + va_end (argptr); + fprintf(stderr, "%s", text); + + Con_Print (text); +} + +void Sys_Printf (char *fmt, ...) +{ + + va_list argptr; + char text[1024], *t_p; + int l, r; + + if (nostdout) + return; + + va_start (argptr,fmt); + vsprintf (text,fmt,argptr); + va_end (argptr); + + l = strlen(text); + t_p = text; + +// make sure everything goes through, even though we are non-blocking + while (l) + { + r = write (1, text, l); + if (r != l) + sleep (0); + if (r > 0) + { + t_p += r; + l -= r; + } + } + +} +*/ + +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[2048]; + unsigned char *p; + + va_start (argptr,fmt); + vsprintf (text,fmt,argptr); + va_end (argptr); + + if (strlen(text) > sizeof(text)) + Sys_Error("memory overwrite in Sys_Printf"); + + if (nostdout) + return; + + for (p = (unsigned char *)text; *p; p++) + if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) + printf("[%02x]", *p); + else + putc(*p, stdout); +} + +void Sys_Quit (void) +{ + Host_Shutdown(); + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + exit(0); +} + +void Sys_Init(void) +{ +#if id386 + Sys_SetFPCW(); +#endif +} + +void Sys_Error (char *error, ...) +{ + va_list argptr; + char string[1024]; + +// change stdin to non blocking + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + fprintf(stderr, "Error: %s\n", string); + + Host_Shutdown (); + exit (1); + +} + +void Sys_Warn (char *warning, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,warning); + vsprintf (string,warning,argptr); + va_end (argptr); + fprintf(stderr, "Warning: %s", string); +} + +/* +============ +Sys_FileTime + +returns -1 if not present +============ +*/ +int Sys_FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + + +void Sys_mkdir (char *path) +{ + mkdir (path, 0777); +} + +int Sys_FileOpenRead (char *path, int *handle) +{ + int h; + struct stat fileinfo; + + + h = open (path, O_RDONLY, 0666); + *handle = h; + if (h == -1) + return -1; + + if (fstat (h,&fileinfo) == -1) + Sys_Error ("Error fstating %s", path); + + return fileinfo.st_size; +} + +int Sys_FileOpenWrite (char *path) +{ + int handle; + + umask (0); + + handle = open(path,O_RDWR | O_CREAT | O_TRUNC + , 0666); + + if (handle == -1) + Sys_Error ("Error opening %s: %s", path,strerror(errno)); + + return handle; +} + +int Sys_FileWrite (int handle, void *src, int count) +{ + return write (handle, src, count); +} + +void Sys_FileClose (int handle) +{ + close (handle); +} + +void Sys_FileSeek (int handle, int position) +{ + lseek (handle, position, SEEK_SET); +} + +int Sys_FileRead (int handle, void *dest, int count) +{ + return read (handle, dest, count); +} + +void Sys_DebugLog(char *file, char *fmt, ...) +{ + va_list argptr; + static char data[1024]; + int fd; + + va_start(argptr, fmt); + vsprintf(data, fmt, argptr); + va_end(argptr); +// fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666); + fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); + write(fd, data, strlen(data)); + close(fd); +} + +void Sys_EditFile(char *filename) +{ + + char cmd[256]; + char *term; + char *editor; + + term = getenv("TERM"); + if (term && !strcmp(term, "xterm")) + { + editor = getenv("VISUAL"); + if (!editor) + editor = getenv("EDITOR"); + if (!editor) + editor = getenv("EDIT"); + if (!editor) + editor = "vi"; + sprintf(cmd, "xterm -e %s %s", editor, filename); + system(cmd); + } + +} + +double Sys_DoubleTime (void) +{ + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000000.0; + } + + return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; +} + +// ======================================================================= +// Sleeps for microseconds +// ======================================================================= + +static volatile int oktogo; + +void alarm_handler(int x) +{ + oktogo=1; +} + +void Sys_LineRefresh(void) +{ +} + +void floating_point_exception_handler(int whatever) +{ +// Sys_Warn("floating point exception\n"); + signal(SIGFPE, floating_point_exception_handler); +} + +char *Sys_ConsoleInput(void) +{ +#if 0 + static char text[256]; + int len; + + if (cls.state == ca_dedicated) { + len = read (0, text, sizeof(text)); + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; + } +#endif + return NULL; +} + +#if !id386 +void Sys_HighFPPrecision (void) +{ +} + +void Sys_LowFPPrecision (void) +{ +} +#endif + +int skipframes; + +int main (int c, char **v) +{ + + double time, oldtime, newtime; + quakeparms_t parms; + int j; + +// static char cwd[1024]; + +// signal(SIGFPE, floating_point_exception_handler); + signal(SIGFPE, SIG_IGN); + + memset(&parms, 0, sizeof(parms)); + + COM_InitArgv(c, v); + parms.argc = com_argc; + parms.argv = com_argv; + + parms.memsize = 16*1024*1024; + + j = COM_CheckParm("-mem"); + if (j) + parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024); + parms.membase = malloc (parms.memsize); + + parms.basedir = basedir; +// caching is disabled by default, use -cachedir to enable +// parms.cachedir = cachedir; + + noconinput = COM_CheckParm("-noconinput"); + if (!noconinput) + fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); + + if (COM_CheckParm("-nostdout")) + nostdout = 1; + + Sys_Init(); + + Host_Init(&parms); + + oldtime = Sys_DoubleTime (); + while (1) + { +// find time spent rendering last frame + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + + Host_Frame(time); + oldtime = newtime; + } + +} + + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + + int r; + unsigned long addr; + int psize = getpagesize(); + + addr = (startaddr & ~(psize-1)) - psize; + +// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, +// addr, startaddr+length, length); + + r = mprotect((char*)addr, length + startaddr - addr + psize, 7); + + if (r < 0) + Sys_Error("Protection change failed\n"); + +} + diff --git a/source/sys_unix.c b/source/sys_unix.c index 422c6c8..c4ce3a3 100644 --- a/source/sys_unix.c +++ b/source/sys_unix.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include "qwsvdef.h" @@ -212,7 +212,7 @@ void Sys_Init (void) main ============= */ -void main(int argc, char *argv[]) +int main(int argc, char *argv[]) { double time, oldtime, newtime; quakeparms_t parms; @@ -279,5 +279,6 @@ void main(int argc, char *argv[]) if (sys_extrasleep.value) usleep (sys_extrasleep.value); } + return 1; } diff --git a/source/sys_win.c b/source/sys_win.c index f9352ea..dd8dca7 100644 --- a/source/sys_win.c +++ b/source/sys_win.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 "quakedef.h" diff --git a/source/sys_win.c.server b/source/sys_win.c.server index b03ac51..9a237ee 100644 --- a/source/sys_win.c.server +++ b/source/sys_win.c.server @@ -1,260 +1,260 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 -#include -#include "qwsvdef.h" -#include -#include +#include +#include "qwsvdef.h" +#include +#include cvar_t sys_nostdout = {"sys_nostdout","0"}; -/* -================ -Sys_FileTime -================ -*/ -int Sys_FileTime (char *path) -{ - FILE *f; - - f = fopen(path, "rb"); - if (f) - { - fclose(f); - return 1; - } - - return -1; -} - -/* -================ -Sys_mkdir -================ -*/ -void Sys_mkdir (char *path) -{ - _mkdir(path); -} - - -/* -================ -Sys_Error -================ -*/ -void Sys_Error (char *error, ...) -{ - va_list argptr; - char text[1024]; - - va_start (argptr,error); - vsprintf (text, error,argptr); - va_end (argptr); - -// MessageBox(NULL, text, "Error", 0 /* MB_OK */ ); - printf ("ERROR: %s\n", text); - - exit (1); -} - - -/* -================ -Sys_DoubleTime -================ -*/ -double Sys_DoubleTime (void) -{ - double t; - struct _timeb tstruct; - static int starttime; - - _ftime( &tstruct ); - - if (!starttime) - starttime = tstruct.time; - t = (tstruct.time-starttime) + tstruct.millitm*0.001; - - return t; -} - - -/* -================ -Sys_ConsoleInput -================ -*/ -char *Sys_ConsoleInput (void) -{ - static char text[256]; - static int len; - int c; - - // read a line out - while (_kbhit()) - { - c = _getch(); - putch (c); - if (c == '\r') - { - text[len] = 0; - putch ('\n'); - len = 0; - return text; - } - if (c == 8) - { - if (len) - { - putch (' '); - putch (c); - len--; - text[len] = 0; - } - continue; - } - text[len] = c; - len++; - text[len] = 0; - if (len == sizeof(text)) - len = 0; - } - - return NULL; -} - - -/* -================ -Sys_Printf -================ -*/ -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - - if (sys_nostdout.value) - return; - - va_start (argptr,fmt); - vprintf (fmt,argptr); - va_end (argptr); -} - -/* -================ -Sys_Quit -================ -*/ -void Sys_Quit (void) -{ - exit (0); -} - - -/* -============= -Sys_Init - -Quake calls this so the system can register variables before host_hunklevel -is marked -============= -*/ -void Sys_Init (void) -{ - Cvar_RegisterVariable (&sys_nostdout); -} - -/* -================== -main - -================== -*/ -char *newargv[256]; - -int main (int argc, char **argv) -{ - quakeparms_t parms; - double newtime, time, oldtime; - static char cwd[1024]; - struct timeval timeout; - fd_set fdset; - int t; - - COM_InitArgv (argc, argv); - - parms.argc = com_argc; - parms.argv = com_argv; - - parms.memsize = 16*1024*1024; - - if ((t = COM_CheckParm ("-heapsize")) != 0 && - t + 1 < com_argc) - parms.memsize = Q_atoi (com_argv[t + 1]) * 1024; - - if ((t = COM_CheckParm ("-mem")) != 0 && - t + 1 < com_argc) - parms.memsize = Q_atoi (com_argv[t + 1]) * 1024 * 1024; - - parms.membase = malloc (parms.memsize); - - if (!parms.membase) - Sys_Error("Insufficient memory.\n"); - - parms.basedir = "."; - parms.cachedir = NULL; - - SV_Init (&parms); - -// run one frame immediately for first heartbeat - SV_Frame (0.1); - -// -// main loop -// - oldtime = Sys_DoubleTime () - 0.1; - while (1) - { - // select on the net socket and stdin - // the only reason we have a timeout at all is so that if the last - // connected client times out, the message would not otherwise - // be printed until the next event. - FD_ZERO(&fdset); - FD_SET(net_socket, &fdset); - timeout.tv_sec = 0; - timeout.tv_usec = 100; - if (select (net_socket+1, &fdset, NULL, NULL, &timeout) == -1) - continue; - - // find time passed since last cycle - newtime = Sys_DoubleTime (); - time = newtime - oldtime; - oldtime = newtime; - - SV_Frame (time); - } - - return true; -} - +/* +================ +Sys_FileTime +================ +*/ +int Sys_FileTime (char *path) +{ + FILE *f; + + f = fopen(path, "rb"); + if (f) + { + fclose(f); + return 1; + } + + return -1; +} + +/* +================ +Sys_mkdir +================ +*/ +void Sys_mkdir (char *path) +{ + _mkdir(path); +} + + +/* +================ +Sys_Error +================ +*/ +void Sys_Error (char *error, ...) +{ + va_list argptr; + char text[1024]; + + va_start (argptr,error); + vsprintf (text, error,argptr); + va_end (argptr); + +// MessageBox(NULL, text, "Error", 0 /* MB_OK */ ); + printf ("ERROR: %s\n", text); + + exit (1); +} + + +/* +================ +Sys_DoubleTime +================ +*/ +double Sys_DoubleTime (void) +{ + double t; + struct _timeb tstruct; + static int starttime; + + _ftime( &tstruct ); + + if (!starttime) + starttime = tstruct.time; + t = (tstruct.time-starttime) + tstruct.millitm*0.001; + + return t; +} + + +/* +================ +Sys_ConsoleInput +================ +*/ +char *Sys_ConsoleInput (void) +{ + static char text[256]; + static int len; + int c; + + // read a line out + while (_kbhit()) + { + c = _getch(); + putch (c); + if (c == '\r') + { + text[len] = 0; + putch ('\n'); + len = 0; + return text; + } + if (c == 8) + { + if (len) + { + putch (' '); + putch (c); + len--; + text[len] = 0; + } + continue; + } + text[len] = c; + len++; + text[len] = 0; + if (len == sizeof(text)) + len = 0; + } + + return NULL; +} + + +/* +================ +Sys_Printf +================ +*/ +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + + if (sys_nostdout.value) + return; + + va_start (argptr,fmt); + vprintf (fmt,argptr); + va_end (argptr); +} + +/* +================ +Sys_Quit +================ +*/ +void Sys_Quit (void) +{ + exit (0); +} + + +/* +============= +Sys_Init + +Quake calls this so the system can register variables before host_hunklevel +is marked +============= +*/ +void Sys_Init (void) +{ + Cvar_RegisterVariable (&sys_nostdout); +} + +/* +================== +main + +================== +*/ +char *newargv[256]; + +int main (int argc, char **argv) +{ + quakeparms_t parms; + double newtime, time, oldtime; + static char cwd[1024]; + struct timeval timeout; + fd_set fdset; + int t; + + COM_InitArgv (argc, argv); + + parms.argc = com_argc; + parms.argv = com_argv; + + parms.memsize = 16*1024*1024; + + if ((t = COM_CheckParm ("-heapsize")) != 0 && + t + 1 < com_argc) + parms.memsize = Q_atoi (com_argv[t + 1]) * 1024; + + if ((t = COM_CheckParm ("-mem")) != 0 && + t + 1 < com_argc) + parms.memsize = Q_atoi (com_argv[t + 1]) * 1024 * 1024; + + parms.membase = malloc (parms.memsize); + + if (!parms.membase) + Sys_Error("Insufficient memory.\n"); + + parms.basedir = "."; + parms.cachedir = NULL; + + SV_Init (&parms); + +// run one frame immediately for first heartbeat + SV_Frame (0.1); + +// +// main loop +// + oldtime = Sys_DoubleTime () - 0.1; + while (1) + { + // select on the net socket and stdin + // the only reason we have a timeout at all is so that if the last + // connected client times out, the message would not otherwise + // be printed until the next event. + FD_ZERO(&fdset); + FD_SET(net_socket, &fdset); + timeout.tv_sec = 0; + timeout.tv_usec = 100; + if (select (net_socket+1, &fdset, NULL, NULL, &timeout) == -1) + continue; + + // find time passed since last cycle + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + oldtime = newtime; + + SV_Frame (time); + } + + return true; +} + diff --git a/source/vid_svgalib.c b/source/vid_svgalib.c index c233e69..94d5573 100644 --- a/source/vid_svgalib.c +++ b/source/vid_svgalib.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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 #include #include diff --git a/source/vid_win.c b/source/vid_win.c index 6445206..0194362 100644 --- a/source/vid_win.c +++ b/source/vid_win.c @@ -1,3391 +1,3391 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// vid_win.c -- Win32 video driver - -#include "quakedef.h" -#include "winquake.h" -#include "d_local.h" -#include "resource.h" - -#define MINIMUM_MEMORY 0x550000 - -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 - -qboolean dibonly; - -extern int Minimized; - -HWND mainwindow; - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -int DIBWidth, DIBHeight; -qboolean DDActive; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -static DEVMODE gdevmode; -static qboolean startwindowed = 0, windowed_mode_set; -static int firstupdate = 1; -static qboolean vid_initialized = false, vid_palettized; -static int lockcount; -static int vid_fulldib_on_focus_mode; -static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; -static int vid_stretched, windowed_mouse; -static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; -static HICON hIcon; - -qboolean mouseactive; // from in_win.c - -viddef_t vid; // global video state - -#define MODE_WINDOWED 0 -#define MODE_SETTABLE_WINDOW 2 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) - -// Note that 0 is MODE_WINDOWED -cvar_t vid_mode = {"vid_mode","0", false}; -// Note that 0 is MODE_WINDOWED -cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; -// Note that 3 is MODE_FULLSCREEN_DEFAULT -cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; -cvar_t vid_wait = {"vid_wait","0"}; -cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; -cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; -cvar_t vid_config_x = {"vid_config_x","800", true}; -cvar_t vid_config_y = {"vid_config_y","600", true}; -cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; -cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; -cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; -cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; -cvar_t block_switch = {"block_switch","0", true}; -cvar_t vid_window_x = {"vid_window_x", "0", true}; -cvar_t vid_window_y = {"vid_window_y", "0", true}; - -typedef struct { - int width; - int height; -} lmode_t; - -lmode_t lowresmodes[] = { - {320, 200}, - {320, 240}, - {400, 300}, - {512, 384}, -}; - -int vid_modenum = NO_MODE; -int vid_testingmode, vid_realmode; -double vid_testendtime; -int vid_default = MODE_WINDOWED; -static int windowed_default; - -modestate_t modestate = MS_UNINIT; - -static byte *vid_surfcache; -static int vid_surfcachesize; -static int VID_highhunkmark; - -unsigned char vid_curpal[256*3]; - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; - -int driver = grDETECT,mode; -bool useWinDirect = true, useDirectDraw = true; -MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int mode13; - int stretched; - int dib; - int fullscreen; - int bpp; - int halfscreen; - char modedesc[13]; -} vmode_t; - -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; -static vmode_t *pcurrentmode; - -int aPage; // Current active display page -int vPage; // Current visible display page -int waitVRT = true; // True to wait for retrace on flip - -static vmode_t badmode; - -static byte backingbuf[48*24]; - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate(BOOL fActive, BOOL minimize); - - -/* -================ -VID_RememberWindowPos -================ -*/ -void VID_RememberWindowPos (void) -{ - RECT rect; - - if (GetWindowRect (mainwindow, &rect)) - { - if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && - (rect.top < GetSystemMetrics (SM_CYSCREEN)) && - (rect.right > 0) && - (rect.bottom > 0)) - { - Cvar_SetValue ("vid_window_x", (float)rect.left); - Cvar_SetValue ("vid_window_y", (float)rect.top); - } - } -} - - -/* -================ -VID_CheckWindowXY -================ -*/ -void VID_CheckWindowXY (void) -{ - - if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - ((int)vid_window_x.value < 0) || - ((int)vid_window_y.value < 0)) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0 ); - } -} - - -/* -================ -VID_UpdateWindowStatus -================ -*/ -void VID_UpdateWindowStatus (void) -{ - - window_rect.left = window_x; - window_rect.top = window_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; - - IN_UpdateClipCursor (); -} - - -/* -================ -ClearAllStates -================ -*/ -void ClearAllStates (void) -{ - int i; - -// send an up event for each key, to make sure the server clears them all - for (i=0 ; i<256 ; i++) - { - Key_Event (i, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - - -/* -================ -VID_CheckAdequateMem -================ -*/ -qboolean VID_CheckAdequateMem (int width, int height) -{ - int tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tbuffersize += D_SurfaceCacheForRes (width, height); - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < MINIMUM_MEMORY) - { - return false; // not enough memory for mode - } - - return true; -} - - -/* -================ -VID_AllocBuffers -================ -*/ -qboolean VID_AllocBuffers (int width, int height) -{ - int tsize, tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tsize = D_SurfaceCacheForRes (width, height); - - tbuffersize += tsize; - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < MINIMUM_MEMORY) - { - Con_SafePrintf ("Not enough memory for video mode\n"); - return false; // not enough memory for mode - } - - vid_surfcachesize = tsize; - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (VID_highhunkmark); - d_pzbuffer = NULL; - } - - VID_highhunkmark = Hunk_HighMark (); - - d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); - - vid_surfcache = (byte *)d_pzbuffer + - width * height * sizeof (*d_pzbuffer); - - return true; -} - - -void initFatalError(void) -{ - MGL_exit(); - MGL_fatalError(MGL_errorMsg(MGL_result())); - exit(EXIT_FAILURE); -} - -#if 0 //def NEW_SUSPEND - -int VID_Suspend (MGLDC *dc, int flags) -{ - int i; - if (flags & MGL_DEACTIVATE) - { - IN_RestoreOriginalMouseState (); - CDAudio_Pause (); - - // keep WM_PAINT from trying to redraw - in_mode_set = true; - block_drawing = true; - } - else if (flags & MGL_REACTIVATE) - { - IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - CDAudio_Resume (); - in_mode_set = false; - - block_drawing = false; -// vid.recalc_refdef = 1; - force_mode_set = 1; - i = msg_suppress_1; - msg_suppress_1 = 1; - VID_Fullscreen_f(); - msg_suppress_1 = i; - force_mode_set = 0; - } - - return 1; -} - -#else - -int VID_Suspend (MGLDC *dc, int flags) -{ - - if (flags & MGL_DEACTIVATE) - { - // FIXME: this doesn't currently work on NT - if (block_switch.value && !WinNT) - { - return MGL_NO_DEACTIVATE; - } - - S_BlockSound (); - S_ClearBuffer (); - - IN_RestoreOriginalMouseState (); - CDAudio_Pause (); - - // keep WM_PAINT from trying to redraw - in_mode_set = true; - - block_drawing = true; // so we don't try to draw while switched away - - return MGL_NO_SUSPEND_APP; - } - else if (flags & MGL_REACTIVATE) - { - IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - CDAudio_Resume (); - S_UnblockSound (); - - in_mode_set = false; - - vid.recalc_refdef = 1; - - block_drawing = false; - - return MGL_NO_SUSPEND_APP; - } - -} -#endif - - -void registerAllDispDrivers(void) -{ - /* Event though these driver require WinDirect, we register - * them so that they will still be available even if DirectDraw - * is present and the user has disable the high performance - * WinDirect modes. - */ - MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); -// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); - - /* Register display drivers */ - if (useWinDirect) - { -//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); - MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); - - if (!COM_CheckParm ("-novbeaf")) - MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); - } - - if (useDirectDraw) - { - MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); - } -} - - -void registerAllMemDrivers(void) -{ - /* Register memory context drivers */ - MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); -} - - -void VID_InitMGLFull (HINSTANCE hInstance) -{ - int i, xRes, yRes, bits, vMode, lowres, curmode, temp; - int lowstretchedres, stretchedmode, lowstretched; - uchar *m; - -// FIXME: NT is checked for because MGL currently has a bug that causes it -// to try to use WinDirect modes even on NT - if (COM_CheckParm("-nowindirect") || - COM_CheckParm("-nowd") || - COM_CheckParm("-novesa") || - WinNT) - { - useWinDirect = false; - } - - if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) - useDirectDraw = false; - - // Initialise the MGL - MGL_unregisterAllDrivers(); - registerAllDispDrivers(); - registerAllMemDrivers(); - MGL_detectGraph(&driver,&mode); - m = MGL_availableModes(); - - if (m[0] != 0xFF) - { - lowres = lowstretchedres = 99999; - lowstretched = 0; - curmode = 0; - - // find the lowest-res mode, or a mode we can stretch up to and get - // lowest-res that way - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (curmode < MAX_MODE_LIST)) - { - if (m[i] == grVGA_320x200x256) - is_mode0x13 = true; - - if (!COM_CheckParm("-noforcevga")) - { - if (m[i] == grVGA_320x200x256) - { - mode = i; - break; - } - } - - if (xRes < lowres) - { - lowres = xRes; - mode = i; - } - - if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) - { - lowstretchedres = xRes >> 1; - stretchedmode = i; - } - } - - curmode++; - } - - // if there's a mode we can stretch by 2 up to, thereby effectively getting - // a lower-res mode than the lowest-res real but still at least 320x200, that - // will be our default mode - if (lowstretchedres < lowres) - { - mode = stretchedmode; - lowres = lowstretchedres; - lowstretched = 1; - } - - // build the mode list, leaving room for the low-res stretched mode, if any - nummodes++; // leave room for default mode - - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - if (i == mode) - { - if (lowstretched) - { - stretchedmode = nummodes; - curmode = nummodes++; - } - else - { - curmode = MODE_FULLSCREEN_DEFAULT; - } - } - else - { - curmode = nummodes++; - } - - modelist[curmode].type = MS_FULLSCREEN; - modelist[curmode].width = xRes; - modelist[curmode].height = yRes; - sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); - - if (m[i] == grVGA_320x200x256) - modelist[curmode].mode13 = 1; - else - modelist[curmode].mode13 = 0; - - modelist[curmode].modenum = m[i]; - modelist[curmode].stretched = 0; - modelist[curmode].dib = 0; - modelist[curmode].fullscreen = 1; - modelist[curmode].halfscreen = 0; - modelist[curmode].bpp = 8; - } - } - - if (lowstretched) - { - modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; - modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; - modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; - modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; - sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - } - - vid_default = MODE_FULLSCREEN_DEFAULT; - - temp = m[0]; - - if (!MGL_init(&driver, &temp, "")) - { - initFatalError(); - } - } - - MGL_setSuspendAppCallback(VID_Suspend); -} - - -MGLDC *createDisplayDC(int forcemem) -/**************************************************************************** -* -* Function: createDisplayDC -* Returns: Pointer to the MGL device context to use for the application -* -* Description: Initialises the MGL and creates an appropriate display -* device context to be used by the GUI. This creates and -* apropriate device context depending on the system being -* compile for, and should be the only place where system -* specific code is required. -* -****************************************************************************/ -{ - MGLDC *dc; - pixel_format_t pf; - int npages; - - // Start the specified video mode - if (!MGL_changeDisplayMode(mode)) - initFatalError(); - - npages = MGL_availablePages(mode); - - if (npages > 3) - npages = 3; - - if (!COM_CheckParm ("-notriplebuf")) - { - if (npages > 2) - { - npages = 2; - } - } - - if ((dc = MGL_createDisplayDC(npages)) == NULL) - return NULL; - - if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) - { - MGL_makeCurrentDC(dc); - memdc = NULL; - } - else - { - // Set up for blitting from a memory buffer - memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); - MGL_makeCurrentDC(memdc); - } - - // Enable page flipping even for even for blitted surfaces - if (forcemem) - { - vid.numpages = 1; - } - else - { - vid.numpages = dc->mi.maxPage + 1; - - if (vid.numpages > 1) - { - // Set up for page flipping - MGL_setActivePage(dc, aPage = 1); - MGL_setVisualPage(dc, vPage = 0, false); - } - - if (vid.numpages > 3) - vid.numpages = 3; - } - - if (vid.numpages == 2) - waitVRT = true; - else - waitVRT = false; - - return dc; -} - - -void VID_InitMGLDIB (HINSTANCE hInstance) -{ - WNDCLASS wc; - HDC hdc; - int i; - - hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); - - /* Register the frame class */ - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)MainWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = 0; - wc.hCursor = LoadCursor (NULL,IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = 0; - wc.lpszClassName = "WinQuake"; - - if (!RegisterClass (&wc) ) - Sys_Error ("Couldn't register window class"); - - /* Find the size for the DIB window */ - /* Initialise the MGL for windowed operation */ - MGL_setAppInstance(hInstance); - registerAllMemDrivers(); - MGL_initWindowed(""); - - modelist[0].type = MS_WINDOWED; - modelist[0].width = 320; - modelist[0].height = 240; - strcpy (modelist[0].modedesc, "320x240"); - modelist[0].mode13 = 0; - modelist[0].modenum = MODE_WINDOWED; - modelist[0].stretched = 0; - modelist[0].dib = 1; - modelist[0].fullscreen = 0; - modelist[0].halfscreen = 0; - modelist[0].bpp = 8; - - modelist[1].type = MS_WINDOWED; - modelist[1].width = 640; - modelist[1].height = 480; - strcpy (modelist[1].modedesc, "640x480"); - modelist[1].mode13 = 0; - modelist[1].modenum = MODE_WINDOWED + 1; - modelist[1].stretched = 1; - modelist[1].dib = 1; - modelist[1].fullscreen = 0; - modelist[1].halfscreen = 0; - modelist[1].bpp = 8; - - modelist[2].type = MS_WINDOWED; - modelist[2].width = 800; - modelist[2].height = 600; - strcpy (modelist[2].modedesc, "800x600"); - modelist[2].mode13 = 0; - modelist[2].modenum = MODE_WINDOWED + 2; - modelist[2].stretched = 1; - modelist[2].dib = 1; - modelist[2].fullscreen = 0; - modelist[2].halfscreen = 0; - modelist[2].bpp = 8; - -// automatically stretch the default mode up if > 640x480 desktop resolution - hdc = GetDC(NULL); - - if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) - { - vid_default = MODE_WINDOWED + 1; - } - else - { - vid_default = MODE_WINDOWED; - } - - windowed_default = vid_default; - - ReleaseDC(NULL,hdc); - - nummodes = 3; // reserve space for windowed mode - - DDActive = 0; -} - - -/* -================= -VID_InitFullDIB -================= -*/ -void VID_InitFullDIB (HINSTANCE hInstance) -{ - DEVMODE devmode; - int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; - int numlowresmodes, bpp, done; - int cstretch, istretch, mstretch; - BOOL stat; - -// enumerate 8 bpp modes - originalnummodes = nummodes; - modenum = 0; - lowestres = 99999; - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((devmode.dmBitsPerPel == 8) && - (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height << 1)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i 8 bpp - if (nummodes == originalnummodes) - { - modenum = 0; - lowestres = 99999; - - Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((((devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT)) || - (!COM_CheckParm("-noadjustaspect") && - (devmode.dmPelsWidth <= (MAXWIDTH*2)) && - (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && - (nummodes < MAX_MODE_LIST) && - (devmode.dmBitsPerPel > 8)) - { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height*2)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i= modelist[i].bpp)) - { - existingmode = 1; - break; - } - } - - if (!existingmode) - { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - switch (bpp) - { - case 8: - bpp = 16; - break; - - case 16: - bpp = 32; - break; - - case 32: - done = 1; - break; - } - } - -// now add the lowest stretch-by-2 pseudo-modes between 320-wide -// (inclusive) and lowest real res (not inclusive) -// don't bother if we have a real VGA mode 0x13 mode - if (!is_mode0x13) - { - for (i=originalnummodes, cstretch=0 ; i> 1) < lowestres) && - ((modelist[i].width >> 1) >= 320)) - { - lowestres = modelist[i].width >> 1; - cstretch = 1; - mstretch = i; - } - } - - if ((nummodes + cstretch) > MAX_MODE_LIST) - cstretch = MAX_MODE_LIST - nummodes; - - if (cstretch > 0) - { - for (i=(nummodes-1) ; i>=originalnummodes ; i--) - modelist[i+cstretch] = modelist[i]; - - nummodes += cstretch; - istretch = originalnummodes; - - modelist[istretch] = modelist[mstretch]; - modelist[istretch].width >>= 1; - modelist[istretch].height >>= 1; - modelist[istretch].stretched = 1; - sprintf (modelist[istretch].modedesc, "%dx%d", - modelist[istretch].width, modelist[istretch].height); - } - } - - if (nummodes != originalnummodes) - vid_default = MODE_FULLSCREEN_DEFAULT; - else - Con_SafePrintf ("No fullscreen DIB modes found\n"); -} - - -/* -================= -VID_NumModes -================= -*/ -int VID_NumModes (void) -{ - return nummodes; -} - - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) -{ - - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; -} - - -/* -================= -VID_CheckModedescFixup -================= -*/ -void VID_CheckModedescFixup (int mode) -{ - int x, y, stretch; - - if (mode == MODE_SETTABLE_WINDOW) - { - modelist[mode].stretched = (int)vid_stretch_by_2.value; - stretch = modelist[mode].stretched; - - if (vid_config_x.value < (320 << stretch)) - vid_config_x.value = 320 << stretch; - - if (vid_config_y.value < (200 << stretch)) - vid_config_y.value = 200 << stretch; - - x = (int)vid_config_x.value; - y = (int)vid_config_y.value; - sprintf (modelist[mode].modedesc, "%dx%d", x, y); - modelist[mode].width = x; - modelist[mode].height = y; - } -} - - -/* -================= -VID_GetModeDescriptionMemCheck -================= -*/ -char *VID_GetModeDescriptionMemCheck (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - - if (VID_CheckAdequateMem (pv->width, pv->height)) - { - return pinfo; - } - else - { - return NULL; - } -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - return pinfo; -} - - -/* -================= -VID_GetModeDescription2 - -Tacks on "windowed" or "fullscreen" -================= -*/ -char *VID_GetModeDescription2 (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -// KJB: Added this to return the mode driver name in description for console - -char *VID_GetExtModeDescription (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen %s",pv->modedesc, - MGL_modeDriverName(pv->modenum)); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -void DestroyDIBWindow (void) -{ - - if (modestate == MS_WINDOWED) - { - // destroy the associated MGL DC's; the window gets reused - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -void DestroyFullscreenWindow (void) -{ - - if (modestate == MS_FULLSCREEN) - { - // destroy the existing fullscreen mode and DC's - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - } -} - - - -void DestroyFullDIBWindow (void) -{ - if (modestate == MS_FULLDIB) - { - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - // Destroy the fullscreen DIB window and associated MGL DC's - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -qboolean VID_SetWindowedMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - qboolean stretched; - int lastmodestate; - LONG wlong; - - if (!windowed_mode_set) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - windowed_mode_set; - } - - VID_CheckModedescFixup (modenum); - - DDActive = 0; - lastmodestate = modestate; - - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - -// KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - stretched = modelist[modenum].stretched; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - if (stretched) - { - DIBWidth >>= 1; - DIBHeight >>= 1; - } - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - -// the first time we're called to set the mode, create the window we'll use -// for the rest of the session - if (!vid_mode_set) - { - mainwindow = CreateWindowEx ( - ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, - NULL, - global_hInstance, - NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window"); - - // tell MGL to use this window for fullscreen modes - MGL_registerFullScreenWindow (mainwindow); - - vid_mode_set = true; - } - else - { - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - } - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER | - SWP_HIDEWINDOW)) - { - Sys_Error ("Couldn't resize DIB window"); - } - - if (hide_window) - return true; - -// position and show the DIB window - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - - if (force_minimized) - ShowWindow (mainwindow, SW_MINIMIZE); - else - ShowWindow (mainwindow, SW_SHOWDEFAULT); - - UpdateWindow (mainwindow); - - modestate = MS_WINDOWED; - vid_fulldib_on_focus_mode = 0; - -// because we have set the background brush for the window to NULL -// (to avoid flickering when re-sizing the window on the desktop), -// we clear the window to black when created, otherwise it will be -// empty while Quake starts up. - hdc = GetDC(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Windowed DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = stretched; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -qboolean VID_SetFullscreenMode (int modenum) -{ - - DDActive = 1; - - DestroyDIBWindow (); - DestroyFullDIBWindow (); - - mode = modelist[modenum].modenum; - - // Destroy old DC's, resetting back to fullscreen mode - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - - if ((mgldc = createDisplayDC (modelist[modenum].stretched || - (int)vid_nopageflip.value)) == NULL) - { - return false; - } - - modestate = MS_FULLSCREEN; - vid_fulldib_on_focus_mode = 0; - - vid.buffer = vid.conbuffer = vid.direct = NULL; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - DIBHeight = vid.height = vid.conheight = modelist[modenum].height; - DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - -// set the large icon, so the Quake icon will show up in the taskbar - SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); - -// shouldn't be needed, but Kendall needs to let us get the activation -// message for this not to be needed on NT - AppActivate (true, false); - - return true; -} - - -qboolean VID_SetFullDIBMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - int lastmodestate; - - DDActive = 0; - - DestroyFullscreenWindow (); - DestroyDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - - // KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - gdevmode.dmBitsPerPel = modelist[modenum].bpp; - gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << - modelist[modenum].halfscreen; - gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; - gdevmode.dmSize = sizeof (gdevmode); - - if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode"); - - lastmodestate = modestate; - modestate = MS_FULLDIB; - vid_fulldib_on_focus_mode = modenum; - - WindowRect.top = WindowRect.left = 0; - - hdc = GetDC(NULL); - - WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; - WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; - - ReleaseDC(NULL,hdc); - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER)) - { - Sys_Error ("Couldn't resize DIB window"); - } - -// position and show the DIB window - SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - // Because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), we - // clear the window to black when created, otherwise it will be - // empty while Quake starts up. - hdc = GetDC(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Fullscreen DIB DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - return true; -} - - -void VID_RestoreOldMode (int original_mode) -{ - static qboolean inerror = false; - - if (inerror) - return; - - in_mode_set = false; - inerror = true; - -// make sure mode set happens (video mode changes) - vid_modenum = original_mode - 1; - - if (!VID_SetMode (original_mode, vid_curpal)) - { - vid_modenum = MODE_WINDOWED - 1; - - if (!VID_SetMode (windowed_default, vid_curpal)) - Sys_Error ("Can't set any video mode"); - } - - inerror = false; -} - - -void VID_SetDefaultMode (void) -{ - - if (vid_initialized) - VID_SetMode (0, vid_curpal); - - IN_DeactivateMouse (); -} - - -int VID_SetMode (int modenum, unsigned char *palette) -{ - int original_mode, temp, dummy; - qboolean stat; - MSG msg; - HDC hdc; - - while ((modenum >= nummodes) || (modenum < 0)) - { - if (vid_modenum == NO_MODE) - { - if (modenum == vid_default) - { - modenum = windowed_default; - } - else - { - modenum = vid_default; - } - - Cvar_SetValue ("vid_mode", (float)modenum); - } - else - { - Cvar_SetValue ("vid_mode", (float)vid_modenum); - return 0; - } - } - - if (!force_mode_set && (modenum == vid_modenum)) - return true; - -// so Con_Printfs don't mess us up by forcing vid and snd updates - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - in_mode_set = true; - - CDAudio_Pause (); - S_ClearBuffer (); - - if (vid_modenum == NO_MODE) - original_mode = windowed_default; - else - original_mode = vid_modenum; - - // Set either the fullscreen or windowed mode - if (modelist[modenum].type == MS_WINDOWED) - { - if (_windowed_mouse.value && key_dest == key_game) - { - stat = VID_SetWindowedMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode(modenum); - } - } - else if (modelist[modenum].type == MS_FULLDIB) - { - stat = VID_SetFullDIBMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - stat = VID_SetFullscreenMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - - window_width = vid.width << vid_stretched; - window_height = vid.height << vid_stretched; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - scr_disabled_for_loading = temp; - - if (!stat) - { - VID_RestoreOldMode (original_mode); - return false; - } - - if (hide_window) - return true; - -// now we try to make sure we get the focus on the mode switch, because -// sometimes in some systems we don't. We grab the foreground, then -// finish setting up, pump all our messages, and sleep for a little while -// to let messages finish bouncing around the system, then we put -// ourselves at the top of the z order, then grab the foreground again, -// Who knows if it helps, but it probably doesn't hurt - if (!force_minimized) - SetForegroundWindow (mainwindow); - - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - VID_SetPalette (palette); - - ReleaseDC(NULL,hdc); - - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - if (!VID_AllocBuffers (vid.width, vid.height)) - { - // couldn't get memory for this mode; try to fall back to previous mode - VID_RestoreOldMode (original_mode); - return false; - } - - D_InitCaches (vid_surfcache, vid_surfcachesize); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - if (!force_minimized) - { - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (mainwindow); - } - -// fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - if (!msg_suppress_1) - Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum)); - - VID_SetPalette (palette); - - in_mode_set = false; - vid.recalc_refdef = 1; - - return true; -} - -void VID_LockBuffer (void) -{ - - if (dibdc) - return; - - lockcount++; - - if (lockcount > 1) - return; - - MGL_beginDirectAccess(); - - if (memdc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = memdc->surface; - vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; - } - else if (mgldc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; - vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; - } - - if (r_dowarp) - d_viewbuffer = r_warpbuffer; - else - d_viewbuffer = (void *)(byte *)vid.buffer; - - if (r_dowarp) - screenwidth = WARP_WIDTH; - else - screenwidth = vid.rowbytes; - - if (lcd_x.value) - screenwidth <<= 1; -} - - -void VID_UnlockBuffer (void) -{ - if (dibdc) - return; - - lockcount--; - - if (lockcount > 0) - return; - - if (lockcount < 0) - Sys_Error ("Unbalanced unlock"); - - MGL_endDirectAccess(); - -// to turn up any unlocked accesses - vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; - -} - - -int VID_ForceUnlockedAndReturnState (void) -{ - int lk; - - if (!lockcount) - return 0; - - lk = lockcount; - - if (dibdc) - { - lockcount = 0; - } - else - { - lockcount = 1; - VID_UnlockBuffer (); - } - - return lk; -} - - -void VID_ForceLockState (int lk) -{ - - if (!dibdc && lk) - { - lockcount = 0; - VID_LockBuffer (); - } - - lockcount = lk; -} - - -void VID_SetPalette (unsigned char *palette) -{ - INT i; - palette_t pal[256]; - HDC hdc; - - if (!Minimized) - { - palette_changed = true; - - // make sure we have the static colors if we're the active app - hdc = GetDC(NULL); - - if (vid_palettized && ActiveApp) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - - ReleaseDC(NULL,hdc); - - // Translate the palette values to an MGL palette array and - // set the values. - for (i = 0; i < 256; i++) - { - pal[i].red = palette[i*3]; - pal[i].green = palette[i*3+1]; - pal[i].blue = palette[i*3+2]; - } - - if (DDActive) - { - if (!mgldc) - return; - - MGL_setPalette(mgldc,pal,256,0); - MGL_realizePalette(mgldc,256,0,false); - if (memdc) - MGL_setPalette(memdc,pal,256,0); - } - else - { - if (!windc) - return; - - MGL_setPalette(windc,pal,256,0); - MGL_realizePalette(windc,256,0,false); - if (dibdc) - { - MGL_setPalette(dibdc,pal,256,0); - MGL_realizePalette(dibdc,256,0,false); - } - } - } - - memcpy (vid_curpal, palette, sizeof(vid_curpal)); - - if (syscolchg) - { - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - syscolchg = false; - } -} - - -void VID_ShiftPalette (unsigned char *palette) -{ - VID_SetPalette (palette); -} - - -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void VID_DescribeCurrentMode_f (void) -{ - Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); -} - - -/* -================= -VID_NumModes_f -================= -*/ -void VID_NumModes_f (void) -{ - - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", nummodes); - else - Con_Printf ("%d video modes are available\n", nummodes); -} - - -/* -================= -VID_DescribeMode_f -================= -*/ -void VID_DescribeMode_f (void) -{ - int modenum; - - modenum = Q_atoi (Cmd_Argv(1)); - - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, lnummodes; - char *pinfo; - qboolean na; - vmode_t *pv; - - na = false; - - lnummodes = VID_NumModes (); - - for (i=0 ; iwidth, pv->height)) - { - Con_Printf ("%2d: %s\n", i, pinfo); - } - else - { - Con_Printf ("**: %s\n", pinfo); - na = true; - } - } - - if (na) - { - Con_Printf ("\n[**: not enough system RAM for mode]\n"); - } -} - - -/* -================= -VID_TestMode_f -================= -*/ -void VID_TestMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - if (VID_SetMode (modenum, vid_curpal)) - { - vid_testingmode = 1; - testduration = Q_atof (Cmd_Argv(2)); - if (testduration == 0) - testduration = 5.0; - vid_testendtime = realtime + testduration; - } - } -} - -/* -================= -VID_Windowed_f -================= -*/ -void VID_Windowed_f (void) -{ - - VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); -} - - -/* -================= -VID_Fullscreen_f -================= -*/ -void VID_Fullscreen_f (void) -{ - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); -} - -/* -================= -VID_Minimize_f -================= -*/ -void VID_Minimize_f (void) -{ - -// we only support minimizing windows; if you're fullscreen, -// switch to windowed first - if (modestate == MS_WINDOWED) - ShowWindow (mainwindow, SW_MINIMIZE); -} - - - -/* -================= -VID_ForceMode_f -================= -*/ -void VID_ForceMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - force_mode_set = 1; - VID_SetMode (modenum, vid_curpal); - force_mode_set = 0; - } -} - - -void VID_Init (unsigned char *palette) -{ - int i, bestmatch, bestmatchmetric, t, dr, dg, db; - int basenummodes; - byte *ptmp; - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_wait); - Cvar_RegisterVariable (&vid_nopageflip); - Cvar_RegisterVariable (&_vid_wait_override); - Cvar_RegisterVariable (&_vid_default_mode); - Cvar_RegisterVariable (&_vid_default_mode_win); - Cvar_RegisterVariable (&vid_config_x); - Cvar_RegisterVariable (&vid_config_y); - Cvar_RegisterVariable (&vid_stretch_by_2); - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&vid_fullscreen_mode); - Cvar_RegisterVariable (&vid_windowed_mode); - Cvar_RegisterVariable (&block_switch); - Cvar_RegisterVariable (&vid_window_x); - Cvar_RegisterVariable (&vid_window_y); - - Cmd_AddCommand ("vid_testmode", VID_TestMode_f); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); - Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); - Cmd_AddCommand ("vid_windowed", VID_Windowed_f); - Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); - Cmd_AddCommand ("vid_minimize", VID_Minimize_f); - - if (COM_CheckParm ("-dibonly")) - dibonly = true; - - VID_InitMGLDIB (global_hInstance); - - basenummodes = nummodes; - - if (!dibonly) - VID_InitMGLFull (global_hInstance); - -// if there are no non-windowed modes, or only windowed and mode 0x13, then use -// fullscreen DIBs as well - if (((nummodes == basenummodes) || - ((nummodes == (basenummodes + 1)) && is_mode0x13)) && - !COM_CheckParm ("-nofulldib")) - - { - VID_InitFullDIB (global_hInstance); - } - - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - vid_testingmode = 0; - -// GDI doesn't let us remap palette index 0, so we'll remap color -// mappings from that black to another one - bestmatchmetric = 256*256*3; - - for (i=1 ; i<256 ; i++) - { - dr = palette[0] - palette[i*3]; - dg = palette[1] - palette[i*3+1]; - db = palette[2] - palette[i*3+2]; - - t = (dr * dr) + (dg * dg) + (db * db); - - if (t < bestmatchmetric) - { - bestmatchmetric = t; - bestmatch = i; - - if (t == 0) - break; - } - } - - for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) - { - if (*ptmp == 0) - *ptmp = bestmatch; - } - - if (COM_CheckParm("-startwindowed")) - { - startwindowed = 1; - vid_default = windowed_default; - } - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - -// sound initialization has to go here, preceded by a windowed mode set, -// so there's a window for DirectSound to work with but we're not yet -// fullscreen so the "hardware already in use" dialog is visible if it -// gets displayed - -// keep the window minimized until we're ready for the first real mode set - hide_window = true; - VID_SetMode (MODE_WINDOWED, palette); - hide_window = false; - S_Init (); - - vid_initialized = true; - - force_mode_set = true; - VID_SetMode (vid_default, palette); - force_mode_set = false; - - vid_realmode = vid_modenum; - - VID_SetPalette (palette); - - vid_menudrawfn = VID_MenuDraw; - vid_menukeyfn = VID_MenuKey; - - strcpy (badmode.modedesc, "Bad mode"); -} - - -void VID_Shutdown (void) -{ - HDC hdc; - int dummy; - - if (vid_initialized) - { - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - - AppActivate(false, false); - DestroyDIBWindow (); - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - - if (mainwindow) - DestroyWindow(mainwindow); - - MGL_exit(); - - vid_testingmode = 0; - vid_initialized = 0; - } -} - - -/* -================ -FlipScreen -================ -*/ -void FlipScreen(vrect_t *rects) -{ - HRESULT ddrval; - - // Flip the surfaces - - if (DDActive) - { - if (mgldc) - { - if (memdc) - { - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(mgldc, memdc, - rects->x, - rects->y, - rects->x + rects->width, - rects->y + rects->height, - rects->x << 1, - rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(mgldc, memdc, - rects->x, rects->y, - (rects->x + rects->width), - (rects->y + rects->height), - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - if (vid.numpages > 1) - { - // We have a flipping surface, so do a hard page flip - aPage = (aPage+1) % vid.numpages; - vPage = (vPage+1) % vid.numpages; - MGL_setActivePage(mgldc,aPage); - MGL_setVisualPage(mgldc,vPage,waitVRT); - } - } - } - else - { - HDC hdcScreen; - - hdcScreen = GetDC(mainwindow); - - if (windc && dibdc) - { - MGL_setWinDC(windc,hdcScreen); - - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x << 1, rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - ReleaseDC(mainwindow, hdcScreen); - } -} - - -void VID_Update (vrect_t *rects) -{ - vrect_t rect; - RECT trect; - - if (!vid_palettized && palette_changed) - { - palette_changed = false; - rect.x = 0; - rect.y = 0; - rect.width = vid.width; - rect.height = vid.height; - rect.pnext = NULL; - rects = ▭ - } - - if (firstupdate) - { - if (modestate == MS_WINDOWED) - { - GetWindowRect (mainwindow, &trect); - - if ((trect.left != (int)vid_window_x.value) || - (trect.top != (int)vid_window_y.value)) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - } - } - - if ((_vid_default_mode_win.value != vid_default) && - (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) - { - firstupdate = 0; - - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - if ((_vid_default_mode_win.value < 0) || - (_vid_default_mode_win.value >= nummodes)) - { - Cvar_SetValue ("_vid_default_mode_win", windowed_default); - } - - Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); - } - } - - // We've drawn the frame; copy it to the screen - FlipScreen (rects); - - if (vid_testingmode) - { - if (realtime >= vid_testendtime) - { - VID_SetMode (vid_realmode, vid_curpal); - vid_testingmode = 0; - } - } - else - { - if ((int)vid_mode.value != vid_realmode) - { - VID_SetMode ((int)vid_mode.value, vid_curpal); - Cvar_SetValue ("vid_mode", (float)vid_modenum); - // so if mode set fails, we don't keep on - // trying to set that mode - vid_realmode = vid_modenum; - } - } - -// handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) - { - if (!_windowed_mouse.value) { - if (windowed_mouse) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - windowed_mouse = false; - } else { - windowed_mouse = true; - if (key_dest == key_game && !mouseactive && ActiveApp) { - IN_ActivateMouse (); - IN_HideMouse (); - } else if (mouseactive && key_dest != key_game) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } -} - - -/* -================ -D_BeginDirectRect -================ -*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j> repshift) * width], - width); - } - } - - VID_UnlockBuffer (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height << repshift; - rect.pnext = NULL; - - FlipScreen (&rect); - } - else - { - // unlock if locked - if (lockcount > 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // save from and draw to screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jsurface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - width); - memcpy ((byte *)mgldc->surface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &pbitmap[(i >> repshift) * width], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -/* -================ -D_EndDirectRect -================ -*/ -void D_EndDirectRect (int x, int y, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // restore to the screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jsurface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &backingbuf[(i + j) * 24], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -//========================================================================== - -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_LEFTARROW,'5',K_RIGHTARROW,'+',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) -{ - key = (key>>16)&255; - if (key > 127) - return 0; - - return scantokey[key]; -} - -void AppActivate(BOOL fActive, BOOL minimize) -/**************************************************************************** -* -* Function: AppActivate -* Parameters: fActive - True if app is activating -* -* Description: If the application is activating, then swap the system -* into SYSPAL_NOSTATIC mode so that our palettes will display -* correctly. -* -****************************************************************************/ -{ - HDC hdc; - int i, t; - static BOOL sound_active; - - ActiveApp = fActive; - -// messy, but it seems to work - if (vid_fulldib_on_focus_mode) - { - Minimized = minimize; - - if (Minimized) - ActiveApp = false; - } - - MGL_appActivate(windc, ActiveApp); - - if (vid_initialized) - { - // yield the palette if we're losing the focus - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - { - if (ActiveApp) - { - if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - } - else if (pal_is_nostatic) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) - { - // switch back to SYSPAL_STATIC and the old mapping - SetSystemPaletteUse(hdc, SYSPAL_STATIC); - syscolchg = true; - } - - pal_is_nostatic = false; - } - } - - if (!Minimized) - VID_SetPalette (vid_curpal); - - scr_fullupdate = 0; - - ReleaseDC(NULL,hdc); - } - -// enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) - { - S_BlockSound (); - S_ClearBuffer (); - sound_active = false; - } - else if (ActiveApp && !sound_active) - { - S_UnblockSound (); - S_ClearBuffer (); - sound_active = true; - } - -// minimize/restore fulldib windows/mouse-capture normal windows on demand - if (!in_mode_set) - { - if (ActiveApp) - { - if (vid_fulldib_on_focus_mode) - { - if (vid_initialized) - { - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); - msg_suppress_1 = false; - - t = in_mode_set; - in_mode_set = true; - AppActivate (true, false); - in_mode_set = t; - } - - IN_ActivateMouse (); - IN_HideMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } - - if (!ActiveApp) - { - if (modestate == MS_FULLDIB) - { - if (vid_initialized) - { - force_minimized = true; - i = vid_fulldib_on_focus_mode; - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (windowed_default, vid_curpal); - msg_suppress_1 = false; - vid_fulldib_on_focus_mode = i; - force_minimized = false; - - // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll - // do it manually - t = in_mode_set; - in_mode_set = true; - AppActivate (false, true); - in_mode_set = t; - } - - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value /* && mouseactive */) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } -} - - -/* -================ -VID_HandlePause -================ -*/ -void VID_HandlePause (qboolean pause) -{ -#if 0 - if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - if (pause) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } -#endif -} - - -/* -=================================================================== - -MAIN WINDOW - -=================================================================== -*/ - -LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -/* main window procedure */ -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LONG lRet = 0; - int fwKeys, xPos, yPos, fActive, fMinimized, temp; - HDC hdc; - PAINTSTRUCT ps; - extern unsigned int uiWheelMessage; - static int recursiveflag; - - if ( uMsg == uiWheelMessage ) { - uMsg = WM_MOUSEWHEEL; - wParam <<= 16; - } - - - switch (uMsg) - { - case WM_CREATE: - break; - - case WM_SYSCOMMAND: - - // Check for maximize being hit - switch (wParam & ~0x0F) - { - case SC_MAXIMIZE: - // if minimized, bring up as a window before going fullscreen, - // so MGL will have the right state to restore - if (Minimized) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); - break; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - if (modestate != MS_WINDOWED) - { - // don't call DefWindowProc() because we don't want to start - // the screen saver fullscreen - break; - } - - // fall through windowed and allow the screen saver to start - - default: - if (!in_mode_set) - { - S_BlockSound (); - S_ClearBuffer (); - } - - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - - if (!in_mode_set) - { - S_UnblockSound (); - } - } - break; - - case WM_MOVE: - window_x = (int) LOWORD(lParam); - window_y = (int) HIWORD(lParam); - VID_UpdateWindowStatus (); - - if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) - VID_RememberWindowPos (); - - break; - - case WM_SIZE: - Minimized = false; - - if (!(wParam & SIZE_RESTORED)) - { - if (wParam & SIZE_MINIMIZED) - Minimized = true; - } - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening - break; - - case WM_ACTIVATE: - fActive = LOWORD(wParam); - fMinimized = (BOOL) HIWORD(wParam); - AppActivate(!(fActive == WA_INACTIVE), fMinimized); - - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - if (!in_mode_set) - { - if (windc) - MGL_activatePalette(windc,true); - - VID_SetPalette(vid_curpal); - } - - break; - - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - - if (!in_mode_set && host_initialized) - SCR_UpdateWholeScreen (); - - EndPaint(hWnd, &ps); - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (!in_mode_set) - Key_Event (MapKey(lParam), true); - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - if (!in_mode_set) - Key_Event (MapKey(lParam), false); - break; - - // 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: - if (!in_mode_set) - { - temp = 0; - - if (wParam & MK_LBUTTON) - temp |= 1; - - if (wParam & MK_RBUTTON) - temp |= 2; - - if (wParam & MK_MBUTTON) - temp |= 4; - - IN_MouseEvent (temp); - } - break; - // JACK: This is the mouse wheel with the Intellimouse - // Its delta is either positive or neg, and we generate the proper - // Event. - case WM_MOUSEWHEEL: - if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); - } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); - } - break; - // KJB: Added these new palette functions - case WM_PALETTECHANGED: - if ((HWND)wParam == hWnd) - break; - /* Fall through to WM_QUERYNEWPALETTE */ - case WM_QUERYNEWPALETTE: - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - ReleaseDC(NULL,hdc); - - scr_fullupdate = 0; - - if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) - { - VID_SetPalette (vid_curpal); - InvalidateRect (mainwindow, NULL, false); - - // specifically required if WM_QUERYNEWPALETTE realizes a new palette - lRet = TRUE; - } - break; - - case WM_DISPLAYCHANGE: - if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - break; - - case WM_CLOSE: - // this causes Close in the right-click task bar menu not to work, but right - // now bad things happen if Close is handled in that case (garbage and a - // crash on Win95) - if (!in_mode_set) - { - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - { - Sys_Quit (); - } - } - break; - - case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); - break; - - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - break; - } - - /* return 0 if handled message, 1 if not */ - return lRet; -} - - -extern void M_Menu_Options_f (void); -extern void M_Print (int cx, int cy, char *str); -extern void M_PrintWhite (int cx, int cy, char *str); -extern void M_DrawCharacter (int cx, int line, int num); -extern void M_DrawTransPic (int x, int y, qpic_t *pic); -extern void M_DrawPic (int x, int y, qpic_t *pic); - -static int vid_line, vid_wmodes; - -typedef struct -{ - int modenum; - char *desc; - int iscur; - int ismode13; - int width; -} modedesc_t; - -#define MAX_COLUMN_SIZE 5 -#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) -#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) - -static modedesc_t modedescs[MAX_MODEDESCS]; - -/* -================ -VID_MenuDraw -================ -*/ -void VID_MenuDraw (void) -{ - qpic_t *p; - char *ptr; - int lnummodes, i, j, k, column, row, dup, dupmode; - char temp[100]; - vmode_t *pv; - modedesc_t tmodedesc; - - p = Draw_CachePic ("gfx/vidmodes.lmp"); - M_DrawPic ( (320-p->width)/2, 4, p); - - for (i=0 ; i<3 ; i++) - { - ptr = VID_GetModeDescriptionMemCheck (i); - modedescs[i].modenum = modelist[i].modenum; - modedescs[i].desc = ptr; - modedescs[i].ismode13 = 0; - modedescs[i].iscur = 0; - - if (vid_modenum == i) - modedescs[i].iscur = 1; - } - - vid_wmodes = 3; - lnummodes = VID_NumModes (); - - for (i=3 ; iwidth != 360) || COM_CheckParm("-allow360"))) - { - dup = 0; - - for (j=3 ; jmode13; - modedescs[k].iscur = 0; - modedescs[k].width = pv->width; - - if (i == vid_modenum) - modedescs[k].iscur = 1; - - if (!dup) - vid_wmodes++; - } - } - } - } - -// sort the modes on width (to handle picking up oddball dibonly modes -// after all the others) - for (i=3 ; i<(vid_wmodes-1) ; i++) - { - for (j=(i+1) ; j modedescs[j].width) - { - tmodedesc = modedescs[i]; - modedescs[i] = modedescs[j]; - modedescs[j] = tmodedesc; - } - } - } - - - M_Print (13*8, 36, "Windowed Modes"); - - column = 16; - row = 36+2*8; - - for (i=0 ; i<3; i++) - { - if (modedescs[i].iscur) - M_PrintWhite (column, row, modedescs[i].desc); - else - M_Print (column, row, modedescs[i].desc); - - column += 13*8; - } - - if (vid_wmodes > 3) - { - M_Print (12*8, 36+4*8, "Fullscreen Modes"); - - column = 16; - row = 36+6*8; - - for (i=3 ; i= 3) - row += 3*8; - - M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); - } -} - - -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) -{ - if (vid_testingmode) - return; - - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; - - case K_LEFTARROW: - - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 2) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = vid_wmodes - 1; - break; - - case K_RIGHTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 4) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; - break; - - case K_UPARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line -= VID_ROW_SIZE; - - if (vid_line < 0) - { - vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line >= vid_wmodes) - vid_line -= VID_ROW_SIZE; - } - break; - - case K_DOWNARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line += VID_ROW_SIZE; - - if (vid_line >= vid_wmodes) - { - vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line < 0) - vid_line += VID_ROW_SIZE; - } - break; - - case K_ENTER: - S_LocalSound ("misc/menu1.wav"); - VID_SetMode (modedescs[vid_line].modenum, vid_curpal); - break; - - case 'T': - case 't': - S_LocalSound ("misc/menu1.wav"); - // have to set this before setting the mode because WM_PAINT - // happens during the mode set and does a VID_Update, which - // checks vid_testingmode - vid_testingmode = 1; - vid_testendtime = realtime + 5.0; - - if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) - { - vid_testingmode = 0; - } - break; - - case 'D': - case 'd': - S_LocalSound ("misc/menu1.wav"); - firstupdate = 0; - Cvar_SetValue ("_vid_default_mode_win", vid_modenum); - break; - - default: - break; - } -} +/* +Copyright (C) 1996-1997 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. + +*/ +// vid_win.c -- Win32 video driver + +#include "quakedef.h" +#include "winquake.h" +#include "d_local.h" +#include "resource.h" + +#define MINIMUM_MEMORY 0x550000 + +#define MAX_MODE_LIST 30 +#define VID_ROW_SIZE 3 + +qboolean dibonly; + +extern int Minimized; + +HWND mainwindow; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); + +int DIBWidth, DIBHeight; +qboolean DDActive; +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +int window_center_x, window_center_y, window_x, window_y, window_width, window_height; +RECT window_rect; + +static DEVMODE gdevmode; +static qboolean startwindowed = 0, windowed_mode_set; +static int firstupdate = 1; +static qboolean vid_initialized = false, vid_palettized; +static int lockcount; +static int vid_fulldib_on_focus_mode; +static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; +static int vid_stretched, windowed_mouse; +static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; +static HICON hIcon; + +qboolean mouseactive; // from in_win.c + +viddef_t vid; // global video state + +#define MODE_WINDOWED 0 +#define MODE_SETTABLE_WINDOW 2 +#define NO_MODE (MODE_WINDOWED - 1) +#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) + +// Note that 0 is MODE_WINDOWED +cvar_t vid_mode = {"vid_mode","0", false}; +// Note that 0 is MODE_WINDOWED +cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; +// Note that 3 is MODE_FULLSCREEN_DEFAULT +cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; +cvar_t vid_wait = {"vid_wait","0"}; +cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; +cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; +cvar_t vid_config_x = {"vid_config_x","800", true}; +cvar_t vid_config_y = {"vid_config_y","600", true}; +cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; +cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; +cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; +cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; +cvar_t block_switch = {"block_switch","0", true}; +cvar_t vid_window_x = {"vid_window_x", "0", true}; +cvar_t vid_window_y = {"vid_window_y", "0", true}; + +typedef struct { + int width; + int height; +} lmode_t; + +lmode_t lowresmodes[] = { + {320, 200}, + {320, 240}, + {400, 300}, + {512, 384}, +}; + +int vid_modenum = NO_MODE; +int vid_testingmode, vid_realmode; +double vid_testendtime; +int vid_default = MODE_WINDOWED; +static int windowed_default; + +modestate_t modestate = MS_UNINIT; + +static byte *vid_surfcache; +static int vid_surfcachesize; +static int VID_highhunkmark; + +unsigned char vid_curpal[256*3]; + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; + +int driver = grDETECT,mode; +bool useWinDirect = true, useDirectDraw = true; +MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; + +typedef struct { + modestate_t type; + int width; + int height; + int modenum; + int mode13; + int stretched; + int dib; + int fullscreen; + int bpp; + int halfscreen; + char modedesc[13]; +} vmode_t; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; +static vmode_t *pcurrentmode; + +int aPage; // Current active display page +int vPage; // Current visible display page +int waitVRT = true; // True to wait for retrace on flip + +static vmode_t badmode; + +static byte backingbuf[48*24]; + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void AppActivate(BOOL fActive, BOOL minimize); + + +/* +================ +VID_RememberWindowPos +================ +*/ +void VID_RememberWindowPos (void) +{ + RECT rect; + + if (GetWindowRect (mainwindow, &rect)) + { + if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && + (rect.top < GetSystemMetrics (SM_CYSCREEN)) && + (rect.right > 0) && + (rect.bottom > 0)) + { + Cvar_SetValue ("vid_window_x", (float)rect.left); + Cvar_SetValue ("vid_window_y", (float)rect.top); + } + } +} + + +/* +================ +VID_CheckWindowXY +================ +*/ +void VID_CheckWindowXY (void) +{ + + if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + ((int)vid_window_x.value < 0) || + ((int)vid_window_y.value < 0)) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0 ); + } +} + + +/* +================ +VID_UpdateWindowStatus +================ +*/ +void VID_UpdateWindowStatus (void) +{ + + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + + IN_UpdateClipCursor (); +} + + +/* +================ +ClearAllStates +================ +*/ +void ClearAllStates (void) +{ + int i; + +// send an up event for each key, to make sure the server clears them all + for (i=0 ; i<256 ; i++) + { + Key_Event (i, false); + } + + Key_ClearStates (); + IN_ClearStates (); +} + + +/* +================ +VID_CheckAdequateMem +================ +*/ +qboolean VID_CheckAdequateMem (int width, int height) +{ + int tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + tbuffersize += D_SurfaceCacheForRes (width, height); + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < MINIMUM_MEMORY) + { + return false; // not enough memory for mode + } + + return true; +} + + +/* +================ +VID_AllocBuffers +================ +*/ +qboolean VID_AllocBuffers (int width, int height) +{ + int tsize, tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + tsize = D_SurfaceCacheForRes (width, height); + + tbuffersize += tsize; + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < MINIMUM_MEMORY) + { + Con_SafePrintf ("Not enough memory for video mode\n"); + return false; // not enough memory for mode + } + + vid_surfcachesize = tsize; + + if (d_pzbuffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (VID_highhunkmark); + d_pzbuffer = NULL; + } + + VID_highhunkmark = Hunk_HighMark (); + + d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); + + vid_surfcache = (byte *)d_pzbuffer + + width * height * sizeof (*d_pzbuffer); + + return true; +} + + +void initFatalError(void) +{ + MGL_exit(); + MGL_fatalError(MGL_errorMsg(MGL_result())); + exit(EXIT_FAILURE); +} + +#if 0 //def NEW_SUSPEND + +int VID_Suspend (MGLDC *dc, int flags) +{ + int i; + if (flags & MGL_DEACTIVATE) + { + IN_RestoreOriginalMouseState (); + CDAudio_Pause (); + + // keep WM_PAINT from trying to redraw + in_mode_set = true; + block_drawing = true; + } + else if (flags & MGL_REACTIVATE) + { + IN_SetQuakeMouseState (); + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + CDAudio_Resume (); + in_mode_set = false; + + block_drawing = false; +// vid.recalc_refdef = 1; + force_mode_set = 1; + i = msg_suppress_1; + msg_suppress_1 = 1; + VID_Fullscreen_f(); + msg_suppress_1 = i; + force_mode_set = 0; + } + + return 1; +} + +#else + +int VID_Suspend (MGLDC *dc, int flags) +{ + + if (flags & MGL_DEACTIVATE) + { + // FIXME: this doesn't currently work on NT + if (block_switch.value && !WinNT) + { + return MGL_NO_DEACTIVATE; + } + + S_BlockSound (); + S_ClearBuffer (); + + IN_RestoreOriginalMouseState (); + CDAudio_Pause (); + + // keep WM_PAINT from trying to redraw + in_mode_set = true; + + block_drawing = true; // so we don't try to draw while switched away + + return MGL_NO_SUSPEND_APP; + } + else if (flags & MGL_REACTIVATE) + { + IN_SetQuakeMouseState (); + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + CDAudio_Resume (); + S_UnblockSound (); + + in_mode_set = false; + + vid.recalc_refdef = 1; + + block_drawing = false; + + return MGL_NO_SUSPEND_APP; + } + +} +#endif + + +void registerAllDispDrivers(void) +{ + /* Event though these driver require WinDirect, we register + * them so that they will still be available even if DirectDraw + * is present and the user has disable the high performance + * WinDirect modes. + */ + MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); +// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); + + /* Register display drivers */ + if (useWinDirect) + { +//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); + MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); + + if (!COM_CheckParm ("-novbeaf")) + MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); + } + + if (useDirectDraw) + { + MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); + } +} + + +void registerAllMemDrivers(void) +{ + /* Register memory context drivers */ + MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); +} + + +void VID_InitMGLFull (HINSTANCE hInstance) +{ + int i, xRes, yRes, bits, vMode, lowres, curmode, temp; + int lowstretchedres, stretchedmode, lowstretched; + uchar *m; + +// FIXME: NT is checked for because MGL currently has a bug that causes it +// to try to use WinDirect modes even on NT + if (COM_CheckParm("-nowindirect") || + COM_CheckParm("-nowd") || + COM_CheckParm("-novesa") || + WinNT) + { + useWinDirect = false; + } + + if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) + useDirectDraw = false; + + // Initialise the MGL + MGL_unregisterAllDrivers(); + registerAllDispDrivers(); + registerAllMemDrivers(); + MGL_detectGraph(&driver,&mode); + m = MGL_availableModes(); + + if (m[0] != 0xFF) + { + lowres = lowstretchedres = 99999; + lowstretched = 0; + curmode = 0; + + // find the lowest-res mode, or a mode we can stretch up to and get + // lowest-res that way + for (i = 0; m[i] != 0xFF; i++) + { + MGL_modeResolution(m[i], &xRes, &yRes,&bits); + + if ((bits == 8) && + (xRes <= MAXWIDTH) && + (yRes <= MAXHEIGHT) && + (curmode < MAX_MODE_LIST)) + { + if (m[i] == grVGA_320x200x256) + is_mode0x13 = true; + + if (!COM_CheckParm("-noforcevga")) + { + if (m[i] == grVGA_320x200x256) + { + mode = i; + break; + } + } + + if (xRes < lowres) + { + lowres = xRes; + mode = i; + } + + if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) + { + lowstretchedres = xRes >> 1; + stretchedmode = i; + } + } + + curmode++; + } + + // if there's a mode we can stretch by 2 up to, thereby effectively getting + // a lower-res mode than the lowest-res real but still at least 320x200, that + // will be our default mode + if (lowstretchedres < lowres) + { + mode = stretchedmode; + lowres = lowstretchedres; + lowstretched = 1; + } + + // build the mode list, leaving room for the low-res stretched mode, if any + nummodes++; // leave room for default mode + + for (i = 0; m[i] != 0xFF; i++) + { + MGL_modeResolution(m[i], &xRes, &yRes,&bits); + + if ((bits == 8) && + (xRes <= MAXWIDTH) && + (yRes <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) + { + if (i == mode) + { + if (lowstretched) + { + stretchedmode = nummodes; + curmode = nummodes++; + } + else + { + curmode = MODE_FULLSCREEN_DEFAULT; + } + } + else + { + curmode = nummodes++; + } + + modelist[curmode].type = MS_FULLSCREEN; + modelist[curmode].width = xRes; + modelist[curmode].height = yRes; + sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); + + if (m[i] == grVGA_320x200x256) + modelist[curmode].mode13 = 1; + else + modelist[curmode].mode13 = 0; + + modelist[curmode].modenum = m[i]; + modelist[curmode].stretched = 0; + modelist[curmode].dib = 0; + modelist[curmode].fullscreen = 1; + modelist[curmode].halfscreen = 0; + modelist[curmode].bpp = 8; + } + } + + if (lowstretched) + { + modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; + modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; + modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; + modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; + sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", + modelist[MODE_FULLSCREEN_DEFAULT].width, + modelist[MODE_FULLSCREEN_DEFAULT].height); + } + + vid_default = MODE_FULLSCREEN_DEFAULT; + + temp = m[0]; + + if (!MGL_init(&driver, &temp, "")) + { + initFatalError(); + } + } + + MGL_setSuspendAppCallback(VID_Suspend); +} + + +MGLDC *createDisplayDC(int forcemem) +/**************************************************************************** +* +* Function: createDisplayDC +* Returns: Pointer to the MGL device context to use for the application +* +* Description: Initialises the MGL and creates an appropriate display +* device context to be used by the GUI. This creates and +* apropriate device context depending on the system being +* compile for, and should be the only place where system +* specific code is required. +* +****************************************************************************/ +{ + MGLDC *dc; + pixel_format_t pf; + int npages; + + // Start the specified video mode + if (!MGL_changeDisplayMode(mode)) + initFatalError(); + + npages = MGL_availablePages(mode); + + if (npages > 3) + npages = 3; + + if (!COM_CheckParm ("-notriplebuf")) + { + if (npages > 2) + { + npages = 2; + } + } + + if ((dc = MGL_createDisplayDC(npages)) == NULL) + return NULL; + + if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) + { + MGL_makeCurrentDC(dc); + memdc = NULL; + } + else + { + // Set up for blitting from a memory buffer + memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); + MGL_makeCurrentDC(memdc); + } + + // Enable page flipping even for even for blitted surfaces + if (forcemem) + { + vid.numpages = 1; + } + else + { + vid.numpages = dc->mi.maxPage + 1; + + if (vid.numpages > 1) + { + // Set up for page flipping + MGL_setActivePage(dc, aPage = 1); + MGL_setVisualPage(dc, vPage = 0, false); + } + + if (vid.numpages > 3) + vid.numpages = 3; + } + + if (vid.numpages == 2) + waitVRT = true; + else + waitVRT = false; + + return dc; +} + + +void VID_InitMGLDIB (HINSTANCE hInstance) +{ + WNDCLASS wc; + HDC hdc; + int i; + + hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + /* Register the frame class */ + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = "WinQuake"; + + if (!RegisterClass (&wc) ) + Sys_Error ("Couldn't register window class"); + + /* Find the size for the DIB window */ + /* Initialise the MGL for windowed operation */ + MGL_setAppInstance(hInstance); + registerAllMemDrivers(); + MGL_initWindowed(""); + + modelist[0].type = MS_WINDOWED; + modelist[0].width = 320; + modelist[0].height = 240; + strcpy (modelist[0].modedesc, "320x240"); + modelist[0].mode13 = 0; + modelist[0].modenum = MODE_WINDOWED; + modelist[0].stretched = 0; + modelist[0].dib = 1; + modelist[0].fullscreen = 0; + modelist[0].halfscreen = 0; + modelist[0].bpp = 8; + + modelist[1].type = MS_WINDOWED; + modelist[1].width = 640; + modelist[1].height = 480; + strcpy (modelist[1].modedesc, "640x480"); + modelist[1].mode13 = 0; + modelist[1].modenum = MODE_WINDOWED + 1; + modelist[1].stretched = 1; + modelist[1].dib = 1; + modelist[1].fullscreen = 0; + modelist[1].halfscreen = 0; + modelist[1].bpp = 8; + + modelist[2].type = MS_WINDOWED; + modelist[2].width = 800; + modelist[2].height = 600; + strcpy (modelist[2].modedesc, "800x600"); + modelist[2].mode13 = 0; + modelist[2].modenum = MODE_WINDOWED + 2; + modelist[2].stretched = 1; + modelist[2].dib = 1; + modelist[2].fullscreen = 0; + modelist[2].halfscreen = 0; + modelist[2].bpp = 8; + +// automatically stretch the default mode up if > 640x480 desktop resolution + hdc = GetDC(NULL); + + if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) + { + vid_default = MODE_WINDOWED + 1; + } + else + { + vid_default = MODE_WINDOWED; + } + + windowed_default = vid_default; + + ReleaseDC(NULL,hdc); + + nummodes = 3; // reserve space for windowed mode + + DDActive = 0; +} + + +/* +================= +VID_InitFullDIB +================= +*/ +void VID_InitFullDIB (HINSTANCE hInstance) +{ + DEVMODE devmode; + int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; + int numlowresmodes, bpp, done; + int cstretch, istretch, mstretch; + BOOL stat; + +// enumerate 8 bpp modes + originalnummodes = nummodes; + modenum = 0; + lowestres = 99999; + + do + { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((devmode.dmBitsPerPel == 8) && + (devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) + { + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].mode13 = 0; + modelist[nummodes].stretched = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = devmode.dmBitsPerPel; + sprintf (modelist[nummodes].modedesc, "%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight); + + // if the width is more than twice the height, reduce it by half because this + // is probably a dual-screen monitor + if (!COM_CheckParm("-noadjustaspect")) + { + if (modelist[nummodes].width > (modelist[nummodes].height << 1)) + { + modelist[nummodes].width >>= 1; + modelist[nummodes].halfscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i=originalnummodes, existingmode = 0 ; i 8 bpp + if (nummodes == originalnummodes) + { + modenum = 0; + lowestres = 99999; + + Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); + + do + { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((((devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT)) || + (!COM_CheckParm("-noadjustaspect") && + (devmode.dmPelsWidth <= (MAXWIDTH*2)) && + (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && + (nummodes < MAX_MODE_LIST) && + (devmode.dmBitsPerPel > 8)) + { + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].mode13 = 0; + modelist[nummodes].stretched = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = devmode.dmBitsPerPel; + sprintf (modelist[nummodes].modedesc, "%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight); + + // if the width is more than twice the height, reduce it by half because this + // is probably a dual-screen monitor + if (!COM_CheckParm("-noadjustaspect")) + { + if (modelist[nummodes].width > (modelist[nummodes].height*2)) + { + modelist[nummodes].width >>= 1; + modelist[nummodes].halfscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i=originalnummodes, existingmode = 0 ; i= modelist[i].bpp)) + { + existingmode = 1; + break; + } + } + + if (!existingmode) + { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; + } + } + } + + switch (bpp) + { + case 8: + bpp = 16; + break; + + case 16: + bpp = 32; + break; + + case 32: + done = 1; + break; + } + } + +// now add the lowest stretch-by-2 pseudo-modes between 320-wide +// (inclusive) and lowest real res (not inclusive) +// don't bother if we have a real VGA mode 0x13 mode + if (!is_mode0x13) + { + for (i=originalnummodes, cstretch=0 ; i> 1) < lowestres) && + ((modelist[i].width >> 1) >= 320)) + { + lowestres = modelist[i].width >> 1; + cstretch = 1; + mstretch = i; + } + } + + if ((nummodes + cstretch) > MAX_MODE_LIST) + cstretch = MAX_MODE_LIST - nummodes; + + if (cstretch > 0) + { + for (i=(nummodes-1) ; i>=originalnummodes ; i--) + modelist[i+cstretch] = modelist[i]; + + nummodes += cstretch; + istretch = originalnummodes; + + modelist[istretch] = modelist[mstretch]; + modelist[istretch].width >>= 1; + modelist[istretch].height >>= 1; + modelist[istretch].stretched = 1; + sprintf (modelist[istretch].modedesc, "%dx%d", + modelist[istretch].width, modelist[istretch].height); + } + } + + if (nummodes != originalnummodes) + vid_default = MODE_FULLSCREEN_DEFAULT; + else + Con_SafePrintf ("No fullscreen DIB modes found\n"); +} + + +/* +================= +VID_NumModes +================= +*/ +int VID_NumModes (void) +{ + return nummodes; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t *VID_GetModePtr (int modenum) +{ + + if ((modenum >= 0) && (modenum < nummodes)) + return &modelist[modenum]; + else + return &badmode; +} + + +/* +================= +VID_CheckModedescFixup +================= +*/ +void VID_CheckModedescFixup (int mode) +{ + int x, y, stretch; + + if (mode == MODE_SETTABLE_WINDOW) + { + modelist[mode].stretched = (int)vid_stretch_by_2.value; + stretch = modelist[mode].stretched; + + if (vid_config_x.value < (320 << stretch)) + vid_config_x.value = 320 << stretch; + + if (vid_config_y.value < (200 << stretch)) + vid_config_y.value = 200 << stretch; + + x = (int)vid_config_x.value; + y = (int)vid_config_y.value; + sprintf (modelist[mode].modedesc, "%dx%d", x, y); + modelist[mode].width = x; + modelist[mode].height = y; + } +} + + +/* +================= +VID_GetModeDescriptionMemCheck +================= +*/ +char *VID_GetModeDescriptionMemCheck (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + + if (VID_CheckAdequateMem (pv->width, pv->height)) + { + return pinfo; + } + else + { + return NULL; + } +} + + +/* +================= +VID_GetModeDescription +================= +*/ +char *VID_GetModeDescription (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + return pinfo; +} + + +/* +================= +VID_GetModeDescription2 + +Tacks on "windowed" or "fullscreen" +================= +*/ +char *VID_GetModeDescription2 (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLSCREEN) + { + sprintf(pinfo,"%s fullscreen", pv->modedesc); + } + else if (modelist[mode].type == MS_FULLDIB) + { + sprintf(pinfo,"%s fullscreen", pv->modedesc); + } + else + { + sprintf(pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +// KJB: Added this to return the mode driver name in description for console + +char *VID_GetExtModeDescription (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + if (modelist[mode].type == MS_FULLSCREEN) + { + sprintf(pinfo,"%s fullscreen %s",pv->modedesc, + MGL_modeDriverName(pv->modenum)); + } + else if (modelist[mode].type == MS_FULLDIB) + { + sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); + } + else + { + sprintf(pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +void DestroyDIBWindow (void) +{ + + if (modestate == MS_WINDOWED) + { + // destroy the associated MGL DC's; the window gets reused + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + } +} + + +void DestroyFullscreenWindow (void) +{ + + if (modestate == MS_FULLSCREEN) + { + // destroy the existing fullscreen mode and DC's + if (mgldc) + MGL_destroyDC (mgldc); + if (memdc) + MGL_destroyDC (memdc); + mgldc = memdc = NULL; + } +} + + + +void DestroyFullDIBWindow (void) +{ + if (modestate == MS_FULLDIB) + { + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + // Destroy the fullscreen DIB window and associated MGL DC's + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + } +} + + +qboolean VID_SetWindowedMode (int modenum) +{ + HDC hdc; + pixel_format_t pf; + qboolean stretched; + int lastmodestate; + LONG wlong; + + if (!windowed_mode_set) + { + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + windowed_mode_set; + } + + VID_CheckModedescFixup (modenum); + + DDActive = 0; + lastmodestate = modestate; + + DestroyFullscreenWindow (); + DestroyFullDIBWindow (); + + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + +// KJB: Signal to the MGL that we are going back to windowed mode + if (!MGL_changeDisplayMode(grWINDOWED)) + initFatalError(); + + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + stretched = modelist[modenum].stretched; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + if (stretched) + { + DIBWidth >>= 1; + DIBHeight >>= 1; + } + + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN; + ExWindowStyle = 0; + AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); + +// the first time we're called to set the mode, create the window we'll use +// for the rest of the session + if (!vid_mode_set) + { + mainwindow = CreateWindowEx ( + ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, + NULL, + global_hInstance, + NULL); + + if (!mainwindow) + Sys_Error ("Couldn't create DIB window"); + + // tell MGL to use this window for fullscreen modes + MGL_registerFullScreenWindow (mainwindow); + + vid_mode_set = true; + } + else + { + SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); + } + + if (!SetWindowPos (mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER | + SWP_HIDEWINDOW)) + { + Sys_Error ("Couldn't resize DIB window"); + } + + if (hide_window) + return true; + +// position and show the DIB window + VID_CheckWindowXY (); + SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, + (int)vid_window_y.value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + + if (force_minimized) + ShowWindow (mainwindow, SW_MINIMIZE); + else + ShowWindow (mainwindow, SW_SHOWDEFAULT); + + UpdateWindow (mainwindow); + + modestate = MS_WINDOWED; + vid_fulldib_on_focus_mode = 0; + +// because we have set the background brush for the window to NULL +// (to avoid flickering when re-sizing the window on the desktop), +// we clear the window to black when created, otherwise it will be +// empty while Quake starts up. + hdc = GetDC(mainwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(mainwindow, hdc); + + /* Create the MGL window DC and the MGL memory DC */ + if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) + MGL_fatalError("Unable to create Windowed DC!"); + + if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) + MGL_fatalError("Unable to create Memory DC!"); + + MGL_makeCurrentDC(dibdc); + + vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; + vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; + vid.numpages = 1; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.height = vid.conheight = DIBHeight; + vid.width = vid.conwidth = DIBWidth; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = stretched; + + SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + + return true; +} + + +qboolean VID_SetFullscreenMode (int modenum) +{ + + DDActive = 1; + + DestroyDIBWindow (); + DestroyFullDIBWindow (); + + mode = modelist[modenum].modenum; + + // Destroy old DC's, resetting back to fullscreen mode + if (mgldc) + MGL_destroyDC (mgldc); + if (memdc) + MGL_destroyDC (memdc); + mgldc = memdc = NULL; + + if ((mgldc = createDisplayDC (modelist[modenum].stretched || + (int)vid_nopageflip.value)) == NULL) + { + return false; + } + + modestate = MS_FULLSCREEN; + vid_fulldib_on_focus_mode = 0; + + vid.buffer = vid.conbuffer = vid.direct = NULL; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + DIBHeight = vid.height = vid.conheight = modelist[modenum].height; + DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = modelist[modenum].stretched; + +// needed because we're not getting WM_MOVE messages fullscreen on NT + window_x = 0; + window_y = 0; + +// set the large icon, so the Quake icon will show up in the taskbar + SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); + +// shouldn't be needed, but Kendall needs to let us get the activation +// message for this not to be needed on NT + AppActivate (true, false); + + return true; +} + + +qboolean VID_SetFullDIBMode (int modenum) +{ + HDC hdc; + pixel_format_t pf; + int lastmodestate; + + DDActive = 0; + + DestroyFullscreenWindow (); + DestroyDIBWindow (); + + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + + // KJB: Signal to the MGL that we are going back to windowed mode + if (!MGL_changeDisplayMode(grWINDOWED)) + initFatalError(); + + gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + gdevmode.dmBitsPerPel = modelist[modenum].bpp; + gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << + modelist[modenum].halfscreen; + gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; + gdevmode.dmSize = sizeof (gdevmode); + + if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + Sys_Error ("Couldn't set fullscreen DIB mode"); + + lastmodestate = modestate; + modestate = MS_FULLDIB; + vid_fulldib_on_focus_mode = modenum; + + WindowRect.top = WindowRect.left = 0; + + hdc = GetDC(NULL); + + WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; + WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; + + ReleaseDC(NULL,hdc); + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + ExWindowStyle = 0; + AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); + + SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); + + if (!SetWindowPos (mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER)) + { + Sys_Error ("Couldn't resize DIB window"); + } + +// position and show the DIB window + SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); + ShowWindow (mainwindow, SW_SHOWDEFAULT); + UpdateWindow (mainwindow); + + // Because we have set the background brush for the window to NULL + // (to avoid flickering when re-sizing the window on the desktop), we + // clear the window to black when created, otherwise it will be + // empty while Quake starts up. + hdc = GetDC(mainwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(mainwindow, hdc); + + /* Create the MGL window DC and the MGL memory DC */ + if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) + MGL_fatalError("Unable to create Fullscreen DIB DC!"); + + if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) + MGL_fatalError("Unable to create Memory DC!"); + + MGL_makeCurrentDC(dibdc); + + vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; + vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; + vid.numpages = 1; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.height = vid.conheight = DIBHeight; + vid.width = vid.conwidth = DIBWidth; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = modelist[modenum].stretched; + +// needed because we're not getting WM_MOVE messages fullscreen on NT + window_x = 0; + window_y = 0; + + return true; +} + + +void VID_RestoreOldMode (int original_mode) +{ + static qboolean inerror = false; + + if (inerror) + return; + + in_mode_set = false; + inerror = true; + +// make sure mode set happens (video mode changes) + vid_modenum = original_mode - 1; + + if (!VID_SetMode (original_mode, vid_curpal)) + { + vid_modenum = MODE_WINDOWED - 1; + + if (!VID_SetMode (windowed_default, vid_curpal)) + Sys_Error ("Can't set any video mode"); + } + + inerror = false; +} + + +void VID_SetDefaultMode (void) +{ + + if (vid_initialized) + VID_SetMode (0, vid_curpal); + + IN_DeactivateMouse (); +} + + +int VID_SetMode (int modenum, unsigned char *palette) +{ + int original_mode, temp, dummy; + qboolean stat; + MSG msg; + HDC hdc; + + while ((modenum >= nummodes) || (modenum < 0)) + { + if (vid_modenum == NO_MODE) + { + if (modenum == vid_default) + { + modenum = windowed_default; + } + else + { + modenum = vid_default; + } + + Cvar_SetValue ("vid_mode", (float)modenum); + } + else + { + Cvar_SetValue ("vid_mode", (float)vid_modenum); + return 0; + } + } + + if (!force_mode_set && (modenum == vid_modenum)) + return true; + +// so Con_Printfs don't mess us up by forcing vid and snd updates + temp = scr_disabled_for_loading; + scr_disabled_for_loading = true; + in_mode_set = true; + + CDAudio_Pause (); + S_ClearBuffer (); + + if (vid_modenum == NO_MODE) + original_mode = windowed_default; + else + original_mode = vid_modenum; + + // Set either the fullscreen or windowed mode + if (modelist[modenum].type == MS_WINDOWED) + { + if (_windowed_mouse.value && key_dest == key_game) + { + stat = VID_SetWindowedMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + IN_DeactivateMouse (); + IN_ShowMouse (); + stat = VID_SetWindowedMode(modenum); + } + } + else if (modelist[modenum].type == MS_FULLDIB) + { + stat = VID_SetFullDIBMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + stat = VID_SetFullscreenMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + + window_width = vid.width << vid_stretched; + window_height = vid.height << vid_stretched; + VID_UpdateWindowStatus (); + + CDAudio_Resume (); + scr_disabled_for_loading = temp; + + if (!stat) + { + VID_RestoreOldMode (original_mode); + return false; + } + + if (hide_window) + return true; + +// now we try to make sure we get the focus on the mode switch, because +// sometimes in some systems we don't. We grab the foreground, then +// finish setting up, pump all our messages, and sleep for a little while +// to let messages finish bouncing around the system, then we put +// ourselves at the top of the z order, then grab the foreground again, +// Who knows if it helps, but it probably doesn't hurt + if (!force_minimized) + SetForegroundWindow (mainwindow); + + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + VID_SetPalette (palette); + + ReleaseDC(NULL,hdc); + + vid_modenum = modenum; + Cvar_SetValue ("vid_mode", (float)vid_modenum); + + if (!VID_AllocBuffers (vid.width, vid.height)) + { + // couldn't get memory for this mode; try to fall back to previous mode + VID_RestoreOldMode (original_mode); + return false; + } + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + if (!force_minimized) + { + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (mainwindow); + } + +// fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!msg_suppress_1) + Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum)); + + VID_SetPalette (palette); + + in_mode_set = false; + vid.recalc_refdef = 1; + + return true; +} + +void VID_LockBuffer (void) +{ + + if (dibdc) + return; + + lockcount++; + + if (lockcount > 1) + return; + + MGL_beginDirectAccess(); + + if (memdc) + { + // Update surface pointer for linear access modes + vid.buffer = vid.conbuffer = vid.direct = memdc->surface; + vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; + } + else if (mgldc) + { + // Update surface pointer for linear access modes + vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; + vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; + } + + if (r_dowarp) + d_viewbuffer = r_warpbuffer; + else + d_viewbuffer = (void *)(byte *)vid.buffer; + + if (r_dowarp) + screenwidth = WARP_WIDTH; + else + screenwidth = vid.rowbytes; + + if (lcd_x.value) + screenwidth <<= 1; +} + + +void VID_UnlockBuffer (void) +{ + if (dibdc) + return; + + lockcount--; + + if (lockcount > 0) + return; + + if (lockcount < 0) + Sys_Error ("Unbalanced unlock"); + + MGL_endDirectAccess(); + +// to turn up any unlocked accesses + vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; + +} + + +int VID_ForceUnlockedAndReturnState (void) +{ + int lk; + + if (!lockcount) + return 0; + + lk = lockcount; + + if (dibdc) + { + lockcount = 0; + } + else + { + lockcount = 1; + VID_UnlockBuffer (); + } + + return lk; +} + + +void VID_ForceLockState (int lk) +{ + + if (!dibdc && lk) + { + lockcount = 0; + VID_LockBuffer (); + } + + lockcount = lk; +} + + +void VID_SetPalette (unsigned char *palette) +{ + INT i; + palette_t pal[256]; + HDC hdc; + + if (!Minimized) + { + palette_changed = true; + + // make sure we have the static colors if we're the active app + hdc = GetDC(NULL); + + if (vid_palettized && ActiveApp) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) + { + // switch to SYSPAL_NOSTATIC and remap the colors + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + syscolchg = true; + pal_is_nostatic = true; + } + } + + ReleaseDC(NULL,hdc); + + // Translate the palette values to an MGL palette array and + // set the values. + for (i = 0; i < 256; i++) + { + pal[i].red = palette[i*3]; + pal[i].green = palette[i*3+1]; + pal[i].blue = palette[i*3+2]; + } + + if (DDActive) + { + if (!mgldc) + return; + + MGL_setPalette(mgldc,pal,256,0); + MGL_realizePalette(mgldc,256,0,false); + if (memdc) + MGL_setPalette(memdc,pal,256,0); + } + else + { + if (!windc) + return; + + MGL_setPalette(windc,pal,256,0); + MGL_realizePalette(windc,256,0,false); + if (dibdc) + { + MGL_setPalette(dibdc,pal,256,0); + MGL_realizePalette(dibdc,256,0,false); + } + } + } + + memcpy (vid_curpal, palette, sizeof(vid_curpal)); + + if (syscolchg) + { + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); + syscolchg = false; + } +} + + +void VID_ShiftPalette (unsigned char *palette) +{ + VID_SetPalette (palette); +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void VID_DescribeCurrentMode_f (void) +{ + Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); +} + + +/* +================= +VID_NumModes_f +================= +*/ +void VID_NumModes_f (void) +{ + + if (nummodes == 1) + Con_Printf ("%d video mode is available\n", nummodes); + else + Con_Printf ("%d video modes are available\n", nummodes); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void VID_DescribeMode_f (void) +{ + int modenum; + + modenum = Q_atoi (Cmd_Argv(1)); + + Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void VID_DescribeModes_f (void) +{ + int i, lnummodes; + char *pinfo; + qboolean na; + vmode_t *pv; + + na = false; + + lnummodes = VID_NumModes (); + + for (i=0 ; iwidth, pv->height)) + { + Con_Printf ("%2d: %s\n", i, pinfo); + } + else + { + Con_Printf ("**: %s\n", pinfo); + na = true; + } + } + + if (na) + { + Con_Printf ("\n[**: not enough system RAM for mode]\n"); + } +} + + +/* +================= +VID_TestMode_f +================= +*/ +void VID_TestMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) + { + modenum = Q_atoi (Cmd_Argv(1)); + + if (VID_SetMode (modenum, vid_curpal)) + { + vid_testingmode = 1; + testduration = Q_atof (Cmd_Argv(2)); + if (testduration == 0) + testduration = 5.0; + vid_testendtime = realtime + testduration; + } + } +} + +/* +================= +VID_Windowed_f +================= +*/ +void VID_Windowed_f (void) +{ + + VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); +} + + +/* +================= +VID_Fullscreen_f +================= +*/ +void VID_Fullscreen_f (void) +{ + + VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); +} + +/* +================= +VID_Minimize_f +================= +*/ +void VID_Minimize_f (void) +{ + +// we only support minimizing windows; if you're fullscreen, +// switch to windowed first + if (modestate == MS_WINDOWED) + ShowWindow (mainwindow, SW_MINIMIZE); +} + + + +/* +================= +VID_ForceMode_f +================= +*/ +void VID_ForceMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) + { + modenum = Q_atoi (Cmd_Argv(1)); + + force_mode_set = 1; + VID_SetMode (modenum, vid_curpal); + force_mode_set = 0; + } +} + + +void VID_Init (unsigned char *palette) +{ + int i, bestmatch, bestmatchmetric, t, dr, dg, db; + int basenummodes; + byte *ptmp; + + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&vid_wait); + Cvar_RegisterVariable (&vid_nopageflip); + Cvar_RegisterVariable (&_vid_wait_override); + Cvar_RegisterVariable (&_vid_default_mode); + Cvar_RegisterVariable (&_vid_default_mode_win); + Cvar_RegisterVariable (&vid_config_x); + Cvar_RegisterVariable (&vid_config_y); + Cvar_RegisterVariable (&vid_stretch_by_2); + Cvar_RegisterVariable (&_windowed_mouse); + Cvar_RegisterVariable (&vid_fullscreen_mode); + Cvar_RegisterVariable (&vid_windowed_mode); + Cvar_RegisterVariable (&block_switch); + Cvar_RegisterVariable (&vid_window_x); + Cvar_RegisterVariable (&vid_window_y); + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); + Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); + Cmd_AddCommand ("vid_windowed", VID_Windowed_f); + Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); + Cmd_AddCommand ("vid_minimize", VID_Minimize_f); + + if (COM_CheckParm ("-dibonly")) + dibonly = true; + + VID_InitMGLDIB (global_hInstance); + + basenummodes = nummodes; + + if (!dibonly) + VID_InitMGLFull (global_hInstance); + +// if there are no non-windowed modes, or only windowed and mode 0x13, then use +// fullscreen DIBs as well + if (((nummodes == basenummodes) || + ((nummodes == (basenummodes + 1)) && is_mode0x13)) && + !COM_CheckParm ("-nofulldib")) + + { + VID_InitFullDIB (global_hInstance); + } + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + vid_testingmode = 0; + +// GDI doesn't let us remap palette index 0, so we'll remap color +// mappings from that black to another one + bestmatchmetric = 256*256*3; + + for (i=1 ; i<256 ; i++) + { + dr = palette[0] - palette[i*3]; + dg = palette[1] - palette[i*3+1]; + db = palette[2] - palette[i*3+2]; + + t = (dr * dr) + (dg * dg) + (db * db); + + if (t < bestmatchmetric) + { + bestmatchmetric = t; + bestmatch = i; + + if (t == 0) + break; + } + } + + for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) + { + if (*ptmp == 0) + *ptmp = bestmatch; + } + + if (COM_CheckParm("-startwindowed")) + { + startwindowed = 1; + vid_default = windowed_default; + } + + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); + +// sound initialization has to go here, preceded by a windowed mode set, +// so there's a window for DirectSound to work with but we're not yet +// fullscreen so the "hardware already in use" dialog is visible if it +// gets displayed + +// keep the window minimized until we're ready for the first real mode set + hide_window = true; + VID_SetMode (MODE_WINDOWED, palette); + hide_window = false; + S_Init (); + + vid_initialized = true; + + force_mode_set = true; + VID_SetMode (vid_default, palette); + force_mode_set = false; + + vid_realmode = vid_modenum; + + VID_SetPalette (palette); + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; + + strcpy (badmode.modedesc, "Bad mode"); +} + + +void VID_Shutdown (void) +{ + HDC hdc; + int dummy; + + if (vid_initialized) + { + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); + + AppActivate(false, false); + DestroyDIBWindow (); + DestroyFullscreenWindow (); + DestroyFullDIBWindow (); + + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); + + if (mainwindow) + DestroyWindow(mainwindow); + + MGL_exit(); + + vid_testingmode = 0; + vid_initialized = 0; + } +} + + +/* +================ +FlipScreen +================ +*/ +void FlipScreen(vrect_t *rects) +{ + HRESULT ddrval; + + // Flip the surfaces + + if (DDActive) + { + if (mgldc) + { + if (memdc) + { + while (rects) + { + if (vid_stretched) + { + MGL_stretchBltCoord(mgldc, memdc, + rects->x, + rects->y, + rects->x + rects->width, + rects->y + rects->height, + rects->x << 1, + rects->y << 1, + (rects->x + rects->width) << 1, + (rects->y + rects->height) << 1); + } + else + { + MGL_bitBltCoord(mgldc, memdc, + rects->x, rects->y, + (rects->x + rects->width), + (rects->y + rects->height), + rects->x, rects->y, MGL_REPLACE_MODE); + } + + rects = rects->pnext; + } + } + + if (vid.numpages > 1) + { + // We have a flipping surface, so do a hard page flip + aPage = (aPage+1) % vid.numpages; + vPage = (vPage+1) % vid.numpages; + MGL_setActivePage(mgldc,aPage); + MGL_setVisualPage(mgldc,vPage,waitVRT); + } + } + } + else + { + HDC hdcScreen; + + hdcScreen = GetDC(mainwindow); + + if (windc && dibdc) + { + MGL_setWinDC(windc,hdcScreen); + + while (rects) + { + if (vid_stretched) + { + MGL_stretchBltCoord(windc,dibdc, + rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + rects->x << 1, rects->y << 1, + (rects->x + rects->width) << 1, + (rects->y + rects->height) << 1); + } + else + { + MGL_bitBltCoord(windc,dibdc, + rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + rects->x, rects->y, MGL_REPLACE_MODE); + } + + rects = rects->pnext; + } + } + + ReleaseDC(mainwindow, hdcScreen); + } +} + + +void VID_Update (vrect_t *rects) +{ + vrect_t rect; + RECT trect; + + if (!vid_palettized && palette_changed) + { + palette_changed = false; + rect.x = 0; + rect.y = 0; + rect.width = vid.width; + rect.height = vid.height; + rect.pnext = NULL; + rects = ▭ + } + + if (firstupdate) + { + if (modestate == MS_WINDOWED) + { + GetWindowRect (mainwindow, &trect); + + if ((trect.left != (int)vid_window_x.value) || + (trect.top != (int)vid_window_y.value)) + { + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + VID_CheckWindowXY (); + SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, + (int)vid_window_y.value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + } + } + + if ((_vid_default_mode_win.value != vid_default) && + (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) + { + firstupdate = 0; + + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + if ((_vid_default_mode_win.value < 0) || + (_vid_default_mode_win.value >= nummodes)) + { + Cvar_SetValue ("_vid_default_mode_win", windowed_default); + } + + Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); + } + } + + // We've drawn the frame; copy it to the screen + FlipScreen (rects); + + if (vid_testingmode) + { + if (realtime >= vid_testendtime) + { + VID_SetMode (vid_realmode, vid_curpal); + vid_testingmode = 0; + } + } + else + { + if ((int)vid_mode.value != vid_realmode) + { + VID_SetMode ((int)vid_mode.value, vid_curpal); + Cvar_SetValue ("vid_mode", (float)vid_modenum); + // so if mode set fails, we don't keep on + // trying to set that mode + vid_realmode = vid_modenum; + } + } + +// handle the mouse state when windowed if that's changed + if (modestate == MS_WINDOWED) + { + if (!_windowed_mouse.value) { + if (windowed_mouse) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + windowed_mouse = false; + } else { + windowed_mouse = true; + if (key_dest == key_game && !mouseactive && ActiveApp) { + IN_ActivateMouse (); + IN_HideMouse (); + } else if (mouseactive && key_dest != key_game) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } + } +} + + +/* +================ +D_BeginDirectRect +================ +*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (vid.aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (vid.numpages == 1) + { + VID_LockBuffer (); + + if (!vid.direct) + Sys_Error ("NULL vid.direct pointer"); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; j> repshift) * width], + width); + } + } + + VID_UnlockBuffer (); + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height << repshift; + rect.pnext = NULL; + + FlipScreen (&rect); + } + else + { + // unlock if locked + if (lockcount > 0) + MGL_endDirectAccess(); + + // set the active page to the displayed page + MGL_setActivePage (mgldc, vPage); + + // lock the screen + MGL_beginDirectAccess (); + + // save from and draw to screen + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jsurface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + width); + memcpy ((byte *)mgldc->surface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + &pbitmap[(i >> repshift) * width], + width); + } + } + + // unlock the screen + MGL_endDirectAccess (); + + // restore the original active page + MGL_setActivePage (mgldc, aPage); + + // relock the screen if it was locked + if (lockcount > 0) + MGL_beginDirectAccess(); + } +} + + +/* +================ +D_EndDirectRect +================ +*/ +void D_EndDirectRect (int x, int y, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (vid.aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (vid.numpages == 1) + { + VID_LockBuffer (); + + if (!vid.direct) + Sys_Error ("NULL vid.direct pointer"); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; j 0) + MGL_endDirectAccess(); + + // set the active page to the displayed page + MGL_setActivePage (mgldc, vPage); + + // lock the screen + MGL_beginDirectAccess (); + + // restore to the screen + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jsurface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + &backingbuf[(i + j) * 24], + width); + } + } + + // unlock the screen + MGL_endDirectAccess (); + + // restore the original active page + MGL_setActivePage (mgldc, aPage); + + // relock the screen if it was locked + if (lockcount > 0) + MGL_beginDirectAccess(); + } +} + + +//========================================================================== + +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_LEFTARROW,'5',K_RIGHTARROW,'+',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) +{ + key = (key>>16)&255; + if (key > 127) + return 0; + + return scantokey[key]; +} + +void AppActivate(BOOL fActive, BOOL minimize) +/**************************************************************************** +* +* Function: AppActivate +* Parameters: fActive - True if app is activating +* +* Description: If the application is activating, then swap the system +* into SYSPAL_NOSTATIC mode so that our palettes will display +* correctly. +* +****************************************************************************/ +{ + HDC hdc; + int i, t; + static BOOL sound_active; + + ActiveApp = fActive; + +// messy, but it seems to work + if (vid_fulldib_on_focus_mode) + { + Minimized = minimize; + + if (Minimized) + ActiveApp = false; + } + + MGL_appActivate(windc, ActiveApp); + + if (vid_initialized) + { + // yield the palette if we're losing the focus + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + { + if (ActiveApp) + { + if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) + { + // switch to SYSPAL_NOSTATIC and remap the colors + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + syscolchg = true; + pal_is_nostatic = true; + } + } + } + else if (pal_is_nostatic) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) + { + // switch back to SYSPAL_STATIC and the old mapping + SetSystemPaletteUse(hdc, SYSPAL_STATIC); + syscolchg = true; + } + + pal_is_nostatic = false; + } + } + + if (!Minimized) + VID_SetPalette (vid_curpal); + + scr_fullupdate = 0; + + ReleaseDC(NULL,hdc); + } + +// enable/disable sound on focus gain/loss + if (!ActiveApp && sound_active) + { + S_BlockSound (); + S_ClearBuffer (); + sound_active = false; + } + else if (ActiveApp && !sound_active) + { + S_UnblockSound (); + S_ClearBuffer (); + sound_active = true; + } + +// minimize/restore fulldib windows/mouse-capture normal windows on demand + if (!in_mode_set) + { + if (ActiveApp) + { + if (vid_fulldib_on_focus_mode) + { + if (vid_initialized) + { + msg_suppress_1 = true; // don't want to see normal mode set message + VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); + msg_suppress_1 = false; + + t = in_mode_set; + in_mode_set = true; + AppActivate (true, false); + in_mode_set = t; + } + + IN_ActivateMouse (); + IN_HideMouse (); + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) + { + IN_ActivateMouse (); + IN_HideMouse (); + } + } + + if (!ActiveApp) + { + if (modestate == MS_FULLDIB) + { + if (vid_initialized) + { + force_minimized = true; + i = vid_fulldib_on_focus_mode; + msg_suppress_1 = true; // don't want to see normal mode set message + VID_SetMode (windowed_default, vid_curpal); + msg_suppress_1 = false; + vid_fulldib_on_focus_mode = i; + force_minimized = false; + + // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll + // do it manually + t = in_mode_set; + in_mode_set = true; + AppActivate (false, true); + in_mode_set = t; + } + + IN_DeactivateMouse (); + IN_ShowMouse (); + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value /* && mouseactive */) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } + } +} + + +/* +================ +VID_HandlePause +================ +*/ +void VID_HandlePause (qboolean pause) +{ +#if 0 + if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + { + if (pause) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + else + { + IN_ActivateMouse (); + IN_HideMouse (); + } + } +#endif +} + + +/* +=================================================================== + +MAIN WINDOW + +=================================================================== +*/ + +LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/* main window procedure */ +LONG WINAPI MainWndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 0; + int fwKeys, xPos, yPos, fActive, fMinimized, temp; + HDC hdc; + PAINTSTRUCT ps; + extern unsigned int uiWheelMessage; + static int recursiveflag; + + if ( uMsg == uiWheelMessage ) { + uMsg = WM_MOUSEWHEEL; + wParam <<= 16; + } + + + switch (uMsg) + { + case WM_CREATE: + break; + + case WM_SYSCOMMAND: + + // Check for maximize being hit + switch (wParam & ~0x0F) + { + case SC_MAXIMIZE: + // if minimized, bring up as a window before going fullscreen, + // so MGL will have the right state to restore + if (Minimized) + { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } + + VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); + break; + + case SC_SCREENSAVE: + case SC_MONITORPOWER: + if (modestate != MS_WINDOWED) + { + // don't call DefWindowProc() because we don't want to start + // the screen saver fullscreen + break; + } + + // fall through windowed and allow the screen saver to start + + default: + if (!in_mode_set) + { + S_BlockSound (); + S_ClearBuffer (); + } + + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + + if (!in_mode_set) + { + S_UnblockSound (); + } + } + break; + + case WM_MOVE: + window_x = (int) LOWORD(lParam); + window_y = (int) HIWORD(lParam); + VID_UpdateWindowStatus (); + + if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) + VID_RememberWindowPos (); + + break; + + case WM_SIZE: + Minimized = false; + + if (!(wParam & SIZE_RESTORED)) + { + if (wParam & SIZE_MINIMIZED) + Minimized = true; + } + break; + + case WM_SYSCHAR: + // keep Alt-Space from happening + break; + + case WM_ACTIVATE: + fActive = LOWORD(wParam); + fMinimized = (BOOL) HIWORD(wParam); + AppActivate(!(fActive == WA_INACTIVE), fMinimized); + + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!in_mode_set) + { + if (windc) + MGL_activatePalette(windc,true); + + VID_SetPalette(vid_curpal); + } + + break; + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + + if (!in_mode_set && host_initialized) + SCR_UpdateWholeScreen (); + + EndPaint(hWnd, &ps); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (!in_mode_set) + Key_Event (MapKey(lParam), true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + if (!in_mode_set) + Key_Event (MapKey(lParam), false); + break; + + // 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: + if (!in_mode_set) + { + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + IN_MouseEvent (temp); + } + break; + // JACK: This is the mouse wheel with the Intellimouse + // Its delta is either positive or neg, and we generate the proper + // Event. + case WM_MOUSEWHEEL: + if ((short) HIWORD(wParam) > 0) { + Key_Event(K_MWHEELUP, true); + Key_Event(K_MWHEELUP, false); + } else { + Key_Event(K_MWHEELDOWN, true); + Key_Event(K_MWHEELDOWN, false); + } + break; + // KJB: Added these new palette functions + case WM_PALETTECHANGED: + if ((HWND)wParam == hWnd) + break; + /* Fall through to WM_QUERYNEWPALETTE */ + case WM_QUERYNEWPALETTE: + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + ReleaseDC(NULL,hdc); + + scr_fullupdate = 0; + + if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) + { + VID_SetPalette (vid_curpal); + InvalidateRect (mainwindow, NULL, false); + + // specifically required if WM_QUERYNEWPALETTE realizes a new palette + lRet = TRUE; + } + break; + + case WM_DISPLAYCHANGE: + if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) + { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } + break; + + case WM_CLOSE: + // this causes Close in the right-click task bar menu not to work, but right + // now bad things happen if Close is handled in that case (garbage and a + // crash on Win95) + if (!in_mode_set) + { + if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) + { + Sys_Quit (); + } + } + break; + + case MM_MCINOTIFY: + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 0 if handled message, 1 if not */ + return lRet; +} + + +extern void M_Menu_Options_f (void); +extern void M_Print (int cx, int cy, char *str); +extern void M_PrintWhite (int cx, int cy, char *str); +extern void M_DrawCharacter (int cx, int line, int num); +extern void M_DrawTransPic (int x, int y, qpic_t *pic); +extern void M_DrawPic (int x, int y, qpic_t *pic); + +static int vid_line, vid_wmodes; + +typedef struct +{ + int modenum; + char *desc; + int iscur; + int ismode13; + int width; +} modedesc_t; + +#define MAX_COLUMN_SIZE 5 +#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +static modedesc_t modedescs[MAX_MODEDESCS]; + +/* +================ +VID_MenuDraw +================ +*/ +void VID_MenuDraw (void) +{ + qpic_t *p; + char *ptr; + int lnummodes, i, j, k, column, row, dup, dupmode; + char temp[100]; + vmode_t *pv; + modedesc_t tmodedesc; + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + for (i=0 ; i<3 ; i++) + { + ptr = VID_GetModeDescriptionMemCheck (i); + modedescs[i].modenum = modelist[i].modenum; + modedescs[i].desc = ptr; + modedescs[i].ismode13 = 0; + modedescs[i].iscur = 0; + + if (vid_modenum == i) + modedescs[i].iscur = 1; + } + + vid_wmodes = 3; + lnummodes = VID_NumModes (); + + for (i=3 ; iwidth != 360) || COM_CheckParm("-allow360"))) + { + dup = 0; + + for (j=3 ; jmode13; + modedescs[k].iscur = 0; + modedescs[k].width = pv->width; + + if (i == vid_modenum) + modedescs[k].iscur = 1; + + if (!dup) + vid_wmodes++; + } + } + } + } + +// sort the modes on width (to handle picking up oddball dibonly modes +// after all the others) + for (i=3 ; i<(vid_wmodes-1) ; i++) + { + for (j=(i+1) ; j modedescs[j].width) + { + tmodedesc = modedescs[i]; + modedescs[i] = modedescs[j]; + modedescs[j] = tmodedesc; + } + } + } + + + M_Print (13*8, 36, "Windowed Modes"); + + column = 16; + row = 36+2*8; + + for (i=0 ; i<3; i++) + { + if (modedescs[i].iscur) + M_PrintWhite (column, row, modedescs[i].desc); + else + M_Print (column, row, modedescs[i].desc); + + column += 13*8; + } + + if (vid_wmodes > 3) + { + M_Print (12*8, 36+4*8, "Fullscreen Modes"); + + column = 16; + row = 36+6*8; + + for (i=3 ; i= 3) + row += 3*8; + + M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); + } +} + + +/* +================ +VID_MenuKey +================ +*/ +void VID_MenuKey (int key) +{ + if (vid_testingmode) + return; + + switch (key) + { + case K_ESCAPE: + S_LocalSound ("misc/menu1.wav"); + M_Menu_Options_f (); + break; + + case K_LEFTARROW: + + S_LocalSound ("misc/menu1.wav"); + vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + + ((vid_line + 2) % VID_ROW_SIZE); + + if (vid_line >= vid_wmodes) + vid_line = vid_wmodes - 1; + break; + + case K_RIGHTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + + ((vid_line + 4) % VID_ROW_SIZE); + + if (vid_line >= vid_wmodes) + vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; + break; + + case K_UPARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line -= VID_ROW_SIZE; + + if (vid_line < 0) + { + vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / + VID_ROW_SIZE) * VID_ROW_SIZE; + + while (vid_line >= vid_wmodes) + vid_line -= VID_ROW_SIZE; + } + break; + + case K_DOWNARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line += VID_ROW_SIZE; + + if (vid_line >= vid_wmodes) + { + vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / + VID_ROW_SIZE) * VID_ROW_SIZE; + + while (vid_line < 0) + vid_line += VID_ROW_SIZE; + } + break; + + case K_ENTER: + S_LocalSound ("misc/menu1.wav"); + VID_SetMode (modedescs[vid_line].modenum, vid_curpal); + break; + + case 'T': + case 't': + S_LocalSound ("misc/menu1.wav"); + // have to set this before setting the mode because WM_PAINT + // happens during the mode set and does a VID_Update, which + // checks vid_testingmode + vid_testingmode = 1; + vid_testendtime = realtime + 5.0; + + if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) + { + vid_testingmode = 0; + } + break; + + case 'D': + case 'd': + S_LocalSound ("misc/menu1.wav"); + firstupdate = 0; + Cvar_SetValue ("_vid_default_mode_win", vid_modenum); + break; + + default: + break; + } +} diff --git a/source/vid_x.c b/source/vid_x.c index 6f986ed..891fb3b 100644 --- a/source/vid_x.c +++ b/source/vid_x.c @@ -1,1116 +1,1116 @@ -/* -Copyright (C) 1996-1997 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. - -*/ -// vid_x.c -- general x video driver - -#define _BSD - -typedef unsigned short PIXEL; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "quakedef.h" -#include "d_local.h" - -cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; -cvar_t m_filter = {"m_filter","0", true}; -float old_windowed_mouse; - -// not used -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; -byte *VGA_pagebase; - - -qboolean mouse_avail; -int mouse_buttons=3; -int mouse_oldbuttonstate; -int mouse_buttonstate; -float mouse_x, mouse_y; -float old_mouse_x, old_mouse_y; -int p_mouse_x; -int p_mouse_y; -int ignorenext; -int bits_per_pixel; - -typedef struct -{ - int input; - int output; -} keymap_t; - -viddef_t vid; // global video state -unsigned short d_8to16table[256]; - -int num_shades=32; - -int d_con_indirect = 0; - -int vid_buffersize; - -static qboolean doShm; -static Display *x_disp; -static Colormap x_cmap; -static Window x_win; -static GC x_gc; -static Visual *x_vis; -static XVisualInfo *x_visinfo; -//static XImage *x_image; - -static int x_shmeventtype; -//static XShmSegmentInfo x_shminfo; - -static qboolean oktodraw = false; - -int XShmQueryExtension(Display *); -int XShmGetEventBase(Display *); - -int current_framebuffer; -static XImage *x_framebuffer[2] = { 0, 0 }; -static XShmSegmentInfo x_shminfo[2]; - -static int verbose=0; - -static byte current_palette[768]; - -static long X11_highhunkmark; -static long X11_buffersize; - -int vid_surfcachesize; -void *vid_surfcache; - -void (*vid_menudrawfn)(void); -void (*vid_menukeyfn)(int key); -void VID_MenuKey (int key); - -static PIXEL st2d_8to16table[256]; -static int shiftmask_fl=0; -static long r_shift,g_shift,b_shift; -static unsigned long r_mask,g_mask,b_mask; - -void shiftmask_init() -{ - unsigned int x; - r_mask=x_vis->red_mask; - g_mask=x_vis->green_mask; - b_mask=x_vis->blue_mask; - for(r_shift=-8,x=1;x0) { - p=(r<<(r_shift))&r_mask; - } else if(r_shift<0) { - p=(r>>(-r_shift))&r_mask; - } else p|=(r&r_mask); - - if(g_shift>0) { - p|=(g<<(g_shift))&g_mask; - } else if(g_shift<0) { - p|=(g>>(-g_shift))&g_mask; - } else p|=(g&g_mask); - - if(b_shift>0) { - p|=(b<<(b_shift))&b_mask; - } else if(b_shift<0) { - p|=(b>>(-b_shift))&b_mask; - } else p|=(b&b_mask); - - return p; -} - -void st2_fixup( XImage *framebuf, int x, int y, int width, int height) -{ - int xi,yi; - unsigned char *src; - PIXEL *dest; - - if( (x<0)||(y<0) )return; - - for (yi = y; yi < (y+height); yi++) { - src = &framebuf->data [yi * framebuf->bytes_per_line]; - dest = (PIXEL*)src; - for(xi = (x+width-1); xi >= x; xi--) { - dest[xi] = st2d_8to16table[src[xi]]; - } - } -} - - -// ======================================================================== -// Tragic death handler -// ======================================================================== - -void TragicDeath(int signal_num) -{ - XAutoRepeatOn(x_disp); - XCloseDisplay(x_disp); - Sys_Error("This death brought to you by the number %d\n", signal_num); -} - -// ======================================================================== -// makes a null cursor -// ======================================================================== - -static Cursor CreateNullCursor(Display *display, Window root) -{ - Pixmap cursormask; - XGCValues xgc; - GC gc; - XColor dummycolour; - Cursor cursor; - - cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); - xgc.function = GXclear; - gc = XCreateGC(display, cursormask, GCFunction, &xgc); - XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); - dummycolour.pixel = 0; - dummycolour.red = 0; - dummycolour.flags = 04; - cursor = XCreatePixmapCursor(display, cursormask, cursormask, - &dummycolour,&dummycolour, 0,0); - XFreePixmap(display,cursormask); - XFreeGC(display,gc); - return cursor; -} - -void ResetFrameBuffer(void) -{ - int mem; - int pwidth; - - if (x_framebuffer[0]) - { - free(x_framebuffer[0]->data); - free(x_framebuffer[0]); - } - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (X11_highhunkmark); - d_pzbuffer = NULL; - } - X11_highhunkmark = Hunk_HighMark (); - -// alloc an extra line in case we want to wrap, and allocate the z-buffer - X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer); - - vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height); - - X11_buffersize += vid_surfcachesize; - - d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video"); - if (d_pzbuffer == NULL) - Sys_Error ("Not enough memory for video mode\n"); - - vid_surfcache = (byte *) d_pzbuffer - + vid.width * vid.height * sizeof (*d_pzbuffer); - - D_InitCaches(vid_surfcache, vid_surfcachesize); - - pwidth = x_visinfo->depth / 8; - if (pwidth == 3) pwidth = 4; - mem = ((vid.width*pwidth+7)&~7) * vid.height; - - x_framebuffer[0] = XCreateImage( x_disp, - x_vis, - x_visinfo->depth, - ZPixmap, - 0, - malloc(mem), - vid.width, vid.height, - 32, - 0); - - if (!x_framebuffer[0]) - Sys_Error("VID: XCreateImage failed\n"); - - vid.buffer = (byte*) (x_framebuffer[0]); - vid.conbuffer = vid.buffer; - -} - -void ResetSharedFrameBuffers(void) -{ - - int size; - int key; - int minsize = getpagesize(); - int frm; - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (X11_highhunkmark); - d_pzbuffer = NULL; - } - - X11_highhunkmark = Hunk_HighMark (); - -// alloc an extra line in case we want to wrap, and allocate the z-buffer - X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer); - - vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height); - - X11_buffersize += vid_surfcachesize; - - d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video"); - if (d_pzbuffer == NULL) - Sys_Error ("Not enough memory for video mode\n"); - - vid_surfcache = (byte *) d_pzbuffer - + vid.width * vid.height * sizeof (*d_pzbuffer); - - D_InitCaches(vid_surfcache, vid_surfcachesize); - - for (frm=0 ; frm<2 ; frm++) - { - - // free up old frame buffer memory - - if (x_framebuffer[frm]) - { - XShmDetach(x_disp, &x_shminfo[frm]); - free(x_framebuffer[frm]); - shmdt(x_shminfo[frm].shmaddr); - } - - // create the image - - x_framebuffer[frm] = XShmCreateImage( x_disp, - x_vis, - x_visinfo->depth, - ZPixmap, - 0, - &x_shminfo[frm], - vid.width, - vid.height ); - - // grab shared memory - - size = x_framebuffer[frm]->bytes_per_line - * x_framebuffer[frm]->height; - if (size < minsize) - Sys_Error("VID: Window must use at least %d bytes\n", minsize); - - key = random(); - x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777); - if (x_shminfo[frm].shmid==-1) - Sys_Error("VID: Could not get any shared memory\n"); - - // attach to the shared memory segment - x_shminfo[frm].shmaddr = - (void *) shmat(x_shminfo[frm].shmid, 0, 0); - - printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid, - (long) x_shminfo[frm].shmaddr); - - x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; - - // get the X server to attach to it - - if (!XShmAttach(x_disp, &x_shminfo[frm])) - Sys_Error("VID: XShmAttach() failed\n"); - XSync(x_disp, 0); - shmctl(x_shminfo[frm].shmid, IPC_RMID, 0); - - } - -} - -// Called at startup to set up translation tables, takes 256 8 bit RGB values -// the palette data will go away after the call, so it must be copied off if -// the video driver will need it again - -void VID_Init (unsigned char *palette) -{ - - int pnum, i; - XVisualInfo template; - int num_visuals; - int template_mask; - - S_Init(); - - ignorenext=0; - vid.width = 320; - vid.height = 200; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.numpages = 2; - vid.colormap = host_colormap; - // vid.cbits = VID_CBITS; - // vid.grades = VID_GRADES; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - - srandom(getpid()); - - verbose=COM_CheckParm("-verbose"); - -// open the display - x_disp = XOpenDisplay(0); - if (!x_disp) - { - if (getenv("DISPLAY")) - Sys_Error("VID: Could not open display [%s]\n", - getenv("DISPLAY")); - else - Sys_Error("VID: Could not open local display\n"); - } - -// catch signals so i can turn on auto-repeat - - { - struct sigaction sa; - sigaction(SIGINT, 0, &sa); - sa.sa_handler = TragicDeath; - sigaction(SIGINT, &sa, 0); - sigaction(SIGTERM, &sa, 0); - } - - XAutoRepeatOff(x_disp); - -// for debugging only - XSynchronize(x_disp, True); - -// check for command-line window size - if ((pnum=COM_CheckParm("-winsize"))) - { - if (pnum >= com_argc-2) - Sys_Error("VID: -winsize \n"); - vid.width = Q_atoi(com_argv[pnum+1]); - vid.height = Q_atoi(com_argv[pnum+2]); - if (!vid.width || !vid.height) - Sys_Error("VID: Bad window width/height\n"); - } - if ((pnum=COM_CheckParm("-width"))) { - if (pnum >= com_argc-1) - Sys_Error("VID: -width \n"); - vid.width = Q_atoi(com_argv[pnum+1]); - if (!vid.width) - Sys_Error("VID: Bad window width\n"); - } - if ((pnum=COM_CheckParm("-height"))) { - if (pnum >= com_argc-1) - Sys_Error("VID: -height \n"); - vid.height = Q_atoi(com_argv[pnum+1]); - if (!vid.height) - Sys_Error("VID: Bad window height\n"); - } - - template_mask = 0; - -// specify a visual id - if ((pnum=COM_CheckParm("-visualid"))) - { - if (pnum >= com_argc-1) - Sys_Error("VID: -visualid \n"); - template.visualid = Q_atoi(com_argv[pnum+1]); - template_mask = VisualIDMask; - } - -// If not specified, use default visual - else - { - int screen; - screen = XDefaultScreen(x_disp); - template.visualid = - XVisualIDFromVisual(XDefaultVisual(x_disp, screen)); - template_mask = VisualIDMask; - } - -// pick a visual- warn if more than one was available - x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals); - if (num_visuals > 1) - { - printf("Found more than one visual id at depth %d:\n", template.depth); - for (i=0 ; ivisualid)); - printf(" screen %d\n", x_visinfo->screen); - printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); - printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); - printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); - printf(" colormap_size %d\n", x_visinfo->colormap_size); - printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); - } - - x_vis = x_visinfo->visual; - -// setup attributes for main window - { - int attribmask = CWEventMask | CWColormap | CWBorderPixel; - XSetWindowAttributes attribs; - Colormap tmpcmap; - - tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp, - x_visinfo->screen), x_vis, AllocNone); - - attribs.event_mask = StructureNotifyMask | KeyPressMask - | KeyReleaseMask | ExposureMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask; - attribs.border_pixel = 0; - attribs.colormap = tmpcmap; - -// create the main window - x_win = XCreateWindow( x_disp, - XRootWindow(x_disp, x_visinfo->screen), - 0, 0, // x, y - vid.width, vid.height, - 0, // borderwidth - x_visinfo->depth, - InputOutput, - x_vis, - attribmask, - &attribs ); - XStoreName( x_disp,x_win,"xquake"); - - - if (x_visinfo->class != TrueColor) - XFreeColormap(x_disp, tmpcmap); - - } - - if (x_visinfo->depth == 8) - { - - // create and upload the palette - if (x_visinfo->class == PseudoColor) - { - x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll); - VID_SetPalette(palette); - XSetWindowColormap(x_disp, x_win, x_cmap); - } - - } - -// inviso cursor - XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); - -// create the GC - { - XGCValues xgcvalues; - int valuemask = GCGraphicsExposures; - xgcvalues.graphics_exposures = False; - x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); - } - -// map the window - XMapWindow(x_disp, x_win); - -// wait for first exposure event - { - XEvent event; - do - { - XNextEvent(x_disp, &event); - if (event.type == Expose && !event.xexpose.count) - oktodraw = true; - } while (!oktodraw); - } -// now safe to draw - -// even if MITSHM is available, make sure it's a local connection - if (XShmQueryExtension(x_disp)) - { - char *displayname; - doShm = true; - displayname = (char *) getenv("DISPLAY"); - if (displayname) - { - char *d = displayname; - while (*d && (*d != ':')) d++; - if (*d) *d = 0; - if (!(!strcasecmp(displayname, "unix") || !*displayname)) - doShm = false; - } - } - - if (doShm) - { - x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion; - ResetSharedFrameBuffers(); - } - else - ResetFrameBuffer(); - - current_framebuffer = 0; - vid.rowbytes = x_framebuffer[0]->bytes_per_line; - vid.buffer = x_framebuffer[0]->data; - vid.direct = 0; - vid.conbuffer = x_framebuffer[0]->data; - vid.conrowbytes = vid.rowbytes; - vid.conwidth = vid.width; - vid.conheight = vid.height; - vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); - -// XSynchronize(x_disp, False); - -} - -void VID_ShiftPalette(unsigned char *p) -{ - VID_SetPalette(p); -} - - - -void VID_SetPalette(unsigned char *palette) -{ - - int i; - XColor colors[256]; - - for(i=0;i<256;i++) - st2d_8to16table[i]= xlib_rgb(palette[i*3], - palette[i*3+1],palette[i*3+2]); - - if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) - { - if (palette != current_palette) - memcpy(current_palette, palette, 768); - for (i=0 ; i<256 ; i++) - { - colors[i].pixel = i; - colors[i].flags = DoRed|DoGreen|DoBlue; - colors[i].red = palette[i*3] * 257; - colors[i].green = palette[i*3+1] * 257; - colors[i].blue = palette[i*3+2] * 257; - } - XStoreColors(x_disp, x_cmap, colors, 256); - } - -} - -// Called at shutdown - -void VID_Shutdown (void) -{ - Con_Printf("VID_Shutdown\n"); - XAutoRepeatOn(x_disp); - XCloseDisplay(x_disp); -} - -int XLateKey(XKeyEvent *ev) -{ - - int key; - char buf[64]; - KeySym keysym; - - key = 0; - - XLookupString(ev, buf, sizeof buf, &keysym, 0); - - switch(keysym) - { - case XK_KP_Page_Up: - case XK_Page_Up: key = K_PGUP; break; - - case XK_KP_Page_Down: - case XK_Page_Down: key = K_PGDN; break; - - case XK_KP_Home: - case XK_Home: key = K_HOME; break; - - case XK_KP_End: - case XK_End: key = K_END; break; - - case XK_KP_Left: - case XK_Left: key = K_LEFTARROW; break; - - case XK_KP_Right: - case XK_Right: key = K_RIGHTARROW; break; - - case XK_KP_Down: - case XK_Down: key = K_DOWNARROW; break; - - case XK_KP_Up: - case XK_Up: key = K_UPARROW; break; - - case XK_Escape: key = K_ESCAPE; break; - - case XK_KP_Enter: - case XK_Return: key = K_ENTER; break; - - case XK_Tab: key = K_TAB; break; - - case XK_F1: key = K_F1; break; - - case XK_F2: key = K_F2; break; - - case XK_F3: key = K_F3; break; - - case XK_F4: key = K_F4; break; - - case XK_F5: key = K_F5; break; - - case XK_F6: key = K_F6; break; - - case XK_F7: key = K_F7; break; - - case XK_F8: key = K_F8; break; - - case XK_F9: key = K_F9; break; - - case XK_F10: key = K_F10; break; - - case XK_F11: key = K_F11; break; - - case XK_F12: key = K_F12; break; - - case XK_BackSpace: key = K_BACKSPACE; break; - - case XK_KP_Delete: - case XK_Delete: key = K_DEL; break; - - case XK_Pause: key = K_PAUSE; break; - - case XK_Shift_L: - case XK_Shift_R: key = K_SHIFT; break; - - case XK_Execute: - case XK_Control_L: - case XK_Control_R: key = K_CTRL; break; - - case XK_Alt_L: - case XK_Meta_L: - case XK_Alt_R: - case XK_Meta_R: key = K_ALT; break; - - case XK_KP_Begin: key = K_AUX30; break; - - case XK_Insert: - case XK_KP_Insert: key = K_INS; break; - - case XK_KP_Multiply: key = '*'; break; - case XK_KP_Add: key = '+'; break; - case XK_KP_Subtract: key = '-'; break; - case XK_KP_Divide: key = '/'; break; - -#if 0 - case 0x021: key = '1';break;/* [!] */ - case 0x040: key = '2';break;/* [@] */ - case 0x023: key = '3';break;/* [#] */ - case 0x024: key = '4';break;/* [$] */ - case 0x025: key = '5';break;/* [%] */ - case 0x05e: key = '6';break;/* [^] */ - case 0x026: key = '7';break;/* [&] */ - case 0x02a: key = '8';break;/* [*] */ - case 0x028: key = '9';;break;/* [(] */ - case 0x029: key = '0';break;/* [)] */ - case 0x05f: key = '-';break;/* [_] */ - case 0x02b: key = '=';break;/* [+] */ - case 0x07c: key = '\'';break;/* [|] */ - case 0x07d: key = '[';break;/* [}] */ - case 0x07b: key = ']';break;/* [{] */ - case 0x022: key = '\'';break;/* ["] */ - case 0x03a: key = ';';break;/* [:] */ - case 0x03f: key = '/';break;/* [?] */ - case 0x03e: key = '.';break;/* [>] */ - case 0x03c: key = ',';break;/* [<] */ -#endif - - default: - key = *(unsigned char*)buf; - if (key >= 'A' && key <= 'Z') - key = key - 'A' + 'a'; -// fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym); - break; - } - - return key; -} - -struct -{ - int key; - int down; -} keyq[64]; -int keyq_head=0; -int keyq_tail=0; - -int config_notify=0; -int config_notify_width; -int config_notify_height; - -void GetEvent(void) -{ - XEvent x_event; - int b; - - XNextEvent(x_disp, &x_event); - switch(x_event.type) { - case KeyPress: - keyq[keyq_head].key = XLateKey(&x_event.xkey); - keyq[keyq_head].down = true; - keyq_head = (keyq_head + 1) & 63; - break; - case KeyRelease: - keyq[keyq_head].key = XLateKey(&x_event.xkey); - keyq[keyq_head].down = false; - keyq_head = (keyq_head + 1) & 63; - break; - - case MotionNotify: - if (_windowed_mouse.value) { - mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2)); - mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2)); -//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n", -// x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y); - - /* move the mouse to the window center again */ - XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask - |KeyReleaseMask|ExposureMask - |ButtonPressMask - |ButtonReleaseMask); - XWarpPointer(x_disp,None,x_win,0,0,0,0, - (vid.width/2),(vid.height/2)); - XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask - |KeyReleaseMask|ExposureMask - |PointerMotionMask|ButtonPressMask - |ButtonReleaseMask); - } else { - mouse_x = (float) (x_event.xmotion.x-p_mouse_x); - mouse_y = (float) (x_event.xmotion.y-p_mouse_y); - p_mouse_x=x_event.xmotion.x; - p_mouse_y=x_event.xmotion.y; - } - break; - - case ButtonPress: - b=-1; - if (x_event.xbutton.button == 1) - b = 0; - else if (x_event.xbutton.button == 2) - b = 2; - else if (x_event.xbutton.button == 3) - b = 1; - if (b>=0) - mouse_buttonstate |= 1<=0) - mouse_buttonstate &= ~(1<bytes_per_line; - vid.buffer = x_framebuffer[current_framebuffer]->data; - vid.conbuffer = vid.buffer; - vid.conwidth = vid.width; - vid.conheight = vid.height; - vid.conrowbytes = vid.rowbytes; - vid.recalc_refdef = 1; // force a surface cache flush - Con_CheckResize(); - Con_Clear_f(); - return; - } - - if (doShm) - { - - while (rects) - { - if (x_visinfo->depth != 8) - st2_fixup( x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, - rects->height); - if (!XShmPutImage(x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], rects->x, rects->y, - rects->x, rects->y, rects->width, rects->height, True)) - Sys_Error("VID_Update: XShmPutImage failed\n"); - oktodraw = false; - while (!oktodraw) GetEvent(); - rects = rects->pnext; - } - current_framebuffer = !current_framebuffer; - vid.buffer = x_framebuffer[current_framebuffer]->data; - vid.conbuffer = vid.buffer; - XSync(x_disp, False); - } - else - { - while (rects) - { - if (x_visinfo->depth != 8) - st2_fixup( x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, - rects->height); - XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x, - rects->y, rects->x, rects->y, rects->width, rects->height); - rects = rects->pnext; - } - XSync(x_disp, False); - } - -} - -static int dither; - -void VID_DitherOn(void) -{ - if (dither == 0) - { - vid.recalc_refdef = 1; - dither = 1; - } -} - -void VID_DitherOff(void) -{ - if (dither) - { - vid.recalc_refdef = 1; - dither = 0; - } -} - -int Sys_OpenWindow(void) -{ - return 0; -} - -void Sys_EraseWindow(int window) -{ -} - -void Sys_DrawCircle(int window, int x, int y, int r) -{ -} - -void Sys_DisplayWindow(int window) -{ -} - -void Sys_SendKeyEvents(void) -{ -// get events from x server - if (x_disp) - { - while (XPending(x_disp)) GetEvent(); - while (keyq_head != keyq_tail) - { - Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down); - keyq_tail = (keyq_tail + 1) & 63; - } - } -} - -#if 0 -char *Sys_ConsoleInput (void) -{ - - static char text[256]; - int len; - fd_set readfds; - int ready; - struct timeval timeout; - - timeout.tv_sec = 0; - timeout.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(0, &readfds); - ready = select(1, &readfds, 0, 0, &timeout); - - if (ready>0) - { - len = read (0, text, sizeof(text)); - if (len >= 1) - { - text[len-1] = 0; // rip off the /n and terminate - return text; - } - } - - return 0; - -} -#endif - -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ -// direct drawing of the "accessing disk" icon isn't supported under Linux -} - -void D_EndDirectRect (int x, int y, int width, int height) -{ -// direct drawing of the "accessing disk" icon isn't supported under Linux -} - -void IN_Init (void) -{ - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&m_filter); - if ( COM_CheckParm ("-nomouse") ) - return; - mouse_x = mouse_y = 0.0; - mouse_avail = 1; -} - -void IN_Shutdown (void) -{ - mouse_avail = 0; -} - -void IN_Commands (void) -{ - int i; - - if (!mouse_avail) return; - - for (i=0 ; isidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } else { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } - mouse_x = mouse_y = 0.0; -} - -void VID_LockBuffer (void) -{ -} - -void VID_UnlockBuffer (void) -{ -} - +/* +Copyright (C) 1996-1997 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. + +*/ +// vid_x.c -- general x video driver + +#define _BSD + +typedef unsigned short PIXEL; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "quakedef.h" +#include "d_local.h" + +cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; +cvar_t m_filter = {"m_filter","0", true}; +float old_windowed_mouse; + +// not used +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +byte *VGA_pagebase; + + +qboolean mouse_avail; +int mouse_buttons=3; +int mouse_oldbuttonstate; +int mouse_buttonstate; +float mouse_x, mouse_y; +float old_mouse_x, old_mouse_y; +int p_mouse_x; +int p_mouse_y; +int ignorenext; +int bits_per_pixel; + +typedef struct +{ + int input; + int output; +} keymap_t; + +viddef_t vid; // global video state +unsigned short d_8to16table[256]; + +int num_shades=32; + +int d_con_indirect = 0; + +int vid_buffersize; + +static qboolean doShm; +static Display *x_disp; +static Colormap x_cmap; +static Window x_win; +static GC x_gc; +static Visual *x_vis; +static XVisualInfo *x_visinfo; +//static XImage *x_image; + +static int x_shmeventtype; +//static XShmSegmentInfo x_shminfo; + +static qboolean oktodraw = false; + +int XShmQueryExtension(Display *); +int XShmGetEventBase(Display *); + +int current_framebuffer; +static XImage *x_framebuffer[2] = { 0, 0 }; +static XShmSegmentInfo x_shminfo[2]; + +static int verbose=0; + +static byte current_palette[768]; + +static long X11_highhunkmark; +static long X11_buffersize; + +int vid_surfcachesize; +void *vid_surfcache; + +void (*vid_menudrawfn)(void); +void (*vid_menukeyfn)(int key); +void VID_MenuKey (int key); + +static PIXEL st2d_8to16table[256]; +static int shiftmask_fl=0; +static long r_shift,g_shift,b_shift; +static unsigned long r_mask,g_mask,b_mask; + +void shiftmask_init() +{ + unsigned int x; + r_mask=x_vis->red_mask; + g_mask=x_vis->green_mask; + b_mask=x_vis->blue_mask; + for(r_shift=-8,x=1;x0) { + p=(r<<(r_shift))&r_mask; + } else if(r_shift<0) { + p=(r>>(-r_shift))&r_mask; + } else p|=(r&r_mask); + + if(g_shift>0) { + p|=(g<<(g_shift))&g_mask; + } else if(g_shift<0) { + p|=(g>>(-g_shift))&g_mask; + } else p|=(g&g_mask); + + if(b_shift>0) { + p|=(b<<(b_shift))&b_mask; + } else if(b_shift<0) { + p|=(b>>(-b_shift))&b_mask; + } else p|=(b&b_mask); + + return p; +} + +void st2_fixup( XImage *framebuf, int x, int y, int width, int height) +{ + int xi,yi; + unsigned char *src; + PIXEL *dest; + + if( (x<0)||(y<0) )return; + + for (yi = y; yi < (y+height); yi++) { + src = &framebuf->data [yi * framebuf->bytes_per_line]; + dest = (PIXEL*)src; + for(xi = (x+width-1); xi >= x; xi--) { + dest[xi] = st2d_8to16table[src[xi]]; + } + } +} + + +// ======================================================================== +// Tragic death handler +// ======================================================================== + +void TragicDeath(int signal_num) +{ + XAutoRepeatOn(x_disp); + XCloseDisplay(x_disp); + Sys_Error("This death brought to you by the number %d\n", signal_num); +} + +// ======================================================================== +// makes a null cursor +// ======================================================================== + +static Cursor CreateNullCursor(Display *display, Window root) +{ + Pixmap cursormask; + XGCValues xgc; + GC gc; + XColor dummycolour; + Cursor cursor; + + cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); + xgc.function = GXclear; + gc = XCreateGC(display, cursormask, GCFunction, &xgc); + XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + cursor = XCreatePixmapCursor(display, cursormask, cursormask, + &dummycolour,&dummycolour, 0,0); + XFreePixmap(display,cursormask); + XFreeGC(display,gc); + return cursor; +} + +void ResetFrameBuffer(void) +{ + int mem; + int pwidth; + + if (x_framebuffer[0]) + { + free(x_framebuffer[0]->data); + free(x_framebuffer[0]); + } + + if (d_pzbuffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (X11_highhunkmark); + d_pzbuffer = NULL; + } + X11_highhunkmark = Hunk_HighMark (); + +// alloc an extra line in case we want to wrap, and allocate the z-buffer + X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + + vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + X11_buffersize += vid_surfcachesize; + + d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video"); + if (d_pzbuffer == NULL) + Sys_Error ("Not enough memory for video mode\n"); + + vid_surfcache = (byte *) d_pzbuffer + + vid.width * vid.height * sizeof (*d_pzbuffer); + + D_InitCaches(vid_surfcache, vid_surfcachesize); + + pwidth = x_visinfo->depth / 8; + if (pwidth == 3) pwidth = 4; + mem = ((vid.width*pwidth+7)&~7) * vid.height; + + x_framebuffer[0] = XCreateImage( x_disp, + x_vis, + x_visinfo->depth, + ZPixmap, + 0, + malloc(mem), + vid.width, vid.height, + 32, + 0); + + if (!x_framebuffer[0]) + Sys_Error("VID: XCreateImage failed\n"); + + vid.buffer = (byte*) (x_framebuffer[0]); + vid.conbuffer = vid.buffer; + +} + +void ResetSharedFrameBuffers(void) +{ + + int size; + int key; + int minsize = getpagesize(); + int frm; + + if (d_pzbuffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (X11_highhunkmark); + d_pzbuffer = NULL; + } + + X11_highhunkmark = Hunk_HighMark (); + +// alloc an extra line in case we want to wrap, and allocate the z-buffer + X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + + vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + X11_buffersize += vid_surfcachesize; + + d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video"); + if (d_pzbuffer == NULL) + Sys_Error ("Not enough memory for video mode\n"); + + vid_surfcache = (byte *) d_pzbuffer + + vid.width * vid.height * sizeof (*d_pzbuffer); + + D_InitCaches(vid_surfcache, vid_surfcachesize); + + for (frm=0 ; frm<2 ; frm++) + { + + // free up old frame buffer memory + + if (x_framebuffer[frm]) + { + XShmDetach(x_disp, &x_shminfo[frm]); + free(x_framebuffer[frm]); + shmdt(x_shminfo[frm].shmaddr); + } + + // create the image + + x_framebuffer[frm] = XShmCreateImage( x_disp, + x_vis, + x_visinfo->depth, + ZPixmap, + 0, + &x_shminfo[frm], + vid.width, + vid.height ); + + // grab shared memory + + size = x_framebuffer[frm]->bytes_per_line + * x_framebuffer[frm]->height; + if (size < minsize) + Sys_Error("VID: Window must use at least %d bytes\n", minsize); + + key = random(); + x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777); + if (x_shminfo[frm].shmid==-1) + Sys_Error("VID: Could not get any shared memory\n"); + + // attach to the shared memory segment + x_shminfo[frm].shmaddr = + (void *) shmat(x_shminfo[frm].shmid, 0, 0); + + printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid, + (long) x_shminfo[frm].shmaddr); + + x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; + + // get the X server to attach to it + + if (!XShmAttach(x_disp, &x_shminfo[frm])) + Sys_Error("VID: XShmAttach() failed\n"); + XSync(x_disp, 0); + shmctl(x_shminfo[frm].shmid, IPC_RMID, 0); + + } + +} + +// Called at startup to set up translation tables, takes 256 8 bit RGB values +// the palette data will go away after the call, so it must be copied off if +// the video driver will need it again + +void VID_Init (unsigned char *palette) +{ + + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + S_Init(); + + ignorenext=0; + vid.width = 320; + vid.height = 200; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.numpages = 2; + vid.colormap = host_colormap; + // vid.cbits = VID_CBITS; + // vid.grades = VID_GRADES; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + + srandom(getpid()); + + verbose=COM_CheckParm("-verbose"); + +// open the display + x_disp = XOpenDisplay(0); + if (!x_disp) + { + if (getenv("DISPLAY")) + Sys_Error("VID: Could not open display [%s]\n", + getenv("DISPLAY")); + else + Sys_Error("VID: Could not open local display\n"); + } + +// catch signals so i can turn on auto-repeat + + { + struct sigaction sa; + sigaction(SIGINT, 0, &sa); + sa.sa_handler = TragicDeath; + sigaction(SIGINT, &sa, 0); + sigaction(SIGTERM, &sa, 0); + } + + XAutoRepeatOff(x_disp); + +// for debugging only + XSynchronize(x_disp, True); + +// check for command-line window size + if ((pnum=COM_CheckParm("-winsize"))) + { + if (pnum >= com_argc-2) + Sys_Error("VID: -winsize \n"); + vid.width = Q_atoi(com_argv[pnum+1]); + vid.height = Q_atoi(com_argv[pnum+2]); + if (!vid.width || !vid.height) + Sys_Error("VID: Bad window width/height\n"); + } + if ((pnum=COM_CheckParm("-width"))) { + if (pnum >= com_argc-1) + Sys_Error("VID: -width \n"); + vid.width = Q_atoi(com_argv[pnum+1]); + if (!vid.width) + Sys_Error("VID: Bad window width\n"); + } + if ((pnum=COM_CheckParm("-height"))) { + if (pnum >= com_argc-1) + Sys_Error("VID: -height \n"); + vid.height = Q_atoi(com_argv[pnum+1]); + if (!vid.height) + Sys_Error("VID: Bad window height\n"); + } + + template_mask = 0; + +// specify a visual id + if ((pnum=COM_CheckParm("-visualid"))) + { + if (pnum >= com_argc-1) + Sys_Error("VID: -visualid \n"); + template.visualid = Q_atoi(com_argv[pnum+1]); + template_mask = VisualIDMask; + } + +// If not specified, use default visual + else + { + int screen; + screen = XDefaultScreen(x_disp); + template.visualid = + XVisualIDFromVisual(XDefaultVisual(x_disp, screen)); + template_mask = VisualIDMask; + } + +// pick a visual- warn if more than one was available + x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals); + if (num_visuals > 1) + { + printf("Found more than one visual id at depth %d:\n", template.depth); + for (i=0 ; ivisualid)); + printf(" screen %d\n", x_visinfo->screen); + printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); + printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); + printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); + printf(" colormap_size %d\n", x_visinfo->colormap_size); + printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); + } + + x_vis = x_visinfo->visual; + +// setup attributes for main window + { + int attribmask = CWEventMask | CWColormap | CWBorderPixel; + XSetWindowAttributes attribs; + Colormap tmpcmap; + + tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp, + x_visinfo->screen), x_vis, AllocNone); + + attribs.event_mask = StructureNotifyMask | KeyPressMask + | KeyReleaseMask | ExposureMask | PointerMotionMask | + ButtonPressMask | ButtonReleaseMask; + attribs.border_pixel = 0; + attribs.colormap = tmpcmap; + +// create the main window + x_win = XCreateWindow( x_disp, + XRootWindow(x_disp, x_visinfo->screen), + 0, 0, // x, y + vid.width, vid.height, + 0, // borderwidth + x_visinfo->depth, + InputOutput, + x_vis, + attribmask, + &attribs ); + XStoreName( x_disp,x_win,"xquake"); + + + if (x_visinfo->class != TrueColor) + XFreeColormap(x_disp, tmpcmap); + + } + + if (x_visinfo->depth == 8) + { + + // create and upload the palette + if (x_visinfo->class == PseudoColor) + { + x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll); + VID_SetPalette(palette); + XSetWindowColormap(x_disp, x_win, x_cmap); + } + + } + +// inviso cursor + XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); + +// create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); + } + +// map the window + XMapWindow(x_disp, x_win); + +// wait for first exposure event + { + XEvent event; + do + { + XNextEvent(x_disp, &event); + if (event.type == Expose && !event.xexpose.count) + oktodraw = true; + } while (!oktodraw); + } +// now safe to draw + +// even if MITSHM is available, make sure it's a local connection + if (XShmQueryExtension(x_disp)) + { + char *displayname; + doShm = true; + displayname = (char *) getenv("DISPLAY"); + if (displayname) + { + char *d = displayname; + while (*d && (*d != ':')) d++; + if (*d) *d = 0; + if (!(!strcasecmp(displayname, "unix") || !*displayname)) + doShm = false; + } + } + + if (doShm) + { + x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion; + ResetSharedFrameBuffers(); + } + else + ResetFrameBuffer(); + + current_framebuffer = 0; + vid.rowbytes = x_framebuffer[0]->bytes_per_line; + vid.buffer = x_framebuffer[0]->data; + vid.direct = 0; + vid.conbuffer = x_framebuffer[0]->data; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); + +// XSynchronize(x_disp, False); + +} + +void VID_ShiftPalette(unsigned char *p) +{ + VID_SetPalette(p); +} + + + +void VID_SetPalette(unsigned char *palette) +{ + + int i; + XColor colors[256]; + + for(i=0;i<256;i++) + st2d_8to16table[i]= xlib_rgb(palette[i*3], + palette[i*3+1],palette[i*3+2]); + + if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) + { + if (palette != current_palette) + memcpy(current_palette, palette, 768); + for (i=0 ; i<256 ; i++) + { + colors[i].pixel = i; + colors[i].flags = DoRed|DoGreen|DoBlue; + colors[i].red = palette[i*3] * 257; + colors[i].green = palette[i*3+1] * 257; + colors[i].blue = palette[i*3+2] * 257; + } + XStoreColors(x_disp, x_cmap, colors, 256); + } + +} + +// Called at shutdown + +void VID_Shutdown (void) +{ + Con_Printf("VID_Shutdown\n"); + XAutoRepeatOn(x_disp); + XCloseDisplay(x_disp); +} + +int XLateKey(XKeyEvent *ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + key = 0; + + XLookupString(ev, buf, sizeof buf, &keysym, 0); + + switch(keysym) + { + case XK_KP_Page_Up: + case XK_Page_Up: key = K_PGUP; break; + + case XK_KP_Page_Down: + case XK_Page_Down: key = K_PGDN; break; + + case XK_KP_Home: + case XK_Home: key = K_HOME; break; + + case XK_KP_End: + case XK_End: key = K_END; break; + + case XK_KP_Left: + case XK_Left: key = K_LEFTARROW; break; + + case XK_KP_Right: + case XK_Right: key = K_RIGHTARROW; break; + + case XK_KP_Down: + case XK_Down: key = K_DOWNARROW; break; + + case XK_KP_Up: + case XK_Up: key = K_UPARROW; break; + + case XK_Escape: key = K_ESCAPE; break; + + case XK_KP_Enter: + case XK_Return: key = K_ENTER; break; + + case XK_Tab: key = K_TAB; break; + + case XK_F1: key = K_F1; break; + + case XK_F2: key = K_F2; break; + + case XK_F3: key = K_F3; break; + + case XK_F4: key = K_F4; break; + + case XK_F5: key = K_F5; break; + + case XK_F6: key = K_F6; break; + + case XK_F7: key = K_F7; break; + + case XK_F8: key = K_F8; break; + + case XK_F9: key = K_F9; break; + + case XK_F10: key = K_F10; break; + + case XK_F11: key = K_F11; break; + + case XK_F12: key = K_F12; break; + + case XK_BackSpace: key = K_BACKSPACE; break; + + case XK_KP_Delete: + case XK_Delete: key = K_DEL; break; + + case XK_Pause: key = K_PAUSE; break; + + case XK_Shift_L: + case XK_Shift_R: key = K_SHIFT; break; + + case XK_Execute: + case XK_Control_L: + case XK_Control_R: key = K_CTRL; break; + + case XK_Alt_L: + case XK_Meta_L: + case XK_Alt_R: + case XK_Meta_R: key = K_ALT; break; + + case XK_KP_Begin: key = K_AUX30; break; + + case XK_Insert: + case XK_KP_Insert: key = K_INS; break; + + case XK_KP_Multiply: key = '*'; break; + case XK_KP_Add: key = '+'; break; + case XK_KP_Subtract: key = '-'; break; + case XK_KP_Divide: key = '/'; break; + +#if 0 + case 0x021: key = '1';break;/* [!] */ + case 0x040: key = '2';break;/* [@] */ + case 0x023: key = '3';break;/* [#] */ + case 0x024: key = '4';break;/* [$] */ + case 0x025: key = '5';break;/* [%] */ + case 0x05e: key = '6';break;/* [^] */ + case 0x026: key = '7';break;/* [&] */ + case 0x02a: key = '8';break;/* [*] */ + case 0x028: key = '9';;break;/* [(] */ + case 0x029: key = '0';break;/* [)] */ + case 0x05f: key = '-';break;/* [_] */ + case 0x02b: key = '=';break;/* [+] */ + case 0x07c: key = '\'';break;/* [|] */ + case 0x07d: key = '[';break;/* [}] */ + case 0x07b: key = ']';break;/* [{] */ + case 0x022: key = '\'';break;/* ["] */ + case 0x03a: key = ';';break;/* [:] */ + case 0x03f: key = '/';break;/* [?] */ + case 0x03e: key = '.';break;/* [>] */ + case 0x03c: key = ',';break;/* [<] */ +#endif + + default: + key = *(unsigned char*)buf; + if (key >= 'A' && key <= 'Z') + key = key - 'A' + 'a'; +// fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym); + break; + } + + return key; +} + +struct +{ + int key; + int down; +} keyq[64]; +int keyq_head=0; +int keyq_tail=0; + +int config_notify=0; +int config_notify_width; +int config_notify_height; + +void GetEvent(void) +{ + XEvent x_event; + int b; + + XNextEvent(x_disp, &x_event); + switch(x_event.type) { + case KeyPress: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = true; + keyq_head = (keyq_head + 1) & 63; + break; + case KeyRelease: + keyq[keyq_head].key = XLateKey(&x_event.xkey); + keyq[keyq_head].down = false; + keyq_head = (keyq_head + 1) & 63; + break; + + case MotionNotify: + if (_windowed_mouse.value) { + mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2)); + mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2)); +//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n", +// x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y); + + /* move the mouse to the window center again */ + XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask + |KeyReleaseMask|ExposureMask + |ButtonPressMask + |ButtonReleaseMask); + XWarpPointer(x_disp,None,x_win,0,0,0,0, + (vid.width/2),(vid.height/2)); + XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask + |KeyReleaseMask|ExposureMask + |PointerMotionMask|ButtonPressMask + |ButtonReleaseMask); + } else { + mouse_x = (float) (x_event.xmotion.x-p_mouse_x); + mouse_y = (float) (x_event.xmotion.y-p_mouse_y); + p_mouse_x=x_event.xmotion.x; + p_mouse_y=x_event.xmotion.y; + } + break; + + case ButtonPress: + b=-1; + if (x_event.xbutton.button == 1) + b = 0; + else if (x_event.xbutton.button == 2) + b = 2; + else if (x_event.xbutton.button == 3) + b = 1; + if (b>=0) + mouse_buttonstate |= 1<=0) + mouse_buttonstate &= ~(1<bytes_per_line; + vid.buffer = x_framebuffer[current_framebuffer]->data; + vid.conbuffer = vid.buffer; + vid.conwidth = vid.width; + vid.conheight = vid.height; + vid.conrowbytes = vid.rowbytes; + vid.recalc_refdef = 1; // force a surface cache flush + Con_CheckResize(); + Con_Clear_f(); + return; + } + + if (doShm) + { + + while (rects) + { + if (x_visinfo->depth != 8) + st2_fixup( x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, + rects->height); + if (!XShmPutImage(x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], rects->x, rects->y, + rects->x, rects->y, rects->width, rects->height, True)) + Sys_Error("VID_Update: XShmPutImage failed\n"); + oktodraw = false; + while (!oktodraw) GetEvent(); + rects = rects->pnext; + } + current_framebuffer = !current_framebuffer; + vid.buffer = x_framebuffer[current_framebuffer]->data; + vid.conbuffer = vid.buffer; + XSync(x_disp, False); + } + else + { + while (rects) + { + if (x_visinfo->depth != 8) + st2_fixup( x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, + rects->height); + XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x, + rects->y, rects->x, rects->y, rects->width, rects->height); + rects = rects->pnext; + } + XSync(x_disp, False); + } + +} + +static int dither; + +void VID_DitherOn(void) +{ + if (dither == 0) + { + vid.recalc_refdef = 1; + dither = 1; + } +} + +void VID_DitherOff(void) +{ + if (dither) + { + vid.recalc_refdef = 1; + dither = 0; + } +} + +int Sys_OpenWindow(void) +{ + return 0; +} + +void Sys_EraseWindow(int window) +{ +} + +void Sys_DrawCircle(int window, int x, int y, int r) +{ +} + +void Sys_DisplayWindow(int window) +{ +} + +void Sys_SendKeyEvents(void) +{ +// get events from x server + if (x_disp) + { + while (XPending(x_disp)) GetEvent(); + while (keyq_head != keyq_tail) + { + Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down); + keyq_tail = (keyq_tail + 1) & 63; + } + } +} + +#if 0 +char *Sys_ConsoleInput (void) +{ + + static char text[256]; + int len; + fd_set readfds; + int ready; + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(0, &readfds); + ready = select(1, &readfds, 0, 0, &timeout); + + if (ready>0) + { + len = read (0, text, sizeof(text)); + if (len >= 1) + { + text[len-1] = 0; // rip off the /n and terminate + return text; + } + } + + return 0; + +} +#endif + +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Linux +} + +void D_EndDirectRect (int x, int y, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Linux +} + +void IN_Init (void) +{ + Cvar_RegisterVariable (&_windowed_mouse); + Cvar_RegisterVariable (&m_filter); + if ( COM_CheckParm ("-nomouse") ) + return; + mouse_x = mouse_y = 0.0; + mouse_avail = 1; +} + +void IN_Shutdown (void) +{ + mouse_avail = 0; +} + +void IN_Commands (void) +{ + int i; + + if (!mouse_avail) return; + + for (i=0 ; isidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } else { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } + mouse_x = mouse_y = 0.0; +} + +void VID_LockBuffer (void) +{ +} + +void VID_UnlockBuffer (void) +{ +} + diff --git a/source/view.c b/source/view.c index 5605049..f34d665 100644 --- a/source/view.c +++ b/source/view.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // view.c -- player eye positioning #include "quakedef.h" @@ -58,11 +58,11 @@ cvar_t crosshaircolor = {"crosshaircolor", "79", true}; cvar_t cl_crossx = {"cl_crossx", "0", true}; cvar_t cl_crossy = {"cl_crossy", "0", true}; - + #ifdef GLQUAKE -cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; -#endif - +cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; +#endif + cvar_t v_contentblend = {"v_contentblend", "1", false}; float v_dmg_time, v_dmg_roll, v_dmg_pitch; @@ -420,11 +420,11 @@ Underwater, lava, etc each has a color shift ============= */ void V_SetContentsColor (int contents) -{ - if (!v_contentblend.value) { - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; - return; - } +{ + if (!v_contentblend.value) { + cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + return; + } switch (contents) { @@ -1044,15 +1044,15 @@ void V_Init (void) Cvar_RegisterVariable (&v_iroll_level); Cvar_RegisterVariable (&v_ipitch_level); - Cvar_RegisterVariable (&v_contentblend); - + Cvar_RegisterVariable (&v_contentblend); + Cvar_RegisterVariable (&v_idlescale); Cvar_RegisterVariable (&crosshaircolor); Cvar_RegisterVariable (&crosshair); Cvar_RegisterVariable (&cl_crossx); - Cvar_RegisterVariable (&cl_crossy); + Cvar_RegisterVariable (&cl_crossy); #ifdef GLQUAKE - Cvar_RegisterVariable (&gl_cshiftpercent); + Cvar_RegisterVariable (&gl_cshiftpercent); #endif Cvar_RegisterVariable (&cl_rollspeed); diff --git a/source/wad.c b/source/wad.c index e0a3e51..c84f72c 100644 --- a/source/wad.c +++ b/source/wad.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // wad.c #include "quakedef.h" diff --git a/source/world.c b/source/world.c index cd20d22..5301df9 100644 --- a/source/world.c +++ b/source/world.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // world.c -- world query functions -#include "qwsvdef.h" +#include "qwsvdef.h" /* diff --git a/source/zone.c b/source/zone.c index d59ce7a..b648968 100644 --- a/source/zone.c +++ b/source/zone.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 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. - -*/ +/* +Copyright (C) 1996-1997 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. + +*/ // Z_zone.c #include "quakedef.h" @@ -410,12 +410,12 @@ void *Hunk_AllocName (int size, char *name) size = sizeof(hunk_t) + ((size+15)&~15); if (hunk_size - hunk_low_used - hunk_high_used < size) -// Sys_Error ("Hunk_Alloc: failed on %i bytes",size); +// Sys_Error ("Hunk_Alloc: failed on %i bytes",size); #ifdef _WIN32 - Sys_Error ("Not enough RAM allocated. Try starting using \"-heapsize 16000\" on the QuakeWorld command line."); -#else - Sys_Error ("Not enough RAM allocated. Try starting using \"-mem 16\" on the QuakeWorld command line."); -#endif + Sys_Error ("Not enough RAM allocated. Try starting using \"-heapsize 16000\" on the QuakeWorld command line."); +#else + Sys_Error ("Not enough RAM allocated. Try starting using \"-mem 16\" on the QuakeWorld command line."); +#endif h = (hunk_t *)(hunk_base + hunk_low_used); hunk_low_used += size; @@ -917,23 +917,23 @@ Memory_Init */ void Memory_Init (void *buf, int size) { - int p; - int zonesize = DYNAMIC_SIZE; - + int p; + int zonesize = DYNAMIC_SIZE; + hunk_base = buf; hunk_size = size; hunk_low_used = 0; hunk_high_used = 0; Cache_Init (); - p = COM_CheckParm ("-zone"); - if (p) - { - if (p < com_argc-1) - zonesize = Q_atoi (com_argv[p+1]) * 1024; - else - Sys_Error ("Memory_Init: you must specify a size in KB after -zone"); - } + p = COM_CheckParm ("-zone"); + if (p) + { + if (p < com_argc-1) + zonesize = Q_atoi (com_argv[p+1]) * 1024; + else + Sys_Error ("Memory_Init: you must specify a size in KB after -zone"); + } mainzone = Hunk_AllocName ( zonesize, "zone" ); Z_ClearZone (mainzone, zonesize); }