Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
DOSBox Glide patch.
From: gulikoza <gulikoza@si-gamer.net>
Add Glide support.
Author: gulikoza (http://vogons.zetafleet.com/viewtopic.php?t=16462)
Changes:
- configurable splash screen
- support multiple buffer locks (eg: back + depth) (Extreme Assault)
- increase available LFB memory
- fix Tie Break Tennis init
- fix Unreal GPF
Previous versions:
- 2012/06/08: Fix grTexClampMode (thanks robertmo!)
- 2011/08/03: Fix polygon rendering
- 2010/10/27: Add Pył support, fix grLFBRead/WriteRegion
- 2009/11/24: Fix some minor issues, add MacOSX support (!)
- 2009/10/09: Various fixes and code cleanups, fix originlocation + splash screen
- 2009/08/30: Fix LFB operations when paging is active
- 2009/06/04: Updated for 0.73, add MSVC6 projects for glide2x win9x build
- 2008/09/14: Updated for current CVS, allow disabling LFB reads/writes
- 2008/02/17: Updated for current CVS
- 2007/11/06: Improve TR shadow support (gidierre)
- 2007/10/18: Add TombRaider shadow hack (thanks gidierre!)
- 2007/09/03: Fix a crash when closing dosbox while glide is active
- 2007/08/28: x86_64 support
- 2007/08/23: Fix buffer overflow
- 2007/08/22: Fix compilation problems
TODO:
- threading (?)
---
configure.ac | 2
include/glide.h | 331 ++++++++
include/glidedef.h | 179 ++++
include/mem.h | 2
src/dosbox.cpp | 12
src/gui/sdlmain.cpp | 13
src/hardware/Makefile.am | 2
src/hardware/glide.cpp | 1962 ++++++++++++++++++++++++++++++++++++++++++++++
src/hardware/memory.cpp | 21
9 files changed, 2520 insertions(+), 4 deletions(-)
create mode 100644 include/glide.h
create mode 100644 include/glidedef.h
create mode 100644 src/hardware/glide.cpp
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -450,7 +450,7 @@ int main(int argc,char * argv[]) {
dnl Some target detection and actions for them
case "$host" in
*-*-cygwin* | *-*-mingw32*)
- LIBS="$LIBS -lwinmm"
+ LIBS="$LIBS -lwinmm -lshlwapi"
AC_CHECK_HEADERS(ddraw.h)
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2 only).])
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
diff --git a/include/glide.h b/include/glide.h
new file mode 100644
--- /dev/null
+++ b/include/glide.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2002-2007 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_GLIDE_H
+#define DOSBOX_GLIDE_H
+
+#define __3DFX_H__
+
+/*
+** basic data types
+*/
+typedef Bit8u FxU8;
+typedef Bit8s FxI8;
+typedef Bit16u FxU16;
+typedef Bit16s FxI16;
+typedef Bit32u FxU32;
+typedef Bit32s FxI32;
+typedef Bit32s FxBool;
+typedef float FxFloat;
+typedef double FxDouble;
+
+/*
+** color types
+*/
+typedef Bit32u FxColor_t;
+typedef struct { float r, g, b, a; } FxColor4;
+
+/*
+** fundamental types
+*/
+#define FXTRUE 1
+#define FXFALSE 0
+
+/*
+** helper macros
+*/
+#define FXUNUSED( a ) ((void)(a))
+#define FXBIT( i ) ( 1L << (i) )
+
+#define FX_ENTRY
+#define FX_GLIDE_NO_FUNC_PROTO
+
+#if defined (WIN32)
+#define FX_CALL __stdcall
+#else
+#define FX_CALL
+#endif
+
+#include <sdk2_glide.h>
+#include "glidedef.h"
+
+// Careful with structures containing pointers
+//
+// GrTexInfo; GrLfbInfo_t; Gu3dfInfo; GrMipMapInfo;
+//
+
+// Some glide structs might have different size in guest 32-bit DOS (pointers)
+typedef struct {
+ Bit32s smallLod;
+ Bit32s largeLod;
+ Bit32s aspectRatio;
+ Bit32s format;
+ PhysPt data;
+} DBGrTexInfo;
+
+typedef struct {
+ Bit32s size;
+ PhysPt lfbPtr;
+ Bit32u strideInBytes;
+ Bit32s writeMode;
+ Bit32s origin;
+} DBGrLfbInfo_t;
+
+typedef struct {
+ Gu3dfHeader header;
+ GuTexTable table;
+ PhysPt data;
+ Bit32u mem_required;
+} DBGu3dfInfo;
+
+typedef struct {
+ const char * name;
+ const Bit8u parms;
+} GLIDE_TABLE;
+
+typedef void (FX_CALL *pfunc0) (void);
+typedef void (FX_CALL *pfunc1i) (FxU32);
+typedef void (FX_CALL *pfunc1p) (void*);
+typedef void (FX_CALL *pfunc1f) (float);
+typedef void (FX_CALL *pfunc2i) (FxU32, FxU32);
+typedef void (FX_CALL *pfunc1i1p) (FxU32, void*);
+typedef void (FX_CALL *pfunc2p) (void*, void*);
+typedef void (FX_CALL *pfunc1i1f) (FxU32, float);
+typedef void (FX_CALL *pfunc1p1f) (void*, float);
+typedef void (FX_CALL *pfunc3i) (FxU32, FxU32, FxU32);
+typedef void (FX_CALL *pfunc2i1p) (FxU32, FxU32, void*);
+typedef void (FX_CALL *pfunc1i2p) (FxU32, void*, void*);
+typedef void (FX_CALL *pfunc3p) (void*, void*, void*);
+typedef void (FX_CALL *pfunc1p2f) (void*, float, float);
+typedef void (FX_CALL *pfunc4i) (FxU32, FxU32, FxU32, FxU32);
+typedef void (FX_CALL *pfunc3i1p) (FxU32, FxU32, FxU32, void*);
+typedef void (FX_CALL *pfunc3i1f) (FxU32, FxU32, FxU32, float);
+typedef void (FX_CALL *pfunc4f) (float, float, float, float);
+typedef void (FX_CALL *pfunc5i) (FxU32, FxU32, FxU32, FxU32, FxU32);
+typedef void (FX_CALL *pfunc2i1p2i) (FxU32, FxU32, void*, FxU32, FxU32);
+typedef void (FX_CALL *pfunc4f1i) (float, float, float, float, FxU32);
+typedef void (FX_CALL *pfunc3p3i) (void*, void*, void*, FxU32, FxU32, FxU32);
+typedef void (FX_CALL *pfunc7i) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32);
+typedef void (FX_CALL *pfunc7i1p) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*);
+typedef void (FX_CALL *pfunc7i1p2i) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*,
+ FxU32, FxU32);
+typedef void (FX_CALL *pfunc7i1p7i1p) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*,
+ FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*);
+
+typedef FxU32 (FX_CALL *prfunc0) (void);
+typedef FxU32 (FX_CALL *prfunc1i) (FxU32);
+typedef FxU32 (FX_CALL *prfunc1p) (void*);
+typedef FxU32 (FX_CALL *prfunc2i) (FxU32, FxU32);
+typedef FxU32 (FX_CALL *prfunc1i1p) (FxU32, void*);
+typedef FxU32 (FX_CALL *prfunc2p) (void*, void*);
+typedef FxU32 (FX_CALL *prfunc4i) (FxU32, FxU32, FxU32, FxU32);
+typedef FxU32 (FX_CALL *prfunc5i1p) (FxU32, FxU32, FxU32, FxU32, FxU32, void*);
+typedef FxU32 (FX_CALL *prfunc7i) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32);
+typedef FxU32 (FX_CALL *prfunc1p6i) (void*, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32);
+typedef FxU32 (FX_CALL *prfunc6i1p) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*);
+typedef FxU32 (FX_CALL *prfunc7i1p) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, void*);
+typedef FxU32 (FX_CALL *prfunc12i) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32,
+ FxU32, FxU32, FxU32, FxU32, FxU32);
+typedef FxU32 (FX_CALL *prfunc13i1f1i) (FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32, FxU32,
+ FxU32, FxU32, FxU32, FxU32, FxU32, float, FxU32);
+
+typedef void* (FX_CALL *prptfunc1i) (FxU32);
+typedef float (FX_CALL *pffunc1i) (FxU32);
+
+typedef union {
+ pfunc0 grFunction0;
+ pfunc1i grFunction1i;
+ pfunc1p grFunction1p;
+ pfunc1f grFunction1f;
+ pfunc2i grFunction2i;
+ pfunc1i1p grFunction1i1p;
+ pfunc2p grFunction2p;
+ pfunc1i1f grFunction1i1f;
+ pfunc1p1f grFunction1p1f;
+ pfunc3i grFunction3i;
+ pfunc2i1p grFunction2i1p;
+ pfunc1i2p grFunction1i2p;
+ pfunc3p grFunction3p;
+ pfunc1p2f grFunction1p2f;
+ pfunc4i grFunction4i;
+ pfunc3i1p grFunction3i1p;
+ pfunc3i1f grFunction3i1f;
+ pfunc4f grFunction4f;
+ pfunc5i grFunction5i;
+ pfunc2i1p2i grFunction2i1p2i;
+ pfunc4f1i grFunction4f1i;
+ pfunc3p3i grFunction3p3i;
+ pfunc7i grFunction7i;
+ pfunc7i1p grFunction7i1p;
+ pfunc7i1p2i grFunction7i1p2i;
+ pfunc7i1p7i1p grFunction7i1p7i1p;
+
+ prfunc0 grRFunction0;
+ prfunc1i grRFunction1i;
+ prfunc1p grRFunction1p;
+ prfunc2i grRFunction2i;
+ prfunc1i1p grRFunction1i1p;
+ prfunc2p grRFunction2p;
+ prfunc4i grRFunction4i;
+ prfunc5i1p grRFunction5i1p;
+ prfunc7i grRFunction7i;
+ prfunc1p6i grRFunction1p6i;
+ prfunc6i1p grRFunction6i1p;
+ prfunc7i1p grRFunction7i1p;
+ prfunc12i grRFunction12i;
+ prfunc13i1f1i grRFunction13i1f1i;
+
+ prptfunc1i grRPTFunction1i;
+
+ pffunc1i grFFunction1i;
+} FncPointers;
+
+static const GLIDE_TABLE grTable[] = {
+ { "grAADrawLine", 8 },
+ { "grAADrawPoint", 4 },
+ { "grAADrawPolygon", 12 },
+ { "grAADrawPolygonVertexList", 8 },
+ { "grAADrawTriangle", 24 },
+ { "grAlphaBlendFunction", 16 },
+ { "grAlphaCombine", 20 },
+ { "grAlphaControlsITRGBLighting", 4 },
+ { "grAlphaTestFunction", 4 },
+ { "grAlphaTestReferenceValue", 4 },
+ { "grBufferClear", 12 },
+ { "grBufferNumPending", 0 },
+ { "grBufferSwap", 4 },
+ { "grCheckForRoom", 4 },
+ { "grChromakeyMode", 4 },
+ { "grChromakeyValue", 4 },
+ { "grClipWindow", 16 },
+ { "grColorCombine", 20 },
+ { "grColorMask", 8 },
+ { "grConstantColorValue4", 16 },
+ { "grConstantColorValue", 4 },
+ { "grCullMode", 4 },
+ { "grDepthBiasLevel", 4 },
+ { "grDepthBufferFunction", 4 },
+ { "grDepthBufferMode", 4 },
+ { "grDepthMask", 4 },
+ { "grDisableAllEffects", 0 },
+ { "grDitherMode", 4 },
+ { "grDrawLine", 8 },
+ { "grDrawPlanarPolygon", 12 },
+ { "grDrawPlanarPolygonVertexList", 8 },
+ { "grDrawPoint", 4 },
+ { "grDrawPolygon", 12 },
+ { "grDrawPolygonVertexList", 8 },
+ { "grDrawTriangle", 12 },
+ { "grErrorSetCallback", 4 },
+ { "grFogColorValue", 4 },
+ { "grFogMode", 4 },
+ { "grFogTable", 4 },
+ { "grGammaCorrectionValue", 4 },
+ { "grGlideGetState", 4 },
+ { "grGlideGetVersion", 4 },
+ { "grGlideInit", 0 },
+ { "grGlideSetState", 4 },
+ { "grGlideShamelessPlug", 4 },
+ { "grGlideShutdown", 0 },
+ { "grHints", 8 },
+ { "grLfbConstantAlpha", 4 },
+ { "grLfbConstantDepth", 4 },
+ { "grLfbLock", 24 },
+ { "grLfbReadRegion", 28 },
+ { "grLfbUnlock", 8 },
+ { "grLfbWriteColorFormat", 4 },
+ { "grLfbWriteColorSwizzle", 8 },
+ { "grLfbWriteRegion", 32 },
+ { "grRenderBuffer", 4 },
+ { "grResetTriStats", 0 },
+ { "grSplash", 20 },
+ { "grSstConfigPipeline", 12 },
+ { "grSstControl", 4 },
+ { "grSstIdle", 0 },
+ { "grSstIsBusy", 0 },
+ { "grSstOrigin", 4 },
+ { "grSstPerfStats", 4 },
+ { "grSstQueryBoards", 4 },
+ { "grSstQueryHardware", 4 },
+ { "grSstResetPerfStats", 0 },
+ { "grSstScreenHeight", 0 },
+ { "grSstScreenWidth", 0 },
+ { "grSstSelect", 4 },
+ { "grSstStatus", 0 },
+ { "grSstVRetraceOn", 0 },
+ { "grSstVidMode", 8 },
+ { "grSstVideoLine", 0 },
+ { "grSstWinClose", 0 },
+ { "grSstWinOpen", 28 },
+ { "grTexCalcMemRequired", 16 },
+ { "grTexClampMode", 12 },
+ { "grTexCombine", 28 },
+ { "grTexCombineFunction", 8 },
+ { "grTexDetailControl", 16 },
+ { "grTexDownloadMipMap", 16 },
+ { "grTexDownloadMipMapLevel", 32 },
+ { "grTexDownloadMipMapLevelPartial", 40 },
+ { "grTexDownloadTable", 12 },
+ { "grTexDownloadTablePartial", 20 },
+ { "grTexFilterMode", 12 },
+ { "grTexLodBiasValue", 8 },
+ { "grTexMaxAddress", 4 },
+ { "grTexMinAddress", 4 },
+ { "grTexMipMapMode", 12 },
+ { "grTexMultibase", 8 },
+ { "grTexMultibaseAddress", 20 },
+ { "grTexNCCTable", 8 },
+ { "grTexSource", 16 },
+ { "grTexTextureMemRequired", 8 },
+ { "grTriStats", 8 },
+ { "gu3dfGetInfo", 8 },
+ { "gu3dfLoad", 8 },
+ { "guAADrawTriangleWithClip", 12 },
+ { "guAlphaSource", 4 },
+ { "guColorCombineFunction", 4 },
+ { "guDrawPolygonVertexListWithClip", 8 },
+ { "guDrawTriangleWithClip", 12 },
+ { "guEncodeRLE16", 16 },
+ { "guEndianSwapBytes", 4 },
+ { "guEndianSwapWords", 4 },
+ { "guFogGenerateExp2", 8 },
+ { "guFogGenerateExp", 8 },
+ { "guFogGenerateLinear", 12 },
+ { "guFogTableIndexToW", 4 },
+ { "guMPDrawTriangle", 12 },
+ { "guMPInit", 0 },
+ { "guMPTexCombineFunction", 4 },
+ { "guMPTexSource", 8 },
+ { "guMovieSetName", 4 },
+ { "guMovieStart", 0 },
+ { "guMovieStop", 0 },
+ { "guTexAllocateMemory", 60 },
+ { "guTexChangeAttributes", 48 },
+ { "guTexCombineFunction", 8 },
+ { "guTexCreateColorMipMap", 0 },
+ { "guTexDownloadMipMap", 12 },
+ { "guTexDownloadMipMapLevel", 12 },
+ { "guTexGetCurrentMipMap", 4 },
+ { "guTexGetMipMapInfo", 4 },
+ { "guTexMemQueryAvail", 4 },
+ { "guTexMemReset", 0 },
+ { "guTexSource", 4 },
+ { "ConvertAndDownloadRle", 64 }
+};
+
+#endif // DOSBOX_GLIDE_H
diff --git a/include/glidedef.h b/include/glidedef.h
new file mode 100644
--- /dev/null
+++ b/include/glidedef.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2002-2007 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLIDEDEF_H
+#define GLIDEDEF_H
+
+#ifdef DOSBOX_DOSBOX_H
+struct GLIDE_Block
+{
+ bool splash;
+ bool enabled;
+ bool * fullscreen;
+ Bit16u width, height;
+ class GLIDE_PageHandler * lfb_pagehandler;
+ GLIDE_Block():enabled(false),fullscreen(0),width(0),height(0),lfb_pagehandler((GLIDE_PageHandler*)0) { }
+};
+extern GLIDE_Block glide;
+extern void GLIDE_ResetScreen(bool update=false);
+extern void GLIDE_DisableScreen(void);
+#endif
+
+#define GLIDE_LFB 0x60000000
+#define GLIDE_BUFFERS 3 /* Front, Back, AUX */
+#define GLIDE_PAGE_BITS 11 /* =2048 pages per buffer, should be enough for 1600x1200x4 */
+#define GLIDE_PAGES (GLIDE_BUFFERS*(1<<GLIDE_PAGE_BITS))
+
+#ifdef __3DFX_H__
+/* If you change these defines, don't forget to change the table in glide.h and compile a matching GLIDE2X.OVL */
+
+#define _grAADrawLine8 0 // void grAADrawLine(GrVertex *va, GrVertex *vb)
+#define _grAADrawPoint4 1 // void grAADrawPoint(GrVertex *p)
+#define _grAADrawPolygon12 2 // void grAADrawPolygon(int nVerts, const int ilist[], const GrVertex vlist[])
+#define _grAADrawPolygonVertexList8 3 // void grAADrawPolygonVertexList(int nVerts, const GrVertex vlist[])
+#define _grAADrawTriangle24 4 // void grAADrawTriangle(GrVertex *a, GrVertex *b, GrVertex *c, FxBool antialiasAB, FxBool antialiasBC, FxBool antialiasCA)
+#define _grAlphaBlendFunction16 5 // void grAlphaBlendFunction(GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df)
+#define _grAlphaCombine20 6 // void grAlphaCombine(GrCombineFunction_t func, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert)
+#define _grAlphaControlsITRGBLighting4 7 // void grAlphaControlsITRGBLighting(FxBool enable)
+#define _grAlphaTestFunction4 8 // void grAlphaTestFunction(GrCmpFnc_t function)
+#define _grAlphaTestReferenceValue4 9 // void grAlphaTestReferenceValue(GrAlpha_t value)
+#define _grBufferClear12 10 // void grBufferClear(GrColor_t color, GrAlpha_t alpha, FxU16 depth)
+#define _grBufferNumPending0 11 // int grBufferNumPending(void)
+#define _grBufferSwap4 12 // void grBufferSwap(int swap_interval)
+#define _grCheckForRoom4 13 // void grCheckForRoom(FxI32 n)
+#define _grChromakeyMode4 14 // void grChromakeyMode(GrChromakeyMode_t mode)
+#define _grChromakeyValue4 15 // void grChromakeyValue(GrColor_t value)
+#define _grClipWindow16 16 // void grClipWindow(FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy)
+#define _grColorCombine20 17 // void grColorCombine(GrCombineFunction_t func, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert)
+#define _grColorMask8 18 // void grColorMask(FxBool rgb, FxBool alpha)
+#define _grConstantColorValue416 19 // void grConstantColorValue4(float a, float r, float g, float b)
+#define _grConstantColorValue4 20 // void grConstantColorValue(GrColor_t color)
+#define _grCullMode4 21 // void grCullMode(GrCullMode_t mode)
+#define _grDepthBiasLevel4 22 // void grDepthBiasLevel(FxI16 level)
+#define _grDepthBufferFunction4 23 // void grDepthBufferFunction(GrCmpFnc_t func)
+#define _grDepthBufferMode4 24 // void grDepthBufferMode(GrDepthBufferMode_t mode)
+#define _grDepthMask4 25 // void grDepthMask(FxBool enable)
+#define _grDisableAllEffects0 26 // void grDisableAllEffects(void)
+#define _grDitherMode4 27 // void grDitherMode(GrDitherMode_t mode)
+#define _grDrawLine8 28 // void grDrawLine(const GrVertex *a, const GrVertex *b)
+#define _grDrawPlanarPolygon12 29 // void grDrawPlanarPolygon(int nVerts, int ilist[], const GrVertex vlist[])
+#define _grDrawPlanarPolygonVertexList8 30 // void grDrawPlanarPolygonVertexList(int nVerts, const GrVertex vlist[])
+#define _grDrawPoint4 31 // void grDrawPoint(const GrVertex *a)
+#define _grDrawPolygon12 32 // void grDrawPolygon(int nVerts, int ilist[], const GrVertex vlist[])
+#define _grDrawPolygonVertexList8 33 // void grDrawPolygonVertexList(int nVerts, const GrVertex vlist[])
+#define _grDrawTriangle12 34 // void grDrawTriangle(const GrVertex *a, const GrVertex *b, const GrVertex *c)
+#define _grErrorSetCallback4 35 // void grErrorSetCallback(void (*function)(const char *string, FxBool fatal))
+#define _grFogColorValue4 36 // void grFogColorValue(GrColor_t value)
+#define _grFogMode4 37 // void grFogMode(GrFogMode_t mode)
+#define _grFogTable4 38 // void grFogTable(const GrFog_t table[GR_FOG_TABLE_SIZE])
+#define _grGammaCorrectionValue4 39 // void grGammaCorrectionValue(float value)
+#define _grGlideGetState4 40 // void grGlideGetState(GrState *state)
+#define _grGlideGetVersion4 41 // void grGlideGetVersion(char version[80])
+#define _grGlideInit0 42 // void grGlideInit(void)
+#define _grGlideSetState4 43 // void grGlideSetState(const GrState *state)
+#define _grGlideShamelessPlug4 44 // void grGlideShamelessPlug(const FxBool on)
+#define _grGlideShutdown0 45 // void grGlideShutdown(void)
+#define _grHints8 46 // void grHints(GrHint_t type, FxU32 hintMask)
+#define _grLfbConstantAlpha4 47 // void grLfbConstantAlpha(GrAlpha_t alpha)
+#define _grLfbConstantDepth4 48 // void grLfbConstantDepth(FxU16 depth)
+#define _grLfbLock24 49 // FxBool grLfbLock(GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, FxBool pixelPipeline, GrLfbInfo_t *info)
+#define _grLfbReadRegion28 50 // FxBool grLfbReadRegion(GrBuffer_t src_buffer, FxU32 src_x, FxU32 src_y, FxU32 src_width, FxU32 src_height, FxU32 dst_stride, void *dst_data)
+#define _grLfbUnlock8 51 // FxBool grLfbUnlock(GrLock_t type, GrBuffer_t buffer)
+#define _grLfbWriteColorFormat4 52 // void grLfbWriteColorFormat(GrColorFormat_t colorFormat)
+#define _grLfbWriteColorSwizzle8 53 // void grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
+#define _grLfbWriteRegion32 54 // FxBool grLfbWriteRegion(GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format, FxU32 src_width, FxU32 src_height, FxU32 src_stride, void *src_data)
+#define _grRenderBuffer4 55 // void grRenderBuffer(GrBuffer_t buffer)
+#define _grResetTriStats0 56 // void grResetTriStats()
+#define _grSplash20 57 // void grSplash(float x, float y, float width, float height, FxU32 frame)
+#define _grSstConfigPipeline12 58 //
+#define _grSstControl4 59 // FxBool grSstControl(FxU32 code)
+#define _grSstIdle0 60 // void grSstIdle(void)
+#define _grSstIsBusy0 61 // FxBool grSstIsBusy(void)
+#define _grSstOrigin4 62 // void grSstOrigin(GrOriginLocation_t origin)
+#define _grSstPerfStats4 63 // void grSstPerfStats(GrSstPerfStats_t *pStats)
+#define _grSstQueryBoards4 64 // FxBool grSstQueryBoards(GrHwConfiguration *hwConfig)
+#define _grSstQueryHardware4 65 // FxBool grSstQueryHardware(GrHwConfiguration *hwConfig)
+#define _grSstResetPerfStats0 66 // void grSstResetPerfStats(void)
+#define _grSstScreenHeight0 67 // FxU32 grSstScreenHeight(void)
+#define _grSstScreenWidth0 68 // FxU32 grSstScreenWidth(void)
+#define _grSstSelect4 69 // void grSstSelect(int which_sst)
+#define _grSstStatus0 70 // FxU32 grSstStatus(void)
+#define _grSstVRetraceOn0 71 // FxBool grSstVRetraceOn(void)
+#define _grSstVidMode8 72 //
+#define _grSstVideoLine0 73 // FxU32 grSstVideoLine(void)
+#define _grSstWinClose0 74 // void grSstWinClose(void)
+#define _grSstWinOpen28 75 // FxBool grSstWinOpen(FxU32 hwnd, GrScreenResolution_t res, GrScreenRefresh_t ref, GrColorFormat_t cformat, GrOriginLocation_t org_loc, int num_buffers, int num_aux_buffers)
+#define _grTexCalcMemRequired16 76 // FxU32 grTexCalcMemRequired(GrLOD_t smallLod, GrLOD_t largeLod, GrAspectRatio_t aspect, GrTextureFormat_t format)
+#define _grTexClampMode12 77 // void grTexClampMode(GrChipID_t tmu, GrTextureClampMode_t sClampMode, GrTextureClampMode_t tClampMode)
+#define _grTexCombine28 78 // void grTexCombine(GrChipID_t tmu, GrCombineFunction_t rgb_function, GrCombineFactor_t rgb_factor, GrCombineFunction_t alpha_function, GrCombineFactor_t alpha_factor, FxBool rgb_invert, FxBool alpha_invert)
+#define _grTexCombineFunction8 79 // void grTexCombineFunction(GrChipID_t tmu, GrTextureCombineFnc_t fnc)
+#define _grTexDetailControl16 80 // void grTexDetailControl(GrChipID_t tmu, int lodBias, FxU8 detailScale, float detailMax)
+#define _grTexDownloadMipMap16 81 // void grTexDownloadMipMap(GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+#define _grTexDownloadMipMapLevel32 82 // void grTexDownloadMipMapLevel(GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data)
+#define _grTexDownloadMipMapLevelPartial40 83 // void grTexDownloadMipMapLevelPartial(GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data, int start, int end)
+#define _grTexDownloadTable12 84 // void grTexDownloadTable(GrChipID_t tmu, GrTexTable_t type, void *data)
+#define _grTexDownloadTablePartial20 85 // void grTexDownloadTablePartial(GrChipID_t tmu, GrTexTable_t type, void *data, int start, int end)
+#define _grTexFilterMode12 86 // void grTexFilterMode(GrChipID_t tmu, GrTextureFilterMode_t minFilterMode, GrTextureFilterMode_t magFilterMode)
+#define _grTexLodBiasValue8 87 // void grTexLodBiasValue(GrChipID_t tmu, float bias)
+#define _grTexMaxAddress4 88 // FxU32 grTexMaxAddress(GrChipID_t tmu)
+#define _grTexMinAddress4 89 // FxU32 grTexMinAddress(GrChipID_t tmu)
+#define _grTexMipMapMode12 90 // void grTexMipMapMode(GrChipID_t tmu, GrMipMapMode_t mode, FxBool lodBlend)
+#define _grTexMultibase8 91 // void grTexMultibase(GrChipID_t tmu, FxBool enable)
+#define _grTexMultibaseAddress20 92 // void grTexMultibaseAddress(GrChipID_t tmu, GrTexBaseRange_t range, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+#define _grTexNCCTable8 93 // void grTexNCCTable(GrChipID_t tmu, GrNCCTable_t table)
+#define _grTexSource16 94 // void grTexSource(GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+#define _grTexTextureMemRequired8 95 // FxU32 grTexTextureMemRequired(FxU32 evenOdd, GrTexInfo *info)
+#define _grTriStats8 96 // void grTriStats(FxU32 *trisProcessed, FxU32 *trisDrawn)
+#define _gu3dfGetInfo8 97 // FxBool gu3dfGetInfo(const char *filename, Gu3dfInfo *info)
+#define _gu3dfLoad8 98 // FxBool gu3dfLoad(const char *filename, Gu3dfInfo *info)
+#define _guAADrawTriangleWithClip12 99 // void guAADrawTriangleWithClip(const GrVertex *va, const GrVertex *vb, const GrVertex *vc)
+#define _guAlphaSource4 100 // void guAlphaSource(GrAlphaSource_t mode)
+#define _guColorCombineFunction4 101 // void guColorCombineFunction(GrColorCombineFnc_t func)
+#define _guDrawPolygonVertexListWithClip8 102 // void guDrawPolygonVertexListWithClip(int nverts, const GrVertex vlist[])
+#define _guDrawTriangleWithClip12 103 // void guDrawTriangleWithClip(const GrVertex *va, const GrVertex *vb, const GrVertex *vc)
+#define _guEncodeRLE1616 104 //
+#define _guEndianSwapBytes4 105 //
+#define _guEndianSwapWords4 106 //
+#define _guFogGenerateExp28 107 // void guFogGenerateExp2(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density)
+#define _guFogGenerateExp8 108 // void guFogGenerateExp(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density)
+#define _guFogGenerateLinear12 109 // void guFogGenerateLinear(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float nearW, float farW)
+#define _guFogTableIndexToW4 110 // float guFogTableIndexToW(int i)
+#define _guMPDrawTriangle12 111 //
+#define _guMPInit0 112 //
+#define _guMPTexCombineFunction4 113 //
+#define _guMPTexSource8 114 //
+#define _guMovieSetName4 115 //
+#define _guMovieStart0 116 //
+#define _guMovieStop0 117 //
+#define _guTexAllocateMemory60 118 // GrMipMapId_t guTexAllocateMemory(GrChipID_t tmu, FxU8 evenOddMask, int width, int height, GrTextureFormat_t format, GrMipMapMode_t mmMode, GrLOD_t smallLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureClampMode_t sClampMode, GrTextureClampMode_t tClampMode, GrTextureFilterMode_t minFilterMode, GrTextureFilterMode_t magFilterMode, float lodBias, FxBool lodBlend)
+#define _guTexChangeAttributes48 119 // FxBool guTexChangeAttributes(GrMipMapID_t mmid, int width, int height, GrTextureFormat_t format, GrMipMapMode_t mmMode, GrLOD_t smallLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureClampMode_t sClampMode, GrTextureClampMode_t tClampMode, GrTextureFilterMode_t minFilterMode, GrTextureFilterMode_t magFilterMode)
+#define _guTexCombineFunction8 120 // void guTexCombineFunction(GrChipID_t tmu, GrTextureCombineFnc_t func)
+#define _guTexCreateColorMipMap0 121 //
+#define _guTexDownloadMipMap12 122 // void guTexDownloadMipMap(GrMipMapId_t mmid, const void *src, const GuNccTable *nccTable)
+#define _guTexDownloadMipMapLevel12 123 // void guTexDownloadMipMapLevel(GrMipMapId_t mmid, GrLOD_t lod, const void **src)
+#define _guTexGetCurrentMipMap4 124 // GrMipMapId_t guTexGetCurrentMipMap (GrChipID_t tmu)
+#define _guTexGetMipMapInfo4 125 // GrMipMapInfo *guTexGetMipMapInfo(GrMipMapId_t mmid)
+#define _guTexMemQueryAvail4 126 // FxU32 guTexMemQueryAvail(GrChipID_t tmu)
+#define _guTexMemReset0 127 // void guTexMemReset(void)
+#define _guTexSource4 128 // void guTexSource(GrMipMapId_t mmid)
+#define _ConvertAndDownloadRle64 129 // void ConvertAndDownloadRle(GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, FxU8 *bm_data, long bm_h, FxU32 u0, FxU32 v0, FxU32 width, FxU32 height, FxU32 dest_width, FxU32 dest_height, FxU16 *tlut)
+#define GLIDE_MAX 129
+
+#endif // __3DFX_H__
+
+#endif // GLIDEDEF_H
diff --git a/include/mem.h b/include/mem.h
--- a/include/mem.h
+++ b/include/mem.h
@@ -152,6 +152,8 @@ static INLINE Bit32u phys_readd(PhysPt addr){
void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size);
void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
+void MEM_BlockWrite32(PhysPt pt,void * data,Bitu size);
+void MEM_BlockRead32(PhysPt pt,void * data,Bitu size);
void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
void MEM_StrCopy(PhysPt pt,char * data,Bitu size);
diff --git a/src/dosbox.cpp b/src/dosbox.cpp
--- a/src/dosbox.cpp
+++ b/src/dosbox.cpp
@@ -81,6 +81,7 @@ void PCI_Init(Section*);
void KEYBOARD_Init(Section*); //TODO This should setup INT 16 too but ok ;)
void JOYSTICK_Init(Section*);
+void GLIDE_Init(Section*);
void MOUSE_Init(Section*);
void SBLASTER_Init(Section*);
void GUS_Init(Section*);
@@ -666,6 +667,17 @@ void DOSBOX_Init(void) {
Pmulti_remain->Set_help("see serial1");
+ secprop=control->AddSection_prop("glide",&GLIDE_Init,true);
+ Pbool = secprop->Add_bool("glide",Property::Changeable::WhenIdle,false);
+ Pbool->Set_help("Enable glide emulation: true,false.");
+ //Phex = secprop->Add_hex("grport",Property::Changeable::WhenIdle,0x600);
+ //Phex->Set_help("I/O port to use for host communication.");
+ Pstring = secprop->Add_string("lfb",Property::Changeable::WhenIdle,"full_noaux");
+ Pstring->Set_help("LFB access: full,full_noaux,read,read_noaux,write,write_noaux,none.\n"
+ "OpenGlide does not support locking aux buffer, please use _noaux modes.");
+ Pbool = secprop->Add_bool("splash",Property::Changeable::WhenIdle,true);
+ Pbool->Set_help("Show 3dfx splash screen (requires 3dfxSpl2.dll).");
+
/* All the DOS Related stuff, which will eventually start up in the shell */
secprop=control->AddSection_prop("dos",&DOS_Init,false);//done
secprop->AddInitFunction(&XMS_Init,true);//done
diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp
--- a/src/gui/sdlmain.cpp
+++ b/src/gui/sdlmain.cpp
@@ -49,6 +49,7 @@
#include "cpu.h"
#include "cross.h"
#include "control.h"
+#include "glidedef.h"
#define MAPPERFILE "mapper-" VERSION ".map"
//#define DISABLE_JOYSTICK
@@ -380,6 +381,10 @@ check_gotbpp:
void GFX_ResetScreen(void) {
+ if(glide.enabled) {
+ GLIDE_ResetScreen(true);
+ return;
+ }
GFX_Stop();
if (sdl.draw.callback)
(sdl.draw.callback)( GFX_CallBackReset );
@@ -780,7 +785,10 @@ void GFX_SwitchFullScreen(void) {
sticky_keys(true); //restore sticky keys to default state in windowed mode.
#endif
}
- GFX_ResetScreen();
+ if (glide.enabled)
+ GLIDE_ResetScreen();
+ else
+ GFX_ResetScreen();
}
static void SwitchFullScreen(bool pressed) {
@@ -1519,7 +1527,7 @@ void GFX_Events() {
throw(0);
break;
case SDL_VIDEOEXPOSE:
- if (sdl.draw.callback) sdl.draw.callback( GFX_CallBackRedraw );
+ if ((sdl.draw.callback) && (!glide.enabled)) sdl.draw.callback( GFX_CallBackRedraw );
break;
#ifdef WIN32
case SDL_KEYDOWN:
@@ -1936,6 +1944,7 @@ int main(int argc, char* argv[]) {
if (strcmp(sdl_drv_name,"windib")==0) LOG_MSG("SDL_Init: Starting up with SDL windib video driver.\n Try to update your video card and directx drivers!");
}
#endif
+ glide.fullscreen = &sdl.desktop.fullscreen;
sdl.num_joysticks=SDL_NumJoysticks();
/* Parse configuration files */
diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am
--- a/src/hardware/Makefile.am
+++ b/src/hardware/Makefile.am
@@ -10,6 +10,6 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler
memory.cpp mixer.cpp pcspeaker.cpp pci_bus.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \
- cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp dbopl.cpp
+ cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp dbopl.cpp glide.cpp
diff --git a/src/hardware/glide.cpp b/src/hardware/glide.cpp
new file mode 100644
--- /dev/null
+++ b/src/hardware/glide.cpp
@@ -0,0 +1,1962 @@
+/*
+ * Copyright (C) 2002-2013 The DOSBox Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "dosbox.h"
+#include "inout.h"
+#include "mem.h"
+#include "paging.h"
+#include "glide.h"
+#include "setup.h"
+#include "vga.h"
+#include "dos_inc.h" /* for Drives[] */
+#include "control.h"
+#include "../dos/drives.h"
+
+#include <iomanip>
+#include <sstream>
+using namespace std;
+
+#include "SDL.h"
+
+#if defined (WIN32)
+#include "SDL_syswm.h"
+#include <windows.h>
+#include <Shlwapi.h>
+
+#ifdef _MSC_VER
+#pragma comment( lib, "Shlwapi" )
+#endif
+
+#else // *nix
+#include <dlfcn.h>
+
+#include <dirent.h>
+#include <errno.h>
+
+#endif
+
+extern void GFX_Stop(void);
+extern void GFX_ResetScreen(void);
+extern const char* RunningProgram;
+
+static float int_to_float(const Bit32u i)
+{
+ float f;
+ Bit32u i_native = SDL_SwapLE32(i);
+ SDL_memcpy(&f, &i_native, 4);
+ return f;
+}
+
+#define SAFE_DELETE(p) { if(p) { delete p; p = NULL; } }
+
+#define G_OK 1
+#define G_FAIL 0
+
+// Print debug messages
+#define LOG_GLIDE 0
+
+void VFILE_Remove(const char *name);
+static void process_msg(Bitu);
+
+/** Global Variables **/
+GLIDE_Block glide;
+
+// Pointers to loaded routines
+static FncPointers FP;
+static void ** fn_pt=NULL;
+
+// Shared memory
+static Bit32u param[20];
+
+// Pointer to return value
+static PhysPt ret;
+static Bit16u ret_value;
+
+// Temporary texture buffer
+static Bit32u texsize=0;
+static void* texmem=NULL;
+
+static HostPt hwnd=NULL;
+static char lfbacc=0;
+
+// Tomb Rider shadow hack
+static Bit8u tomb = 0;
+static FxI32 GrOriginLocation = 0;
+
+#if defined (WIN32)
+static HINSTANCE hdll=NULL; // Handle to glide2x lib file
+#else
+static void * hdll=NULL;
+#endif
+
+#if LOG_GLIDE
+static int GLIDE_count[GLIDE_MAX+2];
+#endif
+
+static Bitu read_gl(Bitu port,Bitu iolen)
+{
+ Bitu r=ret_value;
+#if LOG_GLIDE
+ if(ret_value == G_OK)
+ LOG_MSG("Glide:Port read. Return address: 0x%x, value: %d", ret, mem_readd(ret));
+ else if(ret_value == G_FAIL)
+ LOG_MSG("Glide:Port read. Return address: 0x%x, value: %d. Writing G_FAIL to port", ret, mem_readd(ret));
+ else
+ LOG_MSG("Glide:Port read. Returning %hu", ret_value);
+#endif
+
+ ret_value = ret_value >> 8;
+
+ return r;
+}
+
+static void write_gl(Bitu port,Bitu val,Bitu iolen)
+{
+ static Bit16u glsegment = 0;
+
+ ret = 0;
+ ret_value = G_FAIL;
+ FP.grFunction0 = NULL;
+
+ // Allocate shared memory (80 bytes)
+ if(val > GLIDE_MAX) {
+ if(glsegment==0) {
+ glsegment=DOS_GetMemory(5);
+#if LOG_GLIDE
+ LOG_MSG("Glide:Memory allocated at 0x%x (segment: %hu)", glsegment<<4, glsegment);
+#endif
+ }
+ ret_value=glsegment;
+ LOG_MSG("Glide:Activated");
+ return;
+ }
+
+ // Process function parameters (80 bytes)
+ MEM_BlockRead32(PhysMake(glsegment,0), param, 80);
+ process_msg(val);
+
+// LOG_MSG("Glide:Function %s executed OK", grTable[val].name);
+}
+
+class GLIDE_PageHandler : public PageHandler {
+private:
+ PhysPt base_addr[GLIDE_BUFFERS]; // GLIDE_LFB physical address
+ PhysPt lin_addr[GLIDE_BUFFERS]; // GLIDE_LFB linear address
+ HostPt lfb_addr[GLIDE_BUFFERS]; // Address offset from base_addr for the readable/writable buffers
+
+ /* Calculate physical address for access */
+ #define LFB_getAddr(addr) (lfb_addr[((addr - base_addr[0])>>12)>>GLIDE_PAGE_BITS]+addr)
+
+public:
+
+ FxU8 locked[GLIDE_BUFFERS];
+
+ GLIDE_PageHandler(HostPt addr, PhysPt phyaddr = GLIDE_LFB) {
+
+ if(addr == NULL) {
+ LOG_MSG("Glide:NULL address passed to pagehandler!");
+ }
+
+ /* Set base addresses */
+ for(int i = 0; i < GLIDE_BUFFERS; i++) {
+ locked[i] = 0;
+ base_addr[i] = phyaddr;
+ phyaddr += ((1<<GLIDE_PAGE_BITS)<<12);
+
+ /* store offset from base address */
+ lfb_addr[i] = (addr == NULL) ? NULL : (addr - base_addr[i]);
+ }
+
+ flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE;
+ PAGING_UnlinkPages(base_addr[0]>>12, GLIDE_PAGES);
+#if LOG_GLIDE
+ LOG_MSG("Glide:GLIDE_PageHandler installed at 0x%x", base_addr[0]);
+#endif
+ }
+
+ ~GLIDE_PageHandler() {
+#if LOG_GLIDE
+ LOG_MSG("Glide:Resetting page handler at 0x%x", base_addr[0]);
+#endif
+ PAGING_UnlinkPages(base_addr[0]>>12, GLIDE_PAGES);
+ }
+
+ void SetLFBAddr(HostPt addr, Bitu buffer) {
+ if(buffer >= GLIDE_BUFFERS) return;
+
+ addr = addr - base_addr[buffer]; /* Calculate offset for current buffer */
+
+ if(addr != lfb_addr[buffer]) {
+ lfb_addr[buffer] = addr;
+#if LOG_GLIDE
+ LOG_MSG("Glide:LFB for buffer %d offset set to 0x%p (addr: 0x%p), clear TLB", buffer, lfb_addr[buffer], addr+base_addr[buffer]);
+#endif
+ PAGING_UnlinkPages(base_addr[buffer]>>12, 1<<GLIDE_PAGE_BITS);
+ }
+ }
+
+ PhysPt GetPhysPt(Bitu buffer = 0) {
+ if(buffer >= GLIDE_BUFFERS) return base_addr[0];
+ return base_addr[buffer];
+ }
+
+ void SetLinPt(PhysPt linaddr) {
+ for(int i = 0; i < GLIDE_BUFFERS; i++) {
+ lin_addr[i] = linaddr;
+ linaddr += ((1<<GLIDE_PAGE_BITS)<<12);
+ }
+ }
+
+ PhysPt GetLinPt(Bitu buffer = 0) {
+ if(buffer >= GLIDE_BUFFERS) return lin_addr[0];
+ return lin_addr[buffer];
+ }
+
+ Bitu readb(PhysPt addr) {
+// LOG_MSG("Glide:Read from 0x%p", LFB_getAddr(addr));
+ return *(Bit8u *)(LFB_getAddr(addr));
+ }
+
+ Bitu readw(PhysPt addr) {
+// LOG_MSG("Glide:Read from 0x%p", LFB_getAddr(addr));
+ return *(Bit16u *)(LFB_getAddr(addr));
+ }
+
+ Bitu readd(PhysPt addr) {
+// LOG_MSG("Glide:Read from 0x%p", LFB_getAddr(addr));
+ return *(Bit32u *)(LFB_getAddr(addr));
+ }
+
+ void writeb(PhysPt addr,Bitu val) {
+// LOG_MSG("Glide:Write to 0x%p", LFB_getAddr(addr));
+ *(Bit8u *)(LFB_getAddr(addr))=(Bit8u)val;
+ }
+
+ void writew(PhysPt addr,Bitu val) {
+// LOG_MSG("Glide:Write to 0x%p", LFB_getAddr(addr));
+ *(Bit16u *)(LFB_getAddr(addr))=(Bit16u)val;
+ }
+
+ void writed(PhysPt addr,Bitu val) {
+// LOG_MSG("Glide:Write to 0x%p", LFB_getAddr(addr));
+ *(Bit32u *)(LFB_getAddr(addr))=(Bit32u)val;
+ }
+
+ HostPt GetHostReadPt(Bitu phys_page) {
+ Bitu buffer = (((phys_page<<12) - base_addr[0])>>12)>>GLIDE_PAGE_BITS;
+#if LOG_GLIDE
+ // This only makes sense if full lfb access is used...
+ if (!locked[buffer]) LOG_MSG("Glide:Read from unlocked LFB at: 0x%x", phys_page<<12);
+#endif
+// LOG_MSG("Glide:GetHostReadPt called with %d, returning 0x%p", phys_page, LFB_getAddr((phys_page*MEM_PAGESIZE)));
+ return lfb_addr[buffer]+(phys_page<<12);
+ }
+
+ HostPt GetHostWritePt(Bitu phys_page) {
+ Bitu buffer = (((phys_page<<12) - base_addr[0])>>12)>>GLIDE_PAGE_BITS;
+#if LOG_GLIDE
+ // This only makes sense if full lfb access is used...
+ if (!locked[buffer]) LOG_MSG("Glide:Write to unlocked LFB at: 0x%x", phys_page<<12);
+#endif
+// LOG_MSG("Glide:GetHostWritePt called with %d, returning 0x%p", phys_page, LFB_getAddr((phys_page*MEM_PAGESIZE)));
+ return lfb_addr[buffer]+(phys_page<<12);
+ }
+
+ #undef LFB_getAddr
+};
+
+class GLIDE: public Module_base {
+private:
+ AutoexecObject autoexecline;
+ // Glide port
+ Bitu glide_base;
+ Bit8u *ovl_data;
+public:
+ GLIDE(Section* configuration):Module_base(configuration),glide_base(0),ovl_data(NULL) {
+ Section_prop * section=static_cast<Section_prop *>(configuration);
+
+ if(!section->Get_bool("glide")) return;
+ std::string str = section->Get_string("lfb");
+ lowcase(str);
+ if(str == "none") {
+ LOG_MSG("Glide:Disabled LFB access");
+ lfbacc=0;
+ } else if(str == "read_noaux") {
+ LOG_MSG("Glide:LFB access: read-only (no aux)");
+ lfbacc=1;
+ } else if(str == "write_noaux") {
+ LOG_MSG("Glide:LFB access: write-only (no aux)");
+ lfbacc=2;
+ } else if(str == "full_noaux") {
+ LOG_MSG("Glide:LFB access: read-write (no aux)");
+ lfbacc=3;
+ } else if(str == "read") {
+ LOG_MSG("Glide:LFB access: read-only");
+ lfbacc=5;
+ } else if(str == "write") {
+ LOG_MSG("Glide:LFB access: write-only");
+ lfbacc=6;
+ } else {
+ LOG_MSG("Glide:LFB access: read-write");
+ lfbacc=7;
+ }
+
+ // Load glide2x.dll
+#if defined(WIN32)
+ hdll = LoadLibrary("glide2x.dll");
+#elif defined(MACOSX)
+ hdll = dlopen("libglide2x.dylib", RTLD_NOW);
+#else
+ hdll = dlopen("libglide2x.so", RTLD_NOW);
+#endif
+
+ if(!hdll) {
+ LOG_MSG("Glide:Unable to load glide2x library, glide emulation disabled");
+ return;
+ }
+
+ // Allocate some temporary space
+ texmem = (void*)malloc(1600*1200*4);
+ if(texmem == NULL) {
+ LOG_MSG("Glide:Unable to allocate texture memory, glide disabled");
+ return;
+ }
+
+ glide.lfb_pagehandler = new GLIDE_PageHandler((HostPt)texmem);
+ if(!glide.lfb_pagehandler) {
+ LOG_MSG("Glide:Failed to install page handler, glide disabled!");
+ free(texmem); texmem = NULL;
+ return;
+ }
+
+ // Load glide2x.ovl if possible, so it is available on the Z: drive
+ const char ovl_name[] = "glide2x.ovl";
+
+#if defined (WIN32)
+ // Windows is simple, the search is case insensitive
+ FILE * ovl = fopen(ovl_name, "rb");
+
+ // if not successful try to specifically search dosbox directory
+ if (ovl == NULL) {
+ char * path = (char*)texmem;
+ GetModuleFileName(NULL, path, 32768);
+ // strip "\dosbox.exe" from path
+ PathRemoveFileSpec(path);
+ strcat(path, "\\"); strcat(path, ovl_name);
+ ovl = fopen(path, "rb");
+ }
+
+#else
+ // Try a bit harder in *nix, perform case insensitive search and check /usr/share/dosbox as well
+ DIR * pdir; struct dirent * pfile;
+ char * path = (char*)texmem;
+ FILE * ovl = NULL;
+
+ const char * const dirname[] = { "./", "/usr/share/dosbox/", NULL };
+
+ for (int i = 0; dirname[i]; i++) {
+ if((pdir = opendir(dirname[i]))) {
+ while(pfile = readdir(pdir)) {
+ if(!strcasecmp(pfile->d_name, ovl_name)) {
+ strcpy(path, dirname[i]); strcat(path, pfile->d_name);
+ ovl = fopen(path, "rb");
+ if(ovl) break;
+ }
+ }
+ closedir(pdir);
+ if(ovl) break;
+ }
+ }
+#endif
+
+ long ovl_size = 0;
+
+ if(ovl == NULL) {
+ LOG_MSG("Glide:GLIDE2X.OVL could not be found, make sure correct (compatible) version is in the game directory!");
+ } else {
+ fseek(ovl, 0, SEEK_END);
+ ovl_size=ftell(ovl);
+ ovl_data=(Bit8u*)malloc(ovl_size);
+ fseek(ovl, 0, SEEK_SET);
+ fread(ovl_data, sizeof(char), ovl_size, ovl);
+ fclose(ovl);
+ }
+
+#if LOG_GLIDE
+ SDL_memset(GLIDE_count, 0, sizeof(GLIDE_count));
+#endif
+
+ // Allocate memory for dll pointers
+ fn_pt = (void**)malloc(sizeof(void*)*(GLIDE_MAX+1));
+ if(fn_pt == NULL) {
+ LOG_MSG("Glide:Unable to allocate memory, glide disabled");
+ free(texmem); texmem = NULL;
+ if(ovl_data) free(ovl_data); ovl_data = NULL;
+ return;
+ }
+
+ for(int i=0; i<(GLIDE_MAX+1); i++) {
+#if defined(WIN32)
+ ostringstream temp;
+ // Add function decoration
+ temp << "_" << grTable[i].name << "@" << (Bitu)grTable[i].parms;
+ fn_pt[i] = (void*)(GetProcAddress(hdll, temp.str().c_str()));
+#else
+ fn_pt[i] = (void*)(dlsym(hdll, grTable[i].name));
+#endif
+#if LOG_GLIDE
+ if(fn_pt[i] == NULL) {
+ LOG_MSG("Glide:Warning, unable to load %s from glide2x", grTable[i].name);
+ }
+#endif
+ }
+
+ //glide_base=section->Get_hex("grport");
+ glide_base=0x600; // Anybody else got a better idea?
+
+ IO_RegisterReadHandler(glide_base,read_gl,IO_MB);
+ IO_RegisterWriteHandler(glide_base,write_gl,IO_MB);
+
+ ostringstream temp;
+ temp << "SET GLIDE=" << hex << glide_base << ends;
+
+ autoexecline.Install(temp.str());
+ glide.splash = section->Get_bool("splash");
+
+#if defined (WIN32)
+ // Get hwnd information
+ SDL_SysWMinfo wmi;
+ SDL_VERSION(&wmi.version);
+ if(SDL_GetWMInfo(&wmi)) {
+ hwnd = (HostPt)wmi.window;
+ } else {
+ LOG_MSG("SDL:Error retrieving window information");
+ }
+#endif
+
+ if(ovl_data) {
+ VFILE_Register("GLIDE2X.OVL", ovl_data, ovl_size);
+ }
+ }
+
+ ~GLIDE() {
+ if(glide.enabled) {
+ // void grGlideShutdown(void)
+ FP.grFunction0 = (pfunc0)fn_pt[_grGlideShutdown0];
+ if(FP.grFunction0) FP.grFunction0();
+ glide.enabled = false;
+ }
+
+ SAFE_DELETE(glide.lfb_pagehandler);
+ if(fn_pt)
+ free(fn_pt); fn_pt = NULL;
+ if(texmem)
+ free(texmem); texmem = NULL;
+
+ if(glide_base) {
+ IO_FreeReadHandler(glide_base,IO_MB);
+ IO_FreeWriteHandler(glide_base,IO_MB);
+ }
+
+ if(hdll) {
+#if defined (WIN32)
+ FreeLibrary(hdll);
+#else
+ dlclose(hdll);
+#endif
+ hdll = NULL;
+ }
+
+ VFILE_Remove("GLIDE2X.OVL");
+ if(ovl_data) free(ovl_data);
+ }
+};
+
+static GLIDE* test;
+void GLIDE_ShutDown(Section* sec) {
+ delete test;
+}
+
+void GLIDE_Init(Section* sec) {
+ test = new GLIDE(sec);
+ sec->AddDestroyFunction(&GLIDE_ShutDown,true);
+}
+
+void GLIDE_ResetScreen(bool update)
+{
+#if LOG_GLIDE
+ LOG_MSG("Glide:ResetScreen");
+#endif
+ VGA_SetOverride(true);
+ GFX_Stop();
+
+ // OpenGlide will resize the window on it's own (using SDL)
+ if(glide.width && (
+#ifdef WIN32
+ // dgVoodoo needs a little help :)
+ // Most other wrappers render fullscreen by default
+ (GetProcAddress(hdll, "DispatchDosNT") != NULL) ||
+#endif
+ // and resize when mapper and/or GUI finish
+ update)) {
+ SDL_SetVideoMode(glide.width,glide.height,0,
+ (glide.fullscreen[0]?SDL_FULLSCREEN:0)|SDL_ANYFORMAT|SDL_SWSURFACE);
+ }
+}
+
+void GLIDE_DisableScreen(void)
+{
+ glide.enabled = false; /* if not disabled, GFX_ResetScreen() will call GLIDE_ResetScreen() */
+ VGA_SetOverride(false);
+ GFX_ResetScreen();
+}
+
+static bool GetFileName(char * filename)
+{
+ localDrive *ldp;
+ Bit8u drive;
+ char fullname[DOS_PATHLENGTH];
+
+ // Get full path
+ if(!DOS_MakeName(filename,fullname,&drive)) return false;
+
+#if LOG_GLIDE
+ LOG_MSG("Glide:Fullname: %s", fullname);
+#endif
+
+ // Get real system path
+ ldp = dynamic_cast<localDrive*>(Drives[drive]);
+ if(ldp == NULL) return false;
+
+ ldp->GetSystemFilename(filename,fullname);
+#if LOG_GLIDE
+ LOG_MSG("Glide:System path: %s", filename);
+#endif
+ return true;
+}
+
+typedef FxBool (FX_CALL *pfxSplashInit)(FxU32 hWnd, FxU32 screenWidth, FxU32 screenHeight,
+ FxU32 numColBuf, FxU32 numAuxBuf, GrColorFormat_t colorFormat);
+typedef void (FX_CALL *pfxSplash)(float x, float y, float w, float h, FxU32 frameNumber);
+
+static void grSplash(void)
+{
+#ifdef WIN32
+ FxU32 screenWidth = glide.width, screenHeight = glide.height;
+ HINSTANCE dll = LoadLibrary("3dfxSpl2.dll");
+ if(dll == NULL) {
+ return;
+ }
+
+ pfxSplashInit fxSplashInit = (pfxSplashInit)GetProcAddress(dll, "_fxSplashInit@24");
+ pfxSplash fxSplash = (pfxSplash)GetProcAddress(dll, "_fxSplash@20");
+
+ if((fxSplashInit == NULL) || (fxSplash == NULL)) {
+ FreeLibrary(dll);
+ return;
+ }
+
+ if (screenWidth == 0) {
+ screenWidth = 640;
+ screenHeight = 480;
+ }
+
+ fxSplashInit(0, screenWidth, screenHeight, 2, 1, GR_COLORFORMAT_ABGR);
+ fxSplash(0, 0, screenWidth, screenHeight, 0);
+
+ // OpenGlide does not restore this state
+ FP.grFunction1i = (pfunc1i)fn_pt[_grSstOrigin4];
+ if(FP.grFunction1i) {
+ FP.grFunction1i(GrOriginLocation);
+ }
+
+ FreeLibrary(dll);
+#endif
+}
+
+static void process_msg(Bitu value)
+{
+ GrLfbInfo_t lfbinfo;
+ DBGrLfbInfo_t dblfbinfo;
+
+ GrTexInfo texinfo;
+ DBGrTexInfo dbtexinfo;
+
+ Gu3dfInfo guinfo;
+ DBGu3dfInfo dbguinfo;
+
+ GrVertex vertex[3];
+
+ GrMipMapInfo * mipmap;
+
+ // Temporary memory used in functions
+ FxI32 * ilist = (FxI32*)texmem;
+ FxU16 * ptr16 = (FxU16*)texmem;
+
+ // Filename translation
+ char filename[512];
+
+ // Used so that the pagehandler returns the same address after buffer swap
+ static char b_swap = 0;
+
+ // Return value address
+ ret = param[0];
+ Bitu i = value;
+ Bitu buffer;
+ FxU32 j, k;
+
+ if((i > GLIDE_MAX) || (fn_pt[i] == NULL)) {
+ LOG_MSG("Glide:Invalid function pointer for call %s", (i > GLIDE_MAX) ? "(invalid)" : grTable[i].name);
+ return;
+ }
+
+#if LOG_GLIDE
+ LOG_MSG("Glide:Processing call %s (%d), return address: 0x%x", grTable[i].name, value, ret);
+ GLIDE_count[i]++;
+#endif
+
+ switch (value) {
+
+ case _grAADrawLine8:
+ // void grAADrawLine(GrVertex *va, GrVertex *vb)
+ FP.grFunction2p = (pfunc2p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ FP.grFunction2p(&vertex[0], &vertex[1]);
+ break;
+ case _grAADrawPoint4:
+ // void grAADrawPoint(GrVertex *p)
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ FP.grFunction1p(&vertex[0]);
+ break;
+ case _grAADrawPolygon12:
+ // void grAADrawPolygon(int nVerts, const int ilist[], const GrVertex vlist[])
+ FP.grFunction1i2p = (pfunc1i2p)fn_pt[i];
+ i = sizeof(FxI32)*param[1];
+ MEM_BlockRead32(param[2], ilist, i);
+
+ // Find the number of vertices (?)
+ k = 0;
+ for(j = 0; j < param[1]; j++) {
+ if(ilist[j] > k)
+ k = ilist[j];
+ }
+ k++;
+
+ MEM_BlockRead32(param[3], ilist+i, sizeof(GrVertex)*k);
+ FP.grFunction1i2p(param[1], ilist, ilist+i);
+ break;
+ case _grAADrawPolygonVertexList8:
+ // void grAADrawPolygonVertexList(int nVerts, const GrVertex vlist[])
+ FP.grFunction1i1p = (pfunc1i1p)fn_pt[i];
+ MEM_BlockRead32(param[2], texmem, sizeof(GrVertex)*param[1]);
+ FP.grFunction1i1p(param[1], texmem);
+ break;
+ case _grAADrawTriangle24:
+ // void grAADrawTriangle(GrVertex *a, GrVertex *b, GrVertex *c,
+ // FxBool antialiasAB, FxBool antialiasBC, FxBool antialiasCA)
+ FP.grFunction3p3i = (pfunc3p3i)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ MEM_BlockRead32(param[3], &vertex[2], sizeof(GrVertex));
+ FP.grFunction3p3i(&vertex[0], &vertex[1], &vertex[2], param[4], param[5], param[6]);
+ break;
+ case _grAlphaBlendFunction16:
+ // void grAlphaBlendFunction(GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df,
+ // GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df)
+ if(tomb == 1) {
+ if((FP.grFunction1i = (pfunc1i)fn_pt[_grConstantColorValue4]))
+ FP.grFunction1i(0x7f000000);
+ } else if(tomb == 2) {
+ float color1 = 127.0;
+ float color2 = 0.0;
+ if((FP.grFunction4f = (pfunc4f)fn_pt[_grConstantColorValue416]))
+ FP.grFunction4f(color1, color2, color2, color2);
+ }
+ FP.grFunction4i = (pfunc4i)fn_pt[i];
+ FP.grFunction4i(param[1], param[2], param[3], param[4]);
+ break;
+ case _grAlphaCombine20:
+ // void grAlphaCombine(GrCombineFunction_t func, GrCombineFactor_t factor,
+ // GrCombineLocal_t local, GrCombineOther_t other, FxBool invert)
+ FP.grFunction5i = (pfunc5i)fn_pt[i];
+ FP.grFunction5i(param[1], param[2], param[3], param[4], param[5]);
+ break;
+ case _grAlphaControlsITRGBLighting4:
+ // void grAlphaControlsITRGBLighting(FxBool enable)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grAlphaTestFunction4:
+ // void grAlphaTestFunction(GrCmpFnc_t function)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grAlphaTestReferenceValue4:
+ // void grAlphaTestReferenceValue(GrAlpha_t value)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grBufferClear12:
+ // void grBufferClear(GrColor_t color, GrAlpha_t alpha, FxU16 depth)
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i(param[1], param[2], param[3]);
+ break;
+ case _grBufferNumPending0:
+ // int grBufferNumPending(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grBufferSwap4:
+ // void grBufferSwap(int swap_interval)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ /* Breaks Extreme Assault (which always writes to same address ?) */
+ //if(!(glide.lfb_pagehandler->locked[0] || glide.lfb_pagehandler->locked[1])) b_swap = !b_swap;
+#if LOG_GLIDE
+ LOG_MSG("Glide:BufferSwap (0x%x)", b_swap);
+#endif
+ break;
+ case _grCheckForRoom4:
+ // void grCheckForRoom(FxI32 n)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grChromakeyMode4:
+ // void grChromakeyMode(GrChromakeyMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grChromakeyValue4:
+ // void grChromakeyValue(GrColor_t value)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grClipWindow16:
+ // void grClipWindow(FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy)
+ FP.grFunction4i = (pfunc4i)fn_pt[i];
+ FP.grFunction4i(param[1], param[2], param[3], param[4]);
+ break;
+ case _grColorCombine20:
+ // void grColorCombine(GrCombineFunction_t func, GrCombineFactor_t factor,
+ // GrCombineLocal_t local, GrCombineOther_t other, FxBool invert)
+ FP.grFunction5i = (pfunc5i)fn_pt[i];
+ FP.grFunction5i(param[1], param[2], param[3], param[4], param[5]);
+ break;
+ case _grColorMask8:
+ // void grColorMask(FxBool rgb, FxBool alpha)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+ case _grConstantColorValue416:
+ // void grConstantColorValue4(float a, float r, float g, float b)
+ FP.grFunction4f = (pfunc4f)fn_pt[i];
+ FP.grFunction4f(int_to_float(param[1]), int_to_float(param[2]), int_to_float(param[3]), int_to_float(param[4]));
+ break;
+ case _grConstantColorValue4:
+ // void grConstantColorValue(GrColor_t color)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grCullMode4:
+ // void grCullMode(GrCullMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDepthBiasLevel4:
+ // void grDepthBiasLevel(FxI16 level)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDepthBufferFunction4:
+ // void grDepthBufferFunction(GrCmpFnc_t func)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDepthBufferMode4:
+ // void grDepthBufferMode(GrDepthBufferMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDepthMask4:
+ // void grDepthMask(FxBool enable)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDisableAllEffects0:
+ // void grDisableAllEffects(void)
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _grDitherMode4:
+ // void grDitherMode(GrDitherMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grDrawLine8:
+ // void grDrawLine(const GrVertex *a, const GrVertex *b)
+ FP.grFunction2p = (pfunc2p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ FP.grFunction2p(&vertex[0], &vertex[1]);
+ break;
+ case _grDrawPlanarPolygon12:
+ // void grDrawPlanarPolygon(int nVerts, int ilist[], const GrVertex vlist[])
+ FP.grFunction1i2p = (pfunc1i2p)fn_pt[i];
+ i = sizeof(FxI32)*param[1];
+ MEM_BlockRead32(param[2], ilist, i);
+
+ // Find the number of vertices (?)
+ k = 0;
+ for(j = 0; j < param[1]; j++) {
+ if(ilist[j] > k)
+ k = ilist[j];
+ }
+ k++;
+
+ MEM_BlockRead32(param[3], ilist+i, sizeof(GrVertex)*k);
+ FP.grFunction1i2p(param[1], ilist, ilist+i);
+ break;
+ case _grDrawPlanarPolygonVertexList8:
+ // void grDrawPlanarPolygonVertexList(int nVertices, const GrVertex vlist[])
+ FP.grFunction1i1p = (pfunc1i1p)fn_pt[i];
+ MEM_BlockRead32(param[2], texmem, sizeof(GrVertex)*param[1]);
+ FP.grFunction1i1p(param[1], texmem);
+ break;
+ case _grDrawPoint4:
+ // void grDrawPoint(const GrVertex *a)
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ FP.grFunction1p(&vertex[0]);
+ break;
+ case _grDrawPolygon12:
+ // void grDrawPolygon(int nVerts, int ilist[], const GrVertex vlist[])
+ FP.grFunction1i2p = (pfunc1i2p)fn_pt[i];
+ i = sizeof(FxI32)*param[1];
+ MEM_BlockRead32(param[2], ilist, i);
+
+ // Find the number of vertices (?)
+ k = 0;
+ for(j = 0; j < param[1]; j++) {
+ if(ilist[j] > k)
+ k = ilist[j];
+ }
+ k++;
+
+ MEM_BlockRead32(param[3], ilist+i, sizeof(GrVertex)*k);
+ FP.grFunction1i2p(param[1], ilist, ilist+i);
+ break;
+ case _grDrawPolygonVertexList8:
+ // void grDrawPolygonVertexList(int nVerts, const GrVertex vlist[])
+ FP.grFunction1i1p = (pfunc1i1p)fn_pt[i];
+ MEM_BlockRead32(param[2], texmem, sizeof(GrVertex)*param[1]);
+ FP.grFunction1i1p(param[1], texmem);
+ break;
+ case _grDrawTriangle12:
+ // void grDrawTriangle(const GrVertex *a, const GrVertex *b, const GrVertex *c)
+ FP.grFunction3p = (pfunc3p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ MEM_BlockRead32(param[3], &vertex[2], sizeof(GrVertex));
+ FP.grFunction3p(&vertex[0], &vertex[1], &vertex[2]);
+ break;
+/*
+ case _grErrorSetCallback4:
+ // void grErrorSetCallback(void (*function)(const char *string, FxBool fatal))
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(*param[1]);
+ break;
+*/
+ case _grFogColorValue4:
+ // void grFogColorValue(GrColor_t value)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grFogMode4:
+ // void grFogMode(GrFogMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grFogTable4:
+ // void grFogTable(const GrFog_t grTable[GR_FOG_TABLE_SIZE])
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrFog_t)*GR_FOG_TABLE_SIZE);
+ FP.grFunction1p(texmem);
+ break;
+ case _grGammaCorrectionValue4:
+ // void grGammaCorrectionValue(float value)
+ FP.grFunction1f = (pfunc1f)fn_pt[i];
+ FP.grFunction1f(int_to_float(param[1]));
+ break;
+ case _grGlideGetState4:
+ // void grGlideGetState(GrState *state)
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrState));
+ FP.grFunction1p(texmem);
+ MEM_BlockWrite32(param[1], texmem, sizeof(GrState));
+ break;
+ case _grGlideGetVersion4:
+ // void grGlideGetVersion(char version[80])
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ FP.grFunction1p(filename);
+ k = 0;
+ do {
+ mem_writeb(param[1]++, filename[k++]);
+ } while(filename[k] != '\0');
+ mem_writeb(param[1], '\0');
+ break;
+ case _grGlideInit0:
+ // void grGlideInit(void)
+ if(glide.enabled) break; /* Tie Break Tennis */
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+
+ // Enable Tomb Rider displaying shadow
+ if(!strncasecmp(RunningProgram, "Tombub", 6)) tomb = 2;
+ else if(!strncasecmp(RunningProgram, "Tomb", 4)) tomb = 1;
+ else tomb = 0;
+
+ // Send LFB to the OVL (so it can map it in linear address)
+ if(mem_readd(param[1]) == 0xFFFFF1FB) { // Find LFB magic
+ mem_writed(param[1], glide.lfb_pagehandler->GetPhysPt());
+ mem_writed(param[2], GLIDE_PAGES);
+ } else {
+ LOG_MSG("Glide:Detected incompatible guest ovl/dll!");
+ }
+ break;
+ case _grGlideSetState4:
+ // void grGlideSetState(const GrState *state)
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrState));
+ FP.grFunction1p(texmem);
+ MEM_BlockWrite32(param[1], texmem, sizeof(GrState));
+ break;
+ case _grGlideShamelessPlug4:
+ // void grGlideShamelessPlug(const FxBool on)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grGlideShutdown0: {
+ // void grGlideShutdown(void)
+ if(glide.enabled) {
+ FP.grFunction0 = (pfunc0)fn_pt[_grSstWinClose0];
+ FP.grFunction0();
+ GLIDE_DisableScreen();
+ }
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+
+ Section_prop *section=static_cast<Section_prop *>(control->GetSection("glide"));
+ if (section) glide.splash = section->Get_bool("splash");
+
+#if LOG_GLIDE
+ for(j=0;j<(GLIDE_MAX+1);j++) {
+ if(GLIDE_count[j]) {
+ LOG_MSG("Glide:%6d calls function %s (%d)", GLIDE_count[j], grTable[j].name, j);
+ }
+ }
+ LOG_MSG("Glide: %d framebuffer locks (%d read, %d write)", GLIDE_count[_grLfbLock24],
+ GLIDE_count[GLIDE_MAX+1], GLIDE_count[_grLfbLock24] - GLIDE_count[GLIDE_MAX+1]);
+ SDL_memset(GLIDE_count, 0, sizeof(GLIDE_count));
+#endif
+ break;
+ }
+ case _grHints8:
+ // void grHints(GrHints_t type, FxU32 hintMask)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+ case _grLfbConstantAlpha4:
+ // void grLfbConstantAlpha(GrAlpha_t alpha)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grLfbConstantDepth4:
+ // void grLfbConstantDepth(FxU16 depth)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grLfbLock24:
+ // FxBool grLfbLock(GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,
+ // GrOriginLocation_t origin, FxBool pixelPipeline, GrLfbInfo_t *info)
+ FP.grRFunction5i1p = (prfunc5i1p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+
+ buffer = (Bitu)param[2];
+ if (buffer >= GLIDE_BUFFERS) {
+ LOG_MSG("Glide:Invalid buffer passed in grLfbLock (%d)", buffer);
+ return;
+ }
+
+ // Buffer address should stay the same after BufferSwap, so check which buffer to lock
+ // (currently disabled, see _grBufferSwap4)
+ //if (buffer < 2) buffer = buffer ^ b_swap;
+
+ // Read parameters
+ MEM_BlockRead32(param[6], &dblfbinfo, sizeof(DBGrLfbInfo_t));
+ lfbinfo.size = sizeof(GrLfbInfo_t);
+ lfbinfo.origin = dblfbinfo.origin;
+ lfbinfo.lfbPtr = texmem;
+
+ k = FXTRUE;
+ j = param[1]&1; j++;
+ j = j&lfbacc; // Check LFB access (j = 0 : fake lock)
+ if((buffer > 1) && (lfbacc < 4)) j = 0; // Disable access to AUX buffers
+
+ if(j) {
+ // Lock the buffer
+ k = FP.grRFunction5i1p(param[1], param[2], param[3], param[4], param[5], &lfbinfo);
+ if(k == FXTRUE) {
+ glide.lfb_pagehandler->locked[buffer]++;
+ dblfbinfo.writeMode = lfbinfo.writeMode;
+ dblfbinfo.strideInBytes = lfbinfo.strideInBytes;
+ dblfbinfo.lfbPtr = glide.lfb_pagehandler->GetLinPt(buffer);
+ MEM_BlockWrite32(param[6], &dblfbinfo, sizeof(DBGrLfbInfo_t));
+ } else {
+ LOG_MSG("Glide:LFB Lock failed!");
+ //k = FXFALSE; // Lock failed ?
+ }
+ } else {
+ // else lock is faked (texmem used for read/write)
+ if(param[3] == GR_LFBWRITEMODE_ANY) dblfbinfo.writeMode = GR_LFBWRITEMODE_565;
+ else dblfbinfo.writeMode = param[3];
+
+ if(param[4] == GR_ORIGIN_ANY) dblfbinfo.origin = GR_ORIGIN_UPPER_LEFT;
+ else dblfbinfo.origin = param[4];
+
+ dblfbinfo.strideInBytes = ((glide.width>0) ? glide.width : 1600) * 4;
+ dblfbinfo.lfbPtr = glide.lfb_pagehandler->GetLinPt(buffer);
+
+ //if(!(param[1]&GR_LFB_WRITE_ONLY)) SDL_memset(texmem, 0, 1600*1200*4); // Clear memory on read-lock
+
+ MEM_BlockWrite32(param[6], &dblfbinfo, sizeof(DBGrLfbInfo_t));
+ }
+
+ // Set LFB address for page handler to read from/write to
+ glide.lfb_pagehandler->SetLFBAddr((HostPt)lfbinfo.lfbPtr, buffer);
+ if(dblfbinfo.strideInBytes > 1600*4) LOG_MSG("Glide:WARNING LFB stride (%d) is larger than max supported: %d!", dblfbinfo.strideInBytes, 1600*4);
+
+ if(param[1]&GR_LFB_WRITE_ONLY) { // Is a write-only lock
+#if LOG_GLIDE
+ LOG_MSG("Glide:W/O lock (%d). %s LFB: 0x%p. Returning 0x%x (stride: %d)", param[2], (j ? "Real" : "Fake"),
+ lfbinfo.lfbPtr, dblfbinfo.lfbPtr, dblfbinfo.strideInBytes);
+#endif
+ } else { // Is a read-only lock
+#if LOG_GLIDE
+ LOG_MSG("Glide:R/O lock (%d). %s LFB: 0x%p. Returning 0x%x (stride: %d)", param[2], (j ? "Real" : "Fake"),
+ lfbinfo.lfbPtr, dblfbinfo.lfbPtr, dblfbinfo.strideInBytes);
+ GLIDE_count[GLIDE_MAX+1]++;
+#endif
+ }
+
+ mem_writed(ret, k);
+ ret_value = G_OK;
+ break;
+ case _grLfbReadRegion28:
+ // FxBool grLfbReadRegion(GrBuffer_t src_buffer, FxU32 src_x, FxU32 src_y, FxU32 src_width,
+ // FxU32 src_height, FxU32 dst_stride, void *dst_data)
+ FP.grRFunction6i1p = (prfunc6i1p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction6i1p(param[1], param[2], param[3], param[4], param[5], param[6], ptr16));
+ MEM_BlockWrite(param[7], ptr16, param[5]*param[6]);
+ ret_value = G_OK;
+ break;
+ case _grLfbUnlock8:
+ // FxBool grLfbUnlock(GrLock_t type, GrBuffer_t buffer)
+ FP.grRFunction2i = (prfunc2i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle (%d)!", _grLfbUnlock8);
+ return;
+ }
+ k = FXTRUE;
+ buffer = param[2];
+ if (buffer < 2) buffer = buffer ^ b_swap;
+#if LOG_GLIDE
+ LOG_MSG("Glide:LFB unlock buffer (%d), %d locks active", param[2], glide.lfb_pagehandler->locked[buffer]);
+#endif
+ if(glide.lfb_pagehandler->locked[buffer]) {
+ k = FP.grRFunction2i(param[1], param[2]);
+ glide.lfb_pagehandler->locked[buffer]--;
+ glide.lfb_pagehandler->SetLFBAddr((HostPt)texmem, buffer); // Reset page handler and clear TLB
+ } else {
+ //k = FXFALSE;
+ }
+ mem_writed(ret, k);
+ ret_value = G_OK;
+ break;
+ case _grLfbWriteColorFormat4:
+ // void grLfbWriteColorFormat(GrColorFormat_t colorFormat)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grLfbWriteColorSwizzle8:
+ // void grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+ case _grLfbWriteRegion32:
+ // FxBool grLfbWriteRegion(GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y,
+ // GrLfbSrcFmt_t src_format, FxU32 src_width, FxU32 src_height, FxU32 src_stride, void *src_data)
+ FP.grRFunction7i1p = (prfunc7i1p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+
+ MEM_BlockRead(param[8], ptr16, param[6]*param[7]);
+ mem_writed(ret, FP.grRFunction7i1p(param[1], param[2], param[3], param[4], param[5], param[6], param[7], ptr16));
+ ret_value = G_OK;
+ break;
+ case _grRenderBuffer4:
+ // void grRenderBuffer(GrBuffer_t buffer)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grResetTriStats0:
+ // void grResetTriStats()
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _grSplash20:
+ // void grSplash(float x, float y, float width, float height, FxU32 frame)
+ FP.grFunction4f1i = (pfunc4f1i)fn_pt[i];
+ FP.grFunction4f1i(int_to_float(param[1]), int_to_float(param[2]), int_to_float(param[3]), int_to_float(param[4]), param[5]);
+ break;
+/*
+ case _grSstConfigPipeline12:
+ //
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i();
+ break;
+*/
+ case _grSstControl4:
+ // FxBool grSstControl(FxU32 code)
+ FP.grRFunction1i = (prfunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1i(param[1]));
+ ret_value = G_OK;
+ break;
+ case _grSstIdle0:
+ // void grSstIdle(void)
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _grSstIsBusy0:
+ // FxBool grSstIsBusy(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grSstOrigin4:
+ // void grSstOrigin(GrOriginLocation_t origin)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ GrOriginLocation = param[1];
+ break;
+ case _grSstPerfStats4:
+ // void grSstPerfStats(GrSstPerfStats_t *pStats)
+ FP.grFunction1p = (pfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrSstPerfStats_t));
+ FP.grFunction1p(texmem);
+ MEM_BlockWrite32(param[1], texmem, sizeof(GrSstPerfStats_t));
+ break;
+ case _grSstQueryBoards4:
+ // FxBool grSstQueryBoards(GrHwConfiguration *hwConfig)
+ FP.grRFunction1p = (prfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrHwConfiguration));
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1p(texmem));
+ MEM_BlockWrite32(param[1], texmem, sizeof(GrHwConfiguration));
+ ret_value = G_OK;
+ break;
+ case _grSstQueryHardware4:
+ // FxBool grSstQueryHardware(GrHwConfiguration *hwConfig)
+ FP.grRFunction1p = (prfunc1p)fn_pt[i];
+ MEM_BlockRead32(param[1], texmem, sizeof(GrHwConfiguration));
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1p(texmem));
+ MEM_BlockWrite32(param[1], texmem, sizeof(GrHwConfiguration));
+ ret_value = G_OK;
+ break;
+ case _grSstResetPerfStats0:
+ // void grSstResetPerfStats(void)
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _grSstScreenHeight0:
+ // FxU32 grSstScreenHeight(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grSstScreenWidth0:
+ // FxU32 grSstScreenWidth(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grSstSelect4:
+ // void grSstSelect(int which_sst)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _grSstStatus0:
+ // FxU32 grSstStatus(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grSstVRetraceOn0:
+ // FxBool grSstVRetraceOn(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+/*
+ case _grSstVidMode8:
+ //
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i();
+ break;
+*/
+ case _grSstVideoLine0:
+ // FxU32 grSstVideoLine(void)
+ FP.grRFunction0 = (prfunc0)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction0());
+ ret_value = G_OK;
+ break;
+ case _grSstWinClose0:
+ // void grSstWinClose(void)
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ if(glide.enabled) {
+ GLIDE_DisableScreen();
+ }
+ break;
+ case _grSstWinOpen28:
+ // FxBool grSstWinOpen(FxU32 hwnd, GrScreenResolution_t res, GrScreenRefresh_t ref,
+ // GrColorFormat_t cformat, GrOriginLocation_t org_loc, int num_buffers, int num_aux_buffers)
+ FP.grRFunction1p6i = (prfunc1p6i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+
+ /* Tie Break Tennis */
+ if(glide.enabled) {
+ LOG_MSG("Glide:grSstWinOpen called when glide is active!");
+ mem_writed(ret, FXTRUE);
+ ret_value = G_OK;
+ break;
+ }
+
+ // Check for successful memory map
+ if(mem_readd(param[10]) == 0) {
+ LOG_MSG("Glide:LFB memory map failed, using default LFB address!");
+ // Write physical address instead, it can crash but it just might work
+ mem_writed(param[10], glide.lfb_pagehandler->GetPhysPt());
+ }
+
+ glide.enabled = true;
+ glide.width = param[8];
+ glide.height = param[9];
+ GrOriginLocation = param[5];
+
+ // Resize window and disable updates
+ GLIDE_ResetScreen();
+
+ k = FP.grRFunction1p6i(hwnd, param[2], param[3], param[4], param[5], param[6], param[7]);
+ if(k == FXFALSE) {
+ LOG_MSG("Glide:grSstWinOpen failed!");
+ GLIDE_DisableScreen();
+ mem_writed(ret, FXFALSE);
+ ret_value = G_OK;
+ break;
+ }
+
+ mem_writed(ret, k);
+ if(glide.splash) {
+ grSplash();
+ glide.splash = false;
+ }
+
+ glide.lfb_pagehandler->SetLinPt(mem_readd(param[10]));
+ LOG_MSG("Glide:Resolution:%dx%d, LFB at 0x%x (physical) / 0x%x (linear)",
+ glide.width, glide.height, glide.lfb_pagehandler->GetPhysPt(), glide.lfb_pagehandler->GetLinPt());
+ ret_value = G_OK;
+ break;
+ case _grTexCalcMemRequired16:
+ // FxU32 grTexCalcMemRequired(GrLOD_t smallLod, GrLOD_t largeLod, GrAspectRatio_t aspect,
+ // GrTextureFormat_t format)
+ FP.grRFunction4i = (prfunc4i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction4i(param[1], param[2], param[3], param[4]));
+ ret_value = G_OK;
+ break;
+ case _grTexClampMode12:
+ // void grTexClampMode(GrChipID_t tmu, GrTextureClampMode_t sClampMode, GrTextureClampMode_t tClampMode)
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i(param[1], param[2], param[3]);
+ break;
+ case _grTexCombine28:
+ // void grTexCombine(GrChipID_t tmu, GrCombineFunction_t rgb_function, GrCombineFactor_t rgb_factor,
+ // GrCombineFunction_t alpha_function, GrCombineFactor_t alpha_factor, FxBool rgb_invert,
+ // FxBool alpha_invert)
+ FP.grFunction7i = (pfunc7i)fn_pt[i];
+ FP.grFunction7i(param[1], param[2], param[3], param[4], param[5], param[6], param[7]);
+ break;
+ case _grTexCombineFunction8:
+ // void grTexCombineFunction(GrChipID_t tmu, GrTextureCombineFnc_t fnc)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+ case _grTexDetailControl16:
+ // void grTexDetailControl(GrChipID_t tmu, int lodBias, FxU8 detailScale, float detailMax)
+ FP.grFunction3i1f = (pfunc3i1f)fn_pt[i];
+ FP.grFunction3i1f(param[1], param[2], param[3], int_to_float(param[4]));
+ break;
+ case _grTexDownloadMipMap16:
+ // void grTexDownloadMipMap(GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+ FP.grRFunction1i1p = (prfunc1i1p)fn_pt[_grTexTextureMemRequired8];
+ if(FP.grRFunction1i1p == NULL) {
+ LOG_MSG("Glide:Unable to get pointer to grTexTextureMemRequired");
+ return;
+ }
+
+ MEM_BlockRead32(param[4], &dbtexinfo, sizeof(DBGrTexInfo));
+
+ texinfo.smallLod = dbtexinfo.smallLod;
+ texinfo.largeLod = dbtexinfo.largeLod;
+ texinfo.aspectRatio = dbtexinfo.aspectRatio;
+ texinfo.format = dbtexinfo.format;
+ texinfo.data = NULL;
+
+ // grTexTextureMemRequired
+ texsize = FP.grRFunction1i1p(param[3], &texinfo);
+ MEM_BlockRead(dbtexinfo.data, texmem, texsize);
+ texinfo.data = texmem;
+
+ FP.grFunction3i1p = (pfunc3i1p)fn_pt[i];
+ FP.grFunction3i1p(param[1], param[2], param[3], &texinfo);
+ break;
+ case _grTexDownloadMipMapLevel32:
+ // void grTexDownloadMipMapLevel(GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod,
+ // GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format,
+ // FxU32 evenOdd, void *data)
+ FP.grRFunction1i1p = (prfunc1i1p)fn_pt[_grTexTextureMemRequired8];
+ if(FP.grRFunction1i1p == NULL) {
+ LOG_MSG("Glide:Unable to get pointer to grTexTextureMemRequired");
+ return;
+ }
+
+ texinfo.smallLod = param[3];
+ texinfo.largeLod = param[3]; // Calculate only thisLod
+ texinfo.aspectRatio = param[5];
+ texinfo.format = param[6];
+ texinfo.data = NULL;
+
+ // grTexTextureMemRequired
+ texsize = FP.grRFunction1i1p(param[7], &texinfo);
+ MEM_BlockRead(param[8], texmem, texsize);
+
+#if LOG_GLIDE
+ LOG_MSG("Read %d (%d %d %d %d %d) bytes of texture data", texsize, param[3], param[4], param[5], param[6], param[7]);
+#endif
+
+ FP.grFunction7i1p = (pfunc7i1p)fn_pt[i];
+ FP.grFunction7i1p(param[1], param[2], param[3], param[4], param[5], param[6], param[7], texmem);
+ break;
+ case _grTexDownloadMipMapLevelPartial40:
+ // FX_ENTRY void FX_CALL grTexDownloadMipMapLevelPartial(GrChipID_t tmu, FxU32 startAddress,
+ // GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format,
+ // FxU32 evenOdd, void *data, int start, int end);
+ FP.grRFunction1i1p = (prfunc1i1p)fn_pt[_grTexTextureMemRequired8];
+ if(FP.grRFunction1i1p == NULL) {
+ LOG_MSG("Glide:Unable to get pointer to grTexTextureMemRequired");
+ return;
+ }
+
+ texinfo.smallLod = param[3];
+ texinfo.largeLod = param[3]; // Calculate only thisLod
+ texinfo.aspectRatio = param[5];
+ texinfo.format = param[6];
+ texinfo.data = NULL;
+
+ // grTexTextureMemRequired
+ texsize = FP.grRFunction1i1p(param[7], &texinfo);
+ MEM_BlockRead(param[8], texmem, texsize);
+
+ FP.grFunction7i1p2i = (pfunc7i1p2i)fn_pt[i];
+ FP.grFunction7i1p2i(param[1], param[2], param[3], param[4], param[5], param[6], param[7], texmem,
+ param[9], param[10]);
+ break;
+ case _grTexDownloadTable12:
+ // void grTexDownloadTable(GrChipID_t tmu, GrTexTable_t type, void *data)
+ FP.grFunction2i1p = (pfunc2i1p)fn_pt[i];
+
+ if(param[2] == GR_TEXTABLE_PALETTE) {
+ MEM_BlockRead32(param[3], texmem, sizeof(GuTexPalette));
+ } else { // GR_TEXTABLE_NCC0 or GR_TEXTABLE_NCC1
+ MEM_BlockRead32(param[3], texmem, sizeof(GuNccTable));
+ }
+
+ FP.grFunction2i1p(param[1], param[2], texmem);
+ break;
+ case _grTexDownloadTablePartial20:
+ // void grTexDownloadTablePartial(GrChipID_t tmu, GrTexTable_t type, void *data, int start, int end)
+ FP.grFunction2i1p2i = (pfunc2i1p2i)fn_pt[i];
+
+ if(param[2] == GR_TEXTABLE_PALETTE) {
+ MEM_BlockRead32(param[3], texmem, sizeof(GuTexPalette));
+ FP.grFunction2i1p2i(param[1], param[2], texmem, param[4], param[5]);
+ } else { // GR_TEXTABLE_NCC0 or GR_TEXTABLE_NCC1
+ LOG_MSG("Glide:Downloading partial NCC tables is not supported!");
+ }
+
+ break;
+ case _grTexFilterMode12:
+ // void grTexFilterMode(GrChipID_t tmu, GrTextureFilterMode_t minFilterMode,
+ // GrTextureFilterMode_t magFilterMode)
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i(param[1], param[2], param[3]);
+ break;
+ case _grTexLodBiasValue8:
+ // void grTexLodBiasValue(GrChipID_t tmu, float bias)
+ FP.grFunction1i1f = (pfunc1i1f)fn_pt[i];
+ FP.grFunction1i1f(param[1], int_to_float(param[2]));
+ break;
+ case _grTexMaxAddress4:
+ // FxU32 grTexMaxAddress(GrChipID_t tmu)
+ FP.grRFunction1i = (prfunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1i(param[1]));
+ ret_value = G_OK;
+ break;
+ case _grTexMinAddress4:
+ // FxU32 grTexMinAddress(GrChipID_t tmu)
+ FP.grRFunction1i = (prfunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1i(param[1]));
+ ret_value = G_OK;
+ break;
+ case _grTexMipMapMode12:
+ // void grTexMipMapMode(GrChipID_t tmu, GrMipMapMode_t mode, FxBool lodBlend)
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i(param[1], param[2], param[3]);
+ break;
+ case _grTexMultibase8:
+ // void grTexMultibase(GrChipID_t tmu, FxBool enable)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+/*
+ case _grTexMultibaseAddress20:
+ // void grTexMultibaseAddress(GrChipID_t tmu, GrTexBaseRange_t range, FxU32 startAddress,
+ // FxU32 evenOdd, GrTexInfo *info)
+ FP.grFunction4i1p = (pfunc4i1p)fn_pt[i];
+
+ // This is a bit more complicated since *info contains a pointer to data
+ texinfo = (GrTexInfo*)param[5];
+ data = (PhysPt)texinfo->data; // Store for later reference
+ texinfo->data = VIRTOREAL(data);
+#if LOG_GLIDE
+ if(log_func[value-_grAADrawLine8] == 1) {
+ LOG_MSG("Glide:Replacing pointer 0x%x with 0x%x in function %d", data, texinfo->data, _grTexMultibaseAddress20);
+ log_func[value-_grAADrawLine8] = 2;
+ }
+#endif
+ FP.grFunction20(param[1], param[2], param[3], param[4], (int)texinfo);
+ texinfo->data = (void*)data; // Change the pointer back
+ break;
+*/
+ case _grTexNCCTable8:
+ // void grTexNCCTable(GrChipID_t tmu, GrNCCTable_t table)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+ case _grTexSource16:
+ // void grTexSource(GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+ FP.grFunction3i1p = (pfunc3i1p)fn_pt[i];
+
+ // Copy the data from DB struct
+ MEM_BlockRead32(param[4], &dbtexinfo, sizeof(DBGrTexInfo));
+
+ texinfo.smallLod = dbtexinfo.smallLod;
+ texinfo.largeLod = dbtexinfo.largeLod;
+ texinfo.aspectRatio = dbtexinfo.aspectRatio;
+ texinfo.format = dbtexinfo.format;
+ // Should the data pointer be filled ?
+
+ FP.grFunction3i1p(param[1], param[2], param[3], &texinfo);
+ break;
+ case _grTexTextureMemRequired8:
+ // FxU32 grTexTextureMemRequired(FxU32 evenOdd, GrTexInfo *info)
+ FP.grRFunction1i1p = (prfunc1i1p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+
+ // Copy the data from DB struct
+ MEM_BlockRead32(param[2], &dbtexinfo, sizeof(DBGrTexInfo));
+
+ texinfo.smallLod = dbtexinfo.smallLod;
+ texinfo.largeLod = dbtexinfo.largeLod;
+ texinfo.aspectRatio = dbtexinfo.aspectRatio;
+ texinfo.format = dbtexinfo.format;
+
+ mem_writed(ret, FP.grRFunction1i1p(param[1], &texinfo));
+
+ ret_value = G_OK;
+ break;
+ case _grTriStats8:
+ // void grTriStats(FxU32 *trisProcessed, FxU32 *trisDrawn)
+ FP.grFunction2p = (pfunc2p)fn_pt[i];
+ MEM_BlockRead32(param[1], ilist, sizeof(FxU32));
+ MEM_BlockRead32(param[2], ilist + 1, sizeof(FxU32));
+ FP.grFunction2p(ilist, ilist + 1);
+ MEM_BlockWrite32(param[1], ilist, sizeof(FxU32));
+ MEM_BlockWrite32(param[2], ilist + 1, sizeof(FxU32));
+ break;
+ case _gu3dfGetInfo8:
+ // FxBool gu3dfGetInfo(const char *filename, Gu3dfInfo *info)
+ FP.grRFunction2p = (prfunc2p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ MEM_StrCopy(param[1], filename, 512);
+
+#if LOG_GLIDE
+ LOG_MSG("Glide:Filename info found in gu3dfGetInfo: %s", filename);
+#endif
+ if(!GetFileName(filename)) break;
+ mem_writed(ret, FP.grRFunction2p(filename, &guinfo));
+
+ // Copy the data back to DB struct if successful
+ if(mem_readd(ret)) {
+ MEM_BlockRead32(param[2], &dbguinfo, sizeof(DBGu3dfInfo));
+ dbguinfo.header.width = (Bit32u)guinfo.header.width;
+ dbguinfo.header.height = (Bit32u)guinfo.header.height;
+ dbguinfo.header.small_lod = (Bit32s)guinfo.header.small_lod;
+ dbguinfo.header.large_lod = (Bit32s)guinfo.header.large_lod;
+ dbguinfo.header.aspect_ratio = (Bit32s)guinfo.header.aspect_ratio;
+ dbguinfo.header.format = (Bit32s)guinfo.header.format;
+ dbguinfo.mem_required = (Bit32u)guinfo.mem_required;
+ MEM_BlockWrite32(param[2], &dbguinfo, sizeof(DBGu3dfInfo));
+ }
+
+ ret_value = G_OK;
+ break;
+ case _gu3dfLoad8:
+ // FxBool gu3dfLoad(const char *filename, Gu3dfInfo *info)
+ FP.grRFunction2p = (prfunc2p)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+
+ // Although glide ref specifies *info should be filled by gu3dfGetInfo before calling gu3dfLoad,
+ // OpenGlide will re-read the header in gu3dfLoad as well
+ MEM_BlockRead32(param[2], &dbguinfo, sizeof(DBGu3dfInfo));
+ MEM_StrCopy(param[1], filename, 512);
+
+#if LOG_GLIDE
+ LOG_MSG("Glide:Filename info found in gu3dfLoad: %s", filename);
+#endif
+ if(!GetFileName(filename)) break;
+
+ guinfo.data = texmem;
+ mem_writed(ret, FP.grRFunction2p(filename, &guinfo));
+
+ // Copy the data back to DB struct if successful
+ if(mem_readd(ret)) {
+ for(j=0;j<256;j++)
+ dbguinfo.table.palette.data[j] = (Bit32u)guinfo.table.palette.data[j];
+ MEM_BlockWrite(dbguinfo.data, guinfo.data, guinfo.mem_required);
+ }
+
+ MEM_BlockWrite32(param[2], &dbguinfo, sizeof(DBGu3dfInfo));
+ ret_value = G_OK;
+ break;
+ case _guAADrawTriangleWithClip12:
+ // void guAADrawTriangleWithClip(const GrVertex *va, const GrVertex *vb, const GrVertex *vc)
+ FP.grFunction3p = (pfunc3p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ MEM_BlockRead32(param[3], &vertex[2], sizeof(GrVertex));
+ FP.grFunction3p(&vertex[0], &vertex[1], &vertex[2]);
+ break;
+ case _guAlphaSource4:
+ // void guAlphaSource(GrAlphaSourceMode_t mode)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _guColorCombineFunction4:
+ // void guColorCombineFunction(GrColorCombineFunction_t func)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _guDrawPolygonVertexListWithClip8:
+ // void guDrawPolygonVertexListWithClip(int nverts, const GrVertex vlist[])
+ FP.grFunction1i1p = (pfunc1i1p)fn_pt[i];
+ MEM_BlockRead32(param[2], texmem, sizeof(GrVertex)*param[1]);
+ FP.grFunction1i1p(param[1], texmem);
+ break;
+ case _guDrawTriangleWithClip12:
+ // void guDrawTriangleWithClip(const GrVertex *va, const GrVertex *vb, const GrVertex *vc)
+ FP.grFunction3p = (pfunc3p)fn_pt[i];
+ MEM_BlockRead32(param[1], &vertex[0], sizeof(GrVertex));
+ MEM_BlockRead32(param[2], &vertex[1], sizeof(GrVertex));
+ MEM_BlockRead32(param[3], &vertex[2], sizeof(GrVertex));
+ FP.grFunction3p(&vertex[0], &vertex[1], &vertex[2]);
+ break;
+/*
+ case _guEncodeRLE1616:
+ //
+ FP.grFunction16 = (pfunc16)fn_pt[i];
+ FP.grFunction16();
+ break;
+ case _guEndianSwapBytes4:
+ //
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i();
+ break;
+ case _guEndianSwapWords4:
+ //
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i();
+ break;
+*/
+ case _guFogGenerateExp28:
+ // void guFogGenerateExp2(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density)
+ FP.grFunction1p1f = (pfunc1p1f)fn_pt[i];
+ FP.grFunction1p1f(texmem, int_to_float(param[2]));
+ MEM_BlockWrite32(param[1], texmem, GR_FOG_TABLE_SIZE*sizeof(GrFog_t));
+ break;
+ case _guFogGenerateExp8:
+ // void guFogGenerateExp(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float density)
+ FP.grFunction1p1f = (pfunc1p1f)fn_pt[i];
+ FP.grFunction1p1f(texmem, int_to_float(param[2]));
+ MEM_BlockWrite32(param[1], texmem, GR_FOG_TABLE_SIZE*sizeof(GrFog_t));
+ break;
+ case _guFogGenerateLinear12:
+ // void guFogGenerateLinear(GrFog_t fogTable[GR_FOG_TABLE_SIZE], float nearW, float farW)
+ FP.grFunction1p2f = (pfunc1p2f)fn_pt[i];
+ FP.grFunction1p2f(texmem, int_to_float(param[2]), int_to_float(param[3]));
+ MEM_BlockWrite32(param[1], texmem, GR_FOG_TABLE_SIZE*sizeof(GrFog_t));
+ break;
+ case _guFogTableIndexToW4: {
+ // float guFogTableIndexToW(int i)
+ FP.grFFunction1i = (pffunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ float tmp = FP.grFFunction1i(param[1]);
+ SDL_memcpy(&j, &tmp, 4);
+ mem_writed(ret, SDL_SwapLE32(j));
+ ret_value = G_OK;
+ break;
+ }
+/*
+ case _guMPDrawTriangle12:
+ //
+ FP.grFunction3i = (pfunc3i)fn_pt[i];
+ FP.grFunction3i();
+ break;
+ case _guMPInit0:
+ //
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _guMPTexCombineFunction4:
+ //
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i();
+ break;
+ case _guMPTexSource8:
+ //
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i();
+ break;
+ case _guMovieSetName4:
+ //
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i();
+ break;
+ case _guMovieStart0:
+ //
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _guMovieStop0:
+ //
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+*/
+ case _guTexAllocateMemory60:
+ // GrMipMapId_t guTexAllocateMemory(GrChipID_t tmu, FxU8 evenOddMask, int width, int height,
+ // GrTextureFormat_t format, GrMipMapMode_t mmMode, GrLOD_t smallLod, GrLOD_t largeLod,
+ // GrAspectRatio_t aspectRatio, GrTextureClampMode_t sClampMode,
+ // GrTextureClampMode_t tClampMode, GrTextureFilterMode_t minFilterMode,
+ // GrTextureFilterMode_t magFilterMode, float lodBias, FxBool lodBlend)
+ FP.grRFunction13i1f1i = (prfunc13i1f1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction13i1f1i(param[1], param[2], param[3], param[4], param[5], param[6], param[7],
+ param[8], param[9], param[10], param[11], param[12], param[13], int_to_float(param[14]), param[15]));
+ ret_value = G_OK;
+ break;
+ case _guTexChangeAttributes48:
+ // FxBool guTexChangeAttributes(GrMipMapID_t mmid, int width, int height, GrTextureFormat_t format,
+ // GrMipMapMode_t mmMode, GrLOD_t smallLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio,
+ // GrTextureClampMode_t sClampMode, GrTextureClampMode_t tClampMode,
+ // GrTextureFilterMode_t minFilterMode, GrTextureFilterMode_t magFilterMode)
+ FP.grRFunction12i = (prfunc12i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction12i(param[1], param[2], param[3], param[4], param[5], param[6], param[7],
+ param[8], param[9], param[10], param[11], param[12]));
+ ret_value = G_OK;
+ break;
+ case _guTexCombineFunction8:
+ // void guTexCombineFunction(GrChipID_t tmu, GrTextureCombineFnc_t func)
+ FP.grFunction2i = (pfunc2i)fn_pt[i];
+ FP.grFunction2i(param[1], param[2]);
+ break;
+/*
+ case _guTexCreateColorMipMap0:
+ //
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+*/
+ case _guTexDownloadMipMap12:
+ // void guTexDownloadMipMap(GrMipMapId_t mmid, const void *src, const GuNccTable *nccTable)
+ FP.grRPTFunction1i = (prptfunc1i)fn_pt[_guTexGetMipMapInfo4];
+ mipmap = (GrMipMapInfo*)FP.grRPTFunction1i(param[1]);
+
+ if(mipmap) {
+ texinfo.aspectRatio = mipmap->aspect_ratio;
+ texinfo.format = mipmap->format;
+ texinfo.largeLod = mipmap->lod_max;
+ texinfo.smallLod = mipmap->lod_min;
+
+ FP.grRFunction1i1p = (prfunc1i1p)fn_pt[_grTexTextureMemRequired8];
+ if(FP.grRFunction1i1p == NULL) {
+ LOG_MSG("Glide:Unable to get pointer to grTexTextureMemRequired");
+ return;
+ }
+
+ texsize = FP.grRFunction1i1p(mipmap->odd_even_mask, &texinfo);
+
+ MEM_BlockRead(param[2], texmem, texsize);
+ MEM_BlockRead32(param[3], (Bit8u*)texmem+texsize, sizeof(GuNccTable));
+
+ FP.grFunction1i2p = (pfunc1i2p)fn_pt[i];
+ FP.grFunction1i2p(param[1], texmem, (Bit8u*)texmem+texsize);
+ } else {
+ LOG_MSG("Glide:Unable to get GrMipMapInfo pointer");
+ }
+ break;
+/*
+ case _guTexDownloadMipMapLevel12:
+ // void guTexDownloadMipMapLevel(GrMipMapId_t mmid, GrLOD_t lod, const void **src)
+ FP.grFunction2i1p = (pfunc2i1p)fn_pt[i];
+ FP.grFunction2i1p(param[1], param[2], *param[3]);
+ break;
+*/
+ case _guTexGetCurrentMipMap4:
+ // GrMipMapId_t guTexGetCurrentMipMap(GrChipID_t tmu)
+ FP.grRFunction1i = (prfunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1i(param[1]));
+ ret_value = G_OK;
+ break;
+/*
+ case _guTexGetMipMapInfo4:
+ // GrMipMapInfo *guTexGetMipMapInfo(GrMipMapId_t mmid)
+ FP.grRFunction4 = (prfunc4)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction4(param[1]));
+ ret_value = G_OK;
+ break;
+*/
+ case _guTexMemQueryAvail4:
+ // FxU32 guTexMemQueryAvail(GrChipID_t tmu)
+ FP.grRFunction1i = (prfunc1i)fn_pt[i];
+ if(ret == 0) {
+ LOG_MSG("Glide:Invalid return value handle for %s!", grTable[i].name);
+ return;
+ }
+ mem_writed(ret, FP.grRFunction1i(param[1]));
+ ret_value = G_OK;
+ break;
+ case _guTexMemReset0:
+ // void guTexMemReset(void)
+ FP.grFunction0 = (pfunc0)fn_pt[i];
+ FP.grFunction0();
+ break;
+ case _guTexSource4:
+ // void guTexSource(GrMipMapId_t mmid)
+ FP.grFunction1i = (pfunc1i)fn_pt[i];
+ FP.grFunction1i(param[1]);
+ break;
+ case _ConvertAndDownloadRle64: {
+ // void ConvertAndDownloadRle(GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod,
+ // GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd,
+ // FxU8 *bm_data, long bm_h, FxU32 u0, FxU32 v0, FxU32 width, FxU32 height,
+ // FxU32 dest_width, FxU32 dest_height, FxU16 *tlut)
+
+#if LOG_GLIDE
+ LOG_MSG("Glide: RLE width: %d, height: %d, bm_h: %d, u0: %d, v0: %d, dest %dx%d",
+ param[12], param[13], param[9], param[10], param[11], param[14], param[15]);
+#endif
+
+ FxU8 c;
+ FxU32 scount = 0;
+ FxU32 dcount = 0;
+
+ FxU16 * src = ptr16 + param[14]*param[15];
+ FxU32 offset = 4 + param[9];
+
+ // Line offset (v0)
+ for(j = 0; j < param[11]; j++ ) {
+ offset += mem_readb(param[8]+4+j);
+ }
+
+ // Write height lines
+ for(k = 0; k < param[13]; k++) {
+
+ // Decode one RLE line
+ scount = offset;
+ while((c = mem_readb(param[8]+scount)) != 0xE0) {
+
+ if(c > 0xE0) {
+ for(int count = 0; count < (c&0x1f); count++) {
+
+ // tlut is FxU16*
+ src[dcount] = mem_readw(param[16]+(mem_readb(param[8]+scount+1)<<1));
+ dcount++;
+ }
+ scount += 2;
+
+ } else {
+ src[dcount] = mem_readw(param[16]+(c<<1));
+ dcount++; scount++;
+ }
+ }
+
+ // Copy Line into destination texture, offset u0
+ SDL_memcpy(ptr16 + (k*param[14]), src + param[10], sizeof(FxU16)*param[14]);
+ offset += mem_readb(param[8] + 4 + j++);
+ dcount = 0;
+ }
+
+ // One additional line
+ if(param[13] < param[15])
+ SDL_memcpy(ptr16 + (k*param[14]), src + param[10], sizeof(FxU16)*param[14]);
+
+ // Download decoded texture
+ texinfo.smallLod = param[3];
+ texinfo.largeLod = param[4];
+ texinfo.aspectRatio = param[5];
+ texinfo.format = param[6];
+ texinfo.data = ptr16;
+
+ // void grTexDownloadMipMap(GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info)
+ FP.grFunction3i1p = (pfunc3i1p)fn_pt[_grTexDownloadMipMap16];
+ if(FP.grFunction3i1p == NULL) {
+ LOG_MSG("Glide:Unable to get pointer to grTexDownloadMipMap");
+ break;
+ }
+ FP.grFunction3i1p(param[1], param[2], param[7], &texinfo);
+ break;
+ }
+ default:
+ LOG_MSG("Glide:Unsupported glide call %s", grTable[i].name);
+ break;
+
+ } /* switch */
+} /* process_msg() */
diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp
--- a/src/hardware/memory.cpp
+++ b/src/hardware/memory.cpp
@@ -23,6 +23,7 @@
#include "setup.h"
#include "paging.h"
#include "regs.h"
+#include "glidedef.h"
#include <string.h>
@@ -140,6 +141,8 @@ PageHandler * MEM_GetPageHandler(Bitu phys_page) {
} else if ((phys_page>=memory.lfb.start_page+0x01000000/4096) &&
(phys_page<memory.lfb.start_page+0x01000000/4096+16)) {
return memory.lfb.mmiohandler;
+ } else if (glide.enabled && (phys_page>=(GLIDE_LFB>>12)) && (phys_page<(GLIDE_LFB>>12)+GLIDE_PAGES)) {
+ return (PageHandler*)glide.lfb_pagehandler;
}
return &illegal_page_handler;
}
@@ -191,6 +194,24 @@ void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size) {
}
}
+void MEM_BlockRead32(PhysPt pt,void * data,Bitu size) {
+ Bit32u * write=(Bit32u *) data;
+ size>>=2;
+ while (size--) {
+ *write++=mem_readd_inline(pt);
+ pt+=4;
+ }
+}
+
+void MEM_BlockWrite32(PhysPt pt,void * data,Bitu size) {
+ Bit32u * read=(Bit32u *) data;
+ size>>=2;
+ while (size--) {
+ mem_writed_inline(pt,*read++);
+ pt+=4;
+ }
+}
+
void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) {
mem_memcpy(dest,src,size);
}