From 66fafd3e0e5f1e003810722db3c02163f86d99a8 Mon Sep 17 00:00:00 2001 From: Ragnvald Maartmann-Moe IV Date: Sun, 15 Apr 2001 04:18:22 +0000 Subject: [PATCH] First stage of video and input system merge. The city has collapsed, wreckage sifting ensues... --- configure.in | 3 +- {qw/include => include/QF}/vid.h | 4 + {qw/include => include/QF}/wad.h | 0 {qw/include => include}/asm_draw.h | 0 {qw/include => include}/context_x11.h | 0 {qw/include => include}/dga_check.h | 0 {nq/include => include}/dosisms.h | 0 {qw/include => include}/quakeasm.h | 0 {qw/include => include}/sbar.h | 0 {nq/include => include}/vgamodes.h | 0 {nq/include => include}/vid_dos.h | 0 {nq/include => include}/vregset.h | 0 libs/video/targets/Makefile.am | 38 +- libs/video/targets/context_x11.c | 482 +++ libs/video/targets/dga_check.c | 152 + libs/video/targets/fbset.c | 1071 ++++++ libs/video/targets/fbset_modes_l.c | 1647 +++++++++ libs/video/targets/fbset_modes_l.l | 138 + libs/video/targets/fbset_modes_y.c | 1080 ++++++ libs/video/targets/fbset_modes_y.h | 26 + libs/video/targets/fbset_modes_y.y | 176 + {nq/source => libs/video/targets}/in_dos.c | 2 +- libs/video/targets/in_fbdev.c | 151 + .../sbar.h => libs/video/targets/in_null.c | 48 +- libs/video/targets/in_sdl.c | 432 +++ {nq/source => libs/video/targets}/in_sun.c | 2 +- libs/video/targets/in_svgalib.c | 400 +++ libs/video/targets/in_win.c | 668 ++++ libs/video/targets/in_x11.c | 556 +++ libs/video/targets/vid_3dfxsvga.c | 329 ++ libs/video/targets/vid_common_gl.c | 395 ++ libs/video/targets/vid_common_sw.c | 39 + libs/video/targets/vid_dos.c | 772 ++++ libs/video/targets/vid_ext.c | 773 ++++ libs/video/targets/vid_fbdev.c | 708 ++++ libs/video/targets/vid_glx.c | 249 ++ libs/video/targets/vid_mgl.c | 3196 +++++++++++++++++ libs/video/targets/vid_null.c | 108 + libs/video/targets/vid_sdl.c | 302 ++ libs/video/targets/vid_sgl.c | 267 ++ libs/video/targets/vid_sunx.c | 1389 +++++++ libs/video/targets/vid_sunxil.c | 1423 ++++++++ libs/video/targets/vid_svgalib.c | 772 ++++ libs/video/targets/vid_vga.c | 455 +++ libs/video/targets/vid_wgl.c | 1693 +++++++++ libs/video/targets/vid_win.c | 50 + libs/video/targets/vid_x11.c | 797 ++++ nq/include/asm_draw.h | 154 - nq/include/context_x11.h | 68 - nq/include/d_local.h | 119 - nq/include/quakeasm.h | 263 -- nq/include/render.h | 2 +- nq/include/vid.h | 104 - nq/include/wad.h | 89 - nq/source/cl_main.c | 2 +- nq/source/d_fill.c | 15 +- nq/source/d_init.c | 1 - nq/source/draw.c | 2 +- nq/source/gl_draw.c | 12 +- nq/source/gl_rmisc.c | 2 +- nq/source/gl_rsurf.c | 2 +- nq/source/gl_screen.c | 6 +- nq/source/host.c | 12 +- nq/source/sbar.c | 2 +- nq/source/screen.c | 4 +- nq/source/sw_rmisc.c | 2 +- nq/source/sw_view.c | 4 +- nq/source/vid.c | 128 +- qw/include/Makefile.am | 20 +- qw/include/client.h | 2 +- qw/include/d_local.h | 122 - qw/include/host.h | 2 - qw/include/r_local.h | 2 +- qw/include/r_shared.h | 162 - qw/include/render.h | 2 +- qw/source/cl_main.c | 20 +- qw/source/cl_sys_win.c | 2 +- qw/source/gl_draw.c | 10 +- qw/source/gl_rmain.c | 2 +- qw/source/gl_rmisc.c | 2 +- qw/source/gl_screen.c | 8 +- qw/source/gl_view.c | 2 +- qw/source/pcx.c | 2 +- qw/source/r_view.c | 2 +- qw/source/sbar.c | 2 +- qw/source/screen.c | 18 +- qw/source/skin.c | 2 +- qw/source/sw_rmisc.c | 2 +- qw/source/sw_skin.c | 2 +- qw/source/sw_view.c | 2 +- qw/source/vid.c | 9 +- 91 files changed, 20971 insertions(+), 1214 deletions(-) rename {qw/include => include/QF}/vid.h (97%) rename {qw/include => include/QF}/wad.h (100%) rename {qw/include => include}/asm_draw.h (100%) rename {qw/include => include}/context_x11.h (100%) rename {qw/include => include}/dga_check.h (100%) rename {nq/include => include}/dosisms.h (100%) rename {qw/include => include}/quakeasm.h (100%) rename {qw/include => include}/sbar.h (100%) rename {nq/include => include}/vgamodes.h (100%) rename {nq/include => include}/vid_dos.h (100%) rename {nq/include => include}/vregset.h (100%) create mode 100644 libs/video/targets/context_x11.c create mode 100644 libs/video/targets/dga_check.c create mode 100644 libs/video/targets/fbset.c create mode 100644 libs/video/targets/fbset_modes_l.c create mode 100644 libs/video/targets/fbset_modes_l.l create mode 100644 libs/video/targets/fbset_modes_y.c create mode 100644 libs/video/targets/fbset_modes_y.h create mode 100644 libs/video/targets/fbset_modes_y.y rename {nq/source => libs/video/targets}/in_dos.c (99%) create mode 100644 libs/video/targets/in_fbdev.c rename nq/include/sbar.h => libs/video/targets/in_null.c (57%) create mode 100644 libs/video/targets/in_sdl.c rename {nq/source => libs/video/targets}/in_sun.c (99%) create mode 100644 libs/video/targets/in_svgalib.c create mode 100644 libs/video/targets/in_win.c create mode 100644 libs/video/targets/in_x11.c create mode 100644 libs/video/targets/vid_3dfxsvga.c create mode 100644 libs/video/targets/vid_common_gl.c create mode 100644 libs/video/targets/vid_common_sw.c create mode 100644 libs/video/targets/vid_dos.c create mode 100644 libs/video/targets/vid_ext.c create mode 100644 libs/video/targets/vid_fbdev.c create mode 100644 libs/video/targets/vid_glx.c create mode 100644 libs/video/targets/vid_mgl.c create mode 100644 libs/video/targets/vid_null.c create mode 100644 libs/video/targets/vid_sdl.c create mode 100644 libs/video/targets/vid_sgl.c create mode 100644 libs/video/targets/vid_sunx.c create mode 100644 libs/video/targets/vid_sunxil.c create mode 100644 libs/video/targets/vid_svgalib.c create mode 100644 libs/video/targets/vid_vga.c create mode 100644 libs/video/targets/vid_wgl.c create mode 100644 libs/video/targets/vid_win.c create mode 100644 libs/video/targets/vid_x11.c delete mode 100644 nq/include/asm_draw.h delete mode 100644 nq/include/context_x11.h delete mode 100644 nq/include/d_local.h delete mode 100644 nq/include/quakeasm.h delete mode 100644 nq/include/vid.h delete mode 100644 nq/include/wad.h delete mode 100644 qw/include/d_local.h delete mode 100644 qw/include/r_shared.h diff --git a/configure.in b/configure.in index 9f8cfdac7..db7fc6cab 100644 --- a/configure.in +++ b/configure.in @@ -1258,7 +1258,8 @@ fi dnl We want warnings, lots of warnings... if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -Wall -Werror" + CFLAGS="$CFLAGS -Wall" +# CFLAGS="$CFLAGS -Wall -Werror" # CFLAGS="$CFLAGS -Wall -pedantic" fi diff --git a/qw/include/vid.h b/include/QF/vid.h similarity index 97% rename from qw/include/vid.h rename to include/QF/vid.h index 1bdcc0e99..62a7cb192 100644 --- a/qw/include/vid.h +++ b/include/QF/vid.h @@ -34,6 +34,10 @@ #define VID_CBITS 6 #define VID_GRADES (1 << VID_CBITS) +struct cvar_s; +extern byte *vid_basepal; +extern byte *vid_colormap; + typedef struct vrect_s { int x,y,width,height; struct vrect_s *pnext; diff --git a/qw/include/wad.h b/include/QF/wad.h similarity index 100% rename from qw/include/wad.h rename to include/QF/wad.h diff --git a/qw/include/asm_draw.h b/include/asm_draw.h similarity index 100% rename from qw/include/asm_draw.h rename to include/asm_draw.h diff --git a/qw/include/context_x11.h b/include/context_x11.h similarity index 100% rename from qw/include/context_x11.h rename to include/context_x11.h diff --git a/qw/include/dga_check.h b/include/dga_check.h similarity index 100% rename from qw/include/dga_check.h rename to include/dga_check.h diff --git a/nq/include/dosisms.h b/include/dosisms.h similarity index 100% rename from nq/include/dosisms.h rename to include/dosisms.h diff --git a/qw/include/quakeasm.h b/include/quakeasm.h similarity index 100% rename from qw/include/quakeasm.h rename to include/quakeasm.h diff --git a/qw/include/sbar.h b/include/sbar.h similarity index 100% rename from qw/include/sbar.h rename to include/sbar.h diff --git a/nq/include/vgamodes.h b/include/vgamodes.h similarity index 100% rename from nq/include/vgamodes.h rename to include/vgamodes.h diff --git a/nq/include/vid_dos.h b/include/vid_dos.h similarity index 100% rename from nq/include/vid_dos.h rename to include/vid_dos.h diff --git a/nq/include/vregset.h b/include/vregset.h similarity index 100% rename from nq/include/vregset.h rename to include/vregset.h diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index 77f0a7e58..98afead63 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -1,8 +1,10 @@ INCLUDES= -I$(top_srcdir)/include -lib_LTLIBRARIES = libQFjs.la +lib_LTLIBRARIES = libQFjs.la libQFfbdev.la libQFmgl.la libQFsdl.la \ + libQFsvga.la libQFx11.la libQFglx.la libQFsgl.la \ + libQFtdfx.la libQFwgl.la -libQFjs_la_LDFLAGS = -version-info 1:0:0 $(CD_LIBS) +libQFjs_la_LDFLAGS= -version-info 1:0:0 if JOYTYPE_LINUX libQFjs_la_SOURCES= joy.c joy_linux.c @@ -15,4 +17,34 @@ libQFjs_la_SOURCES= joy.c joy_null.c endif libQFjs_la_CFLAGS= $(JOY_CFLAGS) -LIBLIST = libQFjs.la @LIBRARY_SEARCH_PATH@ +# Linux FBdev +YFLAGS = -d +libQFfbdev_la_LDFLAGS= -version-info 1:0:0 +libQFfbdev_la_SOURCES= fbset.c fbset_modes_y.y fbset_modes_l.l vid_fbdev.c in_fbdev.c +YACCLEX_CLEANFILES= fbset_modes_y.c fbset_modes_y.h fbset_modes_y.tab.h fbset_modes_l.c +EXTRA_libQFfbdev_la_SOURCES=fbset_modes_y.h + +fbset_modes_y.o: fbset_modes_y.c + $(COMPILE) -Wno-error -c fbset_modes_y.c +fbset_modes_l.o: fbset_modes_l.c + $(COMPILE) -Wno-error -c fbset_modes_l.c + +##libQFmgl_la_LDFLAGS= -version-info 1:0:0 +##libQFmgl_la_SOURCES= in_win.c vid_common_sw.c vid_mgl.c +libQFsdl_la_LDFLAGS= -version-info 1:0:0 +libQFsdl_la_SOURCES= in_sdl.c vid_common_sw.c vid_sdl.c +libQFsvga_la_LDFLAGS= -version-info 1:0:0 +libQFsvga_la_SOURCES= d_copy.S in_svgalib.c vid_common_sw.c vid_svgalib.c +libQFx11_la_LDFLAGS= -version-info 1:0:0 +libQFx11_la_SOURCES= in_x11.c context_x11.c dga_check.c vid_common_sw.c vid_x11.c + +libQFglx_la_LDFLAGS= -version-info 1:0:0 +libQFglx_la_SOURCES= in_x11.c context_x11.c dga_check.c vid_common_gl.c vid_glx.c +libQFsgl_la_LDFLAGS= -version-info 1:0:0 +libQFsgl_la_SOURCES= in_sdl.c vid_common_gl.c vid_sgl.c +libQFtdfx_la_LDFLAGS= -version-info 1:0:0 +libQFtdfx_la_SOURCES= in_svgalib.c vid_common_gl.c vid_3dfxsvga.c +##libQFwgl_la_LDFLAGS= -version-info 1:0:0 +##libQFwgl_la_SOURCES= in_win.c vid_wgl.c + +LIBLIST = $(lib_LTLIBRARIES) @LIBRARY_SEARCH_PATH@ diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c new file mode 100644 index 000000000..e92e30009 --- /dev/null +++ b/libs/video/targets/context_x11.c @@ -0,0 +1,482 @@ +/* + context_x11.c + + general x11 context layer + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Zephaniah E. Hull + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_VIDMODE +# include +#endif + +#include "QF/console.h" +#include "context_x11.h" +#include "QF/cvar.h" +#include "dga_check.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/qtypes.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" + +static void (*event_handlers[LASTEvent]) (XEvent *); +qboolean oktodraw = false; +int x_shmeventtype; + +static int x_disp_ref_count = 0; + +Display *x_disp = NULL; +int x_screen; +Window x_root = None; +XVisualInfo *x_visinfo; +Visual *x_vis; +Window x_win; +Cursor nullcursor = None; +static Atom aWMDelete = 0; + +#define X_MASK (VisibilityChangeMask | StructureNotifyMask | ExposureMask) + +#ifdef HAVE_VIDMODE +static XF86VidModeModeInfo **vidmodes; +static int nummodes; +static int original_mode = 0; +#endif + +static qboolean vidmode_avail = false; +static qboolean vidmode_active = false; + +cvar_t *vid_fullscreen; +cvar_t *vid_system_gamma; +qboolean vid_gamma_avail; +qboolean vid_fullscreen_active; +static double x_gamma; + +static int xss_timeout; +static int xss_interval; +static int xss_blanking; +static int xss_exposures; + +qboolean +X11_AddEvent (int event, void (*event_handler) (XEvent *)) +{ + if (event >= LASTEvent) { + printf ("event: %d, LASTEvent: %d\n", event, LASTEvent); + return false; + } + + if (event_handlers[event]) + return false; + + event_handlers[event] = event_handler; + return true; +} + +qboolean +X11_RemoveEvent (int event, void (*event_handler) (XEvent *)) +{ + if (event >= LASTEvent) + return false; + + if (event_handlers[event] != event_handler) + return false; + + event_handlers[event] = NULL; + return true; +} + +void +X11_ProcessEvent (void) +{ + XEvent x_event; + + XNextEvent (x_disp, &x_event); + if (x_event.type >= LASTEvent) { + // FIXME: KLUGE!!!!!! + if (x_event.type == x_shmeventtype) + oktodraw = 1; + return; + } + if (event_handlers[x_event.type]) + event_handlers[x_event.type] (&x_event); +} + +void +X11_ProcessEvents (void) +{ + /* Get events from X server. */ + while (XPending (x_disp)) { + X11_ProcessEvent (); + } +} + +// ======================================================================== +// Tragic death handler +// ======================================================================== + +static void +TragicDeath (int sig) +{ + printf ("Received signal %d, exiting...\n", sig); + Sys_Quit (); + exit (sig); + // XCloseDisplay(x_disp); + // VID_Shutdown(); + // Sys_Error("This death brought to you by the number %d\n", signal_num); +} + +void +X11_OpenDisplay (void) +{ + if (!x_disp) { + x_disp = XOpenDisplay (NULL); + if (!x_disp) { + Sys_Error ("X11_OpenDisplay: Could not open display [%s]\n", + XDisplayName (NULL)); + } + + x_screen = DefaultScreen (x_disp); + x_root = RootWindow (x_disp, x_screen); + + // catch signals + signal (SIGHUP, TragicDeath); + signal (SIGINT, TragicDeath); + signal (SIGQUIT, TragicDeath); + signal (SIGILL, TragicDeath); + signal (SIGTRAP, TragicDeath); + signal (SIGIOT, TragicDeath); + signal (SIGBUS, TragicDeath); +// signal(SIGFPE, TragicDeath); + signal (SIGSEGV, TragicDeath); + signal (SIGTERM, TragicDeath); + + // for debugging only + XSynchronize (x_disp, True); + + x_disp_ref_count = 1; + } else { + x_disp_ref_count++; + } +} + +void +X11_CloseDisplay (void) +{ + if (nullcursor != None) { + XFreeCursor (x_disp, nullcursor); + nullcursor = None; + } + + if (!--x_disp_ref_count) { + XCloseDisplay (x_disp); + x_disp = 0; + } +} + +/* + X11_CreateNullCursor + + Create an empty cursor (in other words, make it disappear) +*/ +void +X11_CreateNullCursor (void) +{ + Pixmap cursormask; + XGCValues xgc; + GC gc; + XColor dummycolour; + + if (nullcursor != None) + return; + + cursormask = XCreatePixmap (x_disp, x_root, 1, 1, 1); + xgc.function = GXclear; + + gc = XCreateGC (x_disp, cursormask, GCFunction, &xgc); + + XFillRectangle (x_disp, cursormask, gc, 0, 0, 1, 1); + + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + nullcursor = XCreatePixmapCursor (x_disp, cursormask, cursormask, + &dummycolour, &dummycolour, 0, 0); + XFreePixmap (x_disp, cursormask); + XFreeGC (x_disp, gc); + XDefineCursor (x_disp, x_win, nullcursor); +} + +void +X11_SetVidMode (int width, int height) +{ + const char *str = getenv ("MESA_GLX_FX"); + + if (str && (tolower (*str) == 'f')) { + Cvar_Set (vid_fullscreen, "1"); + } + + XGetScreenSaver (x_disp, &xss_timeout, &xss_interval, &xss_blanking, + &xss_exposures); + +#ifdef HAVE_VIDMODE + vidmode_avail = VID_CheckVMode (x_disp, NULL, NULL); + + if (vidmode_avail) { + vid_gamma_avail = ((x_gamma = X11_GetGamma ()) > 0); + } + + if (vid_fullscreen->int_val && vidmode_avail) { + + int i, dotclock; + int best_mode = 0; + qboolean found_mode = false; + XF86VidModeModeLine orig_data; + + XF86VidModeGetAllModeLines (x_disp, x_screen, &nummodes, &vidmodes); + XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data); + + for (i = 0; i < nummodes; i++) { + if ((vidmodes[i]->hdisplay == orig_data.hdisplay) && + (vidmodes[i]->vdisplay == orig_data.vdisplay)) { + original_mode = i; + break; + } + } + + for (i = 0; i < nummodes; i++) { + if ((vidmodes[i]->hdisplay == vid.width) && + (vidmodes[i]->vdisplay == vid.height)) { + found_mode = true; + best_mode = i; + break; + } + } + + if (found_mode) { + Con_Printf ("VID: Chose video mode: %dx%d\n", vid.width, vid.height); + + XSetScreenSaver (x_disp, 0, xss_interval, xss_blanking, xss_exposures); + XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[best_mode]); + X11_ForceViewPort (); + vidmode_active = true; + } else { + Con_Printf ("VID: Mode %dx%d can't go fullscreen.\n", vid.width, vid.height); + vid_gamma_avail = vidmode_avail = vidmode_active = false; + } + } +#endif +} + +void +X11_Init_Cvars (void) +{ + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM, NULL, + "Toggles fullscreen game mode"); + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, + "Use system gamma control if available"); +} + +void +X11_CreateWindow (int width, int height) +{ + XSetWindowAttributes attr; + XClassHint *ClassHint; + XSizeHints *SizeHints; + char *resname; + unsigned long mask; + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap (x_disp, x_root, x_vis, AllocNone); + attr.event_mask = X_MASK; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + if (vidmode_active && vid_fullscreen->int_val) { + attr.override_redirect = 1; + mask |= CWOverrideRedirect; + } + + x_win = XCreateWindow (x_disp, x_root, 0, 0, width, height, + 0, x_visinfo->depth, InputOutput, + x_vis, mask, &attr); + + // Set window size hints + SizeHints = XAllocSizeHints (); + if (SizeHints) { + SizeHints->flags = (PMinSize | PMaxSize); + SizeHints->min_width = width; + SizeHints->min_height = height; + SizeHints->max_width = width; + SizeHints->max_height = height; + XSetWMNormalHints (x_disp, x_win, SizeHints); + + XFree (SizeHints); + } + // Set window title + X11_SetCaption (va ("%s %s", PROGRAM, VERSION)); + + // Set icon name + XSetIconName (x_disp, x_win, PROGRAM); + + // Set window class + ClassHint = XAllocClassHint (); + if (ClassHint) { + resname = strrchr (com_argv[0], '/'); + + ClassHint->res_name = (resname ? resname + 1 : com_argv[0]); + ClassHint->res_class = PACKAGE; + XSetClassHint (x_disp, x_win, ClassHint); + XFree (ClassHint); + } + // Make window respond to Delete events + aWMDelete = XInternAtom (x_disp, "WM_DELETE_WINDOW", False); + XSetWMProtocols (x_disp, x_win, &aWMDelete, 1); + + if (vidmode_active && vid_fullscreen->int_val) { + XMoveWindow (x_disp, x_win, 0, 0); + XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, + vid.width + 2, vid.height + 2); + X11_ForceViewPort (); + } + + XMapWindow (x_disp, x_win); + if (vidmode_active && vid_fullscreen->int_val) { + XGrabPointer (x_disp, x_win, True, 0, GrabModeAsync, GrabModeAsync, x_win, None, CurrentTime); + } + XRaiseWindow (x_disp, x_win); +} + +void +X11_RestoreVidMode (void) +{ + XSetScreenSaver (x_disp, xss_timeout, xss_interval, xss_blanking, + xss_exposures); + +#ifdef HAVE_VIDMODE + if (vidmode_active) { + X11_SetGamma (x_gamma); + XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]); + XFree (vidmodes); + } +#endif +} + +void +X11_GrabKeyboard (void) +{ +#ifdef HAVE_VIDMODE + if (vidmode_active && vid_fullscreen->int_val) { + XGrabKeyboard (x_disp, x_win, 1, GrabModeAsync, GrabModeAsync, + CurrentTime); + } +#endif +} + +void +X11_SetCaption (char *text) +{ + if (x_disp && x_win && text) + XStoreName (x_disp, x_win, text); +} + +void +X11_ForceViewPort (void) +{ +#ifdef HAVE_VIDMODE + int x, y; + + if (vidmode_active && vid_fullscreen->int_val) { + do { + XF86VidModeSetViewPort (x_disp, x_screen, 0, 0); + poll (0, 0, 50); + XF86VidModeGetViewPort (x_disp, x_screen, &x, &y); + } while (x || y); + } +#endif +} + +double +X11_GetGamma (void) +{ +#ifdef HAVE_VIDMODE +# ifdef X_XF86VidModeGetGamma + XF86VidModeGamma xgamma; + + if (vidmode_avail && vid_system_gamma->int_val) { + if (XF86VidModeGetGamma (x_disp, x_screen, &xgamma)) { + return ((xgamma.red + xgamma.green + xgamma.blue) / 3); + } + } +# endif +#endif + return -1.0; +} + +qboolean +X11_SetGamma (double gamma) +{ +#ifdef HAVE_VIDMODE +# ifdef X_XF86VidModeSetGamma + XF86VidModeGamma xgamma; + + if (vidmode_avail && vid_system_gamma->int_val) { + xgamma.red = xgamma.green = xgamma.blue = (float) gamma; + if (XF86VidModeSetGamma (x_disp, x_screen, &xgamma)) + return true; + } +# endif +#endif + return false; +} diff --git a/libs/video/targets/dga_check.c b/libs/video/targets/dga_check.c new file mode 100644 index 000000000..207b4190c --- /dev/null +++ b/libs/video/targets/dga_check.c @@ -0,0 +1,152 @@ +/* + dga_check.c + + Routines to check for XFree86 DGA and VidMode extensions + + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_DGA +# include +# include +# ifndef XDGA_MAJOR_VERSION +# ifdef XF86DGA_MAJOR_VERSION +# define XDGA_MAJOR_VERSION XF86DGA_MAJOR_VERSION +# else +# error "Neither XDGA_MAJOR_VERSION nor XF86DGA_MAJOR_VERSION found." +# endif +# endif +#endif +#ifdef HAVE_VIDMODE +# include +# include +#endif + +#include "QF/console.h" +#include "dga_check.h" + + +/* + VID_CheckDGA + + Check for the presence of the XFree86-DGA X server extension +*/ +qboolean +VID_CheckDGA (Display * dpy, int *maj_ver, int *min_ver, int *hasvideo) +{ +#ifdef HAVE_DGA + int event_base, error_base, dgafeat; + int dummy, dummy_major, dummy_minor, dummy_video; + + if (!XQueryExtension (dpy, XF86DGANAME, &dummy, &dummy, &dummy)) { + return false; + } + + if (!XF86DGAQueryExtension (dpy, &event_base, &error_base)) { + return false; + } + + if (!maj_ver) + maj_ver = &dummy_major; + if (!min_ver) + min_ver = &dummy_minor; + + if (!XF86DGAQueryVersion (dpy, maj_ver, min_ver)) { + return false; + } + + if ((!maj_ver) || (*maj_ver != XDGA_MAJOR_VERSION)) { + Con_Printf ("VID: Incorrect DGA version: %d.%d, \n", *maj_ver, *min_ver); + return false; + } + Con_Printf ("VID: DGA version: %d.%d\n", *maj_ver, *min_ver); + + if (!hasvideo) + hasvideo = &dummy_video; + + if (!XF86DGAQueryDirectVideo (dpy, DefaultScreen (dpy), &dgafeat)) { + *hasvideo = 0; + } else { + *hasvideo = (dgafeat & XF86DGADirectGraphics); + } + + if (!(dgafeat & (XF86DGADirectPresent | XF86DGADirectMouse))) { + return false; + } + + return true; +#else + return false; +#endif // HAVE_DGA +} + + +/* + VID_CheckVMode + + Check for the presence of the XFree86-VidMode X server extension +*/ +qboolean +VID_CheckVMode (Display * dpy, int *maj_ver, int *min_ver) +{ +#ifdef HAVE_VIDMODE + int event_base, error_base; + int dummy, dummy_major, dummy_minor; + + if (!XQueryExtension (dpy, XF86VIDMODENAME, &dummy, &dummy, &dummy)) { + return false; + } + + if (!XF86VidModeQueryExtension (dpy, &event_base, &error_base)) { + return false; + } + + if (!maj_ver) + maj_ver = &dummy_major; + if (!min_ver) + min_ver = &dummy_minor; + + if (!XF86VidModeQueryVersion (dpy, maj_ver, min_ver)) + return false; + + if ((!maj_ver) || (*maj_ver != XF86VIDMODE_MAJOR_VERSION)) { + Con_Printf ("VID: Incorrect VidMode version: %d.%d\n", *maj_ver, *min_ver); + return false; + } + + Con_Printf ("VID: VidMode version: %d.%d\n", *maj_ver, *min_ver); + return true; +#else + return false; +#endif // HAVE_VIDMODE +} diff --git a/libs/video/targets/fbset.c b/libs/video/targets/fbset.c new file mode 100644 index 000000000..582152f4d --- /dev/null +++ b/libs/video/targets/fbset.c @@ -0,0 +1,1071 @@ +/* + * Linux Frame Buffer Device Configuration + * + * © Copyright 1995-1999 by Geert Uytterhoeven + * (Geert.Uytterhoeven@cs.kuleuven.ac.be) + * + * -------------------------------------------------------------------------- + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + * + * Petr Vandrovec : + * -grayscale, -rgba, -nonstd, VGA modes reporting + * + * Brad Midgley : + * -match + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct file; +struct inode; + +#include "fbset.h" + + + /* + * Default Frame Buffer Special Device Node + */ + +#define DEFAULT_FRAMEBUFFER "/dev/fb0" + + + /* + * Default Video Mode Database File + */ + +#define DEFAULT_MODEDBFILE "/etc/fb.modes" + + /* + * Command Line Options + */ + +static const char *ProgramName; + +static int Opt_test = 0; +static int Opt_show = 0; +static int Opt_info = 0; +static int Opt_version = 0; +static int Opt_verbose = 0; +static int Opt_xfree86 = 0; +static int Opt_change = 0; +static int Opt_all = 0; + +static const char *Opt_fb = NULL; +const char *Opt_modedb = DEFAULT_MODEDBFILE; +static const char *Opt_xres = NULL; +static const char *Opt_yres = NULL; +static const char *Opt_vxres = NULL; +static const char *Opt_vyres = NULL; +static const char *Opt_depth = NULL; +static const char *Opt_pixclock = NULL; +static const char *Opt_left = NULL; +static const char *Opt_right = NULL; +static const char *Opt_upper = NULL; +static const char *Opt_lower = NULL; +static const char *Opt_hslen = NULL; +static const char *Opt_vslen = NULL; +static const char *Opt_accel = NULL; +static const char *Opt_hsync = NULL; +static const char *Opt_vsync = NULL; +static const char *Opt_csync = NULL; +static const char *Opt_gsync = NULL; +static const char *Opt_extsync = NULL; +static const char *Opt_bcast = NULL; +static const char *Opt_laced = NULL; +static const char *Opt_double = NULL; +static const char *Opt_move = NULL; +static const char *Opt_step = NULL; +static const char *Opt_modename = NULL; +static const char *Opt_rgba = NULL; +static const char *Opt_nonstd = NULL; +static const char *Opt_grayscale = NULL; +static const char *Opt_matchyres = NULL; + +static struct { + const char *name; + const char **value; + const int change; +} Options[] = { + { "-fb", &Opt_fb, 0 }, + { "-db", &Opt_modedb, 0 }, + { "-xres", &Opt_xres, 1 }, + { "-yres", &Opt_yres, 1 }, + { "-vxres", &Opt_vxres, 1 }, + { "-vyres", &Opt_vyres, 1 }, + { "-depth", &Opt_depth, 1 }, + { "-nonstd", &Opt_nonstd, 1}, + { "-pixclock", &Opt_pixclock, 1 }, + { "-left", &Opt_left, 1 }, + { "-right", &Opt_right, 1 }, + { "-upper", &Opt_upper, 1 }, + { "-lower", &Opt_lower, 1 }, + { "-hslen", &Opt_hslen, 1 }, + { "-vslen", &Opt_vslen, 1 }, + { "-accel", &Opt_accel, 1 }, + { "-hsync", &Opt_hsync, 1 }, + { "-vsync", &Opt_vsync, 1 }, + { "-csync", &Opt_csync, 1 }, + { "-gsync", &Opt_gsync, 1 }, + { "-extsync", &Opt_extsync, 1 }, + { "-bcast", &Opt_bcast, 1 }, + { "-laced", &Opt_laced, 1 }, + { "-double", &Opt_double, 1 }, + { "-move", &Opt_move, 1 }, + { "-step", &Opt_step, 1 }, + { "-rgba", &Opt_rgba, 1 }, + { "-grayscale", &Opt_grayscale, 1 }, + { NULL, NULL, 0 } +}; + + /* + * Video Mode Database + */ + +struct VideoMode *VideoModes = NULL; + + + /* + * Hardware Text Modes + */ + +static struct textentry { + __u32 id; + const char *name; +} Textmodes[] = { + { FB_AUX_TEXT_MDA, "Monochrome text" }, + { FB_AUX_TEXT_CGA, "CGA/EGA/VGA Color text" }, + { FB_AUX_TEXT_S3_MMIO, "S3 MMIO fasttext" }, + { FB_AUX_TEXT_MGA_STEP16, "MGA Millennium I step 16 text" }, + { FB_AUX_TEXT_MGA_STEP8, "MGA step 8 text" }, +}; + +static struct textentry VGAModes[] = { +#ifdef HAVE_FB_AUX_VGA_PLANES_VGA4 + { FB_AUX_VGA_PLANES_VGA4, "VGA 16 colors in 4 planes" }, +#endif +#ifdef HAVE_FB_AUX_VGA_PLANES_CFB4 + { FB_AUX_VGA_PLANES_CFB4, "VGA 16 colors in 1 plane" }, +#endif +#ifdef HAVE_FB_AUX_VGA_PLANES_CFB8 + { FB_AUX_VGA_PLANES_CFB8, "VGA 256 colors in 4 planes" }, +#endif + /* last entry has name == NULL */ + { 0, NULL} +}; + + /* + * Hardware Accelerators + */ + +static struct accelentry { + __u32 id; + const char *name; +} Accelerators[] = { + { FB_ACCEL_NONE, "No" }, + { FB_ACCEL_ATARIBLITT, "Atari Blitter" }, + { FB_ACCEL_AMIGABLITT, "Amiga Blitter" }, + { FB_ACCEL_S3_TRIO64, "S3 Trio64" }, + { FB_ACCEL_NCR_77C32BLT, "NCR 77C32BLT" }, + { FB_ACCEL_S3_VIRGE, "S3 ViRGE" }, + { FB_ACCEL_ATI_MACH64GX, "ATI Mach64GX" }, + { FB_ACCEL_DEC_TGA, "DEC 21030 TGA" }, + { FB_ACCEL_ATI_MACH64CT, "ATI Mach64CT" }, + { FB_ACCEL_ATI_MACH64VT, "ATI Mach64VT" }, + { FB_ACCEL_ATI_MACH64GT, "ATI Mach64GT" }, + { FB_ACCEL_SUN_CREATOR, "Sun Creator/Creator3D" }, + { FB_ACCEL_SUN_CGSIX, "Sun cg6" }, + { FB_ACCEL_SUN_LEO, "Sun leo/zx" }, + { FB_ACCEL_IMS_TWINTURBO, "IMS Twin Turbo" }, + { FB_ACCEL_3DLABS_PERMEDIA2, "3Dlabs Permedia 2" }, + { FB_ACCEL_MATROX_MGA2064W, "Matrox MGA2064W (Millennium)" }, + { FB_ACCEL_MATROX_MGA1064SG, "Matrox MGA1064SG (Mystique)" }, + { FB_ACCEL_MATROX_MGA2164W, "Matrox MGA2164W (Millennium II)" }, + { FB_ACCEL_MATROX_MGA2164W_AGP, "Matrox MGA2164W (Millennium II AGP)" }, + { FB_ACCEL_MATROX_MGAG100, "Matrox G100 (Productiva G100)" }, + { FB_ACCEL_MATROX_MGAG200, "Matrox G200 (Millennium, Mystique)" }, + { FB_ACCEL_SUN_CG14, "Sun cg14" }, + { FB_ACCEL_SUN_BWTWO, "Sun bw2" }, + { FB_ACCEL_SUN_CGTHREE, "Sun cg3" }, + { FB_ACCEL_SUN_TCX, "Sun tcx" }, + { FB_ACCEL_MATROX_MGAG400, "Matrox G400" }, +}; + + + /* + * Current Video Mode + */ + +struct VideoMode Current; + + + /* + * Function Prototypes + */ + +int OpenFrameBuffer(const char *name); +void CloseFrameBuffer(int fh); +int GetVarScreenInfo(int fh, struct fb_var_screeninfo *var); +int SetVarScreenInfo(int fh, struct fb_var_screeninfo *var); +int GetFixScreenInfo(int fh, struct fb_fix_screeninfo *fix); +void ConvertFromVideoMode(const struct VideoMode *vmode, + struct fb_var_screeninfo *var); +void ConvertToVideoMode(const struct fb_var_screeninfo *var, + struct VideoMode *vmode); +static int atoboolean(const char *var); +void ReadModeDB(void); +struct VideoMode *FindVideoMode(const char *name); +static void ModifyVideoMode(struct VideoMode *vmode); +static void DisplayVModeInfo(struct VideoMode *vmode); +static void DisplayFBInfo(struct fb_fix_screeninfo *fix); +static int FillScanRates(struct VideoMode *vmode); +static void Usage(void); +int main(int argc, char *argv[]); + +extern void Con_Printf (const char *fmt, ...); + +#define Die Con_Printf +#define puts(s) Con_Printf("%s\n",(s)) +#define printf Con_Printf + + /* + * Open the Frame Buffer Device + */ + +int OpenFrameBuffer(const char *name) +{ + int fh; + + if (Opt_verbose) + printf("Opening frame buffer device `%s'\n", name); + + if ((fh = open(name, O_RDWR)) == -1) + Die("open %s: %s\n", name, strerror(errno)); + return fh; +} + + + /* + * Close the Frame Buffer Device + */ + +void CloseFrameBuffer(int fh) +{ + close(fh); +} + + /* + * Get the Variable Part of the Screen Info + */ + +int GetVarScreenInfo(int fh, struct fb_var_screeninfo *var) +{ + if (ioctl(fh, FBIOGET_VSCREENINFO, var)) { + Die("ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + return -1; + } + return 0; +} + + + /* + * Set (and Get) the Variable Part of the Screen Info + */ + +int SetVarScreenInfo(int fh, struct fb_var_screeninfo *var) +{ + if (ioctl(fh, FBIOPUT_VSCREENINFO, var)) { + Die("ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + return -1; + } + return 0; +} + + + /* + * Get the Fixed Part of the Screen Info + */ + +int GetFixScreenInfo(int fh, struct fb_fix_screeninfo *fix) +{ + if (ioctl(fh, FBIOGET_FSCREENINFO, fix)) { + Die("ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return -1; + } + return 0; +} + + + /* + * Conversion Routines + */ + +void ConvertFromVideoMode(const struct VideoMode *vmode, + struct fb_var_screeninfo *var) +{ + memset(var, 0, sizeof(struct fb_var_screeninfo)); + var->xres = vmode->xres; + var->yres = vmode->yres; + var->xres_virtual = vmode->vxres; + var->yres_virtual = vmode->vyres; + var->bits_per_pixel = vmode->depth; + var->nonstd = vmode->nonstd; + if (Opt_test) + var->activate = FB_ACTIVATE_TEST; + else + var->activate = FB_ACTIVATE_NOW; + if (Opt_all) + var->activate = FB_ACTIVATE_ALL; + var->accel_flags = vmode->accel_flags; + var->pixclock = vmode->pixclock; + var->left_margin = vmode->left; + var->right_margin = vmode->right; + var->upper_margin = vmode->upper; + var->lower_margin = vmode->lower; + var->hsync_len = vmode->hslen; + var->vsync_len = vmode->vslen; + if (vmode->hsync == HIGH) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (vmode->vsync == HIGH) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + if (vmode->csync == HIGH) + var->sync |= FB_SYNC_COMP_HIGH_ACT; + if (vmode->gsync == HIGH) + var->sync |= FB_SYNC_ON_GREEN; + if (vmode->extsync == TRUE) + var->sync |= FB_SYNC_EXT; + if (vmode->bcast == TRUE) + var->sync |= FB_SYNC_BROADCAST; + if (vmode->laced == TRUE) + var->vmode = FB_VMODE_INTERLACED; + else if (vmode->dblscan == TRUE) + var->vmode = FB_VMODE_DOUBLE; + else + var->vmode = FB_VMODE_NONINTERLACED; + var->vmode |= FB_VMODE_CONUPDATE; + var->red.length = vmode->red.length; + var->red.offset = vmode->red.offset; + var->green.length = vmode->green.length; + var->green.offset = vmode->green.offset; + var->blue.length = vmode->blue.length; + var->blue.offset = vmode->blue.offset; + var->transp.length = vmode->transp.length; + var->transp.offset = vmode->transp.offset; + var->grayscale = vmode->grayscale; +} + + +void ConvertToVideoMode(const struct fb_var_screeninfo *var, + struct VideoMode *vmode) +{ + vmode->name = NULL; + vmode->xres = var->xres; + vmode->yres = var->yres; + vmode->vxres = var->xres_virtual; + vmode->vyres = var->yres_virtual; + vmode->depth = var->bits_per_pixel; + vmode->nonstd = var->nonstd; + vmode->accel_flags = var->accel_flags; + vmode->pixclock = var->pixclock; + vmode->left = var->left_margin; + vmode->right = var->right_margin; + vmode->upper = var->upper_margin; + vmode->lower = var->lower_margin; + vmode->hslen = var->hsync_len; + vmode->vslen = var->vsync_len; + vmode->hsync = var->sync & FB_SYNC_HOR_HIGH_ACT ? HIGH : LOW; + vmode->vsync = var->sync & FB_SYNC_VERT_HIGH_ACT ? HIGH : LOW; + vmode->csync = var->sync & FB_SYNC_COMP_HIGH_ACT ? HIGH : LOW; + vmode->gsync = var->sync & FB_SYNC_ON_GREEN ? TRUE : FALSE; + vmode->extsync = var->sync & FB_SYNC_EXT ? TRUE : FALSE; + vmode->bcast = var->sync & FB_SYNC_BROADCAST ? TRUE : FALSE; + vmode->grayscale = var->grayscale; + vmode->laced = FALSE; + vmode->dblscan = FALSE; + switch (var->vmode & FB_VMODE_MASK) { + case FB_VMODE_INTERLACED: + vmode->laced = TRUE; + break; + case FB_VMODE_DOUBLE: + vmode->dblscan = TRUE; + break; + } + vmode->red.length = var->red.length; + vmode->red.offset = var->red.offset; + vmode->green.length = var->green.length; + vmode->green.offset = var->green.offset; + vmode->blue.length = var->blue.length; + vmode->blue.offset = var->blue.offset; + vmode->transp.length = var->transp.length; + vmode->transp.offset = var->transp.offset; + FillScanRates(vmode); +} + + +static int atoboolean(const char *var) +{ + int value = 0; + + if (!strcasecmp(var, "false") || !strcasecmp(var, "low") || + !strcasecmp(var, "no") || !strcasecmp(var, "off") || + !strcmp(var, "0")) + value = 0; + else if (!strcasecmp(var, "true") || !strcasecmp(var, "high") || + !strcasecmp(var, "yes") || !strcasecmp(var, "on") || + !strcmp(var, "1")) + value = 1; + else + Die("Invalid value `%s'\n", var); + + return value; +} + + +void AddVideoMode(const struct VideoMode *vmode) +{ + struct VideoMode *vmode2; + + if (FindVideoMode(vmode->name)) + Die("%s:%d: Duplicate mode name `%s'\n", Opt_modedb, line, + vmode->name); + vmode2 = malloc(sizeof(struct VideoMode)); + *vmode2 = *vmode; + if (!FillScanRates(vmode2)) + Die("%s:%d: Bad video mode `%s'\n", Opt_modedb, line, vmode2->name); + vmode2->next = VideoModes; + VideoModes = vmode2; +} + + + /* + * Read the Video Mode Database + */ + +void ReadModeDB(void) +{ + if (Opt_verbose) + printf("Reading mode database from file `%s'\n", Opt_modedb); + + if (!(yyin = fopen(Opt_modedb, "r"))) { + Die("fopen %s: %s\n", Opt_modedb, strerror(errno)); + return; + } + yyparse(); + fclose(yyin); +} + + +static void getColor(struct color *color, const char** opt) +{ + char* ptr; + + color->length = 0; + color->offset = 0; + ptr = (char*)(*opt); + if (!ptr) + return; + color->length = strtoul(ptr, &ptr, 0); + if (!ptr) + return; + if (*ptr == '/') + color->offset = strtoul(ptr+1, &ptr, 0); + if (ptr) { + while (*ptr && isspace(*ptr)) + ptr++; + if (*ptr == ',') { + ptr++; + } else if (*ptr) + Die("Bad RGBA syntax, rL/rO,gL/gO,bL/bO,tL/tO or rL,gL,bL,tL\n"); + } + *opt = ptr; + return; +} + +void makeRGBA(struct VideoMode *vmode, const char* opt) +{ + getColor(&vmode->red, &opt); + getColor(&vmode->green, &opt); + getColor(&vmode->blue, &opt); + getColor(&vmode->transp, &opt); +} + + /* + * Find a Video Mode + */ + +struct VideoMode *FindVideoMode(const char *name) +{ + struct VideoMode *vmode; + + for (vmode = VideoModes; vmode; vmode = vmode->next) + if (!strcmp(name, vmode->name)) + break; + + return vmode; +} + + + /* + * Modify a Video Mode + */ + +static void ModifyVideoMode(struct VideoMode *vmode) +{ + u_int hstep = 8, vstep = 2; + + if (Opt_xres) + vmode->xres = strtoul(Opt_xres, NULL, 0); + if (Opt_yres) + vmode->yres = strtoul(Opt_yres, NULL, 0); + if (Opt_vxres) + vmode->vxres = strtoul(Opt_vxres, NULL, 0); + if (Opt_vyres) + vmode->vyres = strtoul(Opt_vyres, NULL, 0); + if (Opt_depth) + vmode->depth = strtoul(Opt_depth, NULL, 0); + if (Opt_nonstd) + vmode->nonstd = strtoul(Opt_nonstd, NULL, 0); + if (Opt_accel) + vmode->accel_flags = atoboolean(Opt_accel) ? FB_ACCELF_TEXT : 0; + if (Opt_pixclock) + vmode->pixclock = strtoul(Opt_pixclock, NULL, 0); + if (Opt_left) + vmode->left = strtoul(Opt_left, NULL, 0); + if (Opt_right) + vmode->right = strtoul(Opt_right, NULL, 0); + if (Opt_upper) + vmode->upper = strtoul(Opt_upper, NULL, 0); + if (Opt_lower) + vmode->lower = strtoul(Opt_lower, NULL, 0); + if (Opt_hslen) + vmode->hslen = strtoul(Opt_hslen, NULL, 0); + if (Opt_vslen) + vmode->vslen = strtoul(Opt_vslen, NULL, 0); + if (Opt_hsync) + vmode->hsync = atoboolean(Opt_hsync); + if (Opt_vsync) + vmode->vsync = atoboolean(Opt_vsync); + if (Opt_csync) + vmode->csync = atoboolean(Opt_csync); + if (Opt_gsync) + vmode->gsync = atoboolean(Opt_gsync); + if (Opt_extsync) + vmode->extsync = atoboolean(Opt_extsync); + if (Opt_bcast) + vmode->bcast = atoboolean(Opt_bcast); + if (Opt_laced) + vmode->laced = atoboolean(Opt_laced); + if (Opt_double) + vmode->dblscan = atoboolean(Opt_double); + if (Opt_grayscale) + vmode->grayscale = atoboolean(Opt_grayscale); + if (Opt_step) + hstep = vstep = strtoul(Opt_step, NULL, 0); + if (Opt_matchyres) + vmode->vyres = vmode->yres; + if (Opt_move) { + if (!strcasecmp(Opt_move, "left")) { + if (hstep > vmode->left) + Die("The left margin cannot be negative\n"); + vmode->left -= hstep; + vmode->right += hstep; + } else if (!strcasecmp(Opt_move, "right")) { + if (hstep > vmode->right) + Die("The right margin cannot be negative\n"); + vmode->left += hstep; + vmode->right -= hstep; + } else if (!strcasecmp(Opt_move, "up")) { + if (vstep > vmode->upper) + Die("The upper margin cannot be negative\n"); + vmode->upper -= vstep; + vmode->lower += vstep; + } else if (!strcasecmp(Opt_move, "down")) { + if (vstep > vmode->lower) + Die("The lower margin cannot be negative\n"); + vmode->upper += vstep; + vmode->lower -= vstep; + } else + Die("Invalid direction `%s'\n", Opt_move); + } + if (Opt_rgba) { + makeRGBA(vmode, Opt_rgba); + } + if (!FillScanRates(vmode)) + Die("Bad video mode\n"); +} + + + /* + * Display the Video Mode Information + */ + +static void DisplayVModeInfo(struct VideoMode *vmode) +{ + u_int res, sstart, send, total; + + puts(""); + if (!Opt_xfree86) { + printf("mode \"%dx%d", vmode->xres, vmode->yres); + if (vmode->pixclock) { + printf("-%d\"\n", (int)(vmode->vrate+0.5)); + printf(" # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n", + vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate); + } else + puts("\""); + printf(" geometry %d %d %d %d %d\n", vmode->xres, vmode->yres, + vmode->vxres, vmode->vyres, vmode->depth); + printf(" timings %d %d %d %d %d %d %d\n", vmode->pixclock, + vmode->left, vmode->right, vmode->upper, vmode->lower, + vmode->hslen, vmode->vslen); + if (vmode->hsync) + puts(" hsync high"); + if (vmode->vsync) + puts(" vsync high"); + if (vmode->csync) + puts(" csync high"); + if (vmode->gsync) + puts(" gsync true"); + if (vmode->extsync) + puts(" extsync true"); + if (vmode->bcast) + puts(" bcast true"); + if (vmode->laced) + puts(" laced true"); + if (vmode->dblscan) + puts(" double true"); + if (vmode->nonstd) + printf(" nonstd %u\n", vmode->nonstd); + if (vmode->accel_flags) + puts(" accel true"); + if (vmode->grayscale) + puts(" grayscale true"); + printf(" rgba %u/%u,%u/%u,%u/%u,%u/%u\n", + vmode->red.length, vmode->red.offset, vmode->green.length, + vmode->green.offset, vmode->blue.length, vmode->blue.offset, + vmode->transp.length, vmode->transp.offset); + puts("endmode\n"); + } else { + printf("Mode \"%dx%d\"\n", vmode->xres, vmode->yres); + if (vmode->pixclock) { + printf(" # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n", + vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate); + printf(" DotClock %5.3f\n", vmode->drate/1E6+0.001); + } else + puts(" DotClock Unknown"); + res = vmode->xres; + sstart = res+vmode->right; + send = sstart+vmode->hslen; + total = send+vmode->left; + printf(" HTimings %d %d %d %d\n", res, sstart, send, total); + res = vmode->yres; + sstart = res+vmode->lower; + send = sstart+vmode->vslen; + total = send+vmode->upper; + printf(" VTimings %d %d %d %d\n", res, sstart, send, total); + printf(" Flags "); + if (vmode->laced) + printf(" \"Interlace\""); + if (vmode->dblscan) + printf(" \"DoubleScan\""); + if (vmode->hsync) + printf(" \"+HSync\""); + else + printf(" \"-HSync\""); + if (vmode->vsync) + printf(" \"+VSync\""); + else + printf(" \"-VSync\""); + if (vmode->csync) + printf(" \"Composite\""); + if (vmode->extsync) + puts(" # Warning: XFree86 doesn't support extsync\n"); + if (vmode->bcast) + printf(" \"bcast\""); + if (vmode->accel_flags) + puts(" # Warning: XFree86 doesn't support accel\n"); + if (vmode->grayscale) + puts(" # Warning: XFree86 doesn't support grayscale\n"); + puts("\nEndMode\n"); + } +} + + + /* + * Display the Frame Buffer Device Information + */ + +static void DisplayFBInfo(struct fb_fix_screeninfo *fix) +{ + int i; + + puts("Frame buffer device information:"); + printf(" Name : %s\n", fix->id); + printf(" Address : %p\n", (void *)fix->smem_start); + printf(" Size : %d\n", fix->smem_len); + printf(" Type : "); + switch (fix->type) { + case FB_TYPE_PACKED_PIXELS: + puts("PACKED PIXELS"); + break; + case FB_TYPE_PLANES: + puts("PLANES"); + break; + case FB_TYPE_INTERLEAVED_PLANES: + printf("INTERLEAVED PLANES (%d bytes interleave)\n", + fix->type_aux); + break; + case FB_TYPE_TEXT: + for (i = 0; i < sizeof(Textmodes)/sizeof(*Textmodes); i++) + if (fix->type_aux == Textmodes[i].id) + break; + if (i < sizeof(Textmodes)/sizeof(*Textmodes)) + puts(Textmodes[i].name); + else + printf("Unknown text (%d)\n", fix->type_aux); + break; + case FB_TYPE_VGA_PLANES: + { + struct textentry *t; + + for (t = VGAModes; t->name; t++) + if (fix->type_aux == t->id) + break; + if (t->name) + puts(t->name); + else + printf("Unknown VGA mode (%d)\n", fix->type_aux); + } + break; + default: + printf("%d (UNKNOWN)\n", fix->type); + printf(" Type_aux : %d\n", fix->type_aux); + break; + } + printf(" Visual : "); + switch (fix->visual) { + case FB_VISUAL_MONO01: + puts("MONO01"); + break; + case FB_VISUAL_MONO10: + puts("MONO10"); + break; + case FB_VISUAL_TRUECOLOR: + puts("TRUECOLOR"); + break; + case FB_VISUAL_PSEUDOCOLOR: + puts("PSEUDOCOLOR"); + break; + case FB_VISUAL_DIRECTCOLOR: + puts("DIRECTCOLOR"); + break; + case FB_VISUAL_STATIC_PSEUDOCOLOR: + puts("STATIC PSEUDOCOLOR"); + break; + default: + printf("%d (UNKNOWN)\n", fix->visual); + break; + } + printf(" XPanStep : %d\n", fix->xpanstep); + printf(" YPanStep : %d\n", fix->ypanstep); + printf(" YWrapStep : %d\n", fix->ywrapstep); + printf(" LineLength : %d\n", fix->line_length); + if (fix->mmio_len) { + printf(" MMIO Address: %p\n", (void *)fix->mmio_start); + printf(" MMIO Size : %d\n", fix->mmio_len); + } + printf(" Accelerator : "); + for (i = 0; i < sizeof(Accelerators)/sizeof(*Accelerators); i++) + if (fix->accel == Accelerators[i].id) + break; + if (i < sizeof(Accelerators)/sizeof(*Accelerators)) + puts(Accelerators[i].name); + else + printf("Unknown (%d)\n", fix->accel); +} + + + /* + * Calculate the Scan Rates for a Video Mode + */ + +static int FillScanRates(struct VideoMode *vmode) +{ + u_int htotal = vmode->left+vmode->xres+vmode->right+vmode->hslen; + u_int vtotal = vmode->upper+vmode->yres+vmode->lower+vmode->vslen; + + if (vmode->dblscan) + vtotal <<= 2; + else if (!vmode->laced) + vtotal <<= 1; + + if (!htotal || !vtotal) + return 0; + + if (vmode->pixclock) { + vmode->drate = 1E12/vmode->pixclock; + vmode->hrate = vmode->drate/htotal; + vmode->vrate = vmode->hrate/vtotal*2; + } else { + vmode->drate = 0; + vmode->hrate = 0; + vmode->vrate = 0; + } + + return 1; +} + + /* + * Print the Usage Template and Exit + */ + +static void Usage(void) +{ + puts(FBSET_VERSION); + printf("\nUsage: %s [options] [mode]\n\n" + "Valid options:\n" + " General options:\n" + " -h, --help : display this usage information\n" + " --test : don't change, just test whether the mode is " + "valid\n" + " -s, --show : display video mode settings\n" + " -i, --info : display all frame buffer information\n" + " -v, --verbose : verbose mode\n" + " -V, --version : print version information\n" + " -x, --xfree86 : XFree86 compatibility mode\n" + " -a, --all : change all virtual consoles on this device\n" + " Frame buffer special device nodes:\n" + " -fb : processed frame buffer device\n" + " (default is " DEFAULT_FRAMEBUFFER ")\n" + " Video mode database:\n" + " -db : video mode database file\n" + " (default is " DEFAULT_MODEDBFILE ")\n" + " Display geometry:\n" + " -xres : horizontal resolution (in pixels)\n" + " -yres : vertical resolution (in pixels)\n" + " -vxres : virtual horizontal resolution (in pixels)\n" + " -vyres : virtual vertical resolution (in pixels)\n" + " -depth : display depth (in bits per pixel)\n" + " -nonstd : select nonstandard video mode\n" + " -g, --geometry ... : set all geometry parameters at once\n" + " -match : set virtual vertical resolution by virtual resolution\n" + " Display timings:\n" + " -pixclock : pixel clock (in picoseconds)\n" + " -left : left margin (in pixels)\n" + " -right : right margin (in pixels)\n" + " -upper : upper margin (in pixel lines)\n" + " -lower : lower margin (in pixel lines)\n" + " -hslen : horizontal sync length (in pixels)\n" + " -vslen : vertical sync length (in pixel lines)\n" + " -t, --timings ... : set all timing parameters at once\n" + " Display flags:\n" + " -accel : hardware text acceleration enable (false or " + "true)\n" + " -hsync : horizontal sync polarity (low or high)\n" + " -vsync : vertical sync polarity (low or high)\n" + " -csync : composite sync polarity (low or high)\n" + " -gsync : synch on green (false or true)\n" + " -extsync : external sync enable (false or true)\n" + " -bcast : broadcast enable (false or true)\n" + " -laced : interlace enable (false or true)\n" + " -double : doublescan enable (false or true)\n" + " -rgba : recommended length of color entries\n" + " -grayscale : grayscale enable (false or true)\n" + " Display positioning:\n" + " -move : move the visible part (left, right, up or " + "down)\n" + " -step : step increment (in pixels or pixel lines)\n" + " (default is 8 horizontal, 2 vertical)\n", + ProgramName); +} + + /* + * Main Routine + */ + +int fbset_main(int argc, char *argv[]) +{ + struct VideoMode *vmode; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + int fh = -1, i; + + ProgramName = argv[0]; + + /* + * Parse the Options + */ + + while (--argc > 0) { + argv++; + if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) { + Usage(); + return 1; + } else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) + Opt_verbose = 1; + else if (!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version")) + Opt_version = 1; + else if (!strcmp(argv[0], "--test")) + Opt_test = 1; + else if (!strcmp(argv[0], "-s") || !strcmp(argv[0], "--show")) + Opt_show = 1; + else if (!strcmp(argv[0], "-i") || !strcmp(argv[0], "--info")) { + Opt_show = 1; + Opt_info = 1; + } else if (!strcmp(argv[0], "-x") || !strcmp(argv[0], "--xfree86")) + Opt_xfree86 = 1; + else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--all")) + Opt_all = 1; + else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--geometry")) { + if (argc > 5) { + Opt_xres = argv[1]; + Opt_yres = argv[2]; + Opt_vxres = argv[3]; + Opt_vyres = argv[4]; + Opt_depth = argv[5]; + Opt_change = 1; + argc -= 5; + argv += 5; + } else { + Usage(); + return 1; + } + } else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--timings")) { + if (argc > 7) { + Opt_pixclock = argv[1]; + Opt_left = argv[2]; + Opt_right = argv[3]; + Opt_upper = argv[4]; + Opt_lower = argv[5]; + Opt_hslen = argv[6]; + Opt_vslen = argv[7]; + Opt_change = 1; + argc -= 7; + argv += 7; + } else { + Usage(); + return 1; + } + } else if (!strcmp(argv[0], "-match")) { + Opt_matchyres = argv[0]; + Opt_change = 1; + } else { + for (i = 0; Options[i].name; i++) + if (!strcmp(argv[0], Options[i].name)) + break; + if (Options[i].name) { + if (argc-- > 1) { + *Options[i].value = argv[1]; + Opt_change |= Options[i].change; + argv++; + } else { + Usage(); + return 1; + } + } else if (!Opt_modename) { + Opt_modename = argv[0]; + Opt_change = 1; + } else { + Usage(); + return 1; + } + } + } + + if (Opt_version || Opt_verbose) + puts(FBSET_VERSION); + + if (!Opt_fb) { + Opt_fb = getenv("FRAMEBUFFER"); + if (!Opt_fb) + Opt_fb = DEFAULT_FRAMEBUFFER; + } + + /* + * Open the Frame Buffer Device + */ + + fh = OpenFrameBuffer(Opt_fb); + if (fh < 0) + return 1; + + /* + * Get the Video Mode + */ + + if (Opt_modename) { + +#if 0 + /* + * Read the Video Mode Database + */ + + ReadModeDB(); +#endif + + if (!(vmode = FindVideoMode(Opt_modename))) { + Die("Unknown video mode `%s'\n", Opt_modename); + return 1; + } + Current = *vmode; + if (Opt_verbose) + printf("Using video mode `%s'\n", Opt_modename); + } else { + GetVarScreenInfo(fh, &var); + ConvertToVideoMode(&var, &Current); + if (Opt_verbose) + printf("Using current video mode from `%s'\n", Opt_fb); + } + + if (Opt_change) { + + /* + * Optionally Modify the Video Mode + */ + + ModifyVideoMode(&Current); + + /* + * Set the Video Mode + */ + + ConvertFromVideoMode(&Current, &var); + if (Opt_verbose) + printf("Setting video mode to `%s'\n", Opt_fb); + SetVarScreenInfo(fh, &var); + ConvertToVideoMode(&var, &Current); + } + + /* + * Display some Video Mode Information + */ + + if (Opt_show || !Opt_change) + DisplayVModeInfo(&Current); + + if (Opt_info) { + if (Opt_verbose) + puts("Getting further frame buffer information"); + if (GetFixScreenInfo(fh, &fix) != -1) + DisplayFBInfo(&fix); + } + + /* + * Close the Frame Buffer Device + */ + + CloseFrameBuffer(fh); + + return 0; +} diff --git a/libs/video/targets/fbset_modes_l.c b/libs/video/targets/fbset_modes_l.c new file mode 100644 index 000000000..db3ae7a06 --- /dev/null +++ b/libs/video/targets/fbset_modes_l.c @@ -0,0 +1,1647 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 8 +#define YY_END_OF_BUFFER 9 +static yyconst short int yy_accept[19] = + { 0, + 2, 2, 9, 7, 5, 6, 7, 7, 2, 1, + 5, 0, 3, 0, 4, 2, 1, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, + 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, + + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[8] = + { 0, + 1, 1, 2, 1, 1, 3, 3 + } ; + +static yyconst short int yy_base[22] = + { 0, + 0, 0, 22, 23, 19, 23, 16, 16, 12, 0, + 15, 12, 23, 12, 23, 8, 0, 23, 7, 10, + 6 + } ; + +static yyconst short int yy_def[22] = + { 0, + 18, 1, 18, 18, 18, 18, 19, 20, 18, 21, + 18, 19, 18, 20, 18, 18, 21, 0, 18, 18, + 18 + } ; + +static yyconst short int yy_nxt[31] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 12, 17, 12, + 14, 14, 14, 16, 15, 13, 11, 16, 15, 13, + 11, 18, 3, 18, 18, 18, 18, 18, 18, 18 + } ; + +static yyconst short int yy_chk[31] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 19, 21, 19, + 20, 20, 20, 16, 14, 12, 11, 9, 8, 7, + 5, 3, 18, 18, 18, 18, 18, 18, 18, 18 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "fbset_modes_l.l" +#define INITIAL 0 +/* + * Linux Frame Buffer Device Configuration + * + * © Copyright 1995-1998 by Geert Uytterhoeven + * (Geert.Uytterhoeven@cs.kuleuven.ac.be) + * + * -------------------------------------------------------------------------- + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ +#line 17 "fbset_modes_l.l" + +#define YYSTYPE long + +#include +#include + +#define Die Sys_Error + +#include "fbset.h" +#include "fbset_modes_y.h" + +struct keyword { + const char *name; + int token; + int value; +}; + +static struct keyword keywords[] = { + { "mode", MODE, 0 }, + { "geometry", GEOMETRY, 0 }, + { "timings", TIMINGS, 0 }, + { "hsync", HSYNC, 0 }, + { "vsync", VSYNC, 0 }, + { "csync", CSYNC, 0 }, + { "gsync", GSYNC, 0 }, + { "extsync", EXTSYNC, 0 }, + { "bcast", BCAST, 0 }, + { "laced", LACED, 0 }, + { "double", DOUBLE, 0 }, + { "rgba", RGBA, 0 }, + { "nonstd", NONSTD, 0 }, + { "accel", ACCEL, 0 }, + { "grayscale", GRAYSCALE, 0 }, + { "endmode", ENDMODE, 0 }, + { "low", POLARITY, LOW }, + { "high", POLARITY, HIGH }, + { "false", BOOLEAN, FALSE }, + { "true", BOOLEAN, TRUE }, + { "", -1, 0 } +}; + +int line = 1; + + +void yyerror(const char *s) +{ + Die("%s:%d: %s\n", Opt_modedb, line, s); +} + + +int yywrap(void) +{ + return 1; +} + + +static int FindToken(const char *s) +{ + int i; + + for (i = 0; keywords[i].token > 0; i++) + if (!strcasecmp(s, keywords[i].name)) { + return keywords[i].token; + } + Die("%s:%d: Unknown keyword `%s'\n", Opt_modedb, line, s); +} + + +static const char *CopyString(const char *s) +{ + int len; + char *s2; + + len = strlen(s)-2; + if (!(s2 = malloc(len+1))) + Die("No memory\n"); + strncpy(s2, s+1, len); + s2[len] = '\0'; + return s2; +} + + +#line 467 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 108 "fbset_modes_l.l" + + +#line 621 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 23 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 110 "fbset_modes_l.l" +{ + yylval = FindToken(yytext); + return yylval; + } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 115 "fbset_modes_l.l" +{ + yylval = strtoul(yytext, NULL, 0); + return NUMBER; + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 120 "fbset_modes_l.l" +{ + yylval = (unsigned long)CopyString(yytext); + return STRING; + } + YY_BREAK +case 4: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 125 "fbset_modes_l.l" +break; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 127 "fbset_modes_l.l" +break; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 129 "fbset_modes_l.l" +{ + line++; + break; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 134 "fbset_modes_l.l" +{ + Die("%s:%d: Invalid token `%s'\n", Opt_modedb, line, yytext); + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 138 "fbset_modes_l.l" +ECHO; + YY_BREAK +#line 761 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 18); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 138 "fbset_modes_l.l" + diff --git a/libs/video/targets/fbset_modes_l.l b/libs/video/targets/fbset_modes_l.l new file mode 100644 index 000000000..47932f218 --- /dev/null +++ b/libs/video/targets/fbset_modes_l.l @@ -0,0 +1,138 @@ + +/* + * Linux Frame Buffer Device Configuration + * + * © Copyright 1995-1998 by Geert Uytterhoeven + * (Geert.Uytterhoeven@cs.kuleuven.ac.be) + * + * -------------------------------------------------------------------------- + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + + +%{ + +#define YYSTYPE long + +#include +#include + +#define Die Sys_Error + +#include "fbset.h" +#include "fbset_modes_y.h" + +struct keyword { + const char *name; + int token; + int value; +}; + +static struct keyword keywords[] = { + { "mode", MODE, 0 }, + { "geometry", GEOMETRY, 0 }, + { "timings", TIMINGS, 0 }, + { "hsync", HSYNC, 0 }, + { "vsync", VSYNC, 0 }, + { "csync", CSYNC, 0 }, + { "gsync", GSYNC, 0 }, + { "extsync", EXTSYNC, 0 }, + { "bcast", BCAST, 0 }, + { "laced", LACED, 0 }, + { "double", DOUBLE, 0 }, + { "rgba", RGBA, 0 }, + { "nonstd", NONSTD, 0 }, + { "accel", ACCEL, 0 }, + { "grayscale", GRAYSCALE, 0 }, + { "endmode", ENDMODE, 0 }, + { "low", POLARITY, LOW }, + { "high", POLARITY, HIGH }, + { "false", BOOLEAN, FALSE }, + { "true", BOOLEAN, TRUE }, + { "", -1, 0 } +}; + +int line = 1; + + +void yyerror(const char *s) +{ + Die("%s:%d: %s\n", Opt_modedb, line, s); +} + + +int yywrap(void) +{ + return 1; +} + + +static int FindToken(const char *s) +{ + int i; + + for (i = 0; keywords[i].token > 0; i++) + if (!strcasecmp(s, keywords[i].name)) { + return keywords[i].token; + } + Die("%s:%d: Unknown keyword `%s'\n", Opt_modedb, line, s); +} + + +static const char *CopyString(const char *s) +{ + int len; + char *s2; + + len = strlen(s)-2; + if (!(s2 = malloc(len+1))) + Die("No memory\n"); + strncpy(s2, s+1, len); + s2[len] = '\0'; + return s2; +} + + +%} + +keyword [a-zA-Z][a-zA-Z0-9]* +number [0-9]* +string \"[^\"\n]*\" +comment \#([^\n]*) +space [ \t]+ +junk . + +%% + +{keyword} { + yylval = FindToken(yytext); + return yylval; + } + +{number} { + yylval = strtoul(yytext, NULL, 0); + return NUMBER; + } + +{string} { + yylval = (unsigned long)CopyString(yytext); + return STRING; + } + +{comment}$ break; + +{space} break; + +\n { + line++; + break; + } + +{junk} { + Die("%s:%d: Invalid token `%s'\n", Opt_modedb, line, yytext); + } + +%% diff --git a/libs/video/targets/fbset_modes_y.c b/libs/video/targets/fbset_modes_y.c new file mode 100644 index 000000000..a67c2248c --- /dev/null +++ b/libs/video/targets/fbset_modes_y.c @@ -0,0 +1,1080 @@ + +/* A Bison parser, made from fbset_modes_y.y + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define MODE 257 +#define GEOMETRY 258 +#define TIMINGS 259 +#define HSYNC 260 +#define VSYNC 261 +#define CSYNC 262 +#define GSYNC 263 +#define EXTSYNC 264 +#define BCAST 265 +#define LACED 266 +#define DOUBLE 267 +#define RGBA 268 +#define NONSTD 269 +#define ACCEL 270 +#define GRAYSCALE 271 +#define ENDMODE 272 +#define POLARITY 273 +#define BOOLEAN 274 +#define STRING 275 +#define NUMBER 276 + +#line 15 "fbset_modes_y.y" + + +#define YYSTYPE long + +#include +#include +#include + +#define Die Sys_Error + +#include "fbset.h" + +extern int yylex(void); +extern void yyerror(const char *s); +extern int line; + + +static struct VideoMode VideoMode; + +static void ClearVideoMode(void) +{ + memset(&VideoMode, 0, sizeof(VideoMode)); + VideoMode.accel_flags = FB_ACCELF_TEXT; +} + +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 61 +#define YYFLAG -32768 +#define YYNTBASE 23 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 276 ? yytranslate[x] : 41) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 3, 6, 13, 20, 29, 30, 33, 36, + 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, + 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, + 99 +}; + +static const short yyrhs[] = { 24, + 0, 0, 24, 25, 0, 3, 21, 26, 27, 28, + 18, 0, 4, 22, 22, 22, 22, 22, 0, 5, + 22, 22, 22, 22, 22, 22, 22, 0, 0, 28, + 29, 0, 28, 30, 0, 28, 31, 0, 28, 32, + 0, 28, 33, 0, 28, 34, 0, 28, 35, 0, + 28, 36, 0, 28, 37, 0, 28, 38, 0, 28, + 39, 0, 28, 40, 0, 6, 19, 0, 7, 19, + 0, 8, 19, 0, 9, 19, 0, 10, 20, 0, + 11, 20, 0, 12, 20, 0, 13, 20, 0, 14, + 21, 0, 15, 22, 0, 16, 20, 0, 17, 20, + 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 50, 54, 55, 58, 66, 77, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 104, + 110, 116, 122, 128, 134, 140, 146, 152, 158, 164, + 170 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","MODE","GEOMETRY", +"TIMINGS","HSYNC","VSYNC","CSYNC","GSYNC","EXTSYNC","BCAST","LACED","DOUBLE", +"RGBA","NONSTD","ACCEL","GRAYSCALE","ENDMODE","POLARITY","BOOLEAN","STRING", +"NUMBER","file","vmodes","vmode","geometry","timings","options","hsync","vsync", +"csync","gsync","extsync","bcast","laced","double","rgba","nonstd","accel","grayscale", NULL +}; +#endif + +static const short yyr1[] = { 0, + 23, 24, 24, 25, 26, 27, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40 +}; + +static const short yyr2[] = { 0, + 1, 0, 2, 6, 6, 8, 0, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2 +}; + +static const short yydefact[] = { 2, + 1, 0, 3, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, + 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 5, 0, 0, 0, 6, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 59, + 1, 3, 6, 9, 12, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39 +}; + +static const short yypact[] = {-32768, + 10, -7,-32768, 11, -5, 13, -3, -2,-32768, -1, + 0, -6, 1, 2, 6, 7, 8, 9, -4, 12, + 14, 15, 16, 17, 18, 20,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 19, + 21,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768, 22, 23, 24,-32768, 29, 30, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768 +}; + + +#define YYLAST 46 + + +static const short yytable[] = { 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 2, 4, 5, 46, 7, 8, 10, 11, + 13, 14, 40, 41, 42, 43, 44, 45, 60, 61, + 0, 47, 0, 48, 49, 0, 50, 52, 51, 53, + 54, 0, 55, 56, 57, 58 +}; + +static const short yycheck[] = { 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 3, 21, 4, 20, 22, 5, 22, 22, + 22, 22, 22, 22, 19, 19, 19, 19, 0, 0, + -1, 20, -1, 20, 20, -1, 21, 20, 22, 20, + 22, -1, 22, 22, 22, 22 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, 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, 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. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/share/bison/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 4: +#line 59 "fbset_modes_y.y" +{ + VideoMode.name = (char *)yyvsp[-4]; + AddVideoMode(&VideoMode); + ClearVideoMode(); + ; + break;} +case 5: +#line 67 "fbset_modes_y.y" +{ + ClearVideoMode(); + VideoMode.xres = yyvsp[-4]; + VideoMode.yres = yyvsp[-3]; + VideoMode.vxres = yyvsp[-2]; + VideoMode.vyres = yyvsp[-1]; + VideoMode.depth = yyvsp[0]; + ; + break;} +case 6: +#line 78 "fbset_modes_y.y" +{ + VideoMode.pixclock = yyvsp[-6]; + VideoMode.left = yyvsp[-5]; + VideoMode.right = yyvsp[-4]; + VideoMode.upper = yyvsp[-3]; + VideoMode.lower = yyvsp[-2]; + VideoMode.hslen = yyvsp[-1]; + VideoMode.vslen = yyvsp[0]; + ; + break;} +case 20: +#line 105 "fbset_modes_y.y" +{ + VideoMode.hsync = yyvsp[0]; + ; + break;} +case 21: +#line 111 "fbset_modes_y.y" +{ + VideoMode.vsync = yyvsp[0]; + ; + break;} +case 22: +#line 117 "fbset_modes_y.y" +{ + VideoMode.csync = yyvsp[0]; + ; + break;} +case 23: +#line 123 "fbset_modes_y.y" +{ + VideoMode.gsync = yyvsp[0]; + ; + break;} +case 24: +#line 129 "fbset_modes_y.y" +{ + VideoMode.extsync = yyvsp[0]; + ; + break;} +case 25: +#line 135 "fbset_modes_y.y" +{ + VideoMode.bcast = yyvsp[0]; + ; + break;} +case 26: +#line 141 "fbset_modes_y.y" +{ + VideoMode.laced = yyvsp[0]; + ; + break;} +case 27: +#line 147 "fbset_modes_y.y" +{ + VideoMode.dblscan = yyvsp[0]; + ; + break;} +case 28: +#line 153 "fbset_modes_y.y" +{ + makeRGBA(&VideoMode, (const char*)yyvsp[0]); + ; + break;} +case 29: +#line 159 "fbset_modes_y.y" +{ + VideoMode.nonstd = yyvsp[0]; + ; + break;} +case 30: +#line 165 "fbset_modes_y.y" +{ + VideoMode.accel_flags = yyvsp[0]; + ; + break;} +case 31: +#line 171 "fbset_modes_y.y" +{ + VideoMode.grayscale = yyvsp[0]; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/share/bison/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; +} +#line 176 "fbset_modes_y.y" + diff --git a/libs/video/targets/fbset_modes_y.h b/libs/video/targets/fbset_modes_y.h new file mode 100644 index 000000000..d035f1305 --- /dev/null +++ b/libs/video/targets/fbset_modes_y.h @@ -0,0 +1,26 @@ +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define MODE 257 +#define GEOMETRY 258 +#define TIMINGS 259 +#define HSYNC 260 +#define VSYNC 261 +#define CSYNC 262 +#define GSYNC 263 +#define EXTSYNC 264 +#define BCAST 265 +#define LACED 266 +#define DOUBLE 267 +#define RGBA 268 +#define NONSTD 269 +#define ACCEL 270 +#define GRAYSCALE 271 +#define ENDMODE 272 +#define POLARITY 273 +#define BOOLEAN 274 +#define STRING 275 +#define NUMBER 276 + + +extern YYSTYPE yylval; diff --git a/libs/video/targets/fbset_modes_y.y b/libs/video/targets/fbset_modes_y.y new file mode 100644 index 000000000..82366f25d --- /dev/null +++ b/libs/video/targets/fbset_modes_y.y @@ -0,0 +1,176 @@ +/* + * Linux Frame Buffer Device Configuration + * + * © Copyright 1995-1998 by Geert Uytterhoeven + * (Geert.Uytterhoeven@cs.kuleuven.ac.be) + * + * -------------------------------------------------------------------------- + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + + +%{ + +#define YYSTYPE long + +#include +#include +#include + +#define Die Sys_Error + +#include "fbset.h" + +extern int yylex(void); +extern void yyerror(const char *s); +extern int line; + + +static struct VideoMode VideoMode; + +static void ClearVideoMode(void) +{ + memset(&VideoMode, 0, sizeof(VideoMode)); + VideoMode.accel_flags = FB_ACCELF_TEXT; +} + +%} + +%start file + +%token MODE GEOMETRY TIMINGS HSYNC VSYNC CSYNC GSYNC EXTSYNC BCAST LACED DOUBLE + RGBA NONSTD ACCEL GRAYSCALE + ENDMODE POLARITY BOOLEAN STRING NUMBER + +%% + +file : vmodes + ; + + +vmodes : /* empty */ + | vmodes vmode + ; + +vmode : MODE STRING geometry timings options ENDMODE + { + VideoMode.name = (char *)$2; + AddVideoMode(&VideoMode); + ClearVideoMode(); + } + ; + +geometry : GEOMETRY NUMBER NUMBER NUMBER NUMBER NUMBER + { + ClearVideoMode(); + VideoMode.xres = $2; + VideoMode.yres = $3; + VideoMode.vxres = $4; + VideoMode.vyres = $5; + VideoMode.depth = $6; + } + ; + +timings : TIMINGS NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER + { + VideoMode.pixclock = $2; + VideoMode.left = $3; + VideoMode.right = $4; + VideoMode.upper = $5; + VideoMode.lower = $6; + VideoMode.hslen = $7; + VideoMode.vslen = $8; + } + ; + +options : /* empty */ + | options hsync + | options vsync + | options csync + | options gsync + | options extsync + | options bcast + | options laced + | options double + | options rgba + | options nonstd + | options accel + | options grayscale + ; + +hsync : HSYNC POLARITY + { + VideoMode.hsync = $2; + } + ; + +vsync : VSYNC POLARITY + { + VideoMode.vsync = $2; + } + ; + +csync : CSYNC POLARITY + { + VideoMode.csync = $2; + } + ; + +gsync : GSYNC POLARITY + { + VideoMode.gsync = $2; + } + ; + +extsync : EXTSYNC BOOLEAN + { + VideoMode.extsync = $2; + } + ; + +bcast : BCAST BOOLEAN + { + VideoMode.bcast = $2; + } + ; + +laced : LACED BOOLEAN + { + VideoMode.laced = $2; + } + ; + +double : DOUBLE BOOLEAN + { + VideoMode.dblscan = $2; + } + ; + +rgba : RGBA STRING + { + makeRGBA(&VideoMode, (const char*)$2); + } + ; + +nonstd : NONSTD NUMBER + { + VideoMode.nonstd = $2; + } + ; + +accel : ACCEL BOOLEAN + { + VideoMode.accel_flags = $2; + } + ; + +grayscale : GRAYSCALE BOOLEAN + { + VideoMode.grayscale = $2; + } + ; + +%% diff --git a/nq/source/in_dos.c b/libs/video/targets/in_dos.c similarity index 99% rename from nq/source/in_dos.c rename to libs/video/targets/in_dos.c index 99b6b69d1..f46b2af9e 100644 --- a/nq/source/in_dos.c +++ b/libs/video/targets/in_dos.c @@ -309,7 +309,7 @@ IN_MouseMove (void) if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { viewdelta.angles[PITCH] += mouse_y; } else { - if ((in_strafe.state & 1) && noclip_anglehack) + if (in_strafe.state & 1) viewdelta.position[1] -= mouse_y; else viewdelta.position[2] -= mouse_y; diff --git a/libs/video/targets/in_fbdev.c b/libs/video/targets/in_fbdev.c new file mode 100644 index 000000000..73c79019f --- /dev/null +++ b/libs/video/targets/in_fbdev.c @@ -0,0 +1,151 @@ +/* + in_fbdev.c + + fix this! + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/keys.h" + +cvar_t *_windowed_mouse; + +int +fd_blocking (int fd, int on) +{ + int x; + +#if defined(_POSIX_SOURCE) || !defined(FIONBIO) +#if !defined(O_NONBLOCK) +# if defined(O_NDELAY) +# define O_NONBLOCK O_NDELAY +# endif +#endif + if ((x = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if (on) + x &= ~O_NONBLOCK; + else + x |= O_NONBLOCK; + + return fcntl(fd, F_SETFL, x); +#else + x = !on; + + return ioctl(fd, FIONBIO, &x); +#endif +} + +static struct termios old_tty, new_tty; +static int tty_fd = 0; + +void +IN_Init (void) +{ + fd_blocking(0, 0); + tcgetattr(tty_fd, &old_tty); + new_tty = old_tty; + new_tty.c_cc[VMIN] = 1; + new_tty.c_cc[VTIME] = 0; + new_tty.c_lflag &= ~ICANON; + new_tty.c_iflag &= ~IXON; + tcsetattr(tty_fd, TCSADRAIN, &new_tty); +} + +void +IN_Init_Cvars (void) +{ +} + +void +IN_Shutdown (void) +{ +} + +void +IN_SendKeyEvents (void) +{ + int k, down; + char buf[4]; + + if (read(0, buf, 1) == 1) { + k = buf[0]; + switch (k) { + case '\r': + case '\n': + k = K_ENTER; + break; + case '\033': + if (read(0, buf, 2) != 2) + break; + switch (buf[1]) { + case 'A': + k = K_UPARROW; + break; + case 'B': + k = K_DOWNARROW; + break; + case 'C': + k = K_RIGHTARROW; + break; + case 'D': + k = K_LEFTARROW; + break; + } + break; + } + down = 1; + Key_Event(k, -1, down); + Key_Event(k, -1, !down); + } +} + +void +IN_Commands (void) +{ +} + +void +IN_Move (void) +{ +} + +/* + IN_ModeChanged +*/ +void +IN_ModeChanged (void) +{ +} diff --git a/nq/include/sbar.h b/libs/video/targets/in_null.c similarity index 57% rename from nq/include/sbar.h rename to libs/video/targets/in_null.c index 1b819365a..4a606c77e 100644 --- a/nq/include/sbar.h +++ b/libs/video/targets/in_null.c @@ -1,7 +1,7 @@ /* - sbar.h + in_null.c - @description@ + for systems without a mouse Copyright (C) 1996-1997 Id Software, Inc. @@ -26,23 +26,39 @@ $Id$ */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -// the status bar is only redrawn if something has changed, but if anything -// does, the entire thing will be redrawn for the next vid.numpages frames. +void +IN_Init (void) +{ +} -#define SBAR_HEIGHT 24 +void +IN_Init_Cvars (void) +{ +} -extern int sb_lines; // scan lines to draw +void +IN_Shutdown (void) +{ +} -void Sbar_Init (void); +void +IN_Commands (void) +{ +} -void Sbar_Changed (void); -// call whenever any of the client stats represented on the sbar changes +void +IN_Move (usercmd_t *cmd) +{ +} -void Sbar_Draw (void); -// called every frame by screen - -void Sbar_IntermissionOverlay (void); -// called each frame after the level has been completed - -void Sbar_FinaleOverlay (void); +/* + IN_ModeChanged +*/ +void +IN_ModeChanged (void) +{ +} diff --git a/libs/video/targets/in_sdl.c b/libs/video/targets/in_sdl.c new file mode 100644 index 000000000..96ba9a8a3 --- /dev/null +++ b/libs/video/targets/in_sdl.c @@ -0,0 +1,432 @@ +/* + in_sdl.c + + general sdl input driver + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "client.h" +#include "cl_input.h" +#include "cl_main.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "draw.h" +#include "QF/input.h" +#include "QF/joystick.h" +#include "QF/keys.h" +#include "QF/sys.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "view.h" // FIXME: probable evil + +#ifdef WIN32 +// FIXME: this is evil... +# include +HWND mainwindow; +#endif + +cvar_t *m_filter; +cvar_t *_windowed_mouse; +int old_windowed_mouse; + +int modestate; // FIXME: just to avoid cross-comp. + + // errors - remove later + +static qboolean mouse_avail; +static float mouse_x, mouse_y; +static float old_mouse_x, old_mouse_y; +static int mouse_oldbuttonstate = 0; + +extern viddef_t vid; // global video state + +/* + IN_SendKeyEvents +*/ + +void +IN_SendKeyEvents (void) +{ + SDL_Event event; + int sym, state, but; + int modstate; + + while (SDL_PollEvent (&event)) { + switch (event.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + sym = event.key.keysym.sym; + state = event.key.state; + modstate = SDL_GetModState (); + switch (sym) { + case SDLK_DELETE: + sym = K_DEL; + break; + case SDLK_BACKSPACE: + sym = K_BACKSPACE; + break; + case SDLK_F1: + sym = K_F1; + break; + case SDLK_F2: + sym = K_F2; + break; + case SDLK_F3: + sym = K_F3; + break; + case SDLK_F4: + sym = K_F4; + break; + case SDLK_F5: + sym = K_F5; + break; + case SDLK_F6: + sym = K_F6; + break; + case SDLK_F7: + sym = K_F7; + break; + case SDLK_F8: + sym = K_F8; + break; + case SDLK_F9: + sym = K_F9; + break; + case SDLK_F10: + sym = K_F10; + break; + case SDLK_F11: + sym = K_F11; + break; + case SDLK_F12: + sym = K_F12; + break; + case SDLK_BREAK: + case SDLK_PAUSE: + sym = K_PAUSE; + break; + case SDLK_UP: + sym = K_UPARROW; + break; + case SDLK_DOWN: + sym = K_DOWNARROW; + break; + case SDLK_RIGHT: + sym = K_RIGHTARROW; + break; + case SDLK_LEFT: + sym = K_LEFTARROW; + break; + case SDLK_INSERT: + sym = K_INS; + break; + case SDLK_HOME: + sym = K_HOME; + break; + case SDLK_END: + sym = K_END; + break; + case SDLK_PAGEUP: + sym = K_PGUP; + break; + case SDLK_PAGEDOWN: + sym = K_PGDN; + break; + case SDLK_RSHIFT: + case SDLK_LSHIFT: + sym = K_SHIFT; + break; + case SDLK_RCTRL: + case SDLK_LCTRL: + sym = K_CTRL; + break; + case SDLK_RALT: + case SDLK_LALT: + sym = K_ALT; + break; + case SDLK_CAPSLOCK: + sym = K_CAPSLOCK; + break; + case SDLK_KP0: + if (modstate & KMOD_NUM) + sym = K_INS; + else + sym = SDLK_0; + break; + case SDLK_KP1: + if (modstate & KMOD_NUM) + sym = K_END; + else + sym = SDLK_1; + break; + case SDLK_KP2: + if (modstate & KMOD_NUM) + sym = K_DOWNARROW; + else + sym = SDLK_2; + break; + case SDLK_KP3: + if (modstate & KMOD_NUM) + sym = K_PGDN; + else + sym = SDLK_3; + break; + case SDLK_KP4: + if (modstate & KMOD_NUM) + sym = K_LEFTARROW; + else + sym = SDLK_4; + break; + case SDLK_KP5: + sym = SDLK_5; + break; + case SDLK_KP6: + if (modstate & KMOD_NUM) + sym = K_RIGHTARROW; + else + sym = SDLK_6; + break; + case SDLK_KP7: + if (modstate & KMOD_NUM) + sym = K_HOME; + else + sym = SDLK_7; + break; + case SDLK_KP8: + if (modstate & KMOD_NUM) + sym = K_UPARROW; + else + sym = SDLK_8; + break; + case SDLK_KP9: + if (modstate & KMOD_NUM) + sym = K_PGUP; + else + sym = SDLK_9; + break; + case SDLK_KP_PERIOD: + if (modstate & KMOD_NUM) + sym = K_DEL; + else + sym = SDLK_PERIOD; + break; + case SDLK_KP_DIVIDE: + sym = SDLK_SLASH; + break; + case SDLK_KP_MULTIPLY: + sym = SDLK_ASTERISK; + break; + case SDLK_KP_MINUS: + sym = SDLK_MINUS; + break; + case SDLK_KP_PLUS: + sym = SDLK_PLUS; + break; + case SDLK_KP_ENTER: + sym = SDLK_RETURN; + break; + case SDLK_KP_EQUALS: + sym = SDLK_EQUALS; + break; + } + // If we're not directly handled and still above 255 + // just force it to 0 + if (sym > 255) + sym = 0; + Key_Event (sym, -1, state); + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + but = event.button.button; + if (but == 2) + but = 3; + else if (but == 3) + but = 2; + + switch (but) { + case 1: + case 2: + case 3: + Key_Event (K_MOUSE1 + but - 1, 0, event.type + == SDL_MOUSEBUTTONDOWN); + break; + case 4: + Key_Event (K_MWHEELUP, 0, + event.type == SDL_MOUSEBUTTONDOWN); + break; + case 5: + Key_Event (K_MWHEELDOWN, 0, + event.type == SDL_MOUSEBUTTONDOWN); + break; + } + break; + + case SDL_MOUSEMOTION: + if (_windowed_mouse->value) { + if ((event.motion.x != (vid.width / 2)) + || (event.motion.y != (vid.height / 2))) { + // *2 for vid_sdl.c, *10 for vid_sgl.c. + mouse_x = event.motion.xrel * 5; + mouse_y = event.motion.yrel * 5; + if ( + (event.motion.x < + ((vid.width / 2) - (vid.width / 4))) + || (event.motion.x > + ((vid.width / 2) + (vid.width / 4))) + || (event.motion.y < + ((vid.height / 2) - (vid.height / 4))) + || (event.motion.y > + ((vid.height / 2) + (vid.height / 4)))) + SDL_WarpMouse (vid.width / 2, vid.height / 2); + } + } else { + // following are *2 in vid_sdl.c, vid_sgl.c is *10 + mouse_x = event.motion.xrel * 5; + mouse_y = event.motion.yrel * 5; + } + break; + + case SDL_QUIT: + CL_Disconnect (); + Sys_Quit (); + break; + default: + break; + } + } +} + + +void +IN_Commands (void) +{ + JOY_Command (); + + if (old_windowed_mouse != _windowed_mouse->value) { + old_windowed_mouse = _windowed_mouse->value; + if (!_windowed_mouse->value) { +// SDL_ShowCursor (0); + SDL_WM_GrabInput (SDL_GRAB_OFF); + } else { + SDL_WM_GrabInput (SDL_GRAB_ON); +// SDL_ShowCursor (1); + } + } +} + +void +IN_Init (void) +{ + JOY_Init (); + + if (COM_CheckParm ("-nomouse") && !_windowed_mouse->value) + return; + + mouse_x = mouse_y = 0.0; + mouse_avail = 1; +// SDL_ShowCursor (0); +// SDL_WM_GrabInput (SDL_GRAB_ON); +// FIXME: disable DGA if in_dgamouse says to. +} + +void +IN_Init_Cvars (void) +{ + JOY_Init_Cvars (); + + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, "If set to 1, quake will grab the mouse in X"); + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, "Toggle mouse input filtering"); +} + +void +IN_Shutdown (void) +{ + mouse_avail = 0; +} + +void +IN_Frame (void) +{ + int i; + int mouse_buttonstate; + + if (!mouse_avail) + return; + + i = SDL_GetMouseState (NULL, NULL); + /* Quake swaps the second and third buttons */ + mouse_buttonstate = (i & ~0x06) | ((i & 0x02) << 1) | ((i & 0x04) >> 1); + for (i = 0; i < 3; i++) { + if ((mouse_buttonstate & (1 << i)) + && !(mouse_oldbuttonstate & (1 << i))) Key_Event (K_MOUSE1 + i, 0, + true); + + if (!(mouse_buttonstate & (1 << i)) + && (mouse_oldbuttonstate & (1 << i))) Key_Event (K_MOUSE1 + i, 0, + false); + } + mouse_oldbuttonstate = mouse_buttonstate; +} + +void +IN_Move (void) +{ + + JOY_Move (); + + if (!mouse_avail) + return; + + if (m_filter->value) { + mouse_x = (mouse_x + old_mouse_x) * 0.5; + mouse_y = (mouse_y + old_mouse_y) * 0.5; + } + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + + if ((in_strafe.state & 1) || (lookstrafe->value && (in_mlook.state & 1))) + viewdelta.position[0] += mouse_x; + else + viewdelta.angles[YAW] -= mouse_x; + + if (freelook && !(in_strafe.state & 1)) { + viewdelta.angles[PITCH] += mouse_y; + } else { + if (in_strafe.state & 1) + viewdelta.position[1] -= mouse_y; + else + viewdelta.position[2] -= mouse_y; + } + mouse_x = mouse_y = 0.0; +} diff --git a/nq/source/in_sun.c b/libs/video/targets/in_sun.c similarity index 99% rename from nq/source/in_sun.c rename to libs/video/targets/in_sun.c index f051467ba..7b7a55474 100644 --- a/nq/source/in_sun.c +++ b/libs/video/targets/in_sun.c @@ -258,7 +258,7 @@ IN_Move (void) if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { viewdelta.angles[PITCH] += dy; } else { - if ((in_strafe.state & 1) && noclip_anglehack) + if (in_strafe.state & 1) viewdelta.position[1] -= dy; else viewdelta.position[2] -= dy; diff --git a/libs/video/targets/in_svgalib.c b/libs/video/targets/in_svgalib.c new file mode 100644 index 000000000..77268e16f --- /dev/null +++ b/libs/video/targets/in_svgalib.c @@ -0,0 +1,400 @@ +/* + in_svgalib.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "cl_input.h" +#include "client.h" +#include "QF/cmd.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/input.h" +#include "QF/joystick.h" +#include "QF/keys.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "view.h" + +static int UseKeyboard = 1; +static int UseMouse = 1; +static int in_svgalib_inited = 0; + +static unsigned char scantokey[128]; +static int mouse_buttons; +static int mouse_buttonstate; +static int mouse_oldbuttonstate; +static float mouse_x, mouse_y; +static float old_mouse_x, old_mouse_y; +static int mx, my; + +static void IN_InitKeyboard (void); +static void IN_InitMouse (void); + +cvar_t *_windowed_mouse; +cvar_t *m_filter; + +static void +keyhandler (int scancode, int state) +{ + int sc; + + sc = scancode & 0x7f; +#if 0 + Con_Printf ("scancode=%x (%d%s)\n", scancode, sc, + scancode & 0x80 ? "+128" : ""); +#endif + Key_Event (scantokey[sc], -1, state == KEY_EVENTPRESS); +} + + +static void +mousehandler (int buttonstate, int dx, int dy, int dz, int drx, int dry, int drz) +{ + mouse_buttonstate = buttonstate; + mx += dx; + my += dy; + if (drx > 0) { + Key_Event (K_MWHEELUP, 0, 1); + Key_Event (K_MWHEELUP, 0, 0); + } else if (drx < 0) { + Key_Event (K_MWHEELDOWN, 0, 1); + Key_Event (K_MWHEELDOWN, 0, 0); + } +} + + +void +Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + + +void +IN_Init (void) +{ + if (COM_CheckParm ("-nokbd")) + UseKeyboard = 0; + if (COM_CheckParm ("-nomouse")) + UseMouse = 0; + + if (UseKeyboard) + IN_InitKeyboard (); + if (UseMouse) + IN_InitMouse (); + + JOY_Init (); + + in_svgalib_inited = 1; + return; +} + +void +IN_Init_Cvars (void) +{ + JOY_Init_Cvars (); + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, + "Toggle mouse input filtering."); +} + +static void +IN_InitKeyboard (void) +{ + int i; + + for (i = 0; i < 128; i++) { + scantokey[i] = ' '; + } + + scantokey[1] = K_ESCAPE; + scantokey[2] = '1'; + scantokey[3] = '2'; + scantokey[4] = '3'; + scantokey[5] = '4'; + scantokey[6] = '5'; + scantokey[7] = '6'; + scantokey[8] = '7'; + scantokey[9] = '8'; + scantokey[10] = '9'; + scantokey[11] = '0'; + scantokey[12] = '-'; + scantokey[13] = '='; + scantokey[14] = K_BACKSPACE; + scantokey[15] = K_TAB; + scantokey[16] = 'q'; + scantokey[17] = 'w'; + scantokey[18] = 'e'; + scantokey[19] = 'r'; + scantokey[20] = 't'; + scantokey[21] = 'y'; + scantokey[22] = 'u'; + scantokey[23] = 'i'; + scantokey[24] = 'o'; + scantokey[25] = 'p'; + scantokey[26] = '['; + scantokey[27] = ']'; + scantokey[28] = K_ENTER; + scantokey[29] = K_CTRL; /* left */ + scantokey[30] = 'a'; + scantokey[31] = 's'; + scantokey[32] = 'd'; + scantokey[33] = 'f'; + scantokey[34] = 'g'; + scantokey[35] = 'h'; + scantokey[36] = 'j'; + scantokey[37] = 'k'; + scantokey[38] = 'l'; + scantokey[39] = ';'; + scantokey[40] = '\''; + scantokey[41] = '`'; + scantokey[42] = K_SHIFT; /* left */ + scantokey[43] = '\\'; + scantokey[44] = 'z'; + scantokey[45] = 'x'; + scantokey[46] = 'c'; + scantokey[47] = 'v'; + scantokey[48] = 'b'; + scantokey[49] = 'n'; + scantokey[50] = 'm'; + scantokey[51] = ','; + scantokey[52] = '.'; + scantokey[53] = '/'; + scantokey[54] = K_SHIFT; /* right */ + scantokey[55] = KP_MULTIPLY; + scantokey[56] = K_ALT; /* left */ + scantokey[57] = ' '; + scantokey[58] = K_CAPSLOCK; + scantokey[59] = K_F1; + scantokey[60] = K_F2; + scantokey[61] = K_F3; + scantokey[62] = K_F4; + scantokey[63] = K_F5; + scantokey[64] = K_F6; + scantokey[65] = K_F7; + scantokey[66] = K_F8; + scantokey[67] = K_F9; + scantokey[68] = K_F10; + scantokey[69] = KP_NUMLCK; + scantokey[70] = K_SCRLCK; + scantokey[71] = KP_HOME; + scantokey[72] = KP_UPARROW; + scantokey[73] = KP_PGUP; + scantokey[74] = KP_MINUS; + scantokey[75] = KP_LEFTARROW; + scantokey[76] = KP_5; + scantokey[77] = KP_RIGHTARROW; + scantokey[79] = KP_END; + scantokey[78] = KP_PLUS; + scantokey[80] = KP_DOWNARROW; + scantokey[81] = KP_PGDN; + scantokey[82] = KP_INS; + scantokey[83] = KP_DEL; + /* 84 to 86 not used */ + scantokey[87] = K_F11; + scantokey[88] = K_F12; + /* 89 to 95 not used */ + scantokey[96] = KP_ENTER; /* keypad enter */ + scantokey[97] = K_CTRL; /* right */ + scantokey[98] = KP_DIVIDE; + scantokey[99] = K_PRNTSCR; /* print screen */ + scantokey[100] = K_ALT; /* right */ + + scantokey[101] = K_PAUSE; /* break */ + scantokey[102] = K_HOME; + scantokey[103] = K_UPARROW; + scantokey[104] = K_PGUP; + scantokey[105] = K_LEFTARROW; + scantokey[106] = K_RIGHTARROW; + scantokey[107] = K_END; + scantokey[108] = K_DOWNARROW; + scantokey[109] = K_PGDN; + scantokey[110] = K_INS; + scantokey[111] = K_DEL; + scantokey[119] = K_PAUSE; + + if (keyboard_init ()) { + Sys_Error ("keyboard_init() failed"); + } + keyboard_seteventhandler (keyhandler); +} + +static void +IN_InitMouse (void) +{ + int mtype; + char *mousedev; + int mouserate = MOUSE_DEFAULTSAMPLERATE; + + Cmd_AddCommand ("force_centerview", Force_CenterView_f, "Force viewpoint of player to center"); + + mouse_buttons = 3; + + mtype = vga_getmousetype (); + + mousedev = "/dev/mouse"; + if (getenv ("MOUSEDEV")) + mousedev = getenv ("MOUSEDEV"); + if (COM_CheckParm ("-mdev")) { + mousedev = com_argv[COM_CheckParm ("-mdev") + 1]; + } + + if (getenv ("MOUSERATE")) + mouserate = atoi (getenv ("MOUSERATE")); + if (COM_CheckParm ("-mrate")) { + mouserate = atoi (com_argv[COM_CheckParm ("-mrate") + 1]); + } +#if 0 + printf ("Mouse: dev=%s,type=%s,speed=%d\n", + mousedev, mice[mtype].name, mouserate); +#endif + if (mouse_init (mousedev, mtype, mouserate)) { + Con_Printf ("No mouse found\n"); + UseMouse = 0; + } else { + mouse_seteventhandler ((void *) mousehandler); + } +} + +void +IN_Shutdown (void) +{ + JOY_Shutdown (); + Con_Printf ("IN_Shutdown\n"); + + if (UseMouse) + mouse_close (); + if (UseKeyboard) + keyboard_close (); + in_svgalib_inited = 0; +} + + +void +IN_SendKeyEvents (void) +{ + if (!in_svgalib_inited) + return; + + if (UseKeyboard) { + while ((keyboard_update ())); + } +} + + +void +IN_Commands (void) +{ + JOY_Command (); + if (UseMouse) { + /* Poll mouse values */ + while (mouse_update ()); + + /* Perform button actions */ + if ((mouse_buttonstate & MOUSE_LEFTBUTTON) && + !(mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) + Key_Event (K_MOUSE1, 0, true); + else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) && + (mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) + Key_Event (K_MOUSE1, 0, false); + + if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) && + !(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) + Key_Event (K_MOUSE2, 0, true); + else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) && + (mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) + Key_Event (K_MOUSE2, 0, false); + + if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) && + !(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) + Key_Event (K_MOUSE3, 0, true); + else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) && + (mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) + Key_Event (K_MOUSE3, 0, false); + + mouse_oldbuttonstate = mouse_buttonstate; + } +} + + +void +IN_Move (void) +{ + JOY_Move (); + + if (!UseMouse) + return; + + /* Poll mouse values */ + while (mouse_update ()); + + if (m_filter->int_val) { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } else { + mouse_x = mx; + mouse_y = my; + } + old_mouse_x = mx; + old_mouse_y = my; + /* Clear for next update */ + mx = my = 0; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + + /* Add mouse X/Y movement to cmd */ + if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) { + viewdelta.position[0] += mouse_x; + } else { + viewdelta.angles[YAW] -= mouse_x; + } + + if (freelook && !(in_strafe.state & 1)) { + viewdelta.angles[PITCH] += mouse_y; + } else { + if (in_strafe.state & 1) + viewdelta.position[1] -= mouse_y; + else + viewdelta.position[2] -= mouse_y; + } +} diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c new file mode 100644 index 000000000..9cc009891 --- /dev/null +++ b/libs/video/targets/in_win.c @@ -0,0 +1,668 @@ +/* + in_win.c + + windows 95 mouse stuff + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +// 02/21/97 JCB Added extended DirectInput code to support external controllers. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" +#include +#include "client.h" +#include "QF/keys.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/qargs.h" +#include "QF/cmd.h" +#include "QF/input.h" +#include "cl_input.h" +#include "view.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 public variables + +float mouse_x, mouse_y; +qboolean mouseactive; +unsigned int uiWheelMessage; + +// mouse local variables + +static int mouse_buttons; +static int mouse_oldbuttonstate; +static POINT current_pos; +static float old_mouse_x, old_mouse_y, mx_accum, my_accum; +static qboolean mouseinitialized; +static cvar_t *m_filter; +static qboolean restore_spi; +static int originalmouseparms[3], newmouseparms[3] = { 0, 0, 1 }; +static qboolean mouseparmsvalid, mouseactivatetoggle; +static qboolean mouseshowtoggle = 1; +static qboolean dinput_acquired; +static unsigned int mstate_di; + +// misc locals + +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; + +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, joy + +extern void JOY_Command(void); +extern void JOY_Init_Cvars(void); +extern void JOY_Init (void); +extern void JOY_AdvancedUpdate_f (void); +extern void JOY_Move (void); + +/* + Force_CenterView_f +*/ +static 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 +*/ +static 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_Printf ("Couldn't load dinput.dll\n"); + return false; + } + } + + if (!pDirectInputCreate) { + pDirectInputCreate = + (void *) GetProcAddress (hInstDI, "DirectInputCreateA"); + + if (!pDirectInputCreate) { + Con_Printf ("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_Printf ("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_Printf ("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_Printf ("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_Printf ("Couldn't set DI buffersize\n"); + return false; + } + + return true; +} + + +/* + IN_StartupMouse +*/ +static void +IN_StartupMouse (void) +{ +// HDC hdc; + + if (COM_CheckParm ("-nomouse")) + return; + + mouseinitialized = true; + + if (COM_CheckParm ("-dinput")) { + dinput = IN_InitDInput (); + + if (dinput) { + Con_Printf ("DirectInput initialized\n"); + } else { + Con_Printf ("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) +{ + Cmd_AddCommand ("force_centerview", Force_CenterView_f, "Force view of player to center"); + + uiWheelMessage = RegisterWindowMessage ("MSWHEEL_ROLLMSG"); + + + IN_StartupMouse (); + + JOY_Init (); +} + +void +IN_Init_Cvars (void) +{ + // mouse variables + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, + "Toggle mouse input filtering."); + + JOY_Init_Cvars(); +} + +/* + 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; i < mouse_buttons; i++) { + if ((mstate & (1 << i)) && !(mouse_oldbuttonstate & (1 << i))) { + Key_Event (K_MOUSE1 + i, -1, true); + } + + if (!(mstate & (1 << i)) && (mouse_oldbuttonstate & (1 << i))) { + Key_Event (K_MOUSE1 + i, -1, false); + } + } + + mouse_oldbuttonstate = mstate; + } +} + + +/* + IN_MouseMove +*/ +void +IN_MouseMove (void) +{ + int mx, my; + +// HDC hdc; + int i; + DIDEVICEOBJECTDATA od; + DWORD dwElements; + HRESULT hr; + + if (!mouseactive) + return; + + if (dinput) { + mx = 0; + my = 0; + + for (;;) { + dwElements = 1; + + hr = IDirectInputDevice_GetDeviceData (g_pMouse, + sizeof (DIDEVICEOBJECTDATA), + &od, &dwElements, 0); + + if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED)) { + dinput_acquired = true; + IDirectInputDevice_Acquire (g_pMouse); + break; + } + + /* Unable to read data or no data available */ + if (FAILED (hr) || dwElements == 0) { + break; + } + + /* Look at the element to see what happened */ + + switch (od.dwOfs) { + case DIMOFS_X: + mx += od.dwData; + break; + + case DIMOFS_Y: + my += od.dwData; + break; + + case DIMOFS_BUTTON0: + if (od.dwData & 0x80) + mstate_di |= 1; + else + mstate_di &= ~1; + break; + + case DIMOFS_BUTTON1: + if (od.dwData & 0x80) + mstate_di |= (1 << 1); + else + mstate_di &= ~(1 << 1); + break; + + case DIMOFS_BUTTON2: + if (od.dwData & 0x80) + mstate_di |= (1 << 2); + else + mstate_di &= ~(1 << 2); + break; + } + } + + // perform button actions + for (i = 0; i < mouse_buttons; i++) { + if ((mstate_di & (1 << i)) && !(mouse_oldbuttonstate & (1 << i))) { + Key_Event (K_MOUSE1 + i, -1, true); + } + + if (!(mstate_di & (1 << i)) && (mouse_oldbuttonstate & (1 << i))) { + Key_Event (K_MOUSE1 + i, -1, false); + } + } + + mouse_oldbuttonstate = mstate_di; + } else { + GetCursorPos (¤t_pos); + mx = current_pos.x - window_center_x + mx_accum; + my = current_pos.y - window_center_y + my_accum; + mx_accum = 0; + my_accum = 0; + } + + if (m_filter->value) { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } else { + mouse_x = mx; + mouse_y = my; + } + + old_mouse_x = mx; + old_mouse_y = my; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + +// add mouse X/Y movement to cmd + if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) + viewdelta.position[0] += mouse_x; + else + viewdelta.angles[YAW] -= mouse_x; + + if (freelook && !(in_strafe.state & 1)) { + viewdelta.angles[PITCH] += mouse_y; + } else { + if (in_strafe.state & 1) + viewdelta.position[1] -= mouse_y; + else + viewdelta.position[2] -= 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 (void) +{ + + if (ActiveApp && !Minimized) { + IN_MouseMove (); + JOY_Move (); + } +} + + +/* + IN_Accumulate +*/ +void +IN_Accumulate (void) +{ +// int mx, my; +// HDC hdc; + +// if (dinput) return; // If using dinput we don't probably need this + + 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_Commands +*/ +void +IN_Commands (void) +{ + // Joystick + JOY_Command(); +} diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c new file mode 100644 index 000000000..b5534a7d6 --- /dev/null +++ b/libs/video/targets/in_x11.c @@ -0,0 +1,556 @@ +/* + in_x11.c + + general x11 input driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#define _BSD +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DGA +# include +# include +#endif + +#include "cl_input.h" +#include "client.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "context_x11.h" +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "dga_check.h" +#include "QF/input.h" +#include "QF/joystick.h" +#include "QF/keys.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "view.h" + +cvar_t *_windowed_mouse; +cvar_t *m_filter; + +cvar_t *in_dga; +cvar_t *in_dga_mouseaccel; + +static qboolean dga_avail; +static qboolean dga_active; + +static keydest_t old_key_dest = key_none; + +static qboolean mouse_avail; +static float mouse_x, mouse_y; +static float old_mouse_x, old_mouse_y; +static int p_mouse_x, p_mouse_y; + +#define KEY_MASK (KeyPressMask | KeyReleaseMask) +#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask) +#define INPUT_MASK (KEY_MASK | MOUSE_MASK) + +static int +XLateKey (XKeyEvent * ev, qboolean modified) +{ + char tmp[2]; + int key = 0; + KeySym keysym; + + if (!modified) { + keysym = XLookupKeysym (ev, 0); + } else { + XLookupString (ev, tmp, 1, &keysym, NULL); + } + + switch (keysym) { + case XK_KP_Page_Up: + key = KP_PGUP; + break; + case XK_Page_Up: + key = K_PGUP; + break; + + case XK_KP_Page_Down: + key = KP_PGDN; + break; + case XK_Page_Down: + key = K_PGDN; + break; + + case XK_KP_Home: + key = KP_HOME; + break; + case XK_Home: + key = K_HOME; + break; + + case XK_KP_End: + key = KP_END; + break; + case XK_End: + key = K_END; + break; + + case XK_KP_Left: + key = KP_LEFTARROW; + break; + case XK_Left: + key = K_LEFTARROW; + break; + + case XK_KP_Right: + key = KP_RIGHTARROW; + break; + case XK_Right: + key = K_RIGHTARROW; + break; + + case XK_KP_Down: + key = KP_DOWNARROW; + break; + case XK_Down: + key = K_DOWNARROW; + break; + + case XK_KP_Up: + key = KP_UPARROW; + break; + case XK_Up: + key = K_UPARROW; + break; + + case XK_Escape: + key = K_ESCAPE; + break; + + case XK_KP_Enter: + key = KP_ENTER; + break; + 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: + key = KP_DEL; + break; + 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_Mode_switch: + case XK_Alt_L: + case XK_Meta_L: + case XK_Alt_R: + case XK_Meta_R: + key = K_ALT; + break; + + case XK_Caps_Lock: + key = K_CAPSLOCK; + break; + case XK_KP_Begin: + key = KP_5; + break; + + case XK_Insert: + key = K_INS; + break; + case XK_KP_Insert: + key = KP_INS; + break; + + case XK_KP_Multiply: + key = KP_MULTIPLY; + break; + case XK_KP_Add: + key = KP_PLUS; + break; + case XK_KP_Subtract: + key = KP_MINUS; + break; + case XK_KP_Divide: + key = KP_DIVIDE; + break; + + /* For Sun keyboards */ + case XK_F27: + key = K_HOME; + break; + case XK_F29: + key = K_PGUP; + break; + case XK_F33: + key = K_END; + break; + case XK_F35: + key = K_PGDN; + break; + + default: + if (keysym < 128) { + /* ASCII keys */ + key = keysym; + if (!modified && ((key >= 'A') && (key <= 'Z'))) { + key = key + ('a' - 'A'); + } + } + break; + } + + return key; +} + + +static void +event_key (XEvent * event) +{ + if (old_key_dest != key_dest) { + old_key_dest = key_dest; + if (key_dest == key_game) { + XAutoRepeatOff (x_disp); + } else { + XAutoRepeatOn (x_disp); + } + } + Key_Event (XLateKey (&event->xkey, 0), XLateKey (&event->xkey, 1), + event->type == KeyPress); +} + + +static void +event_button (XEvent * event) +{ + int but; + + but = event->xbutton.button; + if (but == 2) + but = 3; + else if (but == 3) + but = 2; + switch (but) { + case 1: + case 2: + case 3: + Key_Event (K_MOUSE1 + but - 1, 0, event->type == ButtonPress); + break; + case 4: + Key_Event (K_MWHEELUP, 0, event->type == ButtonPress); + break; + case 5: + Key_Event (K_MWHEELDOWN, 0, event->type == ButtonPress); + break; + } +} + + +static void +center_pointer (void) +{ + XEvent event; + + event.type = MotionNotify; + event.xmotion.display = x_disp; + event.xmotion.window = x_win; + event.xmotion.x = vid.width / 2; + event.xmotion.y = vid.height / 2; + XSendEvent (x_disp, x_win, False, PointerMotionMask, &event); + XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, + vid.width / 2, vid.height / 2); +} + + +static void +event_motion (XEvent * event) +{ + if (dga_active) { + mouse_x += event->xmotion.x_root * in_dga_mouseaccel->value; + mouse_y += event->xmotion.y_root * in_dga_mouseaccel->value; + } else { + if (vid_fullscreen->int_val || _windowed_mouse->int_val) { + if (!event->xmotion.send_event) { + mouse_x += (event->xmotion.x - p_mouse_x); + mouse_y += (event->xmotion.y - p_mouse_y); + if (abs (vid.width / 2 - event->xmotion.x) > vid.width / 4 + || abs (vid.height / 2 - event->xmotion.y) > vid.height / 4) { + center_pointer (); + } + } + } else { + mouse_x += (event->xmotion.x - p_mouse_x); + mouse_y += (event->xmotion.y - p_mouse_y); + } + p_mouse_x = event->xmotion.x; + p_mouse_y = event->xmotion.y; + } +} + + +void +IN_Commands (void) +{ + static int old_windowed_mouse; + static int old_in_dga; + + JOY_Command (); + + if ((old_windowed_mouse != _windowed_mouse->int_val) + || (old_in_dga != in_dga->int_val)) { + old_windowed_mouse = _windowed_mouse->int_val; + old_in_dga = in_dga->int_val; + + if (_windowed_mouse->int_val) { // grab the pointer + XGrabPointer (x_disp, x_win, True, MOUSE_MASK, GrabModeAsync, + GrabModeAsync, x_win, None, CurrentTime); +#ifdef HAVE_DGA + if (dga_avail && in_dga->int_val && !dga_active) { + XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), + XF86DGADirectMouse); + dga_active = true; + } +#endif + } else { // ungrab the pointer +#ifdef HAVE_DGA + if (dga_avail && in_dga->int_val && dga_active) { + XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), 0); + dga_active = false; + } +#endif + XUngrabPointer (x_disp, CurrentTime); + } + } +} + + +void +IN_SendKeyEvents (void) +{ + /* Get events from X server. */ + X11_ProcessEvents (); +} + + +void +IN_Move (void) +{ + JOY_Move (); + + if (!mouse_avail) + return; + + if (m_filter->int_val) { + mouse_x = (mouse_x + old_mouse_x) * 0.5; + mouse_y = (mouse_y + old_mouse_y) * 0.5; + } + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + + if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) + viewdelta.position[0] += mouse_x; + else + viewdelta.angles[YAW] -= mouse_x; + + if (freelook && !(in_strafe.state & 1)) { + viewdelta.angles[PITCH] += mouse_y; + } else { + if ((in_strafe.state & 1) && noclip_anglehack) + viewdelta.position[1] -= mouse_y; + else + viewdelta.position[2] -= mouse_y; + } + mouse_x = mouse_y = 0.0; +} + +/* + Called at shutdown +*/ +void +IN_Shutdown (void) +{ + JOY_Shutdown (); + + Con_Printf ("IN_Shutdown\n"); + mouse_avail = 0; + if (x_disp) { + XAutoRepeatOn (x_disp); + +#ifdef HAVE_DGA + if (dga_avail) + XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), 0); +#endif + } + X11_CloseDisplay (); +} + +void +Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + +void +IN_Init (void) +{ + // open the display + if (!x_disp) + Sys_Error ("IN: No display!!\n"); + if (!x_win) + Sys_Error ("IN: No window!!\n"); + + X11_OpenDisplay (); // call to increment the reference counter + + { + int attribmask = CWEventMask; + + XWindowAttributes attribs_1; + XSetWindowAttributes attribs_2; + + XGetWindowAttributes (x_disp, x_win, &attribs_1); + + attribs_2.event_mask = attribs_1.your_event_mask | INPUT_MASK; + + XChangeWindowAttributes (x_disp, x_win, attribmask, &attribs_2); + } + + JOY_Init (); + + XAutoRepeatOff (x_disp); + + if (COM_CheckParm ("-nomouse")) + return; + + dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); + if (vid_fullscreen->int_val) { + Cvar_Set (_windowed_mouse, "1"); + _windowed_mouse->flags |= CVAR_ROM; + } + + mouse_x = mouse_y = 0.0; + mouse_avail = 1; + + X11_AddEvent (KeyPress, &event_key); + X11_AddEvent (KeyRelease, &event_key); + X11_AddEvent (ButtonPress, &event_button); + X11_AddEvent (ButtonRelease, &event_button); + X11_AddEvent (MotionNotify, &event_motion); + + Cmd_AddCommand ("force_centerview", Force_CenterView_f, "Force view of player to center"); +} + +void +IN_Init_Cvars (void) +{ + JOY_Init_Cvars (); + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, + "With this set to 1, quake will grab the mouse from X"); + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, + "Toggle mouse input filtering."); + in_dga = Cvar_Get ("in_dga", "1", CVAR_ARCHIVE, NULL, + "DGA Input support"); + in_dga_mouseaccel = Cvar_Get ("in_dga_mouseaccel", "1", CVAR_ARCHIVE, NULL, + "DGA Mouse accelleration multiplier"); +} + diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c new file mode 100644 index 000000000..35e22e2e4 --- /dev/null +++ b/libs/video/targets/vid_3dfxsvga.c @@ -0,0 +1,329 @@ +/* + vid_3dfxsvga.c + + OpenGL device driver for 3Dfx chipsets running Linux + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "QF/compat.h" +#include "QF/console.h" +#include "glquake.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "QF/qfgl_ext.h" +#include "QF/quakefs.h" +#include "sbar.h" +#include "QF/sys.h" +#include "QF/va.h" + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +// FIXME!!!!! This belongs in include/qfgl_ext.h -- deek +typedef void (GLAPIENTRY * QF_3DfxSetDitherModeEXT) (GrDitherMode_t mode); + +cvar_t *vid_system_gamma; + +static fxMesaContext fc = NULL; + +int VID_options_items = 0; + +extern void GL_Init_Common (void); +extern void VID_Init8bitPalette (void); + +/*-----------------------------------------------------------------------*/ + +void +VID_Shutdown (void) +{ + if (!fc) + return; + + fxMesaDestroyContext (fc); +} + +void +signal_handler (int sig) +{ + printf ("Received signal %d, exiting...\n", sig); + Host_Shutdown (); + abort (); +// Sys_Quit(); + exit (0); +} + +void +InitSig (void) +{ + signal (SIGHUP, signal_handler); + signal (SIGINT, signal_handler); + signal (SIGQUIT, signal_handler); + signal (SIGILL, signal_handler); + signal (SIGTRAP, signal_handler); +// signal(SIGIOT, signal_handler); + signal (SIGBUS, signal_handler); +// signal(SIGFPE, signal_handler); + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); +} + +/* + GL_Init +*/ +void +GL_Init (void) +{ + QF_3DfxSetDitherModeEXT dither_select = NULL; + int p; + + GL_Init_Common (); + + if (!(QFGL_ExtensionPresent ("3DFX_set_dither_mode"))) + return; + + if (!(dither_select = QFGL_ExtensionAddress ("gl3DfxSetDitherModeEXT"))) + return; + + Con_Printf ("Dithering: "); + + if ((p = COM_CheckParm ("-dither")) && p < com_argc) { + if (strequal (com_argv[p+1], "2x2")) { + dither_select (GR_DITHER_2x2); + Con_Printf ("2x2.\n"); + } + if (strequal (com_argv[p+1], "4x4")) { + dither_select (GR_DITHER_4x4); + Con_Printf ("4x4.\n"); + } + } else { + glDisable (GL_DITHER); + Con_Printf ("disabled.\n"); + } +} + +void +GL_EndRendering (void) +{ + glFlush (); + fxMesaSwapBuffers (); + Sbar_Changed (); +} + +static int resolutions[][3] = { + {320, 200, GR_RESOLUTION_320x200}, + {320, 240, GR_RESOLUTION_320x240}, + {400, 256, GR_RESOLUTION_400x256}, + {400, 300, GR_RESOLUTION_400x300}, + {512, 256, GR_RESOLUTION_512x256}, + {512, 384, GR_RESOLUTION_512x384}, + {640, 200, GR_RESOLUTION_640x200}, + {640, 350, GR_RESOLUTION_640x350}, + {640, 400, GR_RESOLUTION_640x400}, + {640, 480, GR_RESOLUTION_640x480}, + {800, 600, GR_RESOLUTION_800x600}, + {856, 480, GR_RESOLUTION_856x480}, + {960, 720, GR_RESOLUTION_960x720}, +#ifdef GR_RESOLUTION_1024x768 + {1024, 768, GR_RESOLUTION_1024x768}, +#endif +#ifdef GR_RESOLUTION_1152x864 + {1152, 864, GR_RESOLUTION_1152x864}, +#endif +#ifdef GR_RESOLUTION_1280x960 + {1280, 960, GR_RESOLUTION_1280x960}, +#endif +#ifdef GR_RESOLUTION_1280x1024 + {1280, 1024, GR_RESOLUTION_1280x1024}, +#endif +#ifdef GR_RESOLUTION_1600x1024 + {1600, 1024, GR_RESOLUTION_1600x1024}, +#endif +#ifdef GR_RESOLUTION_1600x1200 + {1600, 1200, GR_RESOLUTION_1600x1200}, +#endif +#ifdef GR_RESOLUTION_1792x1344 + {1792, 1344, GR_RESOLUTION_1792x1344}, +#endif +#ifdef GR_RESOLUTION_1856x1392 + {1856, 1392, GR_RESOLUTION_1856x1392}, +#endif +#ifdef GR_RESOLUTION_1920x1440 + {1920, 1440, GR_RESOLUTION_1920x1440}, +#endif +#ifdef GR_RESOLUTION_2048x1536 + {2048, 1536, GR_RESOLUTION_2048x1536}, +#endif +#ifdef GR_RESOLUTION_2048x2048 + {2048, 2048, GR_RESOLUTION_2048x2048} +#endif +}; + +#define NUM_RESOLUTIONS (sizeof (resolutions) / (sizeof (int) * 3)) + + +static int +findres (int *width, int *height) +{ + int i; + + for (i = 0; i < NUM_RESOLUTIONS; i++) { + if ((*width <= resolutions[i][0]) && (*height <= resolutions[i][1])) { + *width = resolutions[i][0]; + *height = resolutions[i][1]; + return resolutions[i][2]; + } + } + + *width = 640; + *height = 480; + return GR_RESOLUTION_640x480; +} + +void +VID_Init (unsigned char *palette) +{ + int i; + GLint attribs[32]; + + VID_GetWindowSize (640, 480); + Con_CheckResize (); // Now that we have a window size, fix console + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + + // interpret command-line params + + // set vid parameters + attribs[0] = FXMESA_DOUBLEBUFFER; + attribs[1] = FXMESA_ALPHA_SIZE; + attribs[2] = 1; + attribs[3] = FXMESA_DEPTH_SIZE; + attribs[4] = 1; + attribs[5] = FXMESA_NONE; + + if ((i = COM_CheckParm ("-conwidth"))) + vid.conwidth = atoi (com_argv[i + 1]); + else + vid.conwidth = 640; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + + vid.conwidth = max (vid.conwidth, 320); + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth * 3 / 4; + + if ((i = COM_CheckParm ("-conheight")) != 0) + vid.conheight = atoi (com_argv[i + 1]); + + vid.conheight = max (vid.conheight, 200); + + fc = fxMesaCreateContext (0, findres (&scr_width, &scr_height), + GR_REFRESH_75Hz, attribs); + if (!fc) + Sys_Error ("Unable to create 3DFX context.\n"); + + fxMesaMakeCurrent (fc); + + vid.width = vid.conwidth = min (vid.conwidth, scr_width); + vid.height = vid.conheight = min (vid.conheight, scr_height); + + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.numpages = 2; + + InitSig (); // trap evil signals + + GL_Init (); + + GL_CheckBrightness (palette); + VID_InitGamma (palette); + VID_SetPalette (palette); + + // Check for 3DFX Extensions and initialize them. + VID_Init8bitPalette (); + + Con_Printf ("Video mode %dx%d initialized.\n", scr_width, scr_height); + + vid.recalc_refdef = 1; // force a surface cache flush +} + +void +VID_Init_Cvars (void) +{ + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, "Use system gamma control if available"); +} + +void +VID_ExtraOptionDraw (unsigned int options_draw_cursor) +{ +/* Port specific Options menu entrys */ +} + +void +VID_ExtraOptionCmd (int option_cursor) +{ +/* + switch(option_cursor) + { + case 12: // Always start with 12 + break; + } +*/ +} + +void +VID_SetCaption (char *text) +{ +} + +qboolean +VID_SetGamma (double gamma) +{ + // FIXME: Need function for HW gamma correction + // return X11_SetGamma (gamma); + grGammaCorrectionValue((float) gamma); + return true; + +} + diff --git a/libs/video/targets/vid_common_gl.c b/libs/video/targets/vid_common_gl.c new file mode 100644 index 000000000..3f64cf8bf --- /dev/null +++ b/libs/video/targets/vid_common_gl.c @@ -0,0 +1,395 @@ +/* + vid_common_gl.c + + Common OpenGL video driver functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#ifdef _WIN32 +// must be BEFORE include gl/gl.h +# include "winquake.h" +#endif + +#include + +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "glquake.h" +#include "QF/qfgl_ext.h" +#include "sbar.h" + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +//unsigned short d_8to16table[256]; +unsigned int d_8to24table[256]; +unsigned char d_15to8table[65536]; + +cvar_t *vid_mode; +extern byte gammatable[256]; + +/*-----------------------------------------------------------------------*/ + +int texture_extension_number = 1; +float gldepthmin, gldepthmax; + +const char *gl_vendor; +const char *gl_renderer; +const char *gl_version; +const char *gl_extensions; + +// ARB Multitexture +qboolean gl_mtex_capable = false; +GLenum gl_mtex_enum = GL_TEXTURE0_ARB; + +QF_glColorTableEXT qglColorTableEXT = NULL; +qboolean is8bit = false; + +cvar_t *vid_use8bit; +cvar_t *brightness; +cvar_t *contrast; + +extern int gl_filter_min, gl_filter_max; + +/*-----------------------------------------------------------------------*/ + +void +GL_Common_Init_Cvars (void) +{ + vid_use8bit = Cvar_Get ("vid_use8bit", "0", CVAR_ROM, NULL, "Use 8-bit shared palettes."); + brightness = Cvar_Get ("brightness", "1", CVAR_ARCHIVE, NULL, "Brightness level"); + contrast = Cvar_Get ("contrast", "1", CVAR_ARCHIVE, NULL, "Contrast level"); +} + +/* + CheckMultiTextureExtensions + + Check for ARB multitexture support +*/ +void +CheckMultiTextureExtensions (void) +{ + Con_Printf ("Checking for multitexture: "); + if (COM_CheckParm ("-nomtex")) { + Con_Printf ("disabled.\n"); + return; + } + + if (QFGL_ExtensionPresent ("GL_ARB_multitexture")) { + + int max_texture_units = 0; + + glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &max_texture_units); + if (max_texture_units >= 2) { + Con_Printf ("enabled, %d TMUs.\n", max_texture_units); + qglMultiTexCoord2f = QFGL_ExtensionAddress ("glMultiTexCoord2fARB"); + qglActiveTexture = QFGL_ExtensionAddress ("glActiveTextureARB"); + gl_mtex_enum = GL_TEXTURE0_ARB; + gl_mtex_capable = true; + } else { + Con_Printf ("disabled, not enough TMUs.\n"); + } + } else { + Con_Printf ("not found.\n"); + } +} + +void +VID_SetPalette (unsigned char *palette) +{ + byte *pal; + unsigned int r, g, b; + unsigned int v; + int r1, g1, b1; + int k; + unsigned short i; + unsigned int *table; + QFile *f; + char s[255]; + float dist, bestdist; + static qboolean palflag = false; + +// +// 8 8 8 encoding +// +// Con_Printf("Converting 8to24\n"); + + pal = palette; + table = d_8to24table; + for (i = 0; i < 255; i++) { // used to be i<256, see d_8to24table below + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + +#ifdef WORDS_BIGENDIAN + v = (255 << 0) + (r << 24) + (g << 16) + (b << 8); +#else + v = (255 << 24) + (r << 0) + (g << 8) + (b << 16); +#endif + *table++ = v; + } + d_8to24table[255] = 0; // 255 is transparent + + // JACK: 3D distance calcs - k is last closest, l is the distance. + // FIXME: Precalculate this and cache to disk. + if (palflag) + return; + palflag = true; + + COM_FOpenFile ("glquake/15to8.pal", &f); + if (f) { + Qread (f, d_15to8table, 1 << 15); + Qclose (f); + } else { + 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, bestdist = 10000.0; v < 256; v++, pal += 4) { + r1 = (int) r - (int) pal[0]; + g1 = (int) g - (int) pal[1]; + b1 = (int) b - (int) pal[2]; + dist = sqrt (((r1 * r1) + (g1 * g1) + (b1 * b1))); + if (dist < bestdist) { + k = v; + bestdist = dist; + } + } + d_15to8table[i] = k; + } + snprintf (s, sizeof (s), "%s/glquake/15to8.pal", com_gamedir); + COM_CreatePath (s); + if ((f = Qopen (s, "wb")) != NULL) { + Qwrite (f, d_15to8table, 1 << 15); + Qclose (f); + } + } +} + +/* + GL_Init_Common +*/ +void +GL_Init_Common (void) +{ + GL_Common_Init_Cvars (); + + 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); + + glClearColor (0, 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_filter_min); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + CheckMultiTextureExtensions (); +} + +/* + GL_BeginRendering +*/ +void +GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + *x = *y = 0; + *width = scr_width; + *height = scr_height; +} + +qboolean +VID_Is8bit (void) +{ + return is8bit; +} + + +#ifdef GL_SHARED_TEXTURE_PALETTE_EXT +void +Tdfx_Init8bitPalette (void) +{ + // Check for 8bit Extensions and initialize them. + int i; + + if (is8bit) { + return; + } + + if (QFGL_ExtensionPresent ("3DFX_set_global_palette")) { + + char *oldpal; + GLubyte table[256][4]; + QF_gl3DfxSetPaletteEXT qgl3DfxSetPaletteEXT = NULL; + + if (!(qgl3DfxSetPaletteEXT = QFGL_ExtensionAddress ("gl3DfxSetPaletteEXT"))) { + Con_Printf ("3DFX_set_global_palette not found.\n"); + return; + } + + Con_Printf ("3DFX_set_global_palette.\n"); + + oldpal = (char *) d_8to24table; // d_8to24table3dfx; + for (i = 0; i < 256; i++) { + table[i][2] = *oldpal++; + table[i][1] = *oldpal++; + table[i][0] = *oldpal++; + table[i][3] = 255; + oldpal++; + } + glEnable (GL_SHARED_TEXTURE_PALETTE_EXT); + qgl3DfxSetPaletteEXT ((GLuint *) table); + is8bit = true; + } else { + Con_Printf ("\n 3DFX_set_global_palette not found."); + } +} + +/* + * The GL_EXT_shared_texture_palette seems like an idea which is + * /almost/ a good idea, but seems to be severely broken with many + * drivers, as such it is disabled. + * + * It should be noted, that a palette object extension as suggested by + * the GL_EXT_shared_texture_palette spec might be a very good idea in + * general. + */ +void +Shared_Init8bitPalette (void) +{ + int i; + GLubyte thePalette[256 * 3]; + GLubyte *oldPalette, *newPalette; + + if (is8bit) { + return; + } + + if (QFGL_ExtensionPresent ("GL_EXT_shared_texture_palette")) { + if (!(qglColorTableEXT = QFGL_ExtensionAddress ("glColorTableEXT"))) { + Con_Printf ("glColorTableEXT not found.\n"); + return; + } + + Con_Printf ("GL_EXT_shared_texture_palette\n"); + + glEnable (GL_SHARED_TEXTURE_PALETTE_EXT); + oldPalette = (GLubyte *) d_8to24table; // d_8to24table3dfx; + newPalette = thePalette; + for (i = 0; i < 256; i++) { + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + oldPalette++; + } + qglColorTableEXT (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, + GL_UNSIGNED_BYTE, (GLvoid *) thePalette); + is8bit = true; + } else { + Con_Printf ("\n GL_EXT_shared_texture_palette not found."); + } +} +#endif + +void +VID_Init8bitPalette (void) +{ + Con_Printf ("Checking for 8-bit extension: "); + if (vid_use8bit->int_val) { +#ifdef GL_SHARED_TEXTURE_PALETTE_EXT + Tdfx_Init8bitPalette (); + Shared_Init8bitPalette (); +#endif + if (!is8bit) { + Con_Printf ("\n 8-bit extension not found.\n"); + } + } else { + Con_Printf ("disabled.\n"); + } +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + +void +D_EndDirectRect (int x, int y, int width, int height) +{ +} diff --git a/libs/video/targets/vid_common_sw.c b/libs/video/targets/vid_common_sw.c new file mode 100644 index 000000000..ddd776836 --- /dev/null +++ b/libs/video/targets/vid_common_sw.c @@ -0,0 +1,39 @@ +/* + vid_common_sw.c + + Common software video driver functions + + Copyright (C) 2001 Jeff Teunissen + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/cvar.h" +#include "QF/compat.h" +#include "QF/qargs.h" +#include "QF/vid.h" +#include "view.h" diff --git a/libs/video/targets/vid_dos.c b/libs/video/targets/vid_dos.c new file mode 100644 index 000000000..eeb8d0a05 --- /dev/null +++ b/libs/video/targets/vid_dos.c @@ -0,0 +1,772 @@ +/* + vid_dos.c + + @description@ + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" + +int vid_modenum; +vmode_t *pcurrentmode = NULL; +int vid_testingmode, vid_realmode; +double vid_testendtime; + +cvar_t *vid_mode; +cvar_t *vid_wait; +cvar_t *vid_nopageflip; +cvar_t *_vid_wait_override; +cvar_t *_vid_default_mode; +cvar_t *_vid_default_mode_win; +cvar_t *vid_config_x; +cvar_t *vid_config_y; +cvar_t *vid_stretch_by_2; +cvar_t *_windowed_mouse; +cvar_t *vid_fullscreen_mode; +cvar_t *vid_windowed_mode; +cvar_t *block_switch; +cvar_t *vid_window_x; +cvar_t *vid_window_y; + +int d_con_indirect = 0; + +int numvidmodes; +vmode_t *pvidmodes; + +static int firstupdate = 1; + +extern regs_t regs; + +void VID_TestMode_f (void); +void VID_NumModes_f (void); +void VID_DescribeCurrentMode_f (void); +void VID_DescribeMode_f (void); +void VID_DescribeModes_f (void); + +byte vid_current_palette[768]; // save for mode changes + + +static qboolean nomodecheck = false; + +unsigned short d_8to16table[256]; // not used in 8 bpp mode +unsigned d_8to24table[256]; // not used in 8 bpp mode + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +void +VID_InitCvars (void) +{ +} + + +/* +================ +VID_Init +================ +*/ +void +VID_Init (unsigned char *palette) +{ + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, NULL, "None"); + vid_wait = Cvar_Get ("vid_wait", "0", CVAR_NONE, NULL, "None"); + vid_nopageflip = Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, NULL, + "None"); + _vid_wait_override = + Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE, NULL, "None"); + _vid_default_mode = + Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE, NULL, "None"); + _vid_default_mode_win = + Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE, NULL, "None"); + vid_config_x = Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, NULL, "None"); + vid_config_y = Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, NULL, "None"); + vid_stretch_by_2 = Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, NULL, + "None"); + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, + "None"); + vid_fullscreen_mode = + Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, NULL, "None"); + vid_windowed_mode = + Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, NULL, "None"); + block_switch = Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, NULL, "None"); + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f, "No Description"); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "No Description"); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, + "No Description"); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "No Description"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "No Description"); + +// set up the mode list; note that later inits link in their modes ahead of +// earlier ones, so the standard VGA modes are always first in the list. This +// is important because mode 0 must always be VGA mode 0x13 + if (!COM_CheckParm ("-stdvid")) + VID_InitExtra (); + VGA_Init (); + + vid_testingmode = 0; + + vid_modenum = vid_mode->int_val; + + VID_SetMode (vid_modenum, palette); + + vid_realmode = vid_modenum; + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t * +VID_GetModePtr (int modenum) +{ + vmode_t *pv; + + pv = pvidmodes; + if (!pv) + Sys_Error ("VID_GetModePtr: empty vid mode list"); + + while (modenum--) { + pv = pv->pnext; + if (!pv) + Sys_Error ("VID_GetModePtr: corrupt vid mode list"); + } + + return pv; +} + +/* +================ +VID_NumModes +================ +*/ +int +VID_NumModes () +{ + return (numvidmodes); +} + + +/* +================ +VID_ModeInfo +================ +*/ +char * +VID_ModeInfo (int modenum, char **ppheader) +{ + static char *badmodestr = "Bad mode number"; + vmode_t *pv; + + pv = VID_GetModePtr (modenum); + + if (!pv) { + if (ppheader) + *ppheader = NULL; + return badmodestr; + } else { + if (ppheader) + *ppheader = pv->header; + return pv->name; + } +} + + +/* +================ +VID_SetMode +================ +*/ +int +VID_SetMode (int modenum, unsigned char *palette) +{ + int stat; + vmode_t *pnewmode, *poldmode; + + if ((modenum >= numvidmodes) || (modenum < 0)) { + Cvar_SetValue (vid_mode, (float) vid_modenum); + + nomodecheck = true; + Con_Printf ("No such video mode: %d\n", modenum); + nomodecheck = false; + + if (pcurrentmode == NULL) { + modenum = 0; // mode hasn't been set yet, so + // initialize to base + // mode since they gave us an invalid initial mode + } else { + return 0; + } + } + + pnewmode = VID_GetModePtr (modenum); + + if (pnewmode == pcurrentmode) + return 1; // already in the desired mode + +// initialize the new mode + poldmode = pcurrentmode; + pcurrentmode = pnewmode; + + vid.width = pcurrentmode->width; + vid.height = pcurrentmode->height; + vid.aspect = pcurrentmode->aspect; + vid.rowbytes = pcurrentmode->rowbytes; + + stat = (*pcurrentmode->setmode) (&vid, pcurrentmode); + + if (stat < 1) { + if (stat == 0) { + // real, hard failure that requires resetting the mode + if (!VID_SetMode (vid_modenum, palette)) // restore prior mode + Sys_Error ("VID_SetMode: Unable to set any mode, probably " + "because there's not enough memory available"); + Con_Printf ("Failed to set mode %d\n", modenum); + return 0; + } else if (stat == -1) { + // not enough memory; just put things back the way they were + pcurrentmode = poldmode; + vid.width = pcurrentmode->width; + vid.height = pcurrentmode->height; + vid.aspect = pcurrentmode->aspect; + vid.rowbytes = pcurrentmode->rowbytes; + return 0; + } else { + Sys_Error ("VID_SetMode: invalid setmode return code %d"); + } + } + + (*pcurrentmode->setpalette) (&vid, pcurrentmode, palette); + + vid_modenum = modenum; + Cvar_SetValue (vid_mode, (float) vid_modenum); + + nomodecheck = true; + Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); + nomodecheck = false; + + vid.recalc_refdef = 1; + + return 1; +} + + +/* +================ +VID_SetPalette +================ +*/ +void +VID_SetPalette (unsigned char *palette) +{ + if (palette != vid_current_palette) + Q_memcpy (vid_current_palette, palette, 768); + (*pcurrentmode->setpalette) (&vid, pcurrentmode, vid_current_palette); +} + + +/* +================ +VID_ShiftPalette +================ +*/ +void +VID_ShiftPalette (unsigned char *palette) +{ + + VID_SetPalette (palette); +} + + +/* +================ +VID_Shutdown +================ +*/ +void +VID_Shutdown (void) +{ + + regs.h.ah = 0; + regs.h.al = 0x3; + dos_int86 (0x10); + + vid_testingmode = 0; +} + + +/* +================ +VID_Update +================ +*/ +void +VID_Update (vrect_t *rects) +{ + if (firstupdate && _vid_default_mode->int_val) { + if (_vid_default_mode->int_val >= numvidmodes) + Cvar_SetValue (_vid_default_mode, 0); + + firstupdate = 0; + Cvar_SetValue (vid_mode, _vid_default_mode->int_val); + } + + (*pcurrentmode->swapbuffers) (&vid, pcurrentmode, rects); + + if (!nomodecheck) { + if (vid_testingmode) { + if (realtime >= vid_testendtime) { + VID_SetMode (vid_realmode, vid_current_palette); + vid_testingmode = 0; + } + } else { + if (vid_mode->int_val != vid_realmode) { + VID_SetMode (vid_mode->int_val, vid_current_palette); + 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; + } + } + } +} + + +/* +================= +VID_NumModes_f +================= +*/ +void +VID_NumModes_f (void) +{ + int nummodes; + + nummodes = VID_NumModes (); + if (nummodes == 1) + Con_Printf ("%d video mode is available\n", VID_NumModes ()); + else + Con_Printf ("%d video modes are available\n", VID_NumModes ()); +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void +VID_DescribeCurrentMode_f (void) +{ + Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void +VID_DescribeMode_f (void) +{ + int modenum; + + modenum = Q_atoi (Cmd_Argv (1)); + + Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL)); +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void +VID_DescribeModes_f (void) +{ + int i, nummodes; + char *pinfo, *pheader; + vmode_t *pv; + qboolean na; + + na = false; + + nummodes = VID_NumModes (); + for (i = 0; i < nummodes; i++) { + pv = VID_GetModePtr (i); + pinfo = VID_ModeInfo (i, &pheader); + if (pheader) + Con_Printf ("\n%s\n", pheader); + + if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes, + (pv->numpages == 1) + || vid_nopageflip->int_val)) { + 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_GetModeDescription +================= +*/ +char * +VID_GetModeDescription (int mode) +{ + char *pinfo, *pheader; + vmode_t *pv; + + pv = VID_GetModePtr (mode); + pinfo = VID_ModeInfo (mode, &pheader); + + if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes, + (pv->numpages == 1) || vid_nopageflip->int_val)) { + return pinfo; + } else { + return NULL; + } +} + + +/* +================= +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_current_palette)) { + vid_testingmode = 1; + testduration = Q_atof (Cmd_Argv (2)); + if (testduration == 0) + testduration = 5.0; + vid_testendtime = realtime + testduration; + } + } +} + + +/* +================ +D_BeginDirectRect +================ +*/ +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ + + if (!vid.direct || !pcurrentmode) + return; + + if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) + return; + + if (width & 0x03) + return; + + (*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width, + height); +} + + +/* +================ +D_EndDirectRect +================ +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ + + if (!vid.direct || !pcurrentmode) + return; + + if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) + return; + + if ((width & 0x03) || (height & 0x03)) + return; + + (*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height); +} + + +//=========================================================================== + +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, vid_column_size; + +typedef struct { + int modenum; + char *desc; + int iscur; +} modedesc_t; + +#define MAX_COLUMN_SIZE 11 + +#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 nummodes, i, j, column, row, dup; + char temp[100]; + + vid_wmodes = 0; + nummodes = VID_NumModes (); + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ((320 - p->width) / 2, 4, p); + + for (i = 0; i < nummodes; i++) { + if (vid_wmodes < MAX_MODEDESCS) { + if (i != 1) { + ptr = VID_GetModeDescription (i); + + if (ptr) { + dup = 0; + + for (j = 0; j < vid_wmodes; j++) { + if (!strcmp (modedescs[j].desc, ptr)) { + if (modedescs[j].modenum != 0) { + modedescs[j].modenum = i; + dup = 1; + + if (i == vid_modenum) + modedescs[j].iscur = 1; + } else { + dup = 1; + } + + break; + } + } + + if (!dup) { + modedescs[vid_wmodes].modenum = i; + modedescs[vid_wmodes].desc = ptr; + modedescs[vid_wmodes].iscur = 0; + + if (i == vid_modenum) + modedescs[vid_wmodes].iscur = 1; + + vid_wmodes++; + } + } + } + } + } + + vid_column_size = (vid_wmodes + 2) / 3; + + column = 16; + row = 36; + + for (i = 0; i < vid_wmodes; i++) { + if (modedescs[i].iscur) + M_PrintWhite (column, row, modedescs[i].desc); + else + M_Print (column, row, modedescs[i].desc); + + row += 8; + + if ((i % vid_column_size) == (vid_column_size - 1)) { + column += 13 * 8; + row = 36; + } + } + +// line cursor + if (vid_testingmode) { + snprintf (temp, sizeof (temp), "TESTING %s", modedescs[vid_line].desc); + M_Print (13 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 4, temp); + M_Print (9 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 6, + "Please wait 5 seconds..."); + } else { + M_Print (9 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8, + "Press Enter to set mode"); + M_Print (6 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 3, + "T to test mode for 5 seconds"); + ptr = VID_GetModeDescription (vid_modenum); + snprintf (temp, sizeof (temp), "D to make %s the default", ptr); + M_Print (6 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 5, temp); + ptr = VID_GetModeDescription (_vid_default_mode->int_val); + + if (ptr) { + snprintf (temp, sizeof (temp), "Current default is %s", ptr); + M_Print (7 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 6, temp); + } + + M_Print (15 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 8, "Esc to exit"); + + row = 36 + (vid_line % vid_column_size) * 8; + column = 8 + (vid_line / vid_column_size) * 13 * 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_UPARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line--; + + if (vid_line < 0) + vid_line = vid_wmodes - 1; + break; + + case K_DOWNARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line++; + + if (vid_line >= vid_wmodes) + vid_line = 0; + break; + + case K_LEFTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line -= vid_column_size; + + if (vid_line < 0) { + vid_line += ((vid_wmodes + (vid_column_size - 1)) / + vid_column_size) * vid_column_size; + + while (vid_line >= vid_wmodes) + vid_line -= vid_column_size; + } + break; + + case K_RIGHTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line += vid_column_size; + + if (vid_line >= vid_wmodes) { + vid_line -= ((vid_wmodes + (vid_column_size - 1)) / + vid_column_size) * vid_column_size; + + while (vid_line < 0) + vid_line += vid_column_size; + } + break; + + case K_ENTER: + S_LocalSound ("misc/menu1.wav"); + VID_SetMode (modedescs[vid_line].modenum, vid_current_palette); + break; + + case 'T': + case 't': + S_LocalSound ("misc/menu1.wav"); + if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette)) { + vid_testingmode = 1; + vid_testendtime = realtime + 5.0; + } + break; + + case 'D': + case 'd': + S_LocalSound ("misc/menu1.wav"); + firstupdate = 0; + Cvar_SetValue (_vid_default_mode, vid_modenum); + break; + + default: + break; + } +} + + +void +VID_HandlePause (qboolean pause) +{ +} diff --git a/libs/video/targets/vid_ext.c b/libs/video/targets/vid_ext.c new file mode 100644 index 000000000..d8adaeea2 --- /dev/null +++ b/libs/video/targets/vid_ext.c @@ -0,0 +1,773 @@ + +/* + vid_ext.c + + @description@ + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" +#include + +#define MODE_SUPPORTED_IN_HW 0x0001 +#define COLOR_MODE 0x0008 +#define GRAPHICS_MODE 0x0010 +#define VGA_INCOMPATIBLE 0x0020 +#define LINEAR_FRAME_BUFFER 0x0080 + +#define LINEAR_MODE 0x4000 + +#define VESA_DONT_WAIT_VSYNC 0 // when page flipping +#define VESA_WAIT_VSYNC 0x80 + +#define MAX_VESA_MODES 30 // we'll just take the first 30 if + // there + // are more +typedef struct { + int pages[3]; // either 2 or 3 is valid + int vesamode; // LINEAR_MODE set if linear mode + void *plinearmem; // linear address of start of frame + // buffer + qboolean vga_incompatible; +} vesa_extra_t; + +static vmode_t vesa_modes[MAX_VESA_MODES] = + { {NULL, NULL, " ********* VESA modes ********* "} }; +static vesa_extra_t vesa_extra[MAX_VESA_MODES]; +static char names[MAX_VESA_MODES][10]; + +extern regs_t regs; + +static int VID_currentpage; +static int VID_displayedpage; +static int *VID_pagelist; +static byte *VID_membase; +static int VID_banked; + +typedef struct { + int modenum; + int mode_attributes; + int winasegment; + int winbsegment; + int bytes_per_scanline; // bytes per logical scanline (+16) + int win; // window number (A=0, B=1) + int win_size; // window size (+6) + int granularity; // how finely i can set the window in + // + // + // vid mem (+4) + int width, height; // displayed width and height (+18, + // +20) + int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 + // + // + // (+25) + int bytes_per_pixel; // er, better be 1, 2, or 4 + int memory_model; // and better be 4 or 6, packed or + // direct color (+27) + int num_pages; // number of complete frame buffer + // pages (+29) + int red_width; // the # of bits in the red component + // + // + // (+31) + int red_pos; // the bit position of the red + // component (+32) + int green_width; // etc.. (+33) + int green_pos; // (+34) + int blue_width; // (+35) + int blue_pos; // (+36) + int pptr; + int pagesize; + int numpages; +} modeinfo_t; + +static modeinfo_t modeinfo; + +// all bytes to avoid problems with compiler field packing +typedef struct vbeinfoblock_s { + byte VbeSignature[4]; + byte VbeVersion[2]; + byte OemStringPtr[4]; + byte Capabilities[4]; + byte VideoModePtr[4]; + byte TotalMemory[2]; + byte OemSoftwareRev[2]; + byte OemVendorNamePtr[4]; + byte OemProductNamePtr[4]; + byte OemProductRevPtr[4]; + byte Reserved[222]; + byte OemData[256]; +} vbeinfoblock_t; + +static int totalvidmem; +static byte *ppal; +qboolean vsync_exists, de_exists; + +qboolean VID_ExtraGetModeInfo (int modenum); +int VID_ExtraInitMode (viddef_t *vid, vmode_t * pcurrentmode); +void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t * pcurrentmode, + + vrect_t *rects); + + +/* +================ +VGA_BankedBeginDirectRect +================ +*/ +void +VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, + int x, int y, byte * pbitmap, int width, int height) +{ + + if (!lvid->direct) + return; + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_displayedpage; + dos_int86 (0x10); + + VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height); + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86 (0x10); +} + + +/* +================ +VGA_BankedEndDirectRect +================ +*/ +void +VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, + int x, int y, int width, int height) +{ + + if (!lvid->direct) + return; + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_displayedpage; + dos_int86 (0x10); + + VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height); + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86 (0x10); +} + + +/* +================ +VID_SetVESAPalette +================ +*/ +void +VID_SetVESAPalette (viddef_t *lvid, vmode_t * pcurrentmode, unsigned char *pal) +{ + int i; + byte *pp; + + UNUSED (lvid); + UNUSED (pcurrentmode); + + pp = ppal; + + for (i = 0; i < 256; i++) { + pp[2] = pal[0] >> 2; + pp[1] = pal[1] >> 2; + pp[0] = pal[2] >> 2; + pp += 4; + pal += 3; + } + + regs.x.ax = 0x4F09; + regs.x.bx = 0; + regs.x.cx = 256; + regs.x.dx = 0; + regs.x.es = ptr2real (ppal) >> 4; + regs.x.di = ptr2real (ppal) & 0xf; + dos_int86 (0x10); + + if (regs.x.ax != 0x4f) + Sys_Error ("Unable to load VESA palette\n"); +} + + + + +/* +================ +VID_ExtraFarToLinear +================ +*/ +void * +VID_ExtraFarToLinear (void *ptr) +{ + int temp; + + temp = (int) ptr; + return real2ptr (((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF)); +} + + +/* +================ +VID_ExtraWaitDisplayEnable +================ +*/ +void +VID_ExtraWaitDisplayEnable () +{ + while ((inportb (0x3DA) & 0x01) == 1); +} + + +/* +================ +VID_ExtraVidLookForState +================ +*/ +qboolean +VID_ExtraVidLookForState (unsigned state, unsigned mask) +{ + int i; + double starttime, time; + + starttime = Sys_DoubleTime (); + + do { + for (i = 0; i < 100000; i++) { + if ((inportb (0x3DA) & mask) == state) + return true; + } + + time = Sys_DoubleTime (); + } while ((time - starttime) < 0.1); + + return false; +} + + +/* +================ +VID_ExtraStateFound +================ +*/ +qboolean +VID_ExtraStateFound (unsigned state) +{ + int i, workingstate; + + workingstate = 0; + + for (i = 0; i < 10; i++) { + if (!VID_ExtraVidLookForState (workingstate, state)) { + return false; + } + + workingstate ^= state; + } + + return true; +} + + +/* +================ +VID_InitExtra +================ +*/ +void +VID_InitExtra (void) +{ + int nummodes; + short *pmodenums; + vbeinfoblock_t *pinfoblock; + __dpmi_meminfo phys_mem_info; + + pinfoblock = dos_getmemory (sizeof (vbeinfoblock_t)); + + *(long *) pinfoblock->VbeSignature = + 'V' + ('B' << 8) + ('E' << 16) + ('2' << 24); + +// see if VESA support is available + regs.x.ax = 0x4f00; + regs.x.es = ptr2real (pinfoblock) >> 4; + regs.x.di = ptr2real (pinfoblock) & 0xf; + dos_int86 (0x10); + + if (regs.x.ax != 0x4f) + return; // no VESA support + + if (pinfoblock->VbeVersion[1] < 0x02) + return; // not VESA 2.0 or greater + + Con_Printf ("VESA 2.0 compliant adapter:\n%s\n", + VID_ExtraFarToLinear (*(byte **) & + pinfoblock->OemStringPtr[0])); + + totalvidmem = *(unsigned short *) &pinfoblock->TotalMemory[0] << 16; + + pmodenums = (short *) + VID_ExtraFarToLinear (*(byte **) & pinfoblock->VideoModePtr[0]); + +// find 8 bit modes until we either run out of space or run out of modes + nummodes = 0; + + while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES)) { + if (VID_ExtraGetModeInfo (*pmodenums)) { + vesa_modes[nummodes].pnext = &vesa_modes[nummodes + 1]; + if (modeinfo.width > 999) { + if (modeinfo.height > 999) { + snprintf (&names[nummodes][0], sizeof (&names[nummodes][0]), + "%4dx%4d", modeinfo.width, modeinfo.height); + names[nummodes][9] = 0; + } else { + snprintf (&names[nummodes][0], sizeof (&names[nummodes][0]), + "%4dx%3d", modeinfo.width, modeinfo.height); + names[nummodes][8] = 0; + } + } else { + if (modeinfo.height > 999) { + snprintf (&names[nummodes][0], sizeof (&names[nummodes][0]), + "%3dx%4d", modeinfo.width, modeinfo.height); + names[nummodes][8] = 0; + } else { + snprintf (&names[nummodes][0], sizeof (&names[nummodes][0]), + "%3dx%3d", modeinfo.width, modeinfo.height); + names[nummodes][7] = 0; + } + } + + vesa_modes[nummodes].name = &names[nummodes][0]; + vesa_modes[nummodes].width = modeinfo.width; + vesa_modes[nummodes].height = modeinfo.height; + vesa_modes[nummodes].aspect = + ((float) modeinfo.height / (float) modeinfo.width) * + (320.0 / 240.0); + vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline; + vesa_modes[nummodes].planar = 0; + vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; + vesa_modes[nummodes].setmode = VID_ExtraInitMode; + vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers; + vesa_modes[nummodes].setpalette = VID_SetVESAPalette; + + if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER) { + // add linear bit to mode for linear modes + vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE; + vesa_extra[nummodes].pages[0] = 0; + vesa_extra[nummodes].pages[1] = modeinfo.pagesize; + vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; + vesa_modes[nummodes].numpages = modeinfo.numpages; + + vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect; + vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect; + + phys_mem_info.address = (int) modeinfo.pptr; + phys_mem_info.size = 0x400000; + + if (__dpmi_physical_address_mapping (&phys_mem_info)) + goto NextMode; + + vesa_extra[nummodes].plinearmem = + real2ptr (phys_mem_info.address); + } else { + // banked at 0xA0000 + vesa_extra[nummodes].vesamode = modeinfo.modenum; + vesa_extra[nummodes].pages[0] = 0; + vesa_extra[nummodes].plinearmem = + real2ptr (modeinfo.winasegment << 4); + + vesa_modes[nummodes].begindirectrect = + VGA_BankedBeginDirectRect; + vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect; + vesa_extra[nummodes].pages[1] = modeinfo.pagesize; + vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; + vesa_modes[nummodes].numpages = modeinfo.numpages; + } + + vesa_extra[nummodes].vga_incompatible = + modeinfo.mode_attributes & VGA_INCOMPATIBLE; + + nummodes++; + } + NextMode: + pmodenums++; + } + +// add the VESA modes at the start of the mode list (if there are any) + if (nummodes) { + vesa_modes[nummodes - 1].pnext = pvidmodes; + pvidmodes = &vesa_modes[0]; + numvidmodes += nummodes; + ppal = dos_getmemory (256 * 4); + } + + dos_freememory (pinfoblock); +} + + +/* +================ +VID_ExtraGetModeInfo +================ +*/ +qboolean +VID_ExtraGetModeInfo (int modenum) +{ + char *infobuf; + int numimagepages; + + infobuf = dos_getmemory (256); + + regs.x.ax = 0x4f01; + regs.x.cx = modenum; + regs.x.es = ptr2real (infobuf) >> 4; + regs.x.di = ptr2real (infobuf) & 0xf; + dos_int86 (0x10); + if (regs.x.ax != 0x4f) { + return false; + } else { + modeinfo.modenum = modenum; + modeinfo.bits_per_pixel = *(char *) (infobuf + 25); + modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel + 1) / 8; + modeinfo.width = *(short *) (infobuf + 18); + modeinfo.height = *(short *) (infobuf + 20); + + // we do only 8-bpp in software + if ((modeinfo.bits_per_pixel != 8) || + (modeinfo.bytes_per_pixel != 1) || + (modeinfo.width > MAXWIDTH) || (modeinfo.height > MAXHEIGHT)) { + return false; + } + + modeinfo.mode_attributes = *(short *) infobuf; + + // we only want color graphics modes that are supported by the + // hardware + if ((modeinfo.mode_attributes & + (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) != + (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) { + return false; + } + // we only work with linear frame buffers, except for 320x200, which + // can + // effectively be linear when banked at 0xA000 + if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)) { + if ((modeinfo.width != 320) || (modeinfo.height != 200)) + return false; + } + + modeinfo.bytes_per_scanline = *(short *) (infobuf + 16); + + modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height; + + if (modeinfo.pagesize > totalvidmem) + return false; + + // force to one page if the adapter reports it doesn't support more + // pages + // than that, no matter how much memory it has--it may not have + // hardware + // support for page flipping + numimagepages = *(unsigned char *) (infobuf + 29); + + if (numimagepages <= 0) { + // wrong, but there seems to be an ATI VESA driver that reports 0 + modeinfo.numpages = 1; + } else if (numimagepages < 3) { + modeinfo.numpages = numimagepages; + } else { + modeinfo.numpages = 3; + } + + if (*(char *) (infobuf + 2) & 5) { + modeinfo.winasegment = *(unsigned short *) (infobuf + 8); + modeinfo.win = 0; + } else if (*(char *) (infobuf + 3) & 5) { + modeinfo.winbsegment = *(unsigned short *) (infobuf + 8); + modeinfo.win = 1; + } + modeinfo.granularity = *(short *) (infobuf + 4) * 1024; + modeinfo.win_size = *(short *) (infobuf + 6) * 1024; + modeinfo.bits_per_pixel = *(char *) (infobuf + 25); + modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel + 1) / 8; + modeinfo.memory_model = *(unsigned char *) (infobuf + 27); + modeinfo.num_pages = *(char *) (infobuf + 29) + 1; + + modeinfo.red_width = *(char *) (infobuf + 31); + modeinfo.red_pos = *(char *) (infobuf + 32); + modeinfo.green_width = *(char *) (infobuf + 33); + modeinfo.green_pos = *(char *) (infobuf + 34); + modeinfo.blue_width = *(char *) (infobuf + 35); + modeinfo.blue_pos = *(char *) (infobuf + 36); + + modeinfo.pptr = *(long *) (infobuf + 40); + +#if 0 + printf ("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum); + printf (" mode attrib = 0x%0x\n", modeinfo.mode_attributes); + printf (" win a attrib = 0x%0x\n", *(unsigned char *) (infobuf + 2)); + printf (" win b attrib = 0x%0x\n", *(unsigned char *) (infobuf + 3)); + printf (" win a seg 0x%0x\n", (int) modeinfo.winasegment); + printf (" win b seg 0x%0x\n", (int) modeinfo.winbsegment); + printf (" bytes per scanline = %d\n", modeinfo.bytes_per_scanline); + printf (" width = %d, height = %d\n", modeinfo.width, modeinfo.height); + printf (" win = %c\n", 'A' + modeinfo.win); + printf (" win granularity = %d\n", modeinfo.granularity); + printf (" win size = %d\n", modeinfo.win_size); + printf (" bits per pixel = %d\n", modeinfo.bits_per_pixel); + printf (" bytes per pixel = %d\n", modeinfo.bytes_per_pixel); + printf (" memory model = 0x%x\n", modeinfo.memory_model); + printf (" num pages = %d\n", modeinfo.num_pages); + printf (" red width = %d\n", modeinfo.red_width); + printf (" red pos = %d\n", modeinfo.red_pos); + printf (" green width = %d\n", modeinfo.green_width); + printf (" green pos = %d\n", modeinfo.green_pos); + printf (" blue width = %d\n", modeinfo.blue_width); + printf (" blue pos = %d\n", modeinfo.blue_pos); + printf (" phys mem = %x\n", modeinfo.pptr); +#endif + } + + dos_freememory (infobuf); + + return true; +} + + +/* +================ +VID_ExtraInitMode +================ +*/ +int +VID_ExtraInitMode (viddef_t *lvid, vmode_t * pcurrentmode) +{ + vesa_extra_t *pextra; + int pageoffset; + + pextra = pcurrentmode->pextradata; + + if (vid_nopageflip->int_val) + lvid->numpages = 1; + else + lvid->numpages = pcurrentmode->numpages; + +// clean up any old vid buffer lying around, alloc new if needed + if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1)) + return -1; // memory alloc failed + +// clear the screen and wait for the next frame. VGA_pcurmode, which +// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is +// always the first mode set in a session + if (VGA_pcurmode) + VGA_ClearVideoMem (VGA_pcurmode->planar); + +// set the mode + regs.x.ax = 0x4f02; + regs.x.bx = pextra->vesamode; + dos_int86 (0x10); + + if (regs.x.ax != 0x4f) + return 0; + + VID_banked = !(pextra->vesamode & LINEAR_MODE); + VID_membase = pextra->plinearmem; + VGA_width = lvid->width; + VGA_height = lvid->height; + VGA_rowbytes = lvid->rowbytes; + + lvid->colormap = vid_colormap; + + VID_pagelist = &pextra->pages[0]; + +// wait for display enable by default only when triple-buffering on a VGA- +// compatible machine that actually has a functioning display enable status + vsync_exists = VID_ExtraStateFound (0x08); + de_exists = VID_ExtraStateFound (0x01); + + if (!pextra->vga_incompatible && + (lvid->numpages == 3) && de_exists && !_vid_wait_override->int_val) { + Cvar_SetValue (vid_wait, (float) VID_WAIT_DISPLAY_ENABLE); + + VID_displayedpage = 0; + VID_currentpage = 1; + } else { + if ((lvid->numpages == 1) && !_vid_wait_override->int_val) { + Cvar_SetValue (vid_wait, (float) VID_WAIT_NONE); + VID_displayedpage = VID_currentpage = 0; + } else { + Cvar_SetValue (vid_wait, (float) VID_WAIT_VSYNC); + + VID_displayedpage = 0; + + if (lvid->numpages > 1) + VID_currentpage = 1; + else + VID_currentpage = 0; + } + } + +// TODO: really should be a call to a function + pageoffset = VID_pagelist[VID_displayedpage]; + + regs.x.ax = 0x4f07; + regs.x.bx = 0x80; // wait for vsync so we know page 0 + // is visible + regs.x.cx = pageoffset % VGA_rowbytes; + regs.x.dx = pageoffset / VGA_rowbytes; + dos_int86 (0x10); + + if (VID_banked) { + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86 (0x10); + + VGA_pagebase = VID_membase; + } else { + VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage]; + } + + if (lvid->numpages > 1) { + lvid->buffer = VGA_pagebase; + lvid->conbuffer = lvid->buffer; + } else { + lvid->rowbytes = lvid->width; + } + + lvid->direct = VGA_pagebase; + lvid->conrowbytes = lvid->rowbytes; + lvid->conwidth = lvid->width; + lvid->conheight = lvid->height; + + lvid->maxwarpwidth = WARP_WIDTH; + lvid->maxwarpheight = WARP_HEIGHT; + + VGA_pcurmode = pcurrentmode; + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + return 1; +} + + +/* +================ +VID_ExtraSwapBuffers +================ +*/ +void +VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t * pcurrentmode, vrect_t *rects) +{ + int pageoffset; + + UNUSED (rects); + UNUSED (pcurrentmode); + + pageoffset = VID_pagelist[VID_currentpage]; + +// display the newly finished page + if (lvid->numpages > 1) { + // page flipped + regs.x.ax = 0x4f07; + + if (vid_wait->int_val != VID_WAIT_VSYNC) { + if ((vid_wait->int_val == VID_WAIT_DISPLAY_ENABLE) && de_exists) + VID_ExtraWaitDisplayEnable (); + + regs.x.bx = VESA_DONT_WAIT_VSYNC; + } else { + regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait + } + + regs.x.cx = pageoffset % VGA_rowbytes; + regs.x.dx = pageoffset / VGA_rowbytes; + dos_int86 (0x10); + + VID_displayedpage = VID_currentpage; + if (++VID_currentpage >= lvid->numpages) + VID_currentpage = 0; + + // + // set the new write window if this is a banked mode; otherwise, set + // the + // new address to which to write + // + if (VID_banked) { + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86 (0x10); + } else { + lvid->direct = lvid->buffer; // direct drawing goes to the + // currently displayed page + lvid->buffer = VID_membase + VID_pagelist[VID_currentpage]; + lvid->conbuffer = lvid->buffer; + } + + VGA_pagebase = lvid->buffer; + } else { + // non-page-flipped + if (vsync_exists && (vid_wait->int_val == VID_WAIT_VSYNC)) { + VGA_WaitVsync (); + } + + while (rects) { + VGA_UpdateLinearScreen (lvid->buffer + rects->x + + (rects->y * lvid->rowbytes), + VGA_pagebase + rects->x + + (rects->y * VGA_rowbytes), rects->width, + rects->height, lvid->rowbytes, + VGA_rowbytes); + + rects = rects->pnext; + } + } +} + + +void +VID_HandlePause (qboolean pause) +{ +} diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c new file mode 100644 index 000000000..690513df3 --- /dev/null +++ b/libs/video/targets/vid_fbdev.c @@ -0,0 +1,708 @@ +/* + vid_fbdev.c + + Linux FBDev video routines + + based on vid_svgalib.c + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999-2000 David Symonds [xoxus@usa.net] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_IO_H +# include +#elif defined(HAVE_ASM_IO_H) +# include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QF/cmd.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "QF/sys.h" + +#include "fbset.h" + +unsigned short d_8to16table[256]; + +extern void ReadModeDB(void); +extern struct VideoMode *FindVideoMode(const char *name); +void ConvertFromVideoMode(const struct VideoMode *vmode, + struct fb_var_screeninfo *var); +void ConvertToVideoMode(const struct fb_var_screeninfo *var, + struct VideoMode *vmode); + +extern struct VideoMode *VideoModes; +static struct VideoMode current_mode; +static char current_name[32]; +static int num_modes; + +static int fb_fd = -1; +static int tty_fd = 0; + +static byte vid_current_palette[768]; + +static int fbdev_inited = 0; +static int fbdev_backgrounded = 0; +static int UseDisplay = 1; + +static cvar_t *vid_mode; +static cvar_t *vid_redrawfull; +static cvar_t *vid_waitforrefresh; + +static char *framebuffer_ptr; + +static byte backingbuf[48 * 24]; + +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ + int i, j, reps, repshift, offset, off; + + if (!fbdev_inited || !vid.direct || fbdev_backgrounded) + return; + + if (vid.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + offset = x + ((y << repshift) + i + j) + * vid.rowbytes; + off = offset % 0x10000; + memcpy (&backingbuf[(i + j) * 24], vid.direct + off, width); + memcpy (vid.direct + off, + &pbitmap[(i >> repshift) * width], width); + } + } +} + + +void +D_EndDirectRect (int x, int y, int width, int height) +{ + int i, j, reps, repshift, offset, off; + + if (!fbdev_inited || !vid.direct || fbdev_backgrounded) + return; + + if (vid.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + offset = x + ((y << repshift) + i + j) + * vid.rowbytes; + off = offset % 0x10000; + memcpy (vid.direct + off, &backingbuf[(i + j) * 24], width); + } + } +} + + +static void +VID_Gamma_f (void) +{ + float gamma, f, inf; + unsigned char palette[768]; + int i; + + if (Cmd_Argc () == 2) { + gamma = atof (Cmd_Argv (1)); + + for (i = 0; i < 768; i++) { + f = pow ((vid_basepal[i] + 1) / 256.0, gamma); + inf = f * 255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + palette[i] = inf; + } + + VID_SetPalette (palette); + + /* Force a surface cache flush */ + vid.recalc_refdef = 1; + } +} + + +static void +VID_DescribeMode_f (void) +{ + char *modestr; + struct VideoMode *vmode; + + modestr = Cmd_Argv(1); + vmode = FindVideoMode(modestr); + if (!vmode) { + Con_Printf ("Invalid video mode: %s!\n", modestr); + return; + } + Con_Printf ("%s: %d x %d - %d bpp - %5.3f Hz\n", vmode->name, + vmode->xres, vmode->yres, vmode->depth, vmode->vrate); +} + + +static void +VID_DescribeModes_f (void) +{ + struct VideoMode *vmode; + + for (vmode = VideoModes; vmode; vmode = vmode->next) { + Con_Printf ("%s: %d x %d - %d bpp - %5.3f Hz\n", vmode->name, + vmode->xres, vmode->yres, vmode->depth, vmode->vrate); + } +} + + +/* + VID_NumModes +*/ +static int +VID_NumModes (void) +{ + struct VideoMode *vmode; + int i = 0; + + for (vmode = VideoModes; vmode; vmode = vmode->next) + i++; + + return i; +} + + +static void +VID_NumModes_f (void) +{ + Con_Printf ("%d modes\n", VID_NumModes ()); +} + +int VID_SetMode (char *name, unsigned char *palette); + +extern void fbset_main (int argc, char **argv); + +static void +VID_fbset_f (void) +{ + int i, argc; + char *argv[32]; + + argc = Cmd_Argc(); + if (argc > 32) + argc = 32; + argv[0] = "vid_fbset"; + for (i = 1; i < argc; i++) { + argv[i] = Cmd_Argv(i); + } + fbset_main(argc, argv); +} + +static void +VID_Debug_f (void) +{ + Con_Printf ("mode: %s\n", current_mode.name); + Con_Printf ("height x width: %d x %d\n", current_mode.xres, current_mode.yres); + Con_Printf ("bpp: %d\n", current_mode.depth); + Con_Printf ("vrate: %5.3f\n", current_mode.vrate); + Con_Printf ("vid.aspect: %f\n", vid.aspect); +} + + +static void +VID_InitModes (void) +{ + ReadModeDB(); + num_modes = VID_NumModes(); +} + + +static char * +get_mode (char *name, int width, int height, int depth) +{ + struct VideoMode *vmode; + + for (vmode = VideoModes; vmode; vmode = vmode->next) { + if (name) { + if (!strcmp(vmode->name, name)) + return name; + } else { + if (vmode->xres == width + && vmode->yres == height + && vmode->depth == depth) + return vmode->name; + } + } + + Sys_Printf ("Mode %dx%d (%d bits) not supported\n", + width, height, depth); + + return "640x480-60"; +} + + +void +VID_InitBuffers (void) +{ + int buffersize, zbuffersize, cachesize; + void *vid_surfcache; + + // Calculate the sizes we want first + buffersize = vid.rowbytes * vid.height; + zbuffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + cachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + // Free the old screen buffer + if (vid.buffer) { + free (vid.buffer); + vid.conbuffer = vid.buffer = NULL; + } + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new screen buffer + vid.conbuffer = vid.buffer = calloc (buffersize, 1); + if (!vid.conbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new z-buffer + d_pzbuffer = calloc (zbuffersize, 1); + if (!d_pzbuffer) { + free (vid.buffer); + vid.conbuffer = vid.buffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (cachesize, 1); + if (!vid_surfcache) { + free (vid.buffer); + free (d_pzbuffer); + vid.conbuffer = vid.buffer = NULL; + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + + D_InitCaches (vid_surfcache, cachesize); +} + +static unsigned char *fb_map_addr = 0; +static unsigned long fb_map_length = 0; + +static struct fb_var_screeninfo orig_var; + +void +VID_Shutdown (void) +{ + Sys_Printf ("VID_Shutdown\n"); + + if (!fbdev_inited) + return; + + if (munmap(fb_map_addr, fb_map_length) == -1) { + Sys_Printf("could not unmap framebuffer at %p: %s\n", + fb_map_addr, strerror(errno)); + } else { + if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &orig_var)) + Sys_Printf ("failed to get var screen info\n"); + } + close(fb_fd); + + if (UseDisplay) { + ioctl(tty_fd, KDSETMODE, KD_TEXT); + write(tty_fd, "\033]R", 3); /* reset palette */ + } + + fbdev_inited = 0; +} + + +void +VID_ShiftPalette (unsigned char *p) +{ + VID_SetPalette (p); +} + +static void +loadpalette (unsigned short *red, unsigned short *green, unsigned short *blue) +{ + struct fb_cmap cmap; + + cmap.len = 256; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = NULL; + cmap.start = 0; + if (-1 == ioctl(fb_fd, FBIOPUTCMAP, (void *)&cmap)) + Sys_Error("ioctl FBIOPUTCMAP %s\n", strerror(errno)); +} + +void +VID_SetPalette (byte * palette) +{ + static unsigned short tmppalr[256], tmppalg[256], tmppalb[256]; + unsigned short i, *tpr, *tpg, *tpb; + + if (!fbdev_inited || fbdev_backgrounded || fb_fd < 0) + return; + + memcpy (vid_current_palette, palette, sizeof (vid_current_palette)); + + if (current_mode.depth == 8) { + tpr = tmppalr; + tpg = tmppalg; + tpb = tmppalb; + for (i = 0; i < 256; i++) { + *tpr++ = (*palette++) << 8; + *tpg++ = (*palette++) << 8; + *tpb++ = (*palette++) << 8; + } + + if (UseDisplay) { + loadpalette(tmppalr, tmppalg, tmppalb); + } + } +} + +int +VID_SetMode (char *name, unsigned char *palette) +{ + struct VideoMode *vmode; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + int err; + unsigned long smem_start, smem_offset; + + vmode = FindVideoMode(name); + if (!vmode) { + Cvar_Set (vid_mode, current_mode.name); + // Con_Printf ("No such video mode: %s\n", name); + return 0; + } + + current_mode = *vmode; + Cvar_Set (vid_mode, current_mode.name); + strncpy(current_name, current_mode.name, sizeof(current_name)-1); + current_name[31] = 0; + vid.width = vmode->xres; + vid.height = vmode->yres; + vid.rowbytes = vmode->xres * (vmode->depth >> 3); + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.colormap = (pixel_t *) vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + vid.numpages = 1; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + if (fb_map_addr) { + if (munmap(fb_map_addr, fb_map_length) == -1) { + Sys_Printf("could not unmap framebuffer at %p: %s\n", + fb_map_addr, strerror(errno)); + } + } + + ConvertFromVideoMode(¤t_mode, &var); + err = ioctl(fb_fd, FBIOPUT_VSCREENINFO, &var); + if (err) + Sys_Error ("Video mode failed: %s\n", name); + ConvertToVideoMode(&var, ¤t_mode); + current_mode.name = current_name; + VID_SetPalette (palette); + + err = ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix); + if (err) + Sys_Error ("Video mode failed: %s\n", name); + smem_start = (unsigned long)fix.smem_start & PAGE_MASK; + smem_offset = (unsigned long)fix.smem_start & ~PAGE_MASK; + fb_map_length = (smem_offset+fix.smem_len+~PAGE_MASK) & PAGE_MASK; + fb_map_addr = (char *)mmap(0, fb_map_length, PROT_WRITE, MAP_SHARED, fb_fd, 0); + if (!fb_map_addr) + Sys_Error ("This mode isn't hapnin'\n"); + vid.direct = framebuffer_ptr = fb_map_addr; + + // alloc screen buffer, z-buffer, and surface cache + VID_InitBuffers (); + + if (!fbdev_inited) { + fbdev_inited = 1; + } + + /* Force a surface cache flush */ + vid.recalc_refdef = 1; + + return 1; +} + +static void +fb_switch_handler (int sig) +{ + if (sig == SIGUSR1) { + fbdev_backgrounded = 1; + } else if (sig == SIGUSR2) { + fbdev_backgrounded = 2; + } +} + +static void +fb_switch_release (void) +{ + ioctl(tty_fd, VT_RELDISP, 1); +} + +static void +fb_switch_acquire (void) +{ + ioctl(tty_fd, VT_RELDISP, VT_ACKACQ); +} + +static void +fb_switch_init (void) +{ + struct sigaction act; + struct vt_mode vtmode; + + memset(&act, 0, sizeof(act)); + act.sa_handler = fb_switch_handler; + sigemptyset(&act.sa_mask); + sigaction(SIGUSR1, &act, 0); + sigaction(SIGUSR2, &act, 0); + + if (ioctl(tty_fd, VT_GETMODE, &vtmode)) { + Sys_Error("ioctl VT_GETMODE: %s\n", strerror(errno)); + } + vtmode.mode = VT_PROCESS; + vtmode.waitv = 0; + vtmode.relsig = SIGUSR1; + vtmode.acqsig = SIGUSR2; + if (ioctl(tty_fd, VT_SETMODE, &vtmode)) { + Sys_Error("ioctl VT_SETMODE: %s\n", strerror(errno)); + } +} + +void +VID_Init (unsigned char *palette) +{ + int w, h, d; + struct VideoMode *vmode; + char *modestr; + char *fbname; + + // plugin_load("in_fbdev.so"); + + if (fbdev_inited) + return; + + Cmd_AddCommand ("gamma", VID_Gamma_f, "No Description"); + + if (UseDisplay) { + fbname = getenv("FRAMEBUFFER"); + if (!fbname) + fbname = "/dev/fb0"; + + fb_fd = open(fbname, O_RDWR); + if (fb_fd < 0) + Sys_Error ("failed to open fb device\n"); + + if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &orig_var)) + Sys_Error ("failed to get var screen info\n"); + + fb_switch_init(); + + VID_InitModes (); + + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "No Description"); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "No Description"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "No Description"); + Cmd_AddCommand ("vid_debug", VID_Debug_f, "No Description"); + Cmd_AddCommand ("vid_fbset", VID_fbset_f, "No Description"); + + /* Interpret command-line params */ + w = h = d = 0; + if (getenv ("GFBDEVMODE")) { + modestr = get_mode (getenv ("GFBDEVMODE"), w, h, d); + } else if (COM_CheckParm ("-mode")) { + modestr = get_mode (com_argv[COM_CheckParm ("-mode") + 1], w, h, d); + } else if (COM_CheckParm ("-w") || COM_CheckParm ("-h") + || COM_CheckParm ("-d")) { + if (COM_CheckParm ("-w")) { + w = atoi (com_argv[COM_CheckParm ("-w") + 1]); + } + if (COM_CheckParm ("-h")) { + h = atoi (com_argv[COM_CheckParm ("-h") + 1]); + } + if (COM_CheckParm ("-d")) { + d = atoi (com_argv[COM_CheckParm ("-d") + 1]); + } + modestr = get_mode (0, w, h, d); + } else { + modestr = "640x480-60"; + } + + /* Set vid parameters */ + vmode = FindVideoMode(modestr); + if (!vmode) + Sys_Error("no video mode %s\n", modestr); + current_mode = *vmode; + ioctl(tty_fd, KDSETMODE, KD_GRAPHICS); + VID_SetMode (current_mode.name, palette); + Con_CheckResize (); // Now that we have a window size, fix console + + VID_SetPalette (palette); + } +} + +void +VID_Init_Cvars () +{ + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, NULL, + "Sets the video mode"); + vid_redrawfull = Cvar_Get ("vid_redrawfull", "0", CVAR_NONE, NULL, + "Redraw entire screen each frame instead of just dirty areas"); + vid_waitforrefresh = Cvar_Get ("vid_waitforrefresh", "0", CVAR_ARCHIVE, + NULL, "Wait for vertical retrace before drawing next frame"); +} + + +void +VID_Update (vrect_t *rects) +{ + if (!fbdev_inited) + return; + if (fbdev_backgrounded) { + if (fbdev_backgrounded == 3) { + return; + } else if (fbdev_backgrounded == 2) { + fb_switch_acquire(); + fbdev_backgrounded = 0; + VID_SetPalette(vid_current_palette); + } else if (fbdev_backgrounded == 1) { + fb_switch_release(); + fbdev_backgrounded = 3; + return; + } + } + + if (vid_waitforrefresh->int_val) { + // ??? + } + + if (vid_redrawfull->int_val) { + double *d = (double *)framebuffer_ptr, *s = (double *)vid.buffer; + double *ends = (double *)(vid.buffer + vid.height*vid.rowbytes); + while (s < ends) + *d++ = *s++; + } else { + while (rects) { + int height, width, lineskip, i, j, xoff, yoff; + double *d, *s; + + height = rects->height; + width = rects->width / sizeof(double); + xoff = rects->x; + yoff = rects->y; + lineskip = (vid.width - (xoff + rects->width)) / sizeof(double); + d = (double *)(framebuffer_ptr + yoff * vid.rowbytes + xoff); + s = (double *)(vid.buffer + yoff * vid.rowbytes + xoff); + for (i = yoff; i < height; i++) { + for (j = xoff; j < width; j++) + *d++ = *s++; + d += lineskip; + s += lineskip; + } + rects = rects->pnext; + } + } + + if (current_mode.name && strcmp(vid_mode->string, current_mode.name)) { + VID_SetMode (vid_mode->string, vid_current_palette); + } +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (char *text) +{ +} + +qboolean +VID_SetGamma (double gamma) +{ + return false; +} diff --git a/libs/video/targets/vid_glx.c b/libs/video/targets/vid_glx.c new file mode 100644 index 000000000..d50c4362f --- /dev/null +++ b/libs/video/targets/vid_glx.c @@ -0,0 +1,249 @@ +/* + vid_glx.c + + OpenGL GLX video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include +#include + +#ifdef HAVE_DGA +# include +#endif + +#include "QF/compat.h" +#include "QF/console.h" +#include "context_x11.h" +#include "glquake.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "QF/quakefs.h" +#include "sbar.h" +#include "QF/va.h" + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +static qboolean vid_initialized = false; + +static GLXContext ctx = NULL; + +extern void GL_Init_Common (void); +extern void VID_Init8bitPalette (void); + +/*-----------------------------------------------------------------------*/ + +const char *gl_vendor; +const char *gl_renderer; +const char *gl_version; +const char *gl_extensions; + +void +VID_Shutdown (void) +{ + if (!vid_initialized) + return; + + Con_Printf ("VID_Shutdown\n"); + + X11_RestoreVidMode (); + X11_CloseDisplay (); +} + +#if 0 +static void +signal_handler (int sig) +{ + printf ("Received signal %d, exiting...\n", sig); + Sys_Quit (); + exit (sig); +} + +static void +InitSig (void) +{ + signal (SIGHUP, signal_handler); + signal (SIGINT, signal_handler); + signal (SIGQUIT, signal_handler); + signal (SIGILL, signal_handler); + signal (SIGTRAP, signal_handler); + signal (SIGIOT, signal_handler); + signal (SIGBUS, signal_handler); +/* signal (SIGFPE, signal_handler); */ + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); +} +#endif + +/* + GL_Init +*/ +void +GL_Init (void) +{ + GL_Init_Common (); +} + +void +GL_EndRendering (void) +{ + glFlush (); + glXSwapBuffers (x_disp, x_win); + Sbar_Changed (); +} + +void +VID_Init (unsigned char *palette) +{ + int i; + int attrib[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None + }; + + VID_GetWindowSize (640, 480); + Con_CheckResize (); // Now that we have a window size, fix console + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + + /* Interpret command-line params */ + + /* Set vid parameters */ + + if ((i = COM_CheckParm ("-conwidth"))) + vid.conwidth = atoi (com_argv[i + 1]); + else + vid.conwidth = scr_width; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + vid.conwidth = max (vid.conwidth, 320); + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth * 3 / 4; + + if ((i = COM_CheckParm ("-conheight"))) // conheight no smaller than + // 200px + vid.conheight = atoi (com_argv[i + 1]); + vid.conheight = max (vid.conheight, 200); + + X11_OpenDisplay (); + + x_visinfo = glXChooseVisual (x_disp, x_screen, attrib); + if (!x_visinfo) { + fprintf (stderr, + "Error couldn't get an RGB, Double-buffered, Depth visual\n"); + exit (1); + } + x_vis = x_visinfo->visual; + + X11_SetVidMode (scr_width, scr_height); + X11_CreateWindow (scr_width, scr_height); + /* Invisible cursor */ + X11_CreateNullCursor (); + + X11_GrabKeyboard (); + + XSync (x_disp, 0); + + ctx = glXCreateContext (x_disp, x_visinfo, NULL, True); + + glXMakeCurrent (x_disp, x_win, ctx); + + vid.height = vid.conheight = min (vid.conheight, scr_height); + vid.width = vid.conwidth = min (vid.conwidth, scr_width); + + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.numpages = 2; + + // InitSig (); // trap evil signals + + GL_Init (); + + GL_CheckBrightness (palette); + VID_InitGamma (palette); + VID_SetPalette (palette); + + // Check for 8-bit extension and initialize if present + VID_Init8bitPalette (); + + Con_Printf ("Video mode %dx%d initialized.\n", scr_width, scr_height); + + vid_initialized = true; + + vid.recalc_refdef = 1; // force a surface cache flush +} + +void +VID_Init_Cvars () +{ + X11_Init_Cvars (); +} + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + X11_SetCaption (va ("%s %s: %s", PROGRAM, VERSION, temp)); + free (temp); + } else { + X11_SetCaption (va ("%s %s", PROGRAM, VERSION)); + } +} + +double +VID_GetGamma (void) +{ + return (double) X11_GetGamma (); +} + +qboolean +VID_SetGamma (double gamma) +{ + return X11_SetGamma (gamma); +} diff --git a/libs/video/targets/vid_mgl.c b/libs/video/targets/vid_mgl.c new file mode 100644 index 000000000..5c2ed6472 --- /dev/null +++ b/libs/video/targets/vid_mgl.c @@ -0,0 +1,3196 @@ +/* + vid_mgl.c + + Win32 Scitech MGL video driver + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "cdaudio.h" +#include "QF/cmd.h" +#include "QF/console.h" +#include "d_local.h" +#include "draw.h" +#include "in_win.h" +#include "QF/keys.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "resource.h" +#include "screen.h" +#include "sound.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "wad.h" +#include "winquake.h" + +#define MINIMUM_MEMORY 0x550000 + +#define MAX_MODE_LIST 30 +#define VID_ROW_SIZE 3 + +extern void (*vid_menudrawfn) (void); +extern void (*vid_menukeyfn) (int); + +/* Unused */ +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +byte *VGA_pagebase; + +qboolean dibonly; + +extern qboolean 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 = 0; +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; + +extern 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; + +// Note that 0 is MODE_WINDOWED +// Note that 3 is MODE_FULLSCREEN_DEFAULT +cvar_t *_vid_default_mode_win; +cvar_t *vid_nopageflip; +cvar_t *vid_config_x; +cvar_t *vid_config_y; +cvar_t *vid_stretch_by_2; +cvar_t *_windowed_mouse; +cvar_t *vid_fullscreen_mode; +cvar_t *vid_windowed_mode; +cvar_t *block_switch; +cvar_t *vid_window_x; +cvar_t *vid_window_y; + +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 int d_8to24table[256]; + +int driver = grDETECT, mode; +qboolean 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; + +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, rect.left); + Cvar_SetValue (vid_window_y, rect.top); + } + } +} + + +/* + VID_CheckWindowXY +*/ +void +VID_CheckWindowXY (void) +{ + + if ((vid_window_x->int_val > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + (vid_window_y->int_val > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + (vid_window_x->int_val < 0) || (vid_window_y->int_val < 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 (); +} + + +extern void CL_ClearStates (); + +/* + ClearAllStates +*/ +void +ClearAllStates (void) +{ + CL_ClearStates (); + Key_ClearStates (); + IN_ClearStates (); +} + + +/* + VID_CheckAdequateMem +*/ +qboolean +VID_CheckAdequateMem (int width, int height) +{ + return true; +} + + +/* + + VID_AllocBuffers + +*/ +qboolean +VID_AllocBuffers (int width, int height) +{ + int zbuffersize, cachesize; + + // Calculate the sizes we want first + + zbuffersize = width * height * sizeof (*d_pzbuffer); + cachesize = D_SurfaceCacheForRes (width, height); + + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new z-buffer + d_pzbuffer = calloc (zbuffersize, 1); + if (!d_pzbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + return false; + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (cachesize, 1); + if (!vid_surfcache) { + free (d_pzbuffer); + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + return false; + } + vid_surfcachesize = cachesize; + + 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->int_val && !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 + } 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, lowres, curmode, temp; + int lowstretchedres, stretchedmode = 0, 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; + snprintf (modelist[curmode].modedesc, + sizeof (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; + snprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, + sizeof (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; + + hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON1)); + + /* 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, existingmode, originalnummodes, lowestres; + int numlowresmodes, bpp, done; + int cstretch, istretch, mstretch = 0; + 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%ldx%ld", + 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%dx%d", + modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) && + (modelist[nummodes].height == modelist[i].height)) { + existingmode = 1; + break; + } + } + + if (!existingmode) { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; + } + } + } + + modenum++; + } while (stat); + +// see if any of them were actually settable; if so, this is our mode list, +// else enumerate all modes; our mode list is whichever ones are settable +// with > 8 bpp + if (nummodes == originalnummodes) { + modenum = 0; + lowestres = 99999; + + Con_Printf ("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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%ldx%ld", + 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), + "%dx%d", modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i = originalnummodes, existingmode = 0; i < nummodes; + i++) { + if ((modelist[nummodes].width == modelist[i].width) + && (modelist[nummodes].height == + modelist[i].height)) { + // pick the lowest available bpp + if (modelist[nummodes].bpp < modelist[i].bpp) + modelist[i] = modelist[nummodes]; + + existingmode = 1; + break; + } + } + + if (!existingmode) { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; + } + } + } + + modenum++; + } while (stat); + } +// see if there are any low-res modes that aren't being reported + numlowresmodes = sizeof (lowresmodes) / sizeof (lowresmodes[0]); + bpp = 8; + done = 0; + +// first make sure the driver doesn't just answer yes to all tests + devmode.dmBitsPerPel = 8; + devmode.dmPelsWidth = 42; + devmode.dmPelsHeight = 37; + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) { + done = 1; + } + + while (!done) { + for (j = 0; (j < numlowresmodes) && (nummodes < MAX_MODE_LIST); j++) { + devmode.dmBitsPerPel = bpp; + devmode.dmPelsWidth = lowresmodes[j].width; + devmode.dmPelsHeight = lowresmodes[j].height; + 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%ldx%ld", + devmode.dmPelsWidth, devmode.dmPelsHeight); + + // we only want the lowest-bpp version of each mode + for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) && + (modelist[nummodes].height == modelist[i].height) && + (modelist[nummodes].bpp >= 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 < nummodes; i++) { + if (((modelist[i].width >> 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; + snprintf (modelist[istretch].modedesc, + sizeof (modelist[istretch].modedesc), "%dx%d", + modelist[istretch].width, modelist[istretch].height); + } + } + + if (nummodes != originalnummodes) + vid_default = MODE_FULLSCREEN_DEFAULT; + else + Con_Printf ("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 = vid_stretch_by_2->int_val; + stretch = modelist[mode].stretched; + + Cvar_SetValue (vid_config_x, + max (vid_config_x->int_val, 320 << stretch)); + Cvar_SetValue (vid_config_y, + max (vid_config_y->int_val, 200 << stretch)); + + x = vid_config_x->int_val; + y = vid_config_y->int_val; + snprintf (modelist[mode].modedesc, sizeof (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) { + snprintf (pinfo, sizeof (pinfo), "%s fullscreen", pv->modedesc); + } else if (modelist[mode].type == MS_FULLDIB) { + snprintf (pinfo, sizeof (pinfo), "%s fullscreen", pv->modedesc); + } else { + snprintf (pinfo, sizeof (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) { + snprintf (pinfo, sizeof (pinfo), "%s fullscreen %s", pv->modedesc, + MGL_modeDriverName (pv->modenum)); + } else if (modelist[mode].type == MS_FULLDIB) { + snprintf (pinfo, sizeof (pinfo), "%s fullscreen DIB", pv->modedesc); + } else { + snprintf (pinfo, sizeof (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; + + 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 = 1; + } + + 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", + PROGRAM, + 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, vid_window_x->int_val, + vid_window_y->int_val, 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 || + vid_nopageflip->int_val)) == 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; + 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, modenum); + } else { + Cvar_SetValue (vid_mode, 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->int_val && 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, 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_Printf ("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; +} + + +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 = 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; i < lnummodes; i++) { + pv = VID_GetModePtr (i); + pinfo = VID_GetExtModeDescription (i); + + if (VID_CheckAdequateMem (pv->width, 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 = atoi (Cmd_Argv (1)); + + if (VID_SetMode (modenum, vid_curpal)) { + vid_testingmode = 1; + testduration = atof (Cmd_Argv (2)); + if (testduration == 0) + testduration = 5.0; + vid_testendtime = realtime + testduration; + } + } +} + +/* + VID_Windowed_f +*/ +void +VID_Windowed_f (void) +{ + + VID_SetMode (vid_windowed_mode->int_val, vid_curpal); +} + + +/* + VID_Fullscreen_f +*/ +void +VID_Fullscreen_f (void) +{ + + VID_SetMode (vid_fullscreen_mode->int_val, 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; + + if (!vid_testingmode) { + modenum = 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 = 0, bestmatchmetric, t, dr, dg, db; + int basenummodes; + byte *ptmp; + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f, "Switch to another video mode temporarily for 5-seconds to test it.\n" + "(vid_testmode (mode))"); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available"); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, "Report current video mode."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" + "(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); + Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, "Force QuakeWorld to use a certain video mode. (vid_forcemode (mode))"); + Cmd_AddCommand ("vid_windowed", VID_Windowed_f, "Switch to windowed mode"); + Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, "Switch to full screen mode"); + Cmd_AddCommand ("vid_minimize", VID_Minimize_f, "Minimize windowed Quake"); + + 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 = vid_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") || COM_CheckParm ("-window")) { + startwindowed = 1; + vid_default = windowed_default; + } +#ifdef SPLASH_SCREEN + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); +#endif + +// 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_Init_Cvars () +{ + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, NULL, "Set the video mode"); + vid_nopageflip = Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, NULL, "Toggles the use of page flipping"); + _vid_default_mode_win = + Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE, NULL, "Default windowed video mode"); + vid_config_x = Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, NULL, "Maximum x-axis screen size"); + vid_config_y = Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, NULL, "Maximum y-axis screen size"); + vid_stretch_by_2 = Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, NULL, "Stretch the pixles by a two fold to acheive proper view"); + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, "Have quake grab the mouse from X when you play"); + vid_fullscreen_mode = + Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, NULL, "Set the full screen video mode."); + vid_windowed_mode = + Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, NULL, "Set the windowed video mode"); + block_switch = Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, NULL, "If set, won't allow you to task switch while playing"); + vid_window_x = Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE, NULL, "The x-axis location of the window, if windowed"); + vid_window_y = Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE, NULL, "The y-axis location of the window, if windowed"); +} + + +void +VID_Shutdown (void) +{ + +#ifdef SPLASH_SCREEN + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); +#endif + + 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 (mainwindow) + DestroyWindow (mainwindow); + + MGL_exit (); + + vid_testingmode = 0; + vid_initialized = 0; + } +} + + +/* + FlipScreen +*/ +void +FlipScreen (vrect_t *rects) +{ + /* 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 != vid_window_x->int_val) || + (trect.top != vid_window_y->int_val)) { + if (COM_CheckParm ("-resetwinpos")) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } + + VID_CheckWindowXY (); + SetWindowPos (mainwindow, NULL, vid_window_x->int_val, + vid_window_y->int_val, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | + SWP_DRAWFRAME); + } + } + + if ((_vid_default_mode_win->int_val != vid_default) && + (!startwindowed + || (_vid_default_mode_win->int_val < 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->int_val < 0) || + (_vid_default_mode_win->int_val >= nummodes)) { + Cvar_SetValue (_vid_default_mode_win, windowed_default); + } + + Cvar_SetValue (vid_mode, _vid_default_mode_win->int_val); + } + } + // 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 (vid_mode->int_val != vid_realmode) { + VID_SetMode (vid_mode->int_val, vid_curpal); + Cvar_SetValue (vid_mode, 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->int_val) { + 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 < reps; j++) { + memcpy (&backingbuf[(i + j) * 24], + vid.direct + x + ((y << repshift) + i + + j) * vid.rowbytes, width); + memcpy (vid.direct + x + + ((y << repshift) + i + j) * vid.rowbytes, + &pbitmap[(i >> 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; j < reps; j++) { + memcpy (&backingbuf[(i + j) * 24], + (byte *) mgldc->surface + 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 < reps; j++) { + memcpy (vid.direct + x + + ((y << repshift) + i + j) * vid.rowbytes, + &backingbuf[(i + j) * 24], 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 (); + + // restore to the screen + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + memcpy ((byte *) mgldc->surface + 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, KP_MULTIPLY, + K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCRLCK, KP_HOME, + KP_UPARROW, KP_PGUP, KP_MINUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_PLUS, KP_END, // 4 + KP_DOWNARROW, KP_PGDN, KP_INS, KP_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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +byte extscantokey[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', '[', ']', KP_ENTER, K_CTRL, 'a', 's', // 1 + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2 + 'b', 'n', 'm', ',', '.', KP_DIVIDE, K_SHIFT, '*', + K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLCK, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* + MapKey + + Map from windows to quake keynums +*/ +int +MapKey (int key) +{ + int extended; + + extended = (key >> 24) & 1; + + key = (key >> 16) & 255; + if (key > 127) + return 0; + + if (extended) + return extscantokey[key]; + else + 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->int_val + && 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->int_val /* && + mouseactive + */ ) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } + } +} + + +/* + VID_HandlePause +*/ +void +VID_HandlePause (qboolean pause) +{ +#if 0 + if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { + 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 fActive, fMinimized, temp; + HDC hdc; + PAINTSTRUCT ps; + extern unsigned int uiWheelMessage; + + 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 (vid_fullscreen_mode->int_val, 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), -1, true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + if (!in_mode_set) + Key_Event (MapKey (lParam), -1, 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, -1, true); + Key_Event (K_MWHEELUP, -1, false); + } else { + Key_Event (K_MWHEELDOWN, -1, true); + Key_Event (K_MWHEELDOWN, -1, 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 = 0; + char temp[100]; + vmode_t *pv; + modedesc_t tmodedesc; + + p = Draw_CachePic ("gfx/vidmodes.lmp", true); + 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; i < lnummodes; i++) { + ptr = VID_GetModeDescriptionMemCheck (i); + pv = VID_GetModePtr (i); + + // we only have room for 15 fullscreen modes, so don't allow + // 360-wide modes, because if there are 5 320-wide modes and + // 5 360-wide modes, we'll run out of space + if (ptr && ((pv->width != 360) || COM_CheckParm ("-allow360"))) { + dup = 0; + + for (j = 3; j < vid_wmodes; j++) { + if (!strcmp (modedescs[j].desc, ptr)) { + dup = 1; + dupmode = j; + break; + } + } + + if (dup || (vid_wmodes < MAX_MODEDESCS)) { + if (!dup || !modedescs[dupmode].ismode13 + || COM_CheckParm ("-noforcevga")) { + if (dup) { + k = dupmode; + } else { + k = vid_wmodes; + } + + modedescs[k].modenum = i; + modedescs[k].desc = ptr; + modedescs[k].ismode13 = pv->mode13; + 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 < vid_wmodes; j++) { + if (modedescs[i].width > 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 < vid_wmodes; i++) { + if (modedescs[i].iscur) + M_PrintWhite (column, row, modedescs[i].desc); + else + M_Print (column, row, modedescs[i].desc); + + column += 13 * 8; + + if (((i - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1)) { + column = 16; + row += 8; + } + } + } +// line cursor + if (vid_testingmode) { + snprintf (temp, sizeof (temp), "TESTING %s", modedescs[vid_line].desc); + M_Print (13 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 4, temp); + M_Print (9 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 6, + "Please wait 5 seconds..."); + } else { + M_Print (9 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8, + "Press Enter to set mode"); + M_Print (6 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 3, + "T to test mode for 5 seconds"); + ptr = VID_GetModeDescription2 (vid_modenum); + + if (ptr) { + snprintf (temp, sizeof (temp), "D to set default: %s", ptr); + M_Print (2 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 5, temp); + } + + ptr = VID_GetModeDescription2 (_vid_default_mode_win->int_val); + + if (ptr) { + snprintf (temp, sizeof (temp), "Current default: %s", ptr); + M_Print (3 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 6, temp); + } + + M_Print (15 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 8, "Esc to exit"); + + row = 36 + 2 * 8 + (vid_line / VID_ROW_SIZE) * 8; + column = 8 + (vid_line % VID_ROW_SIZE) * 13 * 8; + + if (vid_line >= 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; + } +} + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + SetWindowText (mainwindow, + (LPSTR) va ("%s %s: %s", PROGRAM, VERSION, text)); + free (temp); + } else { + SetWindowText (mainwindow, (LPSTR) va ("%s %s", PROGRAM, VERSION)); + } +} diff --git a/libs/video/targets/vid_null.c b/libs/video/targets/vid_null.c new file mode 100644 index 000000000..d857b869e --- /dev/null +++ b/libs/video/targets/vid_null.c @@ -0,0 +1,108 @@ +/* + vid_null.c + + null video driver to aid porting efforts + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "d_local.h" + +viddef_t vid; // global video state + +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +byte vid_buffer[BASEWIDTH * BASEHEIGHT]; +short zbuffer[BASEWIDTH * BASEHEIGHT]; +byte surfcache[256 * 1024]; + +unsigned short d_8to16table[256]; +unsigned int d_8to24table[256]; + +void +VID_SetPalette (unsigned char *palette) +{ +} + +void +VID_ShiftPalette (unsigned char *palette) +{ +} + +void +VID_Init (unsigned char *palette) +{ + vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH; + vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT; + vid.aspect = 1.0; + vid.numpages = 1; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.buffer = vid.conbuffer = vid_buffer; + vid.rowbytes = vid.conrowbytes = BASEWIDTH; + + d_pzbuffer = zbuffer; + D_InitCaches (surfcache, sizeof (surfcache)); +} + +void +VID_Init_Cvars () +{ +} + +void +VID_Shutdown (void) +{ +} + +void +VID_Update (vrect_t *rects) +{ +} + +/* + D_BeginDirectRect +*/ +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ +} + + +/* + D_EndDirectRect +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ +} + +void +VID_SetCaption (char *text) +{ +} diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c new file mode 100644 index 000000000..dcdabd22e --- /dev/null +++ b/libs/video/targets/vid_sdl.c @@ -0,0 +1,302 @@ +/* + vid_sdl.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "d_local.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" + +#ifdef WIN32 +/* FIXME: this is evil hack to get full DirectSound support with SDL */ +#include +#include +HWND mainwindow; +#endif + +// static float oldin_grab = 0; + +cvar_t *vid_fullscreen; +cvar_t *vid_system_gamma; +qboolean vid_gamma_avail; +extern viddef_t vid; // global video state +unsigned short d_8to16table[256]; + +int modestate; // FIXME: just to avoid cross-comp. + // errors - remove later + +// The original defaults +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; +byte *VGA_pagebase; + +static SDL_Surface *screen = NULL; + +void +VID_InitBuffers (int width, int height) +{ + int tbuffersize, tcachesize; + void *vid_surfcache; + + // Calculate the sizes we want first + tbuffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + tcachesize = D_SurfaceCacheForRes (width, height); + + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new z-buffer + d_pzbuffer = calloc (tbuffersize, 1); + if (!d_pzbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (tcachesize, 1); + if (!vid_surfcache) { + free (d_pzbuffer); + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + + D_InitCaches (vid_surfcache, tcachesize); +} + +void +VID_SetPalette (unsigned char *palette) +{ + int i; + SDL_Color colors[256]; + + for (i = 0; i < 256; ++i) { + colors[i].r = *palette++; + colors[i].g = *palette++; + colors[i].b = *palette++; + } + SDL_SetColors (screen, colors, 0, 256); +} + +void +VID_ShiftPalette (unsigned char *palette) +{ + VID_SetPalette (palette); +} + +void +VID_Init (unsigned char *palette) +{ + // Uint8 video_bpp; + // Uint16 video_w, video_h; + Uint32 flags; + + // Load the SDL library + if (SDL_Init (SDL_INIT_VIDEO) < 0) // |SDL_INIT_AUDIO|SDL_INIT_CDROM) < + // 0) + Sys_Error ("VID: Couldn't load SDL: %s", SDL_GetError ()); + + // Set up display mode (width and height) + VID_GetWindowSize (BASEWIDTH, BASEHEIGHT); + Con_CheckResize (); // Now that we have a window size, fix console + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + // Set video width, height and flags + flags = (SDL_SWSURFACE | SDL_HWPALETTE); + if (vid_fullscreen->int_val) + flags |= SDL_FULLSCREEN; + + // Initialize display + if (!(screen = SDL_SetVideoMode (vid.width, vid.height, 8, flags))) + Sys_Error ("VID: Couldn't set video mode: %s\n", SDL_GetError ()); + VID_InitGamma (palette); + VID_SetPalette (palette); + + // now know everything we need to know about the buffer + VGA_width = vid.conwidth = vid.width; + VGA_height = vid.conheight = vid.height; + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.numpages = 1; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + VGA_pagebase = vid.buffer = screen->pixels; + VGA_rowbytes = vid.rowbytes = screen->pitch; + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.direct = 0; + + // allocate z buffer and surface cache + VID_InitBuffers (vid.width, vid.height); + + // initialize the mouse + SDL_ShowCursor (0); + +#ifdef WIN32 + // FIXME: EVIL thing - but needed for win32 until + // SDL_sound works better - without this DirectSound fails. + +// SDL_GetWMInfo(&info); +// mainwindow=info.window; + mainwindow=GetActiveWindow(); +#endif + +} + +void +VID_Init_Cvars () +{ + vid_fullscreen = + Cvar_Get ("vid_fullscreen", "0", CVAR_ROM, NULL, + "Toggles fullscreen game mode"); + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, + "Use system gamma control if available"); +} + +void +VID_Shutdown (void) +{ + SDL_Quit (); +} + +void +VID_Update (vrect_t *rects) +{ + SDL_Rect *sdlrects; + int n, i; + vrect_t *rect; + + // Two-pass system, since Quake doesn't do it the SDL way... + + // First, count the number of rectangles + n = 0; + for (rect = rects; rect; rect = rect->pnext) + ++n; + + // Second, copy them to SDL rectangles and update + if (!(sdlrects = (SDL_Rect *) calloc (1, n * sizeof (SDL_Rect)))) + Sys_Error ("Out of memory!"); + i = 0; + for (rect = rects; rect; rect = rect->pnext) { + sdlrects[i].x = rect->x; + sdlrects[i].y = rect->y; + sdlrects[i].w = rect->width; + sdlrects[i].h = rect->height; + ++i; + } + SDL_UpdateRects (screen, n, sdlrects); +} + +/* + D_BeginDirectRect +*/ +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ + Uint8 *offset; + + + if (!screen) + return; + if (x < 0) + x = screen->w + x - 1; + offset = (Uint8 *) screen->pixels + y * screen->pitch + x; + while (height--) { + memcpy (offset, pbitmap, width); + offset += screen->pitch; + pbitmap += width; + } +} + +/* + D_EndDirectRect +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ + if (!screen) + return; + if (x < 0) + x = screen->w + x - 1; + SDL_UpdateRect (screen, x, y, width, height); +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + SDL_WM_SetCaption (va ("%s %s: %s", PROGRAM, VERSION, temp), NULL); + free (temp); + } else { + SDL_WM_SetCaption (va ("%s %s", PROGRAM, VERSION), NULL); + } +} + +qboolean +VID_SetGamma (double gamma) +{ +// return SDL_SetGamma ((float) gamma, (float) gamma, (float) gamma); + return false; // FIXME +} diff --git a/libs/video/targets/vid_sgl.c b/libs/video/targets/vid_sgl.c new file mode 100644 index 000000000..5f5ba1d43 --- /dev/null +++ b/libs/video/targets/vid_sgl.c @@ -0,0 +1,267 @@ +/* + vid_sgl.c + + Video driver for OpenGL-using versions of SDL + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifndef WIN32 +# include +#endif + +#include + +#include "QF/compat.h" +#include "QF/console.h" +#include "glquake.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "sbar.h" +#include "QF/sys.h" +#include "QF/va.h" + +#ifdef WIN32 +/* FIXME: this is evil hack to get full DirectSound support with SDL */ +# include +# include +HWND mainwindow; +#endif + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +static qboolean vid_initialized = false; + +cvar_t *vid_fullscreen; +cvar_t *vid_system_gamma; +qboolean vid_gamma_avail; + +int VID_options_items = 1; +int modestate; + +extern void GL_Init_Common (void); +extern void VID_Init8bitPalette (void); + +/*-----------------------------------------------------------------------*/ + +void +VID_SDL_GammaCheck (void) +{ + Uint16 redtable[256], greentable[256], bluetable[256]; + + if (SDL_GetGammaRamp(redtable, greentable, bluetable) < 0) + vid_gamma_avail = false; + else + vid_gamma_avail = true; +} + +void +VID_Shutdown (void) +{ +// if (!vid_initialized) +// return; +// Con_Printf ("VID_Shutdown\n"); + SDL_Quit (); +} + +#ifndef WIN32 +static void +signal_handler (int sig) +{ + printf ("Received signal %d, exiting...\n", sig); + Sys_Quit (); + exit (sig); +} + +static void +InitSig (void) +{ + signal (SIGHUP, signal_handler); + signal (SIGINT, signal_handler); + signal (SIGQUIT, signal_handler); + signal (SIGILL, signal_handler); + signal (SIGTRAP, signal_handler); + signal (SIGIOT, signal_handler); + signal (SIGBUS, signal_handler); +// signal(SIGFPE, signal_handler); + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); +} +#endif + +void +GL_Init (void) +{ + GL_Init_Common (); +} + +void +GL_EndRendering (void) +{ + glFlush (); + SDL_GL_SwapBuffers (); + Sbar_Changed (); +} + +void +VID_Init (unsigned char *palette) +{ + Uint32 flags = SDL_OPENGL; + int i; + +// SDL_SysWMinfo info; + + VID_GetWindowSize (640, 480); + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + + // Interpret command-line params + + // Set vid parameters + if ((i = COM_CheckParm ("-conwidth")) != 0) + vid.conwidth = atoi (com_argv[i + 1]); + else + vid.conwidth = scr_width; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + if (vid.conwidth < 320) + vid.conwidth = 320; + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth * 3 / 4; + + i = COM_CheckParm ("-conheight"); + if (i != 0) // Set console height, but no smaller + // than 200 px + vid.conheight = max (atoi (com_argv[i + 1]), 200); + + // Initialize the SDL library + if (SDL_Init (SDL_INIT_VIDEO) < 0) + Sys_Error ("Couldn't initialize SDL: %s\n", SDL_GetError ()); + + // Check if we want fullscreen + if (vid_fullscreen->value) { + flags |= SDL_FULLSCREEN; + // Don't annoy Mesa/3dfx folks +#ifndef WIN32 + // FIXME: Maybe this could be put in a different spot, but I don't + // know where. + // Anyway, it's to work around a 3Dfx Glide bug. + SDL_ShowCursor (0); + SDL_WM_GrabInput (SDL_GRAB_ON); + setenv ("MESA_GLX_FX", "fullscreen", 1); + } else { + setenv ("MESA_GLX_FX", "window", 1); +#endif + } + + // Setup GL Attributes + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 1); + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 1); + + if (SDL_SetVideoMode (scr_width, scr_height, 8, flags) == NULL) { + Sys_Error ("Couldn't set video mode: %s\n", SDL_GetError ()); + SDL_Quit (); + } + + vid.height = vid.conheight = min (vid.conheight, scr_height); + vid.width = vid.conwidth = min (vid.conwidth, scr_width); + Con_CheckResize (); // Now that we have a window size, fix console + + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.numpages = 2; + +#ifndef WIN32 + InitSig (); // trap evil signals +#endif + + GL_Init (); + + VID_SDL_GammaCheck (); + + GL_CheckBrightness (palette); + VID_InitGamma (palette); + VID_SetPalette (palette); + + // Check for 3DFX Extensions and initialize them. + VID_Init8bitPalette (); + + Con_Printf ("Video mode %dx%d initialized.\n", scr_width, scr_height); + + vid_initialized = true; + +#ifdef WIN32 + // FIXME: EVIL thing - but needed for win32 until + // SDL_sound works better - without this DirectSound fails. + +// SDL_GetWMInfo(&info); +// mainwindow=info.window; + mainwindow=GetActiveWindow(); +#endif + + vid.recalc_refdef = 1; // force a surface cache flush +} + +void +VID_Init_Cvars () +{ + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM, NULL, + "Toggles fullscreen mode"); + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, + "Use system gamma control if available"); +} + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + SDL_WM_SetCaption (va ("%s %s: %s", PROGRAM, VERSION, temp), NULL); + free (temp); + } else { + SDL_WM_SetCaption (va ("%s %s", PROGRAM, VERSION), NULL); + } +} + +qboolean +VID_SetGamma (double gamma) +{ + return SDL_SetGamma((float) gamma, (float) gamma, (float) gamma); +} diff --git a/libs/video/targets/vid_sunx.c b/libs/video/targets/vid_sunx.c new file mode 100644 index 000000000..da4d02712 --- /dev/null +++ b/libs/video/targets/vid_sunx.c @@ -0,0 +1,1389 @@ +/* + vid_sunx.c + + @description@ + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "d_local.h" + +cvar_t *m_filter; + +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; +qboolean mouse_grabbed = false; // we grab it when console is up + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +byte *VGA_pagebase; + +// The following X property format is defined in Motif 1.1's +// Xm/MwmUtils.h, but QUAKE should not depend on that header +// file. Note: Motif 1.2 expanded this structure with +// uninteresting fields (to QUAKE) so just stick with the +// smaller Motif 1.1 structure. + +#define MWM_HINTS_DECORATIONS 2 +typedef struct { + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +#define MAX_COLUMN_SIZE 11 + +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +typedef struct { + int modenum; + int iscur; + char desc[256]; +} modedesc_t; + +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); + +extern int sb_updates; +extern int x_root, y_root; // root window relative mouse coords + +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; + +#define STD_EVENT_MASK \ +( KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ +PointerMotionMask | EnterWindowMask | LeaveWindowMask | VisibilityChangeMask | \ +ExposureMask | StructureNotifyMask ) + +qboolean x_fullscreen = true; +Display *x_disp = NULL; +int x_screen, x_screen_width, x_screen_height; +int x_center_width, x_center_height; +int x_std_event_mask = STD_EVENT_MASK; +Window x_win, x_root_win; +qboolean mouse_in_window = false; +int global_dx, global_dy; + +static qboolean doShm; +static Colormap x_cmap; +static GC x_gc; +static Visual *x_vis; +static XVisualInfo *x_visinfo; +static Atom aHints = 0; +static Atom aWMDelete = 0; + +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 = 1; + +static byte current_palette[768]; + +typedef unsigned short PIXEL16; +typedef unsigned long PIXEL24; +static PIXEL16 st2d_8to16table[256]; +static PIXEL24 st2d_8to24table[256]; +static int shiftmask_fl = 0; +static long r_shift, g_shift, b_shift; +static unsigned long r_mask, g_mask, b_mask; + +void +VID_InitCvars (void) +{ +} + +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; x < r_mask; x = x << 1) + r_shift++; + for (g_shift = -8, x = 1; x < g_mask; x = x << 1) + g_shift++; + for (b_shift = -8, x = 1; x < b_mask; x = x << 1) + b_shift++; + shiftmask_fl = 1; +} + +PIXEL16 +xlib_rgb16 (int r, int g, int b) +{ + PIXEL16 p; + + if (shiftmask_fl == 0) + shiftmask_init (); + p = 0; + + if (r_shift > 0) { + 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; +} + +PIXEL24 +xlib_rgb24 (int r, int g, int b) +{ + PIXEL24 p; + + if (shiftmask_fl == 0) + shiftmask_init (); + p = 0; + + if (r_shift > 0) { + 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; + PIXEL16 *dest; + register int count, n; + + if ((x < 0) || (y < 0)) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &framebuf->data[yi * framebuf->bytes_per_line]; + + // Duff's Device + count = width; + n = (count + 7) / 8; + dest = ((PIXEL16 *) src) + x + width - 1; + src += x + width - 1; + + switch (count % 8) { + case 0: + do { + *dest-- = st2d_8to16table[*src--]; + case 7: + *dest-- = st2d_8to16table[*src--]; + case 6: + *dest-- = st2d_8to16table[*src--]; + case 5: + *dest-- = st2d_8to16table[*src--]; + case 4: + *dest-- = st2d_8to16table[*src--]; + case 3: + *dest-- = st2d_8to16table[*src--]; + case 2: + *dest-- = st2d_8to16table[*src--]; + case 1: + *dest-- = st2d_8to16table[*src--]; + } while (--n > 0); + } + +// for(xi = (x+width-1); xi >= x; xi--) { +// dest[xi] = st2d_8to16table[src[xi]]; +// } + } +} + +void +st3_fixup (XImage * framebuf, int x, int y, int width, int height) +{ + int xi, yi; + unsigned char *src; + PIXEL24 *dest; + register int count, n; + + if ((x < 0) || (y < 0)) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &framebuf->data[yi * framebuf->bytes_per_line]; + + // Duff's Device + count = width; + n = (count + 7) / 8; + dest = ((PIXEL24 *) src) + x + width - 1; + src += x + width - 1; + + switch (count % 8) { + case 0: + do { + *dest-- = st2d_8to24table[*src--]; + case 7: + *dest-- = st2d_8to24table[*src--]; + case 6: + *dest-- = st2d_8to24table[*src--]; + case 5: + *dest-- = st2d_8to24table[*src--]; + case 4: + *dest-- = st2d_8to24table[*src--]; + case 3: + *dest-- = st2d_8to24table[*src--]; + case 2: + *dest-- = st2d_8to24table[*src--]; + case 1: + *dest-- = st2d_8to24table[*src--]; + } while (--n > 0); + } + +// for(xi = (x+width-1); xi >= x; xi--) { +// dest[xi] = st2d_8to16table[src[xi]]; +// } + } +} + +/* +================ +D_BeginDirectRect +================ +*/ +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Nextstep +} + + +/* +================ +D_EndDirectRect +================ +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Nextstep +} + + +/* +================= +VID_Gamma_f + +Keybinding command +================= +*/ + +byte vid_gamma[256]; + +void +VID_Gamma_f (void) +{ + + float g, f, inf; + int i; + + if (Cmd_Argc () == 2) { + g = Q_atof (Cmd_Argv (1)); + + for (i = 0; i < 255; i++) { + f = pow ((i + 1) / 256.0, g); + inf = f * 255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + vid_gamma[i] = inf; + } + + VID_SetPalette (current_palette); + + vid.recalc_refdef = 1; // force a surface cache flush + } + +} + +// ======================================================================== +// Tragic death handler +// ======================================================================== + +void +TragicDeath (int signal_num) +{ + // XAutoRepeatOn(x_disp); + VID_Shutdown (); + 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]) { + Z_Free (x_framebuffer[0]->data); +// Z_Free(d_pzbuffer); + free (x_framebuffer[0]); + } + + pwidth = x_visinfo->depth / 8; + if (pwidth == 3) + pwidth = 4; + mem = ((vid.width * pwidth + 3) & ~3) * vid.height; + +// d_pzbuffer = (unsigned short *) Z_Malloc(vid.width*vid.height* +// sizeof(*d_pzbuffer)); + d_pzbuffer = (short *) Hunk_HighAllocName (vid.width * vid.height * + sizeof (*d_pzbuffer), "zbuff"); + + x_framebuffer[0] = XCreateImage (x_disp, + x_vis, + x_visinfo->depth, + ZPixmap, + 0, + Z_Malloc (mem), + vid.width, vid.height, 32, 0); + + if (!x_framebuffer[0]) + Sys_Error ("VID: XCreateImage failed\n"); + +} + +void +ResetSharedFrameBuffers (void) +{ + + int size; + int key; + int minsize = getpagesize (); + int frm; + +// if (d_pzbuffer) +// Z_Free(d_pzbuffer); + d_pzbuffer = + Hunk_HighAllocName (vid.width * vid.height * sizeof (*d_pzbuffer), + "zbuff"); + + 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%x\n", x_shminfo[frm].shmid, + (int) 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); + + } + +} + +void +VID_MenuDraw (void) +{ + qpic_t *p; + char *ptr; + int i, j, column, row, dup; + char temp[100]; + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ((320 - p->width) / 2, 4, p); + M_Print (4 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8, + "Video mode switching unavailable"); + M_Print (9 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 6, "Press any key..."); +} + +void +VID_MenuKey (int key) +{ + M_Menu_Options_f (); +} + +// 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 + +byte surfcache[1024 * 1024]; + +// +// VID_SetWindowTitle - set the window and icon titles +// + +void +VID_SetWindowTitle (Window win, char *pszName) +{ + XTextProperty textprop; + XWMHints *wmHints; + + // Setup ICCCM properties + textprop.value = (unsigned char *) pszName; + textprop.encoding = XA_STRING; + textprop.format = 8; + textprop.nitems = strlen (pszName); + wmHints = XAllocWMHints (); + wmHints->initial_state = NormalState; + wmHints->flags = StateHint; + XSetWMProperties (x_disp, win, &textprop, &textprop, + // Only put WM_COMMAND property on first window. + com_argv, com_argc, NULL, NULL, NULL); + XFree (wmHints); + + aWMDelete = XInternAtom (x_disp, "WM_DELETE_WINDOW", False); + XSetWMProtocols (x_disp, win, &aWMDelete, 1); +} + +// +// VID_FullScreen - open the window in full screen mode +// + +qboolean +VID_FullScreen (Window win) +{ + MotifWmHints hints; + XWindowChanges changes; + + aHints = XInternAtom (x_disp, "_MOTIF_WM_HINTS", 0); + if (aHints == None) { + Con_Printf ("Could not intern X atom for _MOTIF_WM_HINTS."); + return (false); + } + + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = 0; // Absolutely no decorations. + XChangeProperty (x_disp, win, aHints, aHints, 32, PropModeReplace, + (unsigned char *) &hints, 4); + + changes.x = 0; + changes.y = 0; + changes.width = x_screen_width; + changes.height = x_screen_height; + changes.stack_mode = TopIf; + XConfigureWindow (x_disp, win, CWX | CWY | CWWidth | CWHeight | CWStackMode, + &changes); + return (true); +} + +void +VID_Init (unsigned char *palette) +{ + + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + Cmd_AddCommand ("gamma", VID_Gamma_f, "No Description"); + for (i = 0; i < 256; i++) + vid_gamma[i] = i; + + vid.width = 320; + vid.height = 200; + vid.aspect = 1.0; + vid.numpages = 2; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + // vid.cbits = VID_CBITS; + // vid.grades = VID_GRADES; + + 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"); + } + + x_screen = XDefaultScreen (x_disp); + x_screen_width = WidthOfScreen (ScreenOfDisplay (x_disp, x_screen)); + x_screen_height = HeightOfScreen (ScreenOfDisplay (x_disp, x_screen)); + + x_center_width = x_screen_width / 2; + + x_center_height = x_screen_height / 2; + + Con_Printf ("Using screen %d: %dx%d\n", x_screen, x_screen_width, + x_screen_height); + + x_root_win = XRootWindow (x_disp, x_screen); + +// catch signals so i can turn on auto-repeat +// we never run full-screen, so no auto-repeat nukage + if (0) { + 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"); + } + + 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; i < num_visuals; i++) + printf (" -visualid %d\n", (int) (x_visinfo[i].visualid)); + } else if (num_visuals == 0) { + if (template_mask == VisualIDMask) + Sys_Error ("VID: Bad visual id %d\n", template.visualid); + else + Sys_Error ("VID: No visuals at depth %d\n", template.depth); + } + + if (verbose) { + printf ("Using visualid %d:\n", (int) (x_visinfo->visualid)); + printf (" class %d\n", x_visinfo->class); + printf (" screen %d\n", x_visinfo->screen); + printf (" depth %d\n", x_visinfo->depth); + 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 = x_std_event_mask; + 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); + + 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); + } + + } + + VID_SetWindowTitle (x_win, "Quake"); + +// 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.conbuffer = x_framebuffer[0]->data; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + D_InitCaches (surfcache, sizeof (surfcache)); + +// XSynchronize(x_disp, False); + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; + +} + +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_rgb16 (palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]); + st2d_8to24table[i] = + xlib_rgb24 (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 = vid_gamma[palette[i * 3]] * 257; + colors[i].green = vid_gamma[palette[i * 3 + 1]] * 257; + colors[i].blue = vid_gamma[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); + if (mouse_grabbed) { + /* ungrab the pointer */ + XUngrabPointer (x_disp, CurrentTime); + XUndefineCursor (x_disp, x_win); + } + XCloseDisplay (x_disp); +} + +int +XLateKey (XKeyEvent * ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + XLookupString (ev, buf, sizeof buf, &keysym, 0); + + switch (keysym) { + case XK_Page_Up: + key = K_PGUP; + break; + case XK_Page_Down: + key = K_PGDN; + break; + case XK_Home: + key = K_HOME; + break; + case XK_End: + key = K_END; + break; + case XK_Left: + key = K_LEFTARROW; + break; + case XK_Right: + key = K_RIGHTARROW; + break; + case XK_Down: + key = K_DOWNARROW; + break; + case XK_Up: + key = K_UPARROW; + break; + case XK_Escape: + key = K_ESCAPE; + break; + 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: + case XK_Delete: + key = K_BACKSPACE; + break; + case XK_Pause: + key = K_PAUSE; + break; + case XK_Shift_L: + case XK_Shift_R: + key = K_SHIFT; + break; + 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; +// various other keys on the keyboard + case XK_F27: + key = K_HOME; + break; + case XK_F29: + key = K_PGUP; + break; + case XK_F33: + key = K_END; + break; + case XK_F35: + key = K_PGDN; + break; + case XK_KP_Insert: + key = K_INS; + break; + + default: + key = *buf; + 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; + + XNextEvent (x_disp, &x_event); + switch (x_event.type) { + case KeyPress: + Key_Event (XLateKey (&x_event.xkey), true); + break; + case KeyRelease: + Key_Event (XLateKey (&x_event.xkey), false); + break; + case ButtonPress: + // printf( "button %d down\n", x_event.xbutton.button ); + Key_Event (K_MOUSE1 + x_event.xbutton.button - 1, true); + break; + case ButtonRelease: + // printf( "button %d up\n", x_event.xbutton.button ); + Key_Event (K_MOUSE1 + x_event.xbutton.button - 1, false); + break; + case MotionNotify: + if (mouse_avail && mouse_grabbed) { + 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, STD_EVENT_MASK & ~PointerMotionMask); + XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, (vid.width / 2), + (vid.height / 2)); + XSelectInput (x_disp, x_win, STD_EVENT_MASK); + } 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 ConfigureNotify: +// printf("config notify\n"); + config_notify_width = x_event.xconfigure.width; + config_notify_height = x_event.xconfigure.height; + config_notify = 1; + sb_updates = 0; + break; + case Expose: + sb_updates = 0; + break; + case ClientMessage: + if (x_event.xclient.data.l[0] == aWMDelete) + Host_Quit_f (); + break; + case EnterNotify: + mouse_in_window = true; + break; + case LeaveNotify: + mouse_in_window = false; + break; + + default: + if (doShm && x_event.type == x_shmeventtype) + oktodraw = true; + } + + if (mouse_avail) { + if (key_dest == key_game && !mouse_grabbed && mouse_in_window) { + mouse_grabbed = true; + /* grab the pointer */ + XGrabPointer (x_disp, x_win, True, 0, GrabModeAsync, + GrabModeAsync, x_win, None, CurrentTime); + // inviso cursor + XDefineCursor (x_disp, x_win, CreateNullCursor (x_disp, x_win)); + } else if ((key_dest != key_game || !mouse_in_window) && mouse_grabbed) { + mouse_grabbed = false; + /* ungrab the pointer */ + XUngrabPointer (x_disp, CurrentTime); + XUndefineCursor (x_disp, x_win); + } + } +} + +// flushes the given rectangles from the view buffer to the screen + +void +VID_Update (vrect_t *rects) +{ +#if 0 + static int count; + static long long s; + long long gethrtime (); + + if (count == 0) + s = gethrtime (); + + if (count++ == 50) { + count = 1; + printf ("%lf frames/secs\n", + 50.0 / ((double) (gethrtime () - s) / 1e9)); + s = gethrtime (); + } +#endif + +// if the window changes dimension, skip this frame + + if (config_notify) { + printf ("config notify\n"); + config_notify = 0; + vid.width = config_notify_width & ~3; + vid.height = config_notify_height; + + printf ("w = %d, h = %d\n", vid.width, vid.height); + + if (doShm) + ResetSharedFrameBuffers (); + else + ResetFrameBuffer (); + vid.rowbytes = x_framebuffer[0]->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 + return; + } + + if (doShm) { +// long long s, gethrtime(); +// s = gethrtime(); + + while (rects) { + printf ("update: %d,%d (%d,%d)\n", rects->x, rects->y, rects->width, + rects->height); + if (x_visinfo->depth == 16) + st2_fixup (x_framebuffer[current_framebuffer], rects->x, + rects->y, rects->width, rects->height); + else if (x_visinfo->depth == 24) + st3_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; + } +// printf("%lf\n", (double)(gethrtime()-s)/1.0e9); + 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 == 16) + st2_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + else if (x_visinfo->depth == 24) + st3_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; + } +} + +void +VID_SetDefaultMode (void) +{ +} + +int +I_OpenWindow (void) +{ + return 0; +} + +void +I_EraseWindow (int window) +{ +} + +void +I_DrawCircle (int window, int x, int y, int r) +{ +} + +void +I_DisplayWindow (int window) +{ +} + +void +IN_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 +IN_Init (void) +{ + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, "None"); + 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; i < mouse_buttons; i++) { + if ((mouse_buttonstate & (1 << i)) + && !(mouse_oldbuttonstate & (1 << i))) + Key_Event (K_MOUSE1 + i, true); + + if (!(mouse_buttonstate & (1 << i)) + && (mouse_oldbuttonstate & (1 << i))) + Key_Event (K_MOUSE1 + i, false); + } + mouse_oldbuttonstate = mouse_buttonstate; +} + +void +IN_Move (usercmd_t *cmd) +{ + if (!mouse_avail) + return; + + if (m_filter->int_val) { + mouse_x = (mouse_x + old_mouse_x) * 0.5; + mouse_y = (mouse_y + old_mouse_y) * 0.5; + } + + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + + if ((in_strafe.state & 1) || (lookstrafe->int_val && (in_mlook.state & 1))) + cmd->sidemove += 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) + cmd->upmove -= m_forward->value * mouse_y; + else + cmd->forwardmove -= m_forward->value * mouse_y; + } + mouse_x = mouse_y = 0.0; +} + +void +VID_HandlePause (qboolean pause) +{ +} diff --git a/libs/video/targets/vid_sunxil.c b/libs/video/targets/vid_sunxil.c new file mode 100644 index 000000000..887e867c6 --- /dev/null +++ b/libs/video/targets/vid_sunxil.c @@ -0,0 +1,1423 @@ +/* + vid_sunxil.c + + @description@ + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "d_local.h" + +#define MIN_WIDTH 320 +#define MIN_HEIGHT 200 + +cvar_t *_windowed_mouse; +cvar_t *m_filter; +float old_windowed_mouse; + +// The following X property format is defined in Motif 1.1's +// Xm/MwmUtils.h, but QUAKE should not depend on that header +// file. Note: Motif 1.2 expanded this structure with +// uninteresting fields (to QUAKE) so just stick with the +// smaller Motif 1.1 structure. + +#define MWM_HINTS_DECORATIONS 2 +typedef struct { + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +#define MAX_COLUMN_SIZE 11 + +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +typedef struct { + int modenum; + int iscur; + char desc[256]; +} modedesc_t; + +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); + +extern int sb_updates; + +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; + +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; + +#define STD_EVENT_MASK \ +( \ + StructureNotifyMask | \ + KeyPressMask | \ + KeyReleaseMask | \ + ButtonPressMask | \ + ButtonReleaseMask | \ + ExposureMask | \ + PointerMotionMask | \ + FocusChangeMask \ +) + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +byte *VGA_pagebase; + +qboolean x_fullscreen = true; +Display *x_disp = NULL; +int x_screen, x_screen_width, x_screen_height; +int x_center_width, x_center_height; +int x_std_event_mask = STD_EVENT_MASK; +Window x_win, x_root_win; +qboolean x_focus = true; +int global_dx, global_dy; + + +static Colormap x_cmap; +static GC x_gc; +static Visual *x_vis; +static XVisualInfo *x_visinfo; +static Atom aHints = NULL; +static Atom aWMDelete = NULL; + +static qboolean oktodraw = false; +static qboolean X11_active = false; + + +static int verbose = 1; + +static byte current_palette[768]; + +cvar_t *pixel_multiply; +int current_pixel_multiply = 2; + +#define PM(a) (int)((current_pixel_multiply)?((a)*current_pixel_multiply):(a)) +#define MP(a) (int)((current_pixel_multiply)?((a)/current_pixel_multiply):(a)) + +static int render_pipeline[2]; +static XilSystemState state; +static XilImage display_image = NULL; +static XilImage quake_image = NULL; +static int use_mt = 0; +static int count_frames = 0; + +void +VID_InitCvars (void) +{ +} + +/* +================ +D_BeginDirectRect +================ +*/ +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported under Nextstep +} + + +/* +================ +D_EndDirectRect +================ +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ +// direct drawing of the "accessing disk" icon isnt supported under Nextstep +} + + +/* +================= +VID_Gamma_f + +Keybinding command +================= +*/ + +byte vid_gamma[256]; + +void +VID_Gamma_f (void) +{ + + float g, f, inf; + int i; + + if (Cmd_Argc () == 2) { + g = Q_atof (Cmd_Argv (1)); + + for (i = 0; i < 255; i++) { + f = pow ((i + 1) / 256.0, g); + inf = f * 255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + vid_gamma[i] = inf; + } + + VID_SetPalette (current_palette); + + vid.recalc_refdef = 1; // force a surface cache flush + } + +} + +qboolean +CheckPixelMultiply (void) +{ + int m; + int w, h; + XWindowAttributes wattr; + XWindowChanges chg; + unsigned int value_mask; + int old_pixel; + + if ((m = pixel_multiply->int_val) != current_pixel_multiply) { + if (m < 1) + m = 1; + if (m > 4) + m = 4; + + old_pixel = current_pixel_multiply; + current_pixel_multiply = m; + Cvar_SetValue (pixel_multiply, m); + + if (XGetWindowAttributes (x_disp, x_win, &wattr) == 0) + return true; // ??? + + memset (&chg, 0, sizeof (chg)); + chg.width = wattr.width / old_pixel * current_pixel_multiply; + chg.height = wattr.height / old_pixel * current_pixel_multiply; + + if (chg.width < MIN_WIDTH * current_pixel_multiply) + chg.width = MIN_WIDTH * current_pixel_multiply; + if (chg.height < MIN_HEIGHT * current_pixel_multiply) + chg.height = MIN_HEIGHT * current_pixel_multiply; + + XConfigureWindow (x_disp, x_win, CWWidth | CWHeight, &chg); + + vid.width = MP (wattr.width) & ~3; + vid.height = MP (wattr.height); + + if (vid.width < 320) + vid.width = 320; + if (vid.height < 200) + vid.height = 200; + VID_ResetFramebuffer (); + + return true; + } + return false; +} + +// ======================================================================== +// 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 +VID_MenuDraw (void) +{ + qpic_t *p; + char *ptr; + int i, j, column, row, dup; + char temp[100]; + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ((320 - p->width) / 2, 4, p); + M_Print (4 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8, + "Video mode switching unavailable"); + M_Print (9 * 8, 36 + MAX_COLUMN_SIZE * 8 + 8 * 6, "Press any key..."); +} + +void +VID_MenuKey (int key) +{ + M_Menu_Options_f (); +} + +// 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 + +byte surfcache[1024 * 1024]; + +// +// VID_SetWindowTitle - set the window and icon titles +// + +void +VID_SetWindowTitle (Window win, char *pszName) +{ + XTextProperty textprop; + XWMHints *wmHints; + + // Setup ICCCM properties + textprop.value = (unsigned char *) pszName; + textprop.encoding = XA_STRING; + textprop.format = 8; + textprop.nitems = strlen (pszName); + wmHints = XAllocWMHints (); + wmHints->initial_state = NormalState; + wmHints->flags = StateHint; + XSetWMProperties (x_disp, win, &textprop, &textprop, + // Only put WM_COMMAND property on first window. + com_argv, com_argc, NULL, NULL, NULL); + XFree (wmHints); + + aWMDelete = XInternAtom (x_disp, "WM_DELETE_WINDOW", False); + XSetWMProtocols (x_disp, win, &aWMDelete, 1); +} + +// +// VID_FullScreen - open the window in full screen mode +// + +qboolean +VID_FullScreen (Window win) +{ + MotifWmHints hints; + XWindowChanges changes; + + aHints = XInternAtom (x_disp, "_MOTIF_WM_HINTS", 0); + if (aHints == None) { + Con_Printf ("Could not intern X atom for _MOTIF_WM_HINTS."); + return (false); + } + + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = 0; // Absolutely no decorations. + XChangeProperty (x_disp, win, aHints, aHints, 32, PropModeReplace, + (unsigned char *) &hints, 4); + + changes.x = 0; + changes.y = 0; + changes.width = x_screen_width; + changes.height = x_screen_height; + changes.stack_mode = TopIf; + XConfigureWindow (x_disp, win, CWX | CWY | CWWidth | CWHeight | CWStackMode, + &changes); + return (true); +} + +void +VID_Init (unsigned char *palette) +{ + + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + int w, h; + + int desired_width = 320, desired_height = 200; + + Cmd_AddCommand ("gamma", VID_Gamma_f, "No Description"); + + pixel_multiply = Cvar_Get ("pixel_multiply", "2", CVAR_ARCHIVE, NULL, + "None"); + + if (pipe (render_pipeline) < 0) + Sys_Error ("VID_Init: pipe"); + + for (i = 0; i < 256; i++) + vid_gamma[i] = i; + + vid.width = 320; + vid.height = 200; + vid.aspect = 1.0; + vid.numpages = 2; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + // vid.cbits = VID_CBITS; + // vid.grades = VID_GRADES; + + srandom (getpid ()); + + verbose = COM_CheckParm ("-verbose"); + count_frames = COM_CheckParm ("-count_frames"); + +// +// 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"); + } + + x_screen = DefaultScreen (x_disp); + x_screen_width = WidthOfScreen (ScreenOfDisplay (x_disp, x_screen)); + x_screen_height = HeightOfScreen (ScreenOfDisplay (x_disp, x_screen)); + + x_center_width = x_screen_width / 2; + + x_center_height = x_screen_height / 2; + + Con_Printf ("Using screen %d: %dx%d\n", x_screen, x_screen_width, + x_screen_height); + + x_root_win = DefaultRootWindow (x_disp); + + // XAutoRepeatOff(x_disp); + +// for debugging only + if (verbose) + 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"); + desired_width = Q_atoi (com_argv[pnum + 1]); + desired_height = Q_atoi (com_argv[pnum + 2]); + if (desired_width < 1 || desired_height < 1) + Sys_Error ("VID: Bad window width/height\n"); + } + + template_mask = VisualScreenMask; // make sure we get the right one + template.screen = x_screen; +// +// 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; + } else { + // If not specified, find an 8 bit visual since others don't work +// template.depth = 8; +// template_mask |= VisualDepthMask; + 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; i < num_visuals; i++) + printf (" -visualid %d\n", (int) (x_visinfo[i].visualid)); + } else if (num_visuals == 0) { + if (template_mask == VisualIDMask) + Sys_Error ("VID: Bad visual id %d\n", template.visualid); + else + Sys_Error ("VID: No visuals at depth %d\n", template.depth); + } + + if (verbose) { + printf ("Using visualid %d:\n", (int) (x_visinfo->visualid)); + 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; +// +// See if we're going to do pixel multiply +// + if (pixel_multiply->int_val < 1 || pixel_multiply->int_val > 4) + Cvar_SetValue (pixel_multiply, 2); + current_pixel_multiply = pixel_multiply->int_val; + + w = 320 * current_pixel_multiply; // minimum width + h = 200 * current_pixel_multiply; // minimum height + if (desired_width < w) + desired_width = w; + if (desired_height < h) + desired_height = h; + + vid.width = MP (desired_width); + vid.height = MP (desired_height); + + // + // patch things up so game doesn't fail if window is too small + // + + if (vid.width < 320) + vid.width = 320; + if (vid.height < 200) + vid.height = 200; + +// +// see if we're going to use threads +// + if (((sysconf (_SC_NPROCESSORS_ONLN) > 1) || COM_CheckParm ("-mt")) && + (COM_CheckParm ("-no_mt") == 0)) { + use_mt = 1; + printf ("VID: Using multiple threads!\n"); + } +// 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 = x_std_event_mask; + 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 + desired_width, desired_height, 0, // borderwidth + x_visinfo->depth, + InputOutput, x_vis, attribmask, &attribs); + + 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); + } + + } + + VID_SetWindowTitle (x_win, "Quake"); + +// 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); + XSync (x_disp, True); /* wait for map */ +// +// wait for first exposure event +// + { + XEvent event; + + do { + XNextEvent (x_disp, &event); + if (event.type == Expose && !event.xexpose.count) + oktodraw = true; + } while (!oktodraw); + } +// +// initialize XIL +// + + state = xil_open (); + + if (state == NULL) { + // + // XIL's default error handler will print an error msg on stderr + // + Sys_Error ("xil_open failed\n"); + } + + X11_active = true; + + VID_ResetFramebuffer (); + + D_InitCaches (surfcache, sizeof (surfcache)); + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; +} + +VID_ResetFramebuffer () +{ + XilMemoryStorage storage; + + if (use_mt) { + VID_ResetFramebuffer_MT (); + return; + } +//printf("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, vid.height); + + xil_destroy (display_image); + + xil_destroy (quake_image); + + display_image = xil_create_from_window (state, x_disp, x_win); + quake_image = xil_create (state, vid.width, vid.height, 1, XIL_BYTE); + + xil_export (quake_image); + + if (xil_get_memory_storage (quake_image, &storage) == FALSE) + Sys_Error ("xil_get_memory_storage"); + + xil_import (quake_image, TRUE); + xil_export (quake_image); + + if (xil_get_memory_storage (quake_image, &storage) == FALSE) + Sys_Error ("xil_get_memory_storage"); + + vid.rowbytes = storage.byte.scanline_stride; + vid.buffer = storage.byte.data; + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.recalc_refdef = 1; // force a surface cache flush + + free (d_pzbuffer); + + d_pzbuffer = + malloc (PM (vid.width) * PM (vid.height) * sizeof (*d_pzbuffer)); + // Hunk_HighAllocName(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer),"zbuff"); +} + +VID_ResetFramebuffer_MT () +{ + XilMemoryStorage storage; + XilImage drain_renderpipeline (); + XilImage old_display_image; + + void *update_thread (); + + printf ("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, + vid.height); + + old_display_image = display_image; + + display_image = xil_create_from_window (state, x_disp, x_win); + + if (quake_image == NULL) + if (thr_create (NULL, NULL, update_thread, NULL, THR_NEW_LWP, NULL) != + 0) Sys_Error ("VID: thr_create"); + + quake_image = drain_renderpipeline (quake_image); + + xil_destroy (old_display_image); + + free (d_pzbuffer); + + d_pzbuffer = + malloc (PM (vid.width) * PM (vid.height) * sizeof (*d_pzbuffer)); +} + +void +VID_ShiftPalette (unsigned char *p) +{ + VID_SetPalette (p); +} + +void +VID_SetPalette (unsigned char *palette) +{ + + int i; + XColor colors[256]; + + 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 = vid_gamma[palette[i * 3]] * 257; + colors[i].green = vid_gamma[palette[i * 3 + 1]] * 257; + colors[i].blue = vid_gamma[palette[i * 3 + 2]] * 257; + } + XStoreColors (x_disp, x_cmap, colors, 256); + } + +} + +// Called at shutdown + +void +VID_Shutdown (void) +{ + X11_active = false; + Con_Printf ("VID_Shutdown\n"); + // XAutoRepeatOn(x_disp); + xil_destroy (display_image); + xil_destroy (quake_image); + display_image = NULL; + quake_image = NULL; + XCloseDisplay (x_disp); +} + +int +XLateKey (XKeyEvent * ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + XLookupString (ev, buf, sizeof buf, &keysym, 0); + + switch (keysym) { + case XK_Page_Up: + key = K_PGUP; + break; + case XK_Page_Down: + key = K_PGDN; + break; + case XK_Home: + key = K_HOME; + break; + case XK_End: + key = K_END; + break; + case XK_Left: + key = K_LEFTARROW; + break; + case XK_Right: + key = K_RIGHTARROW; + break; + case XK_Down: + key = K_DOWNARROW; + break; + case XK_Up: + key = K_UPARROW; + break; + case XK_Escape: + key = K_ESCAPE; + break; + case XK_Return: + key = K_ENTER; + break; + case XK_Tab: + key = K_TAB; + break; + case XK_Help: + 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: + case XK_Delete: + key = K_BACKSPACE; + break; + case XK_Pause: + key = K_PAUSE; + break; + case XK_Shift_L: + case XK_Shift_R: + key = K_SHIFT; + break; + 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; + // various other keys on the keyboard + case XK_F27: + key = K_HOME; + break; + case XK_F29: + key = K_PGUP; + break; + case XK_F33: + key = K_END; + break; + case XK_F35: + key = K_PGDN; + break; + case XK_Insert: + case XK_KP_Insert: + key = K_INS; + break; + case XK_F24: + key = '-'; + break; + case XK_KP_Add: + key = '+'; + break; + case XK_KP_Subtract: + key = '-'; + break; + case XK_F25: + key = '/'; + break; + case XK_F26: + key = '*'; + break; + + default: + key = (unsigned char) *buf; + 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: + Key_Event (XLateKey (&x_event.xkey), true); + break; + case KeyRelease: + Key_Event (XLateKey (&x_event.xkey), false); + break; + + case MotionNotify: + + if (_windowed_mouse->int_val) { + 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, x_std_event_mask & ~PointerMotionMask); + XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, + (vid.width / 2), (vid.height / 2)); + XSelectInput (x_disp, x_win, x_std_event_mask); + } 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 << b; + break; + + case ButtonRelease: + 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 << b); + break; + + case ConfigureNotify: + // printf("config notify\n"); + config_notify_width = x_event.xconfigure.width; + config_notify_height = x_event.xconfigure.height; + config_notify = 1; + sb_updates = 0; + break; + case Expose: + sb_updates = 0; + break; + case ClientMessage: + if (x_event.xclient.data.l[0] == aWMDelete) + Host_Quit_f (); + break; +#if 0 + case FocusIn: + printf ("FocusIn...\n"); + x_focus = true; + break; + case FocusOut: + printf ("FocusOut...\n"); + x_focus = false; + break; +#endif + } + + if (old_windowed_mouse != _windowed_mouse->int_val) { + old_windowed_mouse = _windowed_mouse->int_val; + + if (!_windowed_mouse->int_val) { + /* ungrab the pointer */ + XUngrabPointer (x_disp, CurrentTime); + } else { + /* grab the pointer */ + XGrabPointer (x_disp, x_win, True, 0, GrabModeAsync, + GrabModeAsync, x_win, None, CurrentTime); + } + } +} + +// flushes the given rectangles from the view buffer to the screen + +void +VID_Update (vrect_t *rects) +{ + void VID_Update_MT (vrect_t *); + + + if (count_frames) { + static int count; + static long long s; + long long gethrtime (); + + if (count == 0) + s = gethrtime (); + + if (count++ == 200) { + long long n = gethrtime (); + + count = 1; + printf ("%lf frames/secs\n", 200.0 / ((double) (n - s) / 1e9)); + s = n; + } + } + + if (use_mt) { + VID_Update_MT (rects); + return; + } + // if the window changes dimension, skip this frame + + if (config_notify) { + int w, h; + XWindowChanges chg; + unsigned int value_mask; + + w = 320 * current_pixel_multiply; // minimum width + h = 200 * current_pixel_multiply; // minimum height + + if (config_notify_width < w || config_notify_height < h) { + // We must resize the window + memset (&chg, 0, sizeof (chg)); + value_mask = 0; + if (config_notify_width < w) { + config_notify_width = chg.width = w; + value_mask |= CWWidth; + } + if (config_notify_height < h) { + config_notify_height = chg.height = h; + value_mask |= CWHeight; + } + if (value_mask) + XConfigureWindow (x_disp, x_win, value_mask, &chg); + } + + config_notify = 0; + + vid.width = MP (config_notify_width) & ~3; + vid.height = MP (config_notify_height); + + if (vid.width < 320) + vid.width = 320; + if (vid.height < 200) + vid.height = 200; + + VID_ResetFramebuffer (); + + return; + } + // if pixel multiply changed, skip this frame + if (CheckPixelMultiply ()) + return; + + while (rects) { // I've never seen more than one + // rect? + XilMemoryStorage storage; + + xil_import (quake_image, TRUE); // let xil control the image + + if (current_pixel_multiply < 2) + xil_copy (quake_image, display_image); + else + xil_scale (quake_image, display_image, "nearest", + (float) current_pixel_multiply, + (float) current_pixel_multiply); + + xil_export (quake_image); // back to quake + + if (xil_get_memory_storage (quake_image, &storage) == FALSE) + Sys_Error ("xil_get_memory_storage"); + + vid.buffer = storage.byte.data; + vid.conbuffer = vid.buffer; + + rects = rects->pnext; + } +} + +void +VID_Update_MT (vrect_t *rects) +{ + XilImage sched_update (); + + // if the window changes dimension, skip this frame + + if (config_notify) { + int w, h; + XWindowChanges chg; + unsigned int value_mask; + + w = 320 * current_pixel_multiply; // minimum width + h = 200 * current_pixel_multiply; // minimum height + + if (config_notify_width < w || config_notify_height < h) { + // We must resize the window + memset (&chg, 0, sizeof (chg)); + value_mask = 0; + if (config_notify_width < w) { + config_notify_width = chg.width = w; + value_mask |= CWWidth; + } + if (config_notify_height < h) { + config_notify_height = chg.height = h; + value_mask |= CWHeight; + } + if (value_mask) + XConfigureWindow (x_disp, x_win, value_mask, &chg); + } + + config_notify = 0; + + vid.width = MP (config_notify_width) & ~3; + vid.height = MP (config_notify_height); + + if (vid.width < 320) + vid.width = 320; + if (vid.height < 200) + vid.height = 200; + + VID_ResetFramebuffer_MT (); + + return; + } + // if pixel multiply changed, skip this frame + if (CheckPixelMultiply ()) + return; + + quake_image = sched_update (quake_image); +} + +XilImage drain_renderpipeline (XilImage old) +{ + XilImage new; + + XilMemoryStorage storage; + + if (old) + if (read (render_pipeline[1], &new, sizeof (new)) != sizeof (new)) { + Sys_Error ("drain_renderpipeline: read"); + xil_destroy (new); + } + + xil_destroy (old); + + + new = xil_create (state, vid.width, vid.height, 1, XIL_BYTE); + + if (write (render_pipeline[0], &new, sizeof (new)) != sizeof (new)) + Sys_Error ("drain_renderpipeline: write"); + + new = xil_create (state, vid.width, vid.height, 1, XIL_BYTE); + + xil_export (new); + + if (xil_get_memory_storage (new, &storage) == FALSE) + Sys_Error ("xil_get_memory_storage"); + + vid.rowbytes = storage.byte.scanline_stride; + vid.buffer = storage.byte.data; + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.recalc_refdef = 1; // force a surface cache flush + + return (new); + +} + +XilImage sched_update (XilImage image) +{ + XilImage new; + XilMemoryStorage storage; + + if (write (render_pipeline[1], &image, sizeof (image)) != sizeof (image)) + Sys_Error ("sched_update:write"); + + if (read (render_pipeline[1], &new, sizeof (new)) != sizeof (new)) + Sys_Error ("sched_update:read"); + + xil_export (new); + + if (xil_get_memory_storage (new, &storage) == FALSE) + Sys_Error ("xil_get_memory_storage"); + + vid.buffer = storage.byte.data; + vid.conbuffer = vid.buffer; + + return (new); +} + +void * +update_thread () +{ + XilImage image; + + if (!X11_active) + return; + + while (read (render_pipeline[0], &image, sizeof (image)) == sizeof (image)) { + + xil_import (image, TRUE); // let xil control the image + + if (!display_image) + return; + + if (current_pixel_multiply < 2) + xil_copy (image, display_image); + else + xil_scale (image, display_image, "nearest", + (float) current_pixel_multiply, + (float) current_pixel_multiply); + + if (write (render_pipeline[0], &image, sizeof (image)) != + sizeof (image)) Sys_Error ("update_thread: write"); + } +} + + +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; + } +} + +void +VID_SetDefaultMode (void) +{ +} + +int +I_OpenWindow (void) +{ + return 0; +} + +void +I_EraseWindow (int window) +{ + +} + +void +I_DrawCircle (int window, int x, int y, int r) +{ +} + +void +I_DisplayWindow (int window) +{ +} + +void +IN_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; + } + } +} + +void +IN_Init (void) +{ + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, + "None"); + m_filter = Cvar_Get ("m_filter", "0", CVAR_ARCHIVE, NULL, "None"); + 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; i < mouse_buttons; i++) { + if ((mouse_buttonstate & (1 << i)) + && !(mouse_oldbuttonstate & (1 << i))) + Key_Event (K_MOUSE1 + i, true); + + if (!(mouse_buttonstate & (1 << i)) + && (mouse_oldbuttonstate & (1 << i))) + Key_Event (K_MOUSE1 + i, false); + } + mouse_oldbuttonstate = mouse_buttonstate; +} + +void +IN_Move (usercmd_t *cmd) +{ + if (!mouse_avail) + return; + + if (m_filter->int_val) { + mouse_x = (mouse_x + old_mouse_x) * 0.5; + mouse_y = (mouse_y + old_mouse_y) * 0.5; + } + + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + + mouse_x *= sensitivity->value; + mouse_y *= sensitivity->value; + + if ((in_strafe.state & 1) || (lookstrafe->int_val && (in_mlook.state & 1))) + cmd->sidemove += 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) + cmd->upmove -= m_forward->value * mouse_y; + else + cmd->forwardmove -= m_forward->value * mouse_y; + } + mouse_x = mouse_y = 0.0; +} + +//void VID_UnlockBuffer(void) { } +//void VID_LockBuffer(void) { } + + +void +VID_HandlePause (qboolean pause) +{ +} diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c new file mode 100644 index 000000000..9a0049caf --- /dev/null +++ b/libs/video/targets/vid_svgalib.c @@ -0,0 +1,772 @@ +/* + vid_svgalib.c + + Linux SVGALib video routines + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999-2000 David Symonds [xoxus@usa.net] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#if defined(HAVE_SYS_IO_H) +# include +#elif defined(HAVE_ASM_IO_H) +# include +#endif + +#include +#include + +#include "QF/cmd.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "d_local.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "QF/sys.h" + +void VGA_UpdatePlanarScreen (void *srcbuffer); + +cvar_t *vid_system_gamma; +qboolean vid_gamma_avail; + +unsigned short d_8to16table[256]; + +static int num_modes, current_mode; +static vga_modeinfo *modes; + +static byte vid_current_palette[768]; + +static int svgalib_inited = 0; +static int svgalib_backgrounded = 0; +static int UseDisplay = 1; + +static cvar_t *vid_mode; +static cvar_t *vid_redrawfull; +static cvar_t *vid_waitforrefresh; + +static char *framebuffer_ptr; + + +static byte backingbuf[48 * 24]; + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +byte *VGA_pagebase; + +int VID_options_items = 0; + + +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ + int i, j, k, plane, reps, repshift, offset, vidpage, off; + + if (!svgalib_inited || !vid.direct || svgalib_backgrounded + || !vga_oktowrite ())return; + + if (vid.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + vidpage = 0; + vga_setpage (0); + + if (VGA_planar) { + for (plane = 0; plane < 4; plane++) { + /* Select the correct plane for reading and writing */ + outb (0x02, 0x3C4); + outb (1 << plane, 0x3C5); + outb (4, 0x3CE); + outb (plane, 0x3CF); + + for (i = 0; i < (height << repshift); i += reps) { + for (k = 0; k < reps; k++) { + for (j = 0; j < (width >> 2); j++) { + backingbuf[(i + k) * 24 + (j << 2) + plane] = + vid.direct[(y + i + k) * VGA_rowbytes + + (x >> 2) + j]; + vid.direct[(y + i + k) * VGA_rowbytes + (x >> 2) + j] = + pbitmap[(i >> repshift) * 24 + (j << 2) + plane]; + } + } + } + } + } else { + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + offset = x + ((y << repshift) + i + j) + * vid.rowbytes; + off = offset % 0x10000; + if ((offset / 0x10000) != vidpage) { + vidpage = offset / 0x10000; + vga_setpage (vidpage); + } + memcpy (&backingbuf[(i + j) * 24], vid.direct + off, width); + memcpy (vid.direct + off, + &pbitmap[(i >> repshift) * width], width); + } + } + } +} + + +void +D_EndDirectRect (int x, int y, int width, int height) +{ + int i, j, k, plane, reps, repshift, offset, vidpage, off; + + if (!svgalib_inited || !vid.direct || svgalib_backgrounded + || !vga_oktowrite ())return; + + if (vid.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + vidpage = 0; + vga_setpage (0); + + if (VGA_planar) { + for (plane = 0; plane < 4; plane++) { + /* Select the correct plane for writing */ + outb (2, 0x3C4); + outb (1 << plane, 0x3C5); + outb (4, 0x3CE); + outb (plane, 0x3CF); + + for (i = 0; i < (height << repshift); i += reps) { + for (k = 0; k < reps; k++) { + for (j = 0; j < (width >> 2); j++) { + vid.direct[(y + i + k) * VGA_rowbytes + (x >> 2) + j] = + backingbuf[(i + k) * 24 + (j << 2) + plane]; + } + } + } + } + } else { + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + offset = x + ((y << repshift) + i + j) + * vid.rowbytes; + off = offset % 0x10000; + if ((offset / 0x10000) != vidpage) { + vidpage = offset / 0x10000; + vga_setpage (vidpage); + } + memcpy (vid.direct + off, &backingbuf[(i + j) * 24], width); + } + } + } +} + + +#if 0 +static void +VID_Gamma_f (void) +{ + float gamma, f, inf; + unsigned char palette[768]; + int i; + + if (Cmd_Argc () == 2) { + gamma = atof (Cmd_Argv (1)); + + for (i = 0; i < 768; i++) { + f = pow ((vid_basepal[i] + 1) / 256.0, gamma); + inf = f * 255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + palette[i] = inf; + } + + VID_SetPalette (palette); + + /* Force a surface cache flush */ + vid.recalc_refdef = 1; + } +} +#endif + + +static void +VID_DescribeMode_f (void) +{ + int modenum; + + modenum = atoi (Cmd_Argv (1)); + if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width) { + Con_Printf ("Invalid video mode: %d!\n", modenum); + } + Con_Printf ("%d: %d x %d - ", modenum, + modes[modenum].width, modes[modenum].height); + if (modes[modenum].bytesperpixel == 0) { + Con_Printf ("ModeX\n"); + } else { + Con_Printf ("%d bpp\n", modes[modenum].bytesperpixel << 3); + } +} + + +static void +VID_DescribeModes_f (void) +{ + int i; + + for (i = 0; i < num_modes; i++) { + if (modes[i].width) { + Con_Printf ("%d: %d x %d - ", i, modes[i].width, modes[i].height); + if (modes[i].bytesperpixel == 0) + Con_Printf ("ModeX\n"); + else + Con_Printf ("%d bpp\n", modes[i].bytesperpixel << 3); + } + } +} + + +/* + VID_NumModes +*/ +static int +VID_NumModes (void) +{ + int i, i1 = 0; + + for (i = 0; i < num_modes; i++) { + i1 += modes[i].width ? 1 : 0; + } + return (i1); +} + + +static void +VID_NumModes_f (void) +{ + Con_Printf ("%d modes\n", VID_NumModes ()); +} + + +static void +VID_Debug_f (void) +{ + Con_Printf ("mode: %d\n", current_mode); + Con_Printf ("height x width: %d x %d\n", vid.height, vid.width); + Con_Printf ("bpp: %d\n", modes[current_mode].bytesperpixel * 8); + Con_Printf ("vid.aspect: %f\n", vid.aspect); +} + + +static void +VID_InitModes (void) +{ + int i; + + /* Get complete information on all modes */ + num_modes = vga_lastmodenumber () + 1; + modes = malloc (num_modes * sizeof (vga_modeinfo)); + for (i = 0; i < num_modes; i++) { + if (vga_hasmode (i)) { + memcpy (&modes[i], vga_getmodeinfo (i), sizeof (vga_modeinfo)); + } else { + modes[i].width = 0; // means not available + } + } + + /* Filter for modes we don't support */ + for (i = 0; i < num_modes; i++) { + if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) { + modes[i].width = 0; + } + } +} + + +static int +get_mode (char *name, int width, int height, int depth) +{ + int i, ok, match; + + match = (!!width) + (!!height) * 2 + (!!depth) * 4; + + if (name) { + i = vga_getmodenumber (name); + if (!modes[i].width) { + Sys_Printf ("Mode [%s] not supported\n", name); + i = G320x200x256; + } + } else { + for (i = 0; i < num_modes; i++) { + if (modes[i].width) { + ok = (modes[i].width == width) + + (modes[i].height == height) * 2 + + (modes[i].bytesperpixel == depth / 8) * 4; + if ((ok & match) == ok) + break; + } + } + if (i == num_modes) { + Sys_Printf ("Mode %dx%d (%d bits) not supported\n", + width, height, depth); + i = G320x200x256; + } + } + + return i; +} + + +void +VID_InitBuffers (void) +{ + int buffersize, zbuffersize, cachesize; + void *vid_surfcache; + + // Calculate the sizes we want first + buffersize = vid.rowbytes * vid.height; + zbuffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + cachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + // Free the old screen buffer + if (vid.buffer) { + free (vid.buffer); + vid.conbuffer = vid.buffer = NULL; + } + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new screen buffer + vid.conbuffer = vid.buffer = calloc (buffersize, 1); + if (!vid.conbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new z-buffer + d_pzbuffer = calloc (zbuffersize, 1); + if (!d_pzbuffer) { + free (vid.buffer); + vid.conbuffer = vid.buffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (cachesize, 1); + if (!vid_surfcache) { + free (vid.buffer); + free (d_pzbuffer); + vid.conbuffer = vid.buffer = NULL; + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + + D_InitCaches (vid_surfcache, cachesize); +} + + +void +VID_Shutdown (void) +{ + Sys_Printf ("VID_Shutdown\n"); + + if (!svgalib_inited) + return; + + if (UseDisplay) { + vga_setmode (TEXT); + } + svgalib_inited = 0; +} + + +void +VID_ShiftPalette (unsigned char *p) +{ + VID_SetPalette (p); +} + + +void +VID_SetPalette (byte * palette) +{ + static int tmppal[256 * 3]; + int *tp; + int i; + + if (!svgalib_inited || svgalib_backgrounded) + return; + + memcpy (vid_current_palette, palette, sizeof (vid_current_palette)); + + if (vga_getcolors () == 256) { + tp = tmppal; + for (i = 256 * 3; i; i--) { + *(tp++) = *(palette++) >> 2; + } + + if (UseDisplay && vga_oktowrite ()) { + vga_setpalvec (0, 256, tmppal); + } + } +} + + +int +VID_SetMode (int modenum, unsigned char *palette) +{ + int err; + + if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width) { + Cvar_SetValue (vid_mode, current_mode); + + Con_Printf ("No such video mode: %d\n", modenum); + + return 0; + } + + Cvar_SetValue (vid_mode, modenum); + + current_mode = modenum; + + vid.width = modes[current_mode].width; + vid.height = modes[current_mode].height; + + VGA_width = modes[current_mode].width; + VGA_height = modes[current_mode].height; + VGA_planar = modes[current_mode].bytesperpixel == 0; + VGA_rowbytes = modes[current_mode].linewidth; + vid.rowbytes = modes[current_mode].linewidth; + if (VGA_planar) { + VGA_bufferrowbytes = modes[current_mode].linewidth * 4; + vid.rowbytes = modes[current_mode].linewidth * 4; + } + + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.colormap = (pixel_t *) vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.conrowbytes = vid.rowbytes; + vid.conwidth = vid.width; + vid.conheight = vid.height; + vid.numpages = 1; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + // alloc screen buffer, z-buffer, and surface cache + VID_InitBuffers (); + + /* get goin' */ + err = vga_setmode (current_mode); + if (err) { + Sys_Error ("Video mode failed: %d\n", modenum); + } + VID_SetPalette (palette); + + VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem (); +#if 0 + if (vga_setlinearaddressing () > 0) { + framebuffer_ptr = (char *) vga_getgraphmem (); + } +#endif + if (!framebuffer_ptr) { + Sys_Error ("This mode isn't hapnin'\n"); + } + + vga_setpage (0); + + svgalib_inited = 1; + + /* Force a surface cache flush */ + vid.recalc_refdef = 1; + + return 1; +} + +static void +goto_background (void) +{ + svgalib_backgrounded = 1; +} + +static void +comefrom_background (void) +{ + svgalib_backgrounded = 0; +} + + +void +VID_Init (unsigned char *palette) +{ + int w, h, d; + int err; + + // plugin_load("in_svgalib.so"); + + if (svgalib_inited) + return; + +#if 0 + Cmd_AddCommand ("gamma", VID_Gamma_f, "Brightness level"); +#endif + + if (UseDisplay) { + err = vga_init (); + if (err) + Sys_Error ("SVGALib failed to allocate a new VC\n"); + + if (vga_runinbackground_version () == 1) { + Con_Printf ("SVGALIB background support detected\n"); + vga_runinbackground (VGA_GOTOBACK, goto_background); + vga_runinbackground (VGA_COMEFROMBACK, comefrom_background); + vga_runinbackground (1); + } else { + vga_runinbackground (0); + } + + VID_InitModes (); + + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" + "(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); + Cmd_AddCommand ("vid_debug", VID_Debug_f, "FIXME: No Description"); + + /* Interpret command-line params */ + w = h = d = 0; + if (getenv ("GSVGAMODE")) { + current_mode = get_mode (getenv ("GSVGAMODE"), w, h, d); + } else if (COM_CheckParm ("-mode")) { + current_mode = + get_mode (com_argv[COM_CheckParm ("-mode") + 1], w, h, d); + } else if (COM_CheckParm ("-w") || COM_CheckParm ("-h") + || COM_CheckParm ("-d")) { + if (COM_CheckParm ("-w")) { + w = atoi (com_argv[COM_CheckParm ("-w") + 1]); + } + if (COM_CheckParm ("-h")) { + h = atoi (com_argv[COM_CheckParm ("-h") + 1]); + } + if (COM_CheckParm ("-d")) { + d = atoi (com_argv[COM_CheckParm ("-d") + 1]); + } + current_mode = get_mode (0, w, h, d); + } else { + current_mode = G320x200x256; + } + + /* Set vid parameters */ + VID_SetMode (current_mode, palette); + Con_CheckResize (); // Now that we have a window size, fix console + + VID_SetPalette (palette); + } +} + +void +VID_Init_Cvars () +{ + vid_mode = Cvar_Get ("vid_mode", "5", CVAR_NONE, NULL, + "Sets the video mode"); + vid_redrawfull = Cvar_Get ("vid_redrawfull", "0", CVAR_NONE, NULL, + "Redraw entire screen each frame instead of just dirty areas"); + vid_waitforrefresh = Cvar_Get ("vid_waitforrefresh", "0", CVAR_ARCHIVE, + NULL, "Wait for vertical retrace before drawing next frame"); + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, + "Use system gamma control if available"); +} + + +void +VID_Update (vrect_t *rects) +{ + if (!svgalib_inited || svgalib_backgrounded) + return; + + if (!vga_oktowrite ()) { + /* Can't update screen if it's not active */ + return; + } + + if (vid_waitforrefresh->int_val) { + vga_waitretrace (); + } + + if (VGA_planar) { + VGA_UpdatePlanarScreen (vid.buffer); + } else if (vid_redrawfull->int_val) { + int total = vid.rowbytes * vid.height; + int offset; + + for (offset = 0; offset < total; offset += 0x10000) { + vga_setpage (offset / 0x10000); + memcpy (framebuffer_ptr, vid.buffer + offset, + ((total - offset > 0x10000) ? 0x10000 : (total - offset))); + } + } else { + int ycount; + int offset; + int vidpage = 0; + + vga_setpage (0); + + while (rects) { + ycount = rects->height; + offset = rects->y * vid.rowbytes + rects->x; + while (ycount--) { + register int i = offset % 0x10000; + + if ((offset / 0x10000) != vidpage) { + vidpage = offset / 0x10000; + vga_setpage (vidpage); + } + if (rects->width + i > 0x10000) { + memcpy (framebuffer_ptr + i, + vid.buffer + offset, 0x10000 - i); + vga_setpage (++vidpage); + memcpy (framebuffer_ptr, + vid.buffer + offset + 0x10000 - i, + rects->width - 0x10000 + i); + } else { + memcpy (framebuffer_ptr + i, + vid.buffer + offset, rects->width); + } + offset += vid.rowbytes; + } + rects = rects->pnext; + } + } + + if (vid_mode->int_val != current_mode) { + VID_SetMode (vid_mode->int_val, vid_current_palette); + } +} + + +static int dither = 0; + +void +VID_DitherOn (void) +{ + if (dither == 0) { +#if 0 + R_ViewChanged (&vrect, sb_lines, vid.aspect); +#endif + dither = 1; + } +} + + +void +VID_DitherOff (void) +{ + if (dither) { +#if 0 + R_ViewChanged (&vrect, sb_lines, vid.aspect); +#endif + dither = 0; + } +} + + +/* + VID_ModeInfo +*/ +char * +VID_ModeInfo (int modenum) +{ + static char *badmodestr = "Bad mode number"; + static char modestr[40]; + + if (modenum == 0) { + snprintf (modestr, sizeof (modestr), "%d x %d, %d bpp", + vid.width, vid.height, modes[current_mode].bytesperpixel * 8); + return (modestr); + } else { + return (badmodestr); + } +} + + +void +VID_ExtraOptionDraw (unsigned int options_draw_cursor) +{ + /* No extra option menu items yet */ +} + + +void +VID_ExtraOptionCmd (int option_cursor) +{ +#if 0 + switch (option_cursor) { + case 1: // Always start with 1 + break; + } +#endif +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (char *text) +{ +} + +qboolean +VID_SetGamma (double gamma) +{ + return false; //FIXME +} diff --git a/libs/video/targets/vid_vga.c b/libs/video/targets/vid_vga.c new file mode 100644 index 000000000..541546260 --- /dev/null +++ b/libs/video/targets/vid_vga.c @@ -0,0 +1,455 @@ + +/* + vid_vga.c + + @description@ + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" +#include + +extern regs_t regs; + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; +byte *VGA_pagebase; +vmode_t *VGA_pcurmode; + +static int VGA_planar; +static int VGA_numpages; +static int VGA_buffersize; + +void *vid_surfcache; +int vid_surfcachesize; + +int VGA_highhunkmark; + +#include "vgamodes.h" + +#define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0])) + +void VGA_UpdatePlanarScreen (void *srcbuffer); + +static byte backingbuf[48 * 24]; + +/* +================ +VGA_BeginDirectRect +================ +*/ +void +VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, + int y, byte * pbitmap, int width, int height) +{ + int i, j, k, plane, reps, repshift; + + if (!lvid->direct) + return; + + if (lvid->aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + if (pcurrentmode->planar) { + for (plane = 0; plane < 4; plane++) { + // select the correct plane for reading and writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 1 << plane); + outportb (GC_INDEX, READ_MAP); + outportb (GC_DATA, plane); + + for (i = 0; i < (height << repshift); i += reps) { + for (k = 0; k < reps; k++) { + for (j = 0; j < (width >> 2); j++) { + backingbuf[(i + k) * 24 + (j << 2) + plane] = + lvid->direct[(y + i + k) * VGA_rowbytes + + (x >> 2) + j]; + lvid->direct[(y + i + k) * VGA_rowbytes + (x >> 2) + + j] = + pbitmap[(i >> repshift) * 24 + (j << 2) + plane]; + } + } + } + } + } else { + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + memcpy (&backingbuf[(i + j) * 24], + lvid->direct + x + ((y << repshift) + i + j) * + VGA_rowbytes, width); + memcpy (lvid->direct + x + ((y << repshift) + i + j) * + VGA_rowbytes, &pbitmap[(i >> repshift) * width], width); + } + } + } +} + + +/* +================ +VGA_EndDirectRect +================ +*/ +void +VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, + int y, int width, int height) +{ + int i, j, k, plane, reps, repshift; + + if (!lvid->direct) + return; + + if (lvid->aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + if (pcurrentmode->planar) { + for (plane = 0; plane < 4; plane++) { + // select the correct plane for writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 1 << plane); + + for (i = 0; i < (height << repshift); i += reps) { + for (k = 0; k < reps; k++) { + for (j = 0; j < (width >> 2); j++) { + lvid->direct[(y + i + k) * VGA_rowbytes + (x >> 2) + + j] = + backingbuf[(i + k) * 24 + (j << 2) + plane]; + } + } + } + } + } else { + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + memcpy (lvid->direct + x + ((y << repshift) + i + j) * + VGA_rowbytes, &backingbuf[(i + j) * 24], width); + } + } + } +} + + +/* +================ +VGA_Init +================ +*/ +void +VGA_Init (void) +{ + int i; + +// link together all the VGA modes + for (i = 0; i < (NUMVIDMODES - 1); i++) { + vgavidmodes[i].pnext = &vgavidmodes[i + 1]; + } + +// add the VGA modes at the start of the mode list + vgavidmodes[NUMVIDMODES - 1].pnext = pvidmodes; + pvidmodes = &vgavidmodes[0]; + + numvidmodes += NUMVIDMODES; +} + + +/* +================ +VGA_WaitVsync +================ +*/ +void +VGA_WaitVsync (void) +{ + while ((inportb (0x3DA) & 0x08) == 0); +} + + +/* +================ +VGA_ClearVideoMem +================ +*/ +void +VGA_ClearVideoMem (int planar) +{ + + if (planar) { + // enable all planes for writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 0x0F); + } + + Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height); +} + +/* +================ +VGA_FreeAndAllocVidbuffer +================ +*/ +qboolean +VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer) +{ + int tsize, tbuffersize; + + if (allocnewbuffer) { + // alloc an extra line in case we want to wrap, and allocate the + // z-buffer + tbuffersize = (lvid->rowbytes * (lvid->height + 1)) + + (lvid->width * lvid->height * sizeof (*d_pzbuffer)); + } else { + // just allocate the z-buffer + tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer); + } + + tsize = D_SurfaceCacheForRes (lvid->width, lvid->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_Printf ("Not enough memory for video mode\n"); + VGA_pcurmode = NULL; // so no further accesses to the + // buffer are + // attempted, particularly when clearing + return false; // not enough memory for mode + } + + VGA_buffersize = tbuffersize; + vid_surfcachesize = tsize; + + if (d_pzbuffer) { + D_FlushCaches (); + Hunk_FreeToHighMark (VGA_highhunkmark); + d_pzbuffer = NULL; + } + + VGA_highhunkmark = Hunk_HighMark (); + + d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video"); + + vid_surfcache = (byte *) d_pzbuffer + + lvid->width * lvid->height * sizeof (*d_pzbuffer); + + if (allocnewbuffer) { + lvid->buffer = (void *) ((byte *) vid_surfcache + vid_surfcachesize); + lvid->conbuffer = lvid->buffer; + } + + return true; +} + + +/* +================ +VGA_CheckAdequateMem +================ +*/ +qboolean +VGA_CheckAdequateMem (int width, int height, int rowbytes, int allocnewbuffer) +{ + int tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + if (allocnewbuffer) { + // alloc an extra line in case we want to wrap, and allocate the + // z-buffer + tbuffersize += (rowbytes * (height + 1)); + } + + 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; +} + + +/* +================ +VGA_InitMode +================ +*/ +int +VGA_InitMode (viddef_t *lvid, vmode_t * pcurrentmode) +{ + vextra_t *pextra; + + pextra = pcurrentmode->pextradata; + + if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer)) + return -1; // memory alloc failed + + if (VGA_pcurmode) + VGA_ClearVideoMem (VGA_pcurmode->planar); + +// mode 0x13 is the base for all the Mode X-class mode sets + regs.h.ah = 0; + regs.h.al = 0x13; + dos_int86 (0x10); + + VGA_pagebase = (void *) real2ptr (0xa0000); + lvid->direct = (pixel_t *) VGA_pagebase; + +// set additional registers as needed + VideoRegisterSet (pextra->pregset); + + VGA_numpages = 1; + lvid->numpages = VGA_numpages; + + VGA_width = (lvid->width + 0x1F) & ~0x1F; + VGA_height = lvid->height; + VGA_planar = pcurrentmode->planar; + if (VGA_planar) + VGA_rowbytes = lvid->rowbytes / 4; + else + VGA_rowbytes = lvid->rowbytes; + VGA_bufferrowbytes = lvid->rowbytes; + lvid->colormap = vid_colormap; + lvid->fullbright = 256 - LittleLong (*((int *) lvid->colormap + 2048)); + + lvid->maxwarpwidth = WARP_WIDTH; + lvid->maxwarpheight = WARP_HEIGHT; + + lvid->conbuffer = lvid->buffer; + lvid->conrowbytes = lvid->rowbytes; + lvid->conwidth = lvid->width; + lvid->conheight = lvid->height; + + VGA_pcurmode = pcurrentmode; + + VGA_ClearVideoMem (pcurrentmode->planar); + + if (_vid_wait_override->int_val) { + Cvar_SetValue (vid_wait, (float) VID_WAIT_VSYNC); + } else { + Cvar_SetValue (vid_wait, (float) VID_WAIT_NONE); + } + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + return 1; +} + + +/* +================ +VGA_SetPalette +================ +*/ +void +VGA_SetPalette (viddef_t *lvid, vmode_t * pcurrentmode, unsigned char *pal) +{ + int shiftcomponents = 2; + int i; + + UNUSED (lvid); + UNUSED (pcurrentmode); + + dos_outportb (0x3c8, 0); + for (i = 0; i < 768; i++) + outportb (0x3c9, pal[i] >> shiftcomponents); +} + + +/* +================ +VGA_SwapBuffersCopy +================ +*/ +void +VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t * pcurrentmode, vrect_t *rects) +{ + + UNUSED (pcurrentmode); + +// TODO: can write a dword at a time +// TODO: put in ASM +// TODO: copy only specified rectangles + if (VGA_planar) { + + // TODO: copy only specified rectangles + + VGA_UpdatePlanarScreen (lvid->buffer); + } else { + while (rects) { + VGA_UpdateLinearScreen (lvid->buffer + rects->x + + (rects->y * lvid->rowbytes), + VGA_pagebase + rects->x + + (rects->y * VGA_rowbytes), rects->width, + rects->height, lvid->rowbytes, + VGA_rowbytes); + + rects = rects->pnext; + } + } +} + + +/* +================ +VGA_SwapBuffers +================ +*/ +void +VGA_SwapBuffers (viddef_t *lvid, vmode_t * pcurrentmode, vrect_t *rects) +{ + UNUSED (lvid); + + if (vid_wait->int_val == VID_WAIT_VSYNC) + VGA_WaitVsync (); + + VGA_SwapBuffersCopy (lvid, pcurrentmode, rects); +} + + +void +VID_HandlePause (qboolean pause) +{ +} diff --git a/libs/video/targets/vid_wgl.c b/libs/video/targets/vid_wgl.c new file mode 100644 index 000000000..fa486b515 --- /dev/null +++ b/libs/video/targets/vid_wgl.c @@ -0,0 +1,1693 @@ +/* + vid_wgl.c + + Win32 WGL vid component + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" + +#include "QF/cdaudio.h" +#include "QF/cmd.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "draw.h" +#include "glquake.h" +#include "in_win.h" +#include "QF/keys.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "resource.h" +#include "sbar.h" +#include "screen.h" +#include "QF/sound.h" +#include "QF/sys.h" +#include "QF/va.h" + +extern void (*vid_menudrawfn) (void); +extern void (*vid_menukeyfn) (int); + +#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; + +// ARB Multitexture +qboolean gl_mtex_capable = false; +GLenum gl_mtex_enum = GL_TEXTURE0_ARB; + +// 8-bit and permedia support +QF_glColorTableEXT qglColorTableEXT = NULL; +qboolean is8bit = false; +qboolean isPermedia = false; + +// FIXME: Only used by MGL .. +qboolean DDActive; + +// If you ever merge screen/gl_screen, don't forget this one +qboolean scr_skipupdate; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; +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; +static HICON hIcon; + +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +HWND mainwindow; + +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 = true; + +HDC maindc; + +glvert_t glv; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); +LONG CDAudio_MessageHandler (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +extern void CL_ClearStates (); + +extern viddef_t vid; // global video state + +unsigned short d_8to16table[256]; +unsigned int d_8to24table[256]; +unsigned char d_15to8table[65536]; + +float gldepthmin, gldepthmax; + +modestate_t modestate = MS_UNINIT; + +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); + +//==================================== + +cvar_t *_windowed_mouse; +cvar_t *vid_use8bit; + + +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) +{ + 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; + + window_width = modelist[modenum].width; + window_height = modelist[modenum].height; + + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + rect = WindowRect; + AdjustWindowRect (&rect, WindowStyle, FALSE); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + // Create the window + mainwindow = CreateWindow ("QuakeForge", "GLQuakeWorld", + WindowStyle, rect.left, rect.top, width, height, NULL, NULL, + global_hInstance, NULL); + + if (!mainwindow) + Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); + +// Center and show the window + CenterWindow (mainwindow, WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, false); + + ShowWindow (mainwindow, SW_SHOWDEFAULT); + UpdateWindow (mainwindow); + + 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 (mainwindow); + PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); + ReleaseDC (mainwindow, 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; + + if(hIcon) { + 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; + + memset(&gdevmode,0,sizeof(gdevmode)); + + 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 (%lx)\r\n",GetLastError()); + } + + lastmodestate = modestate; + modestate = MS_FULLDIB; + + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + + + window_width = modelist[modenum].width; + window_height = modelist[modenum].height; + +// FIXME: some drivers have broken FS popup window handling +// until I find way around it, or find some other cause for it +// this is way to avoid it + + if (COM_CheckParm ("-brokenpopup")) WindowStyle = 0; + else WindowStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + rect = WindowRect; + AdjustWindowRect (&rect, WindowStyle, FALSE); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + // Create the DIB window + mainwindow = CreateWindow ("QuakeForge", "GLQuakeWorld", + WindowStyle, rect.left, rect.top, width, height, NULL, NULL, + global_hInstance, NULL); + + if (!mainwindow) + Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); + + 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); + + 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; + + if (hIcon) { + 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 = 0; + MSG msg; + + 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->int_val && 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"); + } + + 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; + + 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_Printf ("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 (); +} + +int texture_extension_number = 1; + +void +CheckMultiTextureExtensions (void) +{ + Con_Printf ("Checking for multitexture... "); + if (COM_CheckParm ("-nomtex")) { + Con_Printf ("disabled.\n"); + return; + } + + if (QFGL_ExtensionPresent ("GL_ARB_multitexture")) { + + int max_texture_units = 0; + + glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &max_texture_units); + if (max_texture_units >= 2) { + Con_Printf ("enabled, %d TMUs.\n", max_texture_units); + qglMultiTexCoord2f = QFGL_ExtensionAddress ("glMultiTexCoord2fARB"); + qglActiveTexture = QFGL_ExtensionAddress ("glActiveTextureARB"); + gl_mtex_enum = GL_TEXTURE0_ARB; + gl_mtex_capable = true; + } else { + Con_Printf ("disabled, not enough TMUs.\n"); + } + } else { + Con_Printf ("not found.\n"); + } +} + +/* + 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; + + CheckMultiTextureExtensions (); + + glClearColor (0, 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); + + glEnable (GL_BLEND); + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + +} + +/* + GL_BeginRendering +*/ +void +GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + *x = *y = 0; + *width = WindowRect.right - WindowRect.left; + *height = WindowRect.bottom - WindowRect.top; +} + +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->int_val) { + 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 int r, g, b; + unsigned int v; + int r1, g1, b1; + int k; + unsigned short i; + unsigned int *table; + QFile *f; + char s[255]; + float dist, bestdist; + static qboolean palflag = false; + +// +// 8 8 8 encoding +// +// Con_Printf("Converting 8to24\n"); + + 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] &= 0; // 255 is transparent + + // JACK: 3D distance calcs - k is last closest, l is the distance. + + if (palflag) + return; + palflag = true; + + COM_FOpenFile ("glquake/15to8.pal", &f); + if (f) { + Qread (f, d_15to8table, 1 << 15); + Qclose (f); + } else { + 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, bestdist = 10000.0; v < 256; v++, pal += 4) { + r1 = (int) r - (int) pal[0]; + g1 = (int) g - (int) pal[1]; + b1 = (int) b - (int) pal[2]; + dist = sqrt (((r1 * r1) + (g1 * g1) + (b1 * b1))); + if (dist < bestdist) { + k = v; + bestdist = dist; + } + } + d_15to8table[i] = k; + } + snprintf (s, sizeof (s), "%s/glquake/15to8.pal", com_gamedir); + COM_CreatePath (s); + if ((f = Qopen (s, "wb")) != NULL) { + Qwrite (f, d_15to8table, 1 << 15); + Qclose (f); + } + } +} + +void +VID_ShiftPalette (unsigned char *palette) +{ +} + +void +VID_SetDefaultMode (void) +{ + IN_DeactivateMouse (); +} + + +void +VID_Shutdown (void) +{ + HGLRC hRC; + HDC hDC; + int i, temp[8192]; + +#ifdef SPLASH_SCREEN + if(hwnd_dialog) + DestroyWindow (hwnd_dialog); +#endif + + if (vid_initialized) { + vid_canalttab = false; + hRC = wglGetCurrentContext (); + hDC = wglGetCurrentDC (); + + wglMakeCurrent (NULL, NULL); + + // LordHavoc: free textures before closing (may help NVIDIA) + for (i = 0; i < 8192; i++) + temp[i] = i + 1; + glDeleteTextures (8192, temp); + + if (hRC) + wglDeleteContext (hRC); + + if (hDC && mainwindow) + ReleaseDC (mainwindow, hDC); + + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, 0); + + if (maindc && mainwindow) + ReleaseDC (mainwindow, maindc); + + AppActivate (false, false); + } +} + + +//========================================================================== + +BOOL +bSetupPixelFormat (HDC hDC) +{ + PIXELFORMATDESCRIPTOR pfd ; + int pixelformat; + + memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pfd.iPixelType = PFD_TYPE_RGBA; + + if (!modelist[vid_default].bpp) pfd.cColorBits = 16; + else pfd.cColorBits = modelist[vid_default].bpp; + + pfd.cDepthBits = 32; + pfd.iLayerType = PFD_MAIN_PLANE; + + if ((pixelformat = ChoosePixelFormat (hDC, &pfd)) == 0) { + MessageBox (NULL, "ChoosePixelFormat failed", "Error", MB_OK); + return FALSE; + } + + if (SetPixelFormat (hDC, pixelformat, &pfd) == FALSE) { + MessageBox (NULL, "SetPixelFormat failed", "Error", MB_OK); + return FALSE; + } + return TRUE; +} + + +//========================================================================== + +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, KP_MULTIPLY, + K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCRLCK, KP_HOME, + KP_UPARROW, KP_PGUP, KP_MINUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_PLUS, KP_END, // 4 + KP_DOWNARROW, KP_PGDN, KP_INS, KP_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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +byte extscantokey[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', '[', ']', KP_ENTER, K_CTRL, 'a', 's', // 1 + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2 + 'b', 'n', 'm', ',', '.', KP_DIVIDE, K_SHIFT, '*', + K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLCK, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* + MapKey + + Map from windows to quake keynums +*/ +int +MapKey (int key) +{ + int extended; + + extended = (key >> 24) & 1; + + key = (key >> 16) & 255; + if (key > 127) + return 0; + + if (extended) + return extscantokey[key]; + else + return scantokey[key]; +} + + +/* + MAIN WINDOW +*/ + + +/* + ClearAllStates +*/ +void +ClearAllStates (void) +{ + CL_ClearStates (); + 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. +* +****************************************************************************/ +{ + 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; + + if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != + DISP_CHANGE_SUCCESSFUL) { + IN_ShowMouse (); + Sys_Error ("Couldn't set fullscreen DIB mode\n(try upgrading your video drivers)\r\n (%lx)",GetLastError()); + } + ShowWindow (mainwindow, SW_SHOWNORMAL); + + // Fix for alt-tab bug in NVidia drivers + MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false); + } + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val + && key_dest == key_game) { + IN_ActivateMouse (); + IN_HideMouse (); + } + + } else { + if (modestate == MS_FULLDIB) { + IN_DeactivateMouse (); + IN_ShowMouse (); + if (vid_canalttab) { + ChangeDisplaySettings (NULL, 0); + vid_wassuspended = true; + } + } else if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } +} + + +/* main window procedure */ +LONG WINAPI +MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LONG lRet = 1; + int 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), -1, true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + Key_Event (MapKey (lParam), -1, 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, -1, true); + Key_Event (K_MWHEELUP, -1, false); + } else { + Key_Event (K_MWHEELDOWN, -1, true); + Key_Event (K_MWHEELDOWN, -1, 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 (mainwindow) + DestroyWindow (mainwindow); + 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 { + snprintf (temp, sizeof (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) { + snprintf (pinfo, sizeof (pinfo), "%s fullscreen", pv->modedesc); + } else { + snprintf (pinfo, sizeof (pinfo), "Desktop resolution (%dx%d)", + modelist[MODE_FULLSCREEN_DEFAULT].width, + modelist[MODE_FULLSCREEN_DEFAULT].height); + } + } else { + if (modestate == MS_WINDOWED) + snprintf (pinfo, sizeof (pinfo), "%s windowed", pv->modedesc); + else + snprintf (pinfo, sizeof (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 = 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; i < lnummodes; i++) { + pv = VID_GetModePtr (i); + pinfo = VID_GetExtModeDescription (i); + Con_Printf ("%2d: %s\n", i, pinfo); + } + + leavecurrentmode = t; +} + + +void +VID_InitDIB (HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* 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 = "QuakeForge"; + + if (!RegisterClass (&wc)) + Sys_Error ("Couldn't register window class (%lx)\r\n",GetLastError()); + + modelist[0].type = MS_WINDOWED; + + if (COM_CheckParm ("-width")) + modelist[0].width = atoi (com_argv[COM_CheckParm ("-width") + 1]); + else + modelist[0].width = 640; + + if (modelist[0].width < 320) + modelist[0].width = 320; + + if (COM_CheckParm ("-height")) + modelist[0].height = atoi (com_argv[COM_CheckParm ("-height") + 1]); + else + modelist[0].height = modelist[0].width * 240 / 320; + + if (modelist[0].height < 240) + modelist[0].height = 240; + + snprintf (modelist[0].modedesc, sizeof (modelist[0].modedesc), "%dx%d", + modelist[0].width, modelist[0].height); + + modelist[0].modenum = MODE_WINDOWED; + modelist[0].dib = 1; + modelist[0].fullscreen = 0; + modelist[0].halfscreen = 0; + modelist[0].bpp = 0; + + nummodes = 1; +} + + +/* + VID_InitFullDIB +*/ +void +VID_InitFullDIB (HINSTANCE hInstance) +{ + DEVMODE devmode; + int i, modenum, originalnummodes, existingmode, numlowresmodes; + int j, bpp, done; + BOOL stat; + +// enumerate >8 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; + snprintf (modelist[nummodes].modedesc, + sizeof (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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), + "%dx%dx%d", modelist[nummodes].width, + modelist[nummodes].height, + modelist[nummodes].bpp); + } + } + + for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) && + (modelist[nummodes].height == modelist[i].height) && + (modelist[nummodes].bpp == modelist[i].bpp)) { + existingmode = 1; + break; + } + } + + if (!existingmode) { + nummodes++; + } + } + } + + modenum++; + } while (stat); + +// see if there are any low-res modes that aren't being reported + numlowresmodes = sizeof (lowresmodes) / sizeof (lowresmodes[0]); + bpp = 16; + done = 0; + + do { + for (j = 0; (j < numlowresmodes) && (nummodes < MAX_MODE_LIST); j++) { + devmode.dmBitsPerPel = bpp; + devmode.dmPelsWidth = lowresmodes[j].width; + devmode.dmPelsHeight = lowresmodes[j].height; + 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%dx%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight, + devmode.dmBitsPerPel); + + for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) && + (modelist[nummodes].height == modelist[i].height) && + (modelist[nummodes].bpp == modelist[i].bpp)) { + existingmode = 1; + break; + } + } + + if (!existingmode) { + nummodes++; + } + } + } + switch (bpp) { + case 16: + bpp = 32; + break; + + case 32: + bpp = 24; + break; + + case 24: + done = 1; + break; + } + } while (!done); + + if (nummodes == originalnummodes) + Con_Printf ("No fullscreen DIB modes found\n"); +} + +qboolean +VID_Is8bit () +{ + return is8bit; +} + +void +VID_Init8bitPalette (void) +{ + int i; + GLubyte thePalette[256 * 3]; + GLubyte *oldPalette, *newPalette; + + vid_use8bit = + Cvar_Get ("vid_use8bit", "0", CVAR_ROM, NULL, + "Use 8-bit shared palettes."); + + if (!vid_use8bit->int_val) return; + + if (is8bit) { // already done... + return; + } + + if (QFGL_ExtensionPresent ("GL_EXT_shared_texture_palette")) { + if (!(qglColorTableEXT = QFGL_ExtensionAddress ("glColorTableEXT"))) { + return; + } + + Con_Printf ("8-bit GL extension enabled.\n"); + + glEnable (GL_SHARED_TEXTURE_PALETTE_EXT); + oldPalette = (GLubyte *) d_8to24table; // d_8to24table3dfx; + newPalette = thePalette; + for (i = 0; i < 256; i++) { + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + oldPalette++; + } + qglColorTableEXT (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, + GL_UNSIGNED_BYTE, (GLvoid *) thePalette); + is8bit = true; + } +} + +/* + VID_Init +*/ +void +VID_Init (unsigned char *palette) +{ + int i, existingmode; + int basenummodes, width, height=480, bpp, findbpp, done; + char gldir[MAX_OSPATH]; + HDC hdc; + DEVMODE devmode; + HGLRC baseRC; + DWORD lasterror; + + memset (&devmode, 0, sizeof (devmode)); + + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available"); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, "Report current video mode."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" + "(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); + + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); + +// FIXME: If you put these back, remember commctrl.h +// 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 = 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 = atoi (com_argv[COM_CheckParm ("-width") + 1]); + } else { + width = 640; + } + + if (COM_CheckParm ("-bpp")) { + bpp = atoi (com_argv[COM_CheckParm ("-bpp") + 1]); + findbpp = 0; + } else { + bpp = 15; + findbpp = 1; + } + + if (COM_CheckParm ("-height")) + height = 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; + snprintf (modelist[nummodes].modedesc, + sizeof (modelist[nummodes].modedesc), "%dx%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight, + devmode.dmBitsPerPel); + + for (i = nummodes, existingmode = 0; i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) && + (modelist[nummodes].height == modelist[i].height) && + (modelist[nummodes].bpp == modelist[i].bpp)) { + existingmode = 1; + break; + } + } + + if (!existingmode) { + nummodes++; + } + } + + done = 0; + + do { + if (COM_CheckParm ("-height")) { + height = atoi (com_argv[COM_CheckParm ("-height") + 1]); + + for (i = 1, vid_default = 0; i < nummodes; i++) { + if ((modelist[i].width == width) && + (modelist[i].height == height) && + (modelist[i].bpp == bpp)) { + vid_default = i; + done = 1; + break; + } + } + } else { + for (i = 1, vid_default = 0; i < nummodes; i++) { + if ((modelist[i].width == width) + && (modelist[i].bpp == bpp)) { + vid_default = i; + done = 1; + break; + } + } + } + + if (!done) { + if (findbpp) { + switch (bpp) { + case 15: + bpp = 16; + break; + case 16: + bpp = 32; + break; + case 32: + bpp = 24; + break; + case 24: + done = 1; + break; + } + } else { + done = 1; + } + } + } while (!done); + + if (!vid_default) { + Sys_Error ("Specified video mode not available"); + } + } + } + } + + vid_initialized = true; + + if ((i = COM_CheckParm ("-conwidth")) != 0) + vid.conwidth = atoi (com_argv[i + 1]); + else + vid.conwidth = 640; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + + if (vid.conwidth < 320) + vid.conwidth = 320; + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth * 3 / 4; + + if ((i = COM_CheckParm ("-conheight")) != 0) + vid.conheight = atoi (com_argv[i + 1]); + if (vid.conheight < 200) + vid.conheight = 200; + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + +#ifdef SPLASH_SCREEN + if(hwnd_dialog) + DestroyWindow (hwnd_dialog); +#endif + + GL_CheckBrightness (palette); + VID_SetPalette (palette); + + VID_SetMode (vid_default, palette); + + maindc = GetDC (mainwindow); + bSetupPixelFormat (maindc); + + baseRC = wglCreateContext (maindc); + if (!baseRC) { + lasterror=GetLastError(); + if (maindc && mainwindow) + ReleaseDC (mainwindow, maindc); + Sys_Error("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window. \nError code: (%lx)\r\n",lasterror); + } + + if (!wglMakeCurrent (maindc, baseRC)) { + lasterror=GetLastError(); + if (baseRC) + wglDeleteContext (baseRC); + if (maindc && mainwindow) + ReleaseDC (mainwindow, maindc); + Sys_Error ("wglMakeCurrent failed (%lx)\r\n",lasterror); + } + + GL_Init (); + + snprintf (gldir, sizeof (gldir), "%s/glquake", com_gamedir); + Sys_mkdir (gldir); + + vid_realmode = vid_modenum; + + // Check for 3DFX Extensions and initialize them. + VID_Init8bitPalette (); + + strcpy (badmode.modedesc, "Bad mode"); + vid_canalttab = true; + + if (COM_CheckParm ("-nofullsbar")) + fullsbardraw = false; +} + +void +VID_Init_Cvars () +{ + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, + "Grab the mouse from X while playing quake"); +} + + +//======================================================== +// Video menu stuff +//======================================================== + +typedef struct { + int modenum; + char *desc; + int iscur; +} modedesc_t; + +#define MAX_COLUMN_SIZE 9 +#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 2) +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +//static modedesc_t modedescs[MAX_MODEDESCS]; + + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + SetWindowText (mainwindow, + (LPSTR) va ("%s %s: %s", PROGRAM, VERSION, temp)); + free (temp); + } else { + SetWindowText (mainwindow, (LPSTR) va ("%s %s", PROGRAM, VERSION)); + } +} diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c new file mode 100644 index 000000000..4d069154e --- /dev/null +++ b/libs/video/targets/vid_win.c @@ -0,0 +1,50 @@ +/* + vid_win.c + + windows video driver functions + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/vid.h" + +extern HWND mainwindow; + +void +VID_RaiseWindow (void) +{ + ShowWindow (mainwindow, SW_RESTORE); + SetForegroundWindow (mainwindow); +} + +void +VID_MinimiseWindow (void) +{ + SendMessage (mainwindow, WM_SYSKEYUP, VK_TAB, 1 | (0x0F << 16) | (1 << 29)); +} diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c new file mode 100644 index 000000000..b4c852edc --- /dev/null +++ b/libs/video/targets/vid_x11.c @@ -0,0 +1,797 @@ +/* + vid_x11.c + + General X11 video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#define _BSD + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_VIDMODE +# include +#endif + +#include "QF/cmd.h" +#include "QF/compat.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "client.h" +#include "context_x11.h" +#include "d_local.h" +#include "dga_check.h" +#include "draw.h" +#include "screen.h" + +extern viddef_t vid; // global video state +unsigned short d_8to16table[256]; + +static Colormap x_cmap; +static GC x_gc; + +int XShmQueryExtension (Display *); +int XShmGetEventBase (Display *); + +static qboolean doShm; +static XShmSegmentInfo x_shminfo[2]; + +static int current_framebuffer; +static XImage *x_framebuffer[2] = { 0, 0 }; + +static int verbose = 0; + +int VID_options_items = 1; + +static byte current_palette[768]; + +typedef unsigned short PIXEL16; +typedef unsigned long PIXEL24; + +static PIXEL16 st2d_8to16table[256]; +static PIXEL24 st2d_8to24table[256]; +static int shiftmask_fl = 0; +static long r_shift, g_shift, b_shift; +static unsigned long r_mask, g_mask, b_mask; + +cvar_t *vid_width; +cvar_t *vid_height; + +static void +shiftmask_init (void) +{ + 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; x < r_mask; x <<= 1) + r_shift++; + for (g_shift = -8, x = 1; x < g_mask; x <<= 1) + g_shift++; + for (b_shift = -8, x = 1; x < b_mask; x <<= 1) + b_shift++; + shiftmask_fl = 1; +} + +static PIXEL16 +xlib_rgb16 (int r, int g, int b) +{ + PIXEL16 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + 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; +} + + +static PIXEL24 +xlib_rgb24 (int r, int g, int b) +{ + PIXEL24 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + 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; +} + +static void +st2_fixup (XImage *framebuf, int x, int y, int width, int height) +{ + int xi, yi; + unsigned char *src; + PIXEL16 *dest; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &framebuf->data[yi * framebuf->bytes_per_line]; + dest = (PIXEL16 *) src; + for (xi = (x + width - 1); xi >= x; xi--) { + dest[xi] = st2d_8to16table[src[xi]]; + } + } +} + + +static void +st3_fixup (XImage * framebuf, int x, int y, int width, int height) +{ + int yi; + unsigned char *src; + PIXEL24 *dest; + register int count, n; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &framebuf->data[yi * framebuf->bytes_per_line]; + + // Duff's Device + count = width; + n = (count + 7) / 8; + dest = ((PIXEL24 *) src) + x + width - 1; + src += x + width - 1; + + switch (count % 8) { + case 0: + do { + *dest-- = st2d_8to24table[*src--]; + case 7: + *dest-- = st2d_8to24table[*src--]; + case 6: + *dest-- = st2d_8to24table[*src--]; + case 5: + *dest-- = st2d_8to24table[*src--]; + case 4: + *dest-- = st2d_8to24table[*src--]; + case 3: + *dest-- = st2d_8to24table[*src--]; + case 2: + *dest-- = st2d_8to24table[*src--]; + case 1: + *dest-- = st2d_8to24table[*src--]; + } while (--n > 0); + } + +// for(xi = (x+width-1); xi >= x; xi--) { +// dest[xi] = st2d_8to16table[src[xi]]; +// } + } +} + +/* + D_BeginDirectRect +*/ +void +D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported +} + + +/* + D_EndDirectRect +*/ +void +D_EndDirectRect (int x, int y, int width, int height) +{ +// direct drawing of the "accessing disk" icon isn't supported +} + + +static void +ResetFrameBuffer (void) +{ + int tbuffersize, tcachesize; + + void *vid_surfcache; + int mem, pwidth; + + // Calculate the sizes we want first + tbuffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + tcachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + if (x_framebuffer[0]) { + XDestroyImage (x_framebuffer[0]); + } + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new z-buffer + d_pzbuffer = calloc (tbuffersize, 1); + if (!d_pzbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (tcachesize, 1); + if (!vid_surfcache) { + free (d_pzbuffer); + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + + D_InitCaches (vid_surfcache, tcachesize); + + 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"); + } +} + +static void +ResetSharedFrameBuffers (void) +{ + int tbuffersize, tcachesize; + void *vid_surfcache; + + int size; + int key; + int minsize = getpagesize (); + int frm; + + // Calculate the sizes we want first + tbuffersize = vid.width * vid.height * sizeof (*d_pzbuffer); + tcachesize = D_SurfaceCacheForRes (vid.width, vid.height); + + // Free the old z-buffer + if (d_pzbuffer) { + free (d_pzbuffer); + d_pzbuffer = NULL; + } + // Free the old surface cache + vid_surfcache = D_SurfaceCacheAddress (); + if (vid_surfcache) { + D_FlushCaches (); + free (vid_surfcache); + vid_surfcache = NULL; + } + // Allocate the new z-buffer + d_pzbuffer = calloc (tbuffersize, 1); + if (!d_pzbuffer) { + Sys_Error ("Not enough memory for video mode\n"); + } + // Allocate the new surface cache; free the z-buffer if we fail + vid_surfcache = calloc (tcachesize, 1); + if (!vid_surfcache) { + free (d_pzbuffer); + d_pzbuffer = NULL; + Sys_Error ("Not enough memory for video mode\n"); + } + + D_InitCaches (vid_surfcache, tcachesize); + + 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); + + } + +} + +static void +event_shm (XEvent * event) +{ + if (doShm) + oktodraw = true; +} + +/* + VID_Init + + Set up color translation tables and the window. Takes a 256-color 8-bit + palette. Palette data will go away after the call, so copy it if you'll + need it later. +*/ +void +VID_Init (unsigned char *palette) +{ + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + VID_GetWindowSize (320, 200); + + vid.width = vid_width->int_val; + vid.height = vid_height->int_val; + Con_CheckResize (); // Now that we have a window size, fix console + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.numpages = 2; + vid.colormap = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + + srandom (getpid ()); + + verbose = COM_CheckParm ("-verbose"); + + // open the display + X11_OpenDisplay (); + + template_mask = 0; + + // specify a visual id + if ((pnum = COM_CheckParm ("-visualid"))) { + if (pnum >= com_argc - 1) + Sys_Error ("VID: -visualid \n"); + template.visualid = atoi (com_argv[pnum + 1]); + template_mask = VisualIDMask; + } else { // If not specified, use default + // visual + template.visualid = + XVisualIDFromVisual (XDefaultVisual (x_disp, x_screen)); + template_mask = VisualIDMask; + } + + // pick a visual -- warn if more than one was available + x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, &num_visuals); + x_vis = x_visinfo->visual; + + if (num_visuals > 1) { + printf ("Found more than one visual id at depth %d:\n", template.depth); + for (i = 0; i < num_visuals; i++) + printf (" -visualid %d\n", (int) x_visinfo[i].visualid); + } else { + if (num_visuals == 0) { + if (template_mask == VisualIDMask) { + Sys_Error ("VID: Bad visual ID %ld\n", template.visualid); + } else { + Sys_Error ("VID: No visuals at depth %d\n", template.depth); + } + } + } + + if (verbose) { + printf ("Using visualid %d:\n", (int) x_visinfo->visualid); + printf (" class %d\n", x_visinfo->class); + printf (" screen %d\n", x_visinfo->screen); + printf (" depth %d\n", x_visinfo->depth); + 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); + } + + /* Setup attributes for main window */ + X11_SetVidMode (vid.width, vid.height); + + /* Create the main window */ + X11_CreateWindow (vid.width, vid.height); + + /* Invisible cursor */ + X11_CreateNullCursor (); + + VID_InitGamma (palette); + VID_SetPalette (palette); + 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); + } + } + // create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC (x_disp, x_win, valuemask, &xgcvalues); + } + + X11_GrabKeyboard (); + + // 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; + char *d; + + doShm = true; + + if ((displayname = XDisplayName (NULL))) { + if ((d = strchr (displayname, ':'))) + *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); + X11_AddEvent (x_shmeventtype, event_shm); +} + +void +VID_Init_Cvars () +{ + X11_Init_Cvars (); +} + + +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_rgb16 (palette[i * 3], palette[i * 3 + 1], + palette[i * 3 + 2]); + st2d_8to24table[i] = xlib_rgb24 (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 = gammatable[(byte) palette[(i * 3)]]; + colors[i].green = gammatable[(byte) palette[(i * 3) + 1]]; + colors[i].blue = gammatable[(byte) palette[(i * 3) + 2]]; + } + XStoreColors (x_disp, x_cmap, colors, 256); + } +} + + +/* + VID_Shutdown + + Restore video mode +*/ +void +VID_Shutdown (void) +{ + Sys_Printf ("VID_Shutdown\n"); + if (x_disp) { + X11_RestoreVidMode (); + X11_CloseDisplay (); + } +} + +static int config_notify = 0; +static int config_notify_width; +static int config_notify_height; + +/* + VID_Update + + Flush the given rectangles from the view buffer to the screen. +*/ +void +VID_Update (vrect_t *rects) +{ + /* If the window changes dimension, skip this frame. */ + if (config_notify) { + fprintf (stderr, "config notify\n"); + config_notify = 0; + vid.width = config_notify_width & ~7; + vid.height = config_notify_height; + + if (doShm) + ResetSharedFrameBuffers (); + else + ResetFrameBuffer (); + + vid.rowbytes = x_framebuffer[0]->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; + } + + while (rects) { + switch (x_visinfo->depth) { + case 16: + st2_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + case 24: + st3_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + } + if (doShm) { + 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) + X11_ProcessEvent (); + rects = rects->pnext; + + current_framebuffer = !current_framebuffer; + vid.buffer = x_framebuffer[current_framebuffer]->data; + vid.conbuffer = vid.buffer; + } else { + if (!XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed\n"); + } + rects = rects->pnext; + } + } + XSync (x_disp, False); + scr_fullupdate = 0; +} + +static qboolean dither; + +void +VID_DitherOn (void) +{ + if (!dither) { + vid.recalc_refdef = 1; + dither = true; + } +} + + +void +VID_DitherOff (void) +{ + if (dither) { + vid.recalc_refdef = 1; + dither = false; + } +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + X11_SetCaption (va ("%s %s: %s", PROGRAM, VERSION, temp)); + free (temp); + } else { + X11_SetCaption (va ("%s %s", PROGRAM, VERSION)); + } +} + +double +VID_GetGamma (void) +{ + return (double) X11_GetGamma (); +} + +qboolean +VID_SetGamma (double gamma) +{ + return X11_SetGamma (gamma); +} diff --git a/nq/include/asm_draw.h b/nq/include/asm_draw.h deleted file mode 100644 index fdc523a50..000000000 --- a/nq/include/asm_draw.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - asm_draw.h - - @description@ - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -// -// !!! note that this file must match the corresponding C structures at all -// times !!! -// - -// !!! if this is changed, it must be changed in r_local.h too !!! -#define NEAR_CLIP 0.01 - -// !!! if this is changed, it must be changed in r_local.h too !!! -#define CYCLE 128 - -// espan_t structure -// !!! if this is changed, it must be changed in r_shared.h too !!! -#define espan_t_u 0 -#define espan_t_v 4 -#define espan_t_count 8 -#define espan_t_pnext 12 -#define espan_t_size 16 - -// sspan_t structure -// !!! if this is changed, it must be changed in d_local.h too !!! -#define sspan_t_u 0 -#define sspan_t_v 4 -#define sspan_t_count 8 -#define sspan_t_size 12 - -// spanpackage_t structure -// !!! if this is changed, it must be changed in d_polyset.c too !!! -#define spanpackage_t_pdest 0 -#define spanpackage_t_pz 4 -#define spanpackage_t_count 8 -#define spanpackage_t_ptex 12 -#define spanpackage_t_sfrac 16 -#define spanpackage_t_tfrac 20 -#define spanpackage_t_light 24 -#define spanpackage_t_zi 28 -#define spanpackage_t_size 32 - -// edge_t structure -// !!! if this is changed, it must be changed in r_shared.h too !!! -#define et_u 0 -#define et_u_step 4 -#define et_prev 8 -#define et_next 12 -#define et_surfs 16 -#define et_nextremove 20 -#define et_nearzi 24 -#define et_owner 28 -#define et_size 32 - -// surf_t structure -// !!! if this is changed, it must be changed in r_shared.h too !!! -#define SURF_T_SHIFT 6 -#define st_next 0 -#define st_prev 4 -#define st_spans 8 -#define st_key 12 -#define st_last_u 16 -#define st_spanstate 20 -#define st_flags 24 -#define st_data 28 -#define st_entity 32 -#define st_nearzi 36 -#define st_insubmodel 40 -#define st_d_ziorigin 44 -#define st_d_zistepu 48 -#define st_d_zistepv 52 -#define st_pad 56 -#define st_size 64 - -// clipplane_t structure -// !!! if this is changed, it must be changed in r_local.h too !!! -#define cp_normal 0 -#define cp_dist 12 -#define cp_next 16 -#define cp_leftedge 20 -#define cp_rightedge 21 -#define cp_reserved 22 -#define cp_size 24 - -// medge_t structure -// !!! if this is changed, it must be changed in model.h too !!! -#define me_v 0 -#define me_cachededgeoffset 4 -#define me_size 8 - -// mvertex_t structure -// !!! if this is changed, it must be changed in model.h too !!! -#define mv_position 0 -#define mv_size 12 - -// refdef_t structure -// !!! if this is changed, it must be changed in render.h too !!! -#define rd_vrect 0 -#define rd_aliasvrect 20 -#define rd_vrectright 40 -#define rd_vrectbottom 44 -#define rd_aliasvrectright 48 -#define rd_aliasvrectbottom 52 -#define rd_vrectrightedge 56 -#define rd_fvrectx 60 -#define rd_fvrecty 64 -#define rd_fvrectx_adj 68 -#define rd_fvrecty_adj 72 -#define rd_vrect_x_adj_shift20 76 -#define rd_vrectright_adj_shift20 80 -#define rd_fvrectright_adj 84 -#define rd_fvrectbottom_adj 88 -#define rd_fvrectright 92 -#define rd_fvrectbottom 96 -#define rd_horizontalFieldOfView 100 -#define rd_xOrigin 104 -#define rd_yOrigin 108 -#define rd_vieworg 112 -#define rd_viewangles 124 -#define rd_ambientlight 136 -#define rd_size 140 - -// mtriangle_t structure -// !!! if this is changed, it must be changed in model.h too !!! -#define mtri_facesfront 0 -#define mtri_vertindex 4 -#define mtri_size 16 // !!! if this changes, array indexing in !!! - // !!! d_polysa.s must be changed to match !!! -#define mtri_shift 4 - diff --git a/nq/include/context_x11.h b/nq/include/context_x11.h deleted file mode 100644 index f8c248045..000000000 --- a/nq/include/context_x11.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - context_x11.h - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - Copyright (C) 1999,2000 contributors of the QuakeForge project - Please see the file "AUTHORS" for a list of contributors - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef __CONTEXT_X11_H__ -#define __CONTEXT_X11_H__ - -#include -#include - -#include "QF/cvar.h" -#include "QF/qtypes.h" - -void GetEvent( void ); - -extern Display *x_disp; -extern int x_screen; -extern Window x_root; -extern XVisualInfo *x_visinfo; -extern Visual *x_vis; -extern Window x_win; -extern qboolean doShm; -extern int x_shmeventtype; -extern qboolean oktodraw; -extern cvar_t *vid_fullscreen; - -qboolean x11_add_event (int event, void (*event_handler)(XEvent *)); -qboolean x11_del_event (int event, void (*event_handler)(XEvent *)); -void x11_process_event (void); -void x11_process_events (void); -void x11_open_display (void); -void x11_close_display (void); -void x11_create_null_cursor (void); -void x11_set_vidmode (int, int); -void x11_restore_vidmode (void); -void x11_create_window (int, int); -void x11_grab_keyboard (void); -void x11_set_caption (char *); -void x11_force_view_port (void); -void x11_Init_Cvars (void); - -#endif // __CONTEXT_X11_H__ diff --git a/nq/include/d_local.h b/nq/include/d_local.h deleted file mode 100644 index 7f39d66a4..000000000 --- a/nq/include/d_local.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - d_local.h - - @description@ - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - - -#include "r_shared.h" - -// -// TODO: fine-tune this; it's based on providing some overage even if there -// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each -// -#define SCANBUFFERPAD 0x1000 - -#define R_SKY_SMASK 0x007F0000 -#define R_SKY_TMASK 0x007F0000 - -#define DS_SPAN_LIST_END -128 - -#define SURFCACHE_SIZE_AT_320X200 600*1024 - -typedef struct surfcache_s -{ - struct surfcache_s *next; - struct surfcache_s **owner; // NULL is an empty chunk of memory - int lightadj[MAXLIGHTMAPS]; // checked for strobe flush - int dlight; - int size; // including header - unsigned width; - unsigned height; // DEBUG only needed for debug - float mipscale; - struct texture_s *texture; // checked for animating textures - byte data[4]; // width*height elements -} surfcache_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct sspan_s -{ - int u, v, count; -} sspan_t; - -extern cvar_t *d_subdiv16; - -extern float scale_for_mip; - -extern qboolean d_roverwrapped; -extern surfcache_t *sc_rover; -extern surfcache_t *d_initial_rover; - -extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; -extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; -extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; - -fixed16_t sadjust, tadjust; -fixed16_t bbextents, bbextentt; - - -void D_DrawSpans8 (espan_t *pspans); -void D_DrawSpans16 (espan_t *pspans); -void D_DrawZSpans (espan_t *pspans); -void Turbulent8 (espan_t *pspan); -void D_SpriteDrawSpans (sspan_t *pspan); - -void D_DrawSkyScans8 (espan_t *pspan); -void D_DrawSkyScans16 (espan_t *pspan); - -void R_ShowSubDiv (void); -void (*prealspandrawer)(void); -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); - -extern int D_MipLevelForScale (float scale); - -#ifdef USE_INTEL_ASM -extern void D_PolysetAff8Start (void); -extern void D_PolysetAff8End (void); -#endif - -extern short *d_pzbuffer; -extern unsigned int d_zrowbytes, d_zwidth; - -extern int *d_pscantable; -extern int d_scantable[MAXHEIGHT]; - -extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; - -extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; - -extern pixel_t *d_viewbuffer; - -extern short *zspantable[MAXHEIGHT]; - -extern int d_minmip; -extern float d_scalemip[3]; - -extern void (*d_drawspans) (espan_t *pspan); - diff --git a/nq/include/quakeasm.h b/nq/include/quakeasm.h deleted file mode 100644 index 87132b01b..000000000 --- a/nq/include/quakeasm.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - quakeasm.h - - general asm header file - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef _QUAKEASM_H_ -#define _QUAKEASM_H_ - -// !!! must be kept the same as in d_iface.h !!! -#define TRANSPARENT_COLOR 255 - - .extern C(d_zistepu) - .extern C(d_pzbuffer) - .extern C(d_zistepv) - .extern C(d_zrowbytes) - .extern C(d_ziorigin) - .extern C(r_turb_s) - .extern C(r_turb_t) - .extern C(r_turb_pdest) - .extern C(r_turb_spancount) - .extern C(r_turb_turb) - .extern C(r_turb_pbase) - .extern C(r_turb_sstep) - .extern C(r_turb_tstep) - .extern C(r_bmodelactive) - .extern C(d_sdivzstepu) - .extern C(d_tdivzstepu) - .extern C(d_sdivzstepv) - .extern C(d_tdivzstepv) - .extern C(d_sdivzorigin) - .extern C(d_tdivzorigin) - .extern C(sadjust) - .extern C(tadjust) - .extern C(bbextents) - .extern C(bbextentt) - .extern C(cacheblock) - .extern C(d_viewbuffer) - .extern C(cachewidth) - .extern C(d_pzbuffer) - .extern C(d_zrowbytes) - .extern C(d_zwidth) - .extern C(d_scantable) - .extern C(r_lightptr) - .extern C(r_numvblocks) - .extern C(prowdestbase) - .extern C(pbasesource) - .extern C(r_lightwidth) - .extern C(lightright) - .extern C(lightrightstep) - .extern C(lightdeltastep) - .extern C(lightdelta) - .extern C(lightright) - .extern C(lightdelta) - .extern C(sourcetstep) - .extern C(surfrowbytes) - .extern C(lightrightstep) - .extern C(lightdeltastep) - .extern C(r_sourcemax) - .extern C(r_stepback) - .extern C(colormap) - .extern C(blocksize) - .extern C(sourcesstep) - .extern C(lightleft) - .extern C(blockdivshift) - .extern C(blockdivmask) - .extern C(lightleftstep) - .extern C(r_origin) - .extern C(r_ppn) - .extern C(r_pup) - .extern C(r_pright) - .extern C(ycenter) - .extern C(xcenter) - .extern C(d_vrectbottom_particle) - .extern C(d_vrectright_particle) - .extern C(d_vrecty) - .extern C(d_vrectx) - .extern C(d_pix_shift) - .extern C(d_pix_min) - .extern C(d_pix_max) - .extern C(d_y_aspect_shift) - .extern C(screenwidth) - .extern C(r_leftclipped) - .extern C(r_leftenter) - .extern C(r_rightclipped) - .extern C(r_rightenter) - .extern C(modelorg) - .extern C(xscale) - .extern C(r_refdef) - .extern C(yscale) - .extern C(r_leftexit) - .extern C(r_rightexit) - .extern C(r_lastvertvalid) - .extern C(cacheoffset) - .extern C(newedges) - .extern C(removeedges) - .extern C(r_pedge) - .extern C(r_framecount) - .extern C(r_u1) - .extern C(r_emitted) - .extern C(edge_p) - .extern C(surface_p) - .extern C(surfaces) - .extern C(r_lzi1) - .extern C(r_v1) - .extern C(r_ceilv1) - .extern C(r_nearzi) - .extern C(r_nearzionly) - .extern C(edge_aftertail) - .extern C(edge_tail) - .extern C(current_iv) - .extern C(edge_head_u_shift20) - .extern C(span_p) - .extern C(edge_head) - .extern C(fv) - .extern C(edge_tail_u_shift20) - .extern C(r_apverts) - .extern C(r_anumverts) - .extern C(aliastransform) - .extern C(r_avertexnormals) - .extern C(r_plightvec) - .extern C(r_ambientlight) - .extern C(r_shadelight) - .extern C(aliasxcenter) - .extern C(aliasycenter) - .extern C(a_sstepxfrac) - .extern C(r_affinetridesc) - .extern C(acolormap) - .extern C(d_pcolormap) - .extern C(r_affinetridesc) - .extern C(d_sfrac) - .extern C(d_ptex) - .extern C(d_pedgespanpackage) - .extern C(d_tfrac) - .extern C(d_light) - .extern C(d_zi) - .extern C(d_pdest) - .extern C(d_pz) - .extern C(d_aspancount) - .extern C(erroradjustup) - .extern C(errorterm) - .extern C(d_xdenom) - .extern C(r_p0) - .extern C(r_p1) - .extern C(r_p2) - .extern C(a_tstepxfrac) - .extern C(r_sstepx) - .extern C(r_tstepx) - .extern C(a_ststepxwhole) - .extern C(zspantable) - .extern C(skintable) - .extern C(r_zistepx) - .extern C(erroradjustdown) - .extern C(d_countextrastep) - .extern C(ubasestep) - .extern C(a_ststepxwhole) - .extern C(a_tstepxfrac) - .extern C(r_lstepx) - .extern C(a_spans) - .extern C(erroradjustdown) - .extern C(d_pdestextrastep) - .extern C(d_pzextrastep) - .extern C(d_sfracextrastep) - .extern C(d_ptexextrastep) - .extern C(d_countextrastep) - .extern C(d_tfracextrastep) - .extern C(d_lightextrastep) - .extern C(d_ziextrastep) - .extern C(d_pdestbasestep) - .extern C(d_pzbasestep) - .extern C(d_sfracbasestep) - .extern C(d_ptexbasestep) - .extern C(ubasestep) - .extern C(d_tfracbasestep) - .extern C(d_lightbasestep) - .extern C(d_zibasestep) - .extern C(zspantable) - .extern C(r_lstepy) - .extern C(r_sstepy) - .extern C(r_tstepy) - .extern C(r_zistepy) - .extern C(D_PolysetSetEdgeTable) - .extern C(D_RasterizeAliasPolySmooth) - - .extern float_point5 - .extern Float2ToThe31nd - .extern izistep - .extern izi - .extern FloatMinus2ToThe31nd - .extern float_1 - .extern float_particle_z_clip - .extern float_minus_1 - .extern float_0 - .extern fp_16 - .extern fp_64k - .extern fp_1m - .extern fp_1m_minus_1 - .extern fp_8 - .extern entryvec_table - .extern advancetable - .extern sstep - .extern tstep - .extern pspantemp - .extern counttemp - .extern jumptemp - .extern reciprocal_table - .extern DP_Count - .extern DP_u - .extern DP_v - .extern DP_32768 - .extern DP_Color - .extern DP_Pix - .extern DP_EntryTable - .extern pbase - .extern s - .extern t - .extern sfracf - .extern tfracf - .extern snext - .extern tnext - .extern spancountminus1 - .extern zi16stepu - .extern sdivz16stepu - .extern tdivz16stepu - .extern zi8stepu - .extern sdivz8stepu - .extern tdivz8stepu - .extern reciprocal_table_16 - .extern entryvec_table_16 - .extern ceil_cw - .extern single_cw - .extern fp_64kx64k - .extern pz - .extern spr8entryvec_table - - .extern C(vright) - .extern C(vup) - .extern C(vpn) - -#endif // _QUAKEASM_H_ - diff --git a/nq/include/render.h b/nq/include/render.h index 48ce2dc58..37f70cf57 100644 --- a/nq/include/render.h +++ b/nq/include/render.h @@ -31,7 +31,7 @@ #include "QF/mathlib.h" #include "QF/cvar.h" -#include "vid.h" +#include "QF/vid.h" #include "protocol.h" #define MAXCLIPPLANES 11 diff --git a/nq/include/vid.h b/nq/include/vid.h deleted file mode 100644 index 818e90d7e..000000000 --- a/nq/include/vid.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - vid.h - - video driver defs - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef __vid_h_ -#define __vid_h_ - -#include "QF/qtypes.h" - -#define VID_CBITS 6 -#define VID_GRADES (1 << VID_CBITS) - -typedef struct vrect_s { - int x,y,width,height; - struct vrect_s *pnext; -} vrect_t; - -typedef struct { - pixel_t *buffer; // invisible buffer - pixel_t *colormap; // 256 * VID_GRADES size - unsigned short *colormap16; // 256 * VID_GRADES size - int fullbright; // index of first fullbright color - unsigned int rowbytes; // may be > width if displayed in a window - unsigned int width; - unsigned int height; - float aspect; // width / height -- < 0 is taller than wide - int numpages; - int recalc_refdef; // if true, recalc vid-based stuff - pixel_t *conbuffer; - int conrowbytes; - unsigned int conwidth; - unsigned int conheight; - int maxwarpwidth; - int maxwarpheight; - pixel_t *direct; // direct drawing to framebuffer, if not - // NULL -} viddef_t; - -extern viddef_t vid; // global video state -extern unsigned short d_8to16table[256]; -extern unsigned int d_8to24table[256]; -extern int scr_width, scr_height; - -// called at startup and after any gamma correction -void VID_SetPalette (unsigned char *palette); - -// called for bonus and pain flashes, and for underwater color changes -void VID_ShiftPalette (unsigned char *palette); - -void VID_Init_Cvars (void); - -// 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 *); - -// Called at shutdown -void VID_Shutdown (void); - -// flushes the given rectangles from the view buffer to the screen -void VID_Update (vrect_t *rects); - -// sets the mode; only used by the Quake engine for resetting to mode 0 (the -// base mode) on memory allocation failures -// int VID_SetMode (int modenum, unsigned char *palette); - -// called only on Win32, when pause happens, so the mouse can be released -void VID_HandlePause (qboolean pause); - -void VID_LockBuffer (void); -void VID_UnlockBuffer (void); - -qboolean VID_Is8bit (void); - -void VID_SetCaption (char *text); -// used to set window caption - -void VID_GetWindowSize (int def_w, int def_h); - -#endif // __vid_h_ diff --git a/nq/include/wad.h b/nq/include/wad.h deleted file mode 100644 index 06d3fee1f..000000000 --- a/nq/include/wad.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - wad.h - - @description@ - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef __wad_h -#define __wad_h - -#include "QF/qtypes.h" - -//=============== -// TYPES -//=============== - -#define CMP_NONE 0 -#define CMP_LZSS 1 - -#define TYP_NONE 0 -#define TYP_LABEL 1 - -#define TYP_LUMPY 64 // 64 + grab command number -#define TYP_PALETTE 64 -#define TYP_QTEX 65 -#define TYP_QPIC 66 -#define TYP_SOUND 67 -#define TYP_MIPTEX 68 - -typedef struct -{ - int width, height; - byte data[4]; // variably sized -} qpic_t; - - - -typedef struct -{ - char identification[4]; // should be WAD2 or 2DAW - int numlumps; - int infotableofs; -} wadinfo_t; - -typedef struct -{ - int filepos; - int disksize; - int size; // uncompressed - char type; - char compression; - char pad1, pad2; - char name[16]; // must be null terminated -} lumpinfo_t; - -extern int wad_numlumps; -extern lumpinfo_t *wad_lumps; -extern byte *wad_base; - -void W_LoadWadFile (char *filename); -void W_CleanupName (char *in, char *out); -lumpinfo_t *W_GetLumpinfo (char *name); -void *W_GetLumpName (char *name); -void *W_GetLumpNum (int num); - -void SwapPic (qpic_t *pic); - -#endif // __wad_h diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index cd1ed9f4d..8a1c6e64e 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -394,7 +394,7 @@ SetPal (int i) old = i; if (i == 0) - VID_SetPalette (host_basepal); + VID_SetPalette (vid_basepal); else if (i == 1) { for (c = 0; c < 768; c += 3) { pal[c] = 0; diff --git a/nq/source/d_fill.c b/nq/source/d_fill.c index 373deda33..33571ed02 100644 --- a/nq/source/d_fill.c +++ b/nq/source/d_fill.c @@ -1,7 +1,7 @@ /* d_fill.c - @description@ + clears a specified rectangle to the specified color Copyright (C) 1996-1997 Id Software, Inc. @@ -30,19 +30,18 @@ # include "config.h" #endif -#include "vid.h" +#include "d_iface.h" + /* -================ -D_FillRect -================ + D_FillRect */ void D_FillRect (vrect_t *rect, int color) { int rx, ry, rwidth, rheight; unsigned char *dest; - unsigned *ldest; + unsigned int *ldest; rx = rect->x; ry = rect->y; @@ -69,7 +68,7 @@ D_FillRect (vrect_t *rect, int color) if (((rwidth & 0x03) == 0) && (((long) dest & 0x03) == 0)) { // faster aligned dword clear - ldest = (unsigned *) dest; + ldest = (unsigned int *) dest; color += color << 16; rwidth >>= 2; @@ -78,7 +77,7 @@ D_FillRect (vrect_t *rect, int color) for (ry = 0; ry < rheight; ry++) { for (rx = 0; rx < rwidth; rx++) ldest[rx] = color; - ldest = (unsigned *) ((byte *) ldest + vid.rowbytes); + ldest = (unsigned int *) ((byte *) ldest + vid.rowbytes); } } else { // slower byte-by-byte clear for unaligned cases diff --git a/nq/source/d_init.c b/nq/source/d_init.c index 46d45b55e..b30ca4991 100644 --- a/nq/source/d_init.c +++ b/nq/source/d_init.c @@ -31,7 +31,6 @@ #endif #include "d_local.h" -#include "vid.h" #define NUM_MIPS 4 diff --git a/nq/source/draw.c b/nq/source/draw.c index f8178a88c..961ca1986 100644 --- a/nq/source/draw.c +++ b/nq/source/draw.c @@ -31,7 +31,7 @@ #endif #include "draw.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/zone.h" #include "QF/sys.h" #include "QF/quakefs.h" diff --git a/nq/source/gl_draw.c b/nq/source/gl_draw.c index b6fe43417..9f692c47b 100644 --- a/nq/source/gl_draw.c +++ b/nq/source/gl_draw.c @@ -37,7 +37,7 @@ #endif #include "QF/compat.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/sys.h" #include "QF/mathlib.h" // needed by: protocol.h, render.h, // client.h, @@ -58,7 +58,7 @@ static int GL_LoadPicTexture (qpic_t *pic); -extern byte *host_basepal; +extern byte *vid_basepal; extern unsigned char d_15to8table[65536]; extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor; extern qboolean lighthalf; @@ -877,11 +877,11 @@ Draw_Fill (int x, int y, int w, int h, int c) { glDisable (GL_TEXTURE_2D); if (lighthalf) - glColor3f (host_basepal[c * 3] / 510.0, host_basepal[c * 3 + 1] / 510.0, - host_basepal[c * 3 + 2] / 510.0); + glColor3f (vid_basepal[c * 3] / 510.0, vid_basepal[c * 3 + 1] / 510.0, + vid_basepal[c * 3 + 2] / 510.0); else - glColor3f (host_basepal[c * 3] / 255.0, host_basepal[c * 3 + 1] / 255.0, - host_basepal[c * 3 + 2] / 255.0); + glColor3f (vid_basepal[c * 3] / 255.0, vid_basepal[c * 3 + 1] / 255.0, + vid_basepal[c * 3 + 2] / 255.0); glBegin (GL_QUADS); diff --git a/nq/source/gl_rmisc.c b/nq/source/gl_rmisc.c index ae0dcee79..472a8f702 100644 --- a/nq/source/gl_rmisc.c +++ b/nq/source/gl_rmisc.c @@ -36,7 +36,7 @@ #include #endif -#include "vid.h" +#include "QF/vid.h" #include "QF/sys.h" #include "QF/mathlib.h" // needed by: protocol.h, render.h, // client.h, diff --git a/nq/source/gl_rsurf.c b/nq/source/gl_rsurf.c index f39f220c4..38bab6650 100644 --- a/nq/source/gl_rsurf.c +++ b/nq/source/gl_rsurf.c @@ -39,7 +39,7 @@ #include "QF/compat.h" #include "r_local.h" #include "QF/qargs.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/sys.h" #include "QF/mathlib.h" // needed by: protocol.h, render.h, // client.h, diff --git a/nq/source/gl_screen.c b/nq/source/gl_screen.c index 96f516605..5252d1010 100644 --- a/nq/source/gl_screen.c +++ b/nq/source/gl_screen.c @@ -39,7 +39,7 @@ #include "QF/compat.h" #include "QF/input.h" #include "QF/qendian.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/sys.h" #include "QF/mathlib.h" // needed by: protocol.h, render.h, // client.h, @@ -110,7 +110,7 @@ console is: */ -extern byte *host_basepal; +extern byte *vid_basepal; extern double host_frametime; extern double realtime; int glx, gly, glwidth, glheight; @@ -887,7 +887,7 @@ SCR_BringDownConsole (void) cl.cshifts[0].percent = 0; // no area contents palette on next // frame - VID_SetPalette (host_basepal); + VID_SetPalette (vid_basepal); } void diff --git a/nq/source/host.c b/nq/source/host.c index 310ac3e40..8e8219945 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -46,7 +46,7 @@ #include "QF/sys.h" #include "QF/va.h" #include "sbar.h" -#include "vid.h" +#include "QF/vid.h" #include "draw.h" #include "QF/input.h" #include "screen.h" @@ -86,7 +86,7 @@ client_t *host_client; // current client jmp_buf host_abortserver; -byte *host_basepal; +byte *vid_basepal; byte *host_colormap; cvar_t *fs_globalcfg; @@ -960,10 +960,10 @@ Host_Init (quakeparms_t *parms) R_InitTextures (); // needed even for dedicated servers if (cls.state != ca_dedicated) { - host_basepal = (byte *) COM_LoadHunkFile ("gfx/palette.lmp"); - if (!host_basepal) + vid_basepal = (byte *) COM_LoadHunkFile ("gfx/palette.lmp"); + if (!vid_basepal) Sys_Error ("Couldn't load gfx/palette.lmp"); - host_basepal[765] = host_basepal[766] = host_basepal[767] = 0; // LordHavoc: + vid_basepal[765] = vid_basepal[766] = vid_basepal[767] = 0; // LordHavoc: // // force // the @@ -975,7 +975,7 @@ Host_Init (quakeparms_t *parms) if (!host_colormap) Sys_Error ("Couldn't load gfx/colormap.lmp"); - VID_Init (host_basepal); + VID_Init (vid_basepal); IN_Init (); Draw_Init (); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 83fe8c8f0..5207cc6c1 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -35,7 +35,7 @@ #include "sbar.h" #include "game.h" #include "QF/cmd.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/va.h" #include "draw.h" #include "wad.h" diff --git a/nq/source/screen.c b/nq/source/screen.c index ca73a46a6..2d653dcf6 100644 --- a/nq/source/screen.c +++ b/nq/source/screen.c @@ -733,7 +733,7 @@ SCR_ScreenShot_f (void) // buffer WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes, - host_basepal); + vid_basepal); D_DisableBackBufferAccess (); // for adapters that can't stay // mapped in @@ -887,7 +887,7 @@ SCR_BringDownConsole (void) cl.cshifts[0].percent = 0; // no area contents palette on next // frame - VID_SetPalette (host_basepal); + VID_SetPalette (vid_basepal); } diff --git a/nq/source/sw_rmisc.c b/nq/source/sw_rmisc.c index c9e406566..6cff8fc29 100644 --- a/nq/source/sw_rmisc.c +++ b/nq/source/sw_rmisc.c @@ -277,7 +277,7 @@ WarpPalette (void) for (i = 0; i < 256; i++) { for (j = 0; j < 3; j++) { newpalette[i * 3 + j] = - (host_basepal[i * 3 + j] + basecolor[j]) / 2; + (vid_basepal[i * 3 + j] + basecolor[j]) / 2; } } diff --git a/nq/source/sw_view.c b/nq/source/sw_view.c index 009d31614..4f606446d 100644 --- a/nq/source/sw_view.c +++ b/nq/source/sw_view.c @@ -37,7 +37,7 @@ #include "draw.h" #include "host.h" #include "view.h" -#include "vid.h" +#include "QF/vid.h" extern byte gammatable[256]; @@ -95,7 +95,7 @@ V_UpdatePalette (void) if (!new && !force) return; - basepal = host_basepal; + basepal = vid_basepal; newpal = pal; for (i = 0; i < 256; i++) { diff --git a/nq/source/vid.c b/nq/source/vid.c index 2b00697ea..e3d02534e 100644 --- a/nq/source/vid.c +++ b/nq/source/vid.c @@ -30,34 +30,50 @@ # include "config.h" #endif +#include + +#include "QF/compat.h" +#include "QF/console.h" #include "QF/cvar.h" -#include "vid.h" -#include "QF/va.h" #include "QF/qargs.h" #include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "view.h" extern viddef_t vid; // global video state -int scr_width, scr_height; -cvar_t *vid_width; -cvar_t *vid_height; +/* + Software and hardware gamma support +*/ +byte gammatable[256]; +cvar_t *vid_gamma; +cvar_t *vid_system_gamma; +qboolean vid_gamma_avail; // hardware gamma availability + +/* + Screen size +*/ +int scr_width, scr_height; +cvar_t *vid_width; +cvar_t *vid_height; void VID_GetWindowSize (int def_w, int def_h) { - int pnum; + int pnum; - vid_width = - Cvar_Get ("vid_width", va ("%d", def_w), CVAR_ROM, NULL, - "screen width"); - vid_height = - Cvar_Get ("vid_height", va ("%d", def_h), CVAR_ROM, NULL, - "screen height"); + vid_width = Cvar_Get ("vid_width", va ("%d", def_w), CVAR_NONE, NULL, + "screen width"); + vid_height = Cvar_Get ("vid_height", va ("%d", def_h), CVAR_NONE, NULL, + "screen height"); if ((pnum = COM_CheckParm ("-width"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -width \n"); - Cvar_SetROM (vid_width, com_argv[pnum + 1]); + + Cvar_Set (vid_width, com_argv[pnum + 1]); + if (!vid_width->int_val) Sys_Error ("VID: Bad window width\n"); } @@ -65,7 +81,9 @@ VID_GetWindowSize (int def_w, int def_h) if ((pnum = COM_CheckParm ("-height"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -height \n"); - Cvar_SetROM (vid_height, com_argv[pnum + 1]); + + Cvar_Set (vid_height, com_argv[pnum + 1]); + if (!vid_height->int_val) Sys_Error ("VID: Bad window height\n"); } @@ -73,12 +91,90 @@ VID_GetWindowSize (int def_w, int def_h) if ((pnum = COM_CheckParm ("-winsize"))) { if (pnum >= com_argc - 2) Sys_Error ("VID: -winsize \n"); - Cvar_SetROM (vid_width, com_argv[pnum + 1]); - Cvar_SetROM (vid_height, com_argv[pnum + 2]); + + Cvar_Set (vid_width, com_argv[pnum + 1]); + Cvar_Set (vid_height, com_argv[pnum + 2]); + if (!vid_width->int_val || !vid_height->int_val) Sys_Error ("VID: Bad window width/height\n"); } + Cvar_SetFlags (vid_width, vid_width->flags | CVAR_ROM); + Cvar_SetFlags (vid_height, vid_height->flags | CVAR_ROM); + scr_width = vid.width = vid_width->int_val; scr_height = vid.height = vid_height->int_val; } + +/**************************************************************************** + * GAMMA FUNCTIONS * + ****************************************************************************/ + +void +VID_BuildGammaTable (double gamma) +{ + int i; + + gammatable[0] = 0; + if (gamma == 1.0) { // linear, don't bother with the math + for (i = 1; i < 255; i++) { + gammatable[i] = i; + } + } else { + double g = 1.0 / gamma; + int v; + + for (i = 1; i < 255; i++) { // Build/update gamma lookup table + v = (int) ((255.0 * pow ((double) i / 255.0, g)) + 0.5); + gammatable[i] = bound (0, v, 255); + } + } + gammatable[255] = 255; +} + +/* + VID_UpdateGamma + + This is a callback to update the palette or system gamma whenever the + vid_gamma Cvar is changed. +*/ +void +VID_UpdateGamma (cvar_t *vid_gamma) +{ + double gamma = bound (0.1, vid_gamma->value, 9.9); + + if (vid_gamma->flags & CVAR_ROM) // System gamma unavailable + return; + + if (vid_gamma_avail && vid_system_gamma->int_val) { // Have system, use it + Con_DPrintf ("Setting hardware gamma to %g\n", gamma); + VID_BuildGammaTable (1.0); // hardware gamma wants a linear palette + VID_SetGamma (gamma); + } else { // We have to hack the palette + Con_DPrintf ("Setting software gamma to %g\n", gamma); + VID_BuildGammaTable (gamma); + V_UpdatePalette (); // update with the new palette + } +} + +/* + VID_InitGamma + + Initialize the vid_gamma Cvar, and set up the palette +*/ +void +VID_InitGamma (unsigned char *pal) +{ + int i; + double gamma = 1.45; + + if ((i = COM_CheckParm ("-gamma"))) { + gamma = atof (com_argv[i + 1]); + } + gamma = bound (0.1, gamma, 9.9); + + vid_gamma = Cvar_Get ("vid_gamma", va ("%f", gamma), CVAR_ARCHIVE, + VID_UpdateGamma, "Gamma correction"); + + VID_BuildGammaTable (vid_gamma->value); +} diff --git a/qw/include/Makefile.am b/qw/include/Makefile.am index 408631d92..c246401ed 100644 --- a/qw/include/Makefile.am +++ b/qw/include/Makefile.am @@ -1,20 +1,14 @@ ## Process this file with automake to produce Makefile.in AUTOMAKE_OPTIONS= foreign -EXTRA_DIST = adivtab.h anorm_dots.h anorms.h asm_draw.h asm_i386.h block16.h \ - block8.h bothdefs.h bspfile.h buildnum.h checksum.h cl_cam.h \ - cl_demo.h cl_ents.h cl_input.h cl_main.h cl_parse.h cl_pred.h \ - cl_slist.h cl_tent.h client.h cmd.h commdef.h compat.h config.h.in \ - console.h context_x11.h crc.h cvar.h d_iface.h d_ifacea.h d_local.h \ - dga_check.h draw.h fbset.h fractalnoise.h gcc_attr.h gl_warp_sin.h \ - glquake.h hash.h host.h in_win.h info.h input.h joystick.h keys.h \ - link.h locs.h mathlib.h mdfour.h model.h modelgen.h msg.h net.h pcx.h \ - pmove.h pr_comp.h progdefs.h progs.h protocol.h qargs.h qdefs.h \ - qendian.h qfgl_ext.h qtypes.h quakeasm.h quakefs.h quakeio.h \ +EXTRA_DIST = adivtab.h anorm_dots.h anorms.h asm_draw.h block16.h block8.h \ + bothdefs.h buildnum.h cl_cam.h cl_demo.h cl_ents.h cl_input.h \ + cl_main.h cl_parse.h cl_pred.h cl_slist.h cl_tent.h client.h \ + commdef.h config.h.in d_iface.h d_ifacea.h d_local.h draw.h \ + gcc_attr.h gl_warp_sin.h glquake.h host.h locs.h modelgen.h net.h \ + pcx.h pmove.h pr_comp.h progdefs.h protocol.h quakeasm.h \ r_dynamic.h r_local.h r_shared.h render.h sbar.h screen.h server.h \ - sizebuf.h skin.h sound.h spritegn.h sv_pr_cmds.h sys.h tga.h \ - teamplay.h texture.h uint32.h va.h ver_check.h vid.h view.h wad.h \ - winquake.h world.h zone.h \ + skin.h sv_pr_cmds.h teamplay.h texture.h tga.h wad.h world.h \ \ win32/fnmatch.h win32/version.h win32/version.h.in \ win32/mingw/config.h \ diff --git a/qw/include/client.h b/qw/include/client.h index 81528779a..44afd0c80 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -34,7 +34,7 @@ #include "protocol.h" #include "QF/quakefs.h" #include "render.h" -#include "vid.h" +#include "QF/vid.h" #include "QF/zone.h" // player_state_t is the information needed by a player entity diff --git a/qw/include/d_local.h b/qw/include/d_local.h deleted file mode 100644 index 73ad99248..000000000 --- a/qw/include/d_local.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - d_local.h - - Private rasterization driver defs - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -#ifndef _D_LOCAL_H -#define _D_LOCAL_H - -#include "r_shared.h" - -// -// TODO: fine-tune this; it's based on providing some overage even if there -// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each -// -#define SCANBUFFERPAD 0x1000 - -#define R_SKY_SMASK 0x007F0000 -#define R_SKY_TMASK 0x007F0000 - -#define DS_SPAN_LIST_END -128 - -#define SURFCACHE_SIZE_AT_320X200 600*1024 - -typedef struct surfcache_s -{ - struct surfcache_s *next; - struct surfcache_s **owner; // NULL is an empty chunk of memory - int lightadj[MAXLIGHTMAPS]; // checked for strobe flush - int dlight; - int size; // including header - unsigned int width; - unsigned int height; // DEBUG only needed for debug - float mipscale; - struct texture_s *texture; // checked for animating textures - byte data[4]; // width*height elements -} surfcache_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct sspan_s -{ - int u, v, count; -} sspan_t; - -extern cvar_t *d_subdiv16; - -extern float scale_for_mip; - -extern qboolean d_roverwrapped; -extern surfcache_t *sc_rover; -extern surfcache_t *d_initial_rover; - -extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; -extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; -extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; - -extern fixed16_t sadjust, tadjust; -extern fixed16_t bbextents, bbextentt; - - -void D_DrawSpans8 (espan_t *pspans); -void D_DrawSpans16 (espan_t *pspans); -void D_DrawZSpans (espan_t *pspans); -void Turbulent8 (espan_t *pspan); -void D_SpriteDrawSpans (sspan_t *pspan); - -void D_DrawSkyScans8 (espan_t *pspan); -void D_DrawSkyScans16 (espan_t *pspan); - -void R_ShowSubDiv (void); -void (*prealspandrawer)(void); -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); - -extern int D_MipLevelForScale (float scale); - -#ifdef USE_INTEL_ASM -extern void D_PolysetAff8Start (void); -extern void D_PolysetAff8End (void); -#endif - -extern short *d_pzbuffer; -extern unsigned int d_zrowbytes, d_zwidth; - -extern int *d_pscantable; -extern int d_scantable[MAXHEIGHT]; - -extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; - -extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; - -extern pixel_t *d_viewbuffer; - -extern short *zspantable[MAXHEIGHT]; - -extern int d_minmip; -extern float d_scalemip[3]; - -extern void (*d_drawspans) (espan_t *pspan); - -#endif // _D_LOCAL_H diff --git a/qw/include/host.h b/qw/include/host.h index 1cf3d0ff5..cc5aafde2 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -49,8 +49,6 @@ extern struct cvar_s *password; extern double host_frametime; // Tonik -extern byte *host_basepal; -extern byte *host_colormap; extern int host_framecount; // incremented every frame, never reset extern qboolean msg_suppress_1; // Suppresses resolution and cache size diff --git a/qw/include/r_local.h b/qw/include/r_local.h index adf2aba1e..0447d8f3c 100644 --- a/qw/include/r_local.h +++ b/qw/include/r_local.h @@ -31,7 +31,7 @@ #include "QF/mathlib.h" #include "QF/cvar.h" -#include "vid.h" +#include "QF/vid.h" #include "client.h" #include "QF/model.h" #include "pmove.h" diff --git a/qw/include/r_shared.h b/qw/include/r_shared.h deleted file mode 100644 index e16b25f3b..000000000 --- a/qw/include/r_shared.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - r_shared.h - - general refresh-related stuff shared between the refresh and the driver - - 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: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - - $Id$ -*/ - -// FIXME: clean up and move into d_iface.h - -#ifndef _R_SHARED_H -#define _R_SHARED_H - -#include "QF/mathlib.h" -#include "QF/cvar.h" -#include "QF/model.h" -#include "d_iface.h" - -#define MAXVERTS 16 // max points in a surface polygon -#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate - // polygon (while processing) -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -#define MAXHEIGHT 1024 -#define MAXWIDTH 1280 - -#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to - // be farther away than anything in - // the scene - -//=================================================================== - -extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); - -extern int cachewidth; -extern pixel_t *cacheblock; -extern int screenwidth; - -extern float pixelAspect; - -extern int r_drawnpolycount; - -extern cvar_t *r_clearcolor; - -extern int sintable[1280]; -extern int intsintable[1280]; - -extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; -extern vec3_t vright, base_vright; -extern entity_t *currententity; - -#define NUMSTACKEDGES 2000 -#define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 1000 -#define MINSURFACES NUMSTACKSURFACES -#define MAXSPANS 3000 - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct espan_s -{ - int u, v, count; - struct espan_s *pnext; -} espan_t; - -// FIXME: compress, make a union if that will help -// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte -typedef struct surf_s -{ - struct surf_s *next; // active surface stack in r_edge.c - struct surf_s *prev; // used in r_edge.c for active surf stack - struct espan_s *spans; // pointer to linked list of spans to draw - int key; // sorting key (BSP order) - int last_u; // set during tracing - int spanstate; // 0 = not in span - // 1 = in span - // -1 = in inverted span (end before - // start) - int flags; // currentface flags - void *data; // associated data like msurface_t - entity_t *entity; - float nearzi; // nearest 1/z on surface, for mipmapping - qboolean insubmodel; - float d_ziorigin, d_zistepu, d_zistepv; - - int pad[2]; // to 64 bytes -} surf_t; - -extern surf_t *surfaces, *surface_p, *surf_max; - -// surfaces are generated in back to front order by the bsp, so if a surf -// pointer is greater than another one, it should be drawn in front -// surfaces[1] is the background, and is used as the active surface stack. -// surfaces[0] is a dummy, because index 0 is used to indicate no surface -// attached to an edge_t - -//=================================================================== - -extern vec3_t sxformaxis[4]; // s axis transformed into viewspace -extern vec3_t txformaxis[4]; // t axis transformed into viewspac - -extern vec3_t modelorg, base_modelorg; - -extern float xcenter, ycenter; -extern float xscale, yscale; -extern float xscaleinv, yscaleinv; -extern float xscaleshrink, yscaleshrink; - -extern int d_lightstylevalue[256]; // 8.8 frac of base light value - -extern void TransformVector (vec3_t in, vec3_t out); -extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, - fixed8_t endvertu, fixed8_t endvertv); - -extern int r_skymade; -extern void R_MakeSky (void); - -extern int ubasestep, errorterm, erroradjustup, erroradjustdown; - -// flags in finalvert_t.flags -#define ALIAS_LEFT_CLIP 0x0001 -#define ALIAS_TOP_CLIP 0x0002 -#define ALIAS_RIGHT_CLIP 0x0004 -#define ALIAS_BOTTOM_CLIP 0x0008 -#define ALIAS_Z_CLIP 0x0010 -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h; - // must be kept in sync -#define ALIAS_XY_CLIP_MASK 0x000F - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct edge_s -{ - fixed16_t u; - fixed16_t u_step; - struct edge_s *prev, *next; - unsigned short surfs[2]; - struct edge_s *nextremove; - float nearzi; - medge_t *owner; -} edge_t; - -#endif // _R_SHARED_H diff --git a/qw/include/render.h b/qw/include/render.h index c263b8dd4..605522aaf 100644 --- a/qw/include/render.h +++ b/qw/include/render.h @@ -32,7 +32,7 @@ #include "QF/mathlib.h" #include "QF/model.h" #include "QF/cvar.h" -#include "vid.h" +#include "QF/vid.h" //#include "model.h" //now we know why (struct model_s *) is used here instead of model_t //damn circular reference ! same with player_info_s -- yan diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f19e7c1da..d908f2d22 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -93,7 +93,7 @@ #include "QF/sound.h" #include "QF/sys.h" #include "teamplay.h" -#include "vid.h" +#include "QF/vid.h" #include "view.h" #include "QF/va.h" @@ -189,8 +189,8 @@ int host_framecount; int host_hunklevel; -byte *host_basepal; -byte *host_colormap; +byte *vid_basepal; +byte *vid_colormap; cvar_t *host_speeds; // set for running times cvar_t *show_fps; // set for running times @@ -1634,15 +1634,15 @@ Host_Init (void) R_Textures_Init (); - host_basepal = (byte *) COM_LoadHunkFile ("gfx/palette.lmp"); - if (!host_basepal) + vid_basepal = (byte *) COM_LoadHunkFile ("gfx/palette.lmp"); + if (!vid_basepal) Sys_Error ("Couldn't load gfx/palette.lmp"); - host_colormap = (byte *) COM_LoadHunkFile ("gfx/colormap.lmp"); - if (!host_colormap) + vid_colormap = (byte *) COM_LoadHunkFile ("gfx/colormap.lmp"); + if (!vid_colormap) Sys_Error ("Couldn't load gfx/colormap.lmp"); #ifdef __linux__ CDAudio_Init (); - VID_Init (host_basepal); + VID_Init (vid_basepal); IN_Init (); Draw_Init (); SCR_Init (); @@ -1655,7 +1655,7 @@ Host_Init (void) Skin_Init (); CL_Init (); #else - VID_Init (host_basepal); + VID_Init (vid_basepal); Draw_Init (); SCR_Init (); R_Init (); @@ -1719,6 +1719,6 @@ Host_Shutdown (void) NET_Shutdown (); S_Shutdown (); IN_Shutdown (); - if (host_basepal) + if (vid_basepal) VID_Shutdown (); } diff --git a/qw/source/cl_sys_win.c b/qw/source/cl_sys_win.c index 51505fd21..33fdbefdd 100644 --- a/qw/source/cl_sys_win.c +++ b/qw/source/cl_sys_win.c @@ -47,7 +47,7 @@ #include "screen.h" #include "QF/sound.h" #include "QF/sys.h" -#include "vid.h" +#include "QF/vid.h" qboolean is_server = false; char *svs_info; diff --git a/qw/source/gl_draw.c b/qw/source/gl_draw.c index b90895ebd..e11b97d38 100644 --- a/qw/source/gl_draw.c +++ b/qw/source/gl_draw.c @@ -47,7 +47,7 @@ #include "QF/sys.h" -extern byte *host_basepal; +extern byte *vid_basepal; extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor, *gl_lightmap_components; @@ -684,11 +684,11 @@ Draw_Fill (int x, int y, int w, int h, int c) { glDisable (GL_TEXTURE_2D); if (lighthalf) - glColor3f (host_basepal[c * 3] / 510.0, host_basepal[c * 3 + 1] / 510.0, - host_basepal[c * 3 + 2] / 510.0); + glColor3f (vid_basepal[c * 3] / 510.0, vid_basepal[c * 3 + 1] / 510.0, + vid_basepal[c * 3 + 2] / 510.0); else - glColor3f (host_basepal[c * 3] / 255.0, host_basepal[c * 3 + 1] / 255.0, - host_basepal[c * 3 + 2] / 255.0); + glColor3f (vid_basepal[c * 3] / 255.0, vid_basepal[c * 3 + 1] / 255.0, + vid_basepal[c * 3 + 2] / 255.0); glBegin (GL_QUADS); diff --git a/qw/source/gl_rmain.c b/qw/source/gl_rmain.c index feee62a04..86b9e1f3a 100644 --- a/qw/source/gl_rmain.c +++ b/qw/source/gl_rmain.c @@ -55,7 +55,7 @@ #include "locs.h" #include "r_dynamic.h" #include "skin.h" -#include "vid.h" +#include "QF/vid.h" #include "view.h" entity_t r_worldentity; diff --git a/qw/source/gl_rmisc.c b/qw/source/gl_rmisc.c index ec7f23fa9..1a6d35525 100644 --- a/qw/source/gl_rmisc.c +++ b/qw/source/gl_rmisc.c @@ -45,7 +45,7 @@ #include "r_dynamic.h" #include "skin.h" #include "QF/sys.h" -#include "vid.h" +#include "QF/vid.h" qboolean VID_Is8bit (void); void R_InitBubble (void); diff --git a/qw/source/gl_screen.c b/qw/source/gl_screen.c index cf241688d..4b290e931 100644 --- a/qw/source/gl_screen.c +++ b/qw/source/gl_screen.c @@ -673,9 +673,9 @@ MipColor (int r, int g, int b) bestdist = 256 * 256 * 3; for (i = 0; i < 256; i++) { - r1 = host_basepal[i * 3] - r; - g1 = host_basepal[i * 3 + 1] - g; - b1 = host_basepal[i * 3 + 2] - b; + r1 = vid_basepal[i * 3] - r; + g1 = vid_basepal[i * 3 + 1] - g; + b1 = vid_basepal[i * 3 + 2] - b; dist = r1 * r1 + g1 * g1 + b1 * b1; if (dist < bestdist) { bestdist = dist; @@ -834,7 +834,7 @@ SCR_RSShot_f (void) 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, true); + WritePCXfile (pcxname, newbuf, w, h, w, vid_basepal, true, true); free (newbuf); diff --git a/qw/source/gl_view.c b/qw/source/gl_view.c index 005d2d414..90807deb6 100644 --- a/qw/source/gl_view.c +++ b/qw/source/gl_view.c @@ -44,7 +44,7 @@ #include "QF/compat.h" -extern byte *host_basepal; +extern byte *vid_basepal; extern double host_frametime; extern int onground; extern byte gammatable[256]; diff --git a/qw/source/pcx.c b/qw/source/pcx.c index c2db301f8..31def71c3 100644 --- a/qw/source/pcx.c +++ b/qw/source/pcx.c @@ -98,7 +98,7 @@ LoadPCX (QFile *f, int convert) if (convert) { tex->palette = 0; } else { - tex->palette = host_basepal; + tex->palette = vid_basepal; } pix = tex->data; diff --git a/qw/source/r_view.c b/qw/source/r_view.c index 9e76ea1de..8029d4068 100644 --- a/qw/source/r_view.c +++ b/qw/source/r_view.c @@ -42,7 +42,7 @@ #include "QF/msg.h" #include "pmove.h" #include "screen.h" -#include "vid.h" +#include "QF/vid.h" #include "view.h" /* diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 18a198553..6acd02ffe 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -48,7 +48,7 @@ #include "sbar.h" #include "screen.h" #include "QF/va.h" -#include "vid.h" +#include "QF/vid.h" int sb_updates; // if >= vid.numpages, no update diff --git a/qw/source/screen.c b/qw/source/screen.c index 0888d0e35..911ee3700 100644 --- a/qw/source/screen.c +++ b/qw/source/screen.c @@ -51,7 +51,7 @@ #include "sbar.h" #include "skin.h" #include "QF/sys.h" -#include "vid.h" +#include "QF/vid.h" #include "view.h" /* @@ -664,7 +664,7 @@ SCR_ScreenShot_f (void) // save the pcx file WritePCXfile (pcxname, vid.buffer, vid.width, vid.height, vid.rowbytes, - host_basepal, false, false); + vid_basepal, false, false); // for adapters that can't stay mapped in for linear writes all the time D_DisableBackBufferAccess (); @@ -692,9 +692,9 @@ MipColor (int r, int g, int b) bestdist = 256 * 256 * 3; for (i = 0; i < 256; i++) { - r1 = host_basepal[i * 3] - r; - g1 = host_basepal[i * 3 + 1] - g; - b1 = host_basepal[i * 3 + 2] - b; + r1 = vid_basepal[i * 3] - r; + g1 = vid_basepal[i * 3 + 1] - g; + b1 = vid_basepal[i * 3 + 2] - b; dist = r1 * r1 + g1 * g1 + b1 * b1; if (dist < bestdist) { bestdist = dist; @@ -815,9 +815,9 @@ SCR_RSShot_f (void) 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]; + r += vid_basepal[*src * 3]; + g += vid_basepal[*src * 3 + 1]; + b += vid_basepal[*src * 3 + 2]; src++; count++; } @@ -842,7 +842,7 @@ SCR_RSShot_f (void) st[sizeof (st) - 1] = 0; SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, 20, w); - WritePCXfile (pcxname, newbuf, w, h, w, host_basepal, true, false); + WritePCXfile (pcxname, newbuf, w, h, w, vid_basepal, true, false); free (newbuf); diff --git a/qw/source/skin.c b/qw/source/skin.c index 7ed26493a..c0600d920 100644 --- a/qw/source/skin.c +++ b/qw/source/skin.c @@ -181,7 +181,7 @@ Skin_Cache (skin_t *skin) opix = out->data; out->width = 320; out->height = 200; - out->palette = tex->palette; //FIXME assumes 0 or host_basepal + out->palette = tex->palette; //FIXME assumes 0 or vid_basepal memset (opix, 0, pixels); for (i = 0, ipix = tex->data; i < tex->height; i++, opix += 320, ipix += tex->width) diff --git a/qw/source/sw_rmisc.c b/qw/source/sw_rmisc.c index 28b4f6f8e..ee9441598 100644 --- a/qw/source/sw_rmisc.c +++ b/qw/source/sw_rmisc.c @@ -350,7 +350,7 @@ WarpPalette (void) for (i = 0; i < 256; i++) { for (j = 0; j < 3; j++) { newpalette[i * 3 + j] = - (host_basepal[i * 3 + j] + basecolor[j]) / 2; + (vid_basepal[i * 3 + j] + basecolor[j]) / 2; } } diff --git a/qw/source/sw_skin.c b/qw/source/sw_skin.c index 6f5503425..138c1caf4 100644 --- a/qw/source/sw_skin.c +++ b/qw/source/sw_skin.c @@ -42,7 +42,7 @@ #include "skin.h" #include "QF/compat.h" #include "QF/sys.h" -#include "vid.h" +#include "QF/vid.h" void Skin_Set_Translate (player_info_t *player) diff --git a/qw/source/sw_view.c b/qw/source/sw_view.c index 3e5a6681f..48bc95b3b 100644 --- a/qw/source/sw_view.c +++ b/qw/source/sw_view.c @@ -128,7 +128,7 @@ V_UpdatePalette (void) if (!new && !force) return; - basepal = host_basepal; + basepal = vid_basepal; newpal = pal; for (i = 0; i < 256; i++) { diff --git a/qw/source/vid.c b/qw/source/vid.c index c2df60e77..e3d02534e 100644 --- a/qw/source/vid.c +++ b/qw/source/vid.c @@ -29,6 +29,7 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif + #include #include "QF/compat.h" @@ -37,7 +38,7 @@ #include "QF/qargs.h" #include "QF/sys.h" #include "QF/va.h" -#include "vid.h" +#include "QF/vid.h" #include "view.h" extern viddef_t vid; // global video state @@ -114,19 +115,21 @@ VID_BuildGammaTable (double gamma) { int i; + gammatable[0] = 0; if (gamma == 1.0) { // linear, don't bother with the math - for (i = 0; i < 256; i++) { + for (i = 1; i < 255; i++) { gammatable[i] = i; } } else { double g = 1.0 / gamma; int v; - for (i = 0; i < 256; i++) { // Build/update gamma lookup table + for (i = 1; i < 255; i++) { // Build/update gamma lookup table v = (int) ((255.0 * pow ((double) i / 255.0, g)) + 0.5); gammatable[i] = bound (0, v, 255); } } + gammatable[255] = 255; } /*