Implemented DirectDraw's Hardware Abstraction Layer (HAL) interface.
Disabled DirectDraw's old XVidMode and DGA2 drivers, it now depends on the
display driver (x11drv) HAL implementations of these features.

diff --git a/dlls/ddraw/Makefile.in b/dlls/ddraw/Makefile.in
index 3c77068..1ed4aa9 100644
--- a/dlls/ddraw/Makefile.in
+++ b/dlls/ddraw/Makefile.in
@@ -24,15 +24,18 @@
 	convert.c \
 	dclipper/main.c \
 	ddraw/dga2.c \
+	ddraw/hal.c \
 	ddraw/main.c \
 	ddraw/thunks.c \
 	ddraw/user.c \
 	ddraw/xvidmode.c \
+	dpalette/hal.c \
 	dpalette/main.c \
 	dsurface/dga2.c \
 	dsurface/dib.c \
 	dsurface/fakezbuffer.c \
 	dsurface/gamma.c \
+	dsurface/hal.c \
 	dsurface/main.c \
 	dsurface/thunks.c \
 	dsurface/user.c \
diff --git a/dlls/ddraw/ddraw/hal.c b/dlls/ddraw/ddraw/hal.c
new file mode 100644
index 0000000..4be6f00
--- /dev/null
+++ b/dlls/ddraw/ddraw/hal.c
@@ -0,0 +1,535 @@
+/*	DirectDraw HAL driver
+ *
+ * Copyright 2001 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+
+#include "debugtools.h"
+#include "ddraw.h"
+#include "ddrawi.h"
+#include "d3dhal.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "ddraw_private.h"
+#include "ddraw/main.h"
+#include "ddraw/user.h"
+#include "ddraw/hal.h"
+#include "dclipper/main.h"
+#include "dpalette/main.h"
+#include "dpalette/hal.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+#include "dsurface/hal.h"
+
+#include "options.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDraw7) HAL_DirectDraw_VTable;
+
+static DDVERSIONDATA hal_version;
+static DD32BITDRIVERDATA hal_driverdata;
+static HINSTANCE hal_instance;
+
+static const DDDEVICEIDENTIFIER2 hal_device = 
+{
+    "display",
+    "DirectDraw HAL",
+    { { 0x00010001, 0x00010001 } },
+    0, 0, 0, 0,
+    /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
+    {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
+    0
+};
+
+HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+			      IUnknown* pUnkOuter, BOOL ex);
+HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
+
+static const ddraw_driver hal_driver =
+{
+    &hal_device,
+    100, /* we prefer the HAL */
+    HAL_DirectDraw_Create,
+    HAL_DirectDraw_Initialize
+};
+
+static DDHAL_CALLBACKS dd_cbs;
+static DDRAWI_DIRECTDRAW_GBL dd_gbl;
+
+static D3DHAL_GLOBALDRIVERDATA d3d_hal_data;
+static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps;
+static D3DHAL_CALLBACKS d3d_hal_cbs1;
+static D3DHAL_CALLBACKS2 d3d_hal_cbs2;
+
+/* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
+static BOOL DDAPI set_hal_info(LPDDHALINFO lpDDHalInfo, BOOL reset)
+{
+    dd_cbs.HALDD	= *lpDDHalInfo->lpDDCallbacks;
+    dd_cbs.HALDDSurface	= *lpDDHalInfo->lpDDSurfaceCallbacks;
+    dd_cbs.HALDDPalette	= *lpDDHalInfo->lpDDPaletteCallbacks;
+    if (lpDDHalInfo->lpDDExeBufCallbacks)
+	dd_cbs.HALDDExeBuf	= *lpDDHalInfo->lpDDExeBufCallbacks;
+
+    dd_gbl.lpDDCBtmp = &dd_cbs;
+
+    dd_gbl.ddCaps		 = lpDDHalInfo->ddCaps;
+    dd_gbl.dwMonitorFrequency	 = lpDDHalInfo->dwMonitorFrequency;
+    dd_gbl.vmiData		 = lpDDHalInfo->vmiData;
+    dd_gbl.dwModeIndex		 = lpDDHalInfo->dwModeIndex;
+    /* FIXME: dwNumFourCC */
+    dd_gbl.lpdwFourCC		 = lpDDHalInfo->lpdwFourCC;
+    dd_gbl.dwNumModes		 = lpDDHalInfo->dwNumModes;
+    dd_gbl.lpModeInfo		 = lpDDHalInfo->lpModeInfo;
+    /* FIXME: dwFlags */
+    dd_gbl.dwPDevice		 = (DWORD)lpDDHalInfo->lpPDevice;
+    dd_gbl.hInstance		 = lpDDHalInfo->hInstance;
+    /* DirectX 2 */
+    if (lpDDHalInfo->lpD3DGlobalDriverData)
+	memcpy(&d3d_hal_data, (LPVOID)lpDDHalInfo->lpD3DGlobalDriverData, sizeof(D3DDEVICEDESC_V1));
+    else
+	memset(&d3d_hal_data, 0, sizeof(D3DDEVICEDESC_V1));
+    dd_gbl.lpD3DGlobalDriverData = (ULONG_PTR)&d3d_hal_data;
+
+    if (lpDDHalInfo->lpD3DHALCallbacks)
+	memcpy(&d3d_hal_cbs1, (LPVOID)lpDDHalInfo->lpD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
+    else
+	memset(&d3d_hal_cbs1, 0, sizeof(D3DDEVICEDESC_V1));
+    dd_gbl.lpD3DHALCallbacks	 = (ULONG_PTR)&d3d_hal_cbs1;
+
+    if (lpDDHalInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) {
+	DDHAL_GETDRIVERINFODATA data;
+	data.dwSize = sizeof(DDHAL_GETDRIVERINFODATA);
+	data.dwFlags = 0; /* ? */
+	data.dwContext = hal_driverdata.dwContext; /* ? */
+
+	data.guidInfo = GUID_D3DExtendedCaps;
+	data.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
+	data.lpvData = &d3d_hal_extcaps;
+	data.dwActualSize = 0;
+	data.ddRVal = 0;
+	lpDDHalInfo->GetDriverInfo(&data);
+	d3d_hal_extcaps.dwSize = data.dwActualSize;
+	dd_gbl.lpD3DExtendedCaps = (ULONG_PTR)&d3d_hal_extcaps;
+
+	data.guidInfo = GUID_D3DCallbacks2;
+	data.dwExpectedSize = sizeof(D3DHAL_CALLBACKS2);
+	data.lpvData = &d3d_hal_cbs2;
+	data.dwActualSize = 0;
+	data.ddRVal = 0;
+	lpDDHalInfo->GetDriverInfo(&data);
+	d3d_hal_cbs2.dwSize = data.dwActualSize;
+	dd_gbl.lpD3DHALCallbacks2 = (ULONG_PTR)&d3d_hal_cbs2;
+    }
+
+#ifdef HAVE_OPENGL
+    if (d3d_hal_data.hwCaps.dwFlags & D3DDD_WINE_OPENGL_DEVICE) {
+        /*GL_DirectDraw_Init(&dd_gbl);*/
+    }
+#endif
+
+    return FALSE;
+}
+
+static DDHALDDRAWFNS hal_funcs = {
+    sizeof(DDHALDDRAWFNS),
+    set_hal_info,
+    NULL, /* VidMemAlloc */
+    NULL  /* VidMemFree */
+};
+
+/* Called from DllInit, which is synchronised so there are no threading
+ * concerns. */
+static BOOL initialize(void)
+{
+    DCICMD cmd;
+    INT ncmd = DCICOMMAND;
+    BOOL ret;
+    HDC dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
+    INT ver = Escape(dc, QUERYESCSUPPORT, sizeof(ncmd), (LPVOID)&ncmd, NULL);
+    if (ver != DD_HAL_VERSION) {
+	DeleteDC(dc);
+	TRACE("DirectDraw HAL not available\n");
+	return FALSE;
+    }
+    cmd.dwVersion = DD_VERSION;
+    cmd.dwReserved = 0;
+
+    /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
+     * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
+     * we'll just work in 32-bit, who'll notice... */
+    cmd.dwCommand = DDNEWCALLBACKFNS;
+    cmd.dwParam1 = (DWORD)&hal_funcs;
+    ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, 0, NULL);
+
+    /* next, exchange version information */
+    cmd.dwCommand = DDVERSIONINFO;
+    cmd.dwParam1 = DD_RUNTIME_VERSION; /* not sure what should *really* go here */
+    ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_version), (LPVOID)&hal_version);
+
+    /* get 32-bit driver data (dll name and entry point) */
+    cmd.dwCommand = DDGET32BITDRIVERNAME;
+    ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_driverdata), (LPVOID)&hal_driverdata);
+    /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
+     * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
+     * as a parameter... but since this is only more remains from the 16-bit world,
+     * we'll ignore it */
+
+    /* finally, initialize the driver object */
+    cmd.dwCommand = DDCREATEDRIVEROBJECT;
+    ret = ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_instance), (LPVOID)&hal_instance);
+    if (ret) {
+	/* the driver should have called our set_hal_info now */
+	if (!dd_gbl.lpDDCBtmp) ret = FALSE;
+    }
+
+    /* init done */
+    DeleteDC(dc);
+
+    TRACE("%s DirectDraw HAL\n", ret ? "enabling" : "disabling");
+
+    return ret;
+}
+
+static void cleanup(void)
+{
+    DDHAL_DESTROYDRIVERDATA data;
+    data.lpDD = NULL;
+    data.ddRVal = 0;
+    data.DestroyDriver = dd_cbs.HALDD.DestroyDriver;
+    data.DestroyDriver(&data);
+}
+
+static DWORD choose_mode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
+			 DWORD dwRefreshRate, DWORD dwFlags)
+{
+    int best = -1;
+    int i;
+
+    if (!dd_gbl.dwNumModes) return 0;
+
+/* let's support HALs that cannot switch depths (XVidMode),
+ * these should return dwBPP == 0 for all their resolutions */
+#define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
+
+/* FIXME: we should try to match the refresh rate too */
+
+    /* Choose the smallest mode that is large enough. */
+    for (i=0; i < dd_gbl.dwNumModes; i++)
+    {
+	if (dd_gbl.lpModeInfo[i].dwWidth >= dwWidth &&
+	    dd_gbl.lpModeInfo[i].dwHeight >= dwHeight &&
+	    BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
+	{
+	    if (best == -1) best = i;
+	    else
+	    {
+		if (dd_gbl.lpModeInfo[i].dwWidth < dd_gbl.lpModeInfo[best].dwWidth ||
+		    dd_gbl.lpModeInfo[i].dwHeight < dd_gbl.lpModeInfo[best].dwHeight)
+		    best = i;
+	    }
+	}
+    }
+
+    if (best == -1)
+    {
+	TRACE("all modes too small\n");
+	/* ok, let's use the largest */
+
+	for (i=0; i < dd_gbl.dwNumModes; i++)
+	{
+	    if (BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
+	    {
+		if (best == -1) best = i;
+		else
+		{
+		    if (dd_gbl.lpModeInfo[i].dwWidth > dd_gbl.lpModeInfo[best].dwWidth ||
+			dd_gbl.lpModeInfo[i].dwHeight > dd_gbl.lpModeInfo[best].dwHeight)
+			best = i;
+		}
+	    }
+	}
+    }
+#undef BPP_MATCH
+
+    if (best == -1)
+    {
+	ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP);
+	return dd_gbl.dwModeIndex;
+    }
+
+    TRACE("using mode %d\n", best);
+
+    return best;
+}
+
+static HRESULT set_mode(IDirectDrawImpl *This, DWORD dwMode)
+{
+    HRESULT hr = DD_OK;
+
+    if (dwMode != dd_gbl.dwModeIndex)
+    {
+	DDHAL_SETMODEDATA data;
+	data.lpDD = &dd_gbl;
+	data.dwModeIndex = dwMode;
+	data.ddRVal = 0;
+	data.SetMode = dd_cbs.HALDD.SetMode;
+	data.inexcl = 0;
+	data.useRefreshRate = FALSE;
+	if (data.SetMode)
+	    data.SetMode(&data);
+	hr = data.ddRVal;
+	if (SUCCEEDED(hr))
+	    dd_gbl.dwModeIndex = dwMode;
+    }
+    return hr;
+}
+
+static HRESULT set_exclusive_mode(IDirectDrawImpl *This, DWORD dwEnterExcl)
+{
+    DDHAL_SETEXCLUSIVEMODEDATA data;
+
+    data.lpDD = &dd_gbl;
+    data.dwEnterExcl = dwEnterExcl;
+    data.dwReserved = 0;
+    data.ddRVal = 0;
+    data.SetExclusiveMode = dd_cbs.HALDD.SetExclusiveMode;
+    if (data.SetExclusiveMode)
+	data.SetExclusiveMode(&data);
+    return data.ddRVal;
+}
+
+BOOL DDRAW_HAL_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH)
+    {
+	if (initialize())
+	    DDRAW_register_driver(&hal_driver);
+    }
+    else if (fdwReason == DLL_PROCESS_DETACH)
+    {
+	cleanup();
+    }
+
+    return TRUE;
+}
+
+/* Not called from the vtable. */
+HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
+{
+    HRESULT hr;
+
+    TRACE("(%p)\n", This);
+
+    hr = User_DirectDraw_Construct(This, ex);
+    if (FAILED(hr)) return hr;
+
+    This->local.lpGbl = &dd_gbl;
+
+    This->final_release = HAL_DirectDraw_final_release;
+    This->set_exclusive_mode = set_exclusive_mode;
+
+    This->create_palette = HAL_DirectDrawPalette_Create;
+
+    This->create_primary    = HAL_DirectDraw_create_primary;
+    This->create_backbuffer = HAL_DirectDraw_create_backbuffer;
+    This->create_texture    = HAL_DirectDraw_create_texture;
+
+    ICOM_INIT_INTERFACE(This, IDirectDraw7, HAL_DirectDraw_VTable);
+
+    /* merge HAL caps */
+    This->caps.dwCaps |= dd_gbl.ddCaps.dwCaps;
+    This->caps.dwCaps2 |= dd_gbl.ddCaps.dwCaps2;
+    This->caps.dwCKeyCaps |= dd_gbl.ddCaps.dwCKeyCaps;
+    This->caps.dwFXCaps |= dd_gbl.ddCaps.dwFXCaps;
+    This->caps.dwPalCaps |= dd_gbl.ddCaps.dwPalCaps;
+    /* FIXME: merge more caps */
+    This->caps.ddsCaps.dwCaps |= dd_gbl.ddCaps.ddsCaps.dwCaps;
+    This->caps.ddsCaps.dwCaps2 |= dd_gbl.ddsCapsMore.dwCaps2;
+    This->caps.ddsCaps.dwCaps3 |= dd_gbl.ddsCapsMore.dwCaps3;
+    This->caps.ddsCaps.dwCaps4 |= dd_gbl.ddsCapsMore.dwCaps4;
+    This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
+
+    return S_OK;
+}
+
+/* This function is called from DirectDrawCreate(Ex) on the most-derived
+ * class to start construction.
+ * Not called from the vtable. */
+HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+			      IUnknown* pUnkOuter, BOOL ex)
+{
+    HRESULT hr;
+    IDirectDrawImpl* This;
+
+    TRACE("\n");
+
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(IDirectDrawImpl)
+		     + sizeof(HAL_DirectDrawImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    /* Note that this relation does *not* hold true if the DD object was
+     * CoCreateInstanced then Initialized. */
+    This->private = (HAL_DirectDrawImpl *)(This+1);
+
+    hr = HAL_DirectDraw_Construct(This, ex);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*pIface = ICOM_INTERFACE(This, IDirectDraw7);
+
+    return hr;
+}
+
+/* This function is called from Uninit_DirectDraw_Initialize on the
+ * most-derived-class to start initialization.
+ * Not called from the vtable. */
+HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			      sizeof(HAL_DirectDrawImpl));
+    if (This->private == NULL) return E_OUTOFMEMORY;
+
+    hr = HAL_DirectDraw_Construct(This, TRUE); /* XXX ex? */
+    if (FAILED(hr))
+    {
+	HeapFree(GetProcessHeap(), 0, This->private);
+	return hr;
+    }
+
+    return DD_OK;
+}
+
+/* Called from an internal function pointer. */
+void HAL_DirectDraw_final_release(IDirectDrawImpl *This)
+{
+    if (dd_gbl.dwFlags & DDRAWI_MODECHANGED) set_mode(This, dd_gbl.dwModeIndexOrig);
+    User_DirectDraw_final_release(This);
+}
+
+HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
+				      const DDSURFACEDESC2* pDDSD,
+				      LPDIRECTDRAWSURFACE7* ppSurf,
+				      IUnknown* pUnkOuter)
+{
+    if (This->cooperative_level & DDSCL_EXCLUSIVE)
+	return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+    else
+	return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
+
+HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+					 const DDSURFACEDESC2* pDDSD,
+					 LPDIRECTDRAWSURFACE7* ppSurf,
+					 IUnknown* pUnkOuter,
+					 IDirectDrawSurfaceImpl* primary)
+{
+    if (This->cooperative_level & DDSCL_EXCLUSIVE)
+	return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+    else
+	return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
+}
+
+HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
+				      const DDSURFACEDESC2* pDDSD,
+				      LPDIRECTDRAWSURFACE7* ppSurf,
+				      LPUNKNOWN pOuter,
+				      DWORD dwMipMapLevel)
+{
+    return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
+}
+
+HRESULT WINAPI
+HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+				   LPDDDEVICEIDENTIFIER2 pDDDI,
+				   DWORD dwFlags)
+{
+    *pDDDI = hal_device;
+    return DD_OK;
+}
+
+HRESULT WINAPI
+HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", iface);
+
+    if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) return DD_OK;
+
+    hr = Main_DirectDraw_RestoreDisplayMode(iface);
+    if (SUCCEEDED(hr)) {
+	hr = set_mode(This, dd_gbl.dwModeIndexOrig);
+	if (SUCCEEDED(hr)) dd_gbl.dwFlags &= ~DDRAWI_MODECHANGED;
+    }
+
+    return hr;
+}
+
+HRESULT WINAPI
+HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+			      DWORD dwHeight, DWORD dwBPP,
+			      DWORD dwRefreshRate, DWORD dwFlags)
+{
+    ICOM_THIS(IDirectDrawImpl, iface);
+
+    HRESULT hr;
+
+    TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
+    hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
+					dwRefreshRate, dwFlags);      
+
+    if (SUCCEEDED(hr)) {
+	if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) dd_gbl.dwModeIndexOrig = dd_gbl.dwModeIndex;
+	hr = set_mode(This, choose_mode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags));
+	if (SUCCEEDED(hr)) dd_gbl.dwFlags |= DDRAWI_MODECHANGED;
+    }
+
+    return hr;
+}
+
+static ICOM_VTABLE(IDirectDraw7) HAL_DirectDraw_VTable =
+{
+    Main_DirectDraw_QueryInterface,
+    Main_DirectDraw_AddRef,
+    Main_DirectDraw_Release,
+    Main_DirectDraw_Compact,
+    Main_DirectDraw_CreateClipper,
+    Main_DirectDraw_CreatePalette,
+    Main_DirectDraw_CreateSurface,
+    Main_DirectDraw_DuplicateSurface,
+    User_DirectDraw_EnumDisplayModes,
+    Main_DirectDraw_EnumSurfaces,
+    Main_DirectDraw_FlipToGDISurface,
+    Main_DirectDraw_GetCaps,
+    Main_DirectDraw_GetDisplayMode,
+    Main_DirectDraw_GetFourCCCodes,
+    Main_DirectDraw_GetGDISurface,
+    Main_DirectDraw_GetMonitorFrequency,
+    Main_DirectDraw_GetScanLine,
+    Main_DirectDraw_GetVerticalBlankStatus,
+    Main_DirectDraw_Initialize,
+    HAL_DirectDraw_RestoreDisplayMode,
+    Main_DirectDraw_SetCooperativeLevel,
+    HAL_DirectDraw_SetDisplayMode,
+    Main_DirectDraw_WaitForVerticalBlank,
+    Main_DirectDraw_GetAvailableVidMem,
+    Main_DirectDraw_GetSurfaceFromDC,
+    Main_DirectDraw_RestoreAllSurfaces,
+    Main_DirectDraw_TestCooperativeLevel,
+    HAL_DirectDraw_GetDeviceIdentifier,
+    Main_DirectDraw_StartModeTest,
+    Main_DirectDraw_EvaluateMode
+};
diff --git a/dlls/ddraw/ddraw/hal.h b/dlls/ddraw/ddraw/hal.h
new file mode 100644
index 0000000..0128ba1
--- /dev/null
+++ b/dlls/ddraw/ddraw/hal.h
@@ -0,0 +1,53 @@
+/* Copyright 2001 TransGaming Technologies, Inc. */
+#ifndef WINE_DDRAW_DDRAW_HAL_H_INCLUDED
+#define WINE_DDRAW_DDRAW_HAL_H_INCLUDED
+
+#define HAL_DDRAW_PRIV(ddraw) \
+	((HAL_DirectDrawImpl*)((ddraw)->private))
+#define HAL_DDRAW_PRIV_VAR(name,ddraw) \
+	HAL_DirectDrawImpl* name = HAL_DDRAW_PRIV(ddraw)
+
+typedef struct
+{
+    DWORD next_vofs;
+} HAL_DirectDrawImpl_Part;
+
+typedef struct
+{
+    User_DirectDrawImpl_Part user;
+    HAL_DirectDrawImpl_Part hal;
+} HAL_DirectDrawImpl;
+
+void HAL_DirectDraw_final_release(IDirectDrawImpl* This);
+HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
+				      const DDSURFACEDESC2* pDDSD,
+				      LPDIRECTDRAWSURFACE7* ppSurf,
+				      LPUNKNOWN pOuter);
+HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
+					 const DDSURFACEDESC2* pDDSD,
+					 LPDIRECTDRAWSURFACE7* ppSurf,
+					 LPUNKNOWN pOuter,
+					 IDirectDrawSurfaceImpl* primary);
+HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
+				      const DDSURFACEDESC2* pDDSD,
+				      LPDIRECTDRAWSURFACE7* ppSurf,
+				      LPUNKNOWN pOuter,
+				      DWORD dwMipMapLevel);
+                                                                                                 
+HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex);
+HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
+				   IUnknown* pUnkOuter, BOOL ex);
+                                  
+
+HRESULT WINAPI
+HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
+					LPDDDEVICEIDENTIFIER2 pDDDI,
+					DWORD dwFlags);
+HRESULT WINAPI
+HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
+				   DWORD dwHeight, DWORD dwBPP,
+				   DWORD dwRefreshRate, DWORD dwFlags);
+HRESULT WINAPI
+HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface);
+
+#endif
diff --git a/dlls/ddraw/dpalette/hal.c b/dlls/ddraw/dpalette/hal.c
new file mode 100644
index 0000000..44dc9f4
--- /dev/null
+++ b/dlls/ddraw/dpalette/hal.c
@@ -0,0 +1,124 @@
+/*	DirectDrawPalette HAL driver
+ *
+ * Copyright 2001 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+#include "winerror.h"
+#include "debugtools.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "ddraw_private.h"
+#include "dpalette/main.h"
+#include "dpalette/hal.h"
+#include "ddraw/main.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDrawPalette) DDRAW_HAL_Palette_VTable;
+
+/******************************************************************************
+ *			IDirectDrawPalette
+ */
+HRESULT HAL_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
+					IDirectDrawImpl* pDD, DWORD dwFlags)
+{
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl;
+    DDHAL_CREATEPALETTEDATA data;
+    HRESULT hr;
+
+    hr = Main_DirectDrawPalette_Construct(This, pDD, dwFlags);
+    if (FAILED(hr)) return hr;
+
+    This->final_release = HAL_DirectDrawPalette_final_release;
+    ICOM_INIT_INTERFACE(This, IDirectDrawPalette, DDRAW_HAL_Palette_VTable);
+
+    /* initialize HAL palette */
+    data.lpDD = dd_gbl;
+    data.lpDDPalette = &This->global;
+    data.lpColorTable = NULL;
+    data.ddRVal = 0;
+    data.CreatePalette = dd_gbl->lpDDCBtmp->HALDD.CreatePalette;
+    if (data.CreatePalette)
+	data.CreatePalette(&data);
+
+    return DD_OK;
+}
+
+HRESULT
+HAL_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
+			     LPDIRECTDRAWPALETTE* ppPalette,
+			     LPUNKNOWN pUnkOuter)
+{
+    IDirectDrawPaletteImpl* This;
+    HRESULT hr;
+
+    if (pUnkOuter != NULL)
+	return CLASS_E_NOAGGREGATION; /* unchecked */
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    hr = HAL_DirectDrawPalette_Construct(This, pDD, dwFlags);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppPalette = ICOM_INTERFACE(This, IDirectDrawPalette);
+
+    return hr;
+}
+
+HRESULT WINAPI
+HAL_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				 DWORD dwStart, DWORD dwCount,
+				 LPPALETTEENTRY palent)
+{
+    ICOM_THIS(IDirectDrawPaletteImpl,iface);
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->local.lpDD_lcl->lpGbl;
+    DDHAL_SETENTRIESDATA data;
+
+    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
+	  palent);
+
+    data.lpDD = dd_gbl;
+    data.lpDDPalette = &This->global;
+    data.dwBase = dwStart;
+    data.dwNumEntries = dwCount;
+    data.lpEntries = palent;
+    data.ddRVal = 0;
+    data.SetEntries = dd_gbl->lpDDCBtmp->HALDDPalette.SetEntries;
+    if (data.SetEntries)
+	data.SetEntries(&data);
+
+    return Main_DirectDrawPalette_SetEntries(iface, dwFlags, dwStart, dwCount, palent);
+}
+
+void HAL_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This)
+{
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->local.lpDD_lcl->lpGbl;
+    DDHAL_DESTROYPALETTEDATA data;
+
+    /* destroy HAL palette */
+    data.lpDD = dd_gbl;
+    data.lpDDPalette = &This->global;
+    data.ddRVal = 0;
+    data.DestroyPalette = dd_gbl->lpDDCBtmp->HALDDPalette.DestroyPalette;
+    if (data.DestroyPalette)
+	data.DestroyPalette(&data);
+
+    Main_DirectDrawPalette_final_release(This);
+}
+
+static ICOM_VTABLE(IDirectDrawPalette) DDRAW_HAL_Palette_VTable =
+{
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    Main_DirectDrawPalette_QueryInterface,
+    Main_DirectDrawPalette_AddRef,
+    Main_DirectDrawPalette_Release,
+    Main_DirectDrawPalette_GetCaps,
+    Main_DirectDrawPalette_GetEntries,
+    Main_DirectDrawPalette_Initialize,
+    HAL_DirectDrawPalette_SetEntries
+};
diff --git a/dlls/ddraw/dpalette/hal.h b/dlls/ddraw/dpalette/hal.h
new file mode 100644
index 0000000..d6bdad7
--- /dev/null
+++ b/dlls/ddraw/dpalette/hal.h
@@ -0,0 +1,20 @@
+/* Copyright 2000-2001 TransGaming Technologies Inc. */
+
+#ifndef WINE_DDRAW_DPALETTE_HAL_H_INCLUDED
+#define WINE_DDRAW_DPALETTE_HAL_H_INCLUDED
+
+HRESULT HAL_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
+					 IDirectDrawImpl* pDD, DWORD dwFlags);
+void HAL_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This);
+
+HRESULT
+HAL_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
+			      LPDIRECTDRAWPALETTE* ppPalette,
+			      LPUNKNOWN pUnkOuter);
+
+HRESULT WINAPI
+HAL_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
+				  DWORD dwStart, DWORD dwCount,
+				  LPPALETTEENTRY palent);
+
+#endif
diff --git a/dlls/ddraw/dsurface/hal.c b/dlls/ddraw/dsurface/hal.c
new file mode 100644
index 0000000..e00d84f
--- /dev/null
+++ b/dlls/ddraw/dsurface/hal.c
@@ -0,0 +1,366 @@
+/*	DirectDrawSurface HAL driver
+ *
+ * Copyright 2001 TransGaming Technologies Inc.
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "debugtools.h"
+#include "ddraw_private.h"
+#include "ddraw/user.h"
+#include "ddraw/hal.h"
+#include "dsurface/main.h"
+#include "dsurface/dib.h"
+#include "dsurface/user.h"
+#include "dsurface/hal.h"
+
+DEFAULT_DEBUG_CHANNEL(ddraw);
+
+static ICOM_VTABLE(IDirectDrawSurface7) HAL_IDirectDrawSurface7_VTable;
+
+static HRESULT HAL_DirectDrawSurface_create_surface(IDirectDrawSurfaceImpl* This,
+						    IDirectDrawImpl* pDD)
+{
+    HAL_PRIV_VAR(priv, This);
+    HAL_DDRAW_PRIV_VAR(ddpriv, pDD);
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl;
+    LPDDRAWI_DDRAWSURFACE_LCL local = &This->local;
+    DDHAL_CREATESURFACEDATA data;
+    HRESULT hr;
+
+    data.lpDD = dd_gbl;
+    data.lpDDSurfaceDesc = (LPDDSURFACEDESC)&This->surface_desc;
+    data.lplpSList = &local;
+    data.dwSCnt = 1;
+    data.ddRVal = 0;
+    data.CreateSurface = dd_gbl->lpDDCBtmp->HALDD.CreateSurface;
+    hr = data.CreateSurface(&data);
+
+    if (hr == DDHAL_DRIVER_HANDLED) {
+	if (This->global.fpVidMem < 4) {
+	    /* grab framebuffer data from current_mode */
+	    priv->hal.fb_pitch = dd_gbl->vmiData.lDisplayPitch;
+	    priv->hal.fb_vofs  = ddpriv->hal.next_vofs;
+	    priv->hal.fb_addr  = ((LPBYTE)dd_gbl->vmiData.fpPrimary) +
+				 dd_gbl->vmiData.lDisplayPitch * priv->hal.fb_vofs;
+	    TRACE("vofs=%ld, addr=%p\n", priv->hal.fb_vofs, priv->hal.fb_addr);
+	    ddpriv->hal.next_vofs += This->surface_desc.dwHeight;
+
+	    This->global.fpVidMem = (FLATPTR)priv->hal.fb_addr;
+	}
+	This->surface_desc.lpSurface = (LPVOID)This->global.fpVidMem;
+	This->surface_desc.dwFlags |= DDSD_LPSURFACE;
+	if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) {
+	    This->surface_desc.u1.dwLinearSize = This->global.u4.dwLinearSize;
+	    This->surface_desc.dwFlags |= DDSD_LINEARSIZE;
+	} else {
+	    This->surface_desc.u1.lPitch = This->global.u4.lPitch;
+	    This->surface_desc.dwFlags |= DDSD_PITCH;
+	}
+    }
+    else priv->hal.need_late = TRUE;
+
+    return data.ddRVal;
+}
+
+static inline BOOL HAL_IsUser(IDirectDrawSurfaceImpl* This)
+{
+    HAL_PRIV_VAR(priv, This);
+    if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_EXECUTEBUFFER))
+	return FALSE;
+    if (priv->hal.fb_addr)
+	return FALSE;
+    return TRUE;
+}
+
+HRESULT
+HAL_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				IDirectDrawImpl* pDD,
+				const DDSURFACEDESC2* pDDSD)
+{
+    HAL_PRIV_VAR(priv, This);
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl;
+    HRESULT hr;
+
+    TRACE("(%p,%p,%p)\n",This,pDD,pDDSD);
+
+    /* copy surface_desc, we may want to modify it before DIB construction */
+    This->surface_desc = *pDDSD;
+
+    /* the driver may want to dereference these pointers */
+    This->local.lpSurfMore = &This->more;
+    This->local.lpGbl = &This->global;   
+    This->gmore = &This->global_more;
+
+    if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
+	hr = HAL_DirectDrawSurface_create_surface(This, pDD);
+	if (FAILED(hr)) return hr;
+
+	hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc);
+	if (FAILED(hr)) return hr;
+    }
+    else if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) {
+	FIXME("create execute buffer\n");
+	return DDERR_GENERIC;
+    }
+    else {
+	if (!(dd_gbl->dwFlags & DDRAWI_MODECHANGED)) {
+	    /* force a mode set (HALs like DGA may need it) */
+	    hr = HAL_DirectDraw_SetDisplayMode(ICOM_INTERFACE(pDD, IDirectDraw7),
+					       pDD->width, pDD->height,
+					       pDD->pixelformat.u1.dwRGBBitCount,
+					       0, 0);
+	    if (FAILED(hr)) return hr;
+	}
+
+	if (dd_gbl->vmiData.fpPrimary) {
+	    hr = HAL_DirectDrawSurface_create_surface(This, pDD);
+	    if (FAILED(hr)) return hr;
+
+	    if (priv->hal.need_late) {
+		/* this doesn't make sense... driver error? */
+		ERR("driver failed to create framebuffer surface\n");
+		return DDERR_GENERIC;
+	    }
+
+	    hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc);
+	    if (FAILED(hr)) return hr;
+	} else {
+	    /* no framebuffer, construct User-based primary */
+	    hr = User_DirectDrawSurface_Construct(This, pDD, pDDSD);
+	    if (FAILED(hr)) return hr;
+
+	    /* must notify HAL *after* creating User-based primary */
+	    /* (or use CreateSurfaceEx, which we don't yet) */
+	    hr = HAL_DirectDrawSurface_create_surface(This, pDD);
+	    if (FAILED(hr)) return hr;
+
+	    priv->hal.need_late = FALSE;
+	}
+    }
+
+    ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
+			HAL_IDirectDrawSurface7_VTable);
+
+    This->final_release = HAL_DirectDrawSurface_final_release;
+    This->late_allocate = HAL_DirectDrawSurface_late_allocate;
+    This->duplicate_surface = HAL_DirectDrawSurface_duplicate_surface;
+
+    This->flip_data   = HAL_DirectDrawSurface_flip_data;
+    This->flip_update = HAL_DirectDrawSurface_flip_update;
+
+    This->set_palette    = HAL_DirectDrawSurface_set_palette;
+
+    This->get_display_window = HAL_DirectDrawSurface_get_display_window;
+
+    return DD_OK;
+}
+
+HRESULT
+HAL_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			     const DDSURFACEDESC2 *pDDSD,
+			     LPDIRECTDRAWSURFACE7 *ppSurf,
+			     IUnknown *pUnkOuter)
+{
+    IDirectDrawSurfaceImpl* This;
+    HRESULT hr;
+    assert(pUnkOuter == NULL);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+		     sizeof(*This) + sizeof(HAL_DirectDrawSurfaceImpl));
+    if (This == NULL) return E_OUTOFMEMORY;
+
+    This->private = (HAL_DirectDrawSurfaceImpl*)(This+1);
+
+    hr = HAL_DirectDrawSurface_Construct(This, pDD, pDDSD);
+    if (FAILED(hr))
+	HeapFree(GetProcessHeap(), 0, This);
+    else
+	*ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
+
+    return hr;
+}
+
+void HAL_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
+{
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
+    DDHAL_DESTROYSURFACEDATA data;
+
+    /* destroy HAL surface */
+    data.lpDD = dd_gbl;
+    data.lpDDSurface = &This->local;
+    data.ddRVal = 0;
+    data.DestroySurface = dd_gbl->lpDDCBtmp->HALDDSurface.DestroySurface;
+    data.DestroySurface(&data);
+
+    if (HAL_IsUser(This)) {
+	User_DirectDrawSurface_final_release(This);
+    } else {
+	DIB_DirectDrawSurface_final_release(This);
+    }
+}
+
+HRESULT HAL_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
+{
+    HAL_PRIV_VAR(priv, This);
+    if (priv->hal.need_late) {
+	priv->hal.need_late = FALSE;
+	return HAL_DirectDrawSurface_create_surface(This, This->ddraw_owner);
+    }
+    return DD_OK;
+}
+
+void HAL_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawPaletteImpl* pal) 
+{
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
+    DDHAL_SETPALETTEDATA data;
+
+    DIB_DirectDrawSurface_set_palette(This, pal);
+    data.lpDD = dd_gbl;
+    data.lpDDSurface = &This->local;
+    data.lpDDPalette = &pal->global;
+    data.ddRVal = 0;
+    data.Attach = TRUE; /* what's this? */
+    data.SetPalette = dd_gbl->lpDDCBtmp->HALDDSurface.SetPalette;
+    if (data.SetPalette)
+	data.SetPalette(&data);
+}
+
+HRESULT HAL_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						LPDIRECTDRAWSURFACE7* ppDup)
+{
+    return HAL_DirectDrawSurface_Create(This->ddraw_owner,
+					     &This->surface_desc, ppDup, NULL);
+}
+
+void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
+				       LPCRECT pRect)
+{
+    if (HAL_IsUser(This)) {
+	User_DirectDrawSurface_lock_update(This, pRect);
+    } else {
+	Main_DirectDrawSurface_lock_update(This, pRect);
+    }
+}
+
+void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+					 LPCRECT pRect)
+{
+    if (HAL_IsUser(This)) {
+	User_DirectDrawSurface_unlock_update(This, pRect);
+    } else {
+	Main_DirectDrawSurface_unlock_update(This, pRect);
+    }
+}
+
+BOOL HAL_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				     IDirectDrawSurfaceImpl* back,
+				     DWORD dwFlags)
+{
+    HAL_PRIV_VAR(front_priv, front);
+    HAL_PRIV_VAR(back_priv, back);
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = front->more.lpDD_lcl->lpGbl;
+    DDHAL_FLIPDATA data;
+    BOOL ret;
+
+    {
+	DWORD tmp;
+	tmp = front_priv->hal.fb_vofs;
+	front_priv->hal.fb_vofs = back_priv->hal.fb_vofs;
+	back_priv->hal.fb_vofs = tmp;
+    }
+    {
+	LPVOID tmp;
+	tmp = front_priv->hal.fb_addr;
+	front_priv->hal.fb_addr = back_priv->hal.fb_addr;
+	back_priv->hal.fb_addr = tmp;
+    }
+
+    if (HAL_IsUser(front)) {
+	ret = User_DirectDrawSurface_flip_data(front, back, dwFlags);
+    } else {
+	ret = DIB_DirectDrawSurface_flip_data(front, back, dwFlags);
+    }
+
+    data.lpDD = dd_gbl;
+    data.lpSurfCurr = &front->local;
+    data.lpSurfTarg = &back->local;
+    data.lpSurfCurrLeft = NULL;
+    data.lpSurfTargLeft = NULL;
+    data.dwFlags = dwFlags;
+    data.ddRVal = 0;
+    data.Flip = dd_gbl->lpDDCBtmp->HALDDSurface.Flip;
+    if (data.Flip)
+	if (data.Flip(&data) == DDHAL_DRIVER_HANDLED) ret = FALSE;
+
+    return ret;
+}
+
+void HAL_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFlags)
+{
+    if (HAL_IsUser(This)) {
+	User_DirectDrawSurface_flip_update(This, dwFlags);
+    }
+}
+
+HWND HAL_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
+{
+    return 0;
+}
+
+static ICOM_VTABLE(IDirectDrawSurface7) HAL_IDirectDrawSurface7_VTable =
+{
+    Main_DirectDrawSurface_QueryInterface,
+    Main_DirectDrawSurface_AddRef,
+    Main_DirectDrawSurface_Release,
+    Main_DirectDrawSurface_AddAttachedSurface,
+    Main_DirectDrawSurface_AddOverlayDirtyRect,
+    DIB_DirectDrawSurface_Blt,
+    Main_DirectDrawSurface_BltBatch,
+    DIB_DirectDrawSurface_BltFast,
+    Main_DirectDrawSurface_DeleteAttachedSurface,
+    Main_DirectDrawSurface_EnumAttachedSurfaces,
+    Main_DirectDrawSurface_EnumOverlayZOrders,
+    Main_DirectDrawSurface_Flip,
+    Main_DirectDrawSurface_GetAttachedSurface,
+    Main_DirectDrawSurface_GetBltStatus,
+    Main_DirectDrawSurface_GetCaps,
+    Main_DirectDrawSurface_GetClipper,
+    Main_DirectDrawSurface_GetColorKey,
+    Main_DirectDrawSurface_GetDC,
+    Main_DirectDrawSurface_GetFlipStatus,
+    Main_DirectDrawSurface_GetOverlayPosition,
+    Main_DirectDrawSurface_GetPalette,
+    Main_DirectDrawSurface_GetPixelFormat,
+    Main_DirectDrawSurface_GetSurfaceDesc,
+    Main_DirectDrawSurface_Initialize,
+    Main_DirectDrawSurface_IsLost,
+    Main_DirectDrawSurface_Lock,
+    Main_DirectDrawSurface_ReleaseDC,
+    DIB_DirectDrawSurface_Restore,
+    Main_DirectDrawSurface_SetClipper,
+    Main_DirectDrawSurface_SetColorKey,
+    Main_DirectDrawSurface_SetOverlayPosition,
+    Main_DirectDrawSurface_SetPalette,
+    Main_DirectDrawSurface_Unlock,
+    Main_DirectDrawSurface_UpdateOverlay,
+    Main_DirectDrawSurface_UpdateOverlayDisplay,
+    Main_DirectDrawSurface_UpdateOverlayZOrder,
+    Main_DirectDrawSurface_GetDDInterface,
+    Main_DirectDrawSurface_PageLock,
+    Main_DirectDrawSurface_PageUnlock,
+    DIB_DirectDrawSurface_SetSurfaceDesc,
+    Main_DirectDrawSurface_SetPrivateData,
+    Main_DirectDrawSurface_GetPrivateData,
+    Main_DirectDrawSurface_FreePrivateData,
+    Main_DirectDrawSurface_GetUniquenessValue,
+    Main_DirectDrawSurface_ChangeUniquenessValue,
+    Main_DirectDrawSurface_SetPriority,
+    Main_DirectDrawSurface_GetPriority,
+    Main_DirectDrawSurface_SetLOD,
+    Main_DirectDrawSurface_GetLOD
+};
diff --git a/dlls/ddraw/dsurface/hal.h b/dlls/ddraw/dsurface/hal.h
new file mode 100644
index 0000000..1f7bd79
--- /dev/null
+++ b/dlls/ddraw/dsurface/hal.h
@@ -0,0 +1,58 @@
+/* Copyright 2000-2001 TransGaming Technologies Inc. */
+
+#ifndef DDRAW_DSURFACE_HAL_H_INCLUDED
+#define DDRAW_DSURFACE_HAL_H_INCLUDED
+
+#define HAL_PRIV(surf) ((HAL_DirectDrawSurfaceImpl*)((surf)->private))
+
+#define HAL_PRIV_VAR(name,surf) \
+	HAL_DirectDrawSurfaceImpl* name = HAL_PRIV(surf)
+
+struct HAL_DirectDrawSurfaceImpl_Part
+{
+    DWORD need_late;
+    LPVOID fb_addr;
+    DWORD fb_pitch, fb_vofs;
+};
+
+typedef struct
+{
+    struct DIB_DirectDrawSurfaceImpl_Part dib;
+    struct User_DirectDrawSurfaceImpl_Part user;
+    struct HAL_DirectDrawSurfaceImpl_Part hal;
+} HAL_DirectDrawSurfaceImpl;
+
+HRESULT
+HAL_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
+				IDirectDrawImpl* pDD,
+				const DDSURFACEDESC2* pDDSD);
+
+HRESULT
+HAL_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
+			     const DDSURFACEDESC2 *pDDSD,
+			     LPDIRECTDRAWSURFACE7 *ppSurf,
+			     IUnknown *pUnkOuter);
+
+void HAL_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
+HRESULT HAL_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This);
+
+void HAL_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
+				       IDirectDrawPaletteImpl* pal);
+void HAL_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
+					  IDirectDrawPaletteImpl* pal,
+					  DWORD dwStart, DWORD dwCount,
+					  LPPALETTEENTRY palent);
+HRESULT HAL_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
+						LPDIRECTDRAWSURFACE7* ppDup);
+void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
+				       LPCRECT pRect);
+void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
+					 LPCRECT pRect);
+BOOL HAL_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
+				     IDirectDrawSurfaceImpl* back,
+				     DWORD dwFlags);
+void HAL_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This,
+				       DWORD dwFlags);
+HWND HAL_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This);
+
+#endif
diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c
index 984c39f..07f1740 100644
--- a/dlls/ddraw/main.c
+++ b/dlls/ddraw/main.c
@@ -2,7 +2,7 @@
  *
  * Copyright 1997-1999 Marcus Meissner
  * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
- * Copyright 2000 TransGaming Technologies Inc.
+ * Copyright 2000-2001 TransGaming Technologies Inc.
  *
  * This file contains the (internal) driver registration functions,
  * driver enumeration APIs and DirectDraw creation functions.
@@ -479,15 +479,9 @@
     /* If we were sufficiently cool, DDraw drivers would just be COM
      * objects, registered with a particular component category. */
 
+    DDRAW_HAL_Init(hInstDLL, fdwReason, lpv);
     DDRAW_User_Init(hInstDLL, fdwReason, lpv);
 
-#ifdef HAVE_LIBXXF86VM
-    DDRAW_XVidMode_Init(hInstDLL, fdwReason, lpv);
-#endif
-#ifdef HAVE_LIBXXF86DGA2
-    DDRAW_XF86DGA2_Init(hInstDLL, fdwReason, lpv);
-#endif
-
     if (DDRAW_num_drivers > 0)
 	DDRAW_default_driver = DDRAW_ChooseDefaultDriver();