shithub: duke3d

Download patch

ref: 553f9ff53af6053926ccd002ddd43001e31f4c14
parent: 882943c43e64604f18ba9bdb217918aa75606f63
author: Fabien Sanglard <fabien.sanglard@gmail.com>
date: Wed Dec 19 17:54:46 EST 2012

Reverse engineered most of draw.c assembly methods.

--- a/Engine/src/build.h
+++ b/Engine/src/build.h
@@ -41,12 +41,7 @@
 	#define EXTERN extern
 #endif
 
-
-#ifdef PLATFORM_DOS
-#pragma pack(push,1);
-#else
 #pragma pack(1)
-#endif
 
 /*
  * ceilingstat/floorstat:
@@ -139,11 +134,7 @@
 	short lotag, hitag, extra;
 } spritetype;
 
-#ifdef PLATFORM_DOS
-#pragma pack(pop);
-#else
 #pragma pack()
-#endif
 
 EXTERN sectortype sector[MAXSECTORS];
 EXTERN walltype wall[MAXWALLS];
@@ -187,7 +178,8 @@
 EXTERN short nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
 
 EXTERN short tilesizx[MAXTILES], tilesizy[MAXTILES];
-// An array of locks for each pic
+
+// An array of locks for each pic: Used to check if a texture is in RAM or in the GRP.
 EXTERN uint8_t  walock[MAXTILES];
 EXTERN int32_t numtiles, picanm[MAXTILES], waloff[MAXTILES];
 
--- /dev/null
+++ b/Engine/src/display.c
@@ -1,0 +1,2282 @@
+/*
+ * An SDL replacement for BUILD's VESA code.
+ *
+ *  Written by Ryan C. Gordon. (icculus@clutteredmind.org)
+ *
+ * Please do NOT harrass Ken Silverman about any code modifications
+ *  (including this file) to BUILD.
+ */
+
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file IS NOT A PART OF Ken Silverman's original release
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include "platform.h"
+
+#if (!defined PLATFORM_SUPPORTS_SDL)
+#error This platform apparently does not use SDL. Do not compile this.
+#endif
+
+
+#define BUILD_NOMOUSEGRAB    "BUILD_NOMOUSEGRAB"
+#define BUILD_WINDOWED       "BUILD_WINDOWED"
+#define BUILD_SDLDEBUG       "BUILD_SDLDEBUG"
+#define BUILD_RENDERER       "BUILD_RENDERER"
+#define BUILD_GLLIBRARY      "BUILD_GLLIBRARY"
+#define BUILD_USERSCREENRES  "BUILD_USERSCREENRES"
+#define BUILD_MAXSCREENRES   "BUILD_MAXSCREENRES"
+#define BUILD_HALLOFMIRRORS  "BUILD_HALLOFMIRRORS"
+#define BUILD_GLDUMP         "BUILD_GLDUMP"
+#define BUILD_SDLJOYSTICK    "BUILD_SDLJOYSTICK"
+
+#include "SDL.h"
+#include "build.h"
+#include "display.h"
+#include "pragmas.h"
+#include "engine.h"
+//#include "engine_protos.h"
+
+#include "mmulti_unstable.h"
+#include "mmulti_stable.h"
+
+#include "icon.h"
+
+// NATIVE TIMER FUNCTION DECLARATION
+/*
+ FCS: The timer section sadly uses Native high precision calls to implement timer functions.
+ QueryPerformanceFrequency and QueryPerformanceCounter
+ it seems SDL precision was not good enough (or rather using unaccurate OS functions) to replicate
+ a DOS timer.
+ */
+
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t);
+void TIMER_GetPlatformTicks(int64_t* t);
+
+//END // NATIVE TIMER FUNCTION DECLARATION
+
+
+
+
+// NETWORK STUFF
+#ifdef __APPLE__
+  #define USER_DUMMY_NETWORK 1
+#endif 
+
+void Setup_UnstableNetworking();
+void Setup_StableNetworking();
+
+int nNetMode = 0;
+
+//TODO ( "[Fix this horrible networking mess. Function pointers not happy]" )
+// I do not like this one bit.
+// Figure out what was causing the problems with the function pointers.
+// This mess is a direct result of my lack of time.. bleh
+// This mess shouldn't even be in this file. /slap /slap
+void callcommit(void)
+{
+#ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:		
+		unstable_callcommit();
+		break;
+	case 1:
+		stable_callcommit();
+		break;		
+	}
+#endif
+}
+void initcrc(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:	
+		unstable_initcrc();
+		break;
+	case 1:	
+		stable_initcrc();
+		break;
+	}
+#endif
+}
+int32_t getcrc(uint8_t  *buffer, short bufleng)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		return unstable_getcrc(buffer, bufleng);
+	case 1:
+		return stable_getcrc(buffer, bufleng);
+	}
+#endif
+	return 0;
+}
+void initmultiplayers(uint8_t  damultioption, uint8_t  dacomrateoption, uint8_t  dapriority)
+{
+#ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_initmultiplayers(damultioption, dacomrateoption, dapriority);
+		break;
+	case 1:
+		stable_initmultiplayers(damultioption, dacomrateoption, dapriority);
+		break;
+	}
+#endif
+}
+void sendpacket(int32_t other, uint8_t  *bufptr, int32_t messleng)
+{
+#ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_sendpacket(other, bufptr, messleng);
+		break;
+	case 1:
+		stable_sendpacket(other, bufptr, messleng);
+		break;
+	}
+#endif
+}
+void setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount)
+{
+#ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_setpackettimeout(datimeoutcount, daresendagaincount);
+		break;
+	case 1:
+		stable_setpackettimeout(datimeoutcount, daresendagaincount);
+		break;
+	}
+#endif
+}
+void uninitmultiplayers(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_uninitmultiplayers();
+		break;
+	case 1:
+		stable_uninitmultiplayers();
+		break;
+	}
+#endif
+}
+void sendlogon(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_sendlogon();
+		break;
+	case 1:
+		unstable_sendlogon();
+		break;
+	}
+#endif
+}
+void sendlogoff(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_sendlogoff();
+		break;
+	case 1:
+		stable_sendlogoff();
+		break;
+	}
+#endif
+}
+int  getoutputcirclesize(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		return unstable_getoutputcirclesize();
+	case 1:
+		return stable_getoutputcirclesize();		
+	}
+#endif
+	return 0;
+}
+void setsocket(short newsocket)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_setsocket(newsocket);
+		break;
+	case 1:
+		stable_setsocket(newsocket);
+		break;
+	}
+#endif
+}
+short getpacket(short *other, uint8_t  *bufptr)
+{
+#ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		return unstable_getpacket(other, bufptr); // default
+	case 1:
+		return stable_getpacket(other, bufptr);
+	}
+#endif
+	return 0;
+}
+void flushpackets(void)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_flushpackets();
+		break;
+	case 1:
+		stable_flushpackets();
+		break;
+	}
+#endif
+}
+void genericmultifunction(int32_t other, char  *bufptr, int32_t messleng, int32_t command)
+{
+    #ifndef USER_DUMMY_NETWORK
+	switch(nNetMode)
+	{
+	case 0:
+		unstable_genericmultifunction(other, bufptr, messleng, command);
+		break;
+	case 1:
+		stable_genericmultifunction(other, bufptr, messleng, command);
+		break;
+	}
+#endif
+}
+
+#if ((defined PLATFORM_WIN32))
+#include <windows.h>
+#endif
+
+typedef enum
+{
+    RENDERER_SOFTWARE,
+    RENDERER_OPENGL3D,
+    RENDERER_TOTAL
+} sdl_renderer_type;
+
+const char  *renderer_name[RENDERER_TOTAL];
+
+#define ENVRSTR_RENDERER_SOFTWARE  "software"
+#define ENVRSTR_RENDERER_OPENGL3D  "opengl3d"
+
+static sdl_renderer_type renderer = RENDERER_SOFTWARE;
+
+#include "draw.h"
+#include "cache.h"
+
+
+/*
+ * !!! remove the surface_end checks, for speed's sake. They are a
+ * !!!  needed safety right now. --ryan.
+ */
+
+
+#define DEFAULT_MAXRESWIDTH  1600
+#define DEFAULT_MAXRESHEIGHT 1200
+
+
+#define UNLOCK_SURFACE_AND_RETURN  if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return;
+
+
+int _argc = 0;
+char  **_argv = NULL;
+
+    /* !!! move these elsewhere? */
+int32_t xres, yres, bytesperline, frameplace, frameoffset, imageSize, maxpages;
+uint8_t  *screen, vesachecked;
+int32_t buffermode, origbuffermode, linearmode;
+uint8_t  permanentupdate = 0, vgacompatible;
+
+SDL_Surface *surface = NULL; /* This isn't static so that we can use it elsewhere AH */
+static int debug_hall_of_mirrors = 0;
+static uint32_t sdl_flags = SDL_HWPALETTE;
+static int32_t mouse_relative_x = 0;
+static int32_t mouse_relative_y = 0;
+static short mouse_buttons = 0;
+static unsigned int lastkey = 0;
+/* so we can make use of setcolor16()... - DDOI */
+static uint8_t  drawpixel_color=0;
+
+static uint32_t scancodes[SDLK_LAST];
+
+static int32_t last_render_ticks = 0;
+int32_t total_render_time = 1;
+int32_t total_rendered_frames = 0;
+
+static char *titleNameLong = NULL;
+static char *titleNameShort = NULL;
+
+void restore256_palette (void);
+void set16color_palette (void);
+
+static FILE *_sdl_debug_file = NULL;
+
+void set_sdl_renderer(void);
+
+static __inline void __out_sdldebug(const char  *subsystem,
+                                  const char  *fmt, va_list ap)
+{
+    fprintf(_sdl_debug_file, "%s: ", subsystem);
+    vfprintf(_sdl_debug_file, fmt, ap);
+    fprintf(_sdl_debug_file, "\n");
+    fflush(_sdl_debug_file);
+} /* __out_sdldebug */
+
+
+static void sdldebug(const char  *fmt, ...)
+{
+    va_list ap;
+
+    if (_sdl_debug_file)
+    {
+        va_start(ap, fmt);
+        __out_sdldebug("BUILDSDL", fmt, ap);
+        va_end(ap);
+    } /* if */
+} /* sdldebug */
+
+static void __append_sdl_surface_flag(SDL_Surface *_surface, char  *str,
+                                      size_t strsize, Uint32 flag,
+                                      const char  *flagstr)
+{
+    if (_surface->flags & flag)
+    {
+        if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) )
+            strcpy(str + (strsize - 5), " ...");
+        else
+            strcat(str, flagstr);
+    } /* if */
+} /* append_sdl_surface_flag */
+
+
+#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)
+#define print_tf_state(str, val) sdldebug("%s: {%s}", str, (val) ? "true" : "false" )
+
+static void output_surface_info(SDL_Surface *_surface)
+{
+    const SDL_VideoInfo *info;
+    char  f[256];
+
+    if (!_sdl_debug_file)
+        return;
+
+    if (_surface == NULL)
+    {
+        sdldebug("-WARNING- You've got a NULL screen surface!");
+    }
+    else
+    {
+        f[0] = '\0';
+        sdldebug("screen surface is (%dx%dx%dbpp).",
+                _surface->w, _surface->h, _surface->format->BitsPerPixel);
+
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SWSURFACE);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWSURFACE);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ASYNCBLIT);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ANYFORMAT);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWPALETTE);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_DOUBLEBUF);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_FULLSCREEN);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGL);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGLBLIT);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RESIZABLE);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_NOFRAME);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWACCEL);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCCOLORKEY);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCELOK);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCEL);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCALPHA);
+        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_PREALLOC);
+
+        if (f[0] == '\0')
+            strcpy(f, " (none)");
+
+        sdldebug("New vidmode flags:%s", f);
+
+        info = SDL_GetVideoInfo();
+        assert(info != NULL);
+
+        print_tf_state("hardware surface available", info->hw_available);
+        print_tf_state("window manager available", info->wm_available);
+        print_tf_state("accelerated hardware->hardware blits", info->blit_hw);
+        print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC);
+        print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A);
+        print_tf_state("accelerated software->hardware blits", info->blit_sw);
+        print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC);
+        print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A);
+        print_tf_state("accelerated color fills", info->blit_fill);
+
+        sdldebug("video memory: (%d)", info->video_mem);
+    } /* else */
+} /* output_surface_info */
+
+
+static void output_driver_info(void)
+{
+    char  buffer[256];
+
+    if (!_sdl_debug_file)
+        return;
+
+    sdldebug("Using BUILD renderer \"%s\".", renderer_name[renderer]);
+
+    if (SDL_VideoDriverName(buffer, sizeof (buffer)) == NULL)
+    {
+        sdldebug("-WARNING- SDL_VideoDriverName() returned NULL!");
+    } /* if */
+    else
+    {
+        sdldebug("Using SDL video driver \"%s\".", buffer);
+    } /* else */
+} /* output_driver_info */
+
+
+Uint8 *get_framebuffer(void)
+{
+    assert(renderer != RENDERER_OPENGL3D);
+
+    if (renderer == RENDERER_SOFTWARE)
+        return((Uint8 *) surface->pixels);
+    else if (renderer == RENDERER_OPENGL3D)
+        return((Uint8 *) frameplace);
+
+    return(NULL);
+} /* get_framebuffer */
+
+
+
+/*
+ * !!! This is almost an entire copy of the original setgamemode().
+ * !!!  Figure out what is needed for just 2D mode, and separate that
+ * !!!  out. Then, place the original setgamemode() back into engine.c,
+ * !!!  and remove our simple implementation (and this function.)
+ * !!!  Just be sure to keep the non-DOS things, like the window's
+ * !!!  titlebar caption.   --ryan.
+ */
+static uint8_t  screenalloctype = 255;
+static void init_new_res_vars(int32_t davidoption)
+{
+    int i = 0;
+    int j = 0;
+
+    setupmouse();
+
+    SDL_WM_SetCaption(titleNameLong, titleNameShort);
+
+    xdim = xres = surface->w;
+    ydim = yres = surface->h;
+
+	printf("init_new_res_vars %d %d\n",xdim,ydim);
+
+    bytesperline = surface->w;
+    vesachecked = 1;
+    vgacompatible = 1;
+    linearmode = 1;
+	qsetmode = surface->h;
+	activepage = visualpage = 0;
+
+    if (renderer == RENDERER_OPENGL3D)
+        frameplace = (int32_t) NULL;
+    else
+		// FIX_00083: Sporadic crash on fullscreen/window mode toggle
+		// frameoffset wasn't always updated fast enought. Build were using the old 
+		// pointer of frameoffset.  
+        frameoffset = frameplace = (int32_t) ( ((Uint8 *) surface->pixels) );
+
+  	if (screen != NULL)
+   	{
+       	if (screenalloctype == 0) kkfree((void *)screen);
+   	    if (screenalloctype == 1) suckcache((int32_t *)screen);
+   		screen = NULL;
+   	} /* if */
+
+
+    	switch(vidoption)
+    	{
+    		case 1:i = xdim*ydim; break;
+    		case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
+    		case 6: xdim = 320; ydim = 200; i = 131072; break;
+    		default: assert(0);
+    	}
+    	j = ydim*4*sizeof(int32_t);  /* Leave room for horizlookup&horizlookup2 */
+
+		if(horizlookup)
+			free(horizlookup);
+
+		if(horizlookup2)
+			free(horizlookup2);
+		
+		horizlookup = (int32_t*)malloc(j);
+		horizlookup2 = (int32_t*)malloc(j);
+
+    j = 0;
+    
+    //Build lookup table (X screespace -> frambuffer offset. 
+  	for(i = 0; i <= ydim; i++)
+    {
+        ylookup[i] = j;
+        j += bytesperline;
+    }
+
+   	horizycent = ((ydim*4)>>1);
+
+    /* Force drawrooms to call dosetaspect & recalculate stuff */
+	oxyaspect = oxdimen = oviewingrange = -1;
+
+    //Let the Assembly module how many pixels to skip when drawing a column
+	setBytesPerLine(bytesperline);
+
+    
+    setview(0L,0L,xdim-1,ydim-1);
+    
+	setbrightness((uint8_t ) curbrightness, (uint8_t  *) &palette[0]);
+
+	if (searchx < 0) {
+        searchx = halfxdimen;
+        searchy = (ydimen>>1);
+    }
+    
+}
+
+
+
+static void go_to_new_vid_mode(int davidoption, int w, int h)
+{
+    getvalidvesamodes();
+    SDL_ClearError();
+    // don't do SDL_SetVideoMode if SDL_WM_SetIcon not called. See sdl doc for SDL_WM_SetIcon
+	surface = SDL_SetVideoMode(w, h, 8, sdl_flags);
+    if (surface == NULL)
+    {
+		Error(EXIT_FAILURE,	"BUILDSDL: Failed to set %dx%d video mode!\n"
+							"BUILDSDL: SDL_Error() says [%s].\n",
+							w, h, SDL_GetError());
+	} /* if */
+
+    output_surface_info(surface);
+    init_new_res_vars(davidoption); // dont be confused between vidoption (global) and davidoption
+}
+
+static __inline int sdl_mouse_button_filter(SDL_MouseButtonEvent const *event)
+{
+        /*
+         * What bits BUILD expects:
+         *  0 left button pressed if 1
+         *  1 right button pressed if 1
+         *  2 middle button pressed if 1
+         *
+         *   (That is, this is what Int 33h (AX=0x05) returns...)
+         *
+         *  additionally bits 3&4 are set for the mouse wheel
+         */
+    Uint8 button = event->button;
+    if (button >= sizeof (mouse_buttons) * 8)
+        return(0);
+
+    if (button == SDL_BUTTON_RIGHT)
+        button = SDL_BUTTON_MIDDLE;
+    else if (button == SDL_BUTTON_MIDDLE)
+        button = SDL_BUTTON_RIGHT;
+
+    if (((const SDL_MouseButtonEvent*)event)->state)
+        mouse_buttons |= 1<<(button-1);
+    else if (button != 4 && button != 5)
+        mouse_buttons ^= 1<<(button-1);
+#if 0
+    Uint8 bmask = SDL_GetMouseState(NULL, NULL);
+    mouse_buttons = 0;
+    if (bmask & SDL_BUTTON_LMASK) mouse_buttons |= 1;
+    if (bmask & SDL_BUTTON_RMASK) mouse_buttons |= 2;
+    if (bmask & SDL_BUTTON_MMASK) mouse_buttons |= 4;
+#endif
+
+    return(0);
+} /* sdl_mouse_up_filter */
+
+
+static int sdl_mouse_motion_filter(SDL_Event const *event)
+{
+    if (surface == NULL)
+		return(0);
+
+    if (event->type == SDL_JOYBALLMOTION)
+    {
+        mouse_relative_x = event->jball.xrel/100;
+        mouse_relative_y = event->jball.yrel/100;
+    }
+    else
+    {
+			if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON) 
+			{
+				mouse_relative_x += event->motion.xrel;
+	       	    mouse_relative_y += event->motion.yrel;
+				//printf("sdl_mouse_motion_filter: mrx=%d, mry=%d, mx=%d, my=%d\n",
+				//	mouse_relative_x, mouse_relative_y, event->motion.xrel, event->motion.yrel);
+				
+				// mouse_relative_* is already reset in 
+				// readmousexy(). It must not be
+				// reset here because calling this function does not mean
+				// we always handle the mouse. 
+				// FIX_00001: Mouse speed is uneven and slower in windowed mode vs fullscreen mode.
+			}
+			else
+				mouse_relative_x = mouse_relative_y = 0;
+	}
+
+    return(0);
+} /* sdl_mouse_motion_filter */
+
+
+    /*
+     * The windib driver can't alert us to the keypad enter key, which
+     *  Ken's code depends on heavily. It sends it as the same key as the
+     *  regular return key. These users will have to hit SHIFT-ENTER,
+     *  which we check for explicitly, and give the engine a keypad enter
+     *  enter event.
+     */
+static __inline int handle_keypad_enter_hack(const SDL_Event *event)
+{
+    static int kp_enter_hack = 0;
+    int retval = 0;
+
+    if (event->key.keysym.sym == SDLK_RETURN)
+    {
+        if (event->key.state == SDL_PRESSED)
+        {
+            if (event->key.keysym.mod & KMOD_SHIFT)
+            {
+                kp_enter_hack = 1;
+                lastkey = scancodes[SDLK_KP_ENTER];
+                retval = 1;
+            } /* if */
+        } /* if */
+
+        else  /* key released */
+        {
+            if (kp_enter_hack)
+            {
+                kp_enter_hack = 0;
+                lastkey = scancodes[SDLK_KP_ENTER];
+                retval = 1;
+            } /* if */
+        } /* if */
+    } /* if */
+
+    return(retval);
+} /* handle_keypad_enter_hack */
+
+void fullscreen_toggle_and_change_driver(void)
+{
+	
+//  FIX_00002: New Toggle Windowed/FullScreen system now simpler and will 
+//  dynamically change for Windib or Directx driver. Windowed/Fullscreen 
+//  toggle also made available from menu.
+//  Replace attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags)
+  	
+	int32_t x,y;
+	x = surface->w;
+	y = surface->h;
+
+	BFullScreen =!BFullScreen;
+	SDL_QuitSubSystem(SDL_INIT_VIDEO);
+	_platform_init(0, NULL, "Duke Nukem 3D", "Duke3D");
+	_setgamemode(ScreenMode,x,y);
+	//vscrn();
+
+	return;
+}
+
+static int sdl_key_filter(const SDL_Event *event)
+{
+    int extended;
+
+    if ( (event->key.keysym.sym == SDLK_m) &&
+         (event->key.state == SDL_PRESSED) &&
+         (event->key.keysym.mod & KMOD_CTRL) )
+    {
+
+
+		// FIX_00005: Mouse pointer can be toggled on/off (see mouse menu or use CTRL-M)
+		// This is usefull to move the duke window when playing in window mode.
+  
+        if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON) 
+		{
+            SDL_WM_GrabInput(SDL_GRAB_OFF);
+			SDL_ShowCursor(1);
+		}
+		else
+		{
+            SDL_WM_GrabInput(SDL_GRAB_ON);
+			SDL_ShowCursor(0);
+		}
+
+        return(0);
+    } /* if */
+
+    else if ( ( (event->key.keysym.sym == SDLK_RETURN) ||
+                (event->key.keysym.sym == SDLK_KP_ENTER) ) &&
+              (event->key.state == SDL_PRESSED) &&
+              (event->key.keysym.mod & KMOD_ALT) )
+    {	fullscreen_toggle_and_change_driver();
+
+		// hack to discard the ALT key...
+		lastkey=scancodes[SDLK_RALT]>>8; // extended
+		keyhandler();
+		lastkey=(scancodes[SDLK_RALT]&0xff)+0x80; // Simulating Key up
+		keyhandler();
+		lastkey=(scancodes[SDLK_LALT]&0xff)+0x80; // Simulating Key up (not extended)
+		keyhandler();
+		SDL_SetModState(KMOD_NONE); // SDL doesnt see we are releasing the ALT-ENTER keys
+        
+		return(0);					
+    }								
+
+    if (!handle_keypad_enter_hack(event))
+        lastkey = scancodes[event->key.keysym.sym];
+
+//	printf("key.keysym.sym=%d\n", event->key.keysym.sym);
+
+    if (lastkey == 0x0000)   /* No DOS equivalent defined. */
+        return(0);
+
+    extended = ((lastkey & 0xFF00) >> 8);
+    if (extended != 0)
+    {
+        lastkey = extended;
+        keyhandler();
+        lastkey = (scancodes[event->key.keysym.sym] & 0xFF);
+    } /* if */
+
+    if (event->key.state == SDL_RELEASED)
+        lastkey += 128;  /* +128 signifies that the key is released in DOS. */
+
+    keyhandler();
+    return(0);
+} /* sdl_key_filter */
+
+
+static int root_sdl_event_filter(const SDL_Event *event)
+{
+    switch (event->type)
+    {
+        case SDL_KEYUP:
+            // FIX_00003: Pause mode is now fully responsive - (Thx to Jonathon Fowler tips)
+			if(event->key.keysym.sym == SDLK_PAUSE)
+				break;
+        case SDL_KEYDOWN:
+            return(sdl_key_filter(event));
+        case SDL_JOYBUTTONDOWN:
+        case SDL_JOYBUTTONUP:
+            {
+                //Do Nothing
+
+                //printf("Joybutton UP/DOWN\n");
+	            //return(sdl_joystick_button_filter((const SDL_MouseButtonEvent*)event));
+                return 0;
+            }
+        case SDL_JOYBALLMOTION:
+        case SDL_MOUSEMOTION:
+            return(sdl_mouse_motion_filter(event));
+        case SDL_MOUSEBUTTONUP:
+        case SDL_MOUSEBUTTONDOWN:
+			return(sdl_mouse_button_filter((const SDL_MouseButtonEvent*)event));
+        case SDL_QUIT:
+            /* !!! rcg TEMP */
+            Error(EXIT_SUCCESS, "Exit through SDL\n"); 
+		default:
+			//printf("This event is not handled: %d\n",event->type);
+			break;
+    } /* switch */
+
+    return(1);
+} /* root_sdl_event_filter */
+
+
+static void handle_events(void)
+{
+    SDL_Event event;
+
+	while(SDL_PollEvent(&event))
+        root_sdl_event_filter(&event);
+} /* handle_events */
+
+
+/* bleh...public version... */
+void _handle_events(void)
+{
+    handle_events();
+} /* _handle_events */
+
+
+static SDL_Joystick *joystick = NULL;
+void _joystick_init(void)
+{
+    const char  *envr = getenv(BUILD_SDLJOYSTICK);
+    int favored = 0;
+    int numsticks;
+    int i;
+
+    if (joystick != NULL)
+    {
+        sdldebug("Joystick appears to be already initialized.");
+        sdldebug("...deinitializing for stick redetection...");
+        _joystick_deinit();
+    } /* if */
+
+    if ((envr != NULL) && (strcmp(envr, "none") == 0))
+    {
+        sdldebug("Skipping joystick detection/initialization at user request");
+        return;
+    } /* if */
+
+    sdldebug("Initializing SDL joystick subsystem...");
+    sdldebug(" (export environment variable BUILD_SDLJOYSTICK=none to skip)");
+
+    if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_NOPARACHUTE) != 0)
+    {
+        sdldebug("SDL_Init(SDL_INIT_JOYSTICK) failed: [%s].", SDL_GetError());
+        return;
+    } /* if */
+
+    numsticks = SDL_NumJoysticks();
+    sdldebug("SDL sees %d joystick%s.", numsticks, numsticks == 1 ? "" : "s");
+    if (numsticks == 0)
+        return;
+
+    for (i = 0; i < numsticks; i++)
+    {
+        const char  *stickname = SDL_JoystickName(i);
+        if ((envr != NULL) && (strcmp(envr, stickname) == 0))
+            favored = i;
+
+        sdldebug("Stick #%d: [%s]", i, stickname);
+    } /* for */
+
+    sdldebug("Using Stick #%d.", favored);
+    if ((envr == NULL) && (numsticks > 1))
+        sdldebug("Set BUILD_SDLJOYSTICK to one of the above names to change.");
+
+    joystick = SDL_JoystickOpen(favored);
+    if (joystick == NULL)
+    {
+        sdldebug("Joystick #%d failed to init: %s", favored, SDL_GetError());
+        return;
+    } /* if */
+
+    sdldebug("Joystick initialized. %d axes, %d buttons, %d hats, %d balls.",
+              SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
+              SDL_JoystickNumHats(joystick), SDL_JoystickNumBalls(joystick));
+
+    SDL_JoystickEventState(SDL_QUERY);
+} /* _joystick_init */
+
+
+void _joystick_deinit(void)
+{
+    if (joystick != NULL)
+    {
+        sdldebug("Closing joystick device...");
+        SDL_JoystickClose(joystick);
+        sdldebug("Joystick device closed. Deinitializing SDL subsystem...");
+        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+        sdldebug("SDL joystick subsystem deinitialized.");
+        joystick = NULL;
+    } /* if */
+} /* _joystick_deinit */
+
+
+int _joystick_update(void)
+{
+    if (joystick == NULL)
+        return(0);
+
+    SDL_JoystickUpdate();
+    return(1);
+} /* _joystick_update */
+
+
+int _joystick_axis(int axis)
+{
+    if (joystick == NULL)
+    {   
+        return(0);
+    }
+
+    return(SDL_JoystickGetAxis(joystick, axis));
+} /* _joystick_axis */
+
+int _joystick_hat(int hat)
+{
+    if (joystick == NULL)
+    {   
+        return(-1);
+    }
+
+    return(SDL_JoystickGetHat(joystick, hat));
+} /* _joystick_axis */
+
+int _joystick_button(int button)
+{
+    if (joystick == NULL)
+        return(0);
+
+    return(SDL_JoystickGetButton(joystick, button) != 0);
+} /* _joystick_button */
+
+
+uint8_t  _readlastkeyhit(void)
+{
+    return(lastkey);
+} /* _readlastkeyhit */
+
+
+static __inline void init_debugging(void)
+{
+    const char  *envr = getenv(BUILD_SDLDEBUG);
+
+    debug_hall_of_mirrors = (getenv(BUILD_HALLOFMIRRORS) != NULL);
+
+    if (_sdl_debug_file != NULL)
+    {
+        fclose(_sdl_debug_file);
+        _sdl_debug_file = NULL;
+    } /* if */
+
+    if (envr != NULL)
+    {
+        if (strcmp(envr, "-") == 0)
+	    _sdl_debug_file = stdout;
+        else
+            _sdl_debug_file = fopen(envr, "w");
+
+        if (_sdl_debug_file == NULL)
+            printf("BUILDSDL: -WARNING- Could not open debug file!\n");
+        else
+            setbuf(_sdl_debug_file, NULL);
+    } /* if */
+} /* init_debugging */
+
+
+#if (!defined __DATE__)
+#define __DATE__ "a long, int32_t time ago"
+#endif
+
+static __inline void output_sdl_versions(void)
+{
+    const SDL_version *linked_ver = SDL_Linked_Version();
+    SDL_version compiled_ver;
+
+    SDL_VERSION(&compiled_ver);
+
+    sdldebug("SDL display driver for the BUILD engine initializing.");
+    sdldebug("  sdl_driver.c by Ryan C. Gordon (icculus@clutteredmind.org).");
+    sdldebug("Compiled %s against SDL version %d.%d.%d ...", __DATE__,
+                compiled_ver.major, compiled_ver.minor, compiled_ver.patch);
+    sdldebug("Linked SDL version is %d.%d.%d ...",
+                linked_ver->major, linked_ver->minor, linked_ver->patch);
+} /* output_sdl_versions */
+
+
+/* lousy -ansi flag.  :) */
+static char  *string_dupe(const char  *str)
+{
+    char  *retval = malloc(strlen(str) + 1);
+    if (retval != NULL)
+        strcpy(retval, str);
+    return(retval);
+} /* string_dupe */
+
+
+void set_sdl_renderer(void)
+{
+    const char  *envr = getenv(BUILD_RENDERER);
+
+
+    if ((envr == NULL) || (strcmp(envr, ENVRSTR_RENDERER_SOFTWARE) == 0))
+        renderer = RENDERER_SOFTWARE;
+    else
+    {
+        fprintf(stderr,
+                "BUILDSDL: \"%s\" in the %s environment var is not available.\n",
+                envr, BUILD_RENDERER);
+        _exit(1);
+    } /* else */
+
+#ifdef __APPLE__
+    SDL_putenv("SDL_VIDEODRIVER=Quartz");
+#endif
+    
+    if (SDL_Init(SDL_INIT_VIDEO) == -1)
+    {
+		Error(EXIT_FAILURE, "BUILDSDL: SDL_Init() failed!\n"
+							"BUILDSDL: SDL_GetError() says \"%s\".\n", SDL_GetError());
+    } /* if */
+
+} /* set_sdl_renderer */
+
+
+static void init_renderer_names(void)
+{
+    memset((void *) renderer_name, '\0', sizeof (renderer_name));
+    renderer_name[RENDERER_SOFTWARE] = "RENDERER_SOFTWARE";
+    renderer_name[RENDERER_OPENGL3D] = "RENDERER_OPENGL3D";
+} /* init_renderer_names */
+
+
+
+//#include "mmulti_stable.h"
+void Setup_UnstableNetworking()
+{
+	nNetMode = 0;
+}
+
+void Setup_StableNetworking()
+{
+	nNetMode = 1;
+}
+
+
+void _platform_init(int argc, char  **argv, const char  *title, const char  *iconName)
+{
+    int i;
+	int64_t timeElapsed;
+	char  dummyString[4096];
+
+    _argc = argc;
+    _argv = argv;
+
+	// FIX_00061: "ERROR: Two players have the same random ID" too frequent cuz of internet windows times
+    TIMER_GetPlatformTicks(&timeElapsed);
+	srand(timeElapsed&0xFFFFFFFF);
+
+	Setup_UnstableNetworking();
+
+    // Look through the command line args
+    for(i = 0; i < argc; i++)
+    {
+        if(argv[i][0] == '-' )
+        {
+            if(strcmpi(argv[i], "-netmode_stable") == 0)
+            {
+                //fullscreen = 1;
+				//TODO:
+//TODO ( "[Todo: handle -netmode <int>]" )
+				Setup_StableNetworking();
+					
+            }
+        }
+    }
+
+	// Set up the correct renderer
+	// Becarfull setenv can't reach dll in VC++
+	// A way to proceed is to integrate the SDL libs
+	// in the exe instead.
+	
+    // FIX_00004: SDL.dll and SDL_Mixer.dll are now integrated within the exe
+    // (this also makes the Windib/Directx driver switching easier with SDL)		
+
+    // This requires to recompile the whole sdl and sdl mixer with the lib
+    // switch instead of the default dll switch.
+	if( BFullScreen )
+	{
+		putenv("SDL_VIDEODRIVER=directx");
+		printf("FullScreen Mode, trying directx\n");
+	}
+	else
+	{
+		putenv("SDL_VIDEODRIVER=windib");
+		printf("Window Mode, trying windib\n");
+	}
+
+	putenv("SDL_VIDEO_CENTERED=1");
+
+    init_renderer_names();
+
+    init_debugging();
+
+    if (title == NULL)
+        title = "BUILD";
+
+    if (iconName == NULL)
+        iconName = "BUILD";
+
+    titleNameLong = string_dupe(title);
+    titleNameShort = string_dupe(iconName);
+
+    sdl_flags = BFullScreen ? SDL_FULLSCREEN : 0;
+
+    sdl_flags |= SDL_HWPALETTE;
+   
+//	// These flags cause duke to exit on fullscreen
+//	/*
+	if(!BFullScreen)
+	{
+	//	sdl_flags |= SDL_HWSURFACE;   //!!!
+	//	sdl_flags |= SDL_DOUBLEBUF; //
+	}
+//	*/
+	
+	
+
+    memset(scancodes, '\0', sizeof (scancodes));
+    scancodes[SDLK_ESCAPE]          = 0x01;
+    scancodes[SDLK_1]               = 0x02;
+    scancodes[SDLK_2]               = 0x03;
+    scancodes[SDLK_3]               = 0x04;
+    scancodes[SDLK_4]               = 0x05;
+    scancodes[SDLK_5]               = 0x06;
+    scancodes[SDLK_6]               = 0x07;
+    scancodes[SDLK_7]               = 0x08;
+    scancodes[SDLK_8]               = 0x09;
+    scancodes[SDLK_9]               = 0x0A;
+    scancodes[SDLK_0]               = 0x0B;
+    scancodes[SDLK_MINUS]           = 0x0C; /* was 0x4A */
+    scancodes[SDLK_EQUALS]          = 0x0D; /* was 0x4E */
+    scancodes[SDLK_BACKSPACE]       = 0x0E;
+    scancodes[SDLK_TAB]             = 0x0F;
+    scancodes[SDLK_q]               = 0x10;
+    scancodes[SDLK_w]               = 0x11;
+    scancodes[SDLK_e]               = 0x12;
+    scancodes[SDLK_r]               = 0x13;
+    scancodes[SDLK_t]               = 0x14;
+    scancodes[SDLK_y]               = 0x15;
+    scancodes[SDLK_u]               = 0x16;
+    scancodes[SDLK_i]               = 0x17;
+    scancodes[SDLK_o]               = 0x18;
+    scancodes[SDLK_p]               = 0x19;
+    scancodes[SDLK_LEFTBRACKET]     = 0x1A;
+    scancodes[SDLK_RIGHTBRACKET]    = 0x1B;
+    scancodes[SDLK_RETURN]          = 0x1C;
+    scancodes[SDLK_LCTRL]           = 0x1D;
+    scancodes[SDLK_a]               = 0x1E;
+    scancodes[SDLK_s]               = 0x1F;
+    scancodes[SDLK_d]               = 0x20;
+    scancodes[SDLK_f]               = 0x21;
+    scancodes[SDLK_g]               = 0x22;
+    scancodes[SDLK_h]               = 0x23;
+    scancodes[SDLK_j]               = 0x24;
+    scancodes[SDLK_k]               = 0x25;
+    scancodes[SDLK_l]               = 0x26;
+    scancodes[SDLK_SEMICOLON]       = 0x27;
+    scancodes[SDLK_QUOTE]           = 0x28;
+    scancodes[SDLK_BACKQUOTE]       = 0x29;
+    scancodes[SDLK_LSHIFT]          = 0x2A;
+    scancodes[SDLK_BACKSLASH]       = 0x2B;
+    scancodes[SDLK_z]               = 0x2C;
+    scancodes[SDLK_x]               = 0x2D;
+    scancodes[SDLK_c]               = 0x2E;
+    scancodes[SDLK_v]               = 0x2F;
+    scancodes[SDLK_b]               = 0x30;
+    scancodes[SDLK_n]               = 0x31;
+    scancodes[SDLK_m]               = 0x32;
+    scancodes[SDLK_COMMA]           = 0x33;
+    scancodes[SDLK_PERIOD]          = 0x34;
+    scancodes[SDLK_SLASH]           = 0x35;
+    scancodes[SDLK_RSHIFT]          = 0x36;
+    scancodes[SDLK_KP_MULTIPLY]     = 0x37;
+    scancodes[SDLK_LALT]            = 0x38;
+    scancodes[SDLK_SPACE]           = 0x39;
+    scancodes[SDLK_CAPSLOCK]        = 0x3A;
+    scancodes[SDLK_F1]              = 0x3B;
+    scancodes[SDLK_F2]              = 0x3C;
+    scancodes[SDLK_F3]              = 0x3D;
+    scancodes[SDLK_F4]              = 0x3E;
+    scancodes[SDLK_F5]              = 0x3F;
+    scancodes[SDLK_F6]              = 0x40;
+    scancodes[SDLK_F7]              = 0x41;
+    scancodes[SDLK_F8]              = 0x42;
+    scancodes[SDLK_F9]              = 0x43;
+    scancodes[SDLK_F10]             = 0x44;
+    scancodes[SDLK_NUMLOCK]         = 0x45;
+    scancodes[SDLK_SCROLLOCK]       = 0x46;
+    scancodes[SDLK_KP7]             = 0x47;
+    scancodes[SDLK_KP8]             = 0x48;
+    scancodes[SDLK_KP9]             = 0x49;
+    scancodes[SDLK_KP_MINUS]        = 0x4A;
+    scancodes[SDLK_KP4]             = 0x4B;
+    scancodes[SDLK_KP5]             = 0x4C;
+    scancodes[SDLK_KP6]             = 0x4D;
+    scancodes[SDLK_KP_PLUS]         = 0x4E;
+    scancodes[SDLK_KP1]             = 0x4F;
+    scancodes[SDLK_KP2]             = 0x50;
+    scancodes[SDLK_KP3]             = 0x51;
+    scancodes[SDLK_KP0]             = 0x52;
+    scancodes[SDLK_KP_PERIOD]       = 0x53;
+    scancodes[SDLK_F11]             = 0x57;
+    scancodes[SDLK_F12]             = 0x58;
+    scancodes[SDLK_PAUSE]           = 0x59; /* SBF - technically incorrect */
+
+    scancodes[SDLK_KP_ENTER]        = 0xE01C;
+    scancodes[SDLK_RCTRL]           = 0xE01D;
+    scancodes[SDLK_KP_DIVIDE]       = 0xE035;
+    scancodes[SDLK_PRINT]           = 0xE037; /* SBF - technically incorrect */
+    scancodes[SDLK_SYSREQ]          = 0xE037; /* SBF - for windows... */
+    scancodes[SDLK_RALT]            = 0xE038;
+    scancodes[SDLK_HOME]            = 0xE047;
+    scancodes[SDLK_UP]              = 0xE048;
+    scancodes[SDLK_PAGEUP]          = 0xE049;
+    scancodes[SDLK_LEFT]            = 0xE04B;
+    scancodes[SDLK_RIGHT]           = 0xE04D;
+    scancodes[SDLK_END]             = 0xE04F;
+    scancodes[SDLK_DOWN]            = 0xE050;
+    scancodes[SDLK_PAGEDOWN]        = 0xE051;
+    scancodes[SDLK_INSERT]          = 0xE052;
+    scancodes[SDLK_DELETE]          = 0xE053;
+    
+    set_sdl_renderer();
+
+    output_sdl_versions();
+    output_driver_info();
+    
+
+	printf("Video Driver [directx or windib]? -> %s \n", SDL_VideoDriverName(dummyString, 20));
+
+} /* _platform_init */
+
+
+int setvesa(int32_t x, int32_t y)
+{
+	Error(EXIT_FAILURE, "setvesa() called in SDL driver\n");
+    return(0);
+} /* setvesa */
+
+
+// Capture BMP of the current frame
+int screencapture(char  *filename, uint8_t  inverseit)
+{
+//  FIX_00006: better naming system for screenshots + message when pic is taken. 
+//  Use ./screenshots folder. Screenshot code rerwritten. Faster and
+//  makes smaller files. Doesn't freeze or lag the game anymore.
+  
+	SDL_SaveBMP(surface, filename);  
+	return 0;
+} /* screencapture */
+
+
+void setvmode(int mode)
+{
+
+    if (mode == 0x3)  /* text mode. */
+    {
+        SDL_QuitSubSystem(SDL_INIT_VIDEO);
+        return;
+    } else
+        printf("setvmode(0x%x) is unsupported in SDL driver.\n", mode);
+
+} 
+
+int _setgamemode(uint8_t  davidoption, int32_t daxdim, int32_t daydim)
+{
+	int validated, i;
+	SDL_Surface     *image;
+	Uint32          colorkey;
+
+	// Install icon
+	image = SDL_LoadBMP_RW(SDL_RWFromMem(iconBMP, sizeof(iconBMP)), 1);
+	// image = SDL_LoadBMP("nuclear2.bmp");
+	// colorkey = SDL_MapRGB(image->format, 252, 254, 252); // to lookup idx in true color img
+	colorkey = 0; // index in this image to be transparent
+	SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
+	SDL_WM_SetIcon(image,NULL);
+
+    if (daxdim > MAXXDIM || daydim > MAXYDIM)
+    {
+		printf("%d x %d is too big. Changed to %d x %d\n", daxdim, daydim, MAXXDIM,MAXYDIM);
+	    daxdim = MAXXDIM;
+	    daydim = MAXYDIM;
+    } 
+
+	getvalidvesamodes();
+
+	validated = 0;
+	for(i=0; i<validmodecnt; i++)
+	{
+		if(validmodexdim[i] == daxdim && validmodeydim[i] == daydim)
+			validated = 1;
+	}
+
+	if(!validated)
+    {
+		printf("%d x %d unsupported. Changed to 640 x 480\n", daxdim, daydim);
+	    daxdim = 640;
+	    daydim = 480;
+    }
+
+    go_to_new_vid_mode((int) davidoption, daxdim, daydim);
+
+    qsetmode = 200;
+    last_render_ticks = getticks();
+
+    return(0);
+} /* setgamemode */
+
+
+static int get_dimensions_from_str(const char  *str, int32_t *_w, int32_t *_h)
+{
+    char  *xptr = NULL;
+    char  *ptr = NULL;
+    int32_t w = -1;
+    int32_t h = -1;
+
+    if (str == NULL)
+        return(0);
+
+    xptr = strchr(str, 'x');
+    if (xptr == NULL)
+        return(0);
+
+    w = strtol(str, &ptr, 10);
+    if (ptr != xptr)
+        return(0);
+
+    xptr++;
+    h = strtol(xptr, &ptr, 10);
+    if ( (*xptr == '\0') || (*ptr != '\0') )
+        return(0);
+
+    if ((w <= 1) || (h <= 1))
+        return(0);
+
+    if (_w != NULL)
+        *_w = w;
+
+    if (_h != NULL)
+        *_h = h;
+
+    return(1);
+} /* get_dimensions_from_str */
+
+
+static __inline void get_max_screen_res(int32_t *max_w, int32_t *max_h)
+{
+    int32_t w = DEFAULT_MAXRESWIDTH;
+    int32_t h = DEFAULT_MAXRESHEIGHT;
+    const char  *envr = getenv(BUILD_MAXSCREENRES);
+
+    if (envr != NULL)
+    {
+        if (!get_dimensions_from_str(envr, &w, &h))
+        {
+            sdldebug("User's resolution ceiling [%s] is bogus!", envr);
+            w = DEFAULT_MAXRESWIDTH;
+            h = DEFAULT_MAXRESHEIGHT;
+        } /* if */
+    } /* if */
+
+    if (max_w != NULL)
+        *max_w = w;
+
+    if (max_h != NULL)
+        *max_h = h;
+} /* get_max_screen_res */
+
+
+static void add_vesa_mode(const char  *typestr, int w, int h)
+{
+    sdldebug("Adding %s resolution (%dx%d).", typestr, w, h);
+    validmode[validmodecnt] = validmodecnt;
+    validmodexdim[validmodecnt] = w;
+    validmodeydim[validmodecnt] = h;
+    validmodecnt++;
+} /* add_vesa_mode */
+
+
+/* Let the user specify a specific mode via environment variable. */
+static __inline void add_user_defined_resolution(void)
+{
+    int32_t w;
+    int32_t h;
+    const char  *envr = getenv(BUILD_USERSCREENRES);
+
+    if (envr == NULL)
+        return;
+
+    if (get_dimensions_from_str(envr, &w, &h))
+        add_vesa_mode("user defined", w, h);
+    else
+        sdldebug("User defined resolution [%s] is bogus!", envr);
+} /* add_user_defined_resolution */
+
+
+static __inline SDL_Rect **get_physical_resolutions(void)
+{
+    const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
+    SDL_Rect **modes = SDL_ListModes(vidInfo->vfmt, sdl_flags | SDL_FULLSCREEN);
+    if (modes == NULL)
+    {
+        sdl_flags &= ~SDL_FULLSCREEN;
+        modes = SDL_ListModes(vidInfo->vfmt, sdl_flags); /* try without fullscreen. */
+        if (modes == NULL)
+            modes = (SDL_Rect **) -1;  /* fuck it. */
+    } /* if */
+
+    if (modes == (SDL_Rect **) -1)
+        sdldebug("Couldn't get any physical resolutions.");
+    else
+    {
+        sdldebug("Highest physical resolution is (%dx%d).",
+                  modes[0]->w, modes[0]->h);
+    } /* else */
+
+    return(modes);
+} /* get_physical_resolutions */
+
+
+static void remove_vesa_mode(int index, const char  *reason)
+{
+    int i;
+
+    assert(index < validmodecnt);
+    sdldebug("Removing resolution #%d, %dx%d [%s].",
+              index, validmodexdim[index], validmodeydim[index], reason);
+
+    for (i = index; i < validmodecnt - 1; i++)
+    {
+        validmode[i] = validmode[i + 1];
+        validmodexdim[i] = validmodexdim[i + 1];
+        validmodeydim[i] = validmodeydim[i + 1];
+    } /* for */
+
+    validmodecnt--;
+} /* remove_vesa_mode */
+
+
+static __inline void cull_large_vesa_modes(void)
+{
+    int32_t max_w;
+    int32_t max_h;
+    int i;
+
+    get_max_screen_res(&max_w, &max_h);
+    sdldebug("Setting resolution ceiling to (%ldx%ld).", max_w, max_h);
+
+    for (i = 0; i < validmodecnt; i++)
+    {
+        if ((validmodexdim[i] > max_w) || (validmodeydim[i] > max_h))
+        {
+            remove_vesa_mode(i, "above resolution ceiling");
+            i--;  /* list shrinks. */
+        } /* if */
+    } /* for */
+} /* cull_large_vesa_modes */
+
+
+static __inline void cull_duplicate_vesa_modes(void)
+{
+    int i;
+    int j;
+
+    for (i = 0; i < validmodecnt; i++)
+    {
+        for (j = i + 1; j < validmodecnt; j++)
+        {
+            if ( (validmodexdim[i] == validmodexdim[j]) &&
+                 (validmodeydim[i] == validmodeydim[j]) )
+            {
+                remove_vesa_mode(j, "duplicate");
+                j--;  /* list shrinks. */
+            } /* if */
+        } /* for */
+    } /* for */
+} /* cull_duplicate_vesa_modes */
+
+
+#define swap_macro(tmp, x, y) { tmp = x; x = y; y = tmp; }
+
+/* be sure to call cull_duplicate_vesa_modes() before calling this. */
+static __inline void sort_vesa_modelist(void)
+{
+    int i;
+    int sorted;
+    int32_t tmp;
+
+    do
+    {
+        sorted = 1;
+        for (i = 0; i < validmodecnt - 1; i++)
+        {
+            if ( (validmodexdim[i] >= validmodexdim[i+1]) &&
+                 (validmodeydim[i] >= validmodeydim[i+1]) )
+            {
+                sorted = 0;
+                swap_macro(tmp, validmode[i], validmode[i+1]);
+                swap_macro(tmp, validmodexdim[i], validmodexdim[i+1]);
+                swap_macro(tmp, validmodeydim[i], validmodeydim[i+1]);
+            } /* if */
+        } /* for */
+    } while (!sorted);
+} /* sort_vesa_modelist */
+
+
+static __inline void cleanup_vesa_modelist(void)
+{
+    cull_large_vesa_modes();
+    cull_duplicate_vesa_modes();
+    sort_vesa_modelist();
+} /* cleanup_vesa_modelist */
+
+
+static __inline void output_vesa_modelist(void)
+{
+    char  buffer[256];
+    char  numbuf[20];
+    int i;
+
+    if (!_sdl_debug_file)
+        return;
+
+    buffer[0] = '\0';
+
+    for (i = 0; i < validmodecnt; i++)
+    {
+        sprintf(numbuf, " (%dx%d)",(int32_t) validmodexdim[i], (int32_t) validmodeydim[i]);
+
+        if ( (strlen(buffer) + strlen(numbuf)) >= (sizeof (buffer) - 1) )
+            strcpy(buffer + (sizeof (buffer) - 5), " ...");
+        else
+            strcat(buffer, numbuf);
+    } /* for */
+
+    sdldebug("Final sorted modelist:%s", buffer);
+} /* output_vesa_modelist */
+
+
+void getvalidvesamodes(void)
+{
+    static int already_checked = 0;
+    int i;
+    SDL_Rect **modes = NULL;
+    int stdres[][2] = {
+                        {320, 200}, {640, 350}, {640, 480},
+                        {800, 600}, {1024, 768}
+                      };
+
+    if (already_checked)
+        return;
+
+    already_checked = 1;
+   	validmodecnt = 0;
+    vidoption = 1;  /* !!! tmp */
+
+        /* fill in the standard resolutions... */
+    for (i = 0; i < sizeof (stdres) / sizeof (stdres[0]); i++)
+        add_vesa_mode("standard", stdres[i][0], stdres[i][1]);
+
+         /* Anything the hardware can specifically do is added now... */
+    modes = get_physical_resolutions();
+    for (i = 0; (modes != (SDL_Rect **) -1) && (modes[i] != NULL); i++)
+        add_vesa_mode("physical", modes[i]->w, modes[i]->h);
+
+        /* Now add specific resolutions that the user wants... */
+    add_user_defined_resolution();
+
+        /* get rid of dupes and bogus resolutions... */
+    cleanup_vesa_modelist();
+
+        /* print it out for debugging purposes... */
+    output_vesa_modelist();
+} /* getvalidvesamodes */
+
+
+int VBE_setPalette(int32_t start, int32_t num, uint8_t  *palettebuffer)
+/*
+ * (From Ken's docs:)
+ *   Set (num) palette palette entries starting at (start)
+ *   palette entries are in a 4-byte format in this order:
+ *       0: Blue (0-63)
+ *       1: Green (0-63)
+ *       2: Red (0-63)
+ *       3: Reserved
+ *
+ * Naturally, the bytes are in the reverse order that SDL wants them...
+ *  More importantly, SDL wants the color elements in a range from 0-255,
+ *  so we do a conversion.
+ */
+{
+    SDL_Color fmt_swap[256];
+    SDL_Color *sdlp = &fmt_swap[start];
+    uint8_t  *p = palettebuffer;
+    int i;
+    assert( (start + num) <= (sizeof (fmt_swap) / sizeof (SDL_Color)) );
+
+    for (i = 0; i < num; i++)
+    {
+        sdlp->b = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+        sdlp->g = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+        sdlp->r = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+        sdlp->unused = *p++;   /* This byte is unused in BUILD, too. */
+        sdlp++;
+    } /* for */
+
+    return(SDL_SetColors(surface, fmt_swap, start, num));
+} /* VBE_setPalette */
+
+
+int VBE_getPalette(int32_t start, int32_t num, uint8_t  *palettebuffer)
+{
+    SDL_Color *sdlp = surface->format->palette->colors + start;
+    uint8_t  *p = palettebuffer + (start * 4);
+    int i;
+
+    for (i = 0; i < num; i++)
+    {
+        *p++ = (Uint8) ((((float) sdlp->b) / 255.0) * 63.0);
+        *p++ = (Uint8) ((((float) sdlp->g) / 255.0) * 63.0);
+        *p++ = (Uint8) ((((float) sdlp->r) / 255.0) * 63.0);
+        *p++ = sdlp->unused;   /* This byte is unused in both SDL and BUILD. */
+        sdlp++;
+    } /* for */
+
+    return(1);
+} /* VBE_getPalette */
+
+
+void _uninitengine(void)
+{
+   SDL_QuitSubSystem(SDL_INIT_VIDEO);
+} /* _uninitengine */
+
+
+
+
+int setupmouse(void)
+{
+
+	SDL_Event event;
+
+    if (surface == NULL)
+        return(0);
+
+    SDL_WM_GrabInput(SDL_GRAB_ON);
+    SDL_ShowCursor(0);
+
+    mouse_relative_x = mouse_relative_y = 0;
+
+        /*
+         * this global usually gets set by BUILD, but it's a one-shot
+         *  deal, and we may not have an SDL surface at that point. --ryan.
+         */
+    moustat = 1;
+
+	// FIX_00063: Duke's angle changing or incorrect when using toggle fullscreen/window mode
+	while(SDL_PollEvent(&event)); // Empying the various pending events (especially the mouse one)
+
+	//SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
+    return(1);
+} /* setupmouse */
+
+
+void readmousexy(short *x, short *y)
+{
+    if (x) *x = mouse_relative_x << 2;
+    if (y) *y = mouse_relative_y << 2;
+
+    mouse_relative_x = mouse_relative_y = 0;
+} /* readmousexy */
+
+
+void readmousebstatus(short *bstatus)
+{
+    if (bstatus)
+        *bstatus = mouse_buttons;
+
+    // special wheel treatment: make it like a button click
+    if(mouse_buttons&8) mouse_buttons ^= 8;
+    if(mouse_buttons&16) mouse_buttons ^= 16;
+
+} /* readmousebstatus */
+
+
+static uint8_t  mirrorcolor = 0;
+
+void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h)
+{
+    if (renderer == RENDERER_SOFTWARE)
+        SDL_UpdateRect(surface, x, y, w, h);
+} /* _updatescreenrect */
+
+
+void _nextpage(void)
+{
+    Uint32 ticks;
+
+    _handle_events();
+
+    if (renderer == RENDERER_SOFTWARE)
+    {
+		// FIX_00085: Optimized Video driver. FPS increases by +20%.
+        // SDL_Flip(surface);
+		SDL_UpdateRect(surface, 0, 0, 0, 0);
+    }
+
+
+    if ((debug_hall_of_mirrors) && (qsetmode == 200) && (frameplace))
+    {
+        memset((void *) frameplace, mirrorcolor, surface->w * surface->h);
+        mirrorcolor++;
+    } /* if */
+
+    ticks = getticks();
+    total_render_time = (ticks - last_render_ticks);
+    if (total_render_time > 1000)
+    {
+        total_rendered_frames = 0;
+        total_render_time = 1;
+        last_render_ticks = ticks;
+    } /* if */
+    total_rendered_frames++;
+} /* _nextpage */
+
+
+uint8_t  readpixel(int32_t offset)
+{
+    return( *((uint8_t  *) offset) );
+} /* readpixel */
+
+void drawpixel(int32_t offset, uint8_t  pixel)
+{
+    *((uint8_t  *) offset) = pixel;
+} /* drawpixel */
+
+
+/* !!! These are incorrect. */
+void drawpixels(int32_t offset, uint16_t pixels)
+{
+    Uint8 *surface_end;
+    Uint16 *pos;
+
+                Error(EXIT_FAILURE, "Blargh!\n");
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_LockSurface(surface);
+
+    surface_end = (((Uint8 *) surface->pixels) + (surface->w * surface->h)) - 2;
+    pos = (Uint16 *) (((Uint8 *) surface->pixels) + offset);
+    if ((pos >= (Uint16 *) surface->pixels) && (pos < (Uint16 *) surface_end))
+        *pos = pixels;
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_UnlockSurface(surface);
+} /* drawpixels */
+
+
+void drawpixelses(int32_t offset, unsigned int pixelses)
+{
+    Uint8 *surface_end;
+    Uint32 *pos;
+
+                Error(EXIT_FAILURE, "Blargh!\n");
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_LockSurface(surface);
+
+    surface_end = (((Uint8 *)surface->pixels) + (surface->w * surface->h)) - 2;
+    pos = (Uint32 *) (((Uint8 *) surface->pixels) + offset);
+    if ((pos >= (Uint32 *) surface->pixels) && (pos < (Uint32 *) surface_end))
+        *pos = pixelses;
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_UnlockSurface(surface);
+} /* drawpixelses */
+
+
+/* Fix this up The Right Way (TM) - DDOI */
+void setcolor16(int col)
+{
+	drawpixel_color = col;
+}
+
+void drawpixel16(int32_t offset)
+{
+    drawpixel(((int32_t) surface->pixels + offset), drawpixel_color);
+} /* drawpixel16 */
+
+
+void fillscreen16(int32_t offset, int32_t color, int32_t blocksize)
+{
+    Uint8 *surface_end;
+    Uint8 *wanted_end;
+    Uint8 *pixels;
+
+	if (SDL_MUSTLOCK(surface))
+        SDL_LockSurface(surface);
+
+    pixels = get_framebuffer();
+
+    /* Make this function pageoffset aware - DDOI */
+    if (!pageoffset) { 
+	    offset = offset << 3;
+	    offset += 640*336;
+    }
+
+    surface_end = (pixels + (surface->w * surface->h)) - 1;
+    wanted_end = (pixels + offset) + blocksize;
+
+    if (offset < 0)
+        offset = 0;
+
+    if (wanted_end > surface_end)
+        blocksize = ((uint32_t) surface_end) - ((uint32_t) pixels + offset);
+
+    memset(pixels + offset, (int) color, blocksize);
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_UnlockSurface(surface);
+
+    _nextpage();
+} /* fillscreen16 */
+
+
+/* Most of this line code is taken from Abrash's "Graphics Programming Blackbook".
+Remember, sharing code is A Good Thing. AH */
+static __inline void DrawHorizontalRun (uint8_t  **ScreenPtr, int XAdvance, int RunLength, uint8_t  Color)
+{
+    int i;
+    uint8_t  *WorkingScreenPtr = *ScreenPtr;
+
+    for (i=0; i<RunLength; i++)
+    {
+        *WorkingScreenPtr = Color;
+        WorkingScreenPtr += XAdvance;
+    }
+    WorkingScreenPtr += surface->w;
+    *ScreenPtr = WorkingScreenPtr;
+}
+
+static __inline void DrawVerticalRun (uint8_t  **ScreenPtr, int XAdvance, int RunLength, uint8_t  Color)
+{
+    int i;
+    uint8_t  *WorkingScreenPtr = *ScreenPtr;
+
+    for (i=0; i<RunLength; i++)
+    {
+      	*WorkingScreenPtr = Color;
+    	WorkingScreenPtr += surface->w;
+    }
+    WorkingScreenPtr += XAdvance;
+    *ScreenPtr = WorkingScreenPtr;
+}
+
+void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t  Color)
+{
+    int Temp, AdjUp, AdjDown, ErrorTerm, XAdvance, XDelta, YDelta;
+    int WholeStep, InitialPixelCount, FinalPixelCount, i, RunLength;
+    uint8_t  *ScreenPtr;
+    int32_t dx, dy;
+
+    if (SDL_MUSTLOCK(surface))
+        SDL_LockSurface(surface);
+
+	dx = XEnd-XStart; dy = YEnd-YStart;
+	if (dx >= 0)
+	{
+		if ((XStart > 639) || (XEnd < 0)) return;
+		if (XStart < 0) { if (dy) YStart += scale(0-XStart,dy,dx); XStart = 0; }
+		if (XEnd > 639) { if (dy) YEnd += scale(639-XEnd,dy,dx); XEnd = 639; }
+	}
+	else
+	{
+		if ((XEnd > 639) || (XStart < 0)) return;
+		if (XEnd < 0) { if (dy) YEnd += scale(0-XEnd,dy,dx); XEnd = 0; }
+		if (XStart > 639) { if (dy) YStart += scale(639-XStart,dy,dx); XStart = 639; }
+	}
+	if (dy >= 0)
+	{
+		if ((YStart >= ydim16) || (YEnd < 0)) return;
+		if (YStart < 0) { if (dx) XStart += scale(0-YStart,dx,dy); YStart = 0; }
+		if (YEnd >= ydim16) { if (dx) XEnd += scale(ydim16-1-YEnd,dx,dy); YEnd = ydim16-1; }
+	}
+	else
+	{
+		if ((YEnd >= ydim16) || (YStart < 0)) return;
+		if (YEnd < 0) { if (dx) XEnd += scale(0-YEnd,dx,dy); YEnd = 0; }
+		if (YStart >= ydim16) { if (dx) XStart += scale(ydim16-1-YStart,dx,dy); YStart = ydim16-1; }
+	}
+
+	/* Make sure the status bar border draws correctly - DDOI */
+	if (!pageoffset) { YStart += 336; YEnd += 336; }
+
+    /* We'll always draw top to bottom */
+    if (YStart > YEnd) {
+        Temp = YStart;
+        YStart = YEnd;
+        YEnd = Temp;
+        Temp = XStart;
+        XStart = XEnd;
+        XEnd = Temp;
+    }
+
+    /* Point to the bitmap address first pixel to draw */
+    ScreenPtr = (uint8_t  *) (get_framebuffer()) + XStart + (surface->w * YStart);
+
+    /* Figure out whether we're going left or right, and how far we're going horizontally */
+    if ((XDelta = XEnd - XStart) < 0)
+    {
+        XAdvance = (-1);
+        XDelta = -XDelta;
+    } else {
+        XAdvance = 1;
+    }
+
+    /* Figure out how far we're going vertically */
+    YDelta = YEnd - YStart;
+
+    /* Special cases: Horizontal, vertical, and diagonal lines */
+    if (XDelta == 0)
+    {
+        for (i=0; i <= YDelta; i++)
+        {
+            *ScreenPtr = Color;
+            ScreenPtr += surface->w;
+        }
+
+        UNLOCK_SURFACE_AND_RETURN;
+    }
+    if (YDelta == 0)
+    {
+    	for (i=0; i <= XDelta; i++)
+    	{
+      	    *ScreenPtr = Color;
+    	    ScreenPtr += XAdvance;
+    	}
+        UNLOCK_SURFACE_AND_RETURN;
+    }
+    if (XDelta == YDelta)
+    {
+    	for (i=0; i <= XDelta; i++)
+        {
+            *ScreenPtr = Color;
+            ScreenPtr += XAdvance + surface->w;
+        }
+        UNLOCK_SURFACE_AND_RETURN;
+    }
+
+    /* Determine whether the line is X or Y major, and handle accordingly */
+    if (XDelta >= YDelta) /* X major line */
+    {
+        WholeStep = XDelta / YDelta;
+        AdjUp = (XDelta % YDelta) * 2;
+        AdjDown = YDelta * 2;
+        ErrorTerm = (XDelta % YDelta) - (YDelta * 2);
+
+        InitialPixelCount = (WholeStep / 2) + 1;
+        FinalPixelCount = InitialPixelCount;
+
+        if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount--;
+        if ((WholeStep & 0x01) != 0) ErrorTerm += YDelta;
+
+        DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
+
+        for (i=0; i<(YDelta-1); i++)
+        {
+            RunLength = WholeStep;
+            if ((ErrorTerm += AdjUp) > 0)
+            {
+        	RunLength ++;
+        	ErrorTerm -= AdjDown;
+            }
+
+            DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
+         }
+
+         DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
+
+         UNLOCK_SURFACE_AND_RETURN;
+    } else {	/* Y major line */
+    	WholeStep = YDelta / XDelta;
+    	AdjUp = (YDelta % XDelta) * 2;
+    	AdjDown = XDelta * 2;
+        ErrorTerm = (YDelta % XDelta) - (XDelta * 2);
+        InitialPixelCount = (WholeStep / 2) + 1;
+        FinalPixelCount = InitialPixelCount;
+
+        if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount --;
+        if ((WholeStep & 0x01) != 0) ErrorTerm += XDelta;
+
+        DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
+
+        for (i=0; i<(XDelta-1); i++)
+        {
+            RunLength = WholeStep;
+            if ((ErrorTerm += AdjUp) > 0)
+            {
+            	RunLength ++;
+            	ErrorTerm -= AdjDown;
+            }
+
+            DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
+        }
+
+        DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
+        UNLOCK_SURFACE_AND_RETURN;
+     }
+} /* drawline16 */
+
+
+void clear2dscreen(void)
+{
+    SDL_Rect rect;
+
+    rect.x = rect.y = 0;
+    rect.w = surface->w;
+
+	if (qsetmode == 350)
+        rect.h = 350;
+	else if (qsetmode == 480)
+	{
+		if (ydim16 <= 336)
+            rect.h = 336;
+        else
+            rect.h = 480;
+	} /* else if */
+
+    SDL_FillRect(surface, &rect, 0);
+} /* clear2dscreen */
+
+
+void _idle(void)
+{
+    if (surface != NULL)
+        _handle_events();
+    SDL_Delay(1);
+} /* _idle */
+
+void *_getVideoBase(void)
+{
+    return((void *) surface->pixels);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+//  TIMER
+//=================================================================================================
+
+
+
+
+// FIX_00007: game speed corrected. The game speed is now as the real
+// DOS duke3d. Unloading a full 200 bullet pistol must take 45.1 sec.
+// SDL timer was not fast/accurate enough and was slowing down the gameplay,
+// so bad
+
+
+static int64_t timerfreq=0;
+static int32_t timerlastsample=0;
+static int timerticspersec=0;
+static void (*usertimercallback)(void) = NULL;
+
+//  This timer stuff is all Ken's idea.
+
+//
+// installusertimercallback() -- set up a callback function to be called when the timer is fired
+//
+void (*installusertimercallback(void (*callback)(void)))(void)
+{
+	void (*oldtimercallback)(void);
+
+	oldtimercallback = usertimercallback;
+	usertimercallback = callback;
+
+	return oldtimercallback;
+}
+
+
+/*
+ inittimer() -- initialise timer
+ FCS: The tickspersecond parameter is a ratio value that helps replicating
+      oldschool DOS tick per seconds.
+ 
+      The way the timer work is:
+      float newSystemTickPerSecond = [0,1]
+      tickPerSecond on a DOS system = tickspersecond * newSystemTickPerSecond ;
+*/
+
+int inittimer(int tickspersecond)
+{
+	int64_t t;
+	
+    
+	if (timerfreq) return 0;	// already installed
+
+	printf("Initialising timer, with tickPerSecond=%d\n",tickspersecond);
+
+	// OpenWatcom seems to want us to query the value into a local variable
+	// instead of the global 'timerfreq' or else it gets pissed with an
+	// access violation
+	if (!TIMER_GetPlatformTicksInOneSecond(&t)) {
+		printf("Failed fetching timer frequency\n");
+		return -1;
+	}
+	timerfreq = t;
+	timerticspersec = tickspersecond;
+	TIMER_GetPlatformTicks(&t);
+	timerlastsample = (int32_t)(t*timerticspersec / timerfreq);
+
+	usertimercallback = NULL;
+    
+	return 0;
+}
+
+//
+// uninittimer() -- shut down timer
+//
+void uninittimer(void)
+{
+	if (!timerfreq) return;
+
+	timerfreq=0;
+	timerticspersec = 0;
+}
+
+//
+// sampletimer() -- update totalclock
+//
+void sampletimer(void)
+{
+	int64_t i;
+	int32_t n;
+	
+	if (!timerfreq) return;
+
+	TIMER_GetPlatformTicks(&i);
+    
+    
+	n = (int32_t)(i*timerticspersec / timerfreq) - timerlastsample;
+	if (n>0) {
+		totalclock += n;
+		timerlastsample += n;
+	}
+
+	if (usertimercallback) for (; n>0; n--) usertimercallback();
+}
+
+
+/*
+   getticks() -- returns the windows ticks count
+   FCS: This seeems to be only used in the multiplayer code
+*/
+uint32_t getticks(void)
+{
+	int64_t i;
+	TIMER_GetPlatformTicks(&i);
+	return (uint32_t)(i*(int32_t)(1000)/timerfreq);
+}
+
+
+//
+// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
+//
+int gettimerfreq(void)
+{
+	return timerticspersec;
+}
+
+// ****************************************************************************
+
+//static Uint32 _timer_catcher(Uint32 interval, void *bleh)
+//{
+//    timerhandler();
+//    return(1);
+//} /* _timer_catcher */
+//
+//
+//void inittimer(void)
+//{
+//    SDL_ClearError();
+//    primary_timer = SDL_AddTimer(1000 / PLATFORM_TIMER_HZ, _timer_catcher, NULL);
+//    if (primary_timer == NULL)
+//    {
+//        fprintf(stderr, "BUILDSDL: -ERROR- Problem initializing primary timer!\n");
+//        fprintf(stderr, "BUILDSDL:  Reason: [%s]\n", SDL_GetError());
+//        Error(EXIT_FAILURE, "");
+//    } /* if */
+//}
+//
+//
+//void uninittimer(void)
+//{
+//    if (primary_timer != NULL)
+//    {
+//        SDL_RemoveTimer(primary_timer);
+//        primary_timer = NULL;
+//    } /* if */
+//}
+
+void initkeys(void)
+{
+    /* does nothing in SDL. Key input handling is set up elsewhere. */
+    /* !!! why not here? */
+}
+
+void uninitkeys(void)
+{
+    /* does nothing in SDL. Key input handling is set up elsewhere. */
+}
+
+
+//unsigned int32_t getticks(void)
+//{
+//    return(SDL_GetTicks());
+//} /* getticks */
+
+
+//Timer on windows 98 used to be really poor but now it is very accurate
+// We can just use what SDL uses, no need for QueryPerformanceFrequency or QueryPerformanceCounter
+// (which I bet SDL is using anyway).
+#if 0//PLATFORM_WIN32 
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
+{
+    QueryPerformanceFrequency((LARGE_INTEGER*)t);
+    return 1;
+}
+
+void TIMER_GetPlatformTicks(int64_t* t)
+{
+    QueryPerformanceCounter((LARGE_INTEGER*)t);
+}
+#else
+//FCS: Let's try to use SDL again: Maybe SDL library is accurate enough now.
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
+{
+    *t = 1000;
+    return 1;
+}
+    
+void TIMER_GetPlatformTicks(int64_t* t)
+{
+    *t = SDL_GetTicks();
+}
+#endif
+/* end of sdl_driver.c ... */
+
--- a/Engine/src/display.h
+++ b/Engine/src/display.h
@@ -11,8 +11,8 @@
 #include "platform.h"
 
 /* set these in your _platform_init() implementation. */
-extern int _argc;
-extern char  **_argv;
+int _argc;
+char  **_argv;
 
 /* !!! gads, look at all the namespace polution... */
 extern int32_t xres, yres, bytesperline, imageSize, maxpages;
@@ -24,10 +24,11 @@
 extern int32_t oxdimen, oviewingrange, oxyaspect;
 extern int32_t curbrightness;
 extern int32_t qsetmode;
-extern int32_t frameplace, frameoffset, pageoffset, ydim16;
+extern int32_t frameplace, pageoffset, ydim16;
+extern int32_t frameoffset;
 extern uint8_t  textfont[1024], smalltextfont[1024];
 extern uint8_t  pow2char[8];
-extern volatile int32_t stereomode, visualpage, activepage, whiteband, blackband;
+extern int32_t stereomode, visualpage, activepage, whiteband, blackband;
 extern int32_t searchx, searchy;
 extern int32_t wx1, wy1, wx2, wy2, ydimen;
 extern int32_t xdimen, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
--- a/Engine/src/draw.c
+++ b/Engine/src/draw.c
@@ -41,12 +41,12 @@
 
 static uint8_t machxbits_al;
 static uint8_t machxbits_bl;
-static int32_t machxbits_ecx;
-void sethlinesizes(int32_t i1, int32_t i2, int32_t i3)
+static uint8_t * machxbits_ecx;
+void sethlinesizes(int32_t i1, int32_t i2, uint8_t * textureAddress)
 {
     machxbits_al = i1;
     machxbits_bl = i2;
-    machxbits_ecx = i3;
+    machxbits_ecx = textureAddress;
 } 
 
 
@@ -102,7 +102,7 @@
 } 
 
 
-void rhlineasm4(int32_t i1, int32_t i2, int32_t i3, uint32_t i4, uint32_t i5, int32_t dest)
+void rhlineasm4(int32_t i1, uint8_t* texture, int32_t i3, uint32_t i4, uint32_t i5, int32_t dest)
 {
     uint32_t ebp = dest - i1;
     uint32_t rmach6b = ebp-1;
@@ -115,12 +115,16 @@
 		
 		
 
-	    i3 = ((i3&0xffffff00)|(*((uint8_t *)i2)));
+	    i3 = ((i3&0xffffff00)|(*texture));
 	    i4 -= rmach_eax;
 	    ebp = (((i4+rmach_eax) < i4) ? -1 : 0);
 	    i5 -= rmach_ebx;
-	    if ((i5 + rmach_ebx) < i5) i2 -= (rmach_ecx+1);
-	    else i2 -= rmach_ecx;
+        
+	    if ((i5 + rmach_ebx) < i5)
+            texture -= (rmach_ecx+1);
+	    else
+            texture -= rmach_ecx;
+        
 	    ebp &= rmach_esi;
 	    i1 = ((i1&0xffffff00)|(((uint8_t *)i3)[rmach_edx]));
 
@@ -127,7 +131,7 @@
 		if (pixelsAllowed-- > 0)
 			 ((uint8_t *)rmach6b)[numPixels] = (i1&0xff);
 
-	    i2 -= ebp;
+	    texture -= ebp;
 	    numPixels--;
     } while (numPixels);
 }
@@ -208,11 +212,10 @@
 static uint8_t  mach3_al;
 
 //FCS:  RENDER TOP AND BOTTOM COLUMN
-int32_t prevlineasm1(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, int32_t i6)
+int32_t prevlineasm1(int32_t i1, int32_t i2, int32_t i3, int32_t i4, uint8_t  *source, uint8_t  *dest)
 {
-    uint8_t  *source = (uint8_t  *)i5;
-    uint8_t  *dest = (uint8_t  *)i6;
 
+
     if (i3 == 0)
     {
 		if (!RENDER_DRAW_TOP_AND_BOTTOM_COLUMN)
@@ -231,13 +234,13 @@
 
 	    return i1;
     } else {
-	    return vlineasm1(i1,i2,i3,i4,i5,i6);
+	    return vlineasm1(i1,i2,i3,i4,source,dest);
     }
 }
 
 
 //FCS: This is used to draw wall border vertical lines
-int32_t vlineasm1(int32_t vince, int32_t palookupoffse, int32_t numPixels, int32_t vplce, int32_t bufplce, int32_t frameBufferDestination)
+int32_t vlineasm1(int32_t vince, int32_t palookupoffse, int32_t numPixels, int32_t vplce, uint8_t* texture, uint8_t  * frameBufferDestination)
 {
     uint32_t temp;
     uint8_t  *dest = (uint8_t  *)frameBufferDestination;
@@ -253,7 +256,7 @@
 
 	    temp = ((uint32_t)vplce) >> mach3_al;
         
-	    temp = ((uint8_t  *)bufplce)[temp];
+	    temp = texture[temp];
       
 		if (pixelsAllowed-- > 0)
 			*dest = ((uint8_t *)palookupoffse)[temp];
@@ -720,14 +723,14 @@
 	transrev = type;
 }
 
-static int32_t mmach_eax;
+static uint8_t  * textureData;
 static int32_t mmach_asm3;
 static int32_t mmach_asm1;
 static int32_t mmach_asm2;
 
-void mhline(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, uint8_t* dest)
+void mhline(uint8_t  * texture, int32_t i2, int32_t i3, int32_t i4, int32_t i5, uint8_t* dest)
 {
-    mmach_eax = i1;
+    textureData = texture;
     mmach_asm3 = asm3;
     mmach_asm1 = asm1;
     mmach_asm2 = asm2;
@@ -746,7 +749,7 @@
     {
 	    ebx = i2 >> mshift_al;
 	    ebx = shld (ebx, (uint32_t)i5, mshift_bl);
-	    colorIndex = ((uint8_t  *)mmach_eax)[ebx];
+	    colorIndex = textureData[ebx];
 
         //Skip transparent color.
 		if ((colorIndex&0xff) != 0xff){
--- a/Engine/src/draw.h
+++ b/Engine/src/draw.h
@@ -28,12 +28,12 @@
 extern int16_t  globalshiftval;
 extern int32_t vplce[4], vince[4], palookupoffse[4], bufplce[4];
     
-void sethlinesizes(int32_t,int32_t,int32_t);
+void sethlinesizes(int32_t,int32_t,uint8_t *);
 
 
 void hlineasm4(int32_t,int32_t,uint32_t,uint32_t,int32_t);
 void setuprhlineasm4(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
-void rhlineasm4(int32_t,int32_t,int32_t,uint32_t,uint32_t,int32_t);
+void rhlineasm4(int32_t,uint8_t*,int32_t,uint32_t,uint32_t,int32_t);
 void setuprmhlineasm4(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
 void rmhlineasm4(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
 
@@ -40,8 +40,8 @@
 
 void setBytesPerLine(int32_t);
 void fixtransluscence(uint8_t*);
-int32_t prevlineasm1(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
-int32_t vlineasm1(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
+int32_t prevlineasm1(int32_t,int32_t,int32_t,int32_t,uint8_t  *,uint8_t  *);
+int32_t vlineasm1(int32_t,int32_t,int32_t,int32_t,uint8_t  *,uint8_t  *);
 
 int32_t tvlineasm1(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
 void setuptvlineasm2(int32_t,int32_t,int32_t);
@@ -57,7 +57,7 @@
 void mspritevline(int32_t,int32_t,int32_t,int32_t,uint8_t  *,uint8_t  *);
 void tsetupspritevline(int32_t,int32_t,int32_t,int32_t,int32_t);
 void DrawSpriteVerticalLine(int32_t,int32_t,int32_t,uint32_t,int32_t,uint8_t*);
-void mhline(int32_t,int32_t,int32_t,int32_t,int32_t,uint8_t*);
+void mhline(uint8_t  *,int32_t,int32_t,int32_t,int32_t,uint8_t*);
 void mhlineskipmodify(uint32_t,int32_t,int32_t,int32_t,uint8_t*);
 void msethlineshift(int32_t,int32_t);
 void thline(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
--- a/Engine/src/engine.c
+++ b/Engine/src/engine.c
@@ -29,14 +29,12 @@
 #endif
 
 #include "build.h"
-#include "cache.h"
-#include "filesystem.h"
 
 #include "engine.h"
 
 int32_t stereowidth = 23040, stereopixelwidth = 28, ostereopixelwidth = -1;
-volatile int32_t stereomode = 0, visualpage, activepage, whiteband, blackband;
-volatile uint8_t  oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
+int32_t stereomode = 0, visualpage, activepage, whiteband, blackband;
+uint8_t  oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
 
 #include "display.h"
 
@@ -211,7 +209,8 @@
 uint8_t  globalxshift, globalyshift;
 int32_t globalxpanning, globalypanning, globalshade;
 int16_t globalpicnum, globalshiftval;
-int32_t globalzd, globalbufplc, globalyscale, globalorientation;
+int32_t globalzd, globalyscale, globalorientation;
+uint8_t* globalbufplc;
 int32_t globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
 int32_t globalx, globaly, globalz;
 
@@ -716,14 +715,19 @@
 }
 
 
-static int animateoffs(int16_t tilenum, int16_t fakevar)
+/*
+  FCS:   If a texture is animated, this will return the offset to add to tilenum
+         in order to retrieve the texture to display.
+*/
+static int animateoffs(int16_t tilenum)
 {
     int32_t i, k, offs;
 
     offs = 0;
+    
     i = (totalclocklock>>((picanm[tilenum]>>24)&15));
-    if ((picanm[tilenum]&63) > 0)
-    {
+    
+    if ((picanm[tilenum]&63) > 0){
         switch(picanm[tilenum]&192)
         {
         case 64:
@@ -740,6 +744,7 @@
             offs = -(i%((picanm[tilenum]&63)+1));
         }
     }
+    
     return(offs);
 }
 
@@ -773,7 +778,7 @@
         return;
     
     if (picanm[globalpicnum]&192)
-        globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
+        globalpicnum += animateoffs(globalpicnum);
 
     if (waloff[globalpicnum] == 0)
         loadtile(globalpicnum);
@@ -982,35 +987,50 @@
     int32_t i, j, ox, oy, x, y1, y2, twall, bwall;
     sectortype *sec;
 
+    //Retrieve the sector object
     sec = &sector[sectnum];
+    
+    //Retrieve the floor palette.
     if (palookup[sec->floorpal] != globalpalwritten)
-    {
         globalpalwritten = palookup[sec->floorpal];
-       
-    }
 
     globalzd = globalposz-sec->floorz;
+    
+    //We are UNDER the floor: Do NOT render anything.
     if (globalzd > 0)
         return;
+    
+    //Retrive the floor texture.
     globalpicnum = sec->floorpicnum;
-    if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+    if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+        globalpicnum = 0;
+    
+    //Lock the floor texture
     setgotpic(globalpicnum);
     
+    
     if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0))
         return;
     
-    if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
+    //If this is an animated texture: Animate it.
+    if (picanm[globalpicnum]&192)
+        globalpicnum += animateoffs(globalpicnum);
 
+    //If the texture is not in RAM: Load it !!
     if (waloff[globalpicnum] == 0)
         loadtile(globalpicnum);
     
+    //Check where is the texture in RAM
     globalbufplc = waloff[globalpicnum];
 
+    //Retrieve the shade of the sector (illumination level).
     globalshade = (int32_t)sec->floorshade;
+    
     globvis = globalcisibility;
-    if (sec->visibility != 0){
+    if (sec->visibility != 0)
         globvis = mulscale4(globvis,(int32_t)((sec->visibility+16)));
-    }
+    
+    
     globalorientation = (int32_t)sec->floorstat;
 
 
@@ -1047,6 +1067,8 @@
         globalxpanning = globalx1*ox - globaly1*oy;
         globalypanning = globaly2*ox + globalx2*oy;
     }
+    
+    
     globalx2 = mulscale16(globalx2,viewingrangerecip);
     globaly1 = mulscale16(globaly1,viewingrangerecip);
     globalxshift = (8-(picsiz[globalpicnum]&15));
@@ -1068,6 +1090,8 @@
         globalx1 = globaly2;
         globaly2 = i;
     }
+    
+    
     if ((globalorientation&0x10) > 0){
         globalx1 = -globalx1;
         globaly1 = -globaly1;
@@ -1079,6 +1103,8 @@
         globaly2 = -globaly2;
         globalypanning = -globalypanning;
     }
+    
+    
     globalx1 <<= globalxshift;
     globaly1 <<= globalxshift;
     globalx2 <<= globalyshift;
@@ -1090,6 +1116,7 @@
     globaly1 = (-globalx1-globaly1)*halfxdimen;
     globalx2 = (globalx2-globaly2)*halfxdimen;
 
+    //Setup the drawing routine paramters
     sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
 
     globalx2 += globaly2*(x1-1);
@@ -1594,7 +1621,7 @@
     }
 
     if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
-    if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)sectnum);
+    if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum);
     globalshiftval = (picsiz[globalpicnum]>>4);
     if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
     globalshiftval = 32-globalshiftval;
@@ -1734,7 +1761,7 @@
     }
 
     if ((picanm[globalpicnum]&192) != 0)
-        globalpicnum += animateoffs(globalpicnum,(short) sectnum);
+        globalpicnum += animateoffs(globalpicnum);
     setgotpic(globalpicnum);
     if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0))
         return;
@@ -2292,7 +2319,11 @@
                     globalshiftval = (picsiz[globalpicnum]>>4);
                     if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
                     globalshiftval = 32-globalshiftval;
-                    if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)(wallnum+16384));
+                    
+                    //Animated
+                    if (picanm[globalpicnum]&192)
+                        globalpicnum += animateoffs(globalpicnum);
+                    
                     globalshade = (int32_t)wal->shade;
                     globvis = globalvisibility;
                     if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
@@ -2375,7 +2406,7 @@
                         if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
                         globalxpanning = (int32_t)wal->xpanning;
                         globalypanning = (int32_t)wal->ypanning;
-                        if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)(wallnum+16384));
+                        if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum);
                         globalshade = (int32_t)wal->shade;
                         globalpal = (int32_t)wal->pal;
                         wallnum = thewall[z];
@@ -2387,7 +2418,7 @@
                         if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
                         globalxpanning = (int32_t)wal->xpanning;
                         globalypanning = (int32_t)wal->ypanning;
-                        if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)(wallnum+16384));
+                        if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum);
                         globalshade = (int32_t)wal->shade;
                         globalpal = (int32_t)wal->pal;
                     }
@@ -2491,7 +2522,7 @@
             globalypanning = (int32_t)wal->ypanning;
             
             if (picanm[globalpicnum]&192)
-                globalpicnum += animateoffs(globalpicnum,(short)(wallnum+16384));
+                globalpicnum += animateoffs(globalpicnum);
             
             globalshade = (int32_t)wal->shade;
             globvis = globalvisibility;
@@ -4697,7 +4728,7 @@
     if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
     globalxpanning = (int32_t)wal->xpanning;
     globalypanning = (int32_t)wal->ypanning;
-    if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)(thewall[z]+16384));
+    if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum);
     globalshade = (int32_t)wal->shade;
     globvis = globalvisibility;
     if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
@@ -4863,7 +4894,7 @@
     if ((cstat&48) != 48)
     {
         if (picanm[tilenum]&192)
-            tilenum += animateoffs(tilenum,(short) (spritenum+32768));
+            tilenum += animateoffs(tilenum);
         
         if ((tilesizx[tilenum] <= 0) || (tilesizy[tilenum] <= 0) || (spritenum < 0))
             return;
@@ -5658,8 +5689,8 @@
 
         globalorientation = cstat;
         globalpicnum = tilenum;
-        if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
-        /* if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,spritenum+32768); */
+        if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+            globalpicnum = 0;
 
         if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
         setgotpic(globalpicnum);
@@ -7416,9 +7447,7 @@
         if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1))
         {
             setcolor16(8);
-#ifdef PLATFORM_DOS
-            koutp(0x3ce,0x8);
-#endif
+
             tempint = ((yp1*640+pageoffset)>>3)+(int32_t)_getVideoBase();
             tempy = yp2-yp1+1;
             mask = 0;
@@ -7433,18 +7462,8 @@
                 if (xp1 >= 0)
                 {
 
-#if (defined PLATFORM_DOS)
-                    if ((xp1|7) != (xp2|7))
-                    {
-                        koutp(0x3cf,mask);
-                        if (((xp2>>3) >= 0) && ((xp2>>3) < 80))
-                            vlin16first(templong+(xp2>>3),tempy);
-                        mask = 0;
-                    }
-                    mask |= pow2char[(xp1&7)^7];
-#else
+
                     drawline16(xp1, 0, xp1, tempy, 8);
-#endif
                 }
             }
             if ((i >= 131072) && (xp1 < 640))
@@ -7452,12 +7471,7 @@
             if ((mask != 0) && ((xp2>>3) >= 0) && ((xp2>>3) < 80))
             {
                 /* !!! Does this code ever get hit? Do something with this! */
-#ifdef PLATFORM_DOS
-                koutp(0x3cf,mask);
-                vlin16first(templong+(xp2>>3),tempy);
-#else
                 fprintf (stderr, "STUB: %s:%d\n",__FILE__,__LINE__);
-#endif
             }
         }
 
@@ -8046,9 +8060,15 @@
     int32_t i;
     permfifotype *per, *per2;
 
-    if ((cx1 > cx2) || (cy1 > cy2)) return;
-    if (z <= 16) return;
-    if (picanm[picnum]&192) picnum += animateoffs(picnum,(short)0xc000);
+    //If 2D target coordinate do not make sense (left > right)..
+    if ((cx1 > cx2) || (cy1 > cy2))
+        return;
+    
+    if (z <= 16)
+        return;
+    
+    if (picanm[picnum]&192)
+        picnum += animateoffs(picnum);
     if ((tilesizx[picnum] <= 0) || (tilesizy[picnum] <= 0)) return;
 
     if (((dastat&128) == 0) || (numpages < 2) || (beforedrawrooms != 0))
@@ -8704,7 +8724,10 @@
                 xb1[npoints] = wal->point2 - startwall;
                 npoints++;
             }
-            if ((i&0xf0) != 0xf0) continue;
+            
+            if ((i&0xf0) != 0xf0)
+                continue;
+            
             bakx1 = rx1[0];
             baky1 = mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11);
             if (i&0x0f)
@@ -8736,7 +8759,7 @@
             if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
             setgotpic(globalpicnum);
             if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
-            if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
+            if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs(globalpicnum);
             if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
             globalbufplc = waloff[globalpicnum];
             globalshade = max(min(sec->floorshade,numpalookups-1),0);
@@ -8908,7 +8931,7 @@
             if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
             setgotpic(globalpicnum);
             if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
-            if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
+            if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs(globalpicnum);
             if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
             globalbufplc = waloff[globalpicnum];
             if ((sector[spr->sectnum].ceilingstat&1) > 0)
--- a/Engine/src/engine.h
+++ b/Engine/src/engine.h
@@ -132,9 +132,9 @@
 void completemirror(void);
 int clipinsidebox(int32_t x, int32_t y, int16_t wallnum, int32_t walldist);
 
-#ifdef SUPERBUILD
-void qloadkvx(int32_t voxindex, uint8_t  *filename);
-#endif
+#include "cache.h"
+#include "filesystem.h"
+#include "display.h"
 
 #ifdef __cplusplus
 }
--- a/Engine/src/engine_protos.h
+++ /dev/null
@@ -1,182 +1,0 @@
-//-------------------------------------------------------------------------
-/*
-Copyright (C) 1996, 2003 - 3D Realms Entertainment
-
-This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
-
-Duke Nukem 3D 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
-aint32_t with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-//-------------------------------------------------------------------------
-
-/* Prototypes for the build engine */
-
-
-extern void initcache(int32_t dacachestart, int32_t dacachesize);
-extern void allocache(int32_t *newhandle, int32_t newbytes, uint8_t  *newlockptr);
-extern void suckcache(int32_t *suckptr);
-extern void agecache(void);
-extern void reportandexit(char  *errormessage);
-extern int32_t initgroupfile(const char  *filename);
-extern void uninitgroupfile(void);
-extern int32_t kopen4load(const char  *filename,int readfromGRP);
-extern int32_t kread(int32_t handle, void *buffer, int32_t leng);
-extern int32_t klseek(int32_t handle, int32_t offset, int32_t whence);
-extern int32_t kfilelength(int32_t handle);
-extern void kclose(int32_t handle);
-extern void kdfsread(void *buffer, size_t dasizeof, size_t count, int32_t fil);
-extern void dfread(void *buffer, size_t dasizeof, size_t count, FILE *fil);
-extern void dfwrite(void *buffer, size_t dasizeof, size_t count, FILE *fil);
-extern int32_t compress(uint8_t  *lzwinbuf, int32_t uncompleng, uint8_t  *lzwoutbuf);
-extern int32_t uncompress(uint8_t  *lzwinbuf, int32_t compleng, uint8_t  *lzwoutbuf);
-
-/* sdl_driver.c */
-extern void _handle_events(void);
-extern uint8_t  _readlastkeyhit(void);
-
-
-extern void _platform_init(int argc, char  **argv, const char  *title, const char  *icon);
-extern int setvesa(int32_t x, int32_t y);
-extern int screencapture(char  *filename, uint8_t  inverseit);
-extern void setvmode(int mode);
-extern int _setgamemode(uint8_t  davidoption, int32_t daxdim, int32_t daydim);
-extern void getvalidvesamodes(void);
-extern int VBE_setPalette(int32_t start, int32_t num, uint8_t  *palettebuffer);
-extern int VBE_getPalette(int32_t start, int32_t num, uint8_t  *palettebuffer);
-extern void _uninitengine(void);
-
-extern int setupmouse(void);
-extern void readmousexy(short *x, short *y);
-extern void readmousebstatus(short *bstatus);
-extern void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h);
-extern void _nextpage(void);
-extern uint8_t  readpixel(int32_t offset);
-extern void drawpixel(int32_t offset, uint8_t  pixel);
-extern void drawpixels(int32_t offset, uint16_t pixels);
-extern void drawpixelses(int32_t offset, unsigned int pixelses);
-extern void setcolor16(int col);
-extern void drawpixel16(int32_t offset);
-extern void fillscreen16(int32_t offset, int32_t color, int32_t blocksize);
-extern void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t  Color);
-extern void clear2dscreen(void);
-extern void _idle(void);
-extern void *_getVideoBase(void);
-
-
-extern int inittimer(int);
-extern void uninittimer(void);
-extern void initkeys(void);
-extern void uninitkeys(void);
-extern void set16color_palette(void);
-extern void restore256_palette(void);
-extern uint32_t  getticks(void);
-
-
-void callcommit(void);
-void initcrc(void);
-int32_t getcrc(uint8_t  *buffer, short bufleng);
-void initmultiplayers(uint8_t  damultioption, uint8_t  dacomrateoption, uint8_t  dapriority);
-void sendpacket(int32_t other, uint8_t  *bufptr, int32_t messleng);
-void setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount);
-void uninitmultiplayers(void);
-void sendlogon(void);
-void sendlogoff(void);
-int getoutputcirclesize(void);
-void setsocket(short newsocket);
-short getpacket(short *other, uint8_t  *bufptr);
-void flushpackets(void);
-void genericmultifunction(int32_t other, char  *bufptr, int32_t messleng, int32_t command);
-
-/* engine.c */
-extern int setgotpic(int32_t i1);
-//extern static __inline int32_t getclipmask(int32_t a, int32_t b, int32_t c, int32_t d);
-extern int wallfront(int32_t l1, int32_t l2);
-extern void drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, short daang, int32_t dahoriz, short dacursectnum);
-extern int loadboard(char  *filename, int32_t *daposx, int32_t *daposy, int32_t *daposz, short *daang, short *dacursectnum);
-extern int saveboard(char  *filename, int32_t *daposx, int32_t *daposy, int32_t *daposz, short *daang, short *dacursectnum);
-extern int setgamemode(uint8_t  davidoption, int32_t daxdim, int32_t daydim);
-
-
-extern void initengine(void);
-extern void uninitengine(void);
-extern void nextpage(void);
-extern void loadtile(short tilenume);
-extern int allocatepermanenttile(short tilenume, int32_t xsiz, int32_t ysiz);
-extern int loadpics(char  *filename, char * gamedir);
-extern void qloadkvx(int32_t voxindex, uint8_t  *filename);
-extern int clipinsidebox(int32_t x, int32_t y, short wallnum, int32_t walldist);
-extern void drawline256(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t  col);
-extern int inside(int32_t x, int32_t y, short sectnum);
-extern int getangle(int32_t xvect, int32_t yvect);
-extern int ksqrt(int32_t num);
-extern void copytilepiece(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, int32_t tilenume2, int32_t sx2, int32_t sy2);
-extern void drawmasks(void);
-extern int setsprite(short spritenum, int32_t newx, int32_t newy, int32_t newz);
-extern void initspritelists(void);
-extern int insertsprite(short sectnum, short statnum);
-extern int insertspritesect(short sectnum);
-extern int insertspritestat(short statnum);
-extern int deletesprite(short spritenum);
-extern int deletespritesect(short deleteme);
-extern int deletespritestat(short deleteme);
-extern int changespritesect(short spritenum, short newsectnum);
-extern int changespritestat(short spritenum, short newstatnum);
-extern int nextsectorneighborz(short sectnum, int32_t thez, short topbottom, short direction);
-extern int cansee(int32_t x1, int32_t y1, int32_t z1, short sect1, int32_t x2, int32_t y2, int32_t z2, short sect2);
-extern int lintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz);
-extern int rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz);
-extern int hitscan(int32_t xs, int32_t ys, int32_t zs, short sectnum, int32_t vx, int32_t vy, int32_t vz, short *hitsect, short *hitwall, short *hitsprite, int32_t *hitx, int32_t *hity, int32_t *hitz, uint32_t  cliptype);
-extern int neartag(int32_t xs, int32_t ys, int32_t zs, short sectnum, short ange, short *neartagsector, short *neartagwall, short *neartagsprite, int32_t *neartaghitdist, int32_t neartagrange, uint8_t  tagsearch);
-extern void dragpoint(short pointhighlight, int32_t dax, int32_t day);
-extern int lastwall(short point);
-extern int clipmove(int32_t *x, int32_t *y, int32_t *z, short *sectnum, int32_t xvect, int32_t yvect, int32_t walldist, int32_t ceildist, int32_t flordist, uint32_t  cliptype);
-extern int pushmove(int32_t *x, int32_t *y, int32_t *z, short *sectnum, int32_t walldist, int32_t ceildist, int32_t flordist, uint32_t  cliptype);
-extern void updatesector(int32_t x, int32_t y, short *sectnum);
-extern void rotatepoint(int32_t xpivot, int32_t ypivot, int32_t x, int32_t y, short daang, int32_t *x2, int32_t *y2);
-extern int initmouse(void);
-extern void getmousevalues(short *mousx, short *mousy, short *bstatus);
-extern void draw2dgrid(int32_t posxe, int32_t posye, short ange, int32_t zoome, short gride);
-extern void draw2dscreen(int32_t posxe, int32_t posye, short ange, int32_t zoome, short gride);
-extern void printext256(int32_t xpos, int32_t ypos, short col, short backcol, char  name[82], uint8_t  fontsize);
-extern void printext256_noupdate(int32_t xpos, int32_t ypos, short col, short backcol, char  name[82], uint8_t  fontsize);
-
-extern int krand(void);
-
-extern void getzrange(int32_t x, int32_t y, int32_t z, short sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit, int32_t walldist, uint32_t  cliptype);
-extern void setview(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
-extern void setaspect(int32_t daxrange, int32_t daaspect);
-extern void flushperms(void);
-extern void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t  dapalnum, uint8_t  dastat, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
-extern void makepalookup(int32_t palnum, uint8_t  *remapbuf, int8_t r, int8_t g, int8_t b, uint8_t  dastat);
-extern void setbrightness(uint8_t  dabrightness, uint8_t  *dapal);
-extern void drawmapview(int32_t dax, int32_t day, int32_t zoome, short ang);
-extern void clearview(int32_t dacol);
-extern void clearallviews(int32_t dacol);
-extern void plotpixel(int32_t x, int32_t y, uint8_t  col);
-extern uint8_t  getpixel(int32_t x, int32_t y);
-extern void setviewtotile(short tilenume, int32_t xsiz, int32_t ysiz);
-extern void setviewback(void);
-extern void squarerotatetile(short tilenume);
-extern void preparemirror(int32_t dax, int32_t day, int32_t daz, short daang, int32_t dahoriz, short dawall, short dasector, int32_t *tposx, int32_t *tposy, short *tang);
-extern void completemirror(void);
-extern int sectorofwall(short theline);
-extern int getceilzofslope(short sectnum, int32_t dax, int32_t day);
-extern int getflorzofslope(short sectnum, int32_t dax, int32_t day);
-extern void getzsofslope(short sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz);
-extern void alignceilslope(short dasect, int32_t x, int32_t y, int32_t z);
-extern void alignflorslope(short dasect, int32_t x, int32_t y, int32_t z);
-extern int loopnumofsector(short sectnum, short wallnum);
-extern void setfirstwall(short sectnum, short newfirstwall);
--- a/Engine/src/sdl_driver.c
+++ /dev/null
@@ -1,2282 +1,0 @@
-/*
- * An SDL replacement for BUILD's VESA code.
- *
- *  Written by Ryan C. Gordon. (icculus@clutteredmind.org)
- *
- * Please do NOT harrass Ken Silverman about any code modifications
- *  (including this file) to BUILD.
- */
-
-/*
- * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
- * Ken Silverman's official web site: "http://www.advsys.net/ken"
- * See the included license file "BUILDLIC.TXT" for license info.
- * This file IS NOT A PART OF Ken Silverman's original release
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include "platform.h"
-
-#if (!defined PLATFORM_SUPPORTS_SDL)
-#error This platform apparently does not use SDL. Do not compile this.
-#endif
-
-
-#define BUILD_NOMOUSEGRAB    "BUILD_NOMOUSEGRAB"
-#define BUILD_WINDOWED       "BUILD_WINDOWED"
-#define BUILD_SDLDEBUG       "BUILD_SDLDEBUG"
-#define BUILD_RENDERER       "BUILD_RENDERER"
-#define BUILD_GLLIBRARY      "BUILD_GLLIBRARY"
-#define BUILD_USERSCREENRES  "BUILD_USERSCREENRES"
-#define BUILD_MAXSCREENRES   "BUILD_MAXSCREENRES"
-#define BUILD_HALLOFMIRRORS  "BUILD_HALLOFMIRRORS"
-#define BUILD_GLDUMP         "BUILD_GLDUMP"
-#define BUILD_SDLJOYSTICK    "BUILD_SDLJOYSTICK"
-
-#include "SDL.h"
-#include "build.h"
-#include "display.h"
-#include "pragmas.h"
-#include "engine.h"
-#include "engine_protos.h"
-
-#include "mmulti_unstable.h"
-#include "mmulti_stable.h"
-
-#include "icon.h"
-
-// NATIVE TIMER FUNCTION DECLARATION
-/*
- FCS: The timer section sadly uses Native high precision calls to implement timer functions.
- QueryPerformanceFrequency and QueryPerformanceCounter
- it seems SDL precision was not good enough (or rather using unaccurate OS functions) to replicate
- a DOS timer.
- */
-
-int TIMER_GetPlatformTicksInOneSecond(int64_t* t);
-void TIMER_GetPlatformTicks(int64_t* t);
-
-//END // NATIVE TIMER FUNCTION DECLARATION
-
-
-
-
-// NETWORK STUFF
-#ifdef __APPLE__
-  #define USER_DUMMY_NETWORK 1
-#endif 
-
-void Setup_UnstableNetworking();
-void Setup_StableNetworking();
-
-int nNetMode = 0;
-
-//TODO ( "[Fix this horrible networking mess. Function pointers not happy]" )
-// I do not like this one bit.
-// Figure out what was causing the problems with the function pointers.
-// This mess is a direct result of my lack of time.. bleh
-// This mess shouldn't even be in this file. /slap /slap
-void callcommit(void)
-{
-#ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:		
-		unstable_callcommit();
-		break;
-	case 1:
-		stable_callcommit();
-		break;		
-	}
-#endif
-}
-void initcrc(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:	
-		unstable_initcrc();
-		break;
-	case 1:	
-		stable_initcrc();
-		break;
-	}
-#endif
-}
-int32_t getcrc(uint8_t  *buffer, short bufleng)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		return unstable_getcrc(buffer, bufleng);
-	case 1:
-		return stable_getcrc(buffer, bufleng);
-	}
-#endif
-	return 0;
-}
-void initmultiplayers(uint8_t  damultioption, uint8_t  dacomrateoption, uint8_t  dapriority)
-{
-#ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_initmultiplayers(damultioption, dacomrateoption, dapriority);
-		break;
-	case 1:
-		stable_initmultiplayers(damultioption, dacomrateoption, dapriority);
-		break;
-	}
-#endif
-}
-void sendpacket(int32_t other, uint8_t  *bufptr, int32_t messleng)
-{
-#ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_sendpacket(other, bufptr, messleng);
-		break;
-	case 1:
-		stable_sendpacket(other, bufptr, messleng);
-		break;
-	}
-#endif
-}
-void setpackettimeout(int32_t datimeoutcount, int32_t daresendagaincount)
-{
-#ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_setpackettimeout(datimeoutcount, daresendagaincount);
-		break;
-	case 1:
-		stable_setpackettimeout(datimeoutcount, daresendagaincount);
-		break;
-	}
-#endif
-}
-void uninitmultiplayers(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_uninitmultiplayers();
-		break;
-	case 1:
-		stable_uninitmultiplayers();
-		break;
-	}
-#endif
-}
-void sendlogon(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_sendlogon();
-		break;
-	case 1:
-		unstable_sendlogon();
-		break;
-	}
-#endif
-}
-void sendlogoff(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_sendlogoff();
-		break;
-	case 1:
-		stable_sendlogoff();
-		break;
-	}
-#endif
-}
-int  getoutputcirclesize(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		return unstable_getoutputcirclesize();
-	case 1:
-		return stable_getoutputcirclesize();		
-	}
-#endif
-	return 0;
-}
-void setsocket(short newsocket)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_setsocket(newsocket);
-		break;
-	case 1:
-		stable_setsocket(newsocket);
-		break;
-	}
-#endif
-}
-short getpacket(short *other, uint8_t  *bufptr)
-{
-#ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		return unstable_getpacket(other, bufptr); // default
-	case 1:
-		return stable_getpacket(other, bufptr);
-	}
-#endif
-	return 0;
-}
-void flushpackets(void)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_flushpackets();
-		break;
-	case 1:
-		stable_flushpackets();
-		break;
-	}
-#endif
-}
-void genericmultifunction(int32_t other, char  *bufptr, int32_t messleng, int32_t command)
-{
-    #ifndef USER_DUMMY_NETWORK
-	switch(nNetMode)
-	{
-	case 0:
-		unstable_genericmultifunction(other, bufptr, messleng, command);
-		break;
-	case 1:
-		stable_genericmultifunction(other, bufptr, messleng, command);
-		break;
-	}
-#endif
-}
-
-#if ((defined PLATFORM_WIN32))
-#include <windows.h>
-#endif
-
-typedef enum
-{
-    RENDERER_SOFTWARE,
-    RENDERER_OPENGL3D,
-    RENDERER_TOTAL
-} sdl_renderer_type;
-
-const char  *renderer_name[RENDERER_TOTAL];
-
-#define ENVRSTR_RENDERER_SOFTWARE  "software"
-#define ENVRSTR_RENDERER_OPENGL3D  "opengl3d"
-
-static sdl_renderer_type renderer = RENDERER_SOFTWARE;
-
-#include "draw.h"
-#include "cache.h"
-
-
-/*
- * !!! remove the surface_end checks, for speed's sake. They are a
- * !!!  needed safety right now. --ryan.
- */
-
-
-#define DEFAULT_MAXRESWIDTH  1600
-#define DEFAULT_MAXRESHEIGHT 1200
-
-
-#define UNLOCK_SURFACE_AND_RETURN  if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return;
-
-
-int _argc = 0;
-char  **_argv = NULL;
-
-    /* !!! move these elsewhere? */
-int32_t xres, yres, bytesperline, frameplace, frameoffset, imageSize, maxpages;
-uint8_t  *screen, vesachecked;
-int32_t buffermode, origbuffermode, linearmode;
-uint8_t  permanentupdate = 0, vgacompatible;
-
-SDL_Surface *surface = NULL; /* This isn't static so that we can use it elsewhere AH */
-static int debug_hall_of_mirrors = 0;
-static uint32_t sdl_flags = SDL_HWPALETTE;
-static int32_t mouse_relative_x = 0;
-static int32_t mouse_relative_y = 0;
-static short mouse_buttons = 0;
-static unsigned int lastkey = 0;
-/* so we can make use of setcolor16()... - DDOI */
-static uint8_t  drawpixel_color=0;
-
-static uint32_t scancodes[SDLK_LAST];
-
-static int32_t last_render_ticks = 0;
-int32_t total_render_time = 1;
-int32_t total_rendered_frames = 0;
-
-static char *titleNameLong = NULL;
-static char *titleNameShort = NULL;
-
-void restore256_palette (void);
-void set16color_palette (void);
-
-static FILE *_sdl_debug_file = NULL;
-
-void set_sdl_renderer(void);
-
-static __inline void __out_sdldebug(const char  *subsystem,
-                                  const char  *fmt, va_list ap)
-{
-    fprintf(_sdl_debug_file, "%s: ", subsystem);
-    vfprintf(_sdl_debug_file, fmt, ap);
-    fprintf(_sdl_debug_file, "\n");
-    fflush(_sdl_debug_file);
-} /* __out_sdldebug */
-
-
-static void sdldebug(const char  *fmt, ...)
-{
-    va_list ap;
-
-    if (_sdl_debug_file)
-    {
-        va_start(ap, fmt);
-        __out_sdldebug("BUILDSDL", fmt, ap);
-        va_end(ap);
-    } /* if */
-} /* sdldebug */
-
-static void __append_sdl_surface_flag(SDL_Surface *_surface, char  *str,
-                                      size_t strsize, Uint32 flag,
-                                      const char  *flagstr)
-{
-    if (_surface->flags & flag)
-    {
-        if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) )
-            strcpy(str + (strsize - 5), " ...");
-        else
-            strcat(str, flagstr);
-    } /* if */
-} /* append_sdl_surface_flag */
-
-
-#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)
-#define print_tf_state(str, val) sdldebug("%s: {%s}", str, (val) ? "true" : "false" )
-
-static void output_surface_info(SDL_Surface *_surface)
-{
-    const SDL_VideoInfo *info;
-    char  f[256];
-
-    if (!_sdl_debug_file)
-        return;
-
-    if (_surface == NULL)
-    {
-        sdldebug("-WARNING- You've got a NULL screen surface!");
-    }
-    else
-    {
-        f[0] = '\0';
-        sdldebug("screen surface is (%dx%dx%dbpp).",
-                _surface->w, _surface->h, _surface->format->BitsPerPixel);
-
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SWSURFACE);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWSURFACE);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ASYNCBLIT);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ANYFORMAT);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWPALETTE);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_DOUBLEBUF);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_FULLSCREEN);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGL);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGLBLIT);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RESIZABLE);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_NOFRAME);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWACCEL);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCCOLORKEY);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCELOK);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCEL);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCALPHA);
-        append_sdl_surface_flag(_surface, f, sizeof (f), SDL_PREALLOC);
-
-        if (f[0] == '\0')
-            strcpy(f, " (none)");
-
-        sdldebug("New vidmode flags:%s", f);
-
-        info = SDL_GetVideoInfo();
-        assert(info != NULL);
-
-        print_tf_state("hardware surface available", info->hw_available);
-        print_tf_state("window manager available", info->wm_available);
-        print_tf_state("accelerated hardware->hardware blits", info->blit_hw);
-        print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC);
-        print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A);
-        print_tf_state("accelerated software->hardware blits", info->blit_sw);
-        print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC);
-        print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A);
-        print_tf_state("accelerated color fills", info->blit_fill);
-
-        sdldebug("video memory: (%d)", info->video_mem);
-    } /* else */
-} /* output_surface_info */
-
-
-static void output_driver_info(void)
-{
-    char  buffer[256];
-
-    if (!_sdl_debug_file)
-        return;
-
-    sdldebug("Using BUILD renderer \"%s\".", renderer_name[renderer]);
-
-    if (SDL_VideoDriverName(buffer, sizeof (buffer)) == NULL)
-    {
-        sdldebug("-WARNING- SDL_VideoDriverName() returned NULL!");
-    } /* if */
-    else
-    {
-        sdldebug("Using SDL video driver \"%s\".", buffer);
-    } /* else */
-} /* output_driver_info */
-
-
-Uint8 *get_framebuffer(void)
-{
-    assert(renderer != RENDERER_OPENGL3D);
-
-    if (renderer == RENDERER_SOFTWARE)
-        return((Uint8 *) surface->pixels);
-    else if (renderer == RENDERER_OPENGL3D)
-        return((Uint8 *) frameplace);
-
-    return(NULL);
-} /* get_framebuffer */
-
-
-
-/*
- * !!! This is almost an entire copy of the original setgamemode().
- * !!!  Figure out what is needed for just 2D mode, and separate that
- * !!!  out. Then, place the original setgamemode() back into engine.c,
- * !!!  and remove our simple implementation (and this function.)
- * !!!  Just be sure to keep the non-DOS things, like the window's
- * !!!  titlebar caption.   --ryan.
- */
-static uint8_t  screenalloctype = 255;
-static void init_new_res_vars(int32_t davidoption)
-{
-    int i = 0;
-    int j = 0;
-
-    setupmouse();
-
-    SDL_WM_SetCaption(titleNameLong, titleNameShort);
-
-    xdim = xres = surface->w;
-    ydim = yres = surface->h;
-
-	printf("init_new_res_vars %d %d\n",xdim,ydim);
-
-    bytesperline = surface->w;
-    vesachecked = 1;
-    vgacompatible = 1;
-    linearmode = 1;
-	qsetmode = surface->h;
-	activepage = visualpage = 0;
-
-    if (renderer == RENDERER_OPENGL3D)
-        frameplace = (int32_t) NULL;
-    else
-		// FIX_00083: Sporadic crash on fullscreen/window mode toggle
-		// frameoffset wasn't always updated fast enought. Build were using the old 
-		// pointer of frameoffset.  
-        frameoffset = frameplace = (int32_t) ( ((Uint8 *) surface->pixels) );
-
-  	if (screen != NULL)
-   	{
-       	if (screenalloctype == 0) kkfree((void *)screen);
-   	    if (screenalloctype == 1) suckcache((int32_t *)screen);
-   		screen = NULL;
-   	} /* if */
-
-
-    	switch(vidoption)
-    	{
-    		case 1:i = xdim*ydim; break;
-    		case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
-    		case 6: xdim = 320; ydim = 200; i = 131072; break;
-    		default: assert(0);
-    	}
-    	j = ydim*4*sizeof(int32_t);  /* Leave room for horizlookup&horizlookup2 */
-
-		if(horizlookup)
-			free(horizlookup);
-
-		if(horizlookup2)
-			free(horizlookup2);
-		
-		horizlookup = (int32_t*)malloc(j);
-		horizlookup2 = (int32_t*)malloc(j);
-
-    j = 0;
-    
-    //Build lookup table (X screespace -> frambuffer offset. 
-  	for(i = 0; i <= ydim; i++)
-    {
-        ylookup[i] = j;
-        j += bytesperline;
-    }
-
-   	horizycent = ((ydim*4)>>1);
-
-    /* Force drawrooms to call dosetaspect & recalculate stuff */
-	oxyaspect = oxdimen = oviewingrange = -1;
-
-    //Let the Assembly module how many pixels to skip when drawing a column
-	setBytesPerLine(bytesperline);
-
-    
-    setview(0L,0L,xdim-1,ydim-1);
-    
-	setbrightness((uint8_t ) curbrightness, (uint8_t  *) &palette[0]);
-
-	if (searchx < 0) {
-        searchx = halfxdimen;
-        searchy = (ydimen>>1);
-    }
-    
-}
-
-
-
-static void go_to_new_vid_mode(int davidoption, int w, int h)
-{
-    getvalidvesamodes();
-    SDL_ClearError();
-    // don't do SDL_SetVideoMode if SDL_WM_SetIcon not called. See sdl doc for SDL_WM_SetIcon
-	surface = SDL_SetVideoMode(w, h, 8, sdl_flags);
-    if (surface == NULL)
-    {
-		Error(EXIT_FAILURE,	"BUILDSDL: Failed to set %dx%d video mode!\n"
-							"BUILDSDL: SDL_Error() says [%s].\n",
-							w, h, SDL_GetError());
-	} /* if */
-
-    output_surface_info(surface);
-    init_new_res_vars(davidoption); // dont be confused between vidoption (global) and davidoption
-}
-
-static __inline int sdl_mouse_button_filter(SDL_MouseButtonEvent const *event)
-{
-        /*
-         * What bits BUILD expects:
-         *  0 left button pressed if 1
-         *  1 right button pressed if 1
-         *  2 middle button pressed if 1
-         *
-         *   (That is, this is what Int 33h (AX=0x05) returns...)
-         *
-         *  additionally bits 3&4 are set for the mouse wheel
-         */
-    Uint8 button = event->button;
-    if (button >= sizeof (mouse_buttons) * 8)
-        return(0);
-
-    if (button == SDL_BUTTON_RIGHT)
-        button = SDL_BUTTON_MIDDLE;
-    else if (button == SDL_BUTTON_MIDDLE)
-        button = SDL_BUTTON_RIGHT;
-
-    if (((const SDL_MouseButtonEvent*)event)->state)
-        mouse_buttons |= 1<<(button-1);
-    else if (button != 4 && button != 5)
-        mouse_buttons ^= 1<<(button-1);
-#if 0
-    Uint8 bmask = SDL_GetMouseState(NULL, NULL);
-    mouse_buttons = 0;
-    if (bmask & SDL_BUTTON_LMASK) mouse_buttons |= 1;
-    if (bmask & SDL_BUTTON_RMASK) mouse_buttons |= 2;
-    if (bmask & SDL_BUTTON_MMASK) mouse_buttons |= 4;
-#endif
-
-    return(0);
-} /* sdl_mouse_up_filter */
-
-
-static int sdl_mouse_motion_filter(SDL_Event const *event)
-{
-    if (surface == NULL)
-		return(0);
-
-    if (event->type == SDL_JOYBALLMOTION)
-    {
-        mouse_relative_x = event->jball.xrel/100;
-        mouse_relative_y = event->jball.yrel/100;
-    }
-    else
-    {
-			if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON) 
-			{
-				mouse_relative_x += event->motion.xrel;
-	       	    mouse_relative_y += event->motion.yrel;
-				//printf("sdl_mouse_motion_filter: mrx=%d, mry=%d, mx=%d, my=%d\n",
-				//	mouse_relative_x, mouse_relative_y, event->motion.xrel, event->motion.yrel);
-				
-				// mouse_relative_* is already reset in 
-				// readmousexy(). It must not be
-				// reset here because calling this function does not mean
-				// we always handle the mouse. 
-				// FIX_00001: Mouse speed is uneven and slower in windowed mode vs fullscreen mode.
-			}
-			else
-				mouse_relative_x = mouse_relative_y = 0;
-	}
-
-    return(0);
-} /* sdl_mouse_motion_filter */
-
-
-    /*
-     * The windib driver can't alert us to the keypad enter key, which
-     *  Ken's code depends on heavily. It sends it as the same key as the
-     *  regular return key. These users will have to hit SHIFT-ENTER,
-     *  which we check for explicitly, and give the engine a keypad enter
-     *  enter event.
-     */
-static __inline int handle_keypad_enter_hack(const SDL_Event *event)
-{
-    static int kp_enter_hack = 0;
-    int retval = 0;
-
-    if (event->key.keysym.sym == SDLK_RETURN)
-    {
-        if (event->key.state == SDL_PRESSED)
-        {
-            if (event->key.keysym.mod & KMOD_SHIFT)
-            {
-                kp_enter_hack = 1;
-                lastkey = scancodes[SDLK_KP_ENTER];
-                retval = 1;
-            } /* if */
-        } /* if */
-
-        else  /* key released */
-        {
-            if (kp_enter_hack)
-            {
-                kp_enter_hack = 0;
-                lastkey = scancodes[SDLK_KP_ENTER];
-                retval = 1;
-            } /* if */
-        } /* if */
-    } /* if */
-
-    return(retval);
-} /* handle_keypad_enter_hack */
-
-void fullscreen_toggle_and_change_driver(void)
-{
-	
-//  FIX_00002: New Toggle Windowed/FullScreen system now simpler and will 
-//  dynamically change for Windib or Directx driver. Windowed/Fullscreen 
-//  toggle also made available from menu.
-//  Replace attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags)
-  	
-	int32_t x,y;
-	x = surface->w;
-	y = surface->h;
-
-	BFullScreen =!BFullScreen;
-	SDL_QuitSubSystem(SDL_INIT_VIDEO);
-	_platform_init(0, NULL, "Duke Nukem 3D", "Duke3D");
-	_setgamemode(ScreenMode,x,y);
-	//vscrn();
-
-	return;
-}
-
-static int sdl_key_filter(const SDL_Event *event)
-{
-    int extended;
-
-    if ( (event->key.keysym.sym == SDLK_m) &&
-         (event->key.state == SDL_PRESSED) &&
-         (event->key.keysym.mod & KMOD_CTRL) )
-    {
-
-
-		// FIX_00005: Mouse pointer can be toggled on/off (see mouse menu or use CTRL-M)
-		// This is usefull to move the duke window when playing in window mode.
-  
-        if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON) 
-		{
-            SDL_WM_GrabInput(SDL_GRAB_OFF);
-			SDL_ShowCursor(1);
-		}
-		else
-		{
-            SDL_WM_GrabInput(SDL_GRAB_ON);
-			SDL_ShowCursor(0);
-		}
-
-        return(0);
-    } /* if */
-
-    else if ( ( (event->key.keysym.sym == SDLK_RETURN) ||
-                (event->key.keysym.sym == SDLK_KP_ENTER) ) &&
-              (event->key.state == SDL_PRESSED) &&
-              (event->key.keysym.mod & KMOD_ALT) )
-    {	fullscreen_toggle_and_change_driver();
-
-		// hack to discard the ALT key...
-		lastkey=scancodes[SDLK_RALT]>>8; // extended
-		keyhandler();
-		lastkey=(scancodes[SDLK_RALT]&0xff)+0x80; // Simulating Key up
-		keyhandler();
-		lastkey=(scancodes[SDLK_LALT]&0xff)+0x80; // Simulating Key up (not extended)
-		keyhandler();
-		SDL_SetModState(KMOD_NONE); // SDL doesnt see we are releasing the ALT-ENTER keys
-        
-		return(0);					
-    }								
-
-    if (!handle_keypad_enter_hack(event))
-        lastkey = scancodes[event->key.keysym.sym];
-
-//	printf("key.keysym.sym=%d\n", event->key.keysym.sym);
-
-    if (lastkey == 0x0000)   /* No DOS equivalent defined. */
-        return(0);
-
-    extended = ((lastkey & 0xFF00) >> 8);
-    if (extended != 0)
-    {
-        lastkey = extended;
-        keyhandler();
-        lastkey = (scancodes[event->key.keysym.sym] & 0xFF);
-    } /* if */
-
-    if (event->key.state == SDL_RELEASED)
-        lastkey += 128;  /* +128 signifies that the key is released in DOS. */
-
-    keyhandler();
-    return(0);
-} /* sdl_key_filter */
-
-
-static int root_sdl_event_filter(const SDL_Event *event)
-{
-    switch (event->type)
-    {
-        case SDL_KEYUP:
-            // FIX_00003: Pause mode is now fully responsive - (Thx to Jonathon Fowler tips)
-			if(event->key.keysym.sym == SDLK_PAUSE)
-				break;
-        case SDL_KEYDOWN:
-            return(sdl_key_filter(event));
-        case SDL_JOYBUTTONDOWN:
-        case SDL_JOYBUTTONUP:
-            {
-                //Do Nothing
-
-                //printf("Joybutton UP/DOWN\n");
-	            //return(sdl_joystick_button_filter((const SDL_MouseButtonEvent*)event));
-                return 0;
-            }
-        case SDL_JOYBALLMOTION:
-        case SDL_MOUSEMOTION:
-            return(sdl_mouse_motion_filter(event));
-        case SDL_MOUSEBUTTONUP:
-        case SDL_MOUSEBUTTONDOWN:
-			return(sdl_mouse_button_filter((const SDL_MouseButtonEvent*)event));
-        case SDL_QUIT:
-            /* !!! rcg TEMP */
-            Error(EXIT_SUCCESS, "Exit through SDL\n"); 
-		default:
-			//printf("This event is not handled: %d\n",event->type);
-			break;
-    } /* switch */
-
-    return(1);
-} /* root_sdl_event_filter */
-
-
-static void handle_events(void)
-{
-    SDL_Event event;
-
-	while(SDL_PollEvent(&event))
-        root_sdl_event_filter(&event);
-} /* handle_events */
-
-
-/* bleh...public version... */
-void _handle_events(void)
-{
-    handle_events();
-} /* _handle_events */
-
-
-static SDL_Joystick *joystick = NULL;
-void _joystick_init(void)
-{
-    const char  *envr = getenv(BUILD_SDLJOYSTICK);
-    int favored = 0;
-    int numsticks;
-    int i;
-
-    if (joystick != NULL)
-    {
-        sdldebug("Joystick appears to be already initialized.");
-        sdldebug("...deinitializing for stick redetection...");
-        _joystick_deinit();
-    } /* if */
-
-    if ((envr != NULL) && (strcmp(envr, "none") == 0))
-    {
-        sdldebug("Skipping joystick detection/initialization at user request");
-        return;
-    } /* if */
-
-    sdldebug("Initializing SDL joystick subsystem...");
-    sdldebug(" (export environment variable BUILD_SDLJOYSTICK=none to skip)");
-
-    if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_NOPARACHUTE) != 0)
-    {
-        sdldebug("SDL_Init(SDL_INIT_JOYSTICK) failed: [%s].", SDL_GetError());
-        return;
-    } /* if */
-
-    numsticks = SDL_NumJoysticks();
-    sdldebug("SDL sees %d joystick%s.", numsticks, numsticks == 1 ? "" : "s");
-    if (numsticks == 0)
-        return;
-
-    for (i = 0; i < numsticks; i++)
-    {
-        const char  *stickname = SDL_JoystickName(i);
-        if ((envr != NULL) && (strcmp(envr, stickname) == 0))
-            favored = i;
-
-        sdldebug("Stick #%d: [%s]", i, stickname);
-    } /* for */
-
-    sdldebug("Using Stick #%d.", favored);
-    if ((envr == NULL) && (numsticks > 1))
-        sdldebug("Set BUILD_SDLJOYSTICK to one of the above names to change.");
-
-    joystick = SDL_JoystickOpen(favored);
-    if (joystick == NULL)
-    {
-        sdldebug("Joystick #%d failed to init: %s", favored, SDL_GetError());
-        return;
-    } /* if */
-
-    sdldebug("Joystick initialized. %d axes, %d buttons, %d hats, %d balls.",
-              SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
-              SDL_JoystickNumHats(joystick), SDL_JoystickNumBalls(joystick));
-
-    SDL_JoystickEventState(SDL_QUERY);
-} /* _joystick_init */
-
-
-void _joystick_deinit(void)
-{
-    if (joystick != NULL)
-    {
-        sdldebug("Closing joystick device...");
-        SDL_JoystickClose(joystick);
-        sdldebug("Joystick device closed. Deinitializing SDL subsystem...");
-        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-        sdldebug("SDL joystick subsystem deinitialized.");
-        joystick = NULL;
-    } /* if */
-} /* _joystick_deinit */
-
-
-int _joystick_update(void)
-{
-    if (joystick == NULL)
-        return(0);
-
-    SDL_JoystickUpdate();
-    return(1);
-} /* _joystick_update */
-
-
-int _joystick_axis(int axis)
-{
-    if (joystick == NULL)
-    {   
-        return(0);
-    }
-
-    return(SDL_JoystickGetAxis(joystick, axis));
-} /* _joystick_axis */
-
-int _joystick_hat(int hat)
-{
-    if (joystick == NULL)
-    {   
-        return(-1);
-    }
-
-    return(SDL_JoystickGetHat(joystick, hat));
-} /* _joystick_axis */
-
-int _joystick_button(int button)
-{
-    if (joystick == NULL)
-        return(0);
-
-    return(SDL_JoystickGetButton(joystick, button) != 0);
-} /* _joystick_button */
-
-
-uint8_t  _readlastkeyhit(void)
-{
-    return(lastkey);
-} /* _readlastkeyhit */
-
-
-static __inline void init_debugging(void)
-{
-    const char  *envr = getenv(BUILD_SDLDEBUG);
-
-    debug_hall_of_mirrors = (getenv(BUILD_HALLOFMIRRORS) != NULL);
-
-    if (_sdl_debug_file != NULL)
-    {
-        fclose(_sdl_debug_file);
-        _sdl_debug_file = NULL;
-    } /* if */
-
-    if (envr != NULL)
-    {
-        if (strcmp(envr, "-") == 0)
-	    _sdl_debug_file = stdout;
-        else
-            _sdl_debug_file = fopen(envr, "w");
-
-        if (_sdl_debug_file == NULL)
-            printf("BUILDSDL: -WARNING- Could not open debug file!\n");
-        else
-            setbuf(_sdl_debug_file, NULL);
-    } /* if */
-} /* init_debugging */
-
-
-#if (!defined __DATE__)
-#define __DATE__ "a long, int32_t time ago"
-#endif
-
-static __inline void output_sdl_versions(void)
-{
-    const SDL_version *linked_ver = SDL_Linked_Version();
-    SDL_version compiled_ver;
-
-    SDL_VERSION(&compiled_ver);
-
-    sdldebug("SDL display driver for the BUILD engine initializing.");
-    sdldebug("  sdl_driver.c by Ryan C. Gordon (icculus@clutteredmind.org).");
-    sdldebug("Compiled %s against SDL version %d.%d.%d ...", __DATE__,
-                compiled_ver.major, compiled_ver.minor, compiled_ver.patch);
-    sdldebug("Linked SDL version is %d.%d.%d ...",
-                linked_ver->major, linked_ver->minor, linked_ver->patch);
-} /* output_sdl_versions */
-
-
-/* lousy -ansi flag.  :) */
-static char  *string_dupe(const char  *str)
-{
-    char  *retval = malloc(strlen(str) + 1);
-    if (retval != NULL)
-        strcpy(retval, str);
-    return(retval);
-} /* string_dupe */
-
-
-void set_sdl_renderer(void)
-{
-    const char  *envr = getenv(BUILD_RENDERER);
-
-
-    if ((envr == NULL) || (strcmp(envr, ENVRSTR_RENDERER_SOFTWARE) == 0))
-        renderer = RENDERER_SOFTWARE;
-    else
-    {
-        fprintf(stderr,
-                "BUILDSDL: \"%s\" in the %s environment var is not available.\n",
-                envr, BUILD_RENDERER);
-        _exit(1);
-    } /* else */
-
-#ifdef __APPLE__
-    SDL_putenv("SDL_VIDEODRIVER=Quartz");
-#endif
-    
-    if (SDL_Init(SDL_INIT_VIDEO) == -1)
-    {
-		Error(EXIT_FAILURE, "BUILDSDL: SDL_Init() failed!\n"
-							"BUILDSDL: SDL_GetError() says \"%s\".\n", SDL_GetError());
-    } /* if */
-
-} /* set_sdl_renderer */
-
-
-static void init_renderer_names(void)
-{
-    memset((void *) renderer_name, '\0', sizeof (renderer_name));
-    renderer_name[RENDERER_SOFTWARE] = "RENDERER_SOFTWARE";
-    renderer_name[RENDERER_OPENGL3D] = "RENDERER_OPENGL3D";
-} /* init_renderer_names */
-
-
-
-//#include "mmulti_stable.h"
-void Setup_UnstableNetworking()
-{
-	nNetMode = 0;
-}
-
-void Setup_StableNetworking()
-{
-	nNetMode = 1;
-}
-
-
-void _platform_init(int argc, char  **argv, const char  *title, const char  *iconName)
-{
-    int i;
-	int64_t timeElapsed;
-	char  dummyString[4096];
-
-    _argc = argc;
-    _argv = argv;
-
-	// FIX_00061: "ERROR: Two players have the same random ID" too frequent cuz of internet windows times
-    TIMER_GetPlatformTicks(&timeElapsed);
-	srand(timeElapsed&0xFFFFFFFF);
-
-	Setup_UnstableNetworking();
-
-    // Look through the command line args
-    for(i = 0; i < argc; i++)
-    {
-        if(argv[i][0] == '-' )
-        {
-            if(strcmpi(argv[i], "-netmode_stable") == 0)
-            {
-                //fullscreen = 1;
-				//TODO:
-//TODO ( "[Todo: handle -netmode <int>]" )
-				Setup_StableNetworking();
-					
-            }
-        }
-    }
-
-	// Set up the correct renderer
-	// Becarfull setenv can't reach dll in VC++
-	// A way to proceed is to integrate the SDL libs
-	// in the exe instead.
-	
-    // FIX_00004: SDL.dll and SDL_Mixer.dll are now integrated within the exe
-    // (this also makes the Windib/Directx driver switching easier with SDL)		
-
-    // This requires to recompile the whole sdl and sdl mixer with the lib
-    // switch instead of the default dll switch.
-	if( BFullScreen )
-	{
-		putenv("SDL_VIDEODRIVER=directx");
-		printf("FullScreen Mode, trying directx\n");
-	}
-	else
-	{
-		putenv("SDL_VIDEODRIVER=windib");
-		printf("Window Mode, trying windib\n");
-	}
-
-	putenv("SDL_VIDEO_CENTERED=1");
-
-    init_renderer_names();
-
-    init_debugging();
-
-    if (title == NULL)
-        title = "BUILD";
-
-    if (iconName == NULL)
-        iconName = "BUILD";
-
-    titleNameLong = string_dupe(title);
-    titleNameShort = string_dupe(iconName);
-
-    sdl_flags = BFullScreen ? SDL_FULLSCREEN : 0;
-
-    sdl_flags |= SDL_HWPALETTE;
-   
-//	// These flags cause duke to exit on fullscreen
-//	/*
-	if(!BFullScreen)
-	{
-	//	sdl_flags |= SDL_HWSURFACE;   //!!!
-	//	sdl_flags |= SDL_DOUBLEBUF; //
-	}
-//	*/
-	
-	
-
-    memset(scancodes, '\0', sizeof (scancodes));
-    scancodes[SDLK_ESCAPE]          = 0x01;
-    scancodes[SDLK_1]               = 0x02;
-    scancodes[SDLK_2]               = 0x03;
-    scancodes[SDLK_3]               = 0x04;
-    scancodes[SDLK_4]               = 0x05;
-    scancodes[SDLK_5]               = 0x06;
-    scancodes[SDLK_6]               = 0x07;
-    scancodes[SDLK_7]               = 0x08;
-    scancodes[SDLK_8]               = 0x09;
-    scancodes[SDLK_9]               = 0x0A;
-    scancodes[SDLK_0]               = 0x0B;
-    scancodes[SDLK_MINUS]           = 0x0C; /* was 0x4A */
-    scancodes[SDLK_EQUALS]          = 0x0D; /* was 0x4E */
-    scancodes[SDLK_BACKSPACE]       = 0x0E;
-    scancodes[SDLK_TAB]             = 0x0F;
-    scancodes[SDLK_q]               = 0x10;
-    scancodes[SDLK_w]               = 0x11;
-    scancodes[SDLK_e]               = 0x12;
-    scancodes[SDLK_r]               = 0x13;
-    scancodes[SDLK_t]               = 0x14;
-    scancodes[SDLK_y]               = 0x15;
-    scancodes[SDLK_u]               = 0x16;
-    scancodes[SDLK_i]               = 0x17;
-    scancodes[SDLK_o]               = 0x18;
-    scancodes[SDLK_p]               = 0x19;
-    scancodes[SDLK_LEFTBRACKET]     = 0x1A;
-    scancodes[SDLK_RIGHTBRACKET]    = 0x1B;
-    scancodes[SDLK_RETURN]          = 0x1C;
-    scancodes[SDLK_LCTRL]           = 0x1D;
-    scancodes[SDLK_a]               = 0x1E;
-    scancodes[SDLK_s]               = 0x1F;
-    scancodes[SDLK_d]               = 0x20;
-    scancodes[SDLK_f]               = 0x21;
-    scancodes[SDLK_g]               = 0x22;
-    scancodes[SDLK_h]               = 0x23;
-    scancodes[SDLK_j]               = 0x24;
-    scancodes[SDLK_k]               = 0x25;
-    scancodes[SDLK_l]               = 0x26;
-    scancodes[SDLK_SEMICOLON]       = 0x27;
-    scancodes[SDLK_QUOTE]           = 0x28;
-    scancodes[SDLK_BACKQUOTE]       = 0x29;
-    scancodes[SDLK_LSHIFT]          = 0x2A;
-    scancodes[SDLK_BACKSLASH]       = 0x2B;
-    scancodes[SDLK_z]               = 0x2C;
-    scancodes[SDLK_x]               = 0x2D;
-    scancodes[SDLK_c]               = 0x2E;
-    scancodes[SDLK_v]               = 0x2F;
-    scancodes[SDLK_b]               = 0x30;
-    scancodes[SDLK_n]               = 0x31;
-    scancodes[SDLK_m]               = 0x32;
-    scancodes[SDLK_COMMA]           = 0x33;
-    scancodes[SDLK_PERIOD]          = 0x34;
-    scancodes[SDLK_SLASH]           = 0x35;
-    scancodes[SDLK_RSHIFT]          = 0x36;
-    scancodes[SDLK_KP_MULTIPLY]     = 0x37;
-    scancodes[SDLK_LALT]            = 0x38;
-    scancodes[SDLK_SPACE]           = 0x39;
-    scancodes[SDLK_CAPSLOCK]        = 0x3A;
-    scancodes[SDLK_F1]              = 0x3B;
-    scancodes[SDLK_F2]              = 0x3C;
-    scancodes[SDLK_F3]              = 0x3D;
-    scancodes[SDLK_F4]              = 0x3E;
-    scancodes[SDLK_F5]              = 0x3F;
-    scancodes[SDLK_F6]              = 0x40;
-    scancodes[SDLK_F7]              = 0x41;
-    scancodes[SDLK_F8]              = 0x42;
-    scancodes[SDLK_F9]              = 0x43;
-    scancodes[SDLK_F10]             = 0x44;
-    scancodes[SDLK_NUMLOCK]         = 0x45;
-    scancodes[SDLK_SCROLLOCK]       = 0x46;
-    scancodes[SDLK_KP7]             = 0x47;
-    scancodes[SDLK_KP8]             = 0x48;
-    scancodes[SDLK_KP9]             = 0x49;
-    scancodes[SDLK_KP_MINUS]        = 0x4A;
-    scancodes[SDLK_KP4]             = 0x4B;
-    scancodes[SDLK_KP5]             = 0x4C;
-    scancodes[SDLK_KP6]             = 0x4D;
-    scancodes[SDLK_KP_PLUS]         = 0x4E;
-    scancodes[SDLK_KP1]             = 0x4F;
-    scancodes[SDLK_KP2]             = 0x50;
-    scancodes[SDLK_KP3]             = 0x51;
-    scancodes[SDLK_KP0]             = 0x52;
-    scancodes[SDLK_KP_PERIOD]       = 0x53;
-    scancodes[SDLK_F11]             = 0x57;
-    scancodes[SDLK_F12]             = 0x58;
-    scancodes[SDLK_PAUSE]           = 0x59; /* SBF - technically incorrect */
-
-    scancodes[SDLK_KP_ENTER]        = 0xE01C;
-    scancodes[SDLK_RCTRL]           = 0xE01D;
-    scancodes[SDLK_KP_DIVIDE]       = 0xE035;
-    scancodes[SDLK_PRINT]           = 0xE037; /* SBF - technically incorrect */
-    scancodes[SDLK_SYSREQ]          = 0xE037; /* SBF - for windows... */
-    scancodes[SDLK_RALT]            = 0xE038;
-    scancodes[SDLK_HOME]            = 0xE047;
-    scancodes[SDLK_UP]              = 0xE048;
-    scancodes[SDLK_PAGEUP]          = 0xE049;
-    scancodes[SDLK_LEFT]            = 0xE04B;
-    scancodes[SDLK_RIGHT]           = 0xE04D;
-    scancodes[SDLK_END]             = 0xE04F;
-    scancodes[SDLK_DOWN]            = 0xE050;
-    scancodes[SDLK_PAGEDOWN]        = 0xE051;
-    scancodes[SDLK_INSERT]          = 0xE052;
-    scancodes[SDLK_DELETE]          = 0xE053;
-    
-    set_sdl_renderer();
-
-    output_sdl_versions();
-    output_driver_info();
-    
-
-	printf("Video Driver [directx or windib]? -> %s \n", SDL_VideoDriverName(dummyString, 20));
-
-} /* _platform_init */
-
-
-int setvesa(int32_t x, int32_t y)
-{
-	Error(EXIT_FAILURE, "setvesa() called in SDL driver\n");
-    return(0);
-} /* setvesa */
-
-
-// Capture BMP of the current frame
-int screencapture(char  *filename, uint8_t  inverseit)
-{
-//  FIX_00006: better naming system for screenshots + message when pic is taken. 
-//  Use ./screenshots folder. Screenshot code rerwritten. Faster and
-//  makes smaller files. Doesn't freeze or lag the game anymore.
-  
-	SDL_SaveBMP(surface, filename);  
-	return 0;
-} /* screencapture */
-
-
-void setvmode(int mode)
-{
-
-    if (mode == 0x3)  /* text mode. */
-    {
-        SDL_QuitSubSystem(SDL_INIT_VIDEO);
-        return;
-    } else
-        printf("setvmode(0x%x) is unsupported in SDL driver.\n", mode);
-
-} 
-
-int _setgamemode(uint8_t  davidoption, int32_t daxdim, int32_t daydim)
-{
-	int validated, i;
-	SDL_Surface     *image;
-	Uint32          colorkey;
-
-	// Install icon
-	image = SDL_LoadBMP_RW(SDL_RWFromMem(iconBMP, sizeof(iconBMP)), 1);
-	// image = SDL_LoadBMP("nuclear2.bmp");
-	// colorkey = SDL_MapRGB(image->format, 252, 254, 252); // to lookup idx in true color img
-	colorkey = 0; // index in this image to be transparent
-	SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
-	SDL_WM_SetIcon(image,NULL);
-
-    if (daxdim > MAXXDIM || daydim > MAXYDIM)
-    {
-		printf("%d x %d is too big. Changed to %d x %d\n", daxdim, daydim, MAXXDIM,MAXYDIM);
-	    daxdim = MAXXDIM;
-	    daydim = MAXYDIM;
-    } 
-
-	getvalidvesamodes();
-
-	validated = 0;
-	for(i=0; i<validmodecnt; i++)
-	{
-		if(validmodexdim[i] == daxdim && validmodeydim[i] == daydim)
-			validated = 1;
-	}
-
-	if(!validated)
-    {
-		printf("%d x %d unsupported. Changed to 640 x 480\n", daxdim, daydim);
-	    daxdim = 640;
-	    daydim = 480;
-    }
-
-    go_to_new_vid_mode((int) davidoption, daxdim, daydim);
-
-    qsetmode = 200;
-    last_render_ticks = getticks();
-
-    return(0);
-} /* setgamemode */
-
-
-static int get_dimensions_from_str(const char  *str, int32_t *_w, int32_t *_h)
-{
-    char  *xptr = NULL;
-    char  *ptr = NULL;
-    int32_t w = -1;
-    int32_t h = -1;
-
-    if (str == NULL)
-        return(0);
-
-    xptr = strchr(str, 'x');
-    if (xptr == NULL)
-        return(0);
-
-    w = strtol(str, &ptr, 10);
-    if (ptr != xptr)
-        return(0);
-
-    xptr++;
-    h = strtol(xptr, &ptr, 10);
-    if ( (*xptr == '\0') || (*ptr != '\0') )
-        return(0);
-
-    if ((w <= 1) || (h <= 1))
-        return(0);
-
-    if (_w != NULL)
-        *_w = w;
-
-    if (_h != NULL)
-        *_h = h;
-
-    return(1);
-} /* get_dimensions_from_str */
-
-
-static __inline void get_max_screen_res(int32_t *max_w, int32_t *max_h)
-{
-    int32_t w = DEFAULT_MAXRESWIDTH;
-    int32_t h = DEFAULT_MAXRESHEIGHT;
-    const char  *envr = getenv(BUILD_MAXSCREENRES);
-
-    if (envr != NULL)
-    {
-        if (!get_dimensions_from_str(envr, &w, &h))
-        {
-            sdldebug("User's resolution ceiling [%s] is bogus!", envr);
-            w = DEFAULT_MAXRESWIDTH;
-            h = DEFAULT_MAXRESHEIGHT;
-        } /* if */
-    } /* if */
-
-    if (max_w != NULL)
-        *max_w = w;
-
-    if (max_h != NULL)
-        *max_h = h;
-} /* get_max_screen_res */
-
-
-static void add_vesa_mode(const char  *typestr, int w, int h)
-{
-    sdldebug("Adding %s resolution (%dx%d).", typestr, w, h);
-    validmode[validmodecnt] = validmodecnt;
-    validmodexdim[validmodecnt] = w;
-    validmodeydim[validmodecnt] = h;
-    validmodecnt++;
-} /* add_vesa_mode */
-
-
-/* Let the user specify a specific mode via environment variable. */
-static __inline void add_user_defined_resolution(void)
-{
-    int32_t w;
-    int32_t h;
-    const char  *envr = getenv(BUILD_USERSCREENRES);
-
-    if (envr == NULL)
-        return;
-
-    if (get_dimensions_from_str(envr, &w, &h))
-        add_vesa_mode("user defined", w, h);
-    else
-        sdldebug("User defined resolution [%s] is bogus!", envr);
-} /* add_user_defined_resolution */
-
-
-static __inline SDL_Rect **get_physical_resolutions(void)
-{
-    const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
-    SDL_Rect **modes = SDL_ListModes(vidInfo->vfmt, sdl_flags | SDL_FULLSCREEN);
-    if (modes == NULL)
-    {
-        sdl_flags &= ~SDL_FULLSCREEN;
-        modes = SDL_ListModes(vidInfo->vfmt, sdl_flags); /* try without fullscreen. */
-        if (modes == NULL)
-            modes = (SDL_Rect **) -1;  /* fuck it. */
-    } /* if */
-
-    if (modes == (SDL_Rect **) -1)
-        sdldebug("Couldn't get any physical resolutions.");
-    else
-    {
-        sdldebug("Highest physical resolution is (%dx%d).",
-                  modes[0]->w, modes[0]->h);
-    } /* else */
-
-    return(modes);
-} /* get_physical_resolutions */
-
-
-static void remove_vesa_mode(int index, const char  *reason)
-{
-    int i;
-
-    assert(index < validmodecnt);
-    sdldebug("Removing resolution #%d, %dx%d [%s].",
-              index, validmodexdim[index], validmodeydim[index], reason);
-
-    for (i = index; i < validmodecnt - 1; i++)
-    {
-        validmode[i] = validmode[i + 1];
-        validmodexdim[i] = validmodexdim[i + 1];
-        validmodeydim[i] = validmodeydim[i + 1];
-    } /* for */
-
-    validmodecnt--;
-} /* remove_vesa_mode */
-
-
-static __inline void cull_large_vesa_modes(void)
-{
-    int32_t max_w;
-    int32_t max_h;
-    int i;
-
-    get_max_screen_res(&max_w, &max_h);
-    sdldebug("Setting resolution ceiling to (%ldx%ld).", max_w, max_h);
-
-    for (i = 0; i < validmodecnt; i++)
-    {
-        if ((validmodexdim[i] > max_w) || (validmodeydim[i] > max_h))
-        {
-            remove_vesa_mode(i, "above resolution ceiling");
-            i--;  /* list shrinks. */
-        } /* if */
-    } /* for */
-} /* cull_large_vesa_modes */
-
-
-static __inline void cull_duplicate_vesa_modes(void)
-{
-    int i;
-    int j;
-
-    for (i = 0; i < validmodecnt; i++)
-    {
-        for (j = i + 1; j < validmodecnt; j++)
-        {
-            if ( (validmodexdim[i] == validmodexdim[j]) &&
-                 (validmodeydim[i] == validmodeydim[j]) )
-            {
-                remove_vesa_mode(j, "duplicate");
-                j--;  /* list shrinks. */
-            } /* if */
-        } /* for */
-    } /* for */
-} /* cull_duplicate_vesa_modes */
-
-
-#define swap_macro(tmp, x, y) { tmp = x; x = y; y = tmp; }
-
-/* be sure to call cull_duplicate_vesa_modes() before calling this. */
-static __inline void sort_vesa_modelist(void)
-{
-    int i;
-    int sorted;
-    int32_t tmp;
-
-    do
-    {
-        sorted = 1;
-        for (i = 0; i < validmodecnt - 1; i++)
-        {
-            if ( (validmodexdim[i] >= validmodexdim[i+1]) &&
-                 (validmodeydim[i] >= validmodeydim[i+1]) )
-            {
-                sorted = 0;
-                swap_macro(tmp, validmode[i], validmode[i+1]);
-                swap_macro(tmp, validmodexdim[i], validmodexdim[i+1]);
-                swap_macro(tmp, validmodeydim[i], validmodeydim[i+1]);
-            } /* if */
-        } /* for */
-    } while (!sorted);
-} /* sort_vesa_modelist */
-
-
-static __inline void cleanup_vesa_modelist(void)
-{
-    cull_large_vesa_modes();
-    cull_duplicate_vesa_modes();
-    sort_vesa_modelist();
-} /* cleanup_vesa_modelist */
-
-
-static __inline void output_vesa_modelist(void)
-{
-    char  buffer[256];
-    char  numbuf[20];
-    int i;
-
-    if (!_sdl_debug_file)
-        return;
-
-    buffer[0] = '\0';
-
-    for (i = 0; i < validmodecnt; i++)
-    {
-        sprintf(numbuf, " (%dx%d)",(int32_t) validmodexdim[i], (int32_t) validmodeydim[i]);
-
-        if ( (strlen(buffer) + strlen(numbuf)) >= (sizeof (buffer) - 1) )
-            strcpy(buffer + (sizeof (buffer) - 5), " ...");
-        else
-            strcat(buffer, numbuf);
-    } /* for */
-
-    sdldebug("Final sorted modelist:%s", buffer);
-} /* output_vesa_modelist */
-
-
-void getvalidvesamodes(void)
-{
-    static int already_checked = 0;
-    int i;
-    SDL_Rect **modes = NULL;
-    int stdres[][2] = {
-                        {320, 200}, {640, 350}, {640, 480},
-                        {800, 600}, {1024, 768}
-                      };
-
-    if (already_checked)
-        return;
-
-    already_checked = 1;
-   	validmodecnt = 0;
-    vidoption = 1;  /* !!! tmp */
-
-        /* fill in the standard resolutions... */
-    for (i = 0; i < sizeof (stdres) / sizeof (stdres[0]); i++)
-        add_vesa_mode("standard", stdres[i][0], stdres[i][1]);
-
-         /* Anything the hardware can specifically do is added now... */
-    modes = get_physical_resolutions();
-    for (i = 0; (modes != (SDL_Rect **) -1) && (modes[i] != NULL); i++)
-        add_vesa_mode("physical", modes[i]->w, modes[i]->h);
-
-        /* Now add specific resolutions that the user wants... */
-    add_user_defined_resolution();
-
-        /* get rid of dupes and bogus resolutions... */
-    cleanup_vesa_modelist();
-
-        /* print it out for debugging purposes... */
-    output_vesa_modelist();
-} /* getvalidvesamodes */
-
-
-int VBE_setPalette(int32_t start, int32_t num, uint8_t  *palettebuffer)
-/*
- * (From Ken's docs:)
- *   Set (num) palette palette entries starting at (start)
- *   palette entries are in a 4-byte format in this order:
- *       0: Blue (0-63)
- *       1: Green (0-63)
- *       2: Red (0-63)
- *       3: Reserved
- *
- * Naturally, the bytes are in the reverse order that SDL wants them...
- *  More importantly, SDL wants the color elements in a range from 0-255,
- *  so we do a conversion.
- */
-{
-    SDL_Color fmt_swap[256];
-    SDL_Color *sdlp = &fmt_swap[start];
-    uint8_t  *p = palettebuffer;
-    int i;
-    assert( (start + num) <= (sizeof (fmt_swap) / sizeof (SDL_Color)) );
-
-    for (i = 0; i < num; i++)
-    {
-        sdlp->b = (Uint8) ((((float) *p++) / 63.0) * 255.0);
-        sdlp->g = (Uint8) ((((float) *p++) / 63.0) * 255.0);
-        sdlp->r = (Uint8) ((((float) *p++) / 63.0) * 255.0);
-        sdlp->unused = *p++;   /* This byte is unused in BUILD, too. */
-        sdlp++;
-    } /* for */
-
-    return(SDL_SetColors(surface, fmt_swap, start, num));
-} /* VBE_setPalette */
-
-
-int VBE_getPalette(int32_t start, int32_t num, uint8_t  *palettebuffer)
-{
-    SDL_Color *sdlp = surface->format->palette->colors + start;
-    uint8_t  *p = palettebuffer + (start * 4);
-    int i;
-
-    for (i = 0; i < num; i++)
-    {
-        *p++ = (Uint8) ((((float) sdlp->b) / 255.0) * 63.0);
-        *p++ = (Uint8) ((((float) sdlp->g) / 255.0) * 63.0);
-        *p++ = (Uint8) ((((float) sdlp->r) / 255.0) * 63.0);
-        *p++ = sdlp->unused;   /* This byte is unused in both SDL and BUILD. */
-        sdlp++;
-    } /* for */
-
-    return(1);
-} /* VBE_getPalette */
-
-
-void _uninitengine(void)
-{
-   SDL_QuitSubSystem(SDL_INIT_VIDEO);
-} /* _uninitengine */
-
-
-
-
-int setupmouse(void)
-{
-
-	SDL_Event event;
-
-    if (surface == NULL)
-        return(0);
-
-    SDL_WM_GrabInput(SDL_GRAB_ON);
-    SDL_ShowCursor(0);
-
-    mouse_relative_x = mouse_relative_y = 0;
-
-        /*
-         * this global usually gets set by BUILD, but it's a one-shot
-         *  deal, and we may not have an SDL surface at that point. --ryan.
-         */
-    moustat = 1;
-
-	// FIX_00063: Duke's angle changing or incorrect when using toggle fullscreen/window mode
-	while(SDL_PollEvent(&event)); // Empying the various pending events (especially the mouse one)
-
-	//SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
-
-    return(1);
-} /* setupmouse */
-
-
-void readmousexy(short *x, short *y)
-{
-    if (x) *x = mouse_relative_x << 2;
-    if (y) *y = mouse_relative_y << 2;
-
-    mouse_relative_x = mouse_relative_y = 0;
-} /* readmousexy */
-
-
-void readmousebstatus(short *bstatus)
-{
-    if (bstatus)
-        *bstatus = mouse_buttons;
-
-    // special wheel treatment: make it like a button click
-    if(mouse_buttons&8) mouse_buttons ^= 8;
-    if(mouse_buttons&16) mouse_buttons ^= 16;
-
-} /* readmousebstatus */
-
-
-static uint8_t  mirrorcolor = 0;
-
-void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h)
-{
-    if (renderer == RENDERER_SOFTWARE)
-        SDL_UpdateRect(surface, x, y, w, h);
-} /* _updatescreenrect */
-
-
-void _nextpage(void)
-{
-    Uint32 ticks;
-
-    _handle_events();
-
-    if (renderer == RENDERER_SOFTWARE)
-    {
-		// FIX_00085: Optimized Video driver. FPS increases by +20%.
-        // SDL_Flip(surface);
-		SDL_UpdateRect(surface, 0, 0, 0, 0);
-    }
-
-
-    if ((debug_hall_of_mirrors) && (qsetmode == 200) && (frameplace))
-    {
-        memset((void *) frameplace, mirrorcolor, surface->w * surface->h);
-        mirrorcolor++;
-    } /* if */
-
-    ticks = getticks();
-    total_render_time = (ticks - last_render_ticks);
-    if (total_render_time > 1000)
-    {
-        total_rendered_frames = 0;
-        total_render_time = 1;
-        last_render_ticks = ticks;
-    } /* if */
-    total_rendered_frames++;
-} /* _nextpage */
-
-
-uint8_t  readpixel(int32_t offset)
-{
-    return( *((uint8_t  *) offset) );
-} /* readpixel */
-
-void drawpixel(int32_t offset, uint8_t  pixel)
-{
-    *((uint8_t  *) offset) = pixel;
-} /* drawpixel */
-
-
-/* !!! These are incorrect. */
-void drawpixels(int32_t offset, uint16_t pixels)
-{
-    Uint8 *surface_end;
-    Uint16 *pos;
-
-                Error(EXIT_FAILURE, "Blargh!\n");
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_LockSurface(surface);
-
-    surface_end = (((Uint8 *) surface->pixels) + (surface->w * surface->h)) - 2;
-    pos = (Uint16 *) (((Uint8 *) surface->pixels) + offset);
-    if ((pos >= (Uint16 *) surface->pixels) && (pos < (Uint16 *) surface_end))
-        *pos = pixels;
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_UnlockSurface(surface);
-} /* drawpixels */
-
-
-void drawpixelses(int32_t offset, unsigned int pixelses)
-{
-    Uint8 *surface_end;
-    Uint32 *pos;
-
-                Error(EXIT_FAILURE, "Blargh!\n");
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_LockSurface(surface);
-
-    surface_end = (((Uint8 *)surface->pixels) + (surface->w * surface->h)) - 2;
-    pos = (Uint32 *) (((Uint8 *) surface->pixels) + offset);
-    if ((pos >= (Uint32 *) surface->pixels) && (pos < (Uint32 *) surface_end))
-        *pos = pixelses;
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_UnlockSurface(surface);
-} /* drawpixelses */
-
-
-/* Fix this up The Right Way (TM) - DDOI */
-void setcolor16(int col)
-{
-	drawpixel_color = col;
-}
-
-void drawpixel16(int32_t offset)
-{
-    drawpixel(((int32_t) surface->pixels + offset), drawpixel_color);
-} /* drawpixel16 */
-
-
-void fillscreen16(int32_t offset, int32_t color, int32_t blocksize)
-{
-    Uint8 *surface_end;
-    Uint8 *wanted_end;
-    Uint8 *pixels;
-
-	if (SDL_MUSTLOCK(surface))
-        SDL_LockSurface(surface);
-
-    pixels = get_framebuffer();
-
-    /* Make this function pageoffset aware - DDOI */
-    if (!pageoffset) { 
-	    offset = offset << 3;
-	    offset += 640*336;
-    }
-
-    surface_end = (pixels + (surface->w * surface->h)) - 1;
-    wanted_end = (pixels + offset) + blocksize;
-
-    if (offset < 0)
-        offset = 0;
-
-    if (wanted_end > surface_end)
-        blocksize = ((uint32_t) surface_end) - ((uint32_t) pixels + offset);
-
-    memset(pixels + offset, (int) color, blocksize);
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_UnlockSurface(surface);
-
-    _nextpage();
-} /* fillscreen16 */
-
-
-/* Most of this line code is taken from Abrash's "Graphics Programming Blackbook".
-Remember, sharing code is A Good Thing. AH */
-static __inline void DrawHorizontalRun (uint8_t  **ScreenPtr, int XAdvance, int RunLength, uint8_t  Color)
-{
-    int i;
-    uint8_t  *WorkingScreenPtr = *ScreenPtr;
-
-    for (i=0; i<RunLength; i++)
-    {
-        *WorkingScreenPtr = Color;
-        WorkingScreenPtr += XAdvance;
-    }
-    WorkingScreenPtr += surface->w;
-    *ScreenPtr = WorkingScreenPtr;
-}
-
-static __inline void DrawVerticalRun (uint8_t  **ScreenPtr, int XAdvance, int RunLength, uint8_t  Color)
-{
-    int i;
-    uint8_t  *WorkingScreenPtr = *ScreenPtr;
-
-    for (i=0; i<RunLength; i++)
-    {
-      	*WorkingScreenPtr = Color;
-    	WorkingScreenPtr += surface->w;
-    }
-    WorkingScreenPtr += XAdvance;
-    *ScreenPtr = WorkingScreenPtr;
-}
-
-void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t  Color)
-{
-    int Temp, AdjUp, AdjDown, ErrorTerm, XAdvance, XDelta, YDelta;
-    int WholeStep, InitialPixelCount, FinalPixelCount, i, RunLength;
-    uint8_t  *ScreenPtr;
-    int32_t dx, dy;
-
-    if (SDL_MUSTLOCK(surface))
-        SDL_LockSurface(surface);
-
-	dx = XEnd-XStart; dy = YEnd-YStart;
-	if (dx >= 0)
-	{
-		if ((XStart > 639) || (XEnd < 0)) return;
-		if (XStart < 0) { if (dy) YStart += scale(0-XStart,dy,dx); XStart = 0; }
-		if (XEnd > 639) { if (dy) YEnd += scale(639-XEnd,dy,dx); XEnd = 639; }
-	}
-	else
-	{
-		if ((XEnd > 639) || (XStart < 0)) return;
-		if (XEnd < 0) { if (dy) YEnd += scale(0-XEnd,dy,dx); XEnd = 0; }
-		if (XStart > 639) { if (dy) YStart += scale(639-XStart,dy,dx); XStart = 639; }
-	}
-	if (dy >= 0)
-	{
-		if ((YStart >= ydim16) || (YEnd < 0)) return;
-		if (YStart < 0) { if (dx) XStart += scale(0-YStart,dx,dy); YStart = 0; }
-		if (YEnd >= ydim16) { if (dx) XEnd += scale(ydim16-1-YEnd,dx,dy); YEnd = ydim16-1; }
-	}
-	else
-	{
-		if ((YEnd >= ydim16) || (YStart < 0)) return;
-		if (YEnd < 0) { if (dx) XEnd += scale(0-YEnd,dx,dy); YEnd = 0; }
-		if (YStart >= ydim16) { if (dx) XStart += scale(ydim16-1-YStart,dx,dy); YStart = ydim16-1; }
-	}
-
-	/* Make sure the status bar border draws correctly - DDOI */
-	if (!pageoffset) { YStart += 336; YEnd += 336; }
-
-    /* We'll always draw top to bottom */
-    if (YStart > YEnd) {
-        Temp = YStart;
-        YStart = YEnd;
-        YEnd = Temp;
-        Temp = XStart;
-        XStart = XEnd;
-        XEnd = Temp;
-    }
-
-    /* Point to the bitmap address first pixel to draw */
-    ScreenPtr = (uint8_t  *) (get_framebuffer()) + XStart + (surface->w * YStart);
-
-    /* Figure out whether we're going left or right, and how far we're going horizontally */
-    if ((XDelta = XEnd - XStart) < 0)
-    {
-        XAdvance = (-1);
-        XDelta = -XDelta;
-    } else {
-        XAdvance = 1;
-    }
-
-    /* Figure out how far we're going vertically */
-    YDelta = YEnd - YStart;
-
-    /* Special cases: Horizontal, vertical, and diagonal lines */
-    if (XDelta == 0)
-    {
-        for (i=0; i <= YDelta; i++)
-        {
-            *ScreenPtr = Color;
-            ScreenPtr += surface->w;
-        }
-
-        UNLOCK_SURFACE_AND_RETURN;
-    }
-    if (YDelta == 0)
-    {
-    	for (i=0; i <= XDelta; i++)
-    	{
-      	    *ScreenPtr = Color;
-    	    ScreenPtr += XAdvance;
-    	}
-        UNLOCK_SURFACE_AND_RETURN;
-    }
-    if (XDelta == YDelta)
-    {
-    	for (i=0; i <= XDelta; i++)
-        {
-            *ScreenPtr = Color;
-            ScreenPtr += XAdvance + surface->w;
-        }
-        UNLOCK_SURFACE_AND_RETURN;
-    }
-
-    /* Determine whether the line is X or Y major, and handle accordingly */
-    if (XDelta >= YDelta) /* X major line */
-    {
-        WholeStep = XDelta / YDelta;
-        AdjUp = (XDelta % YDelta) * 2;
-        AdjDown = YDelta * 2;
-        ErrorTerm = (XDelta % YDelta) - (YDelta * 2);
-
-        InitialPixelCount = (WholeStep / 2) + 1;
-        FinalPixelCount = InitialPixelCount;
-
-        if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount--;
-        if ((WholeStep & 0x01) != 0) ErrorTerm += YDelta;
-
-        DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
-
-        for (i=0; i<(YDelta-1); i++)
-        {
-            RunLength = WholeStep;
-            if ((ErrorTerm += AdjUp) > 0)
-            {
-        	RunLength ++;
-        	ErrorTerm -= AdjDown;
-            }
-
-            DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
-         }
-
-         DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
-
-         UNLOCK_SURFACE_AND_RETURN;
-    } else {	/* Y major line */
-    	WholeStep = YDelta / XDelta;
-    	AdjUp = (YDelta % XDelta) * 2;
-    	AdjDown = XDelta * 2;
-        ErrorTerm = (YDelta % XDelta) - (XDelta * 2);
-        InitialPixelCount = (WholeStep / 2) + 1;
-        FinalPixelCount = InitialPixelCount;
-
-        if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount --;
-        if ((WholeStep & 0x01) != 0) ErrorTerm += XDelta;
-
-        DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
-
-        for (i=0; i<(XDelta-1); i++)
-        {
-            RunLength = WholeStep;
-            if ((ErrorTerm += AdjUp) > 0)
-            {
-            	RunLength ++;
-            	ErrorTerm -= AdjDown;
-            }
-
-            DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
-        }
-
-        DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
-        UNLOCK_SURFACE_AND_RETURN;
-     }
-} /* drawline16 */
-
-
-void clear2dscreen(void)
-{
-    SDL_Rect rect;
-
-    rect.x = rect.y = 0;
-    rect.w = surface->w;
-
-	if (qsetmode == 350)
-        rect.h = 350;
-	else if (qsetmode == 480)
-	{
-		if (ydim16 <= 336)
-            rect.h = 336;
-        else
-            rect.h = 480;
-	} /* else if */
-
-    SDL_FillRect(surface, &rect, 0);
-} /* clear2dscreen */
-
-
-void _idle(void)
-{
-    if (surface != NULL)
-        _handle_events();
-    SDL_Delay(1);
-} /* _idle */
-
-void *_getVideoBase(void)
-{
-    return((void *) surface->pixels);
-}
-
-
-//-------------------------------------------------------------------------------------------------
-//  TIMER
-//=================================================================================================
-
-
-
-
-// FIX_00007: game speed corrected. The game speed is now as the real
-// DOS duke3d. Unloading a full 200 bullet pistol must take 45.1 sec.
-// SDL timer was not fast/accurate enough and was slowing down the gameplay,
-// so bad
-
-
-static int64_t timerfreq=0;
-static int32_t timerlastsample=0;
-static int timerticspersec=0;
-static void (*usertimercallback)(void) = NULL;
-
-//  This timer stuff is all Ken's idea.
-
-//
-// installusertimercallback() -- set up a callback function to be called when the timer is fired
-//
-void (*installusertimercallback(void (*callback)(void)))(void)
-{
-	void (*oldtimercallback)(void);
-
-	oldtimercallback = usertimercallback;
-	usertimercallback = callback;
-
-	return oldtimercallback;
-}
-
-
-/*
- inittimer() -- initialise timer
- FCS: The tickspersecond parameter is a ratio value that helps replicating
-      oldschool DOS tick per seconds.
- 
-      The way the timer work is:
-      float newSystemTickPerSecond = [0,1]
-      tickPerSecond on a DOS system = tickspersecond * newSystemTickPerSecond ;
-*/
-
-int inittimer(int tickspersecond)
-{
-	int64_t t;
-	
-    
-	if (timerfreq) return 0;	// already installed
-
-	printf("Initialising timer, with tickPerSecond=%d\n",tickspersecond);
-
-	// OpenWatcom seems to want us to query the value into a local variable
-	// instead of the global 'timerfreq' or else it gets pissed with an
-	// access violation
-	if (!TIMER_GetPlatformTicksInOneSecond(&t)) {
-		printf("Failed fetching timer frequency\n");
-		return -1;
-	}
-	timerfreq = t;
-	timerticspersec = tickspersecond;
-	TIMER_GetPlatformTicks(&t);
-	timerlastsample = (int32_t)(t*timerticspersec / timerfreq);
-
-	usertimercallback = NULL;
-    
-	return 0;
-}
-
-//
-// uninittimer() -- shut down timer
-//
-void uninittimer(void)
-{
-	if (!timerfreq) return;
-
-	timerfreq=0;
-	timerticspersec = 0;
-}
-
-//
-// sampletimer() -- update totalclock
-//
-void sampletimer(void)
-{
-	int64_t i;
-	int32_t n;
-	
-	if (!timerfreq) return;
-
-	TIMER_GetPlatformTicks(&i);
-    
-    
-	n = (int32_t)(i*timerticspersec / timerfreq) - timerlastsample;
-	if (n>0) {
-		totalclock += n;
-		timerlastsample += n;
-	}
-
-	if (usertimercallback) for (; n>0; n--) usertimercallback();
-}
-
-
-/*
-   getticks() -- returns the windows ticks count
-   FCS: This seeems to be only used in the multiplayer code
-*/
-uint32_t getticks(void)
-{
-	int64_t i;
-	TIMER_GetPlatformTicks(&i);
-	return (uint32_t)(i*(int32_t)(1000)/timerfreq);
-}
-
-
-//
-// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
-//
-int gettimerfreq(void)
-{
-	return timerticspersec;
-}
-
-// ****************************************************************************
-
-//static Uint32 _timer_catcher(Uint32 interval, void *bleh)
-//{
-//    timerhandler();
-//    return(1);
-//} /* _timer_catcher */
-//
-//
-//void inittimer(void)
-//{
-//    SDL_ClearError();
-//    primary_timer = SDL_AddTimer(1000 / PLATFORM_TIMER_HZ, _timer_catcher, NULL);
-//    if (primary_timer == NULL)
-//    {
-//        fprintf(stderr, "BUILDSDL: -ERROR- Problem initializing primary timer!\n");
-//        fprintf(stderr, "BUILDSDL:  Reason: [%s]\n", SDL_GetError());
-//        Error(EXIT_FAILURE, "");
-//    } /* if */
-//}
-//
-//
-//void uninittimer(void)
-//{
-//    if (primary_timer != NULL)
-//    {
-//        SDL_RemoveTimer(primary_timer);
-//        primary_timer = NULL;
-//    } /* if */
-//}
-
-void initkeys(void)
-{
-    /* does nothing in SDL. Key input handling is set up elsewhere. */
-    /* !!! why not here? */
-}
-
-void uninitkeys(void)
-{
-    /* does nothing in SDL. Key input handling is set up elsewhere. */
-}
-
-
-//unsigned int32_t getticks(void)
-//{
-//    return(SDL_GetTicks());
-//} /* getticks */
-
-
-//Timer on windows 98 used to be really poor but now it is very accurate
-// We can just use what SDL uses, no need for QueryPerformanceFrequency or QueryPerformanceCounter
-// (which I bet SDL is using anyway).
-#if 0//PLATFORM_WIN32 
-int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
-{
-    QueryPerformanceFrequency((LARGE_INTEGER*)t);
-    return 1;
-}
-
-void TIMER_GetPlatformTicks(int64_t* t)
-{
-    QueryPerformanceCounter((LARGE_INTEGER*)t);
-}
-#else
-//FCS: Let's try to use SDL again: Maybe SDL library is accurate enough now.
-int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
-{
-    *t = 1000;
-    return 1;
-}
-    
-void TIMER_GetPlatformTicks(int64_t* t)
-{
-    *t = SDL_GetTicks();
-}
-#endif
-/* end of sdl_driver.c ... */
-
--- a/Game/src/audiolib/_multivc.h
+++ b/Game/src/audiolib/_multivc.h
@@ -121,7 +121,7 @@
    int           handle;
    int           priority;
 
-   void          ( *DemandFeed )( char **ptr, unsigned long *length );
+   void          ( *DemandFeed )( char **ptr, uint32_t *length );
 
 #if 0
    short        *LeftVolume;
--- a/Game/src/audiolib/multivoc.c
+++ b/Game/src/audiolib/multivoc.c
@@ -2063,7 +2063,7 @@
 
 int MV_StartDemandFeedPlayback
    (
-   void ( *function )( char **ptr, unsigned long *length ),
+   void ( *function )( char **ptr, uint32_t *length ),
    int rate,
    int pitchoffset,
    int vol,
--- a/Game/src/audiolib/multivoc.h
+++ b/Game/src/audiolib/multivoc.h
@@ -88,7 +88,7 @@
 void  MV_StopPlayback( void );
 int   MV_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
 void  MV_StopRecord( void );
-int   MV_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+int   MV_StartDemandFeedPlayback( void ( *function )( char **ptr, uint32_t *length ),
          int rate, int pitchoffset, int vol, int left, int right,
          int priority, unsigned long callbackval );
 int   MV_PlayRaw( char *ptr, unsigned long length,
--- a/Game/src/config.c
+++ b/Game/src/config.c
@@ -36,9 +36,9 @@
 #include <time.h>
 #include "duke3d.h"
 #include "scriplib.h"
-#include "cache.h"
-#include "filesystem.h"
+#include "build.h"
 
+
 // we load this in to get default button and key assignments
 // as well as setting up function mappings
 
@@ -292,15 +292,15 @@
 	// FIX_00011: duke3d.cfg not needed anymore to start the game. Will create a default one
 	//            if not found and use default keys.
 
-	for(i=0; i<NUMKEYENTRIES; i++)
-	{
-	function = CONFIG_FunctionNameToNum(keydefaults[i].entryKey);
-	key1 = (byte) KB_StringToScanCode( keydefaults[i].keyname1 );
-	key2 = (byte) KB_StringToScanCode( keydefaults[i].keyname2 );
-	CONTROL_MapKey( function, key1, key2 );
+	for(i=0; i<NUMKEYENTRIES; i++){
+        function = CONFIG_FunctionNameToNum(keydefaults[i].entryKey);
+        key1 = (byte) KB_StringToScanCode( keydefaults[i].keyname1 );
+        key2 = (byte) KB_StringToScanCode( keydefaults[i].keyname2 );
+        CONTROL_MapKey( function, key1, key2 );
 	}
 
-   numkeyentries = SCRIPT_NumberEntries( scripthandle, "KeyDefinitions" );
+   
+       numkeyentries = SCRIPT_NumberEntries( scripthandle, "KeyDefinitions" );
 
    for (i=0;i<numkeyentries;i++)  // i = number in which the functions appear in duke3d.cfg
       {
--- a/Game/src/duke3d.h
+++ b/Game/src/duke3d.h
@@ -47,7 +47,7 @@
 #include <time.h>
 #include <ctype.h>
 
-#include "cache.h"
+#include "build.h"
 
 #if (!defined MAX_PATH)
   #if (defined MAXPATHLEN)
@@ -173,15 +173,11 @@
 #include "rts.h"
 #include "soundefs.h"
 
-#if PLATFORM_DOS
-#include "audiolib/task_man.h"
-#include "audiolib/sndcards.h"
-#endif
 #include "audiolib/music.h"
 
 #include "names.h"
 
-#include "engine.h"
+#include "../../Engine/src/engine.h"
 #include "pragmas.h"
 
 //#define TICRATE (120)
@@ -221,8 +217,6 @@
 
 #define    PHEIGHT (38<<8)
 
-// #define P(X) printf("%ld\n",X);
-
 #define WAIT(X) ototalclock=totalclock+(X);while(totalclock<ototalclock)
 
 
@@ -615,7 +609,7 @@
 extern volatile int32_t checksume;
 
 #include "funct.h"
-#include "engine_protos.h"
+//#include "engine_protos.h"
 
 extern uint8_t  screencapt;
 extern short soundps[NUM_SOUNDS],soundpe[NUM_SOUNDS],soundvo[NUM_SOUNDS];
@@ -692,7 +686,7 @@
 extern short numclouds,clouds[128],cloudx[128],cloudy[128];
 extern int32_t cloudtotalclock,totalmemory;
 
-extern int32_t stereomode, stereowidth, stereopixelwidth;
+
 
 extern int32_t myaimmode, myaimstat, omyaimstat;
 
--- a/Game/src/dummy_audiolib.c
+++ b/Game/src/dummy_audiolib.c
@@ -9,7 +9,7 @@
 #include "audiolib/fx_man.h"
 #include <inttypes.h>
 #include <stdio.h>
-#include "engine_protos.h"
+//#include "engine_protos.h"
 #include "audiolib/music.h"
 
 //Dummy sound system for when a system has no sound system yet.
--- a/Game/src/game.c
+++ b/Game/src/game.c
@@ -55,8 +55,6 @@
 
 #include "global.h"
 
-#include "cache.h"
-#include "filesystem.h"
 
 #define MINITEXT_BLUE	0
 #define MINITEXT_RED	2
--- a/Game/src/gamedef.c
+++ b/Game/src/gamedef.c
@@ -25,7 +25,7 @@
 //-------------------------------------------------------------------------
 
 #include "duke3d.h"
-#include "cache.h"
+
 
 extern short otherp;
 
--- a/Game/src/menues.c
+++ b/Game/src/menues.c
@@ -32,6 +32,7 @@
 #include "filesystem.h"
 #include "SDL.h"
 #include "premap.h"
+#include "display.h"
 
 extern SDL_Surface *surface;
 extern short inputloc;
--- a/Game/src/midi/sdl_midi.c
+++ b/Game/src/midi/sdl_midi.c
@@ -10,7 +10,7 @@
 #include "../audiolib/music.h"
 #include "SDL.h"
 #include "SDL_Mixer.h"
-#include "cache.h"
+#include "build.h"
 
 /*
  Because the music is stored in a GRP file that is never fully loaded in RAM
--- a/Game/src/sounds.c
+++ b/Game/src/sounds.c
@@ -34,6 +34,7 @@
 #include "util_lib.h"
 #include "duke3d.h"
 #include "global.h"
+#include "filesystem.h"
 
 
 #define LOUDESTVOLUME 150
--- a/xcode/Duke3D.xcodeproj/project.pbxproj
+++ b/xcode/Duke3D.xcodeproj/project.pbxproj
@@ -21,7 +21,7 @@
 		2D7B62261678885A00E35E54 /* win32.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B620E1678885A00E35E54 /* win32.c */; };
 		2D7B62271678885A00E35E54 /* engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B62101678885A00E35E54 /* engine.c */; };
 		2D7B622C1678885A00E35E54 /* pragmas.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B621A1678885A00E35E54 /* pragmas.c */; };
-		2D7B622D1678885A00E35E54 /* sdl_driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B621C1678885A00E35E54 /* sdl_driver.c */; };
+		2D7B622D1678885A00E35E54 /* display.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D7B621C1678885A00E35E54 /* display.c */; };
 		2D7B623616788ACE00E35E54 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D7B623416788AB200E35E54 /* Cocoa.framework */; };
 		2D7B623716788AE200E35E54 /* SDL_mixer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D7B623216788AAB00E35E54 /* SDL_mixer.framework */; };
 		2D7B623816788AF800E35E54 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D7B623016788A9B00E35E54 /* SDL.framework */; };
@@ -101,7 +101,6 @@
 		2D7B620A1678885A00E35E54 /* protocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protocol.c; sourceTree = "<group>"; };
 		2D7B620D1678885A00E35E54 /* unix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unix.c; sourceTree = "<group>"; };
 		2D7B620E1678885A00E35E54 /* win32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = win32.c; sourceTree = "<group>"; };
-		2D7B620F1678885A00E35E54 /* engine_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = engine_protos.h; path = ../../Engine/src/engine_protos.h; sourceTree = "<group>"; };
 		2D7B62101678885A00E35E54 /* engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = engine.c; path = ../../Engine/src/engine.c; sourceTree = "<group>"; };
 		2D7B62111678885A00E35E54 /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = engine.h; path = ../../Engine/src/engine.h; sourceTree = "<group>"; };
 		2D7B62121678885A00E35E54 /* icon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = icon.h; path = ../../Engine/src/icon.h; sourceTree = "<group>"; };
@@ -108,7 +107,7 @@
 		2D7B62191678885A00E35E54 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = platform.h; path = ../../Engine/src/platform.h; sourceTree = "<group>"; };
 		2D7B621A1678885A00E35E54 /* pragmas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pragmas.c; path = ../../Engine/src/pragmas.c; sourceTree = "<group>"; };
 		2D7B621B1678885A00E35E54 /* pragmas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pragmas.h; path = ../../Engine/src/pragmas.h; sourceTree = "<group>"; };
-		2D7B621C1678885A00E35E54 /* sdl_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sdl_driver.c; path = ../../Engine/src/sdl_driver.c; sourceTree = "<group>"; };
+		2D7B621C1678885A00E35E54 /* display.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = display.c; path = ../../Engine/src/display.c; sourceTree = "<group>"; };
 		2D7B622F1678895A00E35E54 /* macos_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macos_compat.h; path = ../../Engine/src/macos_compat.h; sourceTree = "<group>"; };
 		2D7B623016788A9B00E35E54 /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = /Library/Frameworks/SDL.framework; sourceTree = "<absolute>"; };
 		2D7B623216788AAB00E35E54 /* SDL_mixer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_mixer.framework; path = /Library/Frameworks/SDL_mixer.framework; sourceTree = "<absolute>"; };
@@ -196,16 +195,15 @@
 		2D2A07CC1682870D00064107 /* headers */ = {
 			isa = PBXGroup;
 			children = (
-				2D2A07CE1682875B00064107 /* enet */,
-				2D7B622F1678895A00E35E54 /* macos_compat.h */,
-				2D7B61F21678885A00E35E54 /* draw.h */,
 				2D7B61F31678885A00E35E54 /* build.h */,
-				2D2A07CB168286F200064107 /* filesystem.h */,
 				2D7B61F51678885A00E35E54 /* cache.h */,
 				2D7B61F61678885A00E35E54 /* display.h */,
-				2D7B620F1678885A00E35E54 /* engine_protos.h */,
+				2D7B61F21678885A00E35E54 /* draw.h */,
+				2D2A07CE1682875B00064107 /* enet */,
 				2D7B62111678885A00E35E54 /* engine.h */,
+				2D2A07CB168286F200064107 /* filesystem.h */,
 				2D7B62121678885A00E35E54 /* icon.h */,
+				2D7B622F1678895A00E35E54 /* macos_compat.h */,
 				2D7B62191678885A00E35E54 /* platform.h */,
 				2D7B621B1678885A00E35E54 /* pragmas.h */,
 			);
@@ -215,14 +213,14 @@
 		2D2A07CD1682871200064107 /* implementations */ = {
 			isa = PBXGroup;
 			children = (
-				2D7B61F71678885A00E35E54 /* enet */,
-				2D7B61F11678885A00E35E54 /* draw.c */,
-				2D2A07C9168286D400064107 /* filesystem.c */,
 				2D7B61F41678885A00E35E54 /* cache.c */,
+				2D7B621C1678885A00E35E54 /* display.c */,
+				2D7B61F11678885A00E35E54 /* draw.c */,
+				2D7B630016791C0200E35E54 /* dummy_multi.c */,
+				2D7B61F71678885A00E35E54 /* enet */,
 				2D7B62101678885A00E35E54 /* engine.c */,
+				2D2A07C9168286D400064107 /* filesystem.c */,
 				2D7B621A1678885A00E35E54 /* pragmas.c */,
-				2D7B621C1678885A00E35E54 /* sdl_driver.c */,
-				2D7B630016791C0200E35E54 /* dummy_multi.c */,
 			);
 			name = implementations;
 			sourceTree = "<group>";
@@ -238,20 +236,6 @@
 		2D2A07CF16828B7600064107 /* headers */ = {
 			isa = PBXGroup;
 			children = (
-				2D7B626416788F9B00E35E54 /* rts.h */,
-				2D7B626616788F9B00E35E54 /* scriplib.h */,
-				2D7B626816788F9B00E35E54 /* sounddebugdefs.h */,
-				2D7B626916788F9B00E35E54 /* soundefs.h */,
-				2D7B626B16788F9B00E35E54 /* sounds.h */,
-				2D7B626C16788F9B00E35E54 /* types.h */,
-				2D7B626D16788F9B00E35E54 /* util_lib.h */,
-				2D7B62FD167905C400E35E54 /* dukeunix.h */,
-				2D2A07BA167EFB5500064107 /* premap.h */,
-				2D2A07BB167F1ABA00064107 /* global.h */,
-				2D7B624916788F9B00E35E54 /* DbgHelp.h */,
-				2D7B624D16788F9B00E35E54 /* file_lib.h */,
-				2D7B625F16788F9B00E35E54 /* mouse.h */,
-				2D7B626016788F9B00E35E54 /* names.h */,
 				2D7B623A16788F9B00E35E54 /* _functio.h */,
 				2D7B623B16788F9B00E35E54 /* _rts.h */,
 				2D7B623E16788F9B00E35E54 /* animlib.h */,
@@ -260,15 +244,29 @@
 				2D7B624416788F9B00E35E54 /* control.h */,
 				2D7B624616788F9B00E35E54 /* cvar_defs.h */,
 				2D7B624816788F9B00E35E54 /* cvars.h */,
+				2D7B624916788F9B00E35E54 /* DbgHelp.h */,
 				2D7B624A16788F9B00E35E54 /* develop.h */,
 				2D7B624B16788F9B00E35E54 /* duke3d.h */,
+				2D7B62FD167905C400E35E54 /* dukeunix.h */,
 				2D7B624C16788F9B00E35E54 /* dukewin.h */,
+				2D7B624D16788F9B00E35E54 /* file_lib.h */,
 				2D7B624E16788F9B00E35E54 /* funct.h */,
 				2D7B624F16788F9B00E35E54 /* function.h */,
 				2D7B625116788F9B00E35E54 /* game.h */,
 				2D7B625316788F9B00E35E54 /* gamedefs.h */,
+				2D2A07BB167F1ABA00064107 /* global.h */,
 				2D7B625516788F9B00E35E54 /* joystick.h */,
 				2D7B625716788F9B00E35E54 /* keyboard.h */,
+				2D7B625F16788F9B00E35E54 /* mouse.h */,
+				2D7B626016788F9B00E35E54 /* names.h */,
+				2D2A07BA167EFB5500064107 /* premap.h */,
+				2D7B626416788F9B00E35E54 /* rts.h */,
+				2D7B626616788F9B00E35E54 /* scriplib.h */,
+				2D7B626816788F9B00E35E54 /* sounddebugdefs.h */,
+				2D7B626916788F9B00E35E54 /* soundefs.h */,
+				2D7B626B16788F9B00E35E54 /* sounds.h */,
+				2D7B626C16788F9B00E35E54 /* types.h */,
+				2D7B626D16788F9B00E35E54 /* util_lib.h */,
 			);
 			name = headers;
 			sourceTree = "<group>";
@@ -474,7 +472,7 @@
 				2D7B62261678885A00E35E54 /* win32.c in Sources */,
 				2D7B62271678885A00E35E54 /* engine.c in Sources */,
 				2D7B622C1678885A00E35E54 /* pragmas.c in Sources */,
-				2D7B622D1678885A00E35E54 /* sdl_driver.c in Sources */,
+				2D7B622D1678885A00E35E54 /* display.c in Sources */,
 				2D7B626E16788F9B00E35E54 /* actors.c in Sources */,
 				2D7B626F16788F9B00E35E54 /* animlib.c in Sources */,
 				2D7B627016788F9B00E35E54 /* config.c in Sources */,
--- a/xcode/Duke3D/SDLMain.m
+++ b/xcode/Duke3D/SDLMain.m
@@ -197,7 +197,7 @@
 }
 
 /* Replacement for NSApplicationMain */
-static void CustomApplicationMain (int argc, uint8_t  **argv)
+static void CustomApplicationMain (int argc, char  **argv)
 {
     NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
     SDLMain				*sdlMain;
@@ -254,7 +254,7 @@
 {
     const char  *temparg;
     size_t arglen;
-    uint8_t  *arg;
+    char  *arg;
     char  **newargv;
     
     if (!gFinderLaunch)  /* MacOS is passing command line args. */
@@ -265,11 +265,11 @@
     
     temparg = [filename UTF8String];
     arglen = SDL_strlen(temparg) + 1;
-    arg = (uint8_t  *) SDL_malloc(arglen);
+    arg = (char  *) SDL_malloc(arglen);
     if (arg == NULL)
         return FALSE;
     
-    newargv = (uint8_t  **) realloc(gArgv, sizeof (uint8_t  *) * (gArgc + 2));
+    newargv = (char  **) realloc(gArgv, sizeof (uint8_t  *) * (gArgc + 2));
     if (newargv == NULL)
     {
         SDL_free(arg);
--