summaryrefslogtreecommitdiff
path: root/src/d3d
diff options
context:
space:
mode:
Diffstat (limited to 'src/d3d')
-rw-r--r--src/d3d/d3d.cpp1087
-rw-r--r--src/d3d/d3d8.cpp678
-rw-r--r--src/d3d/d3d8matfx.cpp56
-rw-r--r--src/d3d/d3d8render.cpp65
-rw-r--r--src/d3d/d3d8skin.cpp56
-rw-r--r--src/d3d/d3d9.cpp853
-rw-r--r--src/d3d/d3d9matfx.cpp313
-rw-r--r--src/d3d/d3d9render.cpp185
-rw-r--r--src/d3d/d3d9skin.cpp418
-rw-r--r--src/d3d/d3ddevice.cpp2022
-rw-r--r--src/d3d/d3dimmed.cpp404
-rw-r--r--src/d3d/d3drender.cpp424
-rw-r--r--src/d3d/rwd3d.h421
-rw-r--r--src/d3d/rwd3d8.h74
-rw-r--r--src/d3d/rwd3d9.h112
-rw-r--r--src/d3d/rwd3dimpl.h81
-rw-r--r--src/d3d/rwxbox.h195
-rw-r--r--src/d3d/rwxboximpl.h11
-rw-r--r--src/d3d/shaders/default_PS.h72
-rw-r--r--src/d3d/shaders/default_PS.hlsl19
-rw-r--r--src/d3d/shaders/default_VS.hlsl51
-rw-r--r--src/d3d/shaders/default_all_VS.h491
-rw-r--r--src/d3d/shaders/default_amb_VS.h156
-rw-r--r--src/d3d/shaders/default_amb_dir_VS.h272
-rw-r--r--src/d3d/shaders/default_tex_PS.h89
-rw-r--r--src/d3d/shaders/im2d_PS.h72
-rw-r--r--src/d3d/shaders/im2d_PS.hlsl19
-rw-r--r--src/d3d/shaders/im2d_VS.h107
-rw-r--r--src/d3d/shaders/im2d_VS.hlsl30
-rw-r--r--src/d3d/shaders/im2d_tex_PS.h89
-rw-r--r--src/d3d/shaders/lighting.h44
-rw-r--r--src/d3d/shaders/make_default.cmd11
-rw-r--r--src/d3d/shaders/make_matfx.cmd7
-rw-r--r--src/d3d/shaders/make_skin.cmd4
-rw-r--r--src/d3d/shaders/matfx_env_PS.h124
-rw-r--r--src/d3d/shaders/matfx_env_PS.hlsl42
-rw-r--r--src/d3d/shaders/matfx_env_VS.hlsl59
-rw-r--r--src/d3d/shaders/matfx_env_all_VS.h535
-rw-r--r--src/d3d/shaders/matfx_env_amb_VS.h225
-rw-r--r--src/d3d/shaders/matfx_env_amb_dir_VS.h316
-rw-r--r--src/d3d/shaders/matfx_env_tex_PS.h141
-rw-r--r--src/d3d/shaders/skin_VS.hlsl63
-rw-r--r--src/d3d/shaders/skin_all_VS.h664
-rw-r--r--src/d3d/shaders/skin_amb_VS.h253
-rw-r--r--src/d3d/shaders/skin_amb_dir_VS.h503
-rw-r--r--src/d3d/shaders/standardConstants.h28
-rw-r--r--src/d3d/xbox.cpp1005
-rw-r--r--src/d3d/xboxmatfx.cpp53
-rw-r--r--src/d3d/xboxskin.cpp252
-rw-r--r--src/d3d/xboxvfmt.cpp115
50 files changed, 13366 insertions, 0 deletions
diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp
new file mode 100644
index 0000000..f1f5f49
--- /dev/null
+++ b/src/d3d/d3d.cpp
@@ -0,0 +1,1087 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+#include "rwd3dimpl.h"
+
+#define PLUGIN_ID ID_DRIVER
+
+namespace rw {
+namespace d3d {
+
+bool32 isP8supported = 1; // set to 0 when actual d3d device is used
+
+// stolen from d3d8to9
+static uint32
+calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format)
+{
+#define D3DFMT_W11V11U10 65
+ switch(format){
+ default:
+ case D3DFMT_UNKNOWN:
+ return 0;
+ case D3DFMT_R3G3B2:
+ case D3DFMT_A8:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ case D3DFMT_A4L4:
+ return width * height * depth;
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_V8U8:
+ case D3DFMT_L6V5U5:
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D15S1:
+ case D3DFMT_D16:
+ case D3DFMT_UYVY:
+ case D3DFMT_YUY2:
+ return width * 2 * height * depth;
+ case D3DFMT_R8G8B8:
+ return width * 3 * height * depth;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A2B10G10R10:
+ case D3DFMT_A8B8G8R8:
+ case D3DFMT_X8B8G8R8:
+ case D3DFMT_G16R16:
+ case D3DFMT_X8L8V8U8:
+ case D3DFMT_Q8W8V8U8:
+ case D3DFMT_V16U16:
+ case D3DFMT_W11V11U10:
+ case D3DFMT_A2W10V10U10:
+ case D3DFMT_D32:
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X8:
+ case D3DFMT_D24X4S4:
+ return width * 4 * height * depth;
+ case D3DFMT_DXT1:
+ assert(depth <= 1);
+ return ((width + 3) >> 2) * ((height + 3) >> 2) * 8;
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ assert(depth <= 1);
+ return ((width + 3) >> 2) * ((height + 3) >> 2) * 16;
+ }
+}
+
+int vertFormatMap[] = {
+ -1, VERT_FLOAT2, VERT_FLOAT3, VERT_FLOAT4, VERT_ARGB, VERT_RGBA /* blend indices */
+};
+
+void*
+createIndexBuffer(uint32 length, bool dynamic)
+{
+#ifdef RW_D3D9
+ IDirect3DIndexBuffer9 *ibuf;
+ if(dynamic)
+ d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibuf, 0);
+ else
+ d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0);
+ if(ibuf)
+ d3d9Globals.numIndexBuffers++;
+ return ibuf;
+#else
+ return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER);
+#endif
+}
+
+void
+destroyIndexBuffer(void *indexBuffer)
+{
+#ifdef RW_D3D9
+ if(indexBuffer){
+ if(((IUnknown*)indexBuffer)->Release() != 0)
+ printf("indexBuffer wasn't destroyed\n");
+ d3d9Globals.numIndexBuffers--;
+ }
+#else
+ rwFree(indexBuffer);
+#endif
+}
+
+uint16*
+lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags)
+{
+ if(indexBuffer == nil)
+ return nil;
+#ifdef RW_D3D9
+ uint16 *indices;
+ IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
+ ibuf->Lock(offset, size, (void**)&indices, flags);
+ return indices;
+#else
+ (void)offset;
+ (void)size;
+ (void)flags;
+ return (uint16*)indexBuffer;
+#endif
+}
+
+void
+unlockIndices(void *indexBuffer)
+{
+ if(indexBuffer == nil)
+ return;
+#ifdef RW_D3D9
+ IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
+ ibuf->Unlock();
+#endif
+}
+
+void*
+createVertexBuffer(uint32 length, uint32 fvf, bool dynamic)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexBuffer9 *vbuf;
+ if(dynamic)
+ d3ddevice->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, fvf, D3DPOOL_DEFAULT, &vbuf, 0);
+ else
+ d3ddevice->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, D3DPOOL_MANAGED, &vbuf, 0);
+ if(vbuf)
+ d3d9Globals.numVertexBuffers++;
+ return vbuf;
+#else
+ (void)fvf;
+ return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER);
+#endif
+}
+
+void
+destroyVertexBuffer(void *vertexBuffer)
+{
+#ifdef RW_D3D9
+ if(vertexBuffer){
+ if(((IUnknown*)vertexBuffer)->Release() != 0)
+ printf("vertexBuffer wasn't destroyed\n");
+ d3d9Globals.numVertexBuffers--;
+ }
+#else
+ rwFree(vertexBuffer);
+#endif
+}
+
+uint8*
+lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags)
+{
+ if(vertexBuffer == nil)
+ return nil;
+#ifdef RW_D3D9
+ uint8 *verts;
+ IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
+ vertbuf->Lock(offset, size, (void**)&verts, flags);
+ return verts;
+#else
+ (void)offset;
+ (void)size;
+ (void)flags;
+ return (uint8*)vertexBuffer;
+#endif
+}
+
+void
+unlockVertices(void *vertexBuffer)
+{
+ if(vertexBuffer == nil)
+ return;
+#ifdef RW_D3D9
+ IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
+ vertbuf->Unlock();
+#endif
+}
+
+void*
+createTexture(int32 width, int32 height, int32 numlevels, uint32 usage, uint32 format)
+{
+#ifdef RW_D3D9
+ IDirect3DTexture9 *tex;
+ d3ddevice->CreateTexture(width, height, numlevels, usage,
+ (D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil);
+ if(tex)
+ d3d9Globals.numTextures++;
+ return tex;
+#else
+ int32 w = width;
+ int32 h = height;
+ int32 size = 0;
+ for(int32 i = 0; i < numlevels; i++){
+ size += calculateTextureSize(w, h, 1, format);
+ w /= 2;
+ if(w == 0) w = 1;
+ h /= 2;
+ if(h == 0) h = 1;
+ }
+ uint8 *data = (uint8*)rwNew(sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size,
+ MEMDUR_EVENT | ID_DRIVER);
+ RasterLevels *levels = (RasterLevels*)data;
+ data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1);
+ levels->numlevels = numlevels;
+ levels->format = format;
+ w = width;
+ h = height;
+ for(int32 i = 0; i < numlevels; i++){
+ levels->levels[i].width = w;
+ levels->levels[i].height = h;
+ levels->levels[i].data = data;
+ levels->levels[i].size = calculateTextureSize(w, h, 1, format);
+ data += levels->levels[i].size;
+ w /= 2;
+ if(w == 0) w = 1;
+ h /= 2;
+ if(h == 0) h = 1;
+ }
+ return levels;
+#endif
+}
+
+void
+destroyTexture(void *texture)
+{
+#ifdef RW_D3D9
+ if(texture){
+ if(((IUnknown*)texture)->Release() != 0)
+ printf("texture wasn't destroyed\n");
+ d3d9Globals.numTextures--;
+ }
+#else
+ rwFree(texture);
+#endif
+}
+
+// Native Raster
+
+int32 nativeRasterOffset;
+
+struct RasterFormatInfo
+{
+ uint32 d3dformat;
+ int32 depth;
+ bool32 hasAlpha;
+ uint32 rwFormat;
+};
+
+// indexed directly by RW format
+static RasterFormatInfo formatInfoRW[16] = {
+ { 0, 0, 0, 0},
+ { D3DFMT_A1R5G5B5, 16, 1, Raster::C1555 },
+ { D3DFMT_R5G6B5, 16, 0, Raster::C565 },
+ { D3DFMT_A4R4G4B4, 16, 1, Raster::C4444 },
+ { D3DFMT_L8, 8, 0, Raster::LUM8 },
+ { D3DFMT_A8R8G8B8, 32, 1, Raster::C8888 },
+ { D3DFMT_X8R8G8B8, 32, 0, Raster::C888 },
+ { D3DFMT_D16, 16, 0, Raster::D16 },
+ { D3DFMT_D24X8, 32, 0, Raster::D24 },
+ { D3DFMT_D32, 32, 0, Raster::D32 },
+ { D3DFMT_X1R5G5B5, 16, 0, Raster::C555 },
+};
+
+static RasterFormatInfo formatInfoFull[] = {
+ { D3DFMT_R8G8B8, 0, 24, 0 },
+ { D3DFMT_A8R8G8B8, 1, 32, Raster::C8888 },
+ { D3DFMT_X8R8G8B8, 0, 32, Raster::C888 },
+ { D3DFMT_R5G6B5, 0, 16, Raster::C565 },
+ { D3DFMT_X1R5G5B5, 0, 16, Raster::C555 },
+ { D3DFMT_A1R5G5B5, 1, 16, Raster::C1555 },
+ { D3DFMT_A4R4G4B4, 1, 16, Raster::C4444 },
+ { D3DFMT_R3G3B2, 0, 8, 0 },
+ { D3DFMT_A8, 1, 8, 0 },
+ { D3DFMT_A8R3G3B2, 1, 16, 0 },
+ { D3DFMT_X4R4G4B4, 0, 16, 0 },
+ { D3DFMT_A2B10G10R10, 1, 32, 0 },
+ { D3DFMT_A8B8G8R8, 1, 32, 0 },
+ { D3DFMT_X8B8G8R8, 0, 32, 0 },
+ { D3DFMT_G16R16, 0, 32, 0 },
+ { D3DFMT_A2R10G10B10, 1, 32, 0 },
+ { D3DFMT_A16B16G16R16, 1, 64, 0 },
+ { D3DFMT_A8P8, 1, 16, 0 },
+// { D3DFMT_P8, 0, 8, ... },
+// { D3DFMT_L8, 0, 8, ... },
+ { D3DFMT_A8L8, 1, 16, 0 },
+ { D3DFMT_A4L4, 1, 8, 0 },
+ { D3DFMT_V8U8, 0, 16, 0 },
+ { D3DFMT_L6V5U5, 0, 16, 0 },
+ { D3DFMT_X8L8V8U8, 0, 32, 0 },
+ { D3DFMT_Q8W8V8U8, 0, 32, 0 },
+ { D3DFMT_V16U16, 0, 32, 0 },
+ { D3DFMT_A2W10V10U10, 1, 32, 0 },
+ { D3DFMT_D16_LOCKABLE, 0, 16, Raster::D16 },
+ { D3DFMT_D32, 0, 32, Raster::D32 },
+ { D3DFMT_D15S1, 0, 16, Raster::D16 },
+ { D3DFMT_D24S8, 0, 32, Raster::D32 },
+ { D3DFMT_D24X8, 0, 32, Raster::D32 },
+ { D3DFMT_D24X4S4, 0, 32, Raster::D32 },
+ { D3DFMT_D16, 0, 16, Raster::D16 },
+ { D3DFMT_D32F_LOCKABLE, 0, 32, Raster::D32 },
+ { D3DFMT_D24FS8, 0, 32, Raster::D32 },
+ { D3DFMT_L16, 0, 16, 0 },
+ { D3DFMT_Q16W16V16U16, 0, 64, 0 },
+ { D3DFMT_R16F, 0, 16, 0 },
+ { D3DFMT_G16R16F, 0, 32, 0 },
+ { D3DFMT_A16B16G16R16F, 1, 64, 0 },
+ { D3DFMT_R32F, 0, 32, 0 },
+ { D3DFMT_G32R32F, 0, 64, 0 },
+ { D3DFMT_A32B32G32R32F, 1, 128, 0 },
+ { D3DFMT_CxV8U8, 0, 16, 0 },
+};
+
+RasterFormatInfo*
+findFormatInfoD3D(uint32 d3dformat)
+{
+ static RasterFormatInfo fake = { 0, 0, 0, 0 };
+ int i;
+ for(i = 0; i < (int)nelem(formatInfoFull); i++)
+ if(formatInfoFull[i].d3dformat == d3dformat)
+ return &formatInfoFull[i];
+ return &fake;
+}
+
+
+static void
+rasterSetFormat(Raster *raster)
+{
+ if(raster->format == 0){
+ // have to find a format first
+ // this could perhaps be a bit more intelligent
+
+ switch(raster->type){
+ case Raster::NORMAL:
+ case Raster::TEXTURE:
+ raster->format = Raster::C8888;
+ break;
+
+#ifdef RW_D3D9
+ case Raster::ZBUFFER:
+ // TODO: allow other formats
+ raster->format = findFormatInfoD3D(d3d9Globals.present.AutoDepthStencilFormat)->rwFormat;
+ // can this even happen? just do something...
+ if(raster->format == 0)
+ raster->format = Raster::D32;
+ break;
+
+ case Raster::CAMERATEXTURE:
+// let's not use this because we apparently don't want alpha
+// raster->format = findFormatInfoD3D(d3d9Globals.present.BackBufferFormat)->rwFormat;
+ raster->format = findFormatInfoD3D(d3d9Globals.startMode.mode.Format)->rwFormat;
+ // can this even happen? just do something...
+ if(raster->format == 0)
+ raster->format = Raster::C888;
+ break;
+ case Raster::CAMERA:
+ raster->format = findFormatInfoD3D(d3d9Globals.present.BackBufferFormat)->rwFormat;
+ // can this even happen? just do something...
+ if(raster->format == 0)
+ raster->format = Raster::C8888;
+ break;
+#endif
+ }
+ }
+
+
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ if(raster->format & (Raster::PAL4 | Raster::PAL8)){
+ // TODO: do we even allow PAL4?
+ natras->format = D3DFMT_P8;
+ raster->depth = 8;
+ }else{
+ natras->format = formatInfoRW[(raster->format >> 8) & 0xF].d3dformat;
+ raster->depth = formatInfoRW[(raster->format >> 8) & 0xF].depth;
+ }
+ natras->bpp = raster->depth/8;
+ natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
+ raster->stride = raster->width*natras->bpp;
+
+ natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
+}
+
+static Raster*
+rasterCreateTexture(Raster *raster)
+{
+ int32 levels;
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+
+ if(natras->format == D3DFMT_P8)
+ natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
+ if(natras->autogenMipmap)
+ levels = 0;
+ else if(raster->format & Raster::MIPMAP)
+ levels = Raster::calculateNumLevels(raster->width, raster->height);
+ else
+ levels = 1;
+
+ assert(natras->texture == nil);
+ natras->texture = createTexture(raster->width, raster->height,
+ levels,
+ natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
+ natras->format);
+ if(natras->texture == nil){
+ RWERROR((ERR_NOTEXTURE));
+ return nil;
+ }
+ return raster;
+}
+
+#ifdef RW_D3D9
+
+static Raster*
+rasterCreateCameraTexture(Raster *raster)
+{
+ if(raster->format & (Raster::PAL4 | Raster::PAL8)){
+ RWERROR((ERR_NOTEXTURE));
+ return nil;
+ }
+
+ int32 levels;
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ if(natras->autogenMipmap)
+ levels = 0;
+ else if(raster->format & Raster::MIPMAP)
+ levels = Raster::calculateNumLevels(raster->width, raster->height);
+ else
+ levels = 1;
+
+ IDirect3DTexture9 *tex;
+ d3ddevice->CreateTexture(raster->width, raster->height,
+ levels,
+ (natras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0) | D3DUSAGE_RENDERTARGET,
+ (D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
+ assert(natras->texture == nil);
+ natras->texture = tex;
+ if(natras->texture == nil){
+ RWERROR((ERR_NOTEXTURE));
+ return nil;
+ }
+ d3d9Globals.numTextures++;
+ addVidmemRaster(raster);
+ return raster;
+}
+
+static Raster*
+rasterCreateCamera(Raster *raster)
+{
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+
+ natras->autogenMipmap = 0;
+
+ natras->format = d3d9Globals.present.BackBufferFormat;
+ raster->depth = findFormatDepth(natras->format);
+
+ natras->texture = nil; // global default render target
+ return raster;
+}
+
+static Raster*
+rasterCreateZbuffer(Raster *raster)
+{
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+
+ natras->autogenMipmap = 0;
+
+ // TODO: allow other formats
+ natras->format = d3d9Globals.present.AutoDepthStencilFormat;
+ raster->depth = findFormatDepth(natras->format);
+
+ RECT rect;
+ GetClientRect(d3d9Globals.window, &rect);
+ // This check is done by RW but it's rather strange...
+ if(rect.right == raster->width && rect.bottom == raster->height)
+ natras->texture = d3d9Globals.defaultDepthSurf;
+ else{
+ IDirect3DSurface9 *surf = nil;
+ d3ddevice->CreateDepthStencilSurface(raster->width, raster->height, (D3DFORMAT)natras->format,
+ d3d9Globals.present.MultiSampleType, d3d9Globals.present.MultiSampleQuality,
+ FALSE, &surf, nil);
+ assert(natras->texture == nil);
+ natras->texture = surf;
+ if(natras->texture == nil){
+ RWERROR((ERR_NOTEXTURE));
+ return nil;
+ }
+ }
+ addVidmemRaster(raster);
+
+ return raster;
+}
+#endif
+
+Raster*
+rasterCreate(Raster *raster)
+{
+ rasterSetFormat(raster);
+
+ Raster *ret = raster;
+
+ if(raster->width == 0 || raster->height == 0){
+ raster->flags |= Raster::DONTALLOCATE;
+ raster->stride = 0;
+ goto ret;
+ }
+ if(raster->flags & Raster::DONTALLOCATE)
+ goto ret;
+
+ switch(raster->type){
+ case Raster::NORMAL:
+ case Raster::TEXTURE:
+ ret = rasterCreateTexture(raster);
+ break;
+
+#ifdef RW_D3D9
+ case Raster::CAMERATEXTURE:
+ ret = rasterCreateCameraTexture(raster);
+ break;
+ case Raster::ZBUFFER:
+ ret = rasterCreateZbuffer(raster);
+ break;
+ case Raster::CAMERA:
+ ret = rasterCreateCamera(raster);
+ break;
+#endif
+
+ default:
+ RWERROR((ERR_INVRASTER));
+ return nil;
+ }
+
+ret:
+ raster->originalWidth = raster->width;
+ raster->originalHeight = raster->height;
+ raster->originalStride = raster->stride;
+ raster->originalPixels = raster->pixels;
+ return ret;
+}
+
+uint8*
+rasterLock(Raster *raster, int32 level, int32 lockMode)
+{
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+
+ // check if already locked
+ if(raster->privateFlags & (Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE))
+ return nil;
+
+#ifdef RW_D3D9
+ DWORD flags = D3DLOCK_NOSYSLOCK;
+ if(lockMode & Raster::LOCKREAD)
+ flags |= D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE;
+ IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture;
+ IDirect3DSurface9 *surf, *rt;
+ D3DLOCKED_RECT lr;
+
+ switch(raster->type){
+ case Raster::NORMAL:
+ case Raster::TEXTURE: {
+ tex->GetSurfaceLevel(level, &surf);
+ natras->lockedSurf = surf;
+ HRESULT res = surf->LockRect(&lr, 0, flags);
+ assert(res == D3D_OK);
+ break;
+ }
+
+ case Raster::CAMERATEXTURE:
+ case Raster::CAMERA: {
+ if(lockMode & Raster::PRIVATELOCK_WRITE)
+ assert(0 && "can't lock framebuffer for writing");
+ if(raster->type == Raster::CAMERA)
+ rt = d3d9Globals.defaultRenderTarget;
+ else
+ tex->GetSurfaceLevel(level, &rt);
+ D3DSURFACE_DESC desc;
+ rt->GetDesc(&desc);
+ HRESULT res = d3ddevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, nil);
+ if(res != D3D_OK)
+ return nil;
+ d3ddevice->GetRenderTargetData(rt, surf);
+ natras->lockedSurf = surf;
+ res = surf->LockRect(&lr, 0, flags);
+ assert(res == D3D_OK);
+ break;
+ }
+
+ default:
+ assert(0 && "can't lock this raster type (yet)");
+ }
+
+ raster->pixels = (uint8*)lr.pBits;
+ raster->width >>= level;
+ raster->height >>= level;
+ raster->stride = lr.Pitch;
+ if(raster->width == 0) raster->width = 1;
+ if(raster->height == 0) raster->height = 1;
+#else
+ RasterLevels *levels = (RasterLevels*)natras->texture;
+ raster->pixels = levels->levels[level].data;
+ raster->width = levels->levels[level].width;
+ raster->height = levels->levels[level].height;
+ raster->stride = raster->width*natras->bpp;
+#endif
+ if(lockMode & Raster::LOCKREAD) raster->privateFlags |= Raster::PRIVATELOCK_READ;
+ if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
+
+ return raster->pixels;
+}
+
+void
+rasterUnlock(Raster *raster, int32 level)
+{
+#if RW_D3D9
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ IDirect3DSurface9 *surf = (IDirect3DSurface9*)natras->lockedSurf;
+ surf->UnlockRect();
+ surf->Release();
+ natras->lockedSurf = nil;
+#endif
+ raster->width = raster->originalWidth;
+ raster->height = raster->originalHeight;
+ raster->stride = raster->originalStride;
+ raster->pixels = raster->originalPixels;
+
+ raster->privateFlags &= ~(Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE);
+}
+
+int32
+rasterNumLevels(Raster *raster)
+{
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+#ifdef RW_D3D9
+ IDirect3DTexture9 *tex = (IDirect3DTexture9*)natras->texture;
+ return tex->GetLevelCount();
+#else
+ RasterLevels *levels = (RasterLevels*)natras->texture;
+ return levels->numlevels;
+#endif
+}
+
+// Almost the same as ps2 and gl3 function
+bool32
+imageFindRasterFormat(Image *img, int32 type,
+ int32 *pWidth, int32 *pHeight, int32 *pDepth, int32 *pFormat)
+{
+ int32 width, height, depth, format;
+
+ assert((type&0xF) == Raster::TEXTURE);
+
+// for(width = 1; width < img->width; width <<= 1);
+// for(height = 1; height < img->height; height <<= 1);
+ // Perhaps non-power-of-2 textures are acceptable?
+ width = img->width;
+ height = img->height;
+
+ depth = img->depth;
+
+ if(depth <= 8 && !isP8supported)
+ depth = 32;
+
+ switch(depth){
+ case 32:
+ if(img->hasAlpha())
+ format = Raster::C8888;
+ else{
+ format = Raster::C888;
+ depth = 24;
+ }
+ break;
+ case 24:
+ format = Raster::C888;
+ break;
+ case 16:
+ format = Raster::C1555;
+ break;
+ case 8:
+ format = Raster::PAL8 | Raster::C8888;
+ break;
+ case 4:
+ format = Raster::PAL4 | Raster::C8888;
+ break;
+ default:
+ RWERROR((ERR_INVRASTER));
+ return 0;
+ }
+
+ format |= type;
+
+ *pWidth = width;
+ *pHeight = height;
+ *pDepth = depth;
+ *pFormat = format;
+
+ return 1;
+}
+
+bool32
+rasterFromImage(Raster *raster, Image *image)
+{
+ if((raster->type&0xF) != Raster::TEXTURE)
+ return 0;
+
+ void (*conv)(uint8 *out, uint8 *in) = nil;
+
+ // Unpalettize image if necessary but don't change original
+ Image *truecolimg = nil;
+ if(image->depth <= 8 && !isP8supported){
+ truecolimg = Image::create(image->width, image->height, image->depth);
+ truecolimg->pixels = image->pixels;
+ truecolimg->stride = image->stride;
+ truecolimg->palette = image->palette;
+ truecolimg->unpalettize();
+ image = truecolimg;
+ }
+
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ int32 format = raster->format&(Raster::PAL8 | Raster::PAL4 | 0xF00);
+ switch(image->depth){
+ case 32:
+ if(format == Raster::C8888)
+ conv = conv_BGRA8888_from_RGBA8888;
+ else if(format == Raster::C888)
+ conv = conv_BGR888_from_RGB888;
+ else
+ goto err;
+ break;
+ case 24:
+ if(format == Raster::C8888)
+ conv = conv_BGRA8888_from_RGB888;
+ else if(format == Raster::C888)
+ conv = conv_BGR888_from_RGB888;
+ else
+ goto err;
+ break;
+ case 16:
+ if(format == Raster::C1555)
+ conv = conv_ARGB1555_from_ARGB1555;
+ else
+ goto err;
+ break;
+ case 8:
+ if(format == (Raster::PAL8 | Raster::C8888))
+ conv = conv_8_from_8;
+ else
+ goto err;
+ break;
+ case 4:
+ if(format == (Raster::PAL4 | Raster::C8888) ||
+ format == (Raster::PAL8 | Raster::C8888))
+ conv = conv_8_from_8;
+ else
+ goto err;
+ break;
+ default:
+ err:
+fprintf(stderr, "%d %x\n", image->depth, format); fflush(stdout);
+ RWERROR((ERR_INVRASTER));
+ return 0;
+ }
+
+ uint8 *in, *out;
+ int pallength = 0;
+ if(raster->format & Raster::PAL4)
+ pallength = 16;
+ else if(raster->format & Raster::PAL8)
+ pallength = 256;
+ if(pallength){
+ in = image->palette;
+ out = (uint8*)natras->palette;
+ for(int32 i = 0; i < pallength; i++){
+ conv_RGBA8888_from_RGBA8888(out, in);
+ in += 4;
+ out += 4;
+ }
+ }
+
+ bool unlock = false;
+ if(raster->pixels == nil){
+ raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ unlock = true;
+ }
+
+ uint8 *pixels = raster->pixels;
+ assert(pixels);
+ uint8 *imgpixels = image->pixels;
+
+ int x, y;
+ assert(image->width == raster->width);
+ assert(image->height == raster->height);
+ for(y = 0; y < image->height; y++){
+ uint8 *imgrow = imgpixels;
+ uint8 *rasrow = pixels;
+ for(x = 0; x < image->width; x++){
+ conv(rasrow, imgrow);
+ imgrow += image->bpp;
+ rasrow += natras->bpp;
+ }
+ imgpixels += image->stride;
+ pixels += raster->stride;
+ }
+ if(unlock)
+ raster->unlock(0);
+
+ if(truecolimg)
+ truecolimg->destroy();
+
+ return 1;
+}
+
+Image*
+rasterToImage(Raster *raster)
+{
+ int32 depth;
+ Image *image;
+
+ bool unlock = false;
+ if(raster->pixels == nil){
+ raster->lock(0, Raster::LOCKREAD);
+ unlock = true;
+ }
+
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ if(natras->customFormat){
+ int w = raster->width;
+ int h = raster->height;
+ // pixels are in the upper right corner
+ if(w < 4) w = 4;
+ if(h < 4) h = 4;
+ image = Image::create(w, h, 32);
+ image->allocate();
+ uint8 *pix = raster->pixels;
+ switch(natras->format){
+ case D3DFMT_DXT1:
+ image->setPixelsDXT(1, pix);
+ if((raster->format & 0xF00) == Raster::C565)
+ image->removeMask();
+ break;
+ case D3DFMT_DXT3:
+ image->setPixelsDXT(3, pix);
+ break;
+ case D3DFMT_DXT5:
+ image->setPixelsDXT(5, pix);
+ break;
+ default:
+ image->destroy();
+ if(unlock)
+ raster->unlock(0);
+ return nil;
+ }
+ // fix it up again
+ image->width = raster->width;
+ image->height = raster->height;
+
+ if(unlock)
+ raster->unlock(0);
+ return image;
+ }
+
+ void (*conv)(uint8 *out, uint8 *in) = nil;
+ switch(raster->format & 0xF00){
+ case Raster::C1555:
+ depth = 16;
+ conv = conv_ARGB1555_from_ARGB1555;
+ break;
+ case Raster::C8888:
+ depth = 32;
+ conv = conv_RGBA8888_from_BGRA8888;
+ break;
+ case Raster::C888:
+ depth = 24;
+ conv = conv_RGB888_from_BGR888;
+ break;
+ case Raster::C555:
+ depth = 16;
+ conv = conv_ARGB1555_from_RGB555;
+ break;
+
+ default:
+ case Raster::C565:
+ case Raster::C4444:
+ case Raster::LUM8:
+ RWERROR((ERR_INVRASTER));
+ return nil;
+ }
+ int32 pallength = 0;
+ if((raster->format & Raster::PAL4) == Raster::PAL4){
+ depth = 4;
+ pallength = 16;
+ }else if((raster->format & Raster::PAL8) == Raster::PAL8){
+ depth = 8;
+ pallength = 256;
+ }
+
+ uint8 *in, *out;
+ image = Image::create(raster->width, raster->height, depth);
+ image->allocate();
+
+ if(pallength){
+ out = image->palette;
+ in = (uint8*)natras->palette;
+ for(int32 i = 0; i < pallength; i++){
+ conv_RGBA8888_from_RGBA8888(out, in);
+ in += 4;
+ out += 4;
+ }
+ }
+
+ uint8 *imgpixels = image->pixels;
+ uint8 *pixels = raster->pixels;
+
+ int x, y;
+ assert(image->width == raster->width);
+ assert(image->height == raster->height);
+ for(y = 0; y < image->height; y++){
+ uint8 *imgrow = imgpixels;
+ uint8 *rasrow = pixels;
+ for(x = 0; x < image->width; x++){
+ conv(imgrow, rasrow);
+ imgrow += image->bpp;
+ rasrow += natras->bpp;
+ }
+ imgpixels += image->stride;
+ pixels += raster->stride;
+ }
+ image->compressPalette();
+
+ if(unlock)
+ raster->unlock(0);
+
+ return image;
+}
+
+int32
+getLevelSize(Raster *raster, int32 level)
+{
+ D3dRaster *ras = GETD3DRASTEREXT(raster);
+#ifdef RW_D3D9
+ IDirect3DTexture9 *tex = (IDirect3DTexture9*)ras->texture;
+ D3DSURFACE_DESC desc;
+ tex->GetLevelDesc(level, &desc);
+ return calculateTextureSize(desc.Width, desc.Height, 1, desc.Format);
+#else
+ RasterLevels *levels = (RasterLevels*)ras->texture;
+ return levels->levels[level].size;
+#endif
+}
+
+void
+allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha)
+{
+ static uint32 dxtMap[] = {
+ 0x31545844, // DXT1
+ 0x32545844, // DXT2
+ 0x33545844, // DXT3
+ 0x34545844, // DXT4
+ 0x35545844, // DXT5
+ };
+ D3dRaster *ras = GETD3DRASTEREXT(raster);
+ ras->format = dxtMap[dxt-1];
+ ras->hasAlpha = hasAlpha;
+ ras->customFormat = 1;
+ if(ras->autogenMipmap)
+ numLevels = 0;
+ else if(raster->format & Raster::MIPMAP)
+ {}
+ else
+ numLevels = 1;
+ ras->texture = createTexture(raster->width, raster->height,
+ numLevels,
+ ras->autogenMipmap ? D3DUSAGE_AUTOGENMIPMAP : 0,
+ ras->format);
+ raster->flags &= ~Raster::DONTALLOCATE;
+}
+
+void
+setPalette(Raster *raster, void *palette, int32 size)
+{
+ D3dRaster *ras = GETD3DRASTEREXT(raster);
+ memcpy(ras->palette, palette, 4*size);
+}
+
+void
+setTexels(Raster *raster, void *texels, int32 level)
+{
+ uint8 *dst = raster->lock(level, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ memcpy(dst, texels, getLevelSize(raster, level));
+ raster->unlock(level);
+}
+
+static void*
+createNativeRaster(void *object, int32 offset, int32)
+{
+ D3dRaster *raster = PLUGINOFFSET(D3dRaster, object, offset);
+ raster->texture = nil;
+ raster->palette = nil;
+ raster->lockedSurf = nil;
+ raster->format = 0;
+ raster->hasAlpha = 0;
+ raster->customFormat = 0;
+ return object;
+}
+
+static void*
+destroyNativeRaster(void *object, int32 offset, int32)
+{
+ Raster *raster = (Raster*)object;
+ D3dRaster *natras = PLUGINOFFSET(D3dRaster, raster, offset);
+#ifdef RW_D3D9
+ removeVidmemRaster(raster);
+ evictD3D9Raster(raster);
+#endif
+ switch(raster->type){
+ case Raster::NORMAL:
+ case Raster::TEXTURE:
+ case Raster::CAMERATEXTURE:
+ destroyTexture(natras->texture);
+ break;
+
+ case Raster::ZBUFFER:
+#ifdef RW_D3D9
+ if(raster->flags & Raster::DONTALLOCATE)
+ break;
+ if(natras->texture != d3d9Globals.defaultDepthSurf)
+ ((IDirect3DSurface9*)natras->texture)->Release();
+ natras->texture = nil;
+#endif
+ break;
+ case Raster::CAMERA:
+ break;
+ }
+ rwFree(natras->palette);
+ return object;
+}
+
+static void*
+copyNativeRaster(void *dst, void *, int32 offset, int32)
+{
+ D3dRaster *raster = PLUGINOFFSET(D3dRaster, dst, offset);
+ raster->texture = nil;
+ raster->palette = nil;
+ raster->lockedSurf = nil;
+ raster->format = 0;
+ raster->hasAlpha = 0;
+ raster->customFormat = 0;
+ return dst;
+}
+
+void
+registerNativeRaster(void)
+{
+ nativeRasterOffset = Raster::registerPlugin(sizeof(D3dRaster),
+ ID_RASTERD3D9,
+ createNativeRaster,
+ destroyNativeRaster,
+ copyNativeRaster);
+}
+
+}
+}
diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp
new file mode 100644
index 0000000..671948f
--- /dev/null
+++ b/src/d3d/d3d8.cpp
@@ -0,0 +1,678 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+#include "rwd3d8.h"
+
+#include "rwd3dimpl.h"
+
+#define PLUGIN_ID 2
+
+namespace rw {
+namespace d3d8 {
+using namespace d3d;
+
+static void*
+driverOpen(void *o, int32, int32)
+{
+ engine->driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline();
+
+ engine->driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset;
+ engine->driver[PLATFORM_D3D8]->rasterCreate = rasterCreate;
+ engine->driver[PLATFORM_D3D8]->rasterLock = rasterLock;
+ engine->driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock;
+ engine->driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels;
+ engine->driver[PLATFORM_D3D8]->imageFindRasterFormat = imageFindRasterFormat;
+ engine->driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage;
+ engine->driver[PLATFORM_D3D8]->rasterToImage = rasterToImage;
+ return o;
+}
+
+static void*
+driverClose(void *o, int32, int32)
+{
+ return o;
+}
+
+void
+registerPlatformPlugins(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D8, 0, PLATFORM_D3D8,
+ driverOpen, driverClose);
+ // shared between D3D8 and 9
+ if(nativeRasterOffset == 0)
+ registerNativeRaster();
+}
+
+uint32
+makeFVFDeclaration(uint32 flags, int32 numTex)
+{
+ uint32 fvf = 0x2;
+ if(flags & Geometry::NORMALS)
+ fvf |= 0x10;
+ if(flags & Geometry::PRELIT)
+ fvf |= 0x40;
+ fvf |= numTex << 8;
+ return fvf;
+}
+
+int32
+getStride(uint32 flags, int32 numTex)
+{
+ int32 stride = 12;
+ if(flags & Geometry::NORMALS)
+ stride += 12;;
+ if(flags & Geometry::PRELIT)
+ stride += 4;
+ stride += numTex*8;
+ return stride;
+}
+
+void*
+destroyNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D8)
+ return object;
+ InstanceDataHeader *header =
+ (InstanceDataHeader*)geometry->instData;
+ geometry->instData = nil;
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ destroyIndexBuffer(inst->indexBuffer);
+ destroyVertexBuffer(inst->vertexBuffer);
+ inst++;
+ }
+ rwFree(header->inst);
+ rwFree(header);
+ return object;
+}
+
+Stream*
+readNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ uint32 platform;
+ if(!findChunk(stream, ID_STRUCT, nil, nil)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_D3D8){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ geometry->instData = header;
+ header->platform = PLATFORM_D3D8;
+
+ int32 size = stream->readI32();
+ uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
+ stream->read8(data, size);
+ uint8 *p = data;
+ header->serialNumber = *(uint16*)p; p += 2;
+ header->numMeshes = *(uint16*)p; p += 2;
+ header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ inst->minVert = *(uint32*)p; p += 4;
+ inst->stride = *(uint32*)p; p += 4;
+ inst->numVertices = *(uint32*)p; p += 4;
+ inst->numIndices = *(uint32*)p; p += 4;
+ uint32 matid = *(uint32*)p; p += 4;
+ inst->material = geometry->matList.materials[matid];
+ inst->vertexShader = *(uint32*)p; p += 4;
+ inst->primType = *(uint32*)p; p += 4;
+ inst->indexBuffer = nil; p += 4;
+ inst->vertexBuffer = nil; p += 4;
+ inst->baseIndex = 0; p += 4;
+ inst->vertexAlpha = *p++;
+ inst->managed = 0; p++;
+ inst->remapped = 0; p++; // TODO: really unused? and what's that anyway?
+ inst++;
+ }
+ rwFree(data);
+
+ inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ assert(inst->indexBuffer == nil);
+ inst->indexBuffer = createIndexBuffer(inst->numIndices*2, false);
+ uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
+ stream->read8(indices, 2*inst->numIndices);
+ unlockIndices(inst->indexBuffer);
+
+ inst->managed = 1;
+ assert(inst->vertexBuffer == nil);
+ inst->vertexBuffer = createVertexBuffer(inst->stride*inst->numVertices, 0, false);
+ uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->read8(verts, inst->stride*inst->numVertices);
+ unlockVertices(inst->vertexBuffer);
+
+ inst++;
+ }
+ return stream;
+}
+
+Stream*
+writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ writeChunkHeader(stream, ID_STRUCT, len-12);
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D8)
+ return stream;
+ stream->writeU32(PLATFORM_D3D8);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+
+ int32 size = 4 + geometry->meshHeader->numMeshes*0x2C;
+ uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
+ stream->writeI32(size);
+ uint8 *p = data;
+ *(uint16*)p = header->serialNumber; p += 2;
+ *(uint16*)p = header->numMeshes; p += 2;
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ *(uint32*)p = inst->minVert; p += 4;
+ *(uint32*)p = inst->stride; p += 4;
+ *(uint32*)p = inst->numVertices; p += 4;
+ *(uint32*)p = inst->numIndices; p += 4;
+ int32 matid = geometry->matList.findIndex(inst->material);
+ *(int32*)p = matid; p += 4;
+ *(uint32*)p = inst->vertexShader; p += 4;
+ *(uint32*)p = inst->primType; p += 4;
+ *(uint32*)p = 0; p += 4; // index buffer
+ *(uint32*)p = 0; p += 4; // vertex buffer
+ *(uint32*)p = inst->baseIndex; p += 4;
+ *p++ = inst->vertexAlpha;
+ *p++ = inst->managed;
+ *p++ = inst->remapped;
+ inst++;
+ }
+ stream->write8(data, size);
+ rwFree(data);
+
+ inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
+ stream->write8(indices, 2*inst->numIndices);
+ unlockIndices(inst->indexBuffer);
+
+ uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->write8(verts, inst->stride*inst->numVertices);
+ unlockVertices(inst->vertexBuffer);
+ inst++;
+ }
+ return stream;
+}
+
+int32
+getSizeNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D8)
+ return 0;
+
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ InstanceData *inst = header->inst;
+ int32 size = 12 + 4 + 4 + 4 + header->numMeshes*0x2C;
+ for(int32 i = 0; i < header->numMeshes; i++){
+ size += inst->numIndices*2 + inst->numVertices*inst->stride;
+ inst++;
+ }
+ return size;
+}
+
+void
+registerNativeDataPlugin(void)
+{
+ Geometry::registerPlugin(0, ID_NATIVEDATA,
+ nil, destroyNativeData, nil);
+ Geometry::registerPluginStream(ID_NATIVEDATA,
+ readNativeData,
+ writeNativeData,
+ getSizeNativeData);
+}
+
+
+static void
+instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ // TODO: allow for REINSTANCE
+ if(geo->instData)
+ return;
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ MeshHeader *meshh = geo->meshHeader;
+ geo->instData = header;
+ header->platform = PLATFORM_D3D8;
+
+ header->serialNumber = meshh->serialNum;
+ header->numMeshes = meshh->numMeshes;
+ header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+
+ InstanceData *inst = header->inst;
+ Mesh *mesh = meshh->getMeshes();
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
+ &inst->minVert, &inst->numVertices);
+ inst->numIndices = mesh->numIndices;
+ inst->material = mesh->material;
+ inst->vertexShader = 0;
+ inst->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
+ inst->vertexBuffer = nil;
+ inst->baseIndex = 0; // (maybe) not used by us
+ inst->vertexAlpha = 0;
+ inst->managed = 0;
+ inst->remapped = 0;
+
+ inst->indexBuffer = createIndexBuffer(inst->numIndices*2, false);
+ uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
+ if(inst->minVert == 0)
+ memcpy(indices, mesh->indices, inst->numIndices*2);
+ else
+ for(int32 j = 0; j < inst->numIndices; j++)
+ indices[j] = mesh->indices[j] - inst->minVert;
+ unlockIndices(inst->indexBuffer);
+
+ pipe->instanceCB(geo, inst);
+ mesh++;
+ inst++;
+ }
+}
+
+static void
+uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ if((geo->flags & Geometry::NATIVE) == 0)
+ return;
+ assert(geo->instData != nil);
+ assert(geo->instData->platform == PLATFORM_D3D8);
+ geo->numTriangles = geo->meshHeader->guessNumTriangles();
+ geo->allocateData();
+ geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0);
+
+ InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
+ InstanceData *inst = header->inst;
+ Mesh *mesh = geo->meshHeader->getMeshes();
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
+ if(inst->minVert == 0)
+ memcpy(mesh->indices, indices, inst->numIndices*2);
+ else
+ for(int32 j = 0; j < inst->numIndices; j++)
+ mesh->indices[j] = indices[j] + inst->minVert;
+ unlockIndices(inst->indexBuffer);
+
+ pipe->uninstanceCB(geo, inst);
+ mesh++;
+ inst++;
+ }
+ geo->generateTriangles();
+ geo->flags &= ~Geometry::NATIVE;
+ destroyNativeData(geo, 0, 0);
+}
+
+static void
+render(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ // TODO: allow for REINSTANCE
+ if(geo->instData == nil)
+ pipe->instance(atomic);
+ assert(geo->instData != nil);
+ assert(geo->instData->platform == PLATFORM_D3D8);
+ if(pipe->renderCB)
+ pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
+}
+
+void
+ObjPipeline::init(void)
+{
+ this->rw::ObjPipeline::init(PLATFORM_D3D8);
+ this->impl.instance = d3d8::instance;
+ this->impl.uninstance = d3d8::uninstance;
+ this->impl.render = d3d8::render;
+ this->instanceCB = nil;
+ this->uninstanceCB = nil;
+ this->renderCB = nil;
+}
+
+ObjPipeline*
+ObjPipeline::create(void)
+{
+ ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
+ pipe->init();
+ return pipe;
+}
+
+void
+defaultInstanceCB(Geometry *geo, InstanceData *inst)
+{
+ inst->vertexShader = makeFVFDeclaration(geo->flags, geo->numTexCoordSets);
+ inst->stride = getStride(geo->flags, geo->numTexCoordSets);
+
+ assert(inst->vertexBuffer == nil);
+ inst->vertexBuffer = createVertexBuffer(inst->numVertices*inst->stride,
+ inst->vertexShader, false);
+ inst->managed = 1;
+
+ uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ instV3d(VERT_FLOAT3, dst,
+ &geo->morphTargets[0].vertices[inst->minVert],
+ inst->numVertices, inst->stride);
+ dst += 12;
+
+ if(geo->flags & Geometry::NORMALS){
+ instV3d(VERT_FLOAT3, dst,
+ &geo->morphTargets[0].normals[inst->minVert],
+ inst->numVertices, inst->stride);
+ dst += 12;
+ }
+
+ inst->vertexAlpha = 0;
+ if(geo->flags & Geometry::PRELIT){
+ inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[inst->minVert],
+ inst->numVertices, inst->stride);
+ dst += 4;
+ }
+
+ for(int32 i = 0; i < geo->numTexCoordSets; i++){
+ instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][inst->minVert],
+ inst->numVertices, inst->stride);
+ dst += 8;
+ }
+ unlockVertices(inst->vertexBuffer);
+}
+
+void
+defaultUninstanceCB(Geometry *geo, InstanceData *inst)
+{
+ uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ uninstV3d(VERT_FLOAT3,
+ &geo->morphTargets[0].vertices[inst->minVert],
+ src, inst->numVertices, inst->stride);
+ src += 12;
+
+ if(geo->flags & Geometry::NORMALS){
+ uninstV3d(VERT_FLOAT3,
+ &geo->morphTargets[0].normals[inst->minVert],
+ src, inst->numVertices, inst->stride);
+ src += 12;
+ }
+
+ inst->vertexAlpha = 0;
+ if(geo->flags & Geometry::PRELIT){
+ uninstColor(VERT_ARGB, &geo->colors[inst->minVert], src,
+ inst->numVertices, inst->stride);
+ src += 4;
+ }
+
+ for(int32 i = 0; i < geo->numTexCoordSets; i++){
+ uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][inst->minVert], src,
+ inst->numVertices, inst->stride);
+ src += 8;
+ }
+ unlockVertices(inst->vertexBuffer);
+}
+
+ObjPipeline*
+makeDefaultPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->renderCB = defaultRenderCB;
+ return pipe;
+}
+
+// Native Texture and Raster
+
+// only handles 4 and 8 bit textures right now
+Raster*
+readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels)
+{
+ uint8 palette[256*4];
+ int32 pallen = 0;
+ uint8 *data = nil;
+
+ Image *img = Image::create(width, height, 32);
+ img->allocate();
+
+ if(format & Raster::PAL4){
+ pallen = 16;
+ stream->read8(palette, 4*32);
+ }else if(format & Raster::PAL8){
+ pallen = 256;
+ stream->read8(palette, 4*256);
+ }
+ if(!Raster::formatHasAlpha(format))
+ for(int32 i = 0; i < pallen; i++)
+ palette[i*4+3] = 0xFF;
+
+ Raster *ras = nil;
+
+ for(int i = 0; i < numLevels; i++){
+ uint32 size = stream->readU32();
+
+ // don't read levels that don't exist
+ if(ras && i >= ras->getNumLevels()){
+ stream->seek(size);
+ continue;
+ }
+
+ // one allocation is enough, first level is largest
+ if(data == nil)
+ data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE);
+ stream->read8(data, size);
+
+ if(ras){
+ ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ img->width = ras->width;
+ img->height = ras->height;
+ img->stride = img->width*img->bpp;
+ }
+
+ if(format & (Raster::PAL4 | Raster::PAL8)){
+ uint8 *idx = data;
+ uint8 *pixels = img->pixels;
+ for(int y = 0; y < img->height; y++){
+ uint8 *line = pixels;
+ for(int x = 0; x < img->width; x++){
+ line[0] = palette[*idx*4+0];
+ line[1] = palette[*idx*4+1];
+ line[2] = palette[*idx*4+2];
+ if(img->bpp > 3)
+ line[3] = palette[*idx*4+3];
+ line += img->bpp;
+ idx++;
+ }
+ pixels += img->stride;
+ }
+ }
+
+ if(ras == nil){
+ // Important to have filled the image with data
+ int32 newformat;
+ Raster::imageFindRasterFormat(img, format&7, &width, &height, &depth, &newformat);
+ newformat |= format & (Raster::MIPMAP | Raster::AUTOMIPMAP);
+ ras = Raster::create(width, height, depth, newformat);
+ ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ }
+
+ ras->setFromImage(img);
+ ras->unlock(i);
+ }
+
+ rwFree(data);
+ img->destroy();
+ return ras;
+}
+
+Texture*
+readNativeTexture(Stream *stream)
+{
+ uint32 platform;
+ if(!findChunk(stream, ID_STRUCT, nil, nil)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_D3D8){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ Texture *tex = Texture::create(nil);
+ if(tex == nil)
+ return nil;
+
+ // Texture
+ tex->filterAddressing = stream->readU32();
+ stream->read8(tex->name, 32);
+ stream->read8(tex->mask, 32);
+
+ // Raster
+ uint32 format = stream->readU32();
+ bool32 hasAlpha = stream->readI32();
+ int32 width = stream->readU16();
+ int32 height = stream->readU16();
+ int32 depth = stream->readU8();
+ int32 numLevels = stream->readU8();
+ int32 type = stream->readU8();
+ int32 compression = stream->readU8();
+
+ int32 pallength = 0;
+ if(format & Raster::PAL4 || format & Raster::PAL8){
+ pallength = format & Raster::PAL4 ? 32 : 256;
+ if(!d3d::isP8supported){
+ tex->raster = readAsImage(stream, width, height, depth, format|type, numLevels);
+ return tex;
+ }
+ }
+
+ Raster *raster;
+ D3dRaster *ras;
+ if(compression){
+ raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_D3D8);
+ ras = GETD3DRASTEREXT(raster);
+ allocateDXT(raster, compression, numLevels, hasAlpha);
+ ras->customFormat = 1;
+ }else{
+ raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D8);
+ ras = GETD3DRASTEREXT(raster);
+ }
+ tex->raster = raster;
+
+ // TODO: check if format supported and convert if necessary
+
+ if(pallength != 0)
+ stream->read8(ras->palette, 4*pallength);
+
+ uint32 size;
+ uint8 *data;
+ for(int32 i = 0; i < numLevels; i++){
+ size = stream->readU32();
+ if(i < raster->getNumLevels()){
+ data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ stream->read8(data, size);
+ raster->unlock(i);
+ }else
+ stream->seek(size);
+ }
+ return tex;
+}
+
+void
+writeNativeTexture(Texture *tex, Stream *stream)
+{
+ int32 chunksize = getSizeNativeTexture(tex);
+ writeChunkHeader(stream, ID_STRUCT, chunksize-12);
+ stream->writeU32(PLATFORM_D3D8);
+
+ // Texture
+ stream->writeU32(tex->filterAddressing);
+ stream->write8(tex->name, 32);
+ stream->write8(tex->mask, 32);
+
+ // Raster
+ Raster *raster = tex->raster;
+ D3dRaster *ras = GETD3DRASTEREXT(raster);
+ int32 numLevels = raster->getNumLevels();
+ stream->writeI32(raster->format);
+ stream->writeI32(ras->hasAlpha);
+ stream->writeU16(raster->width);
+ stream->writeU16(raster->height);
+ stream->writeU8(raster->depth);
+ stream->writeU8(numLevels);
+ stream->writeU8(raster->type);
+ int32 compression = 0;
+ if(ras->format)
+ switch(ras->format){
+ case 0x31545844: // DXT1
+ compression = 1;
+ break;
+ case 0x32545844: // DXT2
+ compression = 2;
+ break;
+ case 0x33545844: // DXT3
+ compression = 3;
+ break;
+ case 0x34545844: // DXT4
+ compression = 4;
+ break;
+ case 0x35545844: // DXT5
+ compression = 5;
+ break;
+ }
+ stream->writeU8(compression);
+
+ if(raster->format & Raster::PAL4)
+ stream->write8(ras->palette, 4*32);
+ else if(raster->format & Raster::PAL8)
+ stream->write8(ras->palette, 4*256);
+
+ uint32 size;
+ uint8 *data;
+ for(int32 i = 0; i < numLevels; i++){
+ size = getLevelSize(raster, i);
+ stream->writeU32(size);
+ data = raster->lock(i, Raster::LOCKREAD);
+ stream->write8(data, size);
+ raster->unlock(i);
+ }
+}
+
+uint32
+getSizeNativeTexture(Texture *tex)
+{
+ uint32 size = 12 + 72 + 16;
+ int32 levels = tex->raster->getNumLevels();
+ if(tex->raster->format & Raster::PAL4)
+ size += 4*32;
+ else if(tex->raster->format & Raster::PAL8)
+ size += 4*256;
+ for(int32 i = 0; i < levels; i++)
+ size += 4 + getLevelSize(tex->raster, i);
+ return size;
+}
+
+}
+}
diff --git a/src/d3d/d3d8matfx.cpp b/src/d3d/d3d8matfx.cpp
new file mode 100644
index 0000000..580203e
--- /dev/null
+++ b/src/d3d/d3d8matfx.cpp
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwd3d.h"
+#include "rwd3d8.h"
+
+namespace rw {
+namespace d3d8 {
+using namespace d3d;
+
+static void*
+matfxOpen(void *o, int32, int32)
+{
+ matFXGlobals.pipelines[PLATFORM_D3D8] = makeMatFXPipeline();
+ return o;
+}
+
+static void*
+matfxClose(void *o, int32, int32)
+{
+ ((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_D3D8])->destroy();
+ matFXGlobals.pipelines[PLATFORM_D3D8] = nil;
+ return o;
+}
+
+void
+initMatFX(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D8, 0, ID_MATFX,
+ matfxOpen, matfxClose);
+}
+
+ObjPipeline*
+makeMatFXPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->renderCB = defaultRenderCB;
+ pipe->pluginID = ID_MATFX;
+ pipe->pluginData = 0;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/d3d8render.cpp b/src/d3d/d3d8render.cpp
new file mode 100644
index 0000000..c5375cb
--- /dev/null
+++ b/src/d3d/d3d8render.cpp
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+#include "rwd3d8.h"
+
+namespace rw {
+namespace d3d8 {
+using namespace d3d;
+
+#ifndef RW_D3D9
+void defaultRenderCB(Atomic*, InstanceDataHeader*) {}
+#else
+
+// This is a bit abandoned, use d3d9 instead
+
+void
+defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
+{
+ RawMatrix world;
+
+ d3d::lightingCB_Fix(atomic);
+
+ uint32 flags = atomic->geometry->flags;
+ d3d::setRenderState(D3DRS_LIGHTING, !!(flags & rw::Geometry::LIGHT));
+
+ Frame *f = atomic->getFrame();
+ convMatrix(&world, f->getLTM());
+ d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ d3d::setTexture(0, inst->material->texture);
+ d3d::setMaterial(flags, inst->material->color, inst->material->surfaceProps);
+
+
+ d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
+ d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
+ if(flags & Geometry::PRELIT)
+ d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
+ else
+ d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
+
+ d3ddevice->SetFVF(inst->vertexShader);
+ setStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride);
+ setIndices((IDirect3DIndexBuffer9*)inst->indexBuffer);
+ uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3;
+ d3d::flushCache();
+ d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex,
+ 0, inst->numVertices, 0, numPrim);
+ inst++;
+ }
+}
+
+#endif
+}
+}
diff --git a/src/d3d/d3d8skin.cpp b/src/d3d/d3d8skin.cpp
new file mode 100644
index 0000000..d9b0921
--- /dev/null
+++ b/src/d3d/d3d8skin.cpp
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwd3d.h"
+#include "rwd3d8.h"
+
+namespace rw {
+namespace d3d8 {
+using namespace d3d;
+
+static void*
+skinOpen(void *o, int32, int32)
+{
+ skinGlobals.pipelines[PLATFORM_D3D8] = makeSkinPipeline();
+ return o;
+}
+
+static void*
+skinClose(void *o, int32, int32)
+{
+ ((ObjPipeline*)skinGlobals.pipelines[PLATFORM_D3D8])->destroy();
+ skinGlobals.pipelines[PLATFORM_D3D8] = nil;
+ return o;
+}
+
+void
+initSkin(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D8, 0, ID_SKIN,
+ skinOpen, skinClose);
+}
+
+ObjPipeline*
+makeSkinPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->renderCB = defaultRenderCB;
+ pipe->pluginID = ID_SKIN;
+ pipe->pluginData = 1;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp
new file mode 100644
index 0000000..851397b
--- /dev/null
+++ b/src/d3d/d3d9.cpp
@@ -0,0 +1,853 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+#include "rwd3d9.h"
+
+#include "rwd3dimpl.h"
+
+#define PLUGIN_ID 2
+
+namespace rw {
+namespace d3d9 {
+using namespace d3d;
+
+// TODO: move to header, but not as #define
+#ifndef RW_D3D9
+static VertexElement _d3ddec_end = {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0};
+#define D3DDECL_END() _d3ddec_end
+#endif
+
+#define NUMDECLELT 12
+
+static void*
+driverOpen(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ createDefaultShaders();
+#endif
+ engine->driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline();
+
+ engine->driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset;
+ engine->driver[PLATFORM_D3D9]->rasterCreate = rasterCreate;
+ engine->driver[PLATFORM_D3D9]->rasterLock = rasterLock;
+ engine->driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock;
+ engine->driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels;
+ engine->driver[PLATFORM_D3D9]->imageFindRasterFormat = imageFindRasterFormat;
+ engine->driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage;
+ engine->driver[PLATFORM_D3D9]->rasterToImage = rasterToImage;
+ return o;
+}
+
+static void*
+driverClose(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ destroyDefaultShaders();
+#endif
+ return o;
+}
+
+void
+registerPlatformPlugins(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D9, 0, PLATFORM_D3D9,
+ driverOpen, driverClose);
+ // shared between D3D8 and 9
+ if(nativeRasterOffset == 0)
+ registerNativeRaster();
+}
+
+void*
+createVertexDeclaration(VertexElement *elements)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexDeclaration9 *decl = 0;
+ d3ddevice->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl);
+ if(decl)
+ d3d9Globals.numVertexDeclarations++;
+ return decl;
+#else
+ int n = 0;
+ VertexElement *e = (VertexElement*)elements;
+ while(e[n++].stream != 0xFF)
+ ;
+ e = rwNewT(VertexElement, n, MEMDUR_EVENT | ID_DRIVER);
+ memcpy(e, elements, n*sizeof(VertexElement));
+ return e;
+#endif
+}
+
+void
+destroyVertexDeclaration(void *declaration)
+{
+#ifdef RW_D3D9
+ if(declaration){
+ if(((IUnknown*)declaration)->Release() != 0)
+ printf("declaration wasn't destroyed\n");
+ d3d9Globals.numVertexDeclarations--;
+ }
+#else
+ rwFree(declaration);
+#endif
+}
+
+uint32
+getDeclaration(void *declaration, VertexElement *elements)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexDeclaration9 *decl = (IDirect3DVertexDeclaration9*)declaration;
+ UINT numElt;
+ decl->GetDeclaration((D3DVERTEXELEMENT9*)elements, &numElt);
+ return numElt;
+#else
+ int n = 0;
+ VertexElement *e = (VertexElement*)declaration;
+ while(e[n++].stream != 0xFF)
+ ;
+ if(elements)
+ memcpy(elements, declaration, n*sizeof(VertexElement));
+ return n;
+#endif
+}
+
+void
+freeInstanceData(Geometry *geometry)
+{
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D9)
+ return;
+ InstanceDataHeader *header =
+ (InstanceDataHeader*)geometry->instData;
+ geometry->instData = nil;
+ destroyVertexDeclaration(header->vertexDeclaration);
+ destroyIndexBuffer(header->indexBuffer);
+ destroyVertexBuffer(header->vertexStream[0].vertexBuffer);
+ destroyVertexBuffer(header->vertexStream[1].vertexBuffer);
+ rwFree(header->inst);
+ rwFree(header);
+ return;
+}
+
+
+void*
+destroyNativeData(void *object, int32, int32)
+{
+ freeInstanceData((Geometry*)object);
+ return object;
+}
+
+Stream*
+readNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ uint32 platform;
+ if(!findChunk(stream, ID_STRUCT, nil, nil)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_D3D9){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ geometry->instData = header;
+ header->platform = PLATFORM_D3D9;
+
+ int32 size = stream->readI32();
+ uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
+ stream->read8(data, size);
+ uint8 *p = data;
+ header->serialNumber = *(uint32*)p; p += 4;
+ header->numMeshes = *(uint32*)p; p += 4;
+ header->indexBuffer = nil; p += 4;
+ header->primType = *(uint32*)p; p += 4;
+ p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
+ header->useOffsets = *(bool32*)p; p += 4;
+ header->vertexDeclaration = nil; p += 4;
+ header->totalNumIndex = *(uint32*)p; p += 4;
+ header->totalNumVertex = *(uint32*)p; p += 4;
+ header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ inst->numIndex = *(uint32*)p; p += 4;
+ inst->minVert = *(uint32*)p; p += 4;
+ uint32 matid = *(uint32*)p; p += 4;
+ inst->material = geometry->matList.materials[matid];
+ inst->vertexAlpha = *(bool32*)p; p += 4;
+ inst->vertexShader = nil; p += 4;
+ inst->baseIndex = 0; p += 4;
+ inst->numVertices = *(uint32*)p; p += 4;
+ inst->startIndex = *(uint32*)p; p += 4;
+ inst->numPrimitives = *(uint32*)p; p += 4;
+ inst++;
+ }
+
+ VertexElement elements[NUMDECLELT];
+ uint32 numDeclarations = stream->readU32();
+ stream->read8(elements, numDeclarations*8);
+ header->vertexDeclaration = createVertexDeclaration(elements);
+
+ assert(header->indexBuffer == nil);
+ header->indexBuffer = createIndexBuffer(header->totalNumIndex*2, false);
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ stream->read8(indices, 2*header->totalNumIndex);
+ unlockIndices(header->indexBuffer);
+
+ VertexStream *s;
+ p = data;
+ for(int i = 0; i < 2; i++){
+ stream->read8(p, 16);
+ s = &header->vertexStream[i];
+ s->vertexBuffer = (void*)(uintptr)*(uint32*)p; p += 4;
+ s->offset = 0; p += 4;
+ s->stride = *(uint32*)p; p += 4;
+ s->geometryFlags = *(uint16*)p; p += 2;
+ s->managed = *p++;
+ s->dynamicLock = *p++;
+
+ if(s->vertexBuffer == nil)
+ continue;
+ // TODO: use dynamic VB when doing morphing
+ assert(s->vertexBuffer == nil);
+ s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, 0, false);
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->read8(verts, s->stride*header->totalNumVertex);
+ unlockVertices(s->vertexBuffer);
+ }
+
+ // TODO: somehow depends on number of streams used (baseIndex = minVert when more than one)
+ inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ inst->baseIndex = inst->minVert + header->vertexStream[0].offset / header->vertexStream[0].stride;
+ inst++;
+ }
+
+ rwFree(data);
+ return stream;
+}
+
+Stream*
+writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ writeChunkHeader(stream, ID_STRUCT, len-12);
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D9)
+ return stream;
+ stream->writeU32(PLATFORM_D3D9);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ int32 size = 64 + geometry->meshHeader->numMeshes*36;
+ uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
+ stream->writeI32(size);
+
+ uint8 *p = data;
+ *(uint32*)p = header->serialNumber; p += 4;
+ *(uint32*)p = header->numMeshes; p += 4;
+ p += 4; // skip index buffer
+ *(uint32*)p = header->primType; p += 4;
+ p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
+ *(bool32*)p = header->useOffsets; p += 4;
+ p += 4; // skip vertex declaration
+ *(uint32*)p = header->totalNumIndex; p += 4;
+ *(uint32*)p = header->totalNumVertex; p += 4;
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ *(uint32*)p = inst->numIndex; p += 4;
+ *(uint32*)p = inst->minVert; p += 4;
+ int32 matid = geometry->matList.findIndex(inst->material);
+ *(int32*)p = matid; p += 4;
+ *(bool32*)p = inst->vertexAlpha; p += 4;
+ *(uint32*)p = 0; p += 4; // vertex shader
+ *(uint32*)p = inst->baseIndex; p += 4; // not used but meh...
+ *(uint32*)p = inst->numVertices; p += 4;
+ *(uint32*)p = inst->startIndex; p += 4;
+ *(uint32*)p = inst->numPrimitives; p += 4;
+ inst++;
+ }
+ stream->write8(data, size);
+
+ VertexElement elements[NUMDECLELT];
+ uint32 numElt = getDeclaration(header->vertexDeclaration, elements);
+ stream->writeU32(numElt);
+ stream->write8(elements, 8*numElt);
+
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ stream->write8(indices, 2*header->totalNumIndex);
+ unlockIndices(header->indexBuffer);
+
+ VertexStream *s;
+ for(int i = 0; i < 2; i++){
+ s = &header->vertexStream[i];
+ p = data;
+ *(uint32*)p = s->vertexBuffer ? 0xbadeaffe : 0; p += 4;
+ *(uint32*)p = s->offset; p += 4;
+ *(uint32*)p = s->stride; p += 4;
+ *(uint16*)p = s->geometryFlags; p += 2;
+ *p++ = s->managed;
+ *p++ = s->dynamicLock;
+ stream->write8(data, 16);
+
+ if(s->vertexBuffer == nil)
+ continue;
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->write8(verts, s->stride*header->totalNumVertex);
+ unlockVertices(s->vertexBuffer);
+ }
+
+ rwFree(data);
+ return stream;
+}
+
+int32
+getSizeNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_D3D9)
+ return 0;
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ int32 size = 12 + 4 + 4 + 64 + header->numMeshes*36;
+ uint32 numElt = getDeclaration(header->vertexDeclaration, nil);
+ size += 4 + numElt*8;
+ size += 2*header->totalNumIndex;
+ size += 0x10 + header->vertexStream[0].stride*header->totalNumVertex;
+ size += 0x10 + header->vertexStream[1].stride*header->totalNumVertex;
+ return size;
+}
+
+void
+registerNativeDataPlugin(void)
+{
+ Geometry::registerPlugin(0, ID_NATIVEDATA,
+ nil, destroyNativeData, nil);
+ Geometry::registerPluginStream(ID_NATIVEDATA,
+ readNativeData,
+ writeNativeData,
+ getSizeNativeData);
+}
+
+static InstanceDataHeader*
+instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo)
+{
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ MeshHeader *meshh = geo->meshHeader;
+ header->platform = PLATFORM_D3D9;
+
+ header->serialNumber = meshh->serialNum;
+ header->numMeshes = meshh->numMeshes;
+ header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
+ header->useOffsets = 0;
+ header->vertexDeclaration = nil;
+ header->totalNumVertex = geo->numVertices;
+ header->totalNumIndex = meshh->totalIndices;
+ header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+
+ header->indexBuffer = createIndexBuffer(header->totalNumIndex*2, false);
+
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ InstanceData *inst = header->inst;
+ Mesh *mesh = meshh->getMeshes();
+ uint32 startindex = 0;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
+ &inst->minVert, (int32*)&inst->numVertices);
+ inst->numIndex = mesh->numIndices;
+ inst->material = mesh->material;
+ inst->vertexAlpha = 0;
+ inst->vertexShader = nil;
+ inst->baseIndex = inst->minVert;
+ inst->startIndex = startindex;
+ inst->numPrimitives = header->primType == D3DPT_TRIANGLESTRIP ? inst->numIndex-2 : inst->numIndex/3;
+ if(inst->minVert == 0)
+ memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*2);
+ else
+ for(uint32 j = 0; j < inst->numIndex; j++)
+ indices[inst->startIndex+j] = mesh->indices[j] - inst->minVert;
+ startindex += inst->numIndex;
+ mesh++;
+ inst++;
+ }
+ unlockIndices(header->indexBuffer);
+
+ memset(&header->vertexStream, 0, 2*sizeof(VertexStream));
+
+ return header;
+}
+
+static void
+instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ // don't try to (re)instance native data
+ if(geo->flags & Geometry::NATIVE)
+ return;
+
+ InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
+ if(geo->instData){
+ // Already have instanced data, so check if we have to reinstance
+ assert(header->platform == PLATFORM_D3D9);
+ if(header->serialNumber != geo->meshHeader->serialNum){
+ // Mesh changed, so reinstance everything
+ freeInstanceData(geo);
+ }
+ }
+
+ // no instance or complete reinstance
+ if(geo->instData == nil){
+ geo->instData = instanceMesh(rwpipe, geo);
+ pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0);
+ }else if(geo->lockedSinceInst)
+ pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1);
+
+ geo->lockedSinceInst = 0;
+}
+
+static void
+uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ if((geo->flags & Geometry::NATIVE) == 0)
+ return;
+ assert(geo->instData != nil);
+ assert(geo->instData->platform == PLATFORM_D3D9);
+ geo->numTriangles = geo->meshHeader->guessNumTriangles();
+ geo->allocateData();
+ geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0);
+
+ InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ InstanceData *inst = header->inst;
+ Mesh *mesh = geo->meshHeader->getMeshes();
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ if(inst->minVert == 0)
+ memcpy(mesh->indices, &indices[inst->startIndex], inst->numIndex*2);
+ else
+ for(uint32 j = 0; j < inst->numIndex; j++)
+ mesh->indices[j] = indices[inst->startIndex+j] + inst->minVert;
+ mesh++;
+ inst++;
+ }
+ unlockIndices(header->indexBuffer);
+
+ pipe->uninstanceCB(geo, header);
+ geo->generateTriangles();
+ geo->flags &= ~Geometry::NATIVE;
+ destroyNativeData(geo, 0, 0);
+}
+
+static void
+render(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ pipe->instance(atomic);
+ assert(geo->instData != nil);
+ assert(geo->instData->platform == PLATFORM_D3D9);
+ if(pipe->renderCB)
+ pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
+}
+
+void
+ObjPipeline::init(void)
+{
+ this->rw::ObjPipeline::init(PLATFORM_D3D9);
+ this->impl.instance = d3d9::instance;
+ this->impl.uninstance = d3d9::uninstance;
+ this->impl.render = d3d9::render;
+ this->instanceCB = nil;
+ this->uninstanceCB = nil;
+ this->renderCB = nil;
+}
+
+ObjPipeline*
+ObjPipeline::create(void)
+{
+ ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
+ pipe->init();
+ return pipe;
+}
+
+void
+defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
+{
+ int i = 0;
+ VertexElement dcl[NUMDECLELT];
+ VertexStream *s = &header->vertexStream[0];
+
+ bool isPrelit = (geo->flags & Geometry::PRELIT) != 0;
+ bool hasNormals = (geo->flags & Geometry::NORMALS) != 0;
+
+ // TODO: support both vertex buffers
+
+ if(!reinstance){
+ // Create declarations and buffers only the first time
+
+ assert(s->vertexBuffer == nil);
+ s->offset = 0;
+ s->managed = 1;
+ s->geometryFlags = 0;
+ s->dynamicLock = 0;
+
+ dcl[i].stream = 0;
+ dcl[i].offset = 0;
+ dcl[i].type = D3DDECLTYPE_FLOAT3;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_POSITION;
+ dcl[i].usageIndex = 0;
+ i++;
+ uint16 stride = 12;
+ s->geometryFlags |= 0x2;
+
+ if(isPrelit){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_D3DCOLOR;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_COLOR;
+ dcl[i].usageIndex = 0;
+ i++;
+ s->geometryFlags |= 0x8;
+ stride += 4;
+ }
+
+ for(int32 n = 0; n < geo->numTexCoordSets; n++){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_FLOAT2;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_TEXCOORD;
+ dcl[i].usageIndex = (uint8)n;
+ i++;
+ s->geometryFlags |= 0x10 << n;
+ stride += 8;
+ }
+
+ if(hasNormals){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_FLOAT3;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_NORMAL;
+ dcl[i].usageIndex = 0;
+ i++;
+ s->geometryFlags |= 0x4;
+ stride += 12;
+ }
+
+ // We expect some attributes to always be there, use the constant buffer as fallback
+ if(!isPrelit){
+ dcl[i].stream = 2;
+ dcl[i].offset = offsetof(VertexConstantData, color);
+ dcl[i].type = D3DDECLTYPE_D3DCOLOR;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_COLOR;
+ dcl[i].usageIndex = 0;
+ i++;
+ }
+ if(geo->numTexCoordSets == 0){
+ dcl[i].stream = 2;
+ dcl[i].offset = offsetof(VertexConstantData, texCoors[0]);
+ dcl[i].type = D3DDECLTYPE_FLOAT2;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_TEXCOORD;
+ dcl[i].usageIndex = 0;
+ i++;
+ }
+
+ dcl[i] = D3DDECL_END();
+ s->stride = stride;
+
+ assert(header->vertexDeclaration == nil);
+ header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
+
+ assert(s->vertexBuffer == nil);
+ s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, false);
+ }else
+ getDeclaration(header->vertexDeclaration, dcl);
+
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+
+ // Instance vertices
+ if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].vertices,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ // Instance prelight colors
+ if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
+ ;
+ InstanceData *inst = header->inst;
+ uint32 n = header->numMeshes;
+ while(n--){
+ uint32 stride = header->vertexStream[dcl[i].stream].stride;
+ inst->vertexAlpha = instColor(vertFormatMap[dcl[i].type],
+ verts + dcl[i].offset + stride*inst->minVert,
+ geo->colors + inst->minVert,
+ inst->numVertices,
+ stride);
+ inst++;
+ }
+ }
+
+ // Instance tex coords
+ for(int32 n = 0; n < geo->numTexCoordSets; n++){
+ if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
+ ;
+ instTexCoords(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->texCoords[n],
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+ }
+
+ // Instance normals
+ if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].normals,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+ unlockVertices(s->vertexBuffer);
+}
+
+void
+defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ VertexElement dcl[NUMDECLELT];
+
+ uint8 *verts[2];
+ verts[0] = lockVertices(header->vertexStream[0].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ verts[1] = lockVertices(header->vertexStream[1].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ getDeclaration(header->vertexDeclaration, dcl);
+
+ int i;
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
+ ;
+ uninstV3d(vertFormatMap[dcl[i].type],
+ geo->morphTargets[0].vertices,
+ verts[dcl[i].stream] + dcl[i].offset,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+
+ if(geo->flags & Geometry::PRELIT){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
+ ;
+ uninstColor(vertFormatMap[dcl[i].type],
+ geo->colors,
+ verts[dcl[i].stream] + dcl[i].offset,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ for(int32 n = 0; n < geo->numTexCoordSets; n++){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
+ ;
+ uninstTexCoords(vertFormatMap[dcl[i].type],
+ geo->texCoords[n],
+ verts[dcl[i].stream] + dcl[i].offset,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ if(geo->flags & Geometry::NORMALS){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
+ ;
+ uninstV3d(vertFormatMap[dcl[i].type],
+ geo->morphTargets[0].normals,
+ verts[dcl[i].stream] + dcl[i].offset,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ unlockVertices(verts[0]);
+ unlockVertices(verts[1]);
+}
+
+ObjPipeline*
+makeDefaultPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->renderCB = defaultRenderCB_Shader;
+ return pipe;
+}
+
+// Native Texture and Raster
+
+Texture*
+readNativeTexture(Stream *stream)
+{
+ uint32 platform;
+ if(!findChunk(stream, ID_STRUCT, nil, nil)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_D3D9){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ Texture *tex = Texture::create(nil);
+ if(tex == nil)
+ return nil;
+
+ // Texture
+ tex->filterAddressing = stream->readU32();
+ stream->read8(tex->name, 32);
+ stream->read8(tex->mask, 32);
+
+ // Raster
+ int32 format = stream->readI32();
+ int32 d3dformat = stream->readI32();
+ int32 width = stream->readU16();
+ int32 height = stream->readU16();
+ int32 depth = stream->readU8();
+ int32 numLevels = stream->readU8();
+ int32 type = stream->readU8();
+/*
+#define HAS_ALPHA (1<<0)
+#define IS_CUBE (1<<1)
+#define USE_AUTOMIPMAPGEN (1<<2)
+#define IS_COMPRESSED (1<<3)
+*/
+ int32 flags = stream->readU8();
+
+ Raster *raster;
+ D3dRaster *ext;
+
+ if(flags & 8){
+ // is compressed
+ assert((flags & 2) == 0 && "Can't have cube maps yet");
+ raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_D3D9);
+ assert(raster);
+ ext = GETD3DRASTEREXT(raster);
+ ext->format = d3dformat;
+ ext->hasAlpha = flags & 1;
+ ext->texture = createTexture(raster->width, raster->height,
+ raster->format & Raster::MIPMAP ? numLevels : 1,
+ 0,
+ ext->format);
+ assert(ext->texture);
+ raster->flags &= ~Raster::DONTALLOCATE;
+ ext->customFormat = 1;
+ }else if(flags & 2){
+ assert(0 && "Can't have cube maps yet");
+ }else{
+ raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D9);
+ assert(raster);
+ ext = GETD3DRASTEREXT(raster);
+ }
+ tex->raster = raster;
+
+ // TODO: check if format supported and convert if necessary
+
+ if(raster->format & Raster::PAL4)
+ stream->read8(ext->palette, 4*32);
+ else if(raster->format & Raster::PAL8)
+ stream->read8(ext->palette, 4*256);
+
+ uint32 size;
+ uint8 *data;
+ for(int32 i = 0; i < numLevels; i++){
+ size = stream->readU32();
+ if(i < raster->getNumLevels()){
+ data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ stream->read8(data, size);
+ raster->unlock(i);
+ }else
+ stream->seek(size);
+ }
+ return tex;
+}
+
+void
+writeNativeTexture(Texture *tex, Stream *stream)
+{
+ int32 chunksize = getSizeNativeTexture(tex);
+ writeChunkHeader(stream, ID_STRUCT, chunksize-12);
+ stream->writeU32(PLATFORM_D3D9);
+
+ // Texture
+ stream->writeU32(tex->filterAddressing);
+ stream->write8(tex->name, 32);
+ stream->write8(tex->mask, 32);
+
+ // Raster
+ Raster *raster = tex->raster;
+ D3dRaster *ext = GETD3DRASTEREXT(raster);
+ int32 numLevels = raster->getNumLevels();
+ stream->writeI32(raster->format);
+ stream->writeU32(ext->format);
+ stream->writeU16(raster->width);
+ stream->writeU16(raster->height);
+ stream->writeU8(raster->depth);
+ stream->writeU8(numLevels);
+ stream->writeU8(raster->type);
+ uint8 flags = 0;
+ if(ext->hasAlpha)
+ flags |= 1;
+ // no cube supported yet
+ if(ext->autogenMipmap)
+ flags |= 4;
+ if(ext->customFormat)
+ flags |= 8;
+ stream->writeU8(flags);
+
+ if(raster->format & Raster::PAL4)
+ stream->write8(ext->palette, 4*32);
+ else if(raster->format & Raster::PAL8)
+ stream->write8(ext->palette, 4*256);
+
+ uint32 size;
+ uint8 *data;
+ for(int32 i = 0; i < numLevels; i++){
+ size = getLevelSize(raster, i);
+ stream->writeU32(size);
+ data = raster->lock(i, Raster::LOCKREAD);
+ stream->write8(data, size);
+ raster->unlock(i);
+ }
+}
+
+uint32
+getSizeNativeTexture(Texture *tex)
+{
+ uint32 size = 12 + 72 + 16;
+ int32 levels = tex->raster->getNumLevels();
+ if(tex->raster->format & Raster::PAL4)
+ size += 4*32;
+ else if(tex->raster->format & Raster::PAL8)
+ size += 4*256;
+ for(int32 i = 0; i < levels; i++)
+ size += 4 + getLevelSize(tex->raster, i);
+ return size;
+}
+
+}
+}
diff --git a/src/d3d/d3d9matfx.cpp b/src/d3d/d3d9matfx.cpp
new file mode 100644
index 0000000..d544e65
--- /dev/null
+++ b/src/d3d/d3d9matfx.cpp
@@ -0,0 +1,313 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwrender.h"
+#include "../rwplugins.h"
+#include "rwd3d.h"
+#include "rwd3d9.h"
+
+namespace rw {
+namespace d3d9 {
+using namespace d3d;
+
+#ifndef RW_D3D9
+void matfxRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) {}
+#else
+
+static void *matfx_env_amb_VS;
+static void *matfx_env_amb_dir_VS;
+static void *matfx_env_all_VS;
+static void *matfx_env_PS;
+static void *matfx_env_tex_PS;
+
+enum
+{
+ VSLOC_texMat = VSLOC_afterLights,
+ VSLOC_colorClamp = VSLOC_texMat + 4,
+ VSLOC_envColor,
+
+ PSLOC_shininess = 1,
+};
+
+void
+matfxRender_Default(InstanceDataHeader *header, InstanceData *inst, int32 lightBits)
+{
+ Material *m = inst->material;
+
+ // Pick a shader
+ if((lightBits & VSLIGHT_MASK) == 0)
+ setVertexShader(default_amb_VS);
+ else if((lightBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
+ setVertexShader(default_amb_dir_VS);
+ else
+ setVertexShader(default_all_VS);
+
+ SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
+
+ if(inst->material->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(default_tex_PS);
+ }else
+ setPixelShader(default_PS);
+
+ drawInst(header, inst);
+}
+
+static Frame *lastEnvFrame;
+
+static RawMatrix normal2texcoord = {
+ { 0.5f, 0.0f, 0.0f }, 0.0f,
+ { 0.0f, -0.5f, 0.0f }, 0.0f,
+ { 0.0f, 0.0f, 1.0f }, 0.0f,
+ { 0.5f, 0.5f, 0.0f }, 1.0f
+};
+
+void
+uploadEnvMatrix(Frame *frame)
+{
+ Matrix invMat;
+ if(frame == nil)
+ frame = engine->currentCamera->getFrame();
+
+ // cache the matrix across multiple meshes
+// can't do it, frame matrix may change
+// if(frame == lastEnvFrame)
+// return;
+// lastEnvFrame = frame;
+
+ RawMatrix envMtx, invMtx;
+ Matrix::invert(&invMat, frame->getLTM());
+ convMatrix(&invMtx, &invMat);
+ invMtx.pos.set(0.0f, 0.0f, 0.0f);
+ float uscale = fabs(normal2texcoord.right.x);
+ normal2texcoord.right.x = MatFX::envMapFlipU ? -uscale : uscale;
+ RawMatrix::mult(&envMtx, &invMtx, &normal2texcoord);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_texMat, (float*)&envMtx, 4);
+}
+
+void
+matfxRender_EnvMap(InstanceDataHeader *header, InstanceData *inst, int32 lightBits, MatFX::Env *env)
+{
+ Material *m = inst->material;
+
+ if(env->tex == nil || env->coefficient == 0.0f){
+ matfxRender_Default(header, inst, lightBits);
+ return;
+ }
+
+ d3d::setTexture(1, env->tex);
+ uploadEnvMatrix(env->frame);
+
+ SetRenderState(SRCBLEND, BLENDONE);
+
+ static float zero[4];
+ static float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ struct {
+ float shininess;
+ float disableFBA;
+ float unused[2];
+ } fxparams;
+ fxparams.shininess = env->coefficient;
+ fxparams.disableFBA = env->fbAlpha ? 0.0f : 1.0f;
+ d3ddevice->SetPixelShaderConstantF(PSLOC_shininess, (float*)&fxparams, 1);
+ // This clamps the vertex color below. With it we can achieve both PC and PS2 style matfx
+ if(MatFX::envMapApplyLight)
+ d3ddevice->SetVertexShaderConstantF(VSLOC_colorClamp, zero, 1);
+ else
+ d3ddevice->SetVertexShaderConstantF(VSLOC_colorClamp, one, 1);
+ RGBAf envcol[4];
+ if(MatFX::envMapUseMatColor)
+ convColor(envcol, &m->color);
+ else
+ convColor(envcol, &MatFX::envMapColor);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_envColor, (float*)&envcol, 1);
+
+ // Pick a shader
+ if((lightBits & VSLIGHT_MASK) == 0)
+ setVertexShader(matfx_env_amb_VS);
+ else if((lightBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
+ setVertexShader(matfx_env_amb_dir_VS);
+ else
+ setVertexShader(matfx_env_all_VS);
+
+ bool32 texAlpha = GETD3DRASTEREXT(env->tex->raster)->hasAlpha;
+
+ if(inst->material->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(matfx_env_tex_PS);
+ }else
+ setPixelShader(matfx_env_PS);
+
+ SetRenderState(VERTEXALPHA, texAlpha || inst->vertexAlpha || m->color.alpha != 255);
+
+ drawInst(header, inst);
+
+ SetRenderState(SRCBLEND, BLENDSRCALPHA);
+}
+
+void
+matfxRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header)
+{
+ int vsBits;
+ uint32 flags = atomic->geometry->flags;
+ setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
+ 0, header->vertexStream[0].stride);
+ setIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
+ setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);
+
+ lastEnvFrame = nil;
+
+ vsBits = lightingCB_Shader(atomic);
+ uploadMatrices(atomic->getFrame()->getLTM());
+
+ bool normals = !!(atomic->geometry->flags & Geometry::NORMALS);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ Material *m = inst->material;
+
+ setMaterial(flags, m->color, m->surfaceProps);
+
+ MatFX *matfx = MatFX::get(m);
+ if(matfx == nil)
+ matfxRender_Default(header, inst, vsBits);
+ else switch(matfx->type){
+ case MatFX::ENVMAP:
+ if(normals)
+ matfxRender_EnvMap(header, inst, vsBits, &matfx->fx[0].env);
+ else
+ matfxRender_Default(header, inst, vsBits);
+ break;
+ case MatFX::NOTHING:
+ case MatFX::BUMPMAP:
+ case MatFX::BUMPENVMAP:
+ case MatFX::DUAL:
+ case MatFX::UVTRANSFORM:
+ case MatFX::DUALUVTRANSFORM:
+ // not supported yet
+ matfxRender_Default(header, inst, vsBits);
+ break;
+ }
+
+ inst++;
+ }
+ d3d::setTexture(1, nil);
+}
+
+#define VS_NAME g_vs20_main
+#define PS_NAME g_ps20_main
+
+void
+createMatFXShaders(void)
+{
+ {
+ static
+#include "shaders/matfx_env_amb_VS.h"
+ matfx_env_amb_VS = createVertexShader((void*)VS_NAME);
+ assert(matfx_env_amb_VS);
+ }
+ {
+ static
+#include "shaders/matfx_env_amb_dir_VS.h"
+ matfx_env_amb_dir_VS = createVertexShader((void*)VS_NAME);
+ assert(matfx_env_amb_dir_VS);
+ }
+ {
+ static
+#include "shaders/matfx_env_all_VS.h"
+ matfx_env_all_VS = createVertexShader((void*)VS_NAME);
+ assert(matfx_env_all_VS);
+ }
+
+
+ {
+ static
+#include "shaders/matfx_env_PS.h"
+ matfx_env_PS = createPixelShader((void*)PS_NAME);
+ assert(matfx_env_PS);
+ }
+ {
+ static
+#include "shaders/matfx_env_tex_PS.h"
+ matfx_env_tex_PS = createPixelShader((void*)PS_NAME);
+ assert(matfx_env_tex_PS);
+ }
+
+}
+
+void
+destroyMatFXShaders(void)
+{
+ destroyVertexShader(matfx_env_amb_VS);
+ matfx_env_amb_VS = nil;
+
+ destroyVertexShader(matfx_env_amb_dir_VS);
+ matfx_env_amb_dir_VS = nil;
+
+ destroyVertexShader(matfx_env_all_VS);
+ matfx_env_all_VS = nil;
+
+
+ destroyPixelShader(matfx_env_PS);
+ matfx_env_PS = nil;
+
+ destroyPixelShader(matfx_env_tex_PS);
+ matfx_env_tex_PS = nil;
+}
+
+#endif
+
+static void*
+matfxOpen(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ createMatFXShaders();
+#endif
+
+ matFXGlobals.pipelines[PLATFORM_D3D9] = makeMatFXPipeline();
+ return o;
+}
+
+static void*
+matfxClose(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ destroyMatFXShaders();
+#endif
+
+ ((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_D3D9])->destroy();
+ matFXGlobals.pipelines[PLATFORM_D3D9] = nil;
+ return o;
+}
+
+void
+initMatFX(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D9, 0, ID_MATFX,
+ matfxOpen, matfxClose);
+}
+
+ObjPipeline*
+makeMatFXPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->renderCB = matfxRenderCB_Shader;
+ pipe->pluginID = ID_MATFX;
+ pipe->pluginData = 0;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp
new file mode 100644
index 0000000..89d937f
--- /dev/null
+++ b/src/d3d/d3d9render.cpp
@@ -0,0 +1,185 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "../rwrender.h"
+#include "rwd3d.h"
+#include "rwd3d9.h"
+
+namespace rw {
+namespace d3d9 {
+using namespace d3d;
+
+#ifndef RW_D3D9
+void defaultRenderCB(Atomic*, InstanceDataHeader*) {}
+void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) {}
+#else
+
+void
+drawInst_simple(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst)
+{
+ d3d::flushCache();
+ d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex,
+ 0, inst->numVertices,
+ inst->startIndex, inst->numPrimitives);
+}
+
+// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
+void
+drawInst_GSemu(d3d9::InstanceDataHeader *header, InstanceData *inst)
+{
+ uint32 hasAlpha;
+ int alphafunc, alpharef, gsalpharef;
+ int zwrite;
+ d3d::getRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha);
+ if(hasAlpha){
+ zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
+ alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
+ if(zwrite){
+ alpharef = rw::GetRenderState(rw::ALPHATESTREF);
+ gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);
+
+ SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
+ SetRenderState(rw::ALPHATESTREF, gsalpharef);
+ drawInst_simple(header, inst);
+ SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
+ SetRenderState(rw::ZWRITEENABLE, 0);
+ drawInst_simple(header, inst);
+ SetRenderState(rw::ZWRITEENABLE, 1);
+ SetRenderState(rw::ALPHATESTFUNC, alphafunc);
+ SetRenderState(rw::ALPHATESTREF, alpharef);
+ }else{
+ SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
+ drawInst_simple(header, inst);
+ SetRenderState(rw::ALPHATESTFUNC, alphafunc);
+ }
+ }else
+ drawInst_simple(header, inst);
+}
+
+void
+drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst)
+{
+ if(rw::GetRenderState(rw::GSALPHATEST))
+ drawInst_GSemu(header, inst);
+ else
+ drawInst_simple(header, inst);
+}
+
+/*
+void
+defaultRenderCB_Fix(Atomic *atomic, InstanceDataHeader *header)
+{
+ RawMatrix world;
+ Geometry *geo = atomic->geometry;
+
+ int lighting = !!(geo->flags & rw::Geometry::LIGHT);
+ if(lighting)
+ d3d::lightingCB_Fix(atomic);
+
+ d3d::setRenderState(D3DRS_LIGHTING, lighting);
+
+ Frame *f = atomic->getFrame();
+ convMatrix(&world, f->getLTM());
+ d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world);
+
+ setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
+ setIndices(header->indexBuffer);
+ setVertexDeclaration(header->vertexDeclaration);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ SetRenderState(VERTEXALPHA, inst->vertexAlpha || inst->material->color.alpha != 255);
+ const static rw::RGBA white = { 255, 255, 255, 255 };
+ d3d::setMaterial(white, inst->material->surfaceProps);
+
+ d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
+ if(geo->flags & Geometry::PRELIT)
+ d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
+ else
+ d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
+ d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha ? D3DMCS_COLOR1 : D3DMCS_MATERIAL);
+
+ if(inst->material->texture){
+ // Texture
+ d3d::setTexture(0, inst->material->texture);
+ d3d::setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ d3d::setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT);
+ d3d::setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
+ d3d::setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+ d3d::setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+ d3d::setTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
+ }else{
+ d3d::setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ d3d::setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT);
+ d3d::setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ d3d::setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+ }
+
+ // Material colour
+ const rw::RGBA *col = &inst->material->color;
+ d3d::setTextureStageState(1, D3DTSS_CONSTANT, D3DCOLOR_ARGB(col->alpha,col->red,col->green,col->blue));
+ d3d::setTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ d3d::setTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
+ d3d::setTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CONSTANT);
+ d3d::setTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+ d3d::setTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+ d3d::setTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CONSTANT);
+
+ drawInst(header, inst);
+ inst++;
+ }
+ d3d::setTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ d3d::setTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+}
+*/
+
+void
+defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header)
+{
+ int vsBits;
+ uint32 flags = atomic->geometry->flags;
+ setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
+ setIndices(header->indexBuffer);
+ setVertexDeclaration(header->vertexDeclaration);
+
+ vsBits = lightingCB_Shader(atomic);
+ uploadMatrices(atomic->getFrame()->getLTM());
+
+ // Pick a shader
+ if((vsBits & VSLIGHT_MASK) == 0)
+ setVertexShader(default_amb_VS);
+ else if((vsBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
+ setVertexShader(default_amb_dir_VS);
+ else
+ setVertexShader(default_all_VS);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ Material *m = inst->material;
+
+ SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
+
+ setMaterial(flags, m->color, m->surfaceProps);
+
+ if(m->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(default_tex_PS);
+ }else
+ setPixelShader(default_PS);
+
+ drawInst(header, inst);
+ inst++;
+ }
+}
+
+#endif
+}
+}
diff --git a/src/d3d/d3d9skin.cpp b/src/d3d/d3d9skin.cpp
new file mode 100644
index 0000000..86c79ab
--- /dev/null
+++ b/src/d3d/d3d9skin.cpp
@@ -0,0 +1,418 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwrender.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwd3d.h"
+#include "rwd3d9.h"
+
+namespace rw {
+namespace d3d9 {
+using namespace d3d;
+
+#ifndef RW_D3D9
+void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) {}
+void skinRenderCB(Atomic *atomic, InstanceDataHeader *header) {}
+#else
+
+
+static void *skin_amb_VS;
+static void *skin_amb_dir_VS;
+static void *skin_all_VS;
+
+#define NUMDECLELT 14
+
+void
+skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
+{
+ int i = 0;
+ VertexElement dcl[NUMDECLELT];
+ VertexStream *s = &header->vertexStream[0];
+
+ bool isPrelit = (geo->flags & Geometry::PRELIT) != 0;
+ bool hasNormals = (geo->flags & Geometry::NORMALS) != 0;
+
+ // TODO: support both vertex buffers
+
+ if(!reinstance){
+ // Create declarations and buffers only the first time
+
+ assert(s->vertexBuffer == nil);
+ s->offset = 0;
+ s->managed = 1;
+ s->geometryFlags = 0;
+ s->dynamicLock = 0;
+
+ dcl[i].stream = 0;
+ dcl[i].offset = 0;
+ dcl[i].type = D3DDECLTYPE_FLOAT3;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_POSITION;
+ dcl[i].usageIndex = 0;
+ i++;
+ uint16 stride = 12;
+ s->geometryFlags |= 0x2;
+
+ if(isPrelit){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_D3DCOLOR;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_COLOR;
+ dcl[i].usageIndex = 0;
+ i++;
+ s->geometryFlags |= 0x8;
+ stride += 4;
+ }
+
+ for(int32 n = 0; n < geo->numTexCoordSets; n++){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_FLOAT2;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_TEXCOORD;
+ dcl[i].usageIndex = (uint8)n;
+ i++;
+ s->geometryFlags |= 0x10 << n;
+ stride += 8;
+ }
+
+ if(hasNormals){
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_FLOAT3;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_NORMAL;
+ dcl[i].usageIndex = 0;
+ i++;
+ s->geometryFlags |= 0x4;
+ stride += 12;
+ }
+
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_FLOAT4;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_BLENDWEIGHT;
+ dcl[i].usageIndex = 0;
+ i++;
+ stride += 16;
+
+ dcl[i].stream = 0;
+ dcl[i].offset = stride;
+ dcl[i].type = D3DDECLTYPE_UBYTE4;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_BLENDINDICES;
+ dcl[i].usageIndex = 0;
+ i++;
+ stride += 4;
+
+ // We expect some attributes to always be there, use the constant buffer as fallback
+ if(!isPrelit){
+ dcl[i].stream = 2;
+ dcl[i].offset = offsetof(VertexConstantData, color);
+ dcl[i].type = D3DDECLTYPE_D3DCOLOR;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_COLOR;
+ dcl[i].usageIndex = 0;
+ i++;
+ }
+ if(geo->numTexCoordSets == 0){
+ dcl[i].stream = 2;
+ dcl[i].offset = offsetof(VertexConstantData, texCoors[0]);
+ dcl[i].type = D3DDECLTYPE_FLOAT2;
+ dcl[i].method = D3DDECLMETHOD_DEFAULT;
+ dcl[i].usage = D3DDECLUSAGE_TEXCOORD;
+ dcl[i].usageIndex = 0;
+ i++;
+ }
+
+ dcl[i] = D3DDECL_END();
+ s->stride = stride;
+
+ assert(header->vertexDeclaration == nil);
+ header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
+
+ assert(s->vertexBuffer == nil);
+ s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, false);
+ }else
+ getDeclaration(header->vertexDeclaration, dcl);
+
+ Skin *skin = Skin::get(geo);
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+
+ // Instance vertices
+ if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].vertices,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ // Instance prelight colors
+ if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
+ ;
+ InstanceData *inst = header->inst;
+ uint32 n = header->numMeshes;
+ while(n--){
+ uint32 stride = header->vertexStream[dcl[i].stream].stride;
+ inst->vertexAlpha = instColor(vertFormatMap[dcl[i].type],
+ verts + dcl[i].offset + stride*inst->minVert,
+ geo->colors + inst->minVert,
+ inst->numVertices,
+ stride);
+ inst++;
+ }
+ }
+
+ // Instance tex coords
+ for(int32 n = 0; n < geo->numTexCoordSets; n++){
+ if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
+ ;
+ instTexCoords(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->texCoords[n],
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+ }
+
+ // Instance normals
+ if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].normals,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ // Instance skin weights
+ if(!reinstance){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_BLENDWEIGHT || dcl[i].usageIndex != 0; i++)
+ ;
+ instV4d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ (V4d*)skin->weights,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ // Instance skin indices
+ if(!reinstance){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_BLENDINDICES || dcl[i].usageIndex != 0; i++)
+ ;
+ // not really colors of course but what the heck
+ instColor(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ (RGBA*)skin->indices,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ unlockVertices(s->vertexBuffer);
+}
+
+enum
+{
+ VSLOC_boneMatrices = VSLOC_afterLights
+};
+
+static float skinMatrices[64*16];
+
+void
+uploadSkinMatrices(Atomic *a)
+{
+ int i;
+ Skin *skin = Skin::get(a->geometry);
+ float *m = skinMatrices;
+ HAnimHierarchy *hier = Skin::getHierarchy(a);
+
+ if(hier){
+ Matrix *invMats = (Matrix*)skin->inverseMatrices;
+ Matrix tmp, tmp2;
+
+ assert(skin->numBones == hier->numNodes);
+ if(hier->flags & HAnimHierarchy::LOCALSPACEMATRICES){
+ for(i = 0; i < hier->numNodes; i++){
+ invMats[i].flags = 0;
+ Matrix::mult(&tmp, &invMats[i], &hier->matrices[i]);
+ RawMatrix::transpose((RawMatrix*)m, (RawMatrix*)&tmp);
+ m += 12;
+ }
+ }else{
+ Matrix invAtmMat;
+ Matrix::invert(&invAtmMat, a->getFrame()->getLTM());
+ for(i = 0; i < hier->numNodes; i++){
+ invMats[i].flags = 0;
+ Matrix::mult(&tmp, &hier->matrices[i], &invAtmMat);
+ Matrix::mult(&tmp2, &invMats[i], &tmp);
+ RawMatrix::transpose((RawMatrix*)m, (RawMatrix*)&tmp2);
+ m += 12;
+ }
+ }
+ }else{
+ for(i = 0; i < skin->numBones; i++){
+ m[0] = 1.0f;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = 1.0f;
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = 0.0f;
+
+ m += 12;
+ }
+ }
+ d3ddevice->SetVertexShaderConstantF(VSLOC_boneMatrices, skinMatrices, skin->numBones*3);
+}
+
+void
+skinRenderCB(Atomic *atomic, InstanceDataHeader *header)
+{
+ int vsBits;
+ uint32 flags = atomic->geometry->flags;
+ setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
+ 0, header->vertexStream[0].stride);
+ setIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
+ setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);
+
+ vsBits = lightingCB_Shader(atomic);
+ uploadMatrices(atomic->getFrame()->getLTM());
+
+ uploadSkinMatrices(atomic);
+
+ // Pick a shader
+ if((vsBits & VSLIGHT_MASK) == 0)
+ setVertexShader(skin_amb_VS);
+ else if((vsBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
+ setVertexShader(skin_amb_dir_VS);
+ else
+ setVertexShader(skin_all_VS);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ Material *m = inst->material;
+
+ SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
+
+ setMaterial(flags, m->color, m->surfaceProps);
+
+ if(inst->material->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(default_tex_PS);
+ }else
+ setPixelShader(default_PS);
+
+ drawInst(header, inst);
+ inst++;
+ }
+}
+
+#define VS_NAME g_vs20_main
+#define PS_NAME g_ps20_main
+
+void
+createSkinShaders(void)
+{
+ {
+ static
+#include "shaders/skin_amb_VS.h"
+ skin_amb_VS = createVertexShader((void*)VS_NAME);
+ assert(skin_amb_VS);
+ }
+ {
+ static
+#include "shaders/skin_amb_dir_VS.h"
+ skin_amb_dir_VS = createVertexShader((void*)VS_NAME);
+ assert(skin_amb_dir_VS);
+ }
+ // Skinning takes a lot of instructions....lighting may be not possible
+ // TODO: should do something about this
+ {
+ static
+#include "shaders/skin_all_VS.h"
+ skin_all_VS = createVertexShader((void*)VS_NAME);
+// assert(skin_all_VS);
+ }
+}
+
+void
+destroySkinShaders(void)
+{
+ destroyVertexShader(skin_amb_VS);
+ skin_amb_VS = nil;
+
+ destroyVertexShader(skin_amb_dir_VS);
+ skin_amb_dir_VS = nil;
+
+ if(skin_all_VS){
+ destroyVertexShader(skin_all_VS);
+ skin_all_VS = nil;
+ }
+}
+
+#endif
+
+static void*
+skinOpen(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ createSkinShaders();
+#endif
+
+ skinGlobals.pipelines[PLATFORM_D3D9] = makeSkinPipeline();
+ return o;
+}
+
+static void*
+skinClose(void *o, int32, int32)
+{
+#ifdef RW_D3D9
+ destroySkinShaders();
+#endif
+
+ ((ObjPipeline*)skinGlobals.pipelines[PLATFORM_D3D9])->destroy();
+ skinGlobals.pipelines[PLATFORM_D3D9] = nil;
+ return o;
+}
+
+void
+initSkin(void)
+{
+ Driver::registerPlugin(PLATFORM_D3D9, 0, ID_SKIN,
+ skinOpen, skinClose);
+}
+
+ObjPipeline*
+makeSkinPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = skinInstanceCB;
+ pipe->uninstanceCB = nil;
+ pipe->renderCB = skinRenderCB;
+ pipe->pluginID = ID_SKIN;
+ pipe->pluginData = 1;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp
new file mode 100644
index 0000000..62c46b8
--- /dev/null
+++ b/src/d3d/d3ddevice.cpp
@@ -0,0 +1,2022 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwplg.h"
+#include "../rwerror.h"
+#include "../rwrender.h"
+#include "../rwengine.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "rwd3d.h"
+#include "rwd3dimpl.h"
+
+#define PLUGIN_ID 0
+
+namespace rw {
+namespace d3d {
+
+#ifdef RW_D3D9
+
+D3d9Globals d3d9Globals;
+
+// Keep track of rasters exclusively in video memory
+// as they need special treatment sometimes
+struct VidmemRaster
+{
+ Raster *raster;
+ VidmemRaster *next;
+};
+static VidmemRaster *vidmemRasters;
+void addVidmemRaster(Raster *raster);
+void removeVidmemRaster(Raster *raster);
+
+// Same thing for dynamic vertex buffers
+struct DynamicVB
+{
+ uint32 length;
+ uint32 fvf;
+ IDirect3DVertexBuffer9 **buf;
+ DynamicVB *next;
+};
+static DynamicVB *dynamicVBs;
+void addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf);
+void removeDynamicVB(IDirect3DVertexBuffer9 **buf);
+
+// Same thing for dynamic index buffers
+struct DynamicIB
+{
+ uint32 length;
+ IDirect3DIndexBuffer9 **buf;
+ DynamicIB *next;
+};
+static DynamicIB *dynamicIBs;
+void addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf);
+void removeDynamicIB(IDirect3DIndexBuffer9 **buf);
+
+
+struct RwRasterStateCache {
+ Raster *raster;
+ Texture::Addressing addressingU;
+ Texture::Addressing addressingV;
+ Texture::FilterMode filter;
+ int32 maxAniso;
+};
+
+#define MAXNUMSTAGES 8
+
+// cached RW render states
+struct RwStateCache {
+ bool32 vertexAlpha;
+ bool32 textureAlpha;
+ uint32 srcblend, destblend;
+ uint32 zwrite;
+ uint32 ztest;
+ uint32 fogenable;
+ RGBA fogcolor;
+ uint32 cullmode;
+ uint32 stencilenable;
+ uint32 stencilpass;
+ uint32 stencilfail;
+ uint32 stencilzfail;
+ uint32 stencilfunc;
+ uint32 stencilref;
+ uint32 stencilmask;
+ uint32 stencilwritemask;
+ uint32 alphafunc;
+ uint32 alpharef;
+
+ // emulation of PS2 GS
+ bool32 gsalpha;
+ uint32 gsalpharef;
+
+ RwRasterStateCache texstage[MAXNUMSTAGES];
+};
+static RwStateCache rwStateCache;
+
+void *constantVertexStream;
+static IDirect3DTexture9 *whiteTex;
+
+D3dShaderState d3dShaderState;
+
+#define MAXNUMSTATES (D3DRS_BLENDOPALPHA+1)
+#define MAXNUMTEXSTATES (D3DTSS_CONSTANT+1)
+#define MAXNUMSAMPLERSTATES (D3DSAMP_DMAPOFFSET+1)
+#define MAXNUMSTREAMS (3)
+#define MAXNUMRENDERTARGETS (4)
+
+static int32 numDirtyStates;
+static uint32 dirtyStates[MAXNUMSTATES];
+static struct {
+ uint32 value;
+ bool32 dirty;
+} stateCache[MAXNUMSTATES];
+static uint32 d3dStates[MAXNUMSTATES];
+
+// Things that aren't just integers
+struct D3dDeviceCache {
+ IDirect3DVertexShader9 *vertexShader;
+ IDirect3DPixelShader9 *pixelShader;
+ IDirect3DVertexDeclaration9 *vertexDeclaration;
+ IDirect3DIndexBuffer9 *indices;
+ struct {
+ IDirect3DVertexBuffer9 *buffer;
+ uint32 offset;
+ uint32 stride;
+ } vertexStreams[MAXNUMSTREAMS];
+ IDirect3DSurface9 *renderTargets[MAXNUMRENDERTARGETS];
+ IDirect3DSurface9 *depthSurface;
+};
+static D3dDeviceCache deviceCache;
+
+static int32 numDirtyTextureStageStates;
+static struct {
+ uint32 stage;
+ uint32 type;
+} dirtyTextureStageStates[MAXNUMTEXSTATES*MAXNUMSTAGES];
+static struct {
+ uint32 value;
+ bool32 dirty;
+} textureStageStateCache[MAXNUMTEXSTATES][MAXNUMSTAGES];
+static uint32 d3dTextureStageStates[MAXNUMTEXSTATES][MAXNUMSTAGES];
+
+static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES];
+
+
+static bool validStates[MAXNUMSTATES];
+static bool validTexStates[MAXNUMTEXSTATES];
+
+static D3DMATERIAL9 d3dmaterial;
+
+
+static uint32 blendMap[] = {
+ D3DBLEND_ZERO, // actually invalid
+ D3DBLEND_ZERO,
+ D3DBLEND_ONE,
+ D3DBLEND_SRCCOLOR,
+ D3DBLEND_INVSRCCOLOR,
+ D3DBLEND_SRCALPHA,
+ D3DBLEND_INVSRCALPHA,
+ D3DBLEND_DESTALPHA,
+ D3DBLEND_INVDESTALPHA,
+ D3DBLEND_DESTCOLOR,
+ D3DBLEND_INVDESTCOLOR,
+ D3DBLEND_SRCALPHASAT
+};
+
+static uint32 stencilOpMap[] = {
+ D3DSTENCILOP_KEEP, // actually invalid
+ D3DSTENCILOP_KEEP,
+ D3DSTENCILOP_ZERO,
+ D3DSTENCILOP_REPLACE,
+ D3DSTENCILOP_INCRSAT,
+ D3DSTENCILOP_DECRSAT,
+ D3DSTENCILOP_INVERT,
+ D3DSTENCILOP_INCR,
+ D3DSTENCILOP_DECR
+};
+
+static uint32 stencilFuncMap[] = {
+ D3DCMP_NEVER, // actually invalid
+ D3DCMP_NEVER,
+ D3DCMP_LESS,
+ D3DCMP_EQUAL,
+ D3DCMP_LESSEQUAL,
+ D3DCMP_GREATER,
+ D3DCMP_NOTEQUAL,
+ D3DCMP_GREATEREQUAL,
+ D3DCMP_ALWAYS
+};
+
+static uint32 alphafuncMap[] = {
+ D3DCMP_ALWAYS,
+ D3DCMP_GREATEREQUAL,
+ D3DCMP_LESS
+};
+
+static uint32 cullmodeMap[] = {
+ D3DCULL_NONE, // actually invalid
+ D3DCULL_NONE,
+ D3DCULL_CW,
+ D3DCULL_CCW
+};
+
+static uint32 filterConvMap[] = {
+ 0, D3DTEXF_POINT, D3DTEXF_LINEAR,
+ D3DTEXF_POINT, D3DTEXF_LINEAR,
+ D3DTEXF_POINT, D3DTEXF_LINEAR
+};
+static uint32 filterConvMap_MIP[] = {
+ 0, D3DTEXF_NONE, D3DTEXF_NONE,
+ D3DTEXF_POINT, D3DTEXF_POINT,
+ D3DTEXF_LINEAR, D3DTEXF_LINEAR
+};
+static uint32 addressConvMap[] = {
+ 0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
+ D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
+};
+
+// D3D render state
+
+void
+setRenderState(uint32 state, uint32 value)
+{
+ if(stateCache[state].value != value){
+ stateCache[state].value = value;
+ if(!stateCache[state].dirty){
+ stateCache[state].dirty = 1;
+ dirtyStates[numDirtyStates++] = state;
+ }
+ }
+}
+
+void
+getRenderState(uint32 state, uint32 *value)
+{
+ *value = stateCache[state].value;
+}
+
+void
+setRenderTarget(int n, void *surf)
+{
+ if(surf != deviceCache.renderTargets[n]){
+ deviceCache.renderTargets[n] = (IDirect3DSurface9*)surf;
+ d3ddevice->SetRenderTarget(n, deviceCache.renderTargets[n]);
+ }
+}
+
+void
+setDepthSurface(void *surf)
+{
+ if(surf != deviceCache.depthSurface){
+ deviceCache.depthSurface = (IDirect3DSurface9*)surf;
+ d3ddevice->SetDepthStencilSurface(deviceCache.depthSurface);
+ }
+}
+
+void
+setTextureStageState(uint32 stage, uint32 type, uint32 value)
+{
+ if(textureStageStateCache[type][stage].value != value){
+ textureStageStateCache[type][stage].value = value;
+ if(!textureStageStateCache[type][stage].dirty){
+ textureStageStateCache[type][stage].dirty = 1;
+ dirtyTextureStageStates[numDirtyTextureStageStates].stage = stage;
+ dirtyTextureStageStates[numDirtyTextureStageStates].type = type;
+ numDirtyTextureStageStates++;
+ }
+ }
+}
+
+void
+getTextureStageState(uint32 stage, uint32 type, uint32 *value)
+{
+ *value = textureStageStateCache[type][stage].value;
+}
+
+void
+flushCache(void)
+{
+ uint32 s, t;
+ uint32 v;
+ for(int32 i = 0; i < numDirtyStates; i++){
+ s = dirtyStates[i];
+ v = stateCache[s].value;
+ stateCache[s].dirty = 0;
+ if(d3dStates[s] != v){
+ d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, v);
+ d3dStates[s] = v;
+ }
+ }
+ numDirtyStates = 0;
+ for(int32 i = 0; i < numDirtyTextureStageStates; i++){
+ s = dirtyTextureStageStates[i].stage;
+ t = dirtyTextureStageStates[i].type;
+ v = textureStageStateCache[t][s].value;
+ textureStageStateCache[t][s].dirty = 0;
+ if(d3dTextureStageStates[t][s] != v){
+ d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v);
+ d3dTextureStageStates[t][s] = v;
+ }
+ }
+ numDirtyTextureStageStates = 0;
+
+ if(d3dShaderState.fogDirty){
+ d3ddevice->SetVertexShaderConstantF(VSLOC_fogData, (float*)&d3dShaderState.fogData, 1);
+ d3ddevice->SetPixelShaderConstantF(PSLOC_fogColor, (float*)&d3dShaderState.fogColor, 1);
+ d3dShaderState.fogDirty = false;
+ }
+}
+
+void
+setSamplerState(uint32 stage, uint32 type, uint32 value)
+{
+ if(d3dSamplerStates[type][stage] != value){
+ d3ddevice->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value);
+ d3dSamplerStates[type][stage] = value;
+ }
+}
+
+void
+getSamplerState(uint32 stage, uint32 type, uint32 *value)
+{
+ *value = d3dSamplerStates[type][stage];
+}
+
+// Bring D3D device in accordance with saved render states (after a reset)
+static void
+restoreD3d9Device(void)
+{
+ int32 i;
+ uint32 s, t;
+
+ for(i = 0; i < MAXNUMSTAGES; i++){
+ Raster *raster = rwStateCache.texstage[i].raster;
+ if(raster){
+ D3dRaster *d3draster = GETD3DRASTEREXT(raster);
+ d3ddevice->SetTexture(i, (IDirect3DTexture9*)d3draster->texture);
+ }else
+ d3ddevice->SetTexture(i, nil);
+ setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]);
+ setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]);
+ setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap[rwStateCache.texstage[i].filter]);
+ if(rwStateCache.texstage[i].maxAniso == 1)
+ setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap[rwStateCache.texstage[i].filter]);
+ else
+ setSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
+ setSamplerState(i, D3DSAMP_MIPFILTER, filterConvMap_MIP[rwStateCache.texstage[i].filter]);
+ }
+ for(s = 0; s < MAXNUMSTATES; s++)
+ if(validStates[s])
+ d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, d3dStates[s]);
+ for(t = 0; t < MAXNUMTEXSTATES; t++)
+ if(validTexStates[t])
+ for(s = 0; s < MAXNUMSTAGES; s++)
+ d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, d3dTextureStageStates[t][s]);
+ for(t = 1; t < MAXNUMSAMPLERSTATES; t++)
+ for(s = 0; s < MAXNUMSTAGES; s++)
+ d3ddevice->SetSamplerState(s, (D3DSAMPLERSTATETYPE)t, d3dSamplerStates[t][s]);
+ d3ddevice->SetMaterial(&d3dmaterial);
+
+ d3ddevice->SetVertexShader(deviceCache.vertexShader);
+ d3ddevice->SetPixelShader(deviceCache.pixelShader);
+ d3ddevice->SetVertexDeclaration(deviceCache.vertexDeclaration);
+ d3ddevice->SetIndices(deviceCache.indices);
+ for(i = 0; i < MAXNUMSTREAMS; i++)
+ d3ddevice->SetStreamSource(i, deviceCache.vertexStreams[i].buffer, deviceCache.vertexStreams[i].offset, deviceCache.vertexStreams[i].stride);
+
+ // shader constants are zero now
+ d3dShaderState.fogDirty = true;
+ d3dShaderState.matColor.red = 0;
+ d3dShaderState.matColor.green = 0;
+ d3dShaderState.matColor.blue = 0;
+ d3dShaderState.matColor.alpha = 0;
+ d3dShaderState.surfProps.ambient = 0.0f;
+ d3dShaderState.surfProps.specular = 0.0f;
+ d3dShaderState.surfProps.diffuse = 0.0f;
+ d3dShaderState.extraSurfProp = 0.0f;
+ d3dShaderState.numDir = 0;
+ d3dShaderState.numPoint = 0;
+ d3dShaderState.numSpot = 0;
+ d3dShaderState.ambient.red = 0.0f;
+ d3dShaderState.ambient.green = 0.0f;
+ d3dShaderState.ambient.blue = 0.0f;
+ d3dShaderState.ambient.alpha = 0.0f;
+}
+
+void
+evictD3D9Raster(Raster *raster)
+{
+ int i;
+ // Make sure we're not still referencing this raster
+ D3dRaster *natras = GETD3DRASTEREXT(raster);
+ switch(raster->type){
+ case Raster::CAMERATEXTURE:
+ for(i = 0; i < MAXNUMRENDERTARGETS; i++)
+ if(deviceCache.renderTargets[i] == natras->texture)
+ setRenderTarget(i, i == 0 ? d3d9Globals.defaultRenderTarget : nil);
+ // fall through
+ case Raster::NORMAL:
+ case Raster::TEXTURE:
+ for(i = 0; i < MAXNUMSTAGES; i++)
+ if(rwStateCache.texstage[i].raster == raster)
+ rwStateCache.texstage[i].raster = nil;
+ break;
+ case Raster::ZBUFFER:
+ if(natras->texture == deviceCache.depthSurface)
+ setDepthSurface(d3d9Globals.defaultDepthSurf);
+ break;
+ }
+}
+
+// RW render state
+
+static void
+setDepthTest(bool32 enable)
+{
+ if(rwStateCache.ztest != enable){
+ rwStateCache.ztest = enable;
+ if(rwStateCache.zwrite && !enable){
+ // If we still want to write, enable but set mode to always
+ setRenderState(D3DRS_ZENABLE, TRUE);
+ setRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ }else{
+ setRenderState(D3DRS_ZENABLE, rwStateCache.ztest);
+ setRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
+ }
+ }
+}
+
+static void
+setDepthWrite(bool32 enable)
+{
+ if(rwStateCache.zwrite != enable){
+ rwStateCache.zwrite = enable;
+ if(enable && !rwStateCache.ztest){
+ // Have to switch on ztest so writing can work
+ setRenderState(D3DRS_ZENABLE, TRUE);
+ setRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ }
+ setRenderState(D3DRS_ZWRITEENABLE, rwStateCache.zwrite);
+ }
+}
+
+static void
+setVertexAlpha(bool32 enable)
+{
+ if(rwStateCache.vertexAlpha != enable){
+ if(!rwStateCache.textureAlpha){
+ setRenderState(D3DRS_ALPHABLENDENABLE, enable);
+ setRenderState(D3DRS_ALPHATESTENABLE, enable);
+ }
+ rwStateCache.vertexAlpha = enable;
+ }
+}
+
+void
+setRasterStage(uint32 stage, Raster *raster)
+{
+ bool32 alpha;
+ D3dRaster *d3draster = nil;
+ if(raster != rwStateCache.texstage[stage].raster){
+ rwStateCache.texstage[stage].raster = raster;
+ if(raster){
+ assert(raster->platform == PLATFORM_D3D8 ||
+ raster->platform == PLATFORM_D3D9);
+ d3draster = GETD3DRASTEREXT(raster);
+ d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
+ alpha = d3draster->hasAlpha;
+ }else{
+ d3ddevice->SetTexture(stage, whiteTex);
+ alpha = 0;
+ }
+ if(stage == 0){
+ if(rwStateCache.textureAlpha != alpha){
+ rwStateCache.textureAlpha = alpha;
+ if(!rwStateCache.vertexAlpha){
+ setRenderState(D3DRS_ALPHABLENDENABLE, alpha);
+ setRenderState(D3DRS_ALPHATESTENABLE, alpha);
+ }
+ }
+ }
+ }
+}
+
+static void
+setFilterMode(uint32 stage, int32 filter, int32 maxAniso = 1)
+{
+ if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
+ rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
+ setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap[filter]);
+ if(maxAniso == 1)
+ setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]);
+ else
+ setSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
+ setSamplerState(stage, D3DSAMP_MIPFILTER, filterConvMap_MIP[filter]);
+ }
+ if(rwStateCache.texstage[stage].maxAniso != maxAniso){
+ rwStateCache.texstage[stage].maxAniso = maxAniso;
+ if(maxAniso == 1)
+ setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]);
+ else
+ setSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
+ setSamplerState(stage, D3DSAMP_MAXANISOTROPY, maxAniso);
+ }
+}
+
+static void
+setAddressU(uint32 stage, int32 addressing)
+{
+ if(rwStateCache.texstage[stage].addressingU != (Texture::Addressing)addressing){
+ rwStateCache.texstage[stage].addressingU = (Texture::Addressing)addressing;
+ setSamplerState(stage, D3DSAMP_ADDRESSU, addressConvMap[addressing]);
+ }
+}
+
+static void
+setAddressV(uint32 stage, int32 addressing)
+{
+ if(rwStateCache.texstage[stage].addressingV != (Texture::Addressing)addressing){
+ rwStateCache.texstage[stage].addressingV = (Texture::Addressing)addressing;
+ setSamplerState(stage, D3DSAMP_ADDRESSV, addressConvMap[addressing]);
+ }
+}
+
+void
+setTexture(uint32 stage, Texture *tex)
+{
+ if(tex == nil){
+ setRasterStage(stage, nil);
+ return;
+ }
+ if(tex->raster){
+ setFilterMode(stage, tex->getFilter(), tex->getMaxAnisotropy());
+ setAddressU(stage, tex->getAddressU());
+ setAddressV(stage, tex->getAddressV());
+ }
+ setRasterStage(stage, tex->raster);
+}
+
+void
+setD3dMaterial(D3DMATERIAL9 *mat9)
+{
+ if(d3dmaterial.Diffuse.r != mat9->Diffuse.r ||
+ d3dmaterial.Diffuse.g != mat9->Diffuse.g ||
+ d3dmaterial.Diffuse.b != mat9->Diffuse.b ||
+ d3dmaterial.Diffuse.a != mat9->Diffuse.a ||
+ d3dmaterial.Ambient.r != mat9->Ambient.r ||
+ d3dmaterial.Ambient.g != mat9->Ambient.g ||
+ d3dmaterial.Ambient.b != mat9->Ambient.b ||
+ d3dmaterial.Ambient.a != mat9->Ambient.a ||
+ d3dmaterial.Specular.r != mat9->Specular.r ||
+ d3dmaterial.Specular.g != mat9->Specular.g ||
+ d3dmaterial.Specular.b != mat9->Specular.b ||
+ d3dmaterial.Specular.a != mat9->Specular.a ||
+ d3dmaterial.Emissive.r != mat9->Emissive.r ||
+ d3dmaterial.Emissive.g != mat9->Emissive.g ||
+ d3dmaterial.Emissive.b != mat9->Emissive.b ||
+ d3dmaterial.Emissive.a != mat9->Emissive.a ||
+ d3dmaterial.Power != mat9->Power){
+ d3ddevice->SetMaterial(mat9);
+ d3dmaterial = *mat9;
+ }
+}
+
+void
+setMaterial_fix(const RGBA &color, const SurfaceProperties &surfProps)
+{
+ D3DMATERIAL9 mat9;
+ D3DCOLORVALUE black = { 0, 0, 0, 0 };
+ float ambmult = surfProps.ambient/255.0f;
+ float diffmult = surfProps.diffuse/255.0f;
+ mat9.Ambient.r = color.red*ambmult;
+ mat9.Ambient.g = color.green*ambmult;
+ mat9.Ambient.b = color.blue*ambmult;
+ mat9.Ambient.a = color.alpha;
+ mat9.Diffuse.r = color.red*diffmult;
+ mat9.Diffuse.g = color.green*diffmult;
+ mat9.Diffuse.b = color.blue*diffmult;
+ mat9.Diffuse.a = color.alpha;
+ mat9.Power = 0.0f;
+ mat9.Emissive = black;
+ mat9.Specular = black;
+ setD3dMaterial(&mat9);
+}
+
+
+void
+setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp)
+{
+ if(!equal(d3dShaderState.matColor, color)){
+ rw::RGBAf col;
+ convColor(&col, &color);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_matColor, (float*)&col, 1);
+ d3dShaderState.matColor = color;
+ }
+
+ if(d3dShaderState.surfProps.ambient != surfaceprops.ambient ||
+ d3dShaderState.surfProps.specular != surfaceprops.specular ||
+ d3dShaderState.surfProps.diffuse != surfaceprops.diffuse ||
+ d3dShaderState.extraSurfProp != extraSurfProp){
+ float surfProps[4];
+ surfProps[0] = surfaceprops.ambient;
+ surfProps[1] = surfaceprops.specular;
+ surfProps[2] = surfaceprops.diffuse;
+ surfProps[3] = extraSurfProp;
+ d3ddevice->SetVertexShaderConstantF(VSLOC_surfProps, surfProps, 1);
+ d3dShaderState.surfProps = surfaceprops;
+ d3dShaderState.extraSurfProp = extraSurfProp;
+ }
+}
+
+static void
+setRwRenderState(int32 state, void *pvalue)
+{
+ uint32 value = (uint32)(uintptr)pvalue;
+ uint32 bval = value ? TRUE : FALSE;
+ switch(state){
+ case TEXTURERASTER:
+ setRasterStage(0, (Raster*)pvalue);
+ break;
+ case TEXTUREADDRESS:
+ setAddressU(0, value);
+ setAddressV(0, value);
+ break;
+ case TEXTUREADDRESSU:
+ setAddressU(0, value);
+ break;
+ case TEXTUREADDRESSV:
+ setAddressV(0, value);
+ break;
+ case TEXTUREFILTER:
+ setFilterMode(0, value);
+ break;
+ case VERTEXALPHA:
+ setVertexAlpha(bval);
+ break;
+ case SRCBLEND:
+ if(rwStateCache.srcblend != value){
+ rwStateCache.srcblend = value;
+ setRenderState(D3DRS_SRCBLEND, blendMap[value]);
+ }
+ break;
+ case DESTBLEND:
+ if(rwStateCache.destblend != value){
+ rwStateCache.destblend = value;
+ setRenderState(D3DRS_DESTBLEND, blendMap[value]);
+ }
+ break;
+ case ZTESTENABLE:
+ setDepthTest(bval);
+ break;
+ case ZWRITEENABLE:
+ setDepthWrite(bval);
+ break;
+ case FOGENABLE:
+ if(rwStateCache.fogenable != bval){
+ rwStateCache.fogenable = bval;
+// setRenderState(D3DRS_FOGENABLE, rwStateCache.fogenable);
+ d3dShaderState.fogData.disable = bval ? 0.0f : 1.0f;
+ d3dShaderState.fogDirty = true;
+ };
+ break;
+ case FOGCOLOR:{
+ RGBA c;
+ c.red = value;
+ c.green = value>>8;
+ c.blue = value>>16;
+ c.alpha = value>>24;
+ if(!equal(rwStateCache.fogcolor, c)){
+ rwStateCache.fogcolor = c;
+ setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha));
+ convColor(&d3dShaderState.fogColor, &c);
+ d3dShaderState.fogDirty = true;
+ }} break;
+ case CULLMODE:
+ if(rwStateCache.cullmode != value){
+ rwStateCache.cullmode = value;
+ setRenderState(D3DRS_CULLMODE, cullmodeMap[value]);
+ }
+ break;
+
+ case STENCILENABLE:
+ if(rwStateCache.stencilenable != bval){
+ rwStateCache.stencilenable = bval;
+ setRenderState(D3DRS_STENCILENABLE, bval);
+ }
+ break;
+ case STENCILFAIL:
+ if(rwStateCache.stencilfail != value){
+ rwStateCache.stencilfail = value;
+ setRenderState(D3DRS_STENCILFAIL, stencilOpMap[value]);
+ }
+ break;
+ case STENCILZFAIL:
+ if(rwStateCache.stencilzfail != value){
+ rwStateCache.stencilzfail = value;
+ setRenderState(D3DRS_STENCILZFAIL, stencilOpMap[value]);
+ }
+ break;
+ case STENCILPASS:
+ if(rwStateCache.stencilpass != value){
+ rwStateCache.stencilpass = value;
+ setRenderState(D3DRS_STENCILPASS, stencilOpMap[value]);
+ }
+ break;
+ case STENCILFUNCTION:
+ if(rwStateCache.stencilfunc != value){
+ rwStateCache.stencilfunc = value;
+ setRenderState(D3DRS_STENCILFUNC, stencilFuncMap[value]);
+ }
+ break;
+ case STENCILFUNCTIONREF:
+ if(rwStateCache.stencilref != value){
+ rwStateCache.stencilref = value;
+ setRenderState(D3DRS_STENCILREF, value);
+ }
+ break;
+ case STENCILFUNCTIONMASK:
+ if(rwStateCache.stencilmask != value){
+ rwStateCache.stencilmask = value;
+ setRenderState(D3DRS_STENCILMASK, value);
+ }
+ break;
+ case STENCILFUNCTIONWRITEMASK:
+ if(rwStateCache.stencilwritemask != value){
+ rwStateCache.stencilwritemask = value;
+ setRenderState(D3DRS_STENCILWRITEMASK, value);
+ }
+ break;
+
+ case ALPHATESTFUNC:
+ if(rwStateCache.alphafunc != value){
+ rwStateCache.alphafunc = value;
+ setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[rwStateCache.alphafunc]);
+ }
+ break;
+ case ALPHATESTREF:
+ if(rwStateCache.alpharef != value){
+ rwStateCache.alpharef = value;
+ setRenderState(D3DRS_ALPHAREF, rwStateCache.alpharef);
+ }
+ break;
+ case GSALPHATEST:
+ rwStateCache.gsalpha = value;
+ break;
+ case GSALPHATESTREF:
+ rwStateCache.gsalpharef = value;
+ break;
+ }
+}
+
+static void*
+getRwRenderState(int32 state)
+{
+ uint32 val;
+ switch(state){
+ case TEXTURERASTER:
+ return rwStateCache.texstage[0].raster;
+ case TEXTUREADDRESS:
+ if(rwStateCache.texstage[0].addressingU == rwStateCache.texstage[0].addressingV)
+ val = rwStateCache.texstage[0].addressingU;
+ else
+ val = 0; // invalid
+ break;
+ case TEXTUREADDRESSU:
+ val = rwStateCache.texstage[0].addressingU;
+ break;
+ case TEXTUREADDRESSV:
+ val = rwStateCache.texstage[0].addressingV;
+ break;
+ case TEXTUREFILTER:
+ val = rwStateCache.texstage[0].filter;
+ break;
+
+ case VERTEXALPHA:
+ val = rwStateCache.vertexAlpha;
+ break;
+ case SRCBLEND:
+ val = rwStateCache.srcblend;
+ break;
+ case DESTBLEND:
+ val = rwStateCache.destblend;
+ break;
+ case ZTESTENABLE:
+ val = rwStateCache.ztest;
+ break;
+ case ZWRITEENABLE:
+ val = rwStateCache.zwrite;
+ break;
+ case FOGENABLE:
+ val = rwStateCache.fogenable;
+ break;
+ case FOGCOLOR:
+ val = RWRGBAINT(rwStateCache.fogcolor.red, rwStateCache.fogcolor.green,
+ rwStateCache.fogcolor.blue, rwStateCache.fogcolor.alpha);
+ break;
+ case CULLMODE:
+ val = rwStateCache.cullmode;
+ break;
+
+ case STENCILENABLE:
+ val = rwStateCache.stencilenable;
+ break;
+ case STENCILFAIL:
+ val = rwStateCache.stencilfail;
+ break;
+ case STENCILZFAIL:
+ val = rwStateCache.stencilzfail;
+ break;
+ case STENCILPASS:
+ val = rwStateCache.stencilpass;
+ break;
+ case STENCILFUNCTION:
+ val = rwStateCache.stencilfunc;
+ break;
+ case STENCILFUNCTIONREF:
+ val = rwStateCache.stencilref;
+ break;
+ case STENCILFUNCTIONMASK:
+ val = rwStateCache.stencilmask;
+ break;
+ case STENCILFUNCTIONWRITEMASK:
+ val = rwStateCache.stencilwritemask;
+ break;
+
+ case ALPHATESTFUNC:
+ val = rwStateCache.alphafunc;
+ break;
+ case ALPHATESTREF:
+ val = rwStateCache.alpharef;
+ break;
+ case GSALPHATEST:
+ val = rwStateCache.gsalpha;
+ break;
+ case GSALPHATESTREF:
+ val = rwStateCache.gsalpharef;
+ break;
+ default:
+ val = 0;
+ }
+ return (void*)(uintptr)val;
+}
+
+// Shaders
+
+void
+setVertexShader(void *vs)
+{
+ if(deviceCache.vertexShader != vs){
+ deviceCache.vertexShader = (IDirect3DVertexShader9*)vs;
+ d3ddevice->SetVertexShader(deviceCache.vertexShader);
+ }
+}
+
+void
+setPixelShader(void *ps)
+{
+ if(deviceCache.pixelShader != ps){
+ deviceCache.pixelShader = (IDirect3DPixelShader9*)ps;
+ d3ddevice->SetPixelShader(deviceCache.pixelShader);
+ }
+}
+
+void
+setIndices(void *indexBuffer)
+{
+ if(deviceCache.indices != indexBuffer){
+ deviceCache.indices = (IDirect3DIndexBuffer9*)indexBuffer;
+ d3ddevice->SetIndices(deviceCache.indices);
+ }
+}
+
+void
+setStreamSource(int n, void *buffer, uint32 offset, uint32 stride)
+{
+ if(deviceCache.vertexStreams[n].buffer != buffer ||
+ deviceCache.vertexStreams[n].offset != offset ||
+ deviceCache.vertexStreams[n].stride != stride){
+ deviceCache.vertexStreams[n].buffer = (IDirect3DVertexBuffer9*)buffer;
+ deviceCache.vertexStreams[n].offset = offset;
+ deviceCache.vertexStreams[n].stride = stride;
+ d3ddevice->SetStreamSource(n, deviceCache.vertexStreams[n].buffer, offset, stride);
+ }
+}
+
+void
+setVertexDeclaration(void *declaration)
+{
+ if(deviceCache.vertexDeclaration != declaration){
+ deviceCache.vertexDeclaration = (IDirect3DVertexDeclaration9*)declaration;
+ d3ddevice->SetVertexDeclaration(deviceCache.vertexDeclaration);
+ }
+}
+
+void*
+createVertexShader(void *csosrc)
+{
+ void *shdr;
+ if(d3ddevice->CreateVertexShader((DWORD*)csosrc, (IDirect3DVertexShader9**)&shdr) == D3D_OK){
+ d3d9Globals.numVertexShaders++;
+ return shdr;
+ }
+ return nil;
+}
+
+void*
+createPixelShader(void *csosrc)
+{
+ void *shdr;
+ if(d3ddevice->CreatePixelShader((DWORD*)csosrc, (IDirect3DPixelShader9**)&shdr) == D3D_OK){
+ d3d9Globals.numPixelShaders++;
+ return shdr;
+ }
+ return nil;
+}
+
+void
+destroyVertexShader(void *shader)
+{
+ if(shader){
+ ((IDirect3DVertexShader9*)shader)->Release();
+ d3d9Globals.numVertexShaders--;
+ }
+}
+
+void
+destroyPixelShader(void *shader)
+{
+ if(shader){
+ ((IDirect3DPixelShader9*)shader)->Release();
+ d3d9Globals.numPixelShaders--;
+ }
+}
+
+
+// Camera
+
+static void
+setRenderSurfaces(Camera *cam)
+{
+ Raster *fbuf = cam->frameBuffer;
+ assert(fbuf);
+ {
+ if(fbuf->parent)
+ fbuf = fbuf->parent;
+
+ D3dRaster *natras = GETD3DRASTEREXT(fbuf);
+ assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE);
+ if(natras->texture == nil)
+ setRenderTarget(0, d3d9Globals.defaultRenderTarget);
+ else{
+ assert(fbuf->type == Raster::CAMERATEXTURE);
+ IDirect3DSurface9 *surf;
+ ((IDirect3DTexture9*)natras->texture)->GetSurfaceLevel(0, &surf);
+ setRenderTarget(0, surf);
+ surf->Release();
+ }
+ }
+
+ Raster *zbuf = cam->zBuffer;
+ if(zbuf){
+ if(zbuf->parent)
+ zbuf = zbuf->parent;
+
+ D3dRaster *natras = GETD3DRASTEREXT(zbuf);
+ assert(zbuf->type == Raster::ZBUFFER);
+ setDepthSurface(natras->texture);
+ }else
+ setDepthSurface(nil);
+
+}
+
+static void
+setViewport(Raster *fb)
+{
+ D3DVIEWPORT9 vp;
+ vp.MinZ = 0.0f;
+ vp.MaxZ = 1.0f;
+ vp.X = fb->offsetX;
+ vp.Y = fb->offsetY;
+ vp.Width = fb->width;
+ vp.Height = fb->height;
+ d3ddevice->SetViewport(&vp);
+}
+// Manage video memory
+
+void
+addVidmemRaster(Raster *raster)
+{
+ VidmemRaster *vmr = rwNewT(VidmemRaster, 1, ID_DRIVER | MEMDUR_EVENT);
+ vmr->raster = raster;
+ vmr->next = vidmemRasters;
+ vidmemRasters = vmr;
+}
+
+void
+removeVidmemRaster(Raster *raster)
+{
+ VidmemRaster **p, *vmr;
+ for(p = &vidmemRasters; *p; p = &(*p)->next)
+ if((*p)->raster == raster)
+ goto found;
+ return;
+found:
+ vmr = *p;
+ *p = vmr->next;
+ rwFree(vmr);
+}
+
+static void
+releaseVidmemRasters(void)
+{
+ VidmemRaster *vmr;
+ Raster *raster;
+ D3dRaster *natras;
+ for(vmr = vidmemRasters; vmr; vmr = vmr->next){
+ raster = vmr->raster;
+ natras = GETD3DRASTEREXT(raster);
+ switch(raster->type){
+ case Raster::CAMERATEXTURE:
+ destroyTexture(natras->texture);
+ natras->texture = nil;
+ break;
+
+ case Raster::ZBUFFER:
+ // we'll leave the default surface dangling so we can tell the difference
+ if(natras->texture != d3d9Globals.defaultDepthSurf){
+ ((IDirect3DSurface9*)natras->texture)->Release();
+ natras->texture = nil;
+ }
+ break;
+ }
+ }
+}
+
+static void
+recreateVidmemRasters(void)
+{
+ VidmemRaster *vmr;
+ Raster *raster;
+ D3dRaster *natras;
+ for(vmr = vidmemRasters; vmr; vmr = vmr->next){
+ raster = vmr->raster;
+ natras = GETD3DRASTEREXT(raster);
+ switch(raster->type){
+ case Raster::CAMERATEXTURE: {
+ int32 levels = Raster::calculateNumLevels(raster->width, raster->height);
+ IDirect3DTexture9 *tex = nil;
+ d3ddevice->CreateTexture(raster->width, raster->height,
+ raster->format & Raster::MIPMAP ? levels : 1,
+ D3DUSAGE_RENDERTARGET,
+ (D3DFORMAT)natras->format, D3DPOOL_DEFAULT, &tex, nil);
+ natras->texture = tex;
+ if(natras->texture)
+ d3d9Globals.numTextures++;
+ break;
+ }
+
+ case Raster::ZBUFFER:
+ if(natras->texture){
+ RECT rect;
+ GetClientRect(d3d9Globals.window, &rect);
+ raster->width = rect.right;
+ raster->height = rect.bottom;
+ natras->texture = d3d9Globals.defaultDepthSurf;
+ natras->format = d3d9Globals.present.AutoDepthStencilFormat;
+ raster->depth = findFormatDepth(natras->format);
+ }else{
+ IDirect3DSurface9 *surf = nil;
+ d3ddevice->CreateDepthStencilSurface(raster->width, raster->height, (D3DFORMAT)natras->format,
+ d3d9Globals.present.MultiSampleType, d3d9Globals.present.MultiSampleQuality,
+ FALSE, &surf, nil);
+ natras->texture = surf;
+ }
+ break;
+ }
+ }
+}
+
+void
+addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf)
+{
+ DynamicVB *dvb = rwNewT(DynamicVB, 1, ID_DRIVER | MEMDUR_EVENT);
+ dvb->length = length;
+ dvb->fvf = fvf;
+ dvb->buf = buf;
+ dvb->next = dynamicVBs;
+ dynamicVBs = dvb;
+}
+
+void
+removeDynamicVB(IDirect3DVertexBuffer9 **buf)
+{
+ DynamicVB **p, *dvb;
+ for(p = &dynamicVBs; *p; p = &(*p)->next)
+ if((*p)->buf == buf)
+ goto found;
+ return;
+found:
+ dvb = *p;
+ *p = dvb->next;
+ rwFree(dvb);
+}
+
+static void
+releaseDynamicVBs(void)
+{
+ DynamicVB *dvb;
+ int i;
+ for(dvb = dynamicVBs; dvb; dvb = dvb->next){
+ for(i = 0; i < MAXNUMSTREAMS; i++)
+ if(deviceCache.vertexStreams[i].buffer == *dvb->buf)
+ deviceCache.vertexStreams[i].buffer = nil;
+ destroyVertexBuffer(*dvb->buf);
+ *dvb->buf = nil;
+ }
+}
+
+static void
+recreateDynamicVBs(void)
+{
+ DynamicVB *dvb;
+ for(dvb = dynamicVBs; dvb; dvb = dvb->next){
+ assert(*dvb->buf == nil);
+ *dvb->buf = (IDirect3DVertexBuffer9*)createVertexBuffer(dvb->length, dvb->fvf, true);
+ }
+}
+
+
+void
+addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf)
+{
+ DynamicIB *ivb = rwNewT(DynamicIB, 1, ID_DRIVER | MEMDUR_EVENT);
+ ivb->length = length;
+ ivb->buf = buf;
+ ivb->next = dynamicIBs;
+ dynamicIBs = ivb;
+}
+
+void
+removeDynamicIB(IDirect3DIndexBuffer9 **buf)
+{
+ DynamicIB **p, *ivb;
+ for(p = &dynamicIBs; *p; p = &(*p)->next)
+ if((*p)->buf == buf)
+ goto found;
+ return;
+found:
+ ivb = *p;
+ *p = ivb->next;
+ rwFree(ivb);
+}
+
+static void
+releaseDynamicIBs(void)
+{
+ DynamicIB *ivb;
+ for(ivb = dynamicIBs; ivb; ivb = ivb->next){
+ if(deviceCache.indices == *ivb->buf)
+ deviceCache.indices = nil;
+ destroyIndexBuffer(*ivb->buf);
+ *ivb->buf = nil;
+ }
+}
+
+static void
+recreateDynamicIBs(void)
+{
+ DynamicIB *ivb;
+ for(ivb = dynamicIBs; ivb; ivb = ivb->next){
+ assert(*ivb->buf == nil);
+ *ivb->buf = (IDirect3DIndexBuffer9*)createIndexBuffer(ivb->length, true);
+ }
+}
+
+static void
+releaseVideoMemory(void)
+{
+ int32 i;
+ for(i = 0; i < MAXNUMSTAGES; i++)
+ d3ddevice->SetTexture(i, nil);
+ d3ddevice->SetVertexDeclaration(nil);
+ d3ddevice->SetVertexShader(nil);
+ d3ddevice->SetPixelShader(nil);
+ d3ddevice->SetIndices(nil);
+ for(i = 0; i < MAXNUMSTREAMS; i++)
+ d3ddevice->SetStreamSource(0, nil, 0, 0);
+
+ setRenderTarget(0, d3d9Globals.defaultRenderTarget);
+ for(i = 1; i < MAXNUMRENDERTARGETS; i++)
+ setRenderTarget(i, nil);
+ setDepthSurface(d3d9Globals.defaultDepthSurf);
+
+ releaseVidmemRasters();
+ releaseDynamicVBs();
+ releaseDynamicIBs();
+}
+
+static void
+restoreVideoMemory(void)
+{
+ // Have to get these back before recreating rasters
+ d3ddevice->GetRenderTarget(0, &d3d9Globals.defaultRenderTarget);
+ d3d9Globals.defaultRenderTarget->Release(); // refcount increased by Get
+ deviceCache.renderTargets[0] = d3d9Globals.defaultRenderTarget;
+ d3ddevice->GetDepthStencilSurface(&d3d9Globals.defaultDepthSurf);
+ d3d9Globals.defaultDepthSurf->Release(); // refcount increased by Get
+ deviceCache.depthSurface = d3d9Globals.defaultDepthSurf;
+
+ recreateDynamicIBs();
+ recreateDynamicVBs();
+ // important that we get all raster back before restoring state
+ recreateVidmemRasters();
+
+ restoreD3d9Device();
+}
+
+static void
+beginUpdate(Camera *cam)
+{
+ float view[16], proj[16];
+
+ // View Matrix
+ Matrix inv;
+ Matrix::invert(&inv, cam->getFrame()->getLTM());
+ // Since we're looking into positive Z,
+ // flip X to ge a left handed view space.
+ view[0] = -inv.right.x;
+ view[1] = inv.right.y;
+ view[2] = inv.right.z;
+ view[3] = 0.0f;
+ view[4] = -inv.up.x;
+ view[5] = inv.up.y;
+ view[6] = inv.up.z;
+ view[7] = 0.0f;
+ view[8] = -inv.at.x;
+ view[9] = inv.at.y;
+ view[10] = inv.at.z;
+ view[11] = 0.0f;
+ view[12] = -inv.pos.x;
+ view[13] = inv.pos.y;
+ view[14] = inv.pos.z;
+ view[15] = 1.0f;
+ memcpy(&cam->devView, view, sizeof(RawMatrix));
+// d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view);
+
+ // Projection Matrix
+ float32 invwx = 1.0f/cam->viewWindow.x;
+ float32 invwy = 1.0f/cam->viewWindow.y;
+ float32 invz = 1.0f/(cam->farPlane-cam->nearPlane);
+
+ proj[0] = invwx;
+ proj[1] = 0.0f;
+ proj[2] = 0.0f;
+ proj[3] = 0.0f;
+
+ proj[4] = 0.0f;
+ proj[5] = invwy;
+ proj[6] = 0.0f;
+ proj[7] = 0.0f;
+
+ proj[8] = cam->viewOffset.x*invwx;
+ proj[9] = cam->viewOffset.y*invwy;
+ proj[12] = -proj[8];
+ proj[13] = -proj[9];
+ if(cam->projection == Camera::PERSPECTIVE){
+ proj[10] = cam->farPlane*invz;
+ proj[11] = 1.0f;
+
+ proj[15] = 0.0f;
+ }else{
+ proj[10] = invz;
+ proj[11] = 0.0f;
+
+ proj[15] = 1.0f;
+ }
+ proj[14] = -cam->nearPlane*proj[10];
+ memcpy(&cam->devProj, proj, sizeof(RawMatrix));
+// d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj);
+
+ // TODO: figure out where this is really done
+// setRenderState(D3DRS_FOGSTART, *(uint32*)&cam->fogPlane);
+// setRenderState(D3DRS_FOGEND, *(uint32*)&cam->farPlane);
+ d3dShaderState.fogData.start = cam->fogPlane;
+ d3dShaderState.fogData.end = cam->farPlane;
+ d3dShaderState.fogData.range = 1.0f/(cam->fogPlane - cam->farPlane);
+ // TODO: not quite sure this is the right place to do this...
+ d3dShaderState.fogData.disable = rwStateCache.fogenable ? 0.0f : 1.0f;
+ d3dShaderState.fogDisable.start = 0.0f;
+ d3dShaderState.fogDisable.end = 0.0f;
+ d3dShaderState.fogDisable.range = 0.0f;
+ d3dShaderState.fogDisable.disable = 1.0f;
+ d3dShaderState.fogDirty = true;
+
+ RECT r;
+ GetClientRect(d3d9Globals.window, &r);
+ BOOL icon = IsIconic(d3d9Globals.window);
+ if(!icon &&
+ (r.right != d3d9Globals.present.BackBufferWidth || r.bottom != d3d9Globals.present.BackBufferHeight)){
+
+ d3d9Globals.present.BackBufferWidth = r.right;
+ d3d9Globals.present.BackBufferHeight = r.bottom;
+
+ releaseVideoMemory();
+ d3d::d3ddevice->Reset(&d3d9Globals.present);
+ restoreVideoMemory();
+ }
+
+ setRenderSurfaces(cam);
+
+ setViewport(cam->frameBuffer);
+
+ d3ddevice->BeginScene();
+}
+
+static void
+endUpdate(Camera *cam)
+{
+ d3ddevice->EndScene();
+}
+
+static void
+clearCamera(Camera *cam, RGBA *col, uint32 mode)
+{
+ int flags = 0;
+ if(mode & Camera::CLEARIMAGE)
+ mode |= D3DCLEAR_TARGET;
+ if(mode & Camera::CLEARZ)
+ mode |= D3DCLEAR_ZBUFFER;
+ if(mode & Camera::CLEARSTENCIL)
+ mode |= D3DCLEAR_STENCIL;
+ D3DCOLOR c = D3DCOLOR_RGBA(col->red, col->green, col->blue, col->alpha);
+
+ setRenderSurfaces(cam);
+
+ setViewport(cam->frameBuffer); // need to set this for the clear to work correctly
+ d3ddevice->Clear(0, nil, mode, c, 1.0f, 0);
+}
+
+static void
+showRaster(Raster *raster, uint32 flag)
+{
+ UINT interval = flag & Raster::FLIPWAITVSYNCH ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
+ if(d3d9Globals.present.PresentationInterval != interval){
+ d3d9Globals.present.PresentationInterval = interval;
+ releaseVideoMemory();
+ d3d::d3ddevice->Reset(&d3d9Globals.present);
+ restoreVideoMemory();
+ }
+
+ // not used but we want cameras to have rasters
+ assert(raster);
+ HRESULT res = d3ddevice->Present(nil, nil, 0, nil);
+
+ if(res == D3DERR_DEVICELOST){
+ res = d3ddevice->TestCooperativeLevel();
+ // lost while being minimized, not reset once we're back
+ if(res == D3DERR_DEVICENOTRESET){
+ releaseVideoMemory();
+ d3d::d3ddevice->Reset(&d3d9Globals.present);
+ restoreVideoMemory();
+ }
+ }
+}
+
+static bool32
+rasterRenderFast(Raster *raster, int32 x, int32 y)
+{
+ IDirect3DTexture9 *dsttex;
+ IDirect3DSurface9 *srcsurf, *dstsurf;
+ D3DSURFACE_DESC srcdesc, dstdesc;
+ RECT rect = { x, y, x, y };
+
+ Raster *src = raster;
+ Raster *dst = Raster::getCurrentContext();
+ D3dRaster *natdst = GETD3DRASTEREXT(dst);
+ D3dRaster *natsrc = GETD3DRASTEREXT(src);
+
+ switch(dst->type){
+ case Raster::CAMERATEXTURE:
+ switch(src->type){
+ case Raster::CAMERA:
+ dsttex = (IDirect3DTexture9*)natdst->texture;
+ dsttex->GetSurfaceLevel(0, &dstsurf);
+ assert(dstsurf);
+ dstsurf->GetDesc(&dstdesc);
+
+ d3ddevice->GetRenderTarget(0, &srcsurf);
+ assert(srcsurf);
+ srcsurf->GetDesc(&srcdesc);
+
+ rect.right += srcdesc.Width;
+ rect.bottom += srcdesc.Height;
+
+ d3ddevice->StretchRect(srcsurf, &rect, dstsurf, &rect, D3DTEXF_NONE);
+ dstsurf->Release();
+ srcsurf->Release();
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+//
+// Device
+//
+
+int
+findFormatDepth(uint32 format)
+{
+ // not all formats actually
+ switch(format){
+ case D3DFMT_R8G8B8: return 24;
+ case D3DFMT_A8R8G8B8: return 32;
+ case D3DFMT_X8R8G8B8: return 32;
+ case D3DFMT_R5G6B5: return 16;
+ case D3DFMT_X1R5G5B5: return 16;
+ case D3DFMT_A1R5G5B5: return 16;
+ case D3DFMT_A4R4G4B4: return 16;
+ case D3DFMT_R3G3B2: return 8;
+ case D3DFMT_A8: return 8;
+ case D3DFMT_A8R3G3B2: return 16;
+ case D3DFMT_X4R4G4B4: return 16;
+ case D3DFMT_A2B10G10R10: return 32;
+ case D3DFMT_A8B8G8R8: return 32;
+ case D3DFMT_X8B8G8R8: return 32;
+ case D3DFMT_G16R16: return 32;
+ case D3DFMT_A2R10G10B10: return 32;
+ case D3DFMT_A16B16G16R16: return 64;
+
+ case D3DFMT_L8: return 8;
+ case D3DFMT_D16: return 16;
+ case D3DFMT_D24S8: return 32;
+ case D3DFMT_D24X8: return 32;
+ case D3DFMT_D24X4S4: return 32;
+ case D3DFMT_D32: return 32;
+
+ default: return 0;
+ }
+}
+
+// the commented ones don't "work"
+static D3DFORMAT fbFormats[] = {
+// D3DFMT_A1R5G5B5,
+/// D3DFMT_A2R10G10B10, // works but let's not use it...
+// D3DFMT_A8R8G8B8,
+ D3DFMT_X8R8G8B8,
+// D3DFMT_X1R5G5B5,
+ D3DFMT_R5G6B5
+};
+
+static void
+addVideoMode(D3DDISPLAYMODE *mode)
+{
+ int i;
+
+ for(i = 1; i < d3d9Globals.numModes; i++){
+ if(d3d9Globals.modes[i].mode.Width == mode->Width &&
+ d3d9Globals.modes[i].mode.Height == mode->Height &&
+ d3d9Globals.modes[i].mode.Format == mode->Format){
+ // had this format already, remember highest refresh rate
+ if(mode->RefreshRate > d3d9Globals.modes[i].mode.RefreshRate)
+ d3d9Globals.modes[i].mode.RefreshRate = mode->RefreshRate;
+ return;
+ }
+ }
+
+ // none found, add
+ d3d9Globals.modes[d3d9Globals.numModes].mode = *mode;
+ d3d9Globals.modes[d3d9Globals.numModes].flags = VIDEOMODEEXCLUSIVE;
+ d3d9Globals.numModes++;
+}
+
+static void
+makeVideoModeList(void)
+{
+ int i, j;
+ D3DDISPLAYMODE mode;
+
+ d3d9Globals.numModes = 1;
+ for(i = 0; i < nelem(fbFormats); i++)
+ d3d9Globals.numModes += d3d9Globals.d3d9->GetAdapterModeCount(d3d9Globals.adapter, fbFormats[i]);
+
+ rwFree(d3d9Globals.modes);
+ d3d9Globals.modes = rwNewT(DisplayMode, d3d9Globals.numModes, ID_DRIVER | MEMDUR_EVENT);
+
+ // first mode is current mode as windowed
+ d3d9Globals.d3d9->GetAdapterDisplayMode(d3d9Globals.adapter, &d3d9Globals.modes[0].mode);
+ d3d9Globals.modes[0].flags = 0;
+ d3d9Globals.numModes = 1;
+
+ for(i = 0; i < nelem(fbFormats); i++){
+ int n = d3d9Globals.d3d9->GetAdapterModeCount(d3d9Globals.adapter, fbFormats[i]);
+ for(j = 0; j < n; j++){
+ d3d9Globals.d3d9->EnumAdapterModes(d3d9Globals.adapter, fbFormats[i], j, &mode);
+ addVideoMode(&mode);
+ }
+ }
+}
+
+static int
+openD3D(EngineOpenParams *params)
+{
+ HWND win = params->window;
+
+ d3d9Globals.window = win;
+ d3d9Globals.numAdapters = 0;
+ d3d9Globals.modes = nil;
+ d3d9Globals.numModes = 0;
+ d3d9Globals.currentMode = 0;
+
+ d3d9Globals.d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ if(d3d9Globals.d3d9 == nil){
+ RWERROR((ERR_GENERAL, "Direct3DCreate9() failed"));
+ return 0;
+ }
+
+ d3d9Globals.numAdapters = d3d9Globals.d3d9->GetAdapterCount();
+ d3d9Globals.adapter = 0;
+
+ for(d3d9Globals.adapter = 0; d3d9Globals.adapter < d3d9Globals.numAdapters; d3d9Globals.adapter++)
+ if(d3d9Globals.d3d9->GetDeviceCaps(d3d9Globals.adapter, D3DDEVTYPE_HAL, &d3d9Globals.caps) == D3D_OK)
+ goto found;
+ // no adapter
+ d3d9Globals.d3d9->Release();
+ d3d9Globals.d3d9 = nil;
+ RWERROR((ERR_GENERAL, "Direct3DCreate9() failed"));
+ return 0;
+
+found:
+ makeVideoModeList();
+ return 1;
+}
+
+static int
+closeD3D(void)
+{
+ ULONG ref = d3d9Globals.d3d9->Release();
+ if(ref != 0)
+ printf("IDirect3D9_Release did not destroy\n");
+ d3d9Globals.d3d9 = nil;
+ rwFree(d3d9Globals.modes);
+ d3d9Globals.modes = nil;
+ d3d9Globals.numModes = 0;
+ d3d9Globals.currentMode = 0;
+ return 1;
+}
+
+static int
+startD3D(void)
+{
+ HRESULT hr;
+ int vp;
+ if(d3d9Globals.caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
+ vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+
+ uint32 width, height, depth;
+ D3DFORMAT format, zformat;
+ d3d9Globals.startMode = d3d9Globals.modes[d3d9Globals.currentMode];
+ format = d3d9Globals.startMode.mode.Format;
+
+ bool windowed = !(d3d9Globals.startMode.flags & VIDEOMODEEXCLUSIVE);
+
+ // Use window size in windowed mode, otherwise get size from video mode
+ if(windowed){
+ RECT rect;
+ GetClientRect(d3d9Globals.window, &rect);
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ }else{
+ // this will be much better for restoring after iconification
+ SetWindowLong(d3d9Globals.window, GWL_STYLE, WS_POPUP);
+ width = d3d9Globals.startMode.mode.Width;
+ height = d3d9Globals.startMode.mode.Height;
+ }
+
+ // See if we can get an alpha channel
+ if(format == D3DFMT_X8R8G8B8){
+ if(d3d9Globals.d3d9->CheckDeviceType(d3d9Globals.adapter, D3DDEVTYPE_HAL, format, D3DFMT_A8R8G8B8, windowed) == D3D_OK)
+ format = D3DFMT_A8R8G8B8;
+ }
+
+ depth = findFormatDepth(format);
+
+ // TOOD: use something more sophisticated maybe?
+ if(depth == 32)
+ zformat = D3DFMT_D24S8;
+ else
+ zformat = D3DFMT_D16;
+
+ d3d9Globals.present.BackBufferWidth = width;
+ d3d9Globals.present.BackBufferHeight = height;
+ d3d9Globals.present.BackBufferFormat = format;
+ d3d9Globals.present.BackBufferCount = 1;
+ d3d9Globals.present.MultiSampleType = d3d9Globals.msLevel == 1 ?
+ D3DMULTISAMPLE_NONE : (D3DMULTISAMPLE_TYPE)d3d9Globals.msLevel;
+ d3d9Globals.present.MultiSampleQuality = 0;
+ d3d9Globals.present.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ d3d9Globals.present.hDeviceWindow = d3d9Globals.window;
+ d3d9Globals.present.Windowed = windowed;
+ d3d9Globals.present.EnableAutoDepthStencil = true;
+ d3d9Globals.present.AutoDepthStencilFormat = zformat;
+ d3d9Globals.present.Flags = 0;
+ d3d9Globals.present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+// d3d9Globals.present.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ d3d9Globals.present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+
+ rw::d3d::isP8supported = 0;
+
+ assert(d3d::d3ddevice == nil);
+
+ BOOL icon = IsIconic(d3d9Globals.window);
+ IDirect3DDevice9 *dev;
+ hr = d3d9Globals.d3d9->CreateDevice(d3d9Globals.adapter, D3DDEVTYPE_HAL,
+ d3d9Globals.window, vp, &d3d9Globals.present, &dev);
+ if(FAILED(hr)){
+ RWERROR((ERR_GENERAL, "CreateDevice() failed"));
+ return 0;
+ }
+ d3d::d3ddevice = dev;
+ return 1;
+}
+
+static int
+initD3D(void)
+{
+ int32 s, t;
+
+ memset(&deviceCache, 0, sizeof(deviceCache));
+ d3ddevice->GetRenderTarget(0, &d3d9Globals.defaultRenderTarget);
+ d3d9Globals.defaultRenderTarget->Release(); // refcount increased by Get
+ deviceCache.renderTargets[0] = d3d9Globals.defaultRenderTarget;
+ d3ddevice->GetDepthStencilSurface(&d3d9Globals.defaultDepthSurf);
+ d3d9Globals.defaultDepthSurf->Release(); // refcount increased by Get
+ deviceCache.depthSurface = d3d9Globals.defaultDepthSurf;
+
+ d3d9Globals.numTextures = 0;
+ d3d9Globals.numVertexShaders = 0;
+ d3d9Globals.numPixelShaders = 0;
+ d3d9Globals.numVertexBuffers = 0;
+ d3d9Globals.numIndexBuffers = 0;
+ d3d9Globals.numVertexDeclarations = 0;
+
+ VertexConstantData constants;
+ constants.normal.x = 0.0f;
+ constants.normal.y = 0.0f;
+ constants.normal.z = 0.0f;
+ constants.color.red = 0;
+ constants.color.green = 0;
+ constants.color.blue = 0;
+ constants.color.alpha = 255;
+ for(s = 0; s < 8; s++){
+ constants.texCoors[s].u = 0.0f;
+ constants.texCoors[s].v = 0.0f;
+ }
+ assert(constantVertexStream == nil);
+ constantVertexStream = createVertexBuffer(sizeof(constants)*10000, 0, false);
+ assert(constantVertexStream);
+ uint8 *lockedvertices = lockVertices(constantVertexStream, 0, sizeof(constants), D3DLOCK_NOSYSLOCK);
+ assert(lockedvertices);
+ memcpy(lockedvertices, &constants, sizeof(constants));
+ unlockVertices(constantVertexStream);
+ setStreamSource(2, constantVertexStream, 0, 0);
+
+ d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
+ rwStateCache.alphafunc = ALPHAGREATEREQUAL;
+ d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10);
+ rwStateCache.alpharef = 10;
+
+ rwStateCache.gsalpha = 0;
+ rwStateCache.gsalpharef = 128;
+
+ d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
+ rwStateCache.fogenable = 0;
+ d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
+
+ d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ rwStateCache.cullmode = CULLNONE;
+
+ d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ rwStateCache.srcblend = BLENDSRCALPHA;
+ d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ rwStateCache.destblend = BLENDINVSRCALPHA;
+ d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
+ rwStateCache.vertexAlpha = 0;
+ rwStateCache.textureAlpha = 0;
+
+ rwStateCache.stencilenable = 0;
+ d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ rwStateCache.stencilfail = STENCILKEEP;
+ d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
+ rwStateCache.stencilzfail = STENCILKEEP;
+ d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
+ rwStateCache.stencilpass = STENCILKEEP;
+ d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
+ rwStateCache.stencilfunc = STENCILALWAYS;
+ d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+ rwStateCache.stencilref = 0;
+ d3ddevice->SetRenderState(D3DRS_STENCILREF, 0);
+ rwStateCache.stencilmask = 0xFFFFFFFF;
+ d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
+ rwStateCache.stencilwritemask = 0xFFFFFFFF;
+ d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
+
+ setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF);
+// setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+// setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
+// setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT);
+
+ // These states exist, not all do
+ validStates[D3DRS_ZENABLE] = 1;
+ validStates[D3DRS_FILLMODE] = 1;
+ validStates[D3DRS_SHADEMODE] = 1;
+ validStates[D3DRS_ZWRITEENABLE] = 1;
+ validStates[D3DRS_ALPHATESTENABLE] = 1;
+ validStates[D3DRS_LASTPIXEL] = 1;
+ validStates[D3DRS_SRCBLEND] = 1;
+ validStates[D3DRS_DESTBLEND] = 1;
+ validStates[D3DRS_CULLMODE] = 1;
+ validStates[D3DRS_ZFUNC] = 1;
+ validStates[D3DRS_ALPHAREF] = 1;
+ validStates[D3DRS_ALPHAFUNC] = 1;
+ validStates[D3DRS_DITHERENABLE] = 1;
+ validStates[D3DRS_ALPHABLENDENABLE] = 1;
+ validStates[D3DRS_FOGENABLE] = 1;
+ validStates[D3DRS_SPECULARENABLE] = 1;
+ validStates[D3DRS_FOGCOLOR] = 1;
+ validStates[D3DRS_FOGTABLEMODE] = 1;
+ validStates[D3DRS_FOGSTART] = 1;
+ validStates[D3DRS_FOGEND] = 1;
+ validStates[D3DRS_FOGDENSITY] = 1;
+ validStates[D3DRS_RANGEFOGENABLE] = 1;
+ validStates[D3DRS_STENCILENABLE] = 1;
+ validStates[D3DRS_STENCILFAIL] = 1;
+ validStates[D3DRS_STENCILZFAIL] = 1;
+ validStates[D3DRS_STENCILPASS] = 1;
+ validStates[D3DRS_STENCILFUNC] = 1;
+ validStates[D3DRS_STENCILREF] = 1;
+ validStates[D3DRS_STENCILMASK] = 1;
+ validStates[D3DRS_STENCILWRITEMASK] = 1;
+ validStates[D3DRS_TEXTUREFACTOR] = 1;
+ validStates[D3DRS_WRAP0] = 1;
+ validStates[D3DRS_WRAP1] = 1;
+ validStates[D3DRS_WRAP2] = 1;
+ validStates[D3DRS_WRAP3] = 1;
+ validStates[D3DRS_WRAP4] = 1;
+ validStates[D3DRS_WRAP5] = 1;
+ validStates[D3DRS_WRAP6] = 1;
+ validStates[D3DRS_WRAP7] = 1;
+ validStates[D3DRS_CLIPPING] = 1;
+ validStates[D3DRS_LIGHTING] = 1;
+ validStates[D3DRS_AMBIENT] = 1;
+ validStates[D3DRS_FOGVERTEXMODE] = 1;
+ validStates[D3DRS_COLORVERTEX] = 1;
+ validStates[D3DRS_LOCALVIEWER] = 1;
+ validStates[D3DRS_NORMALIZENORMALS] = 1;
+ validStates[D3DRS_DIFFUSEMATERIALSOURCE] = 1;
+ validStates[D3DRS_SPECULARMATERIALSOURCE] = 1;
+ validStates[D3DRS_AMBIENTMATERIALSOURCE] = 1;
+ validStates[D3DRS_EMISSIVEMATERIALSOURCE] = 1;
+ validStates[D3DRS_VERTEXBLEND] = 1;
+ validStates[D3DRS_CLIPPLANEENABLE] = 1;
+ validStates[D3DRS_POINTSIZE] = 1;
+ validStates[D3DRS_POINTSIZE_MIN] = 1;
+ validStates[D3DRS_POINTSPRITEENABLE] = 1;
+ validStates[D3DRS_POINTSCALEENABLE] = 1;
+ validStates[D3DRS_POINTSCALE_A] = 1;
+ validStates[D3DRS_POINTSCALE_B] = 1;
+ validStates[D3DRS_POINTSCALE_C] = 1;
+ validStates[D3DRS_MULTISAMPLEANTIALIAS] = 1;
+ validStates[D3DRS_MULTISAMPLEMASK] = 1;
+ validStates[D3DRS_PATCHEDGESTYLE] = 1;
+ validStates[D3DRS_DEBUGMONITORTOKEN] = 1;
+ validStates[D3DRS_POINTSIZE_MAX] = 1;
+ validStates[D3DRS_INDEXEDVERTEXBLENDENABLE] = 1;
+ validStates[D3DRS_COLORWRITEENABLE] = 1;
+ validStates[D3DRS_TWEENFACTOR] = 1;
+ validStates[D3DRS_BLENDOP] = 1;
+ validStates[D3DRS_POSITIONDEGREE] = 1;
+ validStates[D3DRS_NORMALDEGREE] = 1;
+ validStates[D3DRS_SCISSORTESTENABLE] = 1;
+ validStates[D3DRS_SLOPESCALEDEPTHBIAS] = 1;
+ validStates[D3DRS_ANTIALIASEDLINEENABLE] = 1;
+ validStates[D3DRS_MINTESSELLATIONLEVEL] = 1;
+ validStates[D3DRS_MAXTESSELLATIONLEVEL] = 1;
+ validStates[D3DRS_ADAPTIVETESS_X] = 1;
+ validStates[D3DRS_ADAPTIVETESS_Y] = 1;
+ validStates[D3DRS_ADAPTIVETESS_Z] = 1;
+ validStates[D3DRS_ADAPTIVETESS_W] = 1;
+ validStates[D3DRS_ENABLEADAPTIVETESSELLATION] = 1;
+ validStates[D3DRS_TWOSIDEDSTENCILMODE] = 1;
+ validStates[D3DRS_CCW_STENCILFAIL] = 1;
+ validStates[D3DRS_CCW_STENCILZFAIL] = 1;
+ validStates[D3DRS_CCW_STENCILPASS] = 1;
+ validStates[D3DRS_CCW_STENCILFUNC] = 1;
+ validStates[D3DRS_COLORWRITEENABLE1] = 1;
+ validStates[D3DRS_COLORWRITEENABLE2] = 1;
+ validStates[D3DRS_COLORWRITEENABLE3] = 1;
+ validStates[D3DRS_BLENDFACTOR] = 1;
+ validStates[D3DRS_SRGBWRITEENABLE] = 1;
+ validStates[D3DRS_DEPTHBIAS] = 1;
+ validStates[D3DRS_WRAP8] = 1;
+ validStates[D3DRS_WRAP9] = 1;
+ validStates[D3DRS_WRAP10] = 1;
+ validStates[D3DRS_WRAP11] = 1;
+ validStates[D3DRS_WRAP12] = 1;
+ validStates[D3DRS_WRAP13] = 1;
+ validStates[D3DRS_WRAP14] = 1;
+ validStates[D3DRS_WRAP15] = 1;
+ validStates[D3DRS_SEPARATEALPHABLENDENABLE] = 1;
+ validStates[D3DRS_SRCBLENDALPHA] = 1;
+ validStates[D3DRS_DESTBLENDALPHA] = 1;
+ validStates[D3DRS_BLENDOPALPHA] = 1;
+
+ validTexStates[D3DTSS_COLOROP] = 1;
+ validTexStates[D3DTSS_COLORARG1] = 1;
+ validTexStates[D3DTSS_COLORARG2] = 1;
+ validTexStates[D3DTSS_ALPHAOP] = 1;
+ validTexStates[D3DTSS_ALPHAARG1] = 1;
+ validTexStates[D3DTSS_ALPHAARG2] = 1;
+ validTexStates[D3DTSS_BUMPENVMAT00] = 1;
+ validTexStates[D3DTSS_BUMPENVMAT01] = 1;
+ validTexStates[D3DTSS_BUMPENVMAT10] = 1;
+ validTexStates[D3DTSS_BUMPENVMAT11] = 1;
+ validTexStates[D3DTSS_TEXCOORDINDEX] = 1;
+ validTexStates[D3DTSS_BUMPENVLSCALE] = 1;
+ validTexStates[D3DTSS_BUMPENVLOFFSET] = 1;
+ validTexStates[D3DTSS_TEXTURETRANSFORMFLAGS] = 1;
+ validTexStates[D3DTSS_COLORARG0] = 1;
+ validTexStates[D3DTSS_ALPHAARG0] = 1;
+ validTexStates[D3DTSS_RESULTARG] = 1;
+ validTexStates[D3DTSS_CONSTANT] = 1;
+
+ // Save the current states
+ for(s = 0; s < MAXNUMSTATES; s++)
+ if(validStates[s]){
+ d3ddevice->GetRenderState((D3DRENDERSTATETYPE)s, (DWORD*)&d3dStates[s]);
+ stateCache[s].value = d3dStates[s];
+ }
+ for(t = 0; t < MAXNUMTEXSTATES; t++)
+ if(validTexStates[t])
+ for(s = 0; s < MAXNUMSTAGES; s++){
+ d3ddevice->GetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, (DWORD*)&d3dTextureStageStates[t][s]);
+ textureStageStateCache[t][s].value = d3dTextureStageStates[t][s];
+ }
+ for(t = 1; t < MAXNUMSAMPLERSTATES; t++)
+ for(s = 0; s < MAXNUMSTAGES; s++){
+ d3ddevice->GetSamplerState(s, (D3DSAMPLERSTATETYPE)t, (DWORD*)&d3dSamplerStates[t][s]);
+ d3dSamplerStates[t][s] = d3dSamplerStates[t][s];
+ }
+ // init rw cache
+ for(t = 0; t < MAXNUMSTAGES; t++){
+ setFilterMode(t, Texture::NEAREST);
+ setAddressU(t, Texture::WRAP);
+ setAddressV(t, Texture::WRAP);
+ }
+
+ IDirect3DSurface9 *surf;
+ D3DLOCKED_RECT lr;
+ uint8 whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+ whiteTex = (IDirect3DTexture9*)createTexture(1, 1, 1, 0, D3DFMT_X8R8G8B8);
+ whiteTex->GetSurfaceLevel(0, &surf);
+ HRESULT res = surf->LockRect(&lr, 0, D3DLOCK_NOSYSLOCK);
+ assert(res == D3D_OK);
+ memcpy(lr.pBits, whitepixel, 4);
+ surf->UnlockRect();
+ surf->Release();
+
+ openIm2D();
+ openIm3D();
+
+ return 1;
+}
+
+static int
+termD3D(void)
+{
+ destroyVertexBuffer(constantVertexStream);
+ constantVertexStream = nil;
+
+ destroyTexture(whiteTex);
+ whiteTex = nil;
+
+ closeIm3D();
+ closeIm2D();
+
+ releaseVideoMemory();
+
+ ULONG ref = d3d::d3ddevice->Release();
+ if(ref != 0)
+ printf("IDirect3D9Device_Release did not destroy\n");
+ d3d::d3ddevice = nil;
+ return 1;
+}
+
+static int
+finalizeD3D(void)
+{
+ return 1;
+}
+
+static int
+deviceSystem(DeviceReq req, void *arg, int32 n)
+{
+ D3DADAPTER_IDENTIFIER9 adapter;
+ VideoMode *rwmode;
+
+ switch(req){
+ case DEVICEOPEN:
+ return openD3D((EngineOpenParams*)arg);
+ case DEVICECLOSE:
+ return closeD3D();
+
+ case DEVICEINIT:
+ return startD3D() && initD3D();
+ case DEVICETERM:
+ return termD3D();
+
+ case DEVICEFINALIZE:
+ return finalizeD3D();
+
+
+ case DEVICEGETNUMSUBSYSTEMS:
+ return d3d9Globals.numAdapters;
+
+ case DEVICEGETCURRENTSUBSYSTEM:
+ return d3d9Globals.adapter;
+
+ case DEVICESETSUBSYSTEM:
+ if(n >= d3d9Globals.numAdapters)
+ return 0;
+ d3d9Globals.adapter = n;
+ if(d3d9Globals.d3d9->GetDeviceCaps(d3d9Globals.adapter, D3DDEVTYPE_HAL, &d3d9Globals.caps) != D3D_OK)
+ return 0;
+ makeVideoModeList();
+ return 1;
+
+ case DEVICEGETSUBSSYSTEMINFO:
+ if(n >= d3d9Globals.numAdapters)
+ return 0;
+ if(d3d9Globals.d3d9->GetAdapterIdentifier(d3d9Globals.adapter, 0, &adapter) != D3D_OK)
+ return 0;
+ strncpy(((SubSystemInfo*)arg)->name, adapter.Description, sizeof(SubSystemInfo::name));
+ return 1;
+
+
+ case DEVICEGETNUMVIDEOMODES:
+ return d3d9Globals.numModes;
+
+ case DEVICEGETCURRENTVIDEOMODE:
+ return d3d9Globals.currentMode;
+
+ case DEVICESETVIDEOMODE:
+ if(n >= d3d9Globals.numModes)
+ return 0;
+ d3d9Globals.currentMode = n;
+ return 1;
+
+ case DEVICEGETVIDEOMODEINFO:
+ rwmode = (VideoMode*)arg;
+ rwmode->width = d3d9Globals.modes[n].mode.Width;
+ rwmode->height = d3d9Globals.modes[n].mode.Height;
+ rwmode->depth = findFormatDepth(d3d9Globals.modes[n].mode.Format);
+ rwmode->flags = d3d9Globals.modes[n].flags;
+ return 1;
+ case DEVICEGETMAXMULTISAMPLINGLEVELS:
+ {
+ assert(d3d9Globals.d3d9 != nil);
+ uint32 level;
+ DWORD quality;
+ for (level = D3DMULTISAMPLE_16_SAMPLES; level > D3DMULTISAMPLE_NONMASKABLE; level--) {
+ if (SUCCEEDED(d3d9Globals.d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9Globals.startMode.mode.Format,
+ !(d3d9Globals.startMode.flags & VIDEOMODEEXCLUSIVE), (D3DMULTISAMPLE_TYPE)level,
+ &quality)))
+ return level;
+ }
+ }
+ return 1;
+ case DEVICEGETMULTISAMPLINGLEVELS:
+ if(d3d9Globals.msLevel == 0)
+ return 1;
+ return d3d9Globals.msLevel;
+ case DEVICESETMULTISAMPLINGLEVELS:
+ d3d9Globals.msLevel = (uint32)n;
+ return 1;
+ }
+ return 1;
+}
+
+Device renderdevice = {
+ 0.0f, 1.0f,
+ d3d::beginUpdate,
+ d3d::endUpdate,
+ d3d::clearCamera,
+ d3d::showRaster,
+ d3d::rasterRenderFast,
+ d3d::setRwRenderState,
+ d3d::getRwRenderState,
+ d3d::im2DRenderLine,
+ d3d::im2DRenderTriangle,
+ d3d::im2DRenderPrimitive,
+ d3d::im2DRenderIndexedPrimitive,
+ d3d::im3DTransform,
+ d3d::im3DRenderPrimitive,
+ d3d::im3DRenderIndexedPrimitive,
+ d3d::im3DEnd,
+ d3d::deviceSystem,
+};
+
+#endif
+}
+}
diff --git a/src/d3d/d3dimmed.cpp b/src/d3d/d3dimmed.cpp
new file mode 100644
index 0000000..e0df9d9
--- /dev/null
+++ b/src/d3d/d3dimmed.cpp
@@ -0,0 +1,404 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwplg.h"
+#include "../rwrender.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+#include "rwd3d9.h"
+#include "rwd3dimpl.h"
+
+namespace rw {
+namespace d3d {
+
+#ifdef RW_D3D9
+
+// might want to tweak this
+#define NUMINDICES 10000
+#define NUMVERTICES 10000
+
+static int primTypeMap[] = {
+ D3DPT_POINTLIST, // invalid
+ D3DPT_LINELIST,
+ D3DPT_LINESTRIP,
+ D3DPT_TRIANGLELIST,
+ D3DPT_TRIANGLESTRIP,
+ D3DPT_TRIANGLEFAN,
+ D3DPT_POINTLIST, // actually not supported!
+};
+
+static IDirect3DVertexDeclaration9 *im2ddecl;
+static IDirect3DVertexBuffer9 *im2dvertbuf;
+static IDirect3DIndexBuffer9 *im2dindbuf;
+
+void *im2dOverridePS;
+
+void
+openIm2D(void)
+{
+ D3DVERTEXELEMENT9 elements[4] = {
+// can't get proper fog with this :(
+// { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
+ { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+ { 0, offsetof(Im2DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
+ { 0, offsetof(Im2DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
+ D3DDECL_END()
+ };
+ assert(im2ddecl == nil);
+ im2ddecl = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
+ assert(im2ddecl);
+
+ assert(im2dvertbuf == nil);
+ im2dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertex), 0, true);
+ assert(im2dvertbuf);
+ addDynamicVB(NUMVERTICES*sizeof(Im2DVertex), 0, &im2dvertbuf);
+
+ assert(im2dindbuf == nil);
+ im2dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16), true);
+ assert(im2dindbuf);
+ addDynamicIB(NUMINDICES*sizeof(uint16), &im2dindbuf);
+}
+
+void
+closeIm2D(void)
+{
+ d3d9::destroyVertexDeclaration(im2ddecl);
+ im2ddecl = nil;
+
+ removeDynamicVB(&im2dvertbuf);
+ destroyVertexBuffer(im2dvertbuf);
+ im2dvertbuf = nil;
+
+ removeDynamicIB(&im2dindbuf);
+ destroyIndexBuffer(im2dindbuf);
+ im2dindbuf = nil;
+}
+
+static Im2DVertex tmpprimbuf[3];
+
+void
+im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
+{
+ Im2DVertex *verts = (Im2DVertex*)vertices;
+ tmpprimbuf[0] = verts[vert1];
+ tmpprimbuf[1] = verts[vert2];
+ im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
+}
+
+void
+im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
+{
+ Im2DVertex *verts = (Im2DVertex*)vertices;
+ tmpprimbuf[0] = verts[vert1];
+ tmpprimbuf[1] = verts[vert2];
+ tmpprimbuf[2] = verts[vert3];
+ im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
+}
+
+void
+im2DSetXform(void)
+{
+ float xform[4];
+ Camera *cam;
+ cam = (Camera*)engine->currentCamera;
+ xform[0] = 2.0f/cam->frameBuffer->width;
+ xform[1] = -2.0f/cam->frameBuffer->height;
+ xform[2] = -1.0f;
+ xform[3] = 1.0f;
+ // TODO: should cache this...
+ d3ddevice->SetVertexShaderConstantF(VSLOC_afterLights, xform, 1);
+}
+
+void
+im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
+{
+ if(numVertices > NUMVERTICES){
+ // TODO: error
+ return;
+ }
+ uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_DISCARD);
+ memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
+ unlockVertices(im2dvertbuf);
+
+ setStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
+ setVertexDeclaration(im2ddecl);
+
+ im2DSetXform();
+
+ setVertexShader(im2d_VS);
+ if(im2dOverridePS)
+ setPixelShader(im2dOverridePS);
+ else if(engine->device.getRenderState(TEXTURERASTER))
+ setPixelShader(im2d_tex_PS);
+ else
+ setPixelShader(im2d_PS);
+
+ d3d::flushCache();
+
+ uint32 primCount = 0;
+ switch(primType){
+ case PRIMTYPELINELIST:
+ primCount = numVertices/2;
+ break;
+ case PRIMTYPEPOLYLINE:
+ primCount = numVertices-1;
+ break;
+ case PRIMTYPETRILIST:
+ primCount = numVertices/3;
+ break;
+ case PRIMTYPETRISTRIP:
+ primCount = numVertices-2;
+ break;
+ case PRIMTYPETRIFAN:
+ primCount = numVertices-2;
+ break;
+ case PRIMTYPEPOINTLIST:
+ primCount = numVertices;
+ break;
+ }
+ d3ddevice->DrawPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, primCount);
+}
+
+void
+im2DRenderIndexedPrimitive(PrimitiveType primType,
+ void *vertices, int32 numVertices, void *indices, int32 numIndices)
+{
+ if(numVertices > NUMVERTICES ||
+ numIndices > NUMINDICES){
+ // TODO: error
+ return;
+ }
+ uint16 *lockedindices = lockIndices(im2dindbuf, 0, numIndices*sizeof(uint16), D3DLOCK_DISCARD);
+ memcpy(lockedindices, indices, numIndices*sizeof(uint16));
+ unlockIndices(im2dindbuf);
+
+ uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_DISCARD);
+ memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex));
+ unlockVertices(im2dvertbuf);
+
+ setStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
+ setIndices(im2dindbuf);
+ setVertexDeclaration(im2ddecl);
+
+ im2DSetXform();
+
+ setVertexShader(im2d_VS);
+ if(im2dOverridePS)
+ setPixelShader(im2dOverridePS);
+ else if(engine->device.getRenderState(TEXTURERASTER))
+ setPixelShader(im2d_tex_PS);
+ else
+ setPixelShader(im2d_PS);
+
+ d3d::flushCache();
+
+ uint32 primCount = 0;
+ switch(primType){
+ case PRIMTYPELINELIST:
+ primCount = numIndices/2;
+ break;
+ case PRIMTYPEPOLYLINE:
+ primCount = numIndices-1;
+ break;
+ case PRIMTYPETRILIST:
+ primCount = numIndices/3;
+ break;
+ case PRIMTYPETRISTRIP:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPETRIFAN:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPEPOINTLIST:
+ primCount = numIndices;
+ break;
+ }
+ d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
+ 0, numVertices,
+ 0, primCount);
+}
+
+
+// Im3D
+
+
+static IDirect3DVertexDeclaration9 *im3ddecl;
+static IDirect3DVertexBuffer9 *im3dvertbuf;
+static IDirect3DIndexBuffer9 *im3dindbuf;
+static int32 num3DVertices;
+
+void
+openIm3D(void)
+{
+ D3DVERTEXELEMENT9 elements[5] = {
+ { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+ { 0, offsetof(Im3DVertex, normal), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
+ { 0, offsetof(Im3DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
+ { 0, offsetof(Im3DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
+ D3DDECL_END()
+ };
+
+ assert(im3ddecl == nil);
+ im3ddecl = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);
+ assert(im3ddecl);
+
+ assert(im3dvertbuf == nil);
+ im3dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im3DVertex), 0, true);
+ assert(im3dvertbuf);
+ addDynamicVB(NUMVERTICES*sizeof(Im3DVertex), 0, &im3dvertbuf);
+
+ assert(im3dindbuf == nil);
+ im3dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16), true);
+ assert(im3dindbuf);
+ addDynamicIB(NUMINDICES*sizeof(uint16), &im3dindbuf);
+}
+
+void
+closeIm3D(void)
+{
+ d3d9::destroyVertexDeclaration(im3ddecl);
+ im3ddecl = nil;
+
+ removeDynamicVB(&im3dvertbuf);
+ destroyVertexBuffer(im3dvertbuf);
+ im3dvertbuf = nil;
+
+ removeDynamicIB(&im3dindbuf);
+ destroyIndexBuffer(im3dindbuf);
+ im3dindbuf = nil;
+}
+
+// settable by user - TOOD: make this less shit
+RGBA im3dMaterialColor = { 255, 255, 255, 255 };
+SurfaceProperties im3dSurfaceProps = { 1.0f, 1.0f, 1.0f };
+
+void
+im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags)
+{
+ if(world == nil)
+ uploadMatrices();
+ else
+ uploadMatrices(world);
+
+ if((flags & im3d::VERTEXUV) == 0)
+ SetRenderStatePtr(TEXTURERASTER, nil);
+
+ void *shader = default_amb_VS;
+ if(flags & im3d::LIGHTING){
+ setMaterial(im3dMaterialColor, im3dSurfaceProps);
+ int32 vsBits = lightingCB_Shader();
+ // Pick a shader
+ if((vsBits & VSLIGHT_MASK) == 0)
+ shader = default_amb_VS;
+ else if((vsBits & VSLIGHT_MASK) == VSLIGHT_DIRECT)
+ shader = default_amb_dir_VS;
+ else
+ shader = default_all_VS;
+ }else{
+ static RGBA white = { 255, 255, 255, 255 };
+ static SurfaceProperties surfprops = { 0.0f, 0.0f, 0.0f };
+ setMaterial(white, surfprops);
+ }
+
+ uint8 *lockedvertices = lockVertices(im3dvertbuf, 0, numVertices*sizeof(Im3DVertex), D3DLOCK_DISCARD);
+ memcpy(lockedvertices, vertices, numVertices*sizeof(Im3DVertex));
+ unlockVertices(im3dvertbuf);
+
+ setStreamSource(0, im3dvertbuf, 0, sizeof(Im3DVertex));
+ setVertexDeclaration(im3ddecl);
+
+ setVertexShader(shader);
+
+ num3DVertices = numVertices;
+}
+
+void
+im3DRenderPrimitive(PrimitiveType primType)
+{
+ if(engine->device.getRenderState(TEXTURERASTER))
+ setPixelShader(default_tex_PS);
+ else
+ setPixelShader(default_PS);
+
+ d3d::flushCache();
+
+ uint32 primCount = 0;
+ switch(primType){
+ case PRIMTYPELINELIST:
+ primCount = num3DVertices/2;
+ break;
+ case PRIMTYPEPOLYLINE:
+ primCount = num3DVertices-1;
+ break;
+ case PRIMTYPETRILIST:
+ primCount = num3DVertices/3;
+ break;
+ case PRIMTYPETRISTRIP:
+ primCount = num3DVertices-2;
+ break;
+ case PRIMTYPETRIFAN:
+ primCount = num3DVertices-2;
+ break;
+ case PRIMTYPEPOINTLIST:
+ primCount = num3DVertices;
+ break;
+ }
+ d3ddevice->DrawPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, primCount);
+}
+
+void
+im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices)
+{
+ uint16 *lockedindices = lockIndices(im3dindbuf, 0, numIndices*sizeof(uint16), D3DLOCK_DISCARD);
+ memcpy(lockedindices, indices, numIndices*sizeof(uint16));
+ unlockIndices(im3dindbuf);
+
+ setIndices(im3dindbuf);
+
+ if(engine->device.getRenderState(TEXTURERASTER))
+ setPixelShader(default_tex_PS);
+ else
+ setPixelShader(default_PS);
+
+ d3d::flushCache();
+
+ uint32 primCount = 0;
+ switch(primType){
+ case PRIMTYPELINELIST:
+ primCount = numIndices/2;
+ break;
+ case PRIMTYPEPOLYLINE:
+ primCount = numIndices-1;
+ break;
+ case PRIMTYPETRILIST:
+ primCount = numIndices/3;
+ break;
+ case PRIMTYPETRISTRIP:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPETRIFAN:
+ primCount = numIndices-2;
+ break;
+ case PRIMTYPEPOINTLIST:
+ primCount = numIndices;
+ break;
+ }
+ d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,
+ 0, num3DVertices,
+ 0, primCount);
+}
+
+void
+im3DEnd(void)
+{
+}
+
+#endif
+}
+}
diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp
new file mode 100644
index 0000000..d135d87
--- /dev/null
+++ b/src/d3d/d3drender.cpp
@@ -0,0 +1,424 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define WITH_D3D
+#include "../rwbase.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwd3d.h"
+
+namespace rw {
+namespace d3d {
+
+#ifdef RW_D3D9
+IDirect3DDevice9 *d3ddevice = nil;
+
+#define MAX_LIGHTS 8
+
+
+#define VS_NAME g_vs20_main
+#define PS_NAME g_ps20_main
+void *default_amb_VS;
+void *default_amb_dir_VS;
+void *default_all_VS;
+void *default_PS;
+void *default_tex_PS;
+void *im2d_VS;
+void *im2d_PS;
+void *im2d_tex_PS;
+
+
+void
+createDefaultShaders(void)
+{
+ {
+ static
+#include "shaders/default_amb_VS.h"
+ default_amb_VS = createVertexShader((void*)VS_NAME);
+ assert(default_amb_VS);
+ }
+ {
+ static
+#include "shaders/default_amb_dir_VS.h"
+ default_amb_dir_VS = createVertexShader((void*)VS_NAME);
+ assert(default_amb_dir_VS);
+ }
+ {
+ static
+#include "shaders/default_all_VS.h"
+ default_all_VS = createVertexShader((void*)VS_NAME);
+ assert(default_all_VS);
+ }
+
+ {
+ static
+#include "shaders/default_PS.h"
+ default_PS = createPixelShader((void*)PS_NAME);
+ assert(default_PS);
+ }
+ {
+ static
+#include "shaders/default_tex_PS.h"
+ default_tex_PS = createPixelShader((void*)PS_NAME);
+ assert(default_tex_PS);
+ }
+
+ {
+ static
+#include "shaders/im2d_VS.h"
+ im2d_VS = createVertexShader((void*)VS_NAME);
+ assert(im2d_VS);
+ }
+ {
+ static
+#include "shaders/im2d_PS.h"
+ im2d_PS = createPixelShader((void*)PS_NAME);
+ assert(im2d_PS);
+ }
+ {
+ static
+#include "shaders/im2d_tex_PS.h"
+ im2d_tex_PS = createPixelShader((void*)PS_NAME);
+ assert(im2d_tex_PS);
+ }
+}
+
+void
+destroyDefaultShaders(void)
+{
+ destroyVertexShader(default_amb_VS);
+ default_amb_VS = nil;
+ destroyVertexShader(default_amb_dir_VS);
+ default_amb_dir_VS = nil;
+ destroyVertexShader(default_all_VS);
+ default_all_VS = nil;
+
+ destroyPixelShader(default_PS);
+ default_PS = nil;
+ destroyPixelShader(default_tex_PS);
+ default_tex_PS = nil;
+
+ destroyVertexShader(im2d_VS);
+ im2d_VS = nil;
+ destroyPixelShader(im2d_PS);
+ im2d_PS = nil;
+ destroyPixelShader(im2d_tex_PS);
+ im2d_tex_PS = nil;
+}
+
+
+void
+lightingCB_Fix(Atomic *atomic)
+{
+ WorldLights lightData;
+ Light *directionals[8];
+ Light *locals[8];
+ lightData.directionals = directionals;
+ lightData.numDirectionals = 8;
+ lightData.locals = locals;
+ lightData.numLocals = 8;
+
+ ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
+
+ int i, n;
+ RGBA amb;
+ D3DLIGHT9 light;
+ light.Type = D3DLIGHT_DIRECTIONAL;
+ //light.Diffuse = { 0.8f, 0.8f, 0.8f, 1.0f };
+ light.Specular = { 0.0f, 0.0f, 0.0f, 0.0f };
+ light.Ambient = { 0.0f, 0.0f, 0.0f, 0.0f };
+ light.Position = { 0.0f, 0.0f, 0.0f };
+ //light.Direction = { 0.0f, 0.0f, -1.0f };
+ light.Range = 0.0f;
+ light.Falloff = 0.0f;
+ light.Attenuation0 = 0.0f;
+ light.Attenuation1 = 0.0f;
+ light.Attenuation2 = 0.0f;
+ light.Theta = 0.0f;
+ light.Phi = 0.0f;
+
+ convColor(&amb, &lightData.ambient);
+ d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha));
+
+ n = 0;
+ for(i = 0; i < lightData.numDirectionals; i++){
+ if(n >= MAX_LIGHTS)
+ return;
+ Light *l = lightData.directionals[i];
+ light.Type = D3DLIGHT_DIRECTIONAL;
+ light.Diffuse = *(D3DCOLORVALUE*)&l->color;
+ light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
+ d3ddevice->SetLight(n, &light);
+ d3ddevice->LightEnable(n, TRUE);
+ n++;
+ }
+
+ for(i = 0; i < lightData.numLocals; i++){
+ if(n >= MAX_LIGHTS)
+ return;
+ Light *l = lightData.locals[i];
+ switch(l->getType()){
+ case Light::POINT:
+ light.Type = D3DLIGHT_POINT;
+ light.Diffuse = *(D3DCOLORVALUE*)&l->color;
+ light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
+ light.Direction.x = 0.0f;
+ light.Direction.y = 0.0f;
+ light.Direction.z = 0.0f;
+ light.Range = l->radius;
+ light.Falloff = 1.0f;
+ light.Attenuation0 = 1.0f;
+ light.Attenuation1 = 0.0f/l->radius;
+ light.Attenuation2 = 5.0f/(l->radius*l->radius);
+ d3ddevice->SetLight(n, &light);
+ d3ddevice->LightEnable(n, TRUE);
+ n++;
+ break;
+
+ case Light::SPOT:
+ light.Type = D3DLIGHT_SPOT;
+ light.Diffuse = *(D3DCOLORVALUE*)&l->color;
+ light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
+ light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
+ light.Range = l->radius;
+ light.Falloff = 1.0f;
+ light.Attenuation0 = 1.0f;
+ light.Attenuation1 = 0.0f/l->radius;
+ light.Attenuation2 = 5.0f/(l->radius*l->radius);
+ light.Theta = l->getAngle()*2.0f;
+ light.Phi = light.Theta;
+ d3ddevice->SetLight(n, &light);
+ d3ddevice->LightEnable(n, TRUE);
+ n++;
+ break;
+
+ case Light::SOFTSPOT:
+ light.Type = D3DLIGHT_SPOT;
+ light.Diffuse = *(D3DCOLORVALUE*)&l->color;
+ light.Position = *(D3DVECTOR*)&l->getFrame()->getLTM()->pos;
+ light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at;
+ light.Range = l->radius;
+ light.Falloff = 1.0f;
+ light.Attenuation0 = 1.0f;
+ light.Attenuation1 = 0.0f/l->radius;
+ light.Attenuation2 = 5.0f/(l->radius*l->radius);
+ light.Theta = 0.0f;
+ light.Phi = l->getAngle()*2.0f;
+ d3ddevice->SetLight(n, &light);
+ d3ddevice->LightEnable(n, TRUE);
+ n++;
+ break;
+ }
+ }
+
+ for(; n < MAX_LIGHTS; n++)
+ d3ddevice->LightEnable(n, FALSE);
+}
+
+
+struct LightVS
+{
+ V3d color; float param0;
+ V3d position; float param1;
+ V3d direction; float param2;
+};
+
+void
+setAmbient(const RGBAf &color)
+{
+ if(!equal(d3dShaderState.ambient, color)){
+ d3dShaderState.ambient = color;
+ d3ddevice->SetVertexShaderConstantF(VSLOC_ambLight, (float*)&color, 1);
+ }
+}
+
+void
+setNumLights(int numDir, int numPoint, int numSpot)
+{
+ static int32 numLights[4*3];
+ if(d3dShaderState.numDir != numDir ||
+ d3dShaderState.numPoint != numPoint ||
+ d3dShaderState.numSpot != numSpot){
+ numLights[0] = d3dShaderState.numDir = numDir;
+ numLights[4] = d3dShaderState.numPoint = numPoint;
+ numLights[8] = d3dShaderState.numSpot = numSpot;
+ d3ddevice->SetVertexShaderConstantI(VSLOC_numLights, numLights, 3);
+ }
+}
+
+int32
+uploadLights(WorldLights *lightData)
+{
+ int i;
+ int bits = 0;
+ float32 firstLight[4];
+ firstLight[0] = 0; // directional
+ firstLight[1] = 0; // point
+ firstLight[2] = 0; // spot
+ firstLight[3] = 0;
+
+ if(lightData->numAmbients)
+ bits |= VSLIGHT_AMBIENT;
+
+ LightVS directionals[8];
+ LightVS points[8];
+ LightVS spots[8];
+ for(i = 0; i < lightData->numDirectionals; i++){
+ Light *l = lightData->directionals[i];
+ directionals[i].color.x = l->color.red;
+ directionals[i].color.y = l->color.green;
+ directionals[i].color.z = l->color.blue;
+ directionals[i].direction = l->getFrame()->getLTM()->at;
+ bits |= VSLIGHT_DIRECT;
+ }
+
+ int np = 0;
+ int ns = 0;
+ for(i = 0; i < lightData->numLocals; i++){
+ Light *l = lightData->locals[i];
+
+ switch(l->getType()){
+ case Light::POINT:
+ points[np].color.x = l->color.red;
+ points[np].color.y = l->color.green;
+ points[np].color.z = l->color.blue;
+ points[np].param0 = l->radius;
+ points[np].position = l->getFrame()->getLTM()->pos;
+ np++;
+ bits |= VSLIGHT_POINT;
+ break;
+ case Light::SPOT:
+ case Light::SOFTSPOT:
+ spots[ns].color.x = l->color.red;
+ spots[ns].color.y = l->color.green;
+ spots[ns].color.z = l->color.blue;
+ spots[ns].param0 = l->radius;
+ spots[ns].position = l->getFrame()->getLTM()->pos;
+ spots[ns].direction = l->getFrame()->getLTM()->at;
+ spots[ns].param1 = l->minusCosAngle;
+ // lower bound of falloff
+ if(l->getType() == Light::SOFTSPOT)
+ spots[ns].param2 = 0.0f;
+ else
+ spots[ns].param2 = 1.0f;
+ bits |= VSLIGHT_SPOT;
+ ns++;
+ break;
+ }
+ }
+
+ firstLight[0] = 0;
+ int numDir = lightData->numDirectionals;
+ firstLight[1] = numDir + firstLight[0];
+ int numPoint = np;
+ firstLight[2] = numPoint + firstLight[1];
+ int numSpot = ns;
+
+ setNumLights(numDir, numPoint, numSpot);
+ if(d3dShaderState.lightOffset[0] != firstLight[0] ||
+ d3dShaderState.lightOffset[1] != firstLight[1] ||
+ d3dShaderState.lightOffset[2] != firstLight[2]){
+ d3dShaderState.lightOffset[0] = firstLight[0];
+ d3dShaderState.lightOffset[1] = firstLight[1];
+ d3dShaderState.lightOffset[2] = firstLight[2];
+ d3ddevice->SetVertexShaderConstantF(VSLOC_lightOffset, firstLight, 1);
+ }
+
+ int32 off = VSLOC_lights;
+ if(numDir)
+ d3ddevice->SetVertexShaderConstantF(off, (float*)&directionals, numDir*3);
+ off += numDir*3;
+
+ if(numPoint)
+ d3ddevice->SetVertexShaderConstantF(off, (float*)&points, numPoint*3);
+ off += numPoint*3;
+
+ if(numSpot)
+ d3ddevice->SetVertexShaderConstantF(off, (float*)&spots, numSpot*3);
+
+ return bits;
+}
+
+int32
+lightingCB_Shader(Atomic *atomic)
+{
+ WorldLights lightData;
+ Light *directionals[8];
+ Light *locals[8];
+ lightData.directionals = directionals;
+ lightData.numDirectionals = 8;
+ lightData.locals = locals;
+ lightData.numLocals = 8;
+
+ if(atomic->geometry->flags & rw::Geometry::LIGHT){
+ ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
+ setAmbient(lightData.ambient);
+ return uploadLights(&lightData);
+ }else{
+ static const RGBAf black = { 0.0f, 0.0f, 0.0f, 0.0f };
+ setAmbient(black);
+ setNumLights(0, 0, 0);
+ return 0;
+ }
+}
+
+int32
+lightingCB_Shader(void)
+{
+ WorldLights lightData;
+ Light *directionals[8];
+ Light *locals[8];
+ lightData.directionals = directionals;
+ lightData.numDirectionals = 8;
+ lightData.locals = locals;
+ lightData.numLocals = 8;
+
+ ((World*)engine->currentWorld)->enumerateLights(&lightData);
+ setAmbient(lightData.ambient);
+ return uploadLights(&lightData);
+}
+
+static RawMatrix identityXform = {
+ { 1.0f, 0.0f, 0.0f }, 0.0f,
+ { 0.0f, 1.0f, 0.0f }, 0.0f,
+ { 0.0f, 0.0f, 1.0f }, 0.0f,
+ { 0.0f, 0.0f, 0.0f }, 1.0f
+};
+
+void
+uploadMatrices(void)
+{
+ RawMatrix combined;
+ Camera *cam = engine->currentCamera;
+ d3ddevice->SetVertexShaderConstantF(VSLOC_world, (float*)&identityXform, 4);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_normal, (float*)&identityXform, 4);
+
+ RawMatrix::mult(&combined, &cam->devView, &cam->devProj);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&combined, 4);
+}
+
+void
+uploadMatrices(Matrix *worldMat)
+{
+ RawMatrix combined, world, worldview;
+ Camera *cam = engine->currentCamera;
+ convMatrix(&world, worldMat);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_world, (float*)&world, 4);
+ // TODO: inverse transpose
+ d3ddevice->SetVertexShaderConstantF(VSLOC_normal, (float*)&world, 4);
+
+ RawMatrix::mult(&worldview, &world, &cam->devView);
+ RawMatrix::mult(&combined, &worldview, &cam->devProj);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&combined, 4);
+}
+
+
+
+#endif
+
+}
+}
diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h
new file mode 100644
index 0000000..cabfeff
--- /dev/null
+++ b/src/d3d/rwd3d.h
@@ -0,0 +1,421 @@
+#ifdef RW_D3D9
+#ifdef WITH_D3D
+#include <d3d9.h>
+#endif
+#endif
+
+namespace rw {
+
+#ifdef RW_D3D9
+
+#ifdef _WINDOWS_
+struct EngineOpenParams
+{
+ HWND window;
+};
+#else
+struct EngineOpenParams
+{
+ uint32 please_include_windows_h;
+};
+#endif
+#else
+#ifdef _D3D9_H_
+#error "please don't include d3d9.h for non-d3d9 platforms"
+#endif
+#endif
+
+namespace d3d {
+
+extern bool32 isP8supported;
+
+extern Device renderdevice;
+
+#ifdef RW_D3D9
+#ifdef _D3D9_H_
+extern IDirect3DDevice9 *d3ddevice;
+void setD3dMaterial(D3DMATERIAL9 *mat9);
+#endif
+
+#define COLOR_ARGB(a, r, g, b) ((rw::uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
+
+struct Im3DVertex
+{
+ V3d position;
+ V3d normal; // librw extension
+ uint32 color;
+ float32 u, v;
+
+ void setX(float32 x) { this->position.x = x; }
+ void setY(float32 y) { this->position.y = y; }
+ void setZ(float32 z) { this->position.z = z; }
+ void setNormalX(float32 x) { this->normal.x = x; }
+ void setNormalY(float32 y) { this->normal.y = y; }
+ void setNormalZ(float32 z) { this->normal.z = z; }
+ void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = COLOR_ARGB(a, r, g, b); }
+ void setU(float32 u) { this->u = u; }
+ void setV(float32 v) { this->v = v; }
+
+ float getX(void) { return this->position.x; }
+ float getY(void) { return this->position.y; }
+ float getZ(void) { return this->position.z; }
+ float getNormalX(void) { return this->normal.x; }
+ float getNormalY(void) { return this->normal.y; }
+ float getNormalZ(void) { return this->normal.z; }
+ RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF,
+ this->color & 0xFF, this->color>>24 & 0xFF); }
+ float getU(void) { return this->u; }
+ float getV(void) { return this->v; }
+};
+extern RGBA im3dMaterialColor;
+extern SurfaceProperties im3dSurfaceProps;
+
+struct Im2DVertex
+{
+ float32 x, y, z;
+ //float32 q; // recipz no longer used because we have a vertex stage now
+ float32 w;
+ uint32 color;
+ float32 u, v;
+
+ void setScreenX(float32 x) { this->x = x; }
+ void setScreenY(float32 y) { this->y = y; }
+ void setScreenZ(float32 z) { this->z = z; }
+ void setCameraZ(float32 z) { this->w = z; }
+// void setRecipCameraZ(float32 recipz) { this->q = recipz; }
+ void setRecipCameraZ(float32 recipz) { this->w = 1.0f/recipz; }
+ void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = COLOR_ARGB(a, r, g, b); }
+ void setU(float32 u, float recipZ) { this->u = u; }
+ void setV(float32 v, float recipZ) { this->v = v; }
+
+ float getScreenX(void) { return this->x; }
+ float getScreenY(void) { return this->y; }
+ float getScreenZ(void) { return this->z; }
+// float getCameraZ(void) { return 1.0f/this->q; }
+// float getRecipCameraZ(void) { return this->q; }
+ float getCameraZ(void) { return this->w; }
+ float getRecipCameraZ(void) { return 1.0f/this->w; }
+ RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF,
+ this->color & 0xFF, this->color>>24 & 0xFF); }
+ float getU(void) { return this->u; }
+ float getV(void) { return this->v; }
+};
+
+#else
+#ifndef MAKEFOURCC
+#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \
+ ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
+#endif
+enum {
+ D3DFMT_UNKNOWN = 0,
+
+ D3DFMT_R8G8B8 = 20,
+ D3DFMT_A8R8G8B8 = 21,
+ D3DFMT_X8R8G8B8 = 22,
+ D3DFMT_R5G6B5 = 23,
+ D3DFMT_X1R5G5B5 = 24,
+ D3DFMT_A1R5G5B5 = 25,
+ D3DFMT_A4R4G4B4 = 26,
+ D3DFMT_R3G3B2 = 27,
+ D3DFMT_A8 = 28,
+ D3DFMT_A8R3G3B2 = 29,
+ D3DFMT_X4R4G4B4 = 30,
+ D3DFMT_A2B10G10R10 = 31,
+ D3DFMT_A8B8G8R8 = 32,
+ D3DFMT_X8B8G8R8 = 33,
+ D3DFMT_G16R16 = 34,
+ D3DFMT_A2R10G10B10 = 35,
+ D3DFMT_A16B16G16R16 = 36,
+
+ D3DFMT_A8P8 = 40,
+ D3DFMT_P8 = 41,
+
+ D3DFMT_L8 = 50,
+ D3DFMT_A8L8 = 51,
+ D3DFMT_A4L4 = 52,
+
+ D3DFMT_V8U8 = 60,
+ D3DFMT_L6V5U5 = 61,
+ D3DFMT_X8L8V8U8 = 62,
+ D3DFMT_Q8W8V8U8 = 63,
+ D3DFMT_V16U16 = 64,
+ D3DFMT_A2W10V10U10 = 67,
+
+ D3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'),
+ D3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'),
+ D3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'),
+ D3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'),
+ D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'),
+ D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'),
+ D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'),
+ D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'),
+ D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'),
+
+ D3DFMT_D16_LOCKABLE = 70,
+ D3DFMT_D32 = 71,
+ D3DFMT_D15S1 = 73,
+ D3DFMT_D24S8 = 75,
+ D3DFMT_D24X8 = 77,
+ D3DFMT_D24X4S4 = 79,
+ D3DFMT_D16 = 80,
+
+ D3DFMT_D32F_LOCKABLE = 82,
+ D3DFMT_D24FS8 = 83,
+
+ // d3d9ex only
+ /* Z-Stencil formats valid for CPU access */
+ D3DFMT_D32_LOCKABLE = 84,
+ D3DFMT_S8_LOCKABLE = 85,
+
+ D3DFMT_L16 = 81,
+
+ D3DFMT_VERTEXDATA =100,
+ D3DFMT_INDEX16 =101,
+ D3DFMT_INDEX32 =102,
+
+ D3DFMT_Q16W16V16U16 =110,
+
+ D3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'),
+
+ // Floating point surface formats
+
+ // s10e5 formats (16-bits per channel)
+ D3DFMT_R16F = 111,
+ D3DFMT_G16R16F = 112,
+ D3DFMT_A16B16G16R16F = 113,
+
+ // IEEE s23e8 formats (32-bits per channel)
+ D3DFMT_R32F = 114,
+ D3DFMT_G32R32F = 115,
+ D3DFMT_A32B32G32R32F = 116,
+
+ D3DFMT_CxV8U8 = 117,
+
+ // d3d9ex only
+ // Monochrome 1 bit per pixel format
+ D3DFMT_A1 = 118,
+ // 2.8 biased fixed point
+ D3DFMT_A2B10G10R10_XR_BIAS = 119,
+ // Binary format indicating that the data has no inherent type
+ D3DFMT_BINARYBUFFER = 199
+};
+
+enum {
+ D3DLOCK_NOSYSLOCK = 0, // ignored
+ D3DPOOL_MANAGED = 0, // ignored
+ D3DPT_TRIANGLELIST = 4,
+ D3DPT_TRIANGLESTRIP = 5,
+
+
+ D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
+ D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
+ D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
+ D3DDECLTYPE_FLOAT4 = 3, // 4D float
+ D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
+ // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
+ D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
+ D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
+ D3DDECLTYPE_SHORT4 = 7, // 4D signed short
+
+ D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
+ D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
+ D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
+ D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
+ D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
+ D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
+ D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
+ D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
+ D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
+ D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
+
+
+ D3DDECLMETHOD_DEFAULT = 0,
+
+
+ D3DDECLUSAGE_POSITION = 0,
+ D3DDECLUSAGE_BLENDWEIGHT, // 1
+ D3DDECLUSAGE_BLENDINDICES, // 2
+ D3DDECLUSAGE_NORMAL, // 3
+ D3DDECLUSAGE_PSIZE, // 4
+ D3DDECLUSAGE_TEXCOORD, // 5
+ D3DDECLUSAGE_TANGENT, // 6
+ D3DDECLUSAGE_BINORMAL, // 7
+ D3DDECLUSAGE_TESSFACTOR, // 8
+ D3DDECLUSAGE_POSITIONT, // 9
+ D3DDECLUSAGE_COLOR, // 10
+ D3DDECLUSAGE_FOG, // 11
+ D3DDECLUSAGE_DEPTH, // 12
+ D3DDECLUSAGE_SAMPLE // 13
+ ,
+
+ D3DUSAGE_AUTOGENMIPMAP = 0x400
+};
+#endif
+
+extern int vertFormatMap[];
+
+void *createIndexBuffer(uint32 length, bool dynamic);
+void destroyIndexBuffer(void *indexBuffer);
+uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags);
+void unlockIndices(void *indexBuffer);
+
+void *createVertexBuffer(uint32 length, uint32 fvf, bool dynamic);
+void destroyVertexBuffer(void *vertexBuffer);
+uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
+void unlockVertices(void *vertexBuffer);
+
+void *createTexture(int32 width, int32 height, int32 levels, uint32 usage, uint32 format);
+void destroyTexture(void *texture);
+uint8 *lockTexture(void *texture, int32 level);
+void unlockTexture(void *texture, int32 level);
+
+// Native Texture and Raster
+
+struct D3dRaster
+{
+ void *texture;
+ void *palette;
+ void *lockedSurf;
+ uint32 format;
+ uint32 bpp; // bytes per pixel
+ bool hasAlpha;
+ bool customFormat;
+ bool autogenMipmap;
+};
+
+int32 getLevelSize(Raster *raster, int32 level);
+void allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha);
+void setPalette(Raster *raster, void *palette, int32 size);
+void setTexels(Raster *raster, void *texels, int32 level);
+
+extern int32 nativeRasterOffset;
+void registerNativeRaster(void);
+#define GETD3DRASTEREXT(raster) PLUGINOFFSET(rw::d3d::D3dRaster, raster, rw::d3d::nativeRasterOffset)
+
+// Rendering
+
+void setRenderState(uint32 state, uint32 value);
+void getRenderState(uint32 state, uint32 *value);
+void setTextureStageState(uint32 stage, uint32 type, uint32 value);
+void getTextureStageState(uint32 stage, uint32 type, uint32 *value);
+void setSamplerState(uint32 stage, uint32 type, uint32 value);
+void getSamplerState(uint32 stage, uint32 type, uint32 *value);
+void flushCache(void);
+
+void setTexture(uint32 stage, Texture *tex);
+void setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f);
+inline void setMaterial(uint32 flags, const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f)
+{
+ static RGBA white = { 255, 255, 255, 255 };
+ if(flags & Geometry::MODULATE)
+ setMaterial(color, surfaceprops, extraSurfProp);
+ else
+ setMaterial(white, surfaceprops, extraSurfProp);
+}
+
+void setVertexShader(void *vs);
+void setPixelShader(void *ps);
+void setIndices(void *indexBuffer);
+void setStreamSource(int n, void *buffer, uint32 offset, uint32 stride);
+void setVertexDeclaration(void *declaration);
+
+void *createVertexShader(void *csosrc);
+void *createPixelShader(void *csosrc);
+void destroyVertexShader(void *shader);
+void destroyPixelShader(void *shader);
+
+
+/*
+ * Vertex shaders and common pipeline stuff
+ */
+
+// This data will be available in vertex stream 2
+struct VertexConstantData
+{
+ V3d normal;
+ RGBA color;
+ TexCoords texCoors[8];
+};
+extern void *constantVertexStream;
+
+// TODO: figure out why this even still exists...
+struct D3dShaderState
+{
+ // for VS
+ struct {
+ float32 start;
+ float32 end;
+ float32 range; // 1/(start-end)
+ float32 disable; // lower clamp
+ } fogData, fogDisable;
+ RGBA matColor;
+ SurfaceProperties surfProps;
+ float extraSurfProp;
+ float lightOffset[3];
+ int32 numDir, numPoint, numSpot;
+ RGBAf ambient;
+ // for PS
+ RGBAf fogColor;
+
+ bool fogDirty;
+};
+extern D3dShaderState d3dShaderState;
+
+// Standard Vertex shader locations
+enum
+{
+ VSLOC_combined = 0,
+ VSLOC_world = 4,
+ VSLOC_normal = 8,
+ VSLOC_matColor = 12,
+ VSLOC_surfProps = 13,
+ VSLOC_fogData = 14,
+ VSLOC_ambLight = 15,
+ VSLOC_lightOffset = 16,
+ VSLOC_lights = 17,
+ VSLOC_afterLights = VSLOC_lights + 8*3,
+
+ VSLOC_numLights = 0,
+
+ PSLOC_fogColor = 0
+};
+
+// Vertex shader bits
+enum
+{
+ // These should be low so they could be used as indices
+ VSLIGHT_DIRECT = 1,
+ VSLIGHT_POINT = 2,
+ VSLIGHT_SPOT = 4,
+ VSLIGHT_MASK = 7, // all the above
+ // less critical
+ VSLIGHT_AMBIENT = 8,
+};
+
+void lightingCB_Fix(Atomic *atomic);
+int32 lightingCB_Shader(Atomic *atomic);
+int32 lightingCB_Shader(void);
+// for VS
+void uploadMatrices(void); // no world transform
+void uploadMatrices(Matrix *worldMat);
+void setAmbient(const RGBAf &color);
+void setNumLights(int numDir, int numPoint, int numSpot);
+int32 uploadLights(WorldLights *lightData); // called by lightingCB_Shader
+
+extern void *im2dOverridePS;
+
+extern void *default_amb_VS;
+extern void *default_amb_dir_VS;
+extern void *default_all_VS;
+extern void *default_PS;
+extern void *default_tex_PS;
+extern void *im2d_VS;
+extern void *im2d_PS;
+extern void *im2d_tex_PS;
+void createDefaultShaders(void);
+void destroyDefaultShaders(void);
+
+
+}
+}
diff --git a/src/d3d/rwd3d8.h b/src/d3d/rwd3d8.h
new file mode 100644
index 0000000..422379d
--- /dev/null
+++ b/src/d3d/rwd3d8.h
@@ -0,0 +1,74 @@
+namespace rw {
+namespace d3d8 {
+
+void registerPlatformPlugins(void);
+
+struct InstanceData
+{
+ uint32 minVert;
+ int32 stride;
+ int32 numVertices;
+ int32 numIndices;
+ Material *material;
+ uint32 vertexShader;
+ uint32 primType;
+ void *indexBuffer;
+ void *vertexBuffer;
+ uint32 baseIndex;
+ uint8 vertexAlpha;
+ uint8 managed;
+ uint8 remapped;
+};
+
+struct InstanceDataHeader : rw::InstanceDataHeader
+{
+ uint16 serialNumber;
+ uint16 numMeshes;
+
+ InstanceData *inst;
+};
+
+uint32 makeFVFDeclaration(uint32 flags, int32 numTex);
+int32 getStride(uint32 flags, int32 numTex);
+
+void *destroyNativeData(void *object, int32, int32);
+Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
+Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
+int32 getSizeNativeData(void *object, int32, int32);
+void registerNativeDataPlugin(void);
+
+class ObjPipeline : public rw::ObjPipeline
+{
+public:
+ void init(void);
+ static ObjPipeline *create(void);
+
+ void (*instanceCB)(Geometry *geo, InstanceData *header);
+ void (*uninstanceCB)(Geometry *geo, InstanceData *header);
+ void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
+};
+
+void defaultInstanceCB(Geometry *geo, InstanceData *header);
+void defaultUninstanceCB(Geometry *geo, InstanceData *header);
+void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
+
+ObjPipeline *makeDefaultPipeline(void);
+
+// Skin plugin
+
+void initSkin(void);
+ObjPipeline *makeSkinPipeline(void);
+
+// MatFX plugin
+
+void initMatFX(void);
+ObjPipeline *makeMatFXPipeline(void);
+
+// Native Texture and Raster
+
+Texture *readNativeTexture(Stream *stream);
+void writeNativeTexture(Texture *tex, Stream *stream);
+uint32 getSizeNativeTexture(Texture *tex);
+
+}
+}
diff --git a/src/d3d/rwd3d9.h b/src/d3d/rwd3d9.h
new file mode 100644
index 0000000..03eccd5
--- /dev/null
+++ b/src/d3d/rwd3d9.h
@@ -0,0 +1,112 @@
+namespace rw {
+namespace d3d9 {
+
+void registerPlatformPlugins(void);
+
+struct VertexElement
+{
+ uint16 stream;
+ uint16 offset;
+ uint8 type;
+ uint8 method;
+ uint8 usage;
+ uint8 usageIndex;
+};
+
+struct VertexStream
+{
+ void *vertexBuffer;
+ uint32 offset;
+ uint32 stride;
+ uint16 geometryFlags;
+ uint8 managed;
+ uint8 dynamicLock;
+};
+
+struct InstanceData
+{
+ uint32 numIndex;
+ uint32 minVert;
+ Material *material;
+ bool32 vertexAlpha;
+ void *vertexShader;
+ uint32 baseIndex;
+ uint32 numVertices;
+ uint32 startIndex;
+ uint32 numPrimitives;
+};
+
+struct InstanceDataHeader : rw::InstanceDataHeader
+{
+ uint32 serialNumber;
+ uint32 numMeshes;
+ void *indexBuffer;
+ uint32 primType;
+ VertexStream vertexStream[2];
+ bool32 useOffsets;
+ void *vertexDeclaration;
+ uint32 totalNumIndex;
+ uint32 totalNumVertex;
+
+ InstanceData *inst;
+};
+
+void *createVertexDeclaration(VertexElement *elements);
+void destroyVertexDeclaration(void *delaration);
+uint32 getDeclaration(void *declaration, VertexElement *elements);
+
+void drawInst_simple(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst);
+// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
+void drawInst_GSemu(d3d9::InstanceDataHeader *header, InstanceData *inst);
+// This one switches between the above two depending on render state;
+void drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst);
+
+
+
+
+void *destroyNativeData(void *object, int32, int32);
+Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
+Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
+int32 getSizeNativeData(void *object, int32, int32);
+void registerNativeDataPlugin(void);
+
+class ObjPipeline : public rw::ObjPipeline
+{
+public:
+ void init(void);
+ static ObjPipeline *create(void);
+
+ void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
+ void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
+ void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
+};
+
+void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
+void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
+void defaultRenderCB_Fix(Atomic *atomic, InstanceDataHeader *header);
+void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header);
+
+ObjPipeline *makeDefaultPipeline(void);
+
+
+// Skin plugin
+
+void initSkin(void);
+void uploadSkinMatrices(Atomic *atomic);
+void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
+void skinRenderCB(Atomic *atomic, InstanceDataHeader *header);
+ObjPipeline *makeSkinPipeline(void);
+
+// MatFX plugin
+
+void initMatFX(void);
+ObjPipeline *makeMatFXPipeline(void);
+
+// Native Texture and Raster
+
+Texture *readNativeTexture(Stream *stream);
+void writeNativeTexture(Texture *tex, Stream *stream);
+uint32 getSizeNativeTexture(Texture *tex);
+
+}
+}
diff --git a/src/d3d/rwd3dimpl.h b/src/d3d/rwd3dimpl.h
new file mode 100644
index 0000000..82f8a13
--- /dev/null
+++ b/src/d3d/rwd3dimpl.h
@@ -0,0 +1,81 @@
+namespace rw {
+namespace d3d {
+
+#ifdef RW_D3D9
+void openIm2D(void);
+void closeIm2D(void);
+void im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2);
+void im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3);
+void im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices);
+void im2DRenderIndexedPrimitive(PrimitiveType primType, void *vertices, int32 numVertices, void *indices, int32 numIndices);
+
+void openIm3D(void);
+void closeIm3D(void);
+void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags);
+void im3DRenderPrimitive(PrimitiveType primType);
+void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices);
+void im3DEnd(void);
+
+
+struct DisplayMode
+{
+ D3DDISPLAYMODE mode;
+ uint32 flags;
+};
+
+struct D3d9Globals
+{
+ HWND window;
+
+ IDirect3D9 *d3d9;
+ int numAdapters;
+ int adapter;
+ D3DCAPS9 caps;
+ DisplayMode *modes;
+ int numModes;
+ int currentMode;
+ DisplayMode startMode;
+
+ uint32 msLevel;
+
+ D3DPRESENT_PARAMETERS present;
+
+ IDirect3DSurface9 *defaultRenderTarget;
+ IDirect3DSurface9 *defaultDepthSurf;
+
+ int numTextures;
+ int numVertexShaders;
+ int numPixelShaders;
+ int numVertexBuffers;
+ int numIndexBuffers;
+ int numVertexDeclarations;
+};
+
+extern D3d9Globals d3d9Globals;
+
+void addVidmemRaster(Raster *raster);
+void removeVidmemRaster(Raster *raster);
+
+void addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf); // NB: don't share this pointer
+void removeDynamicVB(IDirect3DVertexBuffer9 **buf);
+
+void addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf); // NB: don't share this pointer
+void removeDynamicIB(IDirect3DIndexBuffer9 **buf);
+
+
+int findFormatDepth(uint32 format);
+void evictD3D9Raster(Raster *raster);
+
+#endif
+
+Raster *rasterCreate(Raster *raster);
+uint8 *rasterLock(Raster *raster, int32 level, int32 lockMode);
+void rasterUnlock(Raster *raster, int32 level);
+int32 rasterNumLevels(Raster *raster);
+bool32 imageFindRasterFormat(Image *img, int32 type,
+ int32 *width, int32 *height, int32 *depth, int32 *format);
+bool32 rasterFromImage(Raster *raster, Image *image);
+Image *rasterToImage(Raster *raster);
+
+}
+}
diff --git a/src/d3d/rwxbox.h b/src/d3d/rwxbox.h
new file mode 100644
index 0000000..1abebe1
--- /dev/null
+++ b/src/d3d/rwxbox.h
@@ -0,0 +1,195 @@
+namespace rw {
+namespace xbox {
+
+void registerPlatformPlugins(void);
+
+extern int v3dFormatMap[6];
+extern int v2dFormatMap[6];
+
+struct InstanceData
+{
+ uint32 minVert;
+ int32 numVertices;
+ int32 numIndices;
+ void *indexBuffer;
+ Material *material;
+ uint32 vertexShader;
+};
+
+struct InstanceDataHeader : rw::InstanceDataHeader
+{
+ int32 size;
+ uint16 serialNumber;
+ uint16 numMeshes;
+ uint32 primType;
+ int32 numVertices;
+ int32 stride;
+ void *vertexBuffer;
+ bool32 vertexAlpha;
+ InstanceData *begin;
+ InstanceData *end;
+
+ uint8 *data;
+};
+
+void *destroyNativeData(void *object, int32, int32);
+Stream *readNativeData(Stream *stream, int32 len, void *object, int32, int32);
+Stream *writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
+int32 getSizeNativeData(void *object, int32, int32);
+void registerNativeDataPlugin(void);
+
+class ObjPipeline : public rw::ObjPipeline
+{
+public:
+ void init(void);
+ static ObjPipeline *create(void);
+
+ void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
+ void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
+};
+
+ObjPipeline *makeDefaultPipeline(void);
+
+void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header);
+void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
+
+// Skin plugin
+
+Stream *readNativeSkin(Stream *stream, int32, void *object, int32 offset);
+Stream *writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
+int32 getSizeNativeSkin(void *object, int32 offset);
+
+void initSkin(void);
+ObjPipeline *makeSkinPipeline(void);
+
+// MatFX plugin
+
+void initMatFX(void);
+ObjPipeline *makeMatFXPipeline(void);
+
+// Vertex Format plugin
+
+extern uint32 vertexFormatSizes[6];
+
+uint32 *getVertexFmt(Geometry *g);
+uint32 makeVertexFmt(int32 flags, uint32 numTexSets);
+uint32 getVertexFmtStride(uint32 fmt);
+
+void registerVertexFormatPlugin(void);
+
+// Native Texture and Raster
+
+struct XboxRaster
+{
+ void *texture;
+ void *palette;
+ uint32 format;
+ uint32 bpp; // bytes per pixel
+ bool hasAlpha;
+ bool customFormat;
+ bool32 unknownFlag;
+};
+
+int32 getLevelSize(Raster *raster, int32 level);
+
+extern int32 nativeRasterOffset;
+void registerNativeRaster(void);
+#define GETXBOXRASTEREXT(raster) PLUGINOFFSET(rw::xbox::XboxRaster, raster, rw::xbox::nativeRasterOffset)
+
+Texture *readNativeTexture(Stream *stream);
+void writeNativeTexture(Texture *tex, Stream *stream);
+uint32 getSizeNativeTexture(Texture *tex);
+
+enum {
+ D3DFMT_UNKNOWN = 0xFFFFFFFF,
+
+ /* Swizzled formats */
+
+ D3DFMT_A8R8G8B8 = 0x00000006,
+ D3DFMT_X8R8G8B8 = 0x00000007,
+ D3DFMT_R5G6B5 = 0x00000005,
+ D3DFMT_R6G5B5 = 0x00000027,
+ D3DFMT_X1R5G5B5 = 0x00000003,
+ D3DFMT_A1R5G5B5 = 0x00000002,
+ D3DFMT_A4R4G4B4 = 0x00000004,
+ D3DFMT_A8 = 0x00000019,
+ D3DFMT_A8B8G8R8 = 0x0000003A,
+ D3DFMT_B8G8R8A8 = 0x0000003B,
+ D3DFMT_R4G4B4A4 = 0x00000039,
+ D3DFMT_R5G5B5A1 = 0x00000038,
+ D3DFMT_R8G8B8A8 = 0x0000003C,
+ D3DFMT_R8B8 = 0x00000029,
+ D3DFMT_G8B8 = 0x00000028,
+
+ D3DFMT_P8 = 0x0000000B,
+
+ D3DFMT_L8 = 0x00000000,
+ D3DFMT_A8L8 = 0x0000001A,
+ D3DFMT_AL8 = 0x00000001,
+ D3DFMT_L16 = 0x00000032,
+
+ D3DFMT_V8U8 = 0x00000028,
+ D3DFMT_L6V5U5 = 0x00000027,
+ D3DFMT_X8L8V8U8 = 0x00000007,
+ D3DFMT_Q8W8V8U8 = 0x0000003A,
+ D3DFMT_V16U16 = 0x00000033,
+
+ D3DFMT_D16_LOCKABLE = 0x0000002C,
+ D3DFMT_D16 = 0x0000002C,
+ D3DFMT_D24S8 = 0x0000002A,
+ D3DFMT_F16 = 0x0000002D,
+ D3DFMT_F24S8 = 0x0000002B,
+
+ /* YUV formats */
+
+ D3DFMT_YUY2 = 0x00000024,
+ D3DFMT_UYVY = 0x00000025,
+
+ /* Compressed formats */
+
+ D3DFMT_DXT1 = 0x0000000C,
+ D3DFMT_DXT2 = 0x0000000E,
+ D3DFMT_DXT3 = 0x0000000E,
+ D3DFMT_DXT4 = 0x0000000F,
+ D3DFMT_DXT5 = 0x0000000F,
+
+ /* Linear formats */
+
+ D3DFMT_LIN_A1R5G5B5 = 0x00000010,
+ D3DFMT_LIN_A4R4G4B4 = 0x0000001D,
+ D3DFMT_LIN_A8 = 0x0000001F,
+ D3DFMT_LIN_A8B8G8R8 = 0x0000003F,
+ D3DFMT_LIN_A8R8G8B8 = 0x00000012,
+ D3DFMT_LIN_B8G8R8A8 = 0x00000040,
+ D3DFMT_LIN_G8B8 = 0x00000017,
+ D3DFMT_LIN_R4G4B4A4 = 0x0000003E,
+ D3DFMT_LIN_R5G5B5A1 = 0x0000003D,
+ D3DFMT_LIN_R5G6B5 = 0x00000011,
+ D3DFMT_LIN_R6G5B5 = 0x00000037,
+ D3DFMT_LIN_R8B8 = 0x00000016,
+ D3DFMT_LIN_R8G8B8A8 = 0x00000041,
+ D3DFMT_LIN_X1R5G5B5 = 0x0000001C,
+ D3DFMT_LIN_X8R8G8B8 = 0x0000001E,
+
+ D3DFMT_LIN_A8L8 = 0x00000020,
+ D3DFMT_LIN_AL8 = 0x0000001B,
+ D3DFMT_LIN_L16 = 0x00000035,
+ D3DFMT_LIN_L8 = 0x00000013,
+
+ D3DFMT_LIN_V16U16 = 0x00000036,
+ D3DFMT_LIN_V8U8 = 0x00000017,
+ D3DFMT_LIN_L6V5U5 = 0x00000037,
+ D3DFMT_LIN_X8L8V8U8 = 0x0000001E,
+ D3DFMT_LIN_Q8W8V8U8 = 0x00000012,
+
+ D3DFMT_LIN_D24S8 = 0x0000002E,
+ D3DFMT_LIN_F24S8 = 0x0000002F,
+ D3DFMT_LIN_D16 = 0x00000030,
+ D3DFMT_LIN_F16 = 0x00000031,
+
+ D3DFMT_VERTEXDATA = 100,
+ D3DFMT_INDEX16 = 101
+};
+
+}
+}
diff --git a/src/d3d/rwxboximpl.h b/src/d3d/rwxboximpl.h
new file mode 100644
index 0000000..524ec28
--- /dev/null
+++ b/src/d3d/rwxboximpl.h
@@ -0,0 +1,11 @@
+namespace rw {
+namespace xbox {
+
+Raster *rasterCreate(Raster *raster);
+uint8 *rasterLock(Raster *raster, int32 level, int32 lockMode);
+void rasterUnlock(Raster*, int32);
+int32 rasterNumLevels(Raster *raster);
+Image *rasterToImage(Raster *raster);
+
+}
+}
diff --git a/src/d3d/shaders/default_PS.h b/src/d3d/shaders/default_PS.h
new file mode 100644
index 0000000..9f2cb31
--- /dev/null
+++ b/src/d3d/shaders/default_PS.h
@@ -0,0 +1,72 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /Fh default_PS.h default_PS.hlsl
+//
+//
+// Parameters:
+//
+// float4 fogColor;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl v0
+ add r0.xyz, v0, -c0
+ mad r0.xyz, t0.z, r0, c0
+ mov r0.w, v0.w
+ mov oC0, r0
+
+// approximately 4 instruction slots used
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 34, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 83, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 76, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 60, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 67, 111, 108,
+ 111, 114, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 7, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 2, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 144,
+ 0, 0, 228, 161, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 0, 0, 170, 176, 0, 0,
+ 228, 128, 0, 0, 228, 160,
+ 1, 0, 0, 2, 0, 0,
+ 8, 128, 0, 0, 255, 144,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/default_PS.hlsl b/src/d3d/shaders/default_PS.hlsl
new file mode 100644
index 0000000..eaf279d
--- /dev/null
+++ b/src/d3d/shaders/default_PS.hlsl
@@ -0,0 +1,19 @@
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+sampler2D tex0 : register(s0);
+
+float4 fogColor : register(c0);
+
+float4 main(VS_out input) : COLOR
+{
+ float4 color = input.Color;
+#ifdef TEX
+ color *= tex2D(tex0, input.TexCoord0.xy);
+#endif
+ color.rgb = lerp(fogColor.rgb, color.rgb, input.TexCoord0.z);
+ return color;
+}
diff --git a/src/d3d/shaders/default_VS.hlsl b/src/d3d/shaders/default_VS.hlsl
new file mode 100644
index 0000000..d2f5452
--- /dev/null
+++ b/src/d3d/shaders/default_VS.hlsl
@@ -0,0 +1,51 @@
+#include "standardConstants.h"
+
+struct VS_in
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float2 TexCoord : TEXCOORD0;
+ float4 Prelight : COLOR0;
+};
+
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0; // also fog
+ float4 Color : COLOR0;
+};
+
+
+VS_out main(in VS_in input)
+{
+ VS_out output;
+
+ output.Position = mul(combinedMat, input.Position);
+ float3 Vertex = mul(worldMat, input.Position).xyz;
+ float3 Normal = mul(normalMat, input.Normal);
+
+ output.TexCoord0.xy = input.TexCoord;
+
+ output.Color = input.Prelight;
+ output.Color.rgb += ambientLight.rgb * surfAmbient;
+
+ int i;
+#ifdef DIRECTIONALS
+ for(i = 0; i < numDirLights; i++)
+ output.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse;
+#endif
+#ifdef POINTLIGHTS
+ for(i = 0; i < numPointLights; i++)
+ output.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse;
+#endif
+#ifdef SPOTLIGHTS
+ for(i = 0; i < numSpotLights; i++)
+ output.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse;
+#endif
+ // PS2 clamps before material color
+ output.Color = clamp(output.Color, 0.0, 1.0);
+ output.Color *= matCol;
+
+ output.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);
+
+ return output;
+}
diff --git a/src/d3d/shaders/default_all_VS.h b/src/d3d/shaders/default_all_VS.h
new file mode 100644
index 0000000..e6afa5d
--- /dev/null
+++ b/src/d3d/shaders/default_all_VS.h
@@ -0,0 +1,491 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh
+// default_all_VS.h default_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x4 combinedMat;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// int numPointLights;
+// int numSpotLights;
+// float4 surfProps;
+// float4x4 worldMat;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// -------------- ----- ----
+// numDirLights i0 1
+// numPointLights i1 1
+// numSpotLights i2 1
+// combinedMat c0 4
+// worldMat c4 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+//
+
+ vs_2_0
+ def c11, 0, 3, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ mov oPos, r0
+ mul r0.xyz, v0.y, c5
+ mad r0.xyz, c4, v0.x, r0
+ mad r0.xyz, c6, v0.z, r0
+ mad r0.xyz, c7, v0.w, r0
+ mul r1.xyz, v1.y, c9
+ mad r1.xyz, c8, v1.x, r1
+ mad r1.xyz, c10, v1.z, r1
+ mov r2.x, c13.x
+ mad r2.xyz, c15, r2.x, v3
+ mov r3.xyz, r2
+ mov r1.w, c11.x
+ rep i0
+ add r2.w, r1.w, c16.x
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ dp3 r2.w, r1, -c19[a0.x]
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, c17[a0.x]
+ mad r3.xyz, r4, c13.z, r3
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r2.xyz, r3
+ mov r1.w, c11.x
+ rep i1
+ add r2.w, r1.w, c16.y
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ add r4.xyz, r0, -c18[a0.x]
+ dp3 r2.w, r4, r4
+ rsq r2.w, r2.w
+ mul r4.xyz, r2.w, r4
+ dp3 r3.w, r1, -r4
+ max r3.w, r3.w, c11.x
+ mul r4.xyz, r3.w, c17[a0.x]
+ rcp r2.w, r2.w
+ rcp r3.w, c17[a0.x].w
+ mad r2.w, r2.w, -r3.w, c11.z
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, r4
+ mad r2.xyz, r4, c13.z, r2
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r3.xyz, r2
+ mov r1.w, c11.x
+ rep i2
+ add r2.w, r1.w, c16.z
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ add r4.xyz, r0, -c18[a0.x]
+ dp3 r2.w, r4, r4
+ rsq r2.w, r2.w
+ mul r4.xyz, r2.w, r4
+ dp3 r4.w, r1, -r4
+ dp3 r4.x, r4, c19[a0.x]
+ max r4.y, r4.w, c11.x
+ mov r4.z, c11.z
+ add r4.xz, r4, c18[a0.x].w
+ rcp r4.z, r4.z
+ mul r4.x, r4.z, r4.x
+ slt r4.z, r4.x, c11.x
+ mad r4.y, r4.z, -r4.y, r4.y
+ max r4.x, r4.x, c19[a0.x].w
+ mul r4.x, r4.x, r4.y
+ mul r4.xyz, r4.x, c17[a0.x]
+ rcp r2.w, r2.w
+ rcp r4.w, c17[a0.x].w
+ mad r2.w, r2.w, -r4.w, c11.z
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, r4
+ mad r3.xyz, r4, c13.z, r3
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r3.w, v3.w
+ max r1, r3, c11.x
+ min r1, r1, c11.z
+ mul oD0, r1, c12
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c11.z
+ mov oT0.xy, v2
+
+// approximately 95 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 158, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 67, 2,
+ 0, 0, 0, 2, 254, 255,
+ 12, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 60, 2, 0, 0, 12, 1,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 28, 1,
+ 0, 0, 0, 0, 0, 0,
+ 44, 1, 0, 0, 2, 0,
+ 0, 0, 4, 0, 2, 0,
+ 56, 1, 0, 0, 0, 0,
+ 0, 0, 72, 1, 0, 0,
+ 2, 0, 16, 0, 1, 0,
+ 66, 0, 84, 1, 0, 0,
+ 0, 0, 0, 0, 100, 1,
+ 0, 0, 2, 0, 14, 0,
+ 1, 0, 58, 0, 28, 1,
+ 0, 0, 0, 0, 0, 0,
+ 108, 1, 0, 0, 2, 0,
+ 17, 0, 24, 0, 70, 0,
+ 184, 1, 0, 0, 0, 0,
+ 0, 0, 200, 1, 0, 0,
+ 2, 0, 12, 0, 1, 0,
+ 50, 0, 28, 1, 0, 0,
+ 0, 0, 0, 0, 207, 1,
+ 0, 0, 2, 0, 8, 0,
+ 3, 0, 34, 0, 220, 1,
+ 0, 0, 0, 0, 0, 0,
+ 236, 1, 0, 0, 1, 0,
+ 0, 0, 1, 0, 2, 0,
+ 252, 1, 0, 0, 0, 0,
+ 0, 0, 12, 2, 0, 0,
+ 1, 0, 1, 0, 1, 0,
+ 6, 0, 252, 1, 0, 0,
+ 0, 0, 0, 0, 27, 2,
+ 0, 0, 1, 0, 2, 0,
+ 1, 0, 10, 0, 252, 1,
+ 0, 0, 0, 0, 0, 0,
+ 41, 2, 0, 0, 2, 0,
+ 13, 0, 1, 0, 54, 0,
+ 28, 1, 0, 0, 0, 0,
+ 0, 0, 51, 2, 0, 0,
+ 2, 0, 4, 0, 4, 0,
+ 18, 0, 56, 1, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 109, 98, 105, 110,
+ 101, 100, 77, 97, 116, 0,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 105,
+ 114, 115, 116, 76, 105, 103,
+ 104, 116, 0, 171, 1, 0,
+ 2, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 68,
+ 97, 116, 97, 0, 108, 105,
+ 103, 104, 116, 115, 0, 99,
+ 111, 108, 111, 114, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 111, 115, 105, 116, 105,
+ 111, 110, 0, 100, 105, 114,
+ 101, 99, 116, 105, 111, 110,
+ 0, 171, 115, 1, 0, 0,
+ 124, 1, 0, 0, 140, 1,
+ 0, 0, 124, 1, 0, 0,
+ 149, 1, 0, 0, 124, 1,
+ 0, 0, 5, 0, 0, 0,
+ 1, 0, 12, 0, 8, 0,
+ 3, 0, 160, 1, 0, 0,
+ 109, 97, 116, 67, 111, 108,
+ 0, 110, 111, 114, 109, 97,
+ 108, 77, 97, 116, 0, 171,
+ 171, 171, 3, 0, 3, 0,
+ 3, 0, 3, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 110, 117, 109, 68, 105, 114,
+ 76, 105, 103, 104, 116, 115,
+ 0, 171, 171, 171, 0, 0,
+ 2, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 110, 117, 109, 80,
+ 111, 105, 110, 116, 76, 105,
+ 103, 104, 116, 115, 0, 110,
+ 117, 109, 83, 112, 111, 116,
+ 76, 105, 103, 104, 116, 115,
+ 0, 115, 117, 114, 102, 80,
+ 114, 111, 112, 115, 0, 119,
+ 111, 114, 108, 100, 77, 97,
+ 116, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 57, 46, 50, 57,
+ 46, 57, 53, 50, 46, 51,
+ 49, 49, 49, 0, 81, 0,
+ 0, 5, 11, 0, 15, 160,
+ 0, 0, 0, 0, 0, 0,
+ 64, 64, 0, 0, 128, 63,
+ 0, 0, 0, 0, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 15, 144, 31, 0,
+ 0, 2, 3, 0, 0, 128,
+ 1, 0, 15, 144, 31, 0,
+ 0, 2, 5, 0, 0, 128,
+ 2, 0, 15, 144, 31, 0,
+ 0, 2, 10, 0, 0, 128,
+ 3, 0, 15, 144, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 85, 144, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 2, 0, 228, 160, 0, 0,
+ 170, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 3, 0, 228, 160,
+ 0, 0, 255, 144, 0, 0,
+ 228, 128, 1, 0, 0, 2,
+ 0, 0, 15, 192, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0,
+ 85, 144, 5, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 4, 0, 228, 160,
+ 0, 0, 0, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 7, 128, 6, 0,
+ 228, 160, 0, 0, 170, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 7, 0, 228, 160, 0, 0,
+ 255, 144, 0, 0, 228, 128,
+ 5, 0, 0, 3, 1, 0,
+ 7, 128, 1, 0, 85, 144,
+ 9, 0, 228, 160, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 8, 0, 228, 160, 1, 0,
+ 0, 144, 1, 0, 228, 128,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 10, 0, 228, 160,
+ 1, 0, 170, 144, 1, 0,
+ 228, 128, 1, 0, 0, 2,
+ 2, 0, 1, 128, 13, 0,
+ 0, 160, 4, 0, 0, 4,
+ 2, 0, 7, 128, 15, 0,
+ 228, 160, 2, 0, 0, 128,
+ 3, 0, 228, 144, 1, 0,
+ 0, 2, 3, 0, 7, 128,
+ 2, 0, 228, 128, 1, 0,
+ 0, 2, 1, 0, 8, 128,
+ 11, 0, 0, 160, 38, 0,
+ 0, 1, 0, 0, 228, 240,
+ 2, 0, 0, 3, 2, 0,
+ 8, 128, 1, 0, 255, 128,
+ 16, 0, 0, 160, 5, 0,
+ 0, 3, 2, 0, 8, 128,
+ 2, 0, 255, 128, 11, 0,
+ 85, 160, 46, 0, 0, 2,
+ 0, 0, 1, 176, 2, 0,
+ 255, 128, 8, 0, 0, 4,
+ 2, 0, 8, 128, 1, 0,
+ 228, 128, 19, 32, 228, 161,
+ 0, 0, 0, 176, 11, 0,
+ 0, 3, 2, 0, 8, 128,
+ 2, 0, 255, 128, 11, 0,
+ 0, 160, 5, 0, 0, 4,
+ 4, 0, 7, 128, 2, 0,
+ 255, 128, 17, 32, 228, 160,
+ 0, 0, 0, 176, 4, 0,
+ 0, 4, 3, 0, 7, 128,
+ 4, 0, 228, 128, 13, 0,
+ 170, 160, 3, 0, 228, 128,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 11, 0, 170, 160, 39, 0,
+ 0, 0, 1, 0, 0, 2,
+ 2, 0, 7, 128, 3, 0,
+ 228, 128, 1, 0, 0, 2,
+ 1, 0, 8, 128, 11, 0,
+ 0, 160, 38, 0, 0, 1,
+ 1, 0, 228, 240, 2, 0,
+ 0, 3, 2, 0, 8, 128,
+ 1, 0, 255, 128, 16, 0,
+ 85, 160, 5, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 85, 160,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 2, 0, 255, 128,
+ 2, 0, 0, 4, 4, 0,
+ 7, 128, 0, 0, 228, 128,
+ 18, 32, 228, 161, 0, 0,
+ 0, 176, 8, 0, 0, 3,
+ 2, 0, 8, 128, 4, 0,
+ 228, 128, 4, 0, 228, 128,
+ 7, 0, 0, 2, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 5, 0, 0, 3, 4, 0,
+ 7, 128, 2, 0, 255, 128,
+ 4, 0, 228, 128, 8, 0,
+ 0, 3, 3, 0, 8, 128,
+ 1, 0, 228, 128, 4, 0,
+ 228, 129, 11, 0, 0, 3,
+ 3, 0, 8, 128, 3, 0,
+ 255, 128, 11, 0, 0, 160,
+ 5, 0, 0, 4, 4, 0,
+ 7, 128, 3, 0, 255, 128,
+ 17, 32, 228, 160, 0, 0,
+ 0, 176, 6, 0, 0, 2,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 6, 0, 0, 3,
+ 3, 0, 8, 128, 17, 32,
+ 255, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 3, 0, 255, 129, 11, 0,
+ 170, 160, 11, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 0, 160,
+ 5, 0, 0, 3, 4, 0,
+ 7, 128, 2, 0, 255, 128,
+ 4, 0, 228, 128, 4, 0,
+ 0, 4, 2, 0, 7, 128,
+ 4, 0, 228, 128, 13, 0,
+ 170, 160, 2, 0, 228, 128,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 11, 0, 170, 160, 39, 0,
+ 0, 0, 1, 0, 0, 2,
+ 3, 0, 7, 128, 2, 0,
+ 228, 128, 1, 0, 0, 2,
+ 1, 0, 8, 128, 11, 0,
+ 0, 160, 38, 0, 0, 1,
+ 2, 0, 228, 240, 2, 0,
+ 0, 3, 2, 0, 8, 128,
+ 1, 0, 255, 128, 16, 0,
+ 170, 160, 5, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 85, 160,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 2, 0, 255, 128,
+ 2, 0, 0, 4, 4, 0,
+ 7, 128, 0, 0, 228, 128,
+ 18, 32, 228, 161, 0, 0,
+ 0, 176, 8, 0, 0, 3,
+ 2, 0, 8, 128, 4, 0,
+ 228, 128, 4, 0, 228, 128,
+ 7, 0, 0, 2, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 5, 0, 0, 3, 4, 0,
+ 7, 128, 2, 0, 255, 128,
+ 4, 0, 228, 128, 8, 0,
+ 0, 3, 4, 0, 8, 128,
+ 1, 0, 228, 128, 4, 0,
+ 228, 129, 8, 0, 0, 4,
+ 4, 0, 1, 128, 4, 0,
+ 228, 128, 19, 32, 228, 160,
+ 0, 0, 0, 176, 11, 0,
+ 0, 3, 4, 0, 2, 128,
+ 4, 0, 255, 128, 11, 0,
+ 0, 160, 1, 0, 0, 2,
+ 4, 0, 4, 128, 11, 0,
+ 170, 160, 2, 0, 0, 4,
+ 4, 0, 5, 128, 4, 0,
+ 228, 128, 18, 32, 255, 160,
+ 0, 0, 0, 176, 6, 0,
+ 0, 2, 4, 0, 4, 128,
+ 4, 0, 170, 128, 5, 0,
+ 0, 3, 4, 0, 1, 128,
+ 4, 0, 170, 128, 4, 0,
+ 0, 128, 12, 0, 0, 3,
+ 4, 0, 4, 128, 4, 0,
+ 0, 128, 11, 0, 0, 160,
+ 4, 0, 0, 4, 4, 0,
+ 2, 128, 4, 0, 170, 128,
+ 4, 0, 85, 129, 4, 0,
+ 85, 128, 11, 0, 0, 4,
+ 4, 0, 1, 128, 4, 0,
+ 0, 128, 19, 32, 255, 160,
+ 0, 0, 0, 176, 5, 0,
+ 0, 3, 4, 0, 1, 128,
+ 4, 0, 0, 128, 4, 0,
+ 85, 128, 5, 0, 0, 4,
+ 4, 0, 7, 128, 4, 0,
+ 0, 128, 17, 32, 228, 160,
+ 0, 0, 0, 176, 6, 0,
+ 0, 2, 2, 0, 8, 128,
+ 2, 0, 255, 128, 6, 0,
+ 0, 3, 4, 0, 8, 128,
+ 17, 32, 255, 160, 0, 0,
+ 0, 176, 4, 0, 0, 4,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 4, 0, 255, 129,
+ 11, 0, 170, 160, 11, 0,
+ 0, 3, 2, 0, 8, 128,
+ 2, 0, 255, 128, 11, 0,
+ 0, 160, 5, 0, 0, 3,
+ 4, 0, 7, 128, 2, 0,
+ 255, 128, 4, 0, 228, 128,
+ 4, 0, 0, 4, 3, 0,
+ 7, 128, 4, 0, 228, 128,
+ 13, 0, 170, 160, 3, 0,
+ 228, 128, 2, 0, 0, 3,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 11, 0, 170, 160,
+ 39, 0, 0, 0, 1, 0,
+ 0, 2, 3, 0, 8, 128,
+ 3, 0, 255, 144, 11, 0,
+ 0, 3, 1, 0, 15, 128,
+ 3, 0, 228, 128, 11, 0,
+ 0, 160, 10, 0, 0, 3,
+ 1, 0, 15, 128, 1, 0,
+ 228, 128, 11, 0, 170, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 208, 1, 0, 228, 128,
+ 12, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 5, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 11, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/default_amb_VS.h b/src/d3d/shaders/default_amb_VS.h
new file mode 100644
index 0000000..6c22e23
--- /dev/null
+++ b/src/d3d/shaders/default_amb_VS.h
@@ -0,0 +1,156 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /Fh default_amb_VS.h default_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x4 combinedMat;
+// float4 fogData;
+// float4 matCol;
+// float4 surfProps;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// combinedMat c0 4
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+//
+
+ vs_2_0
+ def c4, 0, 1, 0, 0
+ dcl_position v0
+ dcl_texcoord v1
+ dcl_color v2
+ mov r0.xyz, c15
+ mad r0.xyz, r0, c13.x, v2
+ mov r0.w, v2.w
+ max r0, r0, c4.x
+ min r0, r0, c4.y
+ mul oD0, r0, c12
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ add r1.x, r0.w, -c14.y
+ mov oPos, r0
+ mul r0.x, r1.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.y
+ mov oT0.xy, v1
+
+// approximately 16 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 69, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 220, 0,
+ 0, 0, 0, 2, 254, 255,
+ 5, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 213, 0, 0, 0, 128, 0,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 144, 0,
+ 0, 0, 0, 0, 0, 0,
+ 160, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 2, 0,
+ 172, 0, 0, 0, 0, 0,
+ 0, 0, 188, 0, 0, 0,
+ 2, 0, 14, 0, 1, 0,
+ 58, 0, 144, 0, 0, 0,
+ 0, 0, 0, 0, 196, 0,
+ 0, 0, 2, 0, 12, 0,
+ 1, 0, 50, 0, 144, 0,
+ 0, 0, 0, 0, 0, 0,
+ 203, 0, 0, 0, 2, 0,
+ 13, 0, 1, 0, 54, 0,
+ 144, 0, 0, 0, 0, 0,
+ 0, 0, 97, 109, 98, 105,
+ 101, 110, 116, 76, 105, 103,
+ 104, 116, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 99, 111,
+ 109, 98, 105, 110, 101, 100,
+ 77, 97, 116, 0, 3, 0,
+ 3, 0, 4, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 68,
+ 97, 116, 97, 0, 109, 97,
+ 116, 67, 111, 108, 0, 115,
+ 117, 114, 102, 80, 114, 111,
+ 112, 115, 0, 118, 115, 95,
+ 50, 95, 48, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 50,
+ 57, 46, 57, 53, 50, 46,
+ 51, 49, 49, 49, 0, 171,
+ 171, 171, 81, 0, 0, 5,
+ 4, 0, 15, 160, 0, 0,
+ 0, 0, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 5, 0, 0, 128, 1, 0,
+ 15, 144, 31, 0, 0, 2,
+ 10, 0, 0, 128, 2, 0,
+ 15, 144, 1, 0, 0, 2,
+ 0, 0, 7, 128, 15, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 7, 128, 0, 0,
+ 228, 128, 13, 0, 0, 160,
+ 2, 0, 228, 144, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 2, 0, 255, 144, 11, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 4, 0,
+ 0, 160, 10, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 4, 0, 85, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 208, 0, 0, 228, 128,
+ 12, 0, 228, 160, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 85, 144, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 2, 0, 228, 160, 0, 0,
+ 170, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 3, 0, 228, 160,
+ 0, 0, 255, 144, 0, 0,
+ 228, 128, 2, 0, 0, 3,
+ 1, 0, 1, 128, 0, 0,
+ 255, 128, 14, 0, 85, 161,
+ 1, 0, 0, 2, 0, 0,
+ 15, 192, 0, 0, 228, 128,
+ 5, 0, 0, 3, 0, 0,
+ 1, 128, 1, 0, 0, 128,
+ 14, 0, 170, 160, 11, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 0, 128, 14, 0,
+ 255, 160, 10, 0, 0, 3,
+ 0, 0, 4, 224, 0, 0,
+ 0, 128, 4, 0, 85, 160,
+ 1, 0, 0, 2, 0, 0,
+ 3, 224, 1, 0, 228, 144,
+ 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/default_amb_dir_VS.h b/src/d3d/shaders/default_amb_dir_VS.h
new file mode 100644
index 0000000..768042f
--- /dev/null
+++ b/src/d3d/shaders/default_amb_dir_VS.h
@@ -0,0 +1,272 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /Fh default_amb_dir_VS.h
+// default_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x4 combinedMat;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// float4 surfProps;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// numDirLights i0 1
+// combinedMat c0 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+//
+
+ vs_2_0
+ def c4, 0, 3, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ mov oPos, r0
+ mul r0.xyz, v1.y, c9
+ mad r0.xyz, c8, v1.x, r0
+ mad r0.xyz, c10, v1.z, r0
+ mov r1.x, c13.x
+ mad r1.xyz, c15, r1.x, v3
+ mov r2.xyz, r1
+ mov r1.w, c4.x
+ rep i0
+ add r3.x, r1.w, c16.x
+ mul r3.x, r3.x, c4.y
+ mova a0.x, r3.x
+ dp3 r3.x, r0, -c19[a0.x]
+ max r3.x, r3.x, c4.x
+ mul r3.xyz, r3.x, c17[a0.x]
+ mad r2.xyz, r3, c13.z, r2
+ add r1.w, r1.w, c4.z
+ endrep
+ mov r2.w, v3.w
+ max r1, r2, c4.x
+ min r1, r1, c4.z
+ mul oD0, r1, c12
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.z
+ mov oT0.xy, v2
+
+// approximately 34 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 134, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 225, 1,
+ 0, 0, 0, 2, 254, 255,
+ 9, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 218, 1, 0, 0, 208, 0,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 224, 0,
+ 0, 0, 0, 0, 0, 0,
+ 240, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 2, 0,
+ 252, 0, 0, 0, 0, 0,
+ 0, 0, 12, 1, 0, 0,
+ 2, 0, 16, 0, 1, 0,
+ 66, 0, 24, 1, 0, 0,
+ 0, 0, 0, 0, 40, 1,
+ 0, 0, 2, 0, 14, 0,
+ 1, 0, 58, 0, 224, 0,
+ 0, 0, 0, 0, 0, 0,
+ 48, 1, 0, 0, 2, 0,
+ 17, 0, 24, 0, 70, 0,
+ 124, 1, 0, 0, 0, 0,
+ 0, 0, 140, 1, 0, 0,
+ 2, 0, 12, 0, 1, 0,
+ 50, 0, 224, 0, 0, 0,
+ 0, 0, 0, 0, 147, 1,
+ 0, 0, 2, 0, 8, 0,
+ 3, 0, 34, 0, 160, 1,
+ 0, 0, 0, 0, 0, 0,
+ 176, 1, 0, 0, 1, 0,
+ 0, 0, 1, 0, 2, 0,
+ 192, 1, 0, 0, 0, 0,
+ 0, 0, 208, 1, 0, 0,
+ 2, 0, 13, 0, 1, 0,
+ 54, 0, 224, 0, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 109, 98, 105, 110,
+ 101, 100, 77, 97, 116, 0,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 105,
+ 114, 115, 116, 76, 105, 103,
+ 104, 116, 0, 171, 1, 0,
+ 2, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 68,
+ 97, 116, 97, 0, 108, 105,
+ 103, 104, 116, 115, 0, 99,
+ 111, 108, 111, 114, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 111, 115, 105, 116, 105,
+ 111, 110, 0, 100, 105, 114,
+ 101, 99, 116, 105, 111, 110,
+ 0, 171, 55, 1, 0, 0,
+ 64, 1, 0, 0, 80, 1,
+ 0, 0, 64, 1, 0, 0,
+ 89, 1, 0, 0, 64, 1,
+ 0, 0, 5, 0, 0, 0,
+ 1, 0, 12, 0, 8, 0,
+ 3, 0, 100, 1, 0, 0,
+ 109, 97, 116, 67, 111, 108,
+ 0, 110, 111, 114, 109, 97,
+ 108, 77, 97, 116, 0, 171,
+ 171, 171, 3, 0, 3, 0,
+ 3, 0, 3, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 110, 117, 109, 68, 105, 114,
+ 76, 105, 103, 104, 116, 115,
+ 0, 171, 171, 171, 0, 0,
+ 2, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 117, 114, 102,
+ 80, 114, 111, 112, 115, 0,
+ 118, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 171, 171, 81, 0,
+ 0, 5, 4, 0, 15, 160,
+ 0, 0, 0, 0, 0, 0,
+ 64, 64, 0, 0, 128, 63,
+ 0, 0, 0, 0, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 15, 144, 31, 0,
+ 0, 2, 3, 0, 0, 128,
+ 1, 0, 15, 144, 31, 0,
+ 0, 2, 5, 0, 0, 128,
+ 2, 0, 15, 144, 31, 0,
+ 0, 2, 10, 0, 0, 128,
+ 3, 0, 15, 144, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 85, 144, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 2, 0, 228, 160, 0, 0,
+ 170, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 3, 0, 228, 160,
+ 0, 0, 255, 144, 0, 0,
+ 228, 128, 1, 0, 0, 2,
+ 0, 0, 15, 192, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 0, 0, 7, 128, 1, 0,
+ 85, 144, 9, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 8, 0, 228, 160,
+ 1, 0, 0, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 7, 128, 10, 0,
+ 228, 160, 1, 0, 170, 144,
+ 0, 0, 228, 128, 1, 0,
+ 0, 2, 1, 0, 1, 128,
+ 13, 0, 0, 160, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 15, 0, 228, 160, 1, 0,
+ 0, 128, 3, 0, 228, 144,
+ 1, 0, 0, 2, 2, 0,
+ 7, 128, 1, 0, 228, 128,
+ 1, 0, 0, 2, 1, 0,
+ 8, 128, 4, 0, 0, 160,
+ 38, 0, 0, 1, 0, 0,
+ 228, 240, 2, 0, 0, 3,
+ 3, 0, 1, 128, 1, 0,
+ 255, 128, 16, 0, 0, 160,
+ 5, 0, 0, 3, 3, 0,
+ 1, 128, 3, 0, 0, 128,
+ 4, 0, 85, 160, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 3, 0, 0, 128, 8, 0,
+ 0, 4, 3, 0, 1, 128,
+ 0, 0, 228, 128, 19, 32,
+ 228, 161, 0, 0, 0, 176,
+ 11, 0, 0, 3, 3, 0,
+ 1, 128, 3, 0, 0, 128,
+ 4, 0, 0, 160, 5, 0,
+ 0, 4, 3, 0, 7, 128,
+ 3, 0, 0, 128, 17, 32,
+ 228, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 3, 0, 228, 128,
+ 13, 0, 170, 160, 2, 0,
+ 228, 128, 2, 0, 0, 3,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 4, 0, 170, 160,
+ 39, 0, 0, 0, 1, 0,
+ 0, 2, 2, 0, 8, 128,
+ 3, 0, 255, 144, 11, 0,
+ 0, 3, 1, 0, 15, 128,
+ 2, 0, 228, 128, 4, 0,
+ 0, 160, 10, 0, 0, 3,
+ 1, 0, 15, 128, 1, 0,
+ 228, 128, 4, 0, 170, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 208, 1, 0, 228, 128,
+ 12, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 5, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 4, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/default_tex_PS.h b/src/d3d/shaders/default_tex_PS.h
new file mode 100644
index 0000000..a25f918
--- /dev/null
+++ b/src/d3d/shaders/default_tex_PS.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /DTEX /Fh default_tex_PS.h default_PS.hlsl
+//
+//
+// Parameters:
+//
+// float4 fogColor;
+// sampler2D tex0;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+// tex0 s0 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl v0
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0.xyz, v0, r0, -c0
+ mul r1.w, r0.w, v0.w
+ mad r1.xyz, t0.z, r0, c0
+ mov oC0, r1
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 45, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 127, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 120, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 96, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 2, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 67,
+ 111, 108, 111, 114, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 116, 101, 120, 48, 0, 171,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 0, 0, 228, 144,
+ 0, 0, 228, 128, 0, 0,
+ 228, 161, 5, 0, 0, 3,
+ 1, 0, 8, 128, 0, 0,
+ 255, 128, 0, 0, 255, 144,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 0, 0, 170, 176,
+ 0, 0, 228, 128, 0, 0,
+ 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 1, 0,
+ 228, 128, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/im2d_PS.h b/src/d3d/shaders/im2d_PS.h
new file mode 100644
index 0000000..71f8b28
--- /dev/null
+++ b/src/d3d/shaders/im2d_PS.h
@@ -0,0 +1,72 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /Fh im2d_PS.h im2d_PS.hlsl
+//
+//
+// Parameters:
+//
+// float4 fogColor;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl v0
+ add r0.xyz, v0, -c0
+ mad r0.xyz, t0.z, r0, c0
+ mov r0.w, v0.w
+ mov oC0, r0
+
+// approximately 4 instruction slots used
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 34, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 83, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 76, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 60, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 67, 111, 108,
+ 111, 114, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 7, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 2, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 144,
+ 0, 0, 228, 161, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 0, 0, 170, 176, 0, 0,
+ 228, 128, 0, 0, 228, 160,
+ 1, 0, 0, 2, 0, 0,
+ 8, 128, 0, 0, 255, 144,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/im2d_PS.hlsl b/src/d3d/shaders/im2d_PS.hlsl
new file mode 100644
index 0000000..eaf279d
--- /dev/null
+++ b/src/d3d/shaders/im2d_PS.hlsl
@@ -0,0 +1,19 @@
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+sampler2D tex0 : register(s0);
+
+float4 fogColor : register(c0);
+
+float4 main(VS_out input) : COLOR
+{
+ float4 color = input.Color;
+#ifdef TEX
+ color *= tex2D(tex0, input.TexCoord0.xy);
+#endif
+ color.rgb = lerp(fogColor.rgb, color.rgb, input.TexCoord0.z);
+ return color;
+}
diff --git a/src/d3d/shaders/im2d_VS.h b/src/d3d/shaders/im2d_VS.h
new file mode 100644
index 0000000..bc36b1f
--- /dev/null
+++ b/src/d3d/shaders/im2d_VS.h
@@ -0,0 +1,107 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /Fh im2d_VS.h im2d_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 fogData;
+// float4 xform;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogData c14 1
+// xform c41 1
+//
+
+ vs_2_0
+ def c0, 1, 0, 0, 0
+ dcl_position v0
+ dcl_texcoord v1
+ dcl_color v2
+ add r0.x, v0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c0.x
+ mad r0.xy, v0, c41, c41.zwzw
+ mov r0.z, v0.z
+ mul oPos.xyz, r0, v0.w
+ mov oPos.w, v0.w
+ mov oT0.xy, v1
+ mov oD0, v2
+
+// approximately 10 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 40, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 105, 0,
+ 0, 0, 0, 2, 254, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 98, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 14, 0,
+ 1, 0, 58, 0, 76, 0,
+ 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 2, 0,
+ 41, 0, 1, 0, 166, 0,
+ 76, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 68,
+ 97, 116, 97, 0, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 120, 102, 111, 114,
+ 109, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 57, 46, 50, 57,
+ 46, 57, 53, 50, 46, 51,
+ 49, 49, 49, 0, 171, 171,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 5, 0,
+ 0, 128, 1, 0, 15, 144,
+ 31, 0, 0, 2, 10, 0,
+ 0, 128, 2, 0, 15, 144,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 255, 144,
+ 14, 0, 85, 161, 5, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 0, 128, 14, 0,
+ 170, 160, 11, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 255, 160,
+ 10, 0, 0, 3, 0, 0,
+ 4, 224, 0, 0, 0, 128,
+ 0, 0, 0, 160, 4, 0,
+ 0, 4, 0, 0, 3, 128,
+ 0, 0, 228, 144, 41, 0,
+ 228, 160, 41, 0, 238, 160,
+ 1, 0, 0, 2, 0, 0,
+ 4, 128, 0, 0, 170, 144,
+ 5, 0, 0, 3, 0, 0,
+ 7, 192, 0, 0, 228, 128,
+ 0, 0, 255, 144, 1, 0,
+ 0, 2, 0, 0, 8, 192,
+ 0, 0, 255, 144, 1, 0,
+ 0, 2, 0, 0, 3, 224,
+ 1, 0, 228, 144, 1, 0,
+ 0, 2, 0, 0, 15, 208,
+ 2, 0, 228, 144, 255, 255,
+ 0, 0
+};
diff --git a/src/d3d/shaders/im2d_VS.hlsl b/src/d3d/shaders/im2d_VS.hlsl
new file mode 100644
index 0000000..20cf3ce
--- /dev/null
+++ b/src/d3d/shaders/im2d_VS.hlsl
@@ -0,0 +1,30 @@
+#include "standardConstants.h"
+
+struct VS_in
+{
+ float4 Position : POSITION;
+ float2 TexCoord : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0;
+ float4 Color : COLOR0;
+};
+
+float4 xform : register(c41);
+
+VS_out main(in VS_in input)
+{
+ VS_out output;
+
+ output.Position = input.Position;
+ output.Position.xy = output.Position.xy * xform.xy + xform.zw;
+ output.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);
+ output.Position.xyz *= output.Position.w;
+ output.Color = input.Color;
+ output.TexCoord0.xy = input.TexCoord;
+
+ return output;
+}
diff --git a/src/d3d/shaders/im2d_tex_PS.h b/src/d3d/shaders/im2d_tex_PS.h
new file mode 100644
index 0000000..a91888b
--- /dev/null
+++ b/src/d3d/shaders/im2d_tex_PS.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /DTEX /Fh im2d_tex_PS.h im2d_PS.hlsl
+//
+//
+// Parameters:
+//
+// float4 fogColor;
+// sampler2D tex0;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+// tex0 s0 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl v0
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0.xyz, v0, r0, -c0
+ mul r1.w, r0.w, v0.w
+ mad r1.xyz, t0.z, r0, c0
+ mov oC0, r1
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 45, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 127, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 120, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 96, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 2, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 102, 111, 103, 67,
+ 111, 108, 111, 114, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 116, 101, 120, 48, 0, 171,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 0, 0, 228, 144,
+ 0, 0, 228, 128, 0, 0,
+ 228, 161, 5, 0, 0, 3,
+ 1, 0, 8, 128, 0, 0,
+ 255, 128, 0, 0, 255, 144,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 0, 0, 170, 176,
+ 0, 0, 228, 128, 0, 0,
+ 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 1, 0,
+ 228, 128, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/lighting.h b/src/d3d/shaders/lighting.h
new file mode 100644
index 0000000..4b08196
--- /dev/null
+++ b/src/d3d/shaders/lighting.h
@@ -0,0 +1,44 @@
+struct Light
+{
+ float4 color; // and radius
+ float4 position; // and -cos(angle)
+ float4 direction; // and falloff clamp
+};
+
+float3 DoDirLight(Light L, float3 N)
+{
+ float l = max(0.0, dot(N, -L.direction.xyz));
+ return l*L.color.xyz;
+}
+
+float3 DoDirLightSpec(Light L, float3 N, float3 V, float power)
+{
+ return pow(saturate(dot(N, normalize(V + -L.direction.xyz))), power)*L.color.xyz;
+}
+
+float3 DoPointLight(Light L, float3 V, float3 N)
+{
+ // As on PS2
+ float3 dir = V - L.position.xyz;
+ float dist = length(dir);
+ float atten = max(0.0, (1.0 - dist/L.color.w));
+ float l = max(0.0, dot(N, -normalize(dir)));
+ return l*L.color.xyz*atten;
+}
+
+float3 DoSpotLight(Light L, float3 V, float3 N)
+{
+ // As on PS2
+ float3 dir = V - L.position.xyz;
+ float dist = length(dir);
+ float atten = max(0.0, (1.0 - dist/L.color.w));
+ dir /= dist;
+ float l = max(0.0, dot(N, -dir));
+ float pcos = dot(dir, L.direction.xyz); // cos to point
+ float ccos = -L.position.w; // cos of cone
+ float falloff = (pcos-ccos)/(1.0-ccos);
+ if(falloff < 0) // outside of cone
+ l = 0;
+ l *= max(falloff, L.direction.w); // falloff clamp
+ return l*L.color.xyz*atten;
+}
diff --git a/src/d3d/shaders/make_default.cmd b/src/d3d/shaders/make_default.cmd
new file mode 100644
index 0000000..bc44429
--- /dev/null
+++ b/src/d3d/shaders/make_default.cmd
@@ -0,0 +1,11 @@
+@echo off
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /Fh default_amb_VS.h default_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /Fh default_amb_dir_VS.h default_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh default_all_VS.h default_VS.hlsl
+
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /Fh default_PS.h default_PS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /DTEX /Fh default_tex_PS.h default_PS.hlsl
+
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /Fh im2d_VS.h im2d_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /Fh im2d_PS.h im2d_PS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /DTEX /Fh im2d_tex_PS.h im2d_PS.hlsl
diff --git a/src/d3d/shaders/make_matfx.cmd b/src/d3d/shaders/make_matfx.cmd
new file mode 100644
index 0000000..d0bc4fa
--- /dev/null
+++ b/src/d3d/shaders/make_matfx.cmd
@@ -0,0 +1,7 @@
+@echo off
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /Fh matfx_env_amb_VS.h matfx_env_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /Fh matfx_env_amb_dir_VS.h matfx_env_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh matfx_env_all_VS.h matfx_env_VS.hlsl
+
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /Fh matfx_env_PS.h matfx_env_PS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T ps_2_0 /DTEX /Fh matfx_env_tex_PS.h matfx_env_PS.hlsl
diff --git a/src/d3d/shaders/make_skin.cmd b/src/d3d/shaders/make_skin.cmd
new file mode 100644
index 0000000..b7822ca
--- /dev/null
+++ b/src/d3d/shaders/make_skin.cmd
@@ -0,0 +1,4 @@
+@echo off
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /Fh skin_amb_VS.h skin_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /Fh skin_amb_dir_VS.h skin_VS.hlsl
+"%DXSDK_DIR%\utilities\bin\x86\fxc.exe" /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh skin_all_VS.h skin_VS.hlsl
diff --git a/src/d3d/shaders/matfx_env_PS.h b/src/d3d/shaders/matfx_env_PS.h
new file mode 100644
index 0000000..e39a1f5
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_PS.h
@@ -0,0 +1,124 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /Fh matfx_env_PS.h matfx_env_PS.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D envTex;
+// float4 fogColor;
+// float4 fxparams;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+// fxparams c1 1
+// envTex s1 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl t1.xy
+ dcl v0
+ dcl v1.xyz
+ dcl_2d s1
+ texld r0, t1, s1
+ mul r1.xyz, v1, c1.x
+ mul r0.xyz, r0, r1
+ mul r0.xyz, r0, t0.z
+ max r0.w, v0.w, c1.y
+ mul r0.xyz, r0.w, r0
+ add r1.xyz, v0, -c0
+ mad r1.xyz, t0.z, r1, c0
+ mad r0.xyz, r1, v0.w, r0
+ mov r0.w, v0.w
+ mov oC0, r0
+
+// approximately 11 instruction slots used (1 texture, 10 arithmetic)
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 53, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 156, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 149, 0, 0, 0, 88, 0,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 6, 0, 96, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 2, 0,
+ 124, 0, 0, 0, 0, 0,
+ 0, 0, 140, 0, 0, 0,
+ 2, 0, 1, 0, 1, 0,
+ 6, 0, 124, 0, 0, 0,
+ 0, 0, 0, 0, 101, 110,
+ 118, 84, 101, 120, 0, 171,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 111,
+ 103, 67, 111, 108, 111, 114,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 120, 112, 97,
+ 114, 97, 109, 115, 0, 112,
+ 115, 95, 50, 95, 48, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 50, 57, 46, 57, 53,
+ 50, 46, 51, 49, 49, 49,
+ 0, 171, 171, 171, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 7, 176, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 1, 0, 3, 176, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 15, 144, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 1, 0, 7, 144, 31, 0,
+ 0, 2, 0, 0, 0, 144,
+ 1, 8, 15, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 1, 0, 228, 176, 1, 8,
+ 228, 160, 5, 0, 0, 3,
+ 1, 0, 7, 128, 1, 0,
+ 228, 144, 1, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 1, 0, 228, 128, 5, 0,
+ 0, 3, 0, 0, 7, 128,
+ 0, 0, 228, 128, 0, 0,
+ 170, 176, 11, 0, 0, 3,
+ 0, 0, 8, 128, 0, 0,
+ 255, 144, 1, 0, 85, 160,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 255, 128,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 7, 128,
+ 0, 0, 228, 144, 0, 0,
+ 228, 161, 4, 0, 0, 4,
+ 1, 0, 7, 128, 0, 0,
+ 170, 176, 1, 0, 228, 128,
+ 0, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 1, 0, 228, 128, 0, 0,
+ 255, 144, 0, 0, 228, 128,
+ 1, 0, 0, 2, 0, 0,
+ 8, 128, 0, 0, 255, 144,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/matfx_env_PS.hlsl b/src/d3d/shaders/matfx_env_PS.hlsl
new file mode 100644
index 0000000..eb5187d
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_PS.hlsl
@@ -0,0 +1,42 @@
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0;
+ float2 TexCoord1 : TEXCOORD1;
+ float4 Color : COLOR0;
+ float4 EnvColor : COLOR1;
+};
+
+sampler2D diffTex : register(s0);
+sampler2D envTex : register(s1);
+
+float4 fogColor : register(c0);
+
+float4 fxparams : register(c1);
+
+#define shininess (fxparams.x)
+#define disableFBA (fxparams.y)
+
+float4 main(VS_out input) : COLOR
+{
+ float4 pass1 = input.Color;
+#ifdef TEX
+ pass1 *= tex2D(diffTex, input.TexCoord0.xy);
+#endif
+
+ float4 pass2 = input.EnvColor*shininess*tex2D(envTex, input.TexCoord1.xy);
+
+ pass1.rgb = lerp(fogColor.rgb, pass1.rgb, input.TexCoord0.z);
+ pass2.rgb = lerp(float3(0.0, 0.0, 0.0), pass2.rgb, input.TexCoord0.z);
+
+ // We simulate drawing this in two passes.
+ // First pass with standard blending, second with addition
+ // We premultiply alpha so render state should be one.
+ // For FB alpha rendering assume that diffuse alpha (pass1.a) was
+ // written to framebuffer, so just multiply pass2 by it as well then.
+ float fba = max(pass1.a, disableFBA);
+ float4 color;
+ color.rgb = pass1.rgb*pass1.a + pass2.rgb*fba;
+ color.a = pass1.a;
+
+ return color;
+}
diff --git a/src/d3d/shaders/matfx_env_VS.hlsl b/src/d3d/shaders/matfx_env_VS.hlsl
new file mode 100644
index 0000000..31b674c
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_VS.hlsl
@@ -0,0 +1,59 @@
+#include "standardConstants.h"
+
+float4x4 texMat : register(c41);
+float4 colorClamp : register(c45);
+float4 envColor : register(c46);
+
+struct VS_in
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float2 TexCoord : TEXCOORD0;
+ float4 Prelight : COLOR0;
+};
+
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0; // also fog
+ float2 TexCoord1 : TEXCOORD1;
+ float4 Color : COLOR0;
+ float4 EnvColor : COLOR1;
+};
+
+
+VS_out main(in VS_in input)
+{
+ VS_out output;
+
+ output.Position = mul(combinedMat, input.Position);
+ float3 V = mul(worldMat, input.Position).xyz;
+ float3 N = mul(normalMat, input.Normal);
+
+ output.TexCoord0.xy = input.TexCoord;
+ output.TexCoord1 = mul(texMat, float4(N, 1.0)).xy;
+
+ output.Color = input.Prelight;
+ output.Color.rgb += ambientLight.rgb * surfAmbient;
+
+ int i;
+#ifdef DIRECTIONALS
+ for(i = 0; i < numDirLights; i++)
+ output.Color.xyz += DoDirLight(lights[i+firstDirLight], N)*surfDiffuse;
+#endif
+#ifdef POINTLIGHTS
+ for(i = 0; i < numPointLights; i++)
+ output.Color.xyz += DoPointLight(lights[i+firstPointLight], V, N)*surfDiffuse;
+#endif
+#ifdef SPOTLIGHTS
+ for(i = 0; i < numSpotLights; i++)
+ output.Color.xyz += DoSpotLight(lights[i+firstSpotLight], V, N)*surfDiffuse;
+#endif
+ // PS2 clamps before material color
+ output.Color = clamp(output.Color, 0.0, 1.0);
+ output.EnvColor = max(output.Color, colorClamp) * envColor;
+ output.Color *= matCol;
+
+ output.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);
+
+ return output;
+}
diff --git a/src/d3d/shaders/matfx_env_all_VS.h b/src/d3d/shaders/matfx_env_all_VS.h
new file mode 100644
index 0000000..65e1c15
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_all_VS.h
@@ -0,0 +1,535 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh
+// matfx_env_all_VS.h matfx_env_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4 colorClamp;
+// float4x4 combinedMat;
+// float4 envColor;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// int numPointLights;
+// int numSpotLights;
+// float4 surfProps;
+// float4x4 texMat;
+// float4x4 worldMat;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// -------------- ----- ----
+// numDirLights i0 1
+// numPointLights i1 1
+// numSpotLights i2 1
+// combinedMat c0 4
+// worldMat c4 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+// texMat c41 4
+// colorClamp c45 1
+// envColor c46 1
+//
+
+ vs_2_0
+ def c11, 0, 3, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ mov oPos, r0
+ mul r0.xyz, v0.y, c5
+ mad r0.xyz, c4, v0.x, r0
+ mad r0.xyz, c6, v0.z, r0
+ mad r0.xyz, c7, v0.w, r0
+ mul r1.xyz, v1.y, c9
+ mad r1.xyz, c8, v1.x, r1
+ mad r1.xyz, c10, v1.z, r1
+ mov r2.x, c13.x
+ mad r2.xyz, c15, r2.x, v3
+ mov r3.xyz, r2
+ mov r1.w, c11.x
+ rep i0
+ add r2.w, r1.w, c16.x
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ dp3 r2.w, r1, -c19[a0.x]
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, c17[a0.x]
+ mad r3.xyz, r4, c13.z, r3
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r2.xyz, r3
+ mov r1.w, c11.x
+ rep i1
+ add r2.w, r1.w, c16.y
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ add r4.xyz, r0, -c18[a0.x]
+ dp3 r2.w, r4, r4
+ rsq r2.w, r2.w
+ mul r4.xyz, r2.w, r4
+ dp3 r3.w, r1, -r4
+ max r3.w, r3.w, c11.x
+ mul r4.xyz, r3.w, c17[a0.x]
+ rcp r2.w, r2.w
+ rcp r3.w, c17[a0.x].w
+ mad r2.w, r2.w, -r3.w, c11.z
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, r4
+ mad r2.xyz, r4, c13.z, r2
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r3.xyz, r2
+ mov r1.w, c11.x
+ rep i2
+ add r2.w, r1.w, c16.z
+ mul r2.w, r2.w, c11.y
+ mova a0.x, r2.w
+ add r4.xyz, r0, -c18[a0.x]
+ dp3 r2.w, r4, r4
+ rsq r2.w, r2.w
+ mul r4.xyz, r2.w, r4
+ dp3 r4.w, r1, -r4
+ dp3 r4.x, r4, c19[a0.x]
+ max r4.y, r4.w, c11.x
+ mov r4.z, c11.z
+ add r4.xz, r4, c18[a0.x].w
+ rcp r4.z, r4.z
+ mul r4.x, r4.z, r4.x
+ slt r4.z, r4.x, c11.x
+ mad r4.y, r4.z, -r4.y, r4.y
+ max r4.x, r4.x, c19[a0.x].w
+ mul r4.x, r4.x, r4.y
+ mul r4.xyz, r4.x, c17[a0.x]
+ rcp r2.w, r2.w
+ rcp r4.w, c17[a0.x].w
+ mad r2.w, r2.w, -r4.w, c11.z
+ max r2.w, r2.w, c11.x
+ mul r4.xyz, r2.w, r4
+ mad r3.xyz, r4, c13.z, r3
+ add r1.w, r1.w, c11.z
+ endrep
+ mov r3.w, v3.w
+ max r2, r3, c11.x
+ min r2, r2, c11.z
+ mul oD0, r2, c12
+ mul r0.xy, r1.y, c42
+ mad r0.xy, c41, r1.x, r0
+ mad r0.xy, c43, r1.z, r0
+ add oT1.xy, r0, c44
+ max r1, r2, c45
+ mul oD1, r1, c46
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c11.z
+ mov oT0.xy, v2
+
+// approximately 101 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 180, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 154, 2,
+ 0, 0, 0, 2, 254, 255,
+ 15, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 147, 2, 0, 0, 72, 1,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 88, 1,
+ 0, 0, 0, 0, 0, 0,
+ 104, 1, 0, 0, 2, 0,
+ 45, 0, 1, 0, 182, 0,
+ 88, 1, 0, 0, 0, 0,
+ 0, 0, 115, 1, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 128, 1, 0, 0,
+ 0, 0, 0, 0, 144, 1,
+ 0, 0, 2, 0, 46, 0,
+ 1, 0, 186, 0, 88, 1,
+ 0, 0, 0, 0, 0, 0,
+ 153, 1, 0, 0, 2, 0,
+ 16, 0, 1, 0, 66, 0,
+ 164, 1, 0, 0, 0, 0,
+ 0, 0, 180, 1, 0, 0,
+ 2, 0, 14, 0, 1, 0,
+ 58, 0, 88, 1, 0, 0,
+ 0, 0, 0, 0, 188, 1,
+ 0, 0, 2, 0, 17, 0,
+ 24, 0, 70, 0, 8, 2,
+ 0, 0, 0, 0, 0, 0,
+ 24, 2, 0, 0, 2, 0,
+ 12, 0, 1, 0, 50, 0,
+ 88, 1, 0, 0, 0, 0,
+ 0, 0, 31, 2, 0, 0,
+ 2, 0, 8, 0, 3, 0,
+ 34, 0, 44, 2, 0, 0,
+ 0, 0, 0, 0, 60, 2,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 2, 0, 76, 2,
+ 0, 0, 0, 0, 0, 0,
+ 92, 2, 0, 0, 1, 0,
+ 1, 0, 1, 0, 6, 0,
+ 76, 2, 0, 0, 0, 0,
+ 0, 0, 107, 2, 0, 0,
+ 1, 0, 2, 0, 1, 0,
+ 10, 0, 76, 2, 0, 0,
+ 0, 0, 0, 0, 121, 2,
+ 0, 0, 2, 0, 13, 0,
+ 1, 0, 54, 0, 88, 1,
+ 0, 0, 0, 0, 0, 0,
+ 131, 2, 0, 0, 2, 0,
+ 41, 0, 4, 0, 166, 0,
+ 128, 1, 0, 0, 0, 0,
+ 0, 0, 138, 2, 0, 0,
+ 2, 0, 4, 0, 4, 0,
+ 18, 0, 128, 1, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 108, 111, 114, 67,
+ 108, 97, 109, 112, 0, 99,
+ 111, 109, 98, 105, 110, 101,
+ 100, 77, 97, 116, 0, 171,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 101, 110,
+ 118, 67, 111, 108, 111, 114,
+ 0, 102, 105, 114, 115, 116,
+ 76, 105, 103, 104, 116, 0,
+ 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 111,
+ 103, 68, 97, 116, 97, 0,
+ 108, 105, 103, 104, 116, 115,
+ 0, 99, 111, 108, 111, 114,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 111, 115, 105,
+ 116, 105, 111, 110, 0, 100,
+ 105, 114, 101, 99, 116, 105,
+ 111, 110, 0, 171, 195, 1,
+ 0, 0, 204, 1, 0, 0,
+ 220, 1, 0, 0, 204, 1,
+ 0, 0, 229, 1, 0, 0,
+ 204, 1, 0, 0, 5, 0,
+ 0, 0, 1, 0, 12, 0,
+ 8, 0, 3, 0, 240, 1,
+ 0, 0, 109, 97, 116, 67,
+ 111, 108, 0, 110, 111, 114,
+ 109, 97, 108, 77, 97, 116,
+ 0, 171, 171, 171, 3, 0,
+ 3, 0, 3, 0, 3, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 110, 117, 109, 68,
+ 105, 114, 76, 105, 103, 104,
+ 116, 115, 0, 171, 171, 171,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 110, 117,
+ 109, 80, 111, 105, 110, 116,
+ 76, 105, 103, 104, 116, 115,
+ 0, 110, 117, 109, 83, 112,
+ 111, 116, 76, 105, 103, 104,
+ 116, 115, 0, 115, 117, 114,
+ 102, 80, 114, 111, 112, 115,
+ 0, 116, 101, 120, 77, 97,
+ 116, 0, 119, 111, 114, 108,
+ 100, 77, 97, 116, 0, 118,
+ 115, 95, 50, 95, 48, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 50, 57, 46, 57, 53,
+ 50, 46, 51, 49, 49, 49,
+ 0, 171, 81, 0, 0, 5,
+ 11, 0, 15, 160, 0, 0,
+ 0, 0, 0, 0, 64, 64,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 3, 0, 0, 128, 1, 0,
+ 15, 144, 31, 0, 0, 2,
+ 5, 0, 0, 128, 2, 0,
+ 15, 144, 31, 0, 0, 2,
+ 10, 0, 0, 128, 3, 0,
+ 15, 144, 5, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 85, 144, 1, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 0, 0, 228, 160,
+ 0, 0, 0, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 15, 128, 2, 0,
+ 228, 160, 0, 0, 170, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 3, 0, 228, 160, 0, 0,
+ 255, 144, 0, 0, 228, 128,
+ 1, 0, 0, 2, 0, 0,
+ 15, 192, 0, 0, 228, 128,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 85, 144,
+ 5, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 4, 0, 228, 160, 0, 0,
+ 0, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 6, 0, 228, 160,
+ 0, 0, 170, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 7, 128, 7, 0,
+ 228, 160, 0, 0, 255, 144,
+ 0, 0, 228, 128, 5, 0,
+ 0, 3, 1, 0, 7, 128,
+ 1, 0, 85, 144, 9, 0,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 7, 128, 8, 0,
+ 228, 160, 1, 0, 0, 144,
+ 1, 0, 228, 128, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 10, 0, 228, 160, 1, 0,
+ 170, 144, 1, 0, 228, 128,
+ 1, 0, 0, 2, 2, 0,
+ 1, 128, 13, 0, 0, 160,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 15, 0, 228, 160,
+ 2, 0, 0, 128, 3, 0,
+ 228, 144, 1, 0, 0, 2,
+ 3, 0, 7, 128, 2, 0,
+ 228, 128, 1, 0, 0, 2,
+ 1, 0, 8, 128, 11, 0,
+ 0, 160, 38, 0, 0, 1,
+ 0, 0, 228, 240, 2, 0,
+ 0, 3, 2, 0, 8, 128,
+ 1, 0, 255, 128, 16, 0,
+ 0, 160, 5, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 85, 160,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 2, 0, 255, 128,
+ 8, 0, 0, 4, 2, 0,
+ 8, 128, 1, 0, 228, 128,
+ 19, 32, 228, 161, 0, 0,
+ 0, 176, 11, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 0, 160,
+ 5, 0, 0, 4, 4, 0,
+ 7, 128, 2, 0, 255, 128,
+ 17, 32, 228, 160, 0, 0,
+ 0, 176, 4, 0, 0, 4,
+ 3, 0, 7, 128, 4, 0,
+ 228, 128, 13, 0, 170, 160,
+ 3, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 11, 0,
+ 170, 160, 39, 0, 0, 0,
+ 1, 0, 0, 2, 2, 0,
+ 7, 128, 3, 0, 228, 128,
+ 1, 0, 0, 2, 1, 0,
+ 8, 128, 11, 0, 0, 160,
+ 38, 0, 0, 1, 1, 0,
+ 228, 240, 2, 0, 0, 3,
+ 2, 0, 8, 128, 1, 0,
+ 255, 128, 16, 0, 85, 160,
+ 5, 0, 0, 3, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 11, 0, 85, 160, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 2, 0, 255, 128, 2, 0,
+ 0, 4, 4, 0, 7, 128,
+ 0, 0, 228, 128, 18, 32,
+ 228, 161, 0, 0, 0, 176,
+ 8, 0, 0, 3, 2, 0,
+ 8, 128, 4, 0, 228, 128,
+ 4, 0, 228, 128, 7, 0,
+ 0, 2, 2, 0, 8, 128,
+ 2, 0, 255, 128, 5, 0,
+ 0, 3, 4, 0, 7, 128,
+ 2, 0, 255, 128, 4, 0,
+ 228, 128, 8, 0, 0, 3,
+ 3, 0, 8, 128, 1, 0,
+ 228, 128, 4, 0, 228, 129,
+ 11, 0, 0, 3, 3, 0,
+ 8, 128, 3, 0, 255, 128,
+ 11, 0, 0, 160, 5, 0,
+ 0, 4, 4, 0, 7, 128,
+ 3, 0, 255, 128, 17, 32,
+ 228, 160, 0, 0, 0, 176,
+ 6, 0, 0, 2, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 6, 0, 0, 3, 3, 0,
+ 8, 128, 17, 32, 255, 160,
+ 0, 0, 0, 176, 4, 0,
+ 0, 4, 2, 0, 8, 128,
+ 2, 0, 255, 128, 3, 0,
+ 255, 129, 11, 0, 170, 160,
+ 11, 0, 0, 3, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 11, 0, 0, 160, 5, 0,
+ 0, 3, 4, 0, 7, 128,
+ 2, 0, 255, 128, 4, 0,
+ 228, 128, 4, 0, 0, 4,
+ 2, 0, 7, 128, 4, 0,
+ 228, 128, 13, 0, 170, 160,
+ 2, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 11, 0,
+ 170, 160, 39, 0, 0, 0,
+ 1, 0, 0, 2, 3, 0,
+ 7, 128, 2, 0, 228, 128,
+ 1, 0, 0, 2, 1, 0,
+ 8, 128, 11, 0, 0, 160,
+ 38, 0, 0, 1, 2, 0,
+ 228, 240, 2, 0, 0, 3,
+ 2, 0, 8, 128, 1, 0,
+ 255, 128, 16, 0, 170, 160,
+ 5, 0, 0, 3, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 11, 0, 85, 160, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 2, 0, 255, 128, 2, 0,
+ 0, 4, 4, 0, 7, 128,
+ 0, 0, 228, 128, 18, 32,
+ 228, 161, 0, 0, 0, 176,
+ 8, 0, 0, 3, 2, 0,
+ 8, 128, 4, 0, 228, 128,
+ 4, 0, 228, 128, 7, 0,
+ 0, 2, 2, 0, 8, 128,
+ 2, 0, 255, 128, 5, 0,
+ 0, 3, 4, 0, 7, 128,
+ 2, 0, 255, 128, 4, 0,
+ 228, 128, 8, 0, 0, 3,
+ 4, 0, 8, 128, 1, 0,
+ 228, 128, 4, 0, 228, 129,
+ 8, 0, 0, 4, 4, 0,
+ 1, 128, 4, 0, 228, 128,
+ 19, 32, 228, 160, 0, 0,
+ 0, 176, 11, 0, 0, 3,
+ 4, 0, 2, 128, 4, 0,
+ 255, 128, 11, 0, 0, 160,
+ 1, 0, 0, 2, 4, 0,
+ 4, 128, 11, 0, 170, 160,
+ 2, 0, 0, 4, 4, 0,
+ 5, 128, 4, 0, 228, 128,
+ 18, 32, 255, 160, 0, 0,
+ 0, 176, 6, 0, 0, 2,
+ 4, 0, 4, 128, 4, 0,
+ 170, 128, 5, 0, 0, 3,
+ 4, 0, 1, 128, 4, 0,
+ 170, 128, 4, 0, 0, 128,
+ 12, 0, 0, 3, 4, 0,
+ 4, 128, 4, 0, 0, 128,
+ 11, 0, 0, 160, 4, 0,
+ 0, 4, 4, 0, 2, 128,
+ 4, 0, 170, 128, 4, 0,
+ 85, 129, 4, 0, 85, 128,
+ 11, 0, 0, 4, 4, 0,
+ 1, 128, 4, 0, 0, 128,
+ 19, 32, 255, 160, 0, 0,
+ 0, 176, 5, 0, 0, 3,
+ 4, 0, 1, 128, 4, 0,
+ 0, 128, 4, 0, 85, 128,
+ 5, 0, 0, 4, 4, 0,
+ 7, 128, 4, 0, 0, 128,
+ 17, 32, 228, 160, 0, 0,
+ 0, 176, 6, 0, 0, 2,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 6, 0, 0, 3,
+ 4, 0, 8, 128, 17, 32,
+ 255, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 4, 0, 255, 129, 11, 0,
+ 170, 160, 11, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 11, 0, 0, 160,
+ 5, 0, 0, 3, 4, 0,
+ 7, 128, 2, 0, 255, 128,
+ 4, 0, 228, 128, 4, 0,
+ 0, 4, 3, 0, 7, 128,
+ 4, 0, 228, 128, 13, 0,
+ 170, 160, 3, 0, 228, 128,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 11, 0, 170, 160, 39, 0,
+ 0, 0, 1, 0, 0, 2,
+ 3, 0, 8, 128, 3, 0,
+ 255, 144, 11, 0, 0, 3,
+ 2, 0, 15, 128, 3, 0,
+ 228, 128, 11, 0, 0, 160,
+ 10, 0, 0, 3, 2, 0,
+ 15, 128, 2, 0, 228, 128,
+ 11, 0, 170, 160, 5, 0,
+ 0, 3, 0, 0, 15, 208,
+ 2, 0, 228, 128, 12, 0,
+ 228, 160, 5, 0, 0, 3,
+ 0, 0, 3, 128, 1, 0,
+ 85, 128, 42, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 3, 128, 41, 0, 228, 160,
+ 1, 0, 0, 128, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 3, 128, 43, 0,
+ 228, 160, 1, 0, 170, 128,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 3, 224,
+ 0, 0, 228, 128, 44, 0,
+ 228, 160, 11, 0, 0, 3,
+ 1, 0, 15, 128, 2, 0,
+ 228, 128, 45, 0, 228, 160,
+ 5, 0, 0, 3, 1, 0,
+ 15, 208, 1, 0, 228, 128,
+ 46, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 5, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 11, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/matfx_env_amb_VS.h b/src/d3d/shaders/matfx_env_amb_VS.h
new file mode 100644
index 0000000..0367d5e
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_amb_VS.h
@@ -0,0 +1,225 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /Fh matfx_env_amb_VS.h matfx_env_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4 colorClamp;
+// float4x4 combinedMat;
+// float4 envColor;
+// float4 fogData;
+// float4 matCol;
+// float3x3 normalMat;
+// float4 surfProps;
+// float4x4 texMat;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// combinedMat c0 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// texMat c41 4
+// colorClamp c45 1
+// envColor c46 1
+//
+
+ vs_2_0
+ def c4, 0, 1, 0, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ mul r0.xyz, v1.y, c9
+ mad r0.xyz, c8, v1.x, r0
+ mad r0.xyz, c10, v1.z, r0
+ mul r0.yw, r0.y, c42.xxzy
+ mad r0.xy, c41, r0.x, r0.ywzw
+ mad r0.xy, c43, r0.z, r0
+ add oT1.xy, r0, c44
+ mov r0.xyz, c15
+ mad r0.xyz, r0, c13.x, v3
+ mov r0.w, v3.w
+ max r0, r0, c4.x
+ min r0, r0, c4.y
+ max r1, r0, c45
+ mul oD0, r0, c12
+ mul oD1, r1, c46
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ add r1.x, r0.w, -c14.y
+ mov oPos, r0
+ mul r0.x, r1.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.y
+ mov oT0.xy, v2
+
+// approximately 25 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 103, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 100, 1,
+ 0, 0, 0, 2, 254, 255,
+ 9, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 93, 1, 0, 0, 208, 0,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 224, 0,
+ 0, 0, 0, 0, 0, 0,
+ 240, 0, 0, 0, 2, 0,
+ 45, 0, 1, 0, 182, 0,
+ 224, 0, 0, 0, 0, 0,
+ 0, 0, 251, 0, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 8, 1, 0, 0,
+ 0, 0, 0, 0, 24, 1,
+ 0, 0, 2, 0, 46, 0,
+ 1, 0, 186, 0, 224, 0,
+ 0, 0, 0, 0, 0, 0,
+ 33, 1, 0, 0, 2, 0,
+ 14, 0, 1, 0, 58, 0,
+ 224, 0, 0, 0, 0, 0,
+ 0, 0, 41, 1, 0, 0,
+ 2, 0, 12, 0, 1, 0,
+ 50, 0, 224, 0, 0, 0,
+ 0, 0, 0, 0, 48, 1,
+ 0, 0, 2, 0, 8, 0,
+ 3, 0, 34, 0, 60, 1,
+ 0, 0, 0, 0, 0, 0,
+ 76, 1, 0, 0, 2, 0,
+ 13, 0, 1, 0, 54, 0,
+ 224, 0, 0, 0, 0, 0,
+ 0, 0, 86, 1, 0, 0,
+ 2, 0, 41, 0, 4, 0,
+ 166, 0, 8, 1, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 108, 111, 114, 67,
+ 108, 97, 109, 112, 0, 99,
+ 111, 109, 98, 105, 110, 101,
+ 100, 77, 97, 116, 0, 171,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 101, 110,
+ 118, 67, 111, 108, 111, 114,
+ 0, 102, 111, 103, 68, 97,
+ 116, 97, 0, 109, 97, 116,
+ 67, 111, 108, 0, 110, 111,
+ 114, 109, 97, 108, 77, 97,
+ 116, 0, 171, 171, 3, 0,
+ 3, 0, 3, 0, 3, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 117, 114, 102,
+ 80, 114, 111, 112, 115, 0,
+ 116, 101, 120, 77, 97, 116,
+ 0, 118, 115, 95, 50, 95,
+ 48, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 57, 46, 50, 57, 46,
+ 57, 53, 50, 46, 51, 49,
+ 49, 49, 0, 171, 171, 171,
+ 81, 0, 0, 5, 4, 0,
+ 15, 160, 0, 0, 0, 0,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 3, 0,
+ 0, 128, 1, 0, 15, 144,
+ 31, 0, 0, 2, 5, 0,
+ 0, 128, 2, 0, 15, 144,
+ 31, 0, 0, 2, 10, 0,
+ 0, 128, 3, 0, 15, 144,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 1, 0, 85, 144,
+ 9, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 8, 0, 228, 160, 1, 0,
+ 0, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 10, 0, 228, 160,
+ 1, 0, 170, 144, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 0, 0, 10, 128, 0, 0,
+ 85, 128, 42, 0, 96, 160,
+ 4, 0, 0, 4, 0, 0,
+ 3, 128, 41, 0, 228, 160,
+ 0, 0, 0, 128, 0, 0,
+ 237, 128, 4, 0, 0, 4,
+ 0, 0, 3, 128, 43, 0,
+ 228, 160, 0, 0, 170, 128,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 3, 224,
+ 0, 0, 228, 128, 44, 0,
+ 228, 160, 1, 0, 0, 2,
+ 0, 0, 7, 128, 15, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 7, 128, 0, 0,
+ 228, 128, 13, 0, 0, 160,
+ 3, 0, 228, 144, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 3, 0, 255, 144, 11, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 4, 0,
+ 0, 160, 10, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 4, 0, 85, 160,
+ 11, 0, 0, 3, 1, 0,
+ 15, 128, 0, 0, 228, 128,
+ 45, 0, 228, 160, 5, 0,
+ 0, 3, 0, 0, 15, 208,
+ 0, 0, 228, 128, 12, 0,
+ 228, 160, 5, 0, 0, 3,
+ 1, 0, 15, 208, 1, 0,
+ 228, 128, 46, 0, 228, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 85, 144,
+ 1, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 228, 160, 0, 0,
+ 0, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 2, 0, 228, 160,
+ 0, 0, 170, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 15, 128, 3, 0,
+ 228, 160, 0, 0, 255, 144,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 1, 0, 0, 2,
+ 0, 0, 15, 192, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 0, 0, 1, 128, 1, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 4, 0,
+ 85, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/matfx_env_amb_dir_VS.h b/src/d3d/shaders/matfx_env_amb_dir_VS.h
new file mode 100644
index 0000000..b93e572
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_amb_dir_VS.h
@@ -0,0 +1,316 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /Fh matfx_env_amb_dir_VS.h
+// matfx_env_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4 colorClamp;
+// float4x4 combinedMat;
+// float4 envColor;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// float4 surfProps;
+// float4x4 texMat;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// numDirLights i0 1
+// combinedMat c0 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+// texMat c41 4
+// colorClamp c45 1
+// envColor c46 1
+//
+
+ vs_2_0
+ def c4, 0, 3, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ mul r0, v0.y, c1
+ mad r0, c0, v0.x, r0
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ mov oPos, r0
+ mul r0.xyz, v1.y, c9
+ mad r0.xyz, c8, v1.x, r0
+ mad r0.xyz, c10, v1.z, r0
+ mov r1.x, c13.x
+ mad r1.xyz, c15, r1.x, v3
+ mov r2.xyz, r1
+ mov r1.w, c4.x
+ rep i0
+ add r3.x, r1.w, c16.x
+ mul r3.x, r3.x, c4.y
+ mova a0.x, r3.x
+ dp3 r3.x, r0, -c19[a0.x]
+ max r3.x, r3.x, c4.x
+ mul r3.xyz, r3.x, c17[a0.x]
+ mad r2.xyz, r3, c13.z, r2
+ add r1.w, r1.w, c4.z
+ endrep
+ mov r2.w, v3.w
+ max r1, r2, c4.x
+ min r1, r1, c4.z
+ mul oD0, r1, c12
+ mul r2.xy, r0.y, c42
+ mad r0.xy, c41, r0.x, r2
+ mad r0.xy, c43, r0.z, r0
+ add oT1.xy, r0, c44
+ max r1, r1, c45
+ mul oD1, r1, c46
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.z
+ mov oT0.xy, v2
+
+// approximately 40 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 156, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 56, 2,
+ 0, 0, 0, 2, 254, 255,
+ 12, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 49, 2, 0, 0, 12, 1,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 28, 1,
+ 0, 0, 0, 0, 0, 0,
+ 44, 1, 0, 0, 2, 0,
+ 45, 0, 1, 0, 182, 0,
+ 28, 1, 0, 0, 0, 0,
+ 0, 0, 55, 1, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 68, 1, 0, 0,
+ 0, 0, 0, 0, 84, 1,
+ 0, 0, 2, 0, 46, 0,
+ 1, 0, 186, 0, 28, 1,
+ 0, 0, 0, 0, 0, 0,
+ 93, 1, 0, 0, 2, 0,
+ 16, 0, 1, 0, 66, 0,
+ 104, 1, 0, 0, 0, 0,
+ 0, 0, 120, 1, 0, 0,
+ 2, 0, 14, 0, 1, 0,
+ 58, 0, 28, 1, 0, 0,
+ 0, 0, 0, 0, 128, 1,
+ 0, 0, 2, 0, 17, 0,
+ 24, 0, 70, 0, 204, 1,
+ 0, 0, 0, 0, 0, 0,
+ 220, 1, 0, 0, 2, 0,
+ 12, 0, 1, 0, 50, 0,
+ 28, 1, 0, 0, 0, 0,
+ 0, 0, 227, 1, 0, 0,
+ 2, 0, 8, 0, 3, 0,
+ 34, 0, 240, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 2, 0, 16, 2,
+ 0, 0, 0, 0, 0, 0,
+ 32, 2, 0, 0, 2, 0,
+ 13, 0, 1, 0, 54, 0,
+ 28, 1, 0, 0, 0, 0,
+ 0, 0, 42, 2, 0, 0,
+ 2, 0, 41, 0, 4, 0,
+ 166, 0, 68, 1, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 108, 111, 114, 67,
+ 108, 97, 109, 112, 0, 99,
+ 111, 109, 98, 105, 110, 101,
+ 100, 77, 97, 116, 0, 171,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 101, 110,
+ 118, 67, 111, 108, 111, 114,
+ 0, 102, 105, 114, 115, 116,
+ 76, 105, 103, 104, 116, 0,
+ 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 111,
+ 103, 68, 97, 116, 97, 0,
+ 108, 105, 103, 104, 116, 115,
+ 0, 99, 111, 108, 111, 114,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 111, 115, 105,
+ 116, 105, 111, 110, 0, 100,
+ 105, 114, 101, 99, 116, 105,
+ 111, 110, 0, 171, 135, 1,
+ 0, 0, 144, 1, 0, 0,
+ 160, 1, 0, 0, 144, 1,
+ 0, 0, 169, 1, 0, 0,
+ 144, 1, 0, 0, 5, 0,
+ 0, 0, 1, 0, 12, 0,
+ 8, 0, 3, 0, 180, 1,
+ 0, 0, 109, 97, 116, 67,
+ 111, 108, 0, 110, 111, 114,
+ 109, 97, 108, 77, 97, 116,
+ 0, 171, 171, 171, 3, 0,
+ 3, 0, 3, 0, 3, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 110, 117, 109, 68,
+ 105, 114, 76, 105, 103, 104,
+ 116, 115, 0, 171, 171, 171,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 117,
+ 114, 102, 80, 114, 111, 112,
+ 115, 0, 116, 101, 120, 77,
+ 97, 116, 0, 118, 115, 95,
+ 50, 95, 48, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 50,
+ 57, 46, 57, 53, 50, 46,
+ 51, 49, 49, 49, 0, 171,
+ 171, 171, 81, 0, 0, 5,
+ 4, 0, 15, 160, 0, 0,
+ 0, 0, 0, 0, 64, 64,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 3, 0, 0, 128, 1, 0,
+ 15, 144, 31, 0, 0, 2,
+ 5, 0, 0, 128, 2, 0,
+ 15, 144, 31, 0, 0, 2,
+ 10, 0, 0, 128, 3, 0,
+ 15, 144, 5, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 85, 144, 1, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 0, 0, 228, 160,
+ 0, 0, 0, 144, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 15, 128, 2, 0,
+ 228, 160, 0, 0, 170, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 3, 0, 228, 160, 0, 0,
+ 255, 144, 0, 0, 228, 128,
+ 1, 0, 0, 2, 0, 0,
+ 15, 192, 0, 0, 228, 128,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 1, 0, 85, 144,
+ 9, 0, 228, 160, 4, 0,
+ 0, 4, 0, 0, 7, 128,
+ 8, 0, 228, 160, 1, 0,
+ 0, 144, 0, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 10, 0, 228, 160,
+ 1, 0, 170, 144, 0, 0,
+ 228, 128, 1, 0, 0, 2,
+ 1, 0, 1, 128, 13, 0,
+ 0, 160, 4, 0, 0, 4,
+ 1, 0, 7, 128, 15, 0,
+ 228, 160, 1, 0, 0, 128,
+ 3, 0, 228, 144, 1, 0,
+ 0, 2, 2, 0, 7, 128,
+ 1, 0, 228, 128, 1, 0,
+ 0, 2, 1, 0, 8, 128,
+ 4, 0, 0, 160, 38, 0,
+ 0, 1, 0, 0, 228, 240,
+ 2, 0, 0, 3, 3, 0,
+ 1, 128, 1, 0, 255, 128,
+ 16, 0, 0, 160, 5, 0,
+ 0, 3, 3, 0, 1, 128,
+ 3, 0, 0, 128, 4, 0,
+ 85, 160, 46, 0, 0, 2,
+ 0, 0, 1, 176, 3, 0,
+ 0, 128, 8, 0, 0, 4,
+ 3, 0, 1, 128, 0, 0,
+ 228, 128, 19, 32, 228, 161,
+ 0, 0, 0, 176, 11, 0,
+ 0, 3, 3, 0, 1, 128,
+ 3, 0, 0, 128, 4, 0,
+ 0, 160, 5, 0, 0, 4,
+ 3, 0, 7, 128, 3, 0,
+ 0, 128, 17, 32, 228, 160,
+ 0, 0, 0, 176, 4, 0,
+ 0, 4, 2, 0, 7, 128,
+ 3, 0, 228, 128, 13, 0,
+ 170, 160, 2, 0, 228, 128,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 4, 0, 170, 160, 39, 0,
+ 0, 0, 1, 0, 0, 2,
+ 2, 0, 8, 128, 3, 0,
+ 255, 144, 11, 0, 0, 3,
+ 1, 0, 15, 128, 2, 0,
+ 228, 128, 4, 0, 0, 160,
+ 10, 0, 0, 3, 1, 0,
+ 15, 128, 1, 0, 228, 128,
+ 4, 0, 170, 160, 5, 0,
+ 0, 3, 0, 0, 15, 208,
+ 1, 0, 228, 128, 12, 0,
+ 228, 160, 5, 0, 0, 3,
+ 2, 0, 3, 128, 0, 0,
+ 85, 128, 42, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 3, 128, 41, 0, 228, 160,
+ 0, 0, 0, 128, 2, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 3, 128, 43, 0,
+ 228, 160, 0, 0, 170, 128,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 3, 224,
+ 0, 0, 228, 128, 44, 0,
+ 228, 160, 11, 0, 0, 3,
+ 1, 0, 15, 128, 1, 0,
+ 228, 128, 45, 0, 228, 160,
+ 5, 0, 0, 3, 1, 0,
+ 15, 208, 1, 0, 228, 128,
+ 46, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 5, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 4, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/matfx_env_tex_PS.h b/src/d3d/shaders/matfx_env_tex_PS.h
new file mode 100644
index 0000000..e2e7429
--- /dev/null
+++ b/src/d3d/shaders/matfx_env_tex_PS.h
@@ -0,0 +1,141 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T ps_2_0 /DTEX /Fh matfx_env_tex_PS.h matfx_env_PS.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D diffTex;
+// sampler2D envTex;
+// float4 fogColor;
+// float4 fxparams;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fogColor c0 1
+// fxparams c1 1
+// diffTex s0 1
+// envTex s1 1
+//
+
+ ps_2_0
+ dcl t0.xyz
+ dcl t1.xy
+ dcl v0
+ dcl v1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t1, s1
+ texld r1, t0, s0
+ mul r2.xyz, v1, c1.x
+ mul r0.xyz, r0, r2
+ mul r0.xyz, r0, t0.z
+ mul r2.w, r1.w, v0.w
+ mad r1.xyz, v0, r1, -c0
+ mad r1.xyz, t0.z, r1, c0
+ max r0.w, r2.w, c1.y
+ mul r0.xyz, r0.w, r0
+ mad r2.xyz, r1, r2.w, r0
+ mov oC0, r2
+
+// approximately 12 instruction slots used (2 texture, 10 arithmetic)
+#endif
+
+const BYTE g_ps20_main[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 64, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 200, 0,
+ 0, 0, 0, 2, 255, 255,
+ 4, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 193, 0, 0, 0, 108, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 2, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0,
+ 132, 0, 0, 0, 3, 0,
+ 1, 0, 1, 0, 6, 0,
+ 140, 0, 0, 0, 0, 0,
+ 0, 0, 156, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 2, 0, 168, 0, 0, 0,
+ 0, 0, 0, 0, 184, 0,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 6, 0, 168, 0,
+ 0, 0, 0, 0, 0, 0,
+ 100, 105, 102, 102, 84, 101,
+ 120, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 101, 110, 118, 84, 101, 120,
+ 0, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 67, 111, 108,
+ 111, 114, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 102, 120,
+ 112, 97, 114, 97, 109, 115,
+ 0, 112, 115, 95, 50, 95,
+ 48, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 57, 46, 50, 57, 46,
+ 57, 53, 50, 46, 51, 49,
+ 49, 49, 0, 171, 171, 171,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 7, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 1, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 1, 0, 7, 144,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 1, 0, 228, 176,
+ 1, 8, 228, 160, 66, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 5, 0, 0, 3,
+ 2, 0, 7, 128, 1, 0,
+ 228, 144, 1, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 2, 0, 228, 128, 5, 0,
+ 0, 3, 0, 0, 7, 128,
+ 0, 0, 228, 128, 0, 0,
+ 170, 176, 5, 0, 0, 3,
+ 2, 0, 8, 128, 1, 0,
+ 255, 128, 0, 0, 255, 144,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 0, 0, 228, 144,
+ 1, 0, 228, 128, 0, 0,
+ 228, 161, 4, 0, 0, 4,
+ 1, 0, 7, 128, 0, 0,
+ 170, 176, 1, 0, 228, 128,
+ 0, 0, 228, 160, 11, 0,
+ 0, 3, 0, 0, 8, 128,
+ 2, 0, 255, 128, 1, 0,
+ 85, 160, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0,
+ 255, 128, 0, 0, 228, 128,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 1, 0, 228, 128,
+ 2, 0, 255, 128, 0, 0,
+ 228, 128, 1, 0, 0, 2,
+ 0, 8, 15, 128, 2, 0,
+ 228, 128, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/skin_VS.hlsl b/src/d3d/shaders/skin_VS.hlsl
new file mode 100644
index 0000000..bede50f
--- /dev/null
+++ b/src/d3d/shaders/skin_VS.hlsl
@@ -0,0 +1,63 @@
+#include "standardConstants.h"
+
+float4x3 boneMatrices[64] : register(c41);
+
+struct VS_in
+{
+ float4 Position : POSITION;
+ float3 Normal : NORMAL;
+ float2 TexCoord : TEXCOORD0;
+ float4 Prelight : COLOR0;
+ float4 Weights : BLENDWEIGHT;
+ int4 Indices : BLENDINDICES;
+};
+
+struct VS_out {
+ float4 Position : POSITION;
+ float3 TexCoord0 : TEXCOORD0; // also fog
+ float4 Color : COLOR0;
+};
+
+
+VS_out main(in VS_in input)
+{
+ VS_out output;
+
+ int j;
+ float3 SkinVertex = float3(0.0, 0.0, 0.0);
+ float3 SkinNormal = float3(0.0, 0.0, 0.0);
+ for(j = 0; j < 4; j++){
+ SkinVertex += mul(input.Position, boneMatrices[input.Indices[j]]).xyz * input.Weights[j];
+ SkinNormal += mul(input.Normal, (float3x3)boneMatrices[input.Indices[j]]).xyz * input.Weights[j];
+ }
+
+ output.Position = mul(combinedMat, float4(SkinVertex, 1.0));
+ float3 Vertex = mul(worldMat, float4(SkinVertex, 1.0)).xyz;
+ float3 Normal = mul(normalMat, SkinNormal);
+
+ output.TexCoord0.xy = input.TexCoord;
+
+ output.Color = input.Prelight;
+ output.Color.rgb += ambientLight.rgb * surfAmbient;
+
+ int i;
+#ifdef DIRECTIONALS
+ for(i = 0; i < numDirLights; i++)
+ output.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse;
+#endif
+#ifdef POINTLIGHTS
+ for(i = 0; i < numPointLights; i++)
+ output.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse;
+#endif
+#ifdef SPOTLIGHTS
+ for(i = 0; i < numSpotLights; i++)
+ output.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse;
+#endif
+ // PS2 clamps before material color
+ output.Color = clamp(output.Color, 0.0, 1.0);
+ output.Color *= matCol;
+
+ output.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);
+
+ return output;
+}
diff --git a/src/d3d/shaders/skin_all_VS.h b/src/d3d/shaders/skin_all_VS.h
new file mode 100644
index 0000000..67f89f3
--- /dev/null
+++ b/src/d3d/shaders/skin_all_VS.h
@@ -0,0 +1,664 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /DPOINTLIGHTS /DSPOTLIGHTS /Fh
+// skin_all_VS.h skin_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x3 boneMatrices[64];
+// float4x4 combinedMat;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// int numPointLights;
+// int numSpotLights;
+// float4 surfProps;
+// float4x4 worldMat;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// -------------- ----- ----
+// numDirLights i0 1
+// numPointLights i1 1
+// numSpotLights i2 1
+// combinedMat c0 4
+// worldMat c4 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+// boneMatrices c41 192
+//
+
+ vs_2_0
+ def c11, 3, 0, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ dcl_blendweight v4
+ dcl_blendindices v5
+ mul r0, v5, c11.x
+ mova a0.x, r0.x
+ dp3 r1.z, v1, c43[a0.x]
+ dp4 r2.x, v0, c41[a0.x]
+ dp4 r2.y, v0, c42[a0.x]
+ dp4 r2.z, v0, c43[a0.x]
+ dp3 r1.x, v1, c41[a0.x]
+ dp3 r1.y, v1, c42[a0.x]
+ mova a0.x, r0.y
+ dp3 r3.z, v1, c43[a0.x]
+ dp4 r4.x, v0, c41[a0.x]
+ dp4 r4.y, v0, c42[a0.x]
+ dp4 r4.z, v0, c43[a0.x]
+ mul r4.xyz, r4, v4.y
+ mad r2.xyz, r2, v4.x, r4
+ dp3 r3.x, v1, c41[a0.x]
+ dp3 r3.y, v1, c42[a0.x]
+ mul r3.xyz, r3, v4.y
+ mad r1.xyz, r1, v4.x, r3
+ mova a0.x, r0.z
+ dp3 r0.z, v1, c43[a0.x]
+ dp4 r3.x, v0, c41[a0.x]
+ dp4 r3.y, v0, c42[a0.x]
+ dp4 r3.z, v0, c43[a0.x]
+ mad r2.xyz, r3, v4.z, r2
+ dp3 r0.x, v1, c41[a0.x]
+ dp3 r0.y, v1, c42[a0.x]
+ mad r0.xyz, r0, v4.z, r1
+ mova a0.x, r0.w
+ dp3 r1.z, v1, c43[a0.x]
+ dp4 r3.x, v0, c41[a0.x]
+ dp4 r3.y, v0, c42[a0.x]
+ dp4 r3.z, v0, c43[a0.x]
+ mad r2.xyz, r3, v4.w, r2
+ dp3 r1.x, v1, c41[a0.x]
+ dp3 r1.y, v1, c42[a0.x]
+ mad r0.xyz, r1, v4.w, r0
+ mul r1.xyz, r2.y, c5
+ mad r1.xyz, c4, r2.x, r1
+ mad r1.xyz, c6, r2.z, r1
+ add r1.xyz, r1, c7
+ mul r3.xyz, r0.y, c9
+ mad r0.xyw, c8.xyzz, r0.x, r3.xyzz
+ mad r0.xyz, c10, r0.z, r0.xyww
+ mov r3.x, c13.x
+ mad r3.xyz, c15, r3.x, v3
+ mov r4.xyz, r3
+ mov r0.w, c11.y
+ rep i0
+ add r1.w, r0.w, c16.x
+ mul r1.w, r1.w, c11.x
+ mova a0.x, r1.w
+ dp3 r1.w, r0, -c19[a0.x]
+ max r1.w, r1.w, c11.y
+ mul r5.xyz, r1.w, c17[a0.x]
+ mad r4.xyz, r5, c13.z, r4
+ add r0.w, r0.w, c11.z
+ endrep
+ mov r3.xyz, r4
+ mov r0.w, c11.y
+ rep i1
+ add r1.w, r0.w, c16.y
+ mul r1.w, r1.w, c11.x
+ mova a0.x, r1.w
+ add r5.xyz, r1, -c18[a0.x]
+ dp3 r1.w, r5, r5
+ rsq r1.w, r1.w
+ mul r5.xyz, r1.w, r5
+ dp3 r2.w, r0, -r5
+ max r2.w, r2.w, c11.y
+ mul r5.xyz, r2.w, c17[a0.x]
+ rcp r1.w, r1.w
+ rcp r2.w, c17[a0.x].w
+ mad r1.w, r1.w, -r2.w, c11.z
+ max r1.w, r1.w, c11.y
+ mul r5.xyz, r1.w, r5
+ mad r3.xyz, r5, c13.z, r3
+ add r0.w, r0.w, c11.z
+ endrep
+ mov r4.xyz, r3
+ mov r0.w, c11.y
+ rep i2
+ add r1.w, r0.w, c16.z
+ mul r1.w, r1.w, c11.x
+ mova a0.x, r1.w
+ add r5.xyz, r1, -c18[a0.x]
+ dp3 r1.w, r5, r5
+ rsq r1.w, r1.w
+ mul r5.xyz, r1.w, r5
+ dp3 r2.w, r0, -r5
+ dp3 r3.w, r5, c19[a0.x]
+ max r2.w, r2.w, c11.y
+ add r3.w, r3.w, c18[a0.x].w
+ mov r5.z, c11.z
+ add r5.x, r5.z, c18[a0.x].w
+ rcp r5.x, r5.x
+ mul r3.w, r3.w, r5.x
+ slt r5.x, r3.w, c11.y
+ mad r2.w, r5.x, -r2.w, r2.w
+ max r3.w, r3.w, c19[a0.x].w
+ mul r2.w, r2.w, r3.w
+ mul r5.xyz, r2.w, c17[a0.x]
+ rcp r1.w, r1.w
+ rcp r2.w, c17[a0.x].w
+ mad r1.w, r1.w, -r2.w, c11.z
+ max r1.w, r1.w, c11.y
+ mul r5.xyz, r1.w, r5
+ mad r4.xyz, r5, c13.z, r4
+ add r0.w, r0.w, c11.z
+ endrep
+ mov r4.w, v3.w
+ max r0, r4, c11.y
+ min r0, r0, c11.z
+ mul oD0, r0, c12
+ mul r0, r2.y, c1
+ mad r0, c0, r2.x, r0
+ mad r0, c2, r2.z, r0
+ add r0, r0, c3
+ mov oPos, r0
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c11.z
+ mov oT0.xy, v2
+
+// approximately 133 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 171, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 119, 2,
+ 0, 0, 0, 2, 254, 255,
+ 13, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 112, 2, 0, 0, 32, 1,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 48, 1,
+ 0, 0, 0, 0, 0, 0,
+ 64, 1, 0, 0, 2, 0,
+ 41, 0, 192, 0, 166, 0,
+ 80, 1, 0, 0, 0, 0,
+ 0, 0, 96, 1, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 108, 1, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 2, 0, 16, 0,
+ 1, 0, 66, 0, 136, 1,
+ 0, 0, 0, 0, 0, 0,
+ 152, 1, 0, 0, 2, 0,
+ 14, 0, 1, 0, 58, 0,
+ 48, 1, 0, 0, 0, 0,
+ 0, 0, 160, 1, 0, 0,
+ 2, 0, 17, 0, 24, 0,
+ 70, 0, 236, 1, 0, 0,
+ 0, 0, 0, 0, 252, 1,
+ 0, 0, 2, 0, 12, 0,
+ 1, 0, 50, 0, 48, 1,
+ 0, 0, 0, 0, 0, 0,
+ 3, 2, 0, 0, 2, 0,
+ 8, 0, 3, 0, 34, 0,
+ 16, 2, 0, 0, 0, 0,
+ 0, 0, 32, 2, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 2, 0, 48, 2, 0, 0,
+ 0, 0, 0, 0, 64, 2,
+ 0, 0, 1, 0, 1, 0,
+ 1, 0, 6, 0, 48, 2,
+ 0, 0, 0, 0, 0, 0,
+ 79, 2, 0, 0, 1, 0,
+ 2, 0, 1, 0, 10, 0,
+ 48, 2, 0, 0, 0, 0,
+ 0, 0, 93, 2, 0, 0,
+ 2, 0, 13, 0, 1, 0,
+ 54, 0, 48, 1, 0, 0,
+ 0, 0, 0, 0, 103, 2,
+ 0, 0, 2, 0, 4, 0,
+ 4, 0, 18, 0, 108, 1,
+ 0, 0, 0, 0, 0, 0,
+ 97, 109, 98, 105, 101, 110,
+ 116, 76, 105, 103, 104, 116,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 98, 111, 110, 101,
+ 77, 97, 116, 114, 105, 99,
+ 101, 115, 0, 171, 171, 171,
+ 3, 0, 3, 0, 4, 0,
+ 3, 0, 64, 0, 0, 0,
+ 0, 0, 0, 0, 99, 111,
+ 109, 98, 105, 110, 101, 100,
+ 77, 97, 116, 0, 3, 0,
+ 3, 0, 4, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 105, 114, 115,
+ 116, 76, 105, 103, 104, 116,
+ 0, 171, 1, 0, 2, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 68, 97, 116,
+ 97, 0, 108, 105, 103, 104,
+ 116, 115, 0, 99, 111, 108,
+ 111, 114, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 111,
+ 115, 105, 116, 105, 111, 110,
+ 0, 100, 105, 114, 101, 99,
+ 116, 105, 111, 110, 0, 171,
+ 167, 1, 0, 0, 176, 1,
+ 0, 0, 192, 1, 0, 0,
+ 176, 1, 0, 0, 201, 1,
+ 0, 0, 176, 1, 0, 0,
+ 5, 0, 0, 0, 1, 0,
+ 12, 0, 8, 0, 3, 0,
+ 212, 1, 0, 0, 109, 97,
+ 116, 67, 111, 108, 0, 110,
+ 111, 114, 109, 97, 108, 77,
+ 97, 116, 0, 171, 171, 171,
+ 3, 0, 3, 0, 3, 0,
+ 3, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 110, 117,
+ 109, 68, 105, 114, 76, 105,
+ 103, 104, 116, 115, 0, 171,
+ 171, 171, 0, 0, 2, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 110, 117, 109, 80, 111, 105,
+ 110, 116, 76, 105, 103, 104,
+ 116, 115, 0, 110, 117, 109,
+ 83, 112, 111, 116, 76, 105,
+ 103, 104, 116, 115, 0, 115,
+ 117, 114, 102, 80, 114, 111,
+ 112, 115, 0, 119, 111, 114,
+ 108, 100, 77, 97, 116, 0,
+ 118, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 81, 0, 0, 5,
+ 11, 0, 15, 160, 0, 0,
+ 64, 64, 0, 0, 0, 0,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 3, 0, 0, 128, 1, 0,
+ 15, 144, 31, 0, 0, 2,
+ 5, 0, 0, 128, 2, 0,
+ 15, 144, 31, 0, 0, 2,
+ 10, 0, 0, 128, 3, 0,
+ 15, 144, 31, 0, 0, 2,
+ 1, 0, 0, 128, 4, 0,
+ 15, 144, 31, 0, 0, 2,
+ 2, 0, 0, 128, 5, 0,
+ 15, 144, 5, 0, 0, 3,
+ 0, 0, 15, 128, 5, 0,
+ 228, 144, 11, 0, 0, 160,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 0, 0, 0, 128,
+ 8, 0, 0, 4, 1, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 2, 0, 1, 128, 0, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 2, 0, 2, 128,
+ 0, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 9, 0, 0, 4, 2, 0,
+ 4, 128, 0, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 8, 0, 0, 4,
+ 1, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 8, 0,
+ 0, 4, 1, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 0, 0, 85, 128,
+ 8, 0, 0, 4, 3, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 4, 0, 1, 128, 0, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 4, 0, 2, 128,
+ 0, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 9, 0, 0, 4, 4, 0,
+ 4, 128, 0, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 5, 0, 0, 3,
+ 4, 0, 7, 128, 4, 0,
+ 228, 128, 4, 0, 85, 144,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 2, 0, 228, 128,
+ 4, 0, 0, 144, 4, 0,
+ 228, 128, 8, 0, 0, 4,
+ 3, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 8, 0,
+ 0, 4, 3, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 5, 0, 0, 3, 3, 0,
+ 7, 128, 3, 0, 228, 128,
+ 4, 0, 85, 144, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 1, 0, 228, 128, 4, 0,
+ 0, 144, 3, 0, 228, 128,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 0, 0, 170, 128,
+ 8, 0, 0, 4, 0, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 3, 0, 1, 128, 0, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 3, 0, 2, 128,
+ 0, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 9, 0, 0, 4, 3, 0,
+ 4, 128, 0, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 0, 176, 4, 0, 0, 4,
+ 2, 0, 7, 128, 3, 0,
+ 228, 128, 4, 0, 170, 144,
+ 2, 0, 228, 128, 8, 0,
+ 0, 4, 0, 0, 1, 128,
+ 1, 0, 228, 144, 41, 32,
+ 228, 160, 0, 0, 0, 176,
+ 8, 0, 0, 4, 0, 0,
+ 2, 128, 1, 0, 228, 144,
+ 42, 32, 228, 160, 0, 0,
+ 0, 176, 4, 0, 0, 4,
+ 0, 0, 7, 128, 0, 0,
+ 228, 128, 4, 0, 170, 144,
+ 1, 0, 228, 128, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 0, 0, 255, 128, 8, 0,
+ 0, 4, 1, 0, 4, 128,
+ 1, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 0, 176,
+ 9, 0, 0, 4, 3, 0,
+ 1, 128, 0, 0, 228, 144,
+ 41, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 3, 0, 2, 128, 0, 0,
+ 228, 144, 42, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 3, 0, 4, 128,
+ 0, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 3, 0, 228, 128,
+ 4, 0, 255, 144, 2, 0,
+ 228, 128, 8, 0, 0, 4,
+ 1, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 0, 176, 8, 0,
+ 0, 4, 1, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 1, 0, 228, 128,
+ 4, 0, 255, 144, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 1, 0, 7, 128, 2, 0,
+ 85, 128, 5, 0, 228, 160,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 4, 0, 228, 160,
+ 2, 0, 0, 128, 1, 0,
+ 228, 128, 4, 0, 0, 4,
+ 1, 0, 7, 128, 6, 0,
+ 228, 160, 2, 0, 170, 128,
+ 1, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 7, 128,
+ 1, 0, 228, 128, 7, 0,
+ 228, 160, 5, 0, 0, 3,
+ 3, 0, 7, 128, 0, 0,
+ 85, 128, 9, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 11, 128, 8, 0, 164, 160,
+ 0, 0, 0, 128, 3, 0,
+ 164, 128, 4, 0, 0, 4,
+ 0, 0, 7, 128, 10, 0,
+ 228, 160, 0, 0, 170, 128,
+ 0, 0, 244, 128, 1, 0,
+ 0, 2, 3, 0, 1, 128,
+ 13, 0, 0, 160, 4, 0,
+ 0, 4, 3, 0, 7, 128,
+ 15, 0, 228, 160, 3, 0,
+ 0, 128, 3, 0, 228, 144,
+ 1, 0, 0, 2, 4, 0,
+ 7, 128, 3, 0, 228, 128,
+ 1, 0, 0, 2, 0, 0,
+ 8, 128, 11, 0, 85, 160,
+ 38, 0, 0, 1, 0, 0,
+ 228, 240, 2, 0, 0, 3,
+ 1, 0, 8, 128, 0, 0,
+ 255, 128, 16, 0, 0, 160,
+ 5, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 11, 0, 0, 160, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 1, 0, 255, 128, 8, 0,
+ 0, 4, 1, 0, 8, 128,
+ 0, 0, 228, 128, 19, 32,
+ 228, 161, 0, 0, 0, 176,
+ 11, 0, 0, 3, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 11, 0, 85, 160, 5, 0,
+ 0, 4, 5, 0, 7, 128,
+ 1, 0, 255, 128, 17, 32,
+ 228, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 4, 0,
+ 7, 128, 5, 0, 228, 128,
+ 13, 0, 170, 160, 4, 0,
+ 228, 128, 2, 0, 0, 3,
+ 0, 0, 8, 128, 0, 0,
+ 255, 128, 11, 0, 170, 160,
+ 39, 0, 0, 0, 1, 0,
+ 0, 2, 3, 0, 7, 128,
+ 4, 0, 228, 128, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 11, 0, 85, 160, 38, 0,
+ 0, 1, 1, 0, 228, 240,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 0, 0, 255, 128,
+ 16, 0, 85, 160, 5, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 11, 0,
+ 0, 160, 46, 0, 0, 2,
+ 0, 0, 1, 176, 1, 0,
+ 255, 128, 2, 0, 0, 4,
+ 5, 0, 7, 128, 1, 0,
+ 228, 128, 18, 32, 228, 161,
+ 0, 0, 0, 176, 8, 0,
+ 0, 3, 1, 0, 8, 128,
+ 5, 0, 228, 128, 5, 0,
+ 228, 128, 7, 0, 0, 2,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 5, 0, 0, 3,
+ 5, 0, 7, 128, 1, 0,
+ 255, 128, 5, 0, 228, 128,
+ 8, 0, 0, 3, 2, 0,
+ 8, 128, 0, 0, 228, 128,
+ 5, 0, 228, 129, 11, 0,
+ 0, 3, 2, 0, 8, 128,
+ 2, 0, 255, 128, 11, 0,
+ 85, 160, 5, 0, 0, 4,
+ 5, 0, 7, 128, 2, 0,
+ 255, 128, 17, 32, 228, 160,
+ 0, 0, 0, 176, 6, 0,
+ 0, 2, 1, 0, 8, 128,
+ 1, 0, 255, 128, 6, 0,
+ 0, 3, 2, 0, 8, 128,
+ 17, 32, 255, 160, 0, 0,
+ 0, 176, 4, 0, 0, 4,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 2, 0, 255, 129,
+ 11, 0, 170, 160, 11, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 11, 0,
+ 85, 160, 5, 0, 0, 3,
+ 5, 0, 7, 128, 1, 0,
+ 255, 128, 5, 0, 228, 128,
+ 4, 0, 0, 4, 3, 0,
+ 7, 128, 5, 0, 228, 128,
+ 13, 0, 170, 160, 3, 0,
+ 228, 128, 2, 0, 0, 3,
+ 0, 0, 8, 128, 0, 0,
+ 255, 128, 11, 0, 170, 160,
+ 39, 0, 0, 0, 1, 0,
+ 0, 2, 4, 0, 7, 128,
+ 3, 0, 228, 128, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 11, 0, 85, 160, 38, 0,
+ 0, 1, 2, 0, 228, 240,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 0, 0, 255, 128,
+ 16, 0, 170, 160, 5, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 11, 0,
+ 0, 160, 46, 0, 0, 2,
+ 0, 0, 1, 176, 1, 0,
+ 255, 128, 2, 0, 0, 4,
+ 5, 0, 7, 128, 1, 0,
+ 228, 128, 18, 32, 228, 161,
+ 0, 0, 0, 176, 8, 0,
+ 0, 3, 1, 0, 8, 128,
+ 5, 0, 228, 128, 5, 0,
+ 228, 128, 7, 0, 0, 2,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 5, 0, 0, 3,
+ 5, 0, 7, 128, 1, 0,
+ 255, 128, 5, 0, 228, 128,
+ 8, 0, 0, 3, 2, 0,
+ 8, 128, 0, 0, 228, 128,
+ 5, 0, 228, 129, 8, 0,
+ 0, 4, 3, 0, 8, 128,
+ 5, 0, 228, 128, 19, 32,
+ 228, 160, 0, 0, 0, 176,
+ 11, 0, 0, 3, 2, 0,
+ 8, 128, 2, 0, 255, 128,
+ 11, 0, 85, 160, 2, 0,
+ 0, 4, 3, 0, 8, 128,
+ 3, 0, 255, 128, 18, 32,
+ 255, 160, 0, 0, 0, 176,
+ 1, 0, 0, 2, 5, 0,
+ 4, 128, 11, 0, 170, 160,
+ 2, 0, 0, 4, 5, 0,
+ 1, 128, 5, 0, 170, 128,
+ 18, 32, 255, 160, 0, 0,
+ 0, 176, 6, 0, 0, 2,
+ 5, 0, 1, 128, 5, 0,
+ 0, 128, 5, 0, 0, 3,
+ 3, 0, 8, 128, 3, 0,
+ 255, 128, 5, 0, 0, 128,
+ 12, 0, 0, 3, 5, 0,
+ 1, 128, 3, 0, 255, 128,
+ 11, 0, 85, 160, 4, 0,
+ 0, 4, 2, 0, 8, 128,
+ 5, 0, 0, 128, 2, 0,
+ 255, 129, 2, 0, 255, 128,
+ 11, 0, 0, 4, 3, 0,
+ 8, 128, 3, 0, 255, 128,
+ 19, 32, 255, 160, 0, 0,
+ 0, 176, 5, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 3, 0, 255, 128,
+ 5, 0, 0, 4, 5, 0,
+ 7, 128, 2, 0, 255, 128,
+ 17, 32, 228, 160, 0, 0,
+ 0, 176, 6, 0, 0, 2,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 6, 0, 0, 3,
+ 2, 0, 8, 128, 17, 32,
+ 255, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 1, 0,
+ 8, 128, 1, 0, 255, 128,
+ 2, 0, 255, 129, 11, 0,
+ 170, 160, 11, 0, 0, 3,
+ 1, 0, 8, 128, 1, 0,
+ 255, 128, 11, 0, 85, 160,
+ 5, 0, 0, 3, 5, 0,
+ 7, 128, 1, 0, 255, 128,
+ 5, 0, 228, 128, 4, 0,
+ 0, 4, 4, 0, 7, 128,
+ 5, 0, 228, 128, 13, 0,
+ 170, 160, 4, 0, 228, 128,
+ 2, 0, 0, 3, 0, 0,
+ 8, 128, 0, 0, 255, 128,
+ 11, 0, 170, 160, 39, 0,
+ 0, 0, 1, 0, 0, 2,
+ 4, 0, 8, 128, 3, 0,
+ 255, 144, 11, 0, 0, 3,
+ 0, 0, 15, 128, 4, 0,
+ 228, 128, 11, 0, 85, 160,
+ 10, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 11, 0, 170, 160, 5, 0,
+ 0, 3, 0, 0, 15, 208,
+ 0, 0, 228, 128, 12, 0,
+ 228, 160, 5, 0, 0, 3,
+ 0, 0, 15, 128, 2, 0,
+ 85, 128, 1, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 0, 0, 228, 160,
+ 2, 0, 0, 128, 0, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 15, 128, 2, 0,
+ 228, 160, 2, 0, 170, 128,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 3, 0,
+ 228, 160, 1, 0, 0, 2,
+ 0, 0, 15, 192, 0, 0,
+ 228, 128, 2, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 255, 128, 14, 0, 85, 161,
+ 5, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 170, 160, 11, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 0, 128, 14, 0,
+ 255, 160, 10, 0, 0, 3,
+ 0, 0, 4, 224, 0, 0,
+ 0, 128, 11, 0, 170, 160,
+ 1, 0, 0, 2, 0, 0,
+ 3, 224, 2, 0, 228, 144,
+ 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/skin_amb_VS.h b/src/d3d/shaders/skin_amb_VS.h
new file mode 100644
index 0000000..e0a5548
--- /dev/null
+++ b/src/d3d/shaders/skin_amb_VS.h
@@ -0,0 +1,253 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /Fh skin_amb_VS.h skin_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x3 boneMatrices[64];
+// float4x4 combinedMat;
+// float4 fogData;
+// float4 matCol;
+// float4 surfProps;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// combinedMat c0 4
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// boneMatrices c41 192
+//
+
+ vs_2_0
+ def c4, 3, 0, 1, 0
+ dcl_position v0
+ dcl_texcoord v1
+ dcl_color v2
+ dcl_blendweight v3
+ dcl_blendindices v4
+ mov r0.xyz, c15
+ mad r0.xyz, r0, c13.x, v2
+ mov r0.w, v2.w
+ max r0, r0, c4.y
+ min r0, r0, c4.z
+ mul oD0, r0, c12
+ mul r0, v4, c4.x
+ mova a0.x, r0.y
+ dp4 r1.x, v0, c41[a0.x]
+ dp4 r1.y, v0, c42[a0.x]
+ dp4 r1.z, v0, c43[a0.x]
+ mul r1.xyz, r1, v3.y
+ mova a0.x, r0.x
+ dp4 r2.x, v0, c41[a0.x]
+ dp4 r2.y, v0, c42[a0.x]
+ dp4 r2.z, v0, c43[a0.x]
+ mad r1.xyz, r2, v3.x, r1
+ mova a0.xy, r0.zwzw
+ dp4 r0.x, v0, c41[a0.x]
+ dp4 r0.y, v0, c42[a0.x]
+ dp4 r0.z, v0, c43[a0.x]
+ mad r0.xyz, r0, v3.z, r1
+ dp4 r1.x, v0, c41[a0.y]
+ dp4 r1.y, v0, c42[a0.y]
+ dp4 r1.z, v0, c43[a0.y]
+ mad r0.xyz, r1, v3.w, r0
+ mul r1, r0.y, c1
+ mad r1, c0, r0.x, r1
+ mad r0, c2, r0.z, r1
+ add r0, r0, c3
+ add r1.x, r0.w, -c14.y
+ mov oPos, r0
+ mul r0.x, r1.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.z
+ mov oT0.xy, v1
+
+// approximately 36 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 82, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 16, 1,
+ 0, 0, 0, 2, 254, 255,
+ 6, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 9, 1, 0, 0, 148, 0,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 164, 0,
+ 0, 0, 0, 0, 0, 0,
+ 180, 0, 0, 0, 2, 0,
+ 41, 0, 192, 0, 166, 0,
+ 196, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 224, 0, 0, 0,
+ 0, 0, 0, 0, 240, 0,
+ 0, 0, 2, 0, 14, 0,
+ 1, 0, 58, 0, 164, 0,
+ 0, 0, 0, 0, 0, 0,
+ 248, 0, 0, 0, 2, 0,
+ 12, 0, 1, 0, 50, 0,
+ 164, 0, 0, 0, 0, 0,
+ 0, 0, 255, 0, 0, 0,
+ 2, 0, 13, 0, 1, 0,
+ 54, 0, 164, 0, 0, 0,
+ 0, 0, 0, 0, 97, 109,
+ 98, 105, 101, 110, 116, 76,
+ 105, 103, 104, 116, 0, 171,
+ 171, 171, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 98, 111, 110, 101, 77, 97,
+ 116, 114, 105, 99, 101, 115,
+ 0, 171, 171, 171, 3, 0,
+ 3, 0, 4, 0, 3, 0,
+ 64, 0, 0, 0, 0, 0,
+ 0, 0, 99, 111, 109, 98,
+ 105, 110, 101, 100, 77, 97,
+ 116, 0, 3, 0, 3, 0,
+ 4, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 68, 97, 116,
+ 97, 0, 109, 97, 116, 67,
+ 111, 108, 0, 115, 117, 114,
+ 102, 80, 114, 111, 112, 115,
+ 0, 118, 115, 95, 50, 95,
+ 48, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 57, 46, 50, 57, 46,
+ 57, 53, 50, 46, 51, 49,
+ 49, 49, 0, 171, 171, 171,
+ 81, 0, 0, 5, 4, 0,
+ 15, 160, 0, 0, 64, 64,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 31, 0, 0, 2, 5, 0,
+ 0, 128, 1, 0, 15, 144,
+ 31, 0, 0, 2, 10, 0,
+ 0, 128, 2, 0, 15, 144,
+ 31, 0, 0, 2, 1, 0,
+ 0, 128, 3, 0, 15, 144,
+ 31, 0, 0, 2, 2, 0,
+ 0, 128, 4, 0, 15, 144,
+ 1, 0, 0, 2, 0, 0,
+ 7, 128, 15, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 13, 0, 0, 160, 2, 0,
+ 228, 144, 1, 0, 0, 2,
+ 0, 0, 8, 128, 2, 0,
+ 255, 144, 11, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 4, 0, 85, 160,
+ 10, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 4, 0, 170, 160, 5, 0,
+ 0, 3, 0, 0, 15, 208,
+ 0, 0, 228, 128, 12, 0,
+ 228, 160, 5, 0, 0, 3,
+ 0, 0, 15, 128, 4, 0,
+ 228, 144, 4, 0, 0, 160,
+ 46, 0, 0, 2, 0, 0,
+ 1, 176, 0, 0, 85, 128,
+ 9, 0, 0, 4, 1, 0,
+ 1, 128, 0, 0, 228, 144,
+ 41, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 1, 0, 2, 128, 0, 0,
+ 228, 144, 42, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 1, 0, 4, 128,
+ 0, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 0, 176,
+ 5, 0, 0, 3, 1, 0,
+ 7, 128, 1, 0, 228, 128,
+ 3, 0, 85, 144, 46, 0,
+ 0, 2, 0, 0, 1, 176,
+ 0, 0, 0, 128, 9, 0,
+ 0, 4, 2, 0, 1, 128,
+ 0, 0, 228, 144, 41, 32,
+ 228, 160, 0, 0, 0, 176,
+ 9, 0, 0, 4, 2, 0,
+ 2, 128, 0, 0, 228, 144,
+ 42, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 2, 0, 4, 128, 0, 0,
+ 228, 144, 43, 32, 228, 160,
+ 0, 0, 0, 176, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 2, 0, 228, 128, 3, 0,
+ 0, 144, 1, 0, 228, 128,
+ 46, 0, 0, 2, 0, 0,
+ 3, 176, 0, 0, 238, 128,
+ 9, 0, 0, 4, 0, 0,
+ 1, 128, 0, 0, 228, 144,
+ 41, 32, 228, 160, 0, 0,
+ 0, 176, 9, 0, 0, 4,
+ 0, 0, 2, 128, 0, 0,
+ 228, 144, 42, 32, 228, 160,
+ 0, 0, 0, 176, 9, 0,
+ 0, 4, 0, 0, 4, 128,
+ 0, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 0, 176,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 3, 0, 170, 144, 1, 0,
+ 228, 128, 9, 0, 0, 4,
+ 1, 0, 1, 128, 0, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 85, 176, 9, 0,
+ 0, 4, 1, 0, 2, 128,
+ 0, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 85, 176,
+ 9, 0, 0, 4, 1, 0,
+ 4, 128, 0, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 85, 176, 4, 0, 0, 4,
+ 0, 0, 7, 128, 1, 0,
+ 228, 128, 3, 0, 255, 144,
+ 0, 0, 228, 128, 5, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 85, 128, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 128,
+ 1, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 2, 0, 228, 160, 0, 0,
+ 170, 128, 1, 0, 228, 128,
+ 2, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 3, 0, 228, 160, 2, 0,
+ 0, 3, 1, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 1, 0, 0, 2,
+ 0, 0, 15, 192, 0, 0,
+ 228, 128, 5, 0, 0, 3,
+ 0, 0, 1, 128, 1, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 4, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 1, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/skin_amb_dir_VS.h b/src/d3d/shaders/skin_amb_dir_VS.h
new file mode 100644
index 0000000..7949749
--- /dev/null
+++ b/src/d3d/shaders/skin_amb_dir_VS.h
@@ -0,0 +1,503 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /T vs_2_0 /DDIRECTIONALS /Fh skin_amb_dir_VS.h skin_VS.hlsl
+//
+//
+// Parameters:
+//
+// float4 ambientLight;
+// float4x3 boneMatrices[64];
+// float4x4 combinedMat;
+// int4 firstLight;
+// float4 fogData;
+//
+// struct
+// {
+// float4 color;
+// float4 position;
+// float4 direction;
+//
+// } lights[8];
+//
+// float4 matCol;
+// float3x3 normalMat;
+// int numDirLights;
+// float4 surfProps;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// numDirLights i0 1
+// combinedMat c0 4
+// normalMat c8 3
+// matCol c12 1
+// surfProps c13 1
+// fogData c14 1
+// ambientLight c15 1
+// firstLight c16 1
+// lights c17 24
+// boneMatrices c41 192
+//
+
+ vs_2_0
+ def c4, 3, 0, 1, 0
+ dcl_position v0
+ dcl_normal v1
+ dcl_texcoord v2
+ dcl_color v3
+ dcl_blendweight v4
+ dcl_blendindices v5
+ mul r0, v5, c4.x
+ mova a0.w, r0.x
+ dp3 r1.z, v1, c43[a0.w]
+ mova a0.w, r0.x
+ dp3 r1.x, v1, c41[a0.w]
+ mova a0.w, r0.x
+ dp3 r1.y, v1, c42[a0.w]
+ mova a0.w, r0.y
+ dp3 r2.z, v1, c43[a0.w]
+ mova a0.w, r0.y
+ dp3 r2.x, v1, c41[a0.w]
+ mova a0.w, r0.y
+ dp3 r2.y, v1, c42[a0.w]
+ mul r2.xyz, r2, v4.y
+ mad r1.xyz, r1, v4.x, r2
+ mova a0.w, r0.z
+ dp3 r2.z, v1, c43[a0.w]
+ mova a0.w, r0.z
+ dp3 r2.x, v1, c41[a0.w]
+ mova a0.w, r0.z
+ dp3 r2.y, v1, c42[a0.w]
+ mad r1.xyz, r2, v4.z, r1
+ mova a0.w, r0.w
+ dp3 r2.z, v1, c43[a0.w]
+ mova a0.w, r0.w
+ dp3 r2.x, v1, c41[a0.w]
+ mova a0.w, r0.w
+ dp3 r2.y, v1, c42[a0.w]
+ mad r1.xyz, r2, v4.w, r1
+ mul r2.xyz, r1.y, c9
+ mad r1.xyw, c8.xyzz, r1.x, r2.xyzz
+ mad r1.xyz, c10, r1.z, r1.xyww
+ mov r2.x, c13.x
+ mad r2.xyz, c15, r2.x, v3
+ mov r3.xyz, r2
+ mov r1.w, c4.y
+ rep i0
+ add r2.w, r1.w, c16.x
+ mul r2.w, r2.w, c4.x
+ mova a0.w, r2.w
+ dp3 r4.x, r1, -c19[a0.w]
+ max r4.x, r4.x, c4.y
+ mova a0.w, r2.w
+ mul r4.xyz, r4.x, c17[a0.w]
+ mad r3.xyz, r4, c13.z, r3
+ add r1.w, r1.w, c4.z
+ endrep
+ mov r3.w, v3.w
+ max r1, r3, c4.y
+ min r1, r1, c4.z
+ mul oD0, r1, c12
+ mova a0.w, r0.y
+ dp4 r1.x, v0, c41[a0.w]
+ mova a0.w, r0.y
+ dp4 r1.y, v0, c42[a0.w]
+ mova a0.w, r0.y
+ dp4 r1.z, v0, c43[a0.w]
+ mul r1.xyz, r1, v4.y
+ mova a0.w, r0.x
+ dp4 r2.x, v0, c41[a0.w]
+ mova a0.w, r0.x
+ dp4 r2.y, v0, c42[a0.w]
+ mova a0.w, r0.x
+ dp4 r2.z, v0, c43[a0.w]
+ mad r1.xyz, r2, v4.x, r1
+ mova a0.w, r0.z
+ dp4 r2.x, v0, c41[a0.w]
+ mova a0.w, r0.z
+ dp4 r2.y, v0, c42[a0.w]
+ mova a0.w, r0.z
+ dp4 r2.z, v0, c43[a0.w]
+ mad r0.xyz, r2, v4.z, r1
+ mova a0.w, r0.w
+ dp4 r1.x, v0, c41[a0.w]
+ mova a0.w, r0.w
+ dp4 r1.y, v0, c42[a0.w]
+ mova a0.w, r0.w
+ dp4 r1.z, v0, c43[a0.w]
+ mad r0.xyz, r1, v4.w, r0
+ mul r1, r0.y, c1
+ mad r1, c0, r0.x, r1
+ mad r0, c2, r0.z, r1
+ add r0, r0, c3
+ mov oPos, r0
+ add r0.x, r0.w, -c14.y
+ mul r0.x, r0.x, c14.z
+ max r0.x, r0.x, c14.w
+ min oT0.z, r0.x, c4.z
+ mov oT0.xy, v2
+
+// approximately 92 instruction slots used
+#endif
+
+const BYTE g_vs20_main[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 147, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 21, 2,
+ 0, 0, 0, 2, 254, 255,
+ 10, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 14, 2, 0, 0, 228, 0,
+ 0, 0, 2, 0, 15, 0,
+ 1, 0, 62, 0, 244, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 1, 0, 0, 2, 0,
+ 41, 0, 192, 0, 166, 0,
+ 20, 1, 0, 0, 0, 0,
+ 0, 0, 36, 1, 0, 0,
+ 2, 0, 0, 0, 4, 0,
+ 2, 0, 48, 1, 0, 0,
+ 0, 0, 0, 0, 64, 1,
+ 0, 0, 2, 0, 16, 0,
+ 1, 0, 66, 0, 76, 1,
+ 0, 0, 0, 0, 0, 0,
+ 92, 1, 0, 0, 2, 0,
+ 14, 0, 1, 0, 58, 0,
+ 244, 0, 0, 0, 0, 0,
+ 0, 0, 100, 1, 0, 0,
+ 2, 0, 17, 0, 24, 0,
+ 70, 0, 176, 1, 0, 0,
+ 0, 0, 0, 0, 192, 1,
+ 0, 0, 2, 0, 12, 0,
+ 1, 0, 50, 0, 244, 0,
+ 0, 0, 0, 0, 0, 0,
+ 199, 1, 0, 0, 2, 0,
+ 8, 0, 3, 0, 34, 0,
+ 212, 1, 0, 0, 0, 0,
+ 0, 0, 228, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 2, 0, 244, 1, 0, 0,
+ 0, 0, 0, 0, 4, 2,
+ 0, 0, 2, 0, 13, 0,
+ 1, 0, 54, 0, 244, 0,
+ 0, 0, 0, 0, 0, 0,
+ 97, 109, 98, 105, 101, 110,
+ 116, 76, 105, 103, 104, 116,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 98, 111, 110, 101,
+ 77, 97, 116, 114, 105, 99,
+ 101, 115, 0, 171, 171, 171,
+ 3, 0, 3, 0, 4, 0,
+ 3, 0, 64, 0, 0, 0,
+ 0, 0, 0, 0, 99, 111,
+ 109, 98, 105, 110, 101, 100,
+ 77, 97, 116, 0, 3, 0,
+ 3, 0, 4, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 102, 105, 114, 115,
+ 116, 76, 105, 103, 104, 116,
+ 0, 171, 1, 0, 2, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 111, 103, 68, 97, 116,
+ 97, 0, 108, 105, 103, 104,
+ 116, 115, 0, 99, 111, 108,
+ 111, 114, 0, 171, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 111,
+ 115, 105, 116, 105, 111, 110,
+ 0, 100, 105, 114, 101, 99,
+ 116, 105, 111, 110, 0, 171,
+ 107, 1, 0, 0, 116, 1,
+ 0, 0, 132, 1, 0, 0,
+ 116, 1, 0, 0, 141, 1,
+ 0, 0, 116, 1, 0, 0,
+ 5, 0, 0, 0, 1, 0,
+ 12, 0, 8, 0, 3, 0,
+ 152, 1, 0, 0, 109, 97,
+ 116, 67, 111, 108, 0, 110,
+ 111, 114, 109, 97, 108, 77,
+ 97, 116, 0, 171, 171, 171,
+ 3, 0, 3, 0, 3, 0,
+ 3, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 110, 117,
+ 109, 68, 105, 114, 76, 105,
+ 103, 104, 116, 115, 0, 171,
+ 171, 171, 0, 0, 2, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 117, 114, 102, 80, 114,
+ 111, 112, 115, 0, 118, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 171, 171, 81, 0, 0, 5,
+ 4, 0, 15, 160, 0, 0,
+ 64, 64, 0, 0, 0, 0,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 31, 0, 0, 2,
+ 3, 0, 0, 128, 1, 0,
+ 15, 144, 31, 0, 0, 2,
+ 5, 0, 0, 128, 2, 0,
+ 15, 144, 31, 0, 0, 2,
+ 10, 0, 0, 128, 3, 0,
+ 15, 144, 31, 0, 0, 2,
+ 1, 0, 0, 128, 4, 0,
+ 15, 144, 31, 0, 0, 2,
+ 2, 0, 0, 128, 5, 0,
+ 15, 144, 5, 0, 0, 3,
+ 0, 0, 15, 128, 5, 0,
+ 228, 144, 4, 0, 0, 160,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 0, 128,
+ 8, 0, 0, 4, 1, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 0, 128, 8, 0, 0, 4,
+ 1, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 0, 128, 8, 0,
+ 0, 4, 1, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 255, 176,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 85, 128,
+ 8, 0, 0, 4, 2, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 85, 128, 8, 0, 0, 4,
+ 2, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 85, 128, 8, 0,
+ 0, 4, 2, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 255, 176,
+ 5, 0, 0, 3, 2, 0,
+ 7, 128, 2, 0, 228, 128,
+ 4, 0, 85, 144, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 1, 0, 228, 128, 4, 0,
+ 0, 144, 2, 0, 228, 128,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 170, 128,
+ 8, 0, 0, 4, 2, 0,
+ 4, 128, 1, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 170, 128, 8, 0, 0, 4,
+ 2, 0, 1, 128, 1, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 170, 128, 8, 0,
+ 0, 4, 2, 0, 2, 128,
+ 1, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 255, 176,
+ 4, 0, 0, 4, 1, 0,
+ 7, 128, 2, 0, 228, 128,
+ 4, 0, 170, 144, 1, 0,
+ 228, 128, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 255, 128, 8, 0, 0, 4,
+ 2, 0, 4, 128, 1, 0,
+ 228, 144, 43, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 255, 128, 8, 0,
+ 0, 4, 2, 0, 1, 128,
+ 1, 0, 228, 144, 41, 32,
+ 228, 160, 0, 0, 255, 176,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 255, 128,
+ 8, 0, 0, 4, 2, 0,
+ 2, 128, 1, 0, 228, 144,
+ 42, 32, 228, 160, 0, 0,
+ 255, 176, 4, 0, 0, 4,
+ 1, 0, 7, 128, 2, 0,
+ 228, 128, 4, 0, 255, 144,
+ 1, 0, 228, 128, 5, 0,
+ 0, 3, 2, 0, 7, 128,
+ 1, 0, 85, 128, 9, 0,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 11, 128, 8, 0,
+ 164, 160, 1, 0, 0, 128,
+ 2, 0, 164, 128, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 10, 0, 228, 160, 1, 0,
+ 170, 128, 1, 0, 244, 128,
+ 1, 0, 0, 2, 2, 0,
+ 1, 128, 13, 0, 0, 160,
+ 4, 0, 0, 4, 2, 0,
+ 7, 128, 15, 0, 228, 160,
+ 2, 0, 0, 128, 3, 0,
+ 228, 144, 1, 0, 0, 2,
+ 3, 0, 7, 128, 2, 0,
+ 228, 128, 1, 0, 0, 2,
+ 1, 0, 8, 128, 4, 0,
+ 85, 160, 38, 0, 0, 1,
+ 0, 0, 228, 240, 2, 0,
+ 0, 3, 2, 0, 8, 128,
+ 1, 0, 255, 128, 16, 0,
+ 0, 160, 5, 0, 0, 3,
+ 2, 0, 8, 128, 2, 0,
+ 255, 128, 4, 0, 0, 160,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 2, 0, 255, 128,
+ 8, 0, 0, 4, 4, 0,
+ 1, 128, 1, 0, 228, 128,
+ 19, 32, 228, 161, 0, 0,
+ 255, 176, 11, 0, 0, 3,
+ 4, 0, 1, 128, 4, 0,
+ 0, 128, 4, 0, 85, 160,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 2, 0, 255, 128,
+ 5, 0, 0, 4, 4, 0,
+ 7, 128, 4, 0, 0, 128,
+ 17, 32, 228, 160, 0, 0,
+ 255, 176, 4, 0, 0, 4,
+ 3, 0, 7, 128, 4, 0,
+ 228, 128, 13, 0, 170, 160,
+ 3, 0, 228, 128, 2, 0,
+ 0, 3, 1, 0, 8, 128,
+ 1, 0, 255, 128, 4, 0,
+ 170, 160, 39, 0, 0, 0,
+ 1, 0, 0, 2, 3, 0,
+ 8, 128, 3, 0, 255, 144,
+ 11, 0, 0, 3, 1, 0,
+ 15, 128, 3, 0, 228, 128,
+ 4, 0, 85, 160, 10, 0,
+ 0, 3, 1, 0, 15, 128,
+ 1, 0, 228, 128, 4, 0,
+ 170, 160, 5, 0, 0, 3,
+ 0, 0, 15, 208, 1, 0,
+ 228, 128, 12, 0, 228, 160,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 85, 128,
+ 9, 0, 0, 4, 1, 0,
+ 1, 128, 0, 0, 228, 144,
+ 41, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 85, 128, 9, 0, 0, 4,
+ 1, 0, 2, 128, 0, 0,
+ 228, 144, 42, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 85, 128, 9, 0,
+ 0, 4, 1, 0, 4, 128,
+ 0, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 255, 176,
+ 5, 0, 0, 3, 1, 0,
+ 7, 128, 1, 0, 228, 128,
+ 4, 0, 85, 144, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 0, 128, 9, 0,
+ 0, 4, 2, 0, 1, 128,
+ 0, 0, 228, 144, 41, 32,
+ 228, 160, 0, 0, 255, 176,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 0, 128,
+ 9, 0, 0, 4, 2, 0,
+ 2, 128, 0, 0, 228, 144,
+ 42, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 0, 128, 9, 0, 0, 4,
+ 2, 0, 4, 128, 0, 0,
+ 228, 144, 43, 32, 228, 160,
+ 0, 0, 255, 176, 4, 0,
+ 0, 4, 1, 0, 7, 128,
+ 2, 0, 228, 128, 4, 0,
+ 0, 144, 1, 0, 228, 128,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 170, 128,
+ 9, 0, 0, 4, 2, 0,
+ 1, 128, 0, 0, 228, 144,
+ 41, 32, 228, 160, 0, 0,
+ 255, 176, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 170, 128, 9, 0, 0, 4,
+ 2, 0, 2, 128, 0, 0,
+ 228, 144, 42, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 170, 128, 9, 0,
+ 0, 4, 2, 0, 4, 128,
+ 0, 0, 228, 144, 43, 32,
+ 228, 160, 0, 0, 255, 176,
+ 4, 0, 0, 4, 0, 0,
+ 7, 128, 2, 0, 228, 128,
+ 4, 0, 170, 144, 1, 0,
+ 228, 128, 46, 0, 0, 2,
+ 0, 0, 8, 176, 0, 0,
+ 255, 128, 9, 0, 0, 4,
+ 1, 0, 1, 128, 0, 0,
+ 228, 144, 41, 32, 228, 160,
+ 0, 0, 255, 176, 46, 0,
+ 0, 2, 0, 0, 8, 176,
+ 0, 0, 255, 128, 9, 0,
+ 0, 4, 1, 0, 2, 128,
+ 0, 0, 228, 144, 42, 32,
+ 228, 160, 0, 0, 255, 176,
+ 46, 0, 0, 2, 0, 0,
+ 8, 176, 0, 0, 255, 128,
+ 9, 0, 0, 4, 1, 0,
+ 4, 128, 0, 0, 228, 144,
+ 43, 32, 228, 160, 0, 0,
+ 255, 176, 4, 0, 0, 4,
+ 0, 0, 7, 128, 1, 0,
+ 228, 128, 4, 0, 255, 144,
+ 0, 0, 228, 128, 5, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 85, 128, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 128,
+ 1, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 2, 0, 228, 160, 0, 0,
+ 170, 128, 1, 0, 228, 128,
+ 2, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 3, 0, 228, 160, 1, 0,
+ 0, 2, 0, 0, 15, 192,
+ 0, 0, 228, 128, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 14, 0,
+ 85, 161, 5, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 0, 128, 14, 0, 170, 160,
+ 11, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 14, 0, 255, 160, 10, 0,
+ 0, 3, 0, 0, 4, 224,
+ 0, 0, 0, 128, 4, 0,
+ 170, 160, 1, 0, 0, 2,
+ 0, 0, 3, 224, 2, 0,
+ 228, 144, 255, 255, 0, 0
+};
diff --git a/src/d3d/shaders/standardConstants.h b/src/d3d/shaders/standardConstants.h
new file mode 100644
index 0000000..088df7d
--- /dev/null
+++ b/src/d3d/shaders/standardConstants.h
@@ -0,0 +1,28 @@
+float4x4 combinedMat : register(c0);
+float4x4 worldMat : register(c4);
+float3x3 normalMat : register(c8);
+float4 matCol : register(c12);
+float4 surfProps : register(c13);
+float4 fogData : register(c14);
+float4 ambientLight : register(c15);
+
+#define surfAmbient (surfProps.x)
+#define surfSpecular (surfProps.y)
+#define surfDiffuse (surfProps.z)
+
+#define fogStart (fogData.x)
+#define fogEnd (fogData.y)
+#define fogRange (fogData.z)
+#define fogDisable (fogData.w)
+
+#include "lighting.h"
+
+int numDirLights : register(i0);
+int numPointLights : register(i1);
+int numSpotLights : register(i2);
+int4 firstLight : register(c16);
+Light lights[8] : register(c17);
+
+#define firstDirLight (firstLight.x)
+#define firstPointLight (firstLight.y)
+#define firstSpotLight (firstLight.z)
diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp
new file mode 100644
index 0000000..62fab0c
--- /dev/null
+++ b/src/d3d/xbox.cpp
@@ -0,0 +1,1005 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwengine.h"
+#include "rwxbox.h"
+
+#include "rwxboximpl.h"
+
+#define PLUGIN_ID 2
+
+namespace rw {
+namespace xbox {
+
+static void*
+driverOpen(void *o, int32, int32)
+{
+ engine->driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline();
+
+ engine->driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset;
+ engine->driver[PLATFORM_XBOX]->rasterCreate = rasterCreate;
+ engine->driver[PLATFORM_XBOX]->rasterLock = rasterLock;
+ engine->driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock;
+ engine->driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels;
+ engine->driver[PLATFORM_XBOX]->rasterToImage = rasterToImage;
+
+ return o;
+}
+
+static void*
+driverClose(void *o, int32, int32)
+{
+ return o;
+}
+
+void
+registerPlatformPlugins(void)
+{
+ Driver::registerPlugin(PLATFORM_XBOX, 0, PLATFORM_XBOX,
+ driverOpen, driverClose);
+ registerNativeRaster();
+}
+
+void*
+destroyNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_XBOX)
+ return object;
+ InstanceDataHeader *header =
+ (InstanceDataHeader*)geometry->instData;
+ geometry->instData = nil;
+ rwFree(header->vertexBuffer);
+ rwFree(header->begin);
+ rwFree(header->data);
+ rwFree(header);
+ return object;
+}
+
+Stream*
+readNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ uint32 vers;
+ uint32 platform;
+ if(!findChunk(stream, ID_STRUCT, nil, &vers)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_XBOX){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ if(vers < 0x35000){
+ RWERROR((ERR_VERSION, vers));
+ return nil;
+ }
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ geometry->instData = header;
+ header->platform = PLATFORM_XBOX;
+
+ int32 size = stream->readI32();
+ // The 0x18 byte are the resentryheader.
+ // We don't have it but it's used for alignment.
+ header->data = rwNewT(uint8, size + 0x18, MEMDUR_EVENT | ID_GEOMETRY);
+ uint8 *p = header->data+0x18+4;
+ stream->read8(p, size-4);
+
+ header->size = size;
+ header->serialNumber = *(uint16*)p; p += 2;
+ header->numMeshes = *(uint16*)p; p += 2;
+ header->primType = *(uint32*)p; p += 4;
+ header->numVertices = *(uint32*)p; p += 4;
+ header->stride = *(uint32*)p; p += 4;
+ // RxXboxVertexFormat in 3.3 here
+ p += 4; // skip vertexBuffer pointer
+ header->vertexAlpha = *(bool32*)p; p += 4;
+ p += 8; // skip begin, end pointers
+
+ InstanceData *inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+ header->begin = inst;
+ for(int i = 0; i < header->numMeshes; i++){
+ inst->minVert = *(uint32*)p; p += 4;
+ inst->numVertices = *(int32*)p; p += 4;
+ inst->numIndices = *(int32*)p; p += 4;
+ inst->indexBuffer = header->data + *(uint32*)p; p += 4;
+ p += 8; // skip material and vertexShader
+ inst->vertexShader = 0;
+ // pixelShader in 3.3 here
+ inst++;
+ }
+ header->end = inst;
+
+ header->vertexBuffer = rwNewT(uint8, header->stride*header->numVertices, MEMDUR_EVENT | ID_GEOMETRY);
+ stream->read8(header->vertexBuffer, header->stride*header->numVertices);
+ return stream;
+}
+
+Stream*
+writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ writeChunkHeader(stream, ID_STRUCT, len-12);
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_XBOX)
+ return stream;
+ stream->writeU32(PLATFORM_XBOX);
+ assert(rw::version >= 0x35000 && "can't write native Xbox data < 0x35000");
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+
+ // we just fill header->data and write that
+ uint8 *p = header->data+0x18;
+ *(int32*)p = header->size; p += 4;
+ *(uint16*)p = header->serialNumber; p += 2;
+ *(uint16*)p = header->numMeshes; p += 2;
+ *(uint32*)p = header->primType; p += 4;
+ *(uint32*)p = header->numVertices; p += 4;
+ *(uint32*)p = header->stride; p += 4;
+ // RxXboxVertexFormat in 3.3 here
+ p += 4; // skip vertexBuffer pointer
+ *(bool32*)p = header->vertexAlpha; p += 4;
+ p += 8; // skip begin, end pointers
+
+ InstanceData *inst = header->begin;
+ for(int i = 0; i < header->numMeshes; i++){
+ *(uint32*)p = inst->minVert; p += 4;
+ *(int32*)p = inst->numVertices; p += 4;
+ *(int32*)p = inst->numIndices; p += 4;
+ *(uint32*)p = (uint8*)inst->indexBuffer - header->data; p += 4;
+ p += 8; // skip material and vertexShader
+ // pixelShader in 3.3 here
+ inst++;
+ }
+
+ stream->write8(header->data+0x18, header->size);
+ stream->write8(header->vertexBuffer, header->stride*header->numVertices);
+ return stream;
+}
+
+int32
+getSizeNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ if(geometry->instData == nil ||
+ geometry->instData->platform != PLATFORM_XBOX)
+ return 0;
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ return 12 + 4 + header->size + header->stride*header->numVertices;
+}
+
+void
+registerNativeDataPlugin(void)
+{
+ Geometry::registerPlugin(0, ID_NATIVEDATA,
+ nil, destroyNativeData, nil);
+ Geometry::registerPluginStream(ID_NATIVEDATA,
+ readNativeData,
+ writeNativeData,
+ getSizeNativeData);
+}
+
+enum {
+ D3DPT_TRIANGLELIST = 5,
+ D3DPT_TRIANGLESTRIP = 6
+};
+
+static void
+instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ // TODO: allow for REINSTANCE (or not, xbox can't render)
+ if(geo->instData)
+ return;
+ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
+ MeshHeader *meshh = geo->meshHeader;
+ geo->instData = header;
+ header->platform = PLATFORM_XBOX;
+
+ header->size = 0x24 + meshh->numMeshes*0x18 + 0x10;
+ Mesh *mesh = meshh->getMeshes();
+ for(uint32 i = 0; i < meshh->numMeshes; i++)
+ header->size += (mesh++->numIndices*2 + 0xF) & ~0xF;
+ // The 0x18 byte are the resentryheader.
+ // We don't have it but it's used for alignment.
+ header->data = rwNewT(uint8, header->size + 0x18, MEMDUR_EVENT | ID_GEOMETRY);
+ header->serialNumber = meshh->serialNum;
+ header->numMeshes = meshh->numMeshes;
+ header->primType = meshh->flags == MeshHeader::TRISTRIP ?
+ D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
+ header->numVertices = geo->numVertices;
+ header->vertexAlpha = 0;
+ // set by the instanceCB
+ header->stride = 0;
+ header->vertexBuffer = nil;
+
+ InstanceData *inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
+ header->begin = inst;
+ mesh = meshh->getMeshes();
+ uint8 *indexbuf = (uint8*)header->data + ((0x18 + 0x24 + header->numMeshes*0x18 + 0xF)&~0xF);
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
+ &inst->minVert, &inst->numVertices);
+ inst->numIndices = mesh->numIndices;
+ inst->indexBuffer = indexbuf;
+ memcpy(inst->indexBuffer, mesh->indices, inst->numIndices*sizeof(uint16));
+ indexbuf += (inst->numIndices*2 + 0xF) & ~0xF;
+ inst->material = mesh->material;
+ inst->vertexShader = 0; // TODO?
+ mesh++;
+ inst++;
+ }
+ header->end = inst;
+
+ pipe->instanceCB(geo, header);
+}
+
+static void
+uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
+{
+ ObjPipeline *pipe = (ObjPipeline*)rwpipe;
+ Geometry *geo = atomic->geometry;
+ if((geo->flags & Geometry::NATIVE) == 0)
+ return;
+ assert(geo->instData != nil);
+ assert(geo->instData->platform == PLATFORM_XBOX);
+
+ InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
+ InstanceData *inst = header->begin;
+ Mesh *mesh = geo->meshHeader->getMeshes();
+ // For some reason numIndices in mesh and instance data are not always equal
+ // And primitive isn't always correct either. Maybe some internal conversion...
+ geo->meshHeader->totalIndices = 0;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ mesh[i].numIndices = inst[i].numIndices;
+ geo->meshHeader->totalIndices += mesh[i].numIndices;
+ }
+ geo->meshHeader->flags = header->primType == D3DPT_TRIANGLESTRIP ?
+ MeshHeader::TRISTRIP : 0;
+
+ geo->numTriangles = geo->meshHeader->guessNumTriangles();
+ geo->allocateData();
+ geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0);
+
+ mesh = geo->meshHeader->getMeshes();
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ uint16 *indices = (uint16*)inst->indexBuffer;
+ memcpy(mesh->indices, indices, inst->numIndices*2);
+ mesh++;
+ inst++;
+ }
+
+ pipe->uninstanceCB(geo, header);
+ geo->generateTriangles();
+ geo->flags &= ~Geometry::NATIVE;
+ destroyNativeData(geo, 0, 0);
+}
+
+void
+ObjPipeline::init(void)
+{
+ this->rw::ObjPipeline::init(PLATFORM_XBOX);
+ this->impl.instance = xbox::instance;
+ this->impl.uninstance = xbox::uninstance;
+ this->instanceCB = nil;
+ this->uninstanceCB = nil;
+}
+
+ObjPipeline*
+ObjPipeline::create(void)
+{
+ ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
+ pipe->init();
+ return pipe;
+}
+
+int v3dFormatMap[] = {
+ -1, VERT_BYTE3, VERT_SHORT3, VERT_NORMSHORT3, VERT_COMPNORM, VERT_FLOAT3
+};
+
+int v2dFormatMap[] = {
+ -1, VERT_BYTE2, VERT_SHORT2, VERT_NORMSHORT2, VERT_COMPNORM, VERT_FLOAT2
+};
+
+void
+defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ uint32 *vertexFmt = getVertexFmt(geo);
+ if(*vertexFmt == 0)
+ *vertexFmt = makeVertexFmt(geo->flags, geo->numTexCoordSets);
+ header->stride = getVertexFmtStride(*vertexFmt);
+ header->vertexBuffer = rwNewT(uint8, header->stride*header->numVertices, MEMDUR_EVENT | ID_GEOMETRY);
+ uint8 *dst = (uint8*)header->vertexBuffer;
+
+ uint32 fmt = *vertexFmt;
+ uint32 sel = fmt & 0xF;
+ instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].vertices,
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+
+ sel = (fmt >> 4) & 0xF;
+ if(sel){
+ instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].normals,
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+ }
+
+ if(fmt & 0x1000000){
+ header->vertexAlpha = instColor(VERT_ARGB, dst, geo->colors,
+ header->numVertices, header->stride);
+ dst += 4;
+ }
+
+ for(int i = 0; i < 4; i++){
+ sel = (fmt >> (i*4 + 8)) & 0xF;
+ if(sel == 0)
+ break;
+ instTexCoords(v2dFormatMap[sel], dst, geo->texCoords[i],
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 2*vertexFormatSizes[sel];
+ }
+
+ if(fmt & 0xE000000)
+ assert(0 && "can't instance tangents or whatever it is");
+}
+
+void
+defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ uint32 *vertexFmt = getVertexFmt(geo);
+ uint32 fmt = *vertexFmt;
+ assert(fmt != 0);
+ uint8 *src = (uint8*)header->vertexBuffer;
+
+ uint32 sel = fmt & 0xF;
+ uninstV3d(v3dFormatMap[sel], geo->morphTargets[0].vertices, src,
+ header->numVertices, header->stride);
+ src += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+
+ sel = (fmt >> 4) & 0xF;
+ if(sel){
+ uninstV3d(v3dFormatMap[sel], geo->morphTargets[0].normals, src,
+ header->numVertices, header->stride);
+ src += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+ }
+
+ if(fmt & 0x1000000){
+ uninstColor(VERT_ARGB, geo->colors, src,
+ header->numVertices, header->stride);
+ src += 4;
+ }
+
+ for(int i = 0; i < 4; i++){
+ sel = (fmt >> (i*4 + 8)) & 0xF;
+ if(sel == 0)
+ break;
+ uninstTexCoords(v2dFormatMap[sel], geo->texCoords[i], src,
+ header->numVertices, header->stride);
+ src += sel == 4 ? 4 : 2*vertexFormatSizes[sel];
+ }
+}
+
+ObjPipeline*
+makeDefaultPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ return pipe;
+}
+
+// Native Texture and Raster
+
+int32 nativeRasterOffset;
+
+static uint32
+calculateTextureSize(uint32 width, uint32 height, uint32 depth, uint32 format)
+{
+#define D3DFMT_W11V11U10 65
+ switch(format){
+ default:
+ case D3DFMT_UNKNOWN:
+ return 0;
+ case D3DFMT_A8:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ case D3DFMT_AL8:
+ case D3DFMT_LIN_A8:
+ case D3DFMT_LIN_AL8:
+ case D3DFMT_LIN_L8:
+ return width * height * depth;
+ case D3DFMT_R5G6B5:
+ case D3DFMT_R6G5B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_R4G4B4A4:
+ case D3DFMT_R5G5B5A1:
+ case D3DFMT_R8B8:
+ case D3DFMT_G8B8:
+ case D3DFMT_A8L8:
+ case D3DFMT_L16:
+ //case D3DFMT_V8U8:
+ //case D3DFMT_L6V5U5:
+ case D3DFMT_D16_LOCKABLE:
+ //case D3DFMT_D16:
+ case D3DFMT_F16:
+ case D3DFMT_YUY2:
+ case D3DFMT_UYVY:
+ case D3DFMT_LIN_A1R5G5B5:
+ case D3DFMT_LIN_A4R4G4B4:
+ case D3DFMT_LIN_G8B8:
+ case D3DFMT_LIN_R4G4B4A4:
+ case D3DFMT_LIN_R5G5B5A1:
+ case D3DFMT_LIN_R5G6B5:
+ case D3DFMT_LIN_R6G5B5:
+ case D3DFMT_LIN_R8B8:
+ case D3DFMT_LIN_X1R5G5B5:
+ case D3DFMT_LIN_A8L8:
+ case D3DFMT_LIN_L16:
+ //case D3DFMT_LIN_V8U8:
+ //case D3DFMT_LIN_L6V5U5:
+ case D3DFMT_LIN_D16:
+ case D3DFMT_LIN_F16:
+ return width * 2 * height * depth;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8B8G8R8:
+ case D3DFMT_B8G8R8A8:
+ case D3DFMT_R8G8B8A8:
+ //case D3DFMT_X8L8V8U8:
+ //case D3DFMT_Q8W8V8U8:
+ case D3DFMT_V16U16:
+ case D3DFMT_D24S8:
+ case D3DFMT_F24S8:
+ case D3DFMT_LIN_A8B8G8R8:
+ case D3DFMT_LIN_A8R8G8B8:
+ case D3DFMT_LIN_B8G8R8A8:
+ case D3DFMT_LIN_R8G8B8A8:
+ case D3DFMT_LIN_X8R8G8B8:
+ case D3DFMT_LIN_V16U16:
+ //case D3DFMT_LIN_X8L8V8U8:
+ //case D3DFMT_LIN_Q8W8V8U8:
+ case D3DFMT_LIN_D24S8:
+ case D3DFMT_LIN_F24S8:
+ return width * 4 * height * depth;
+ case D3DFMT_DXT1:
+ assert(depth <= 1);
+ return ((width + 3) >> 2) * ((height + 3) >> 2) * 8;
+ //case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ //case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ assert(depth <= 1);
+ return ((width + 3) >> 2) * ((height + 3) >> 2) * 16;
+ }
+}
+
+static void*
+createTexture(int32 width, int32 height, int32 numlevels, uint32 format)
+{
+ int32 w = width;
+ int32 h = height;
+ int32 size = 0;
+ for(int32 i = 0; i < numlevels; i++){
+ size += calculateTextureSize(w, h, 1, format);
+ w /= 2;
+ if(w == 0) w = 1;
+ h /= 2;
+ if(h == 0) h = 1;
+ }
+ size = (size+3)&~3;
+ uint8 *data = (uint8*)rwNew(sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size,
+ MEMDUR_EVENT | ID_DRIVER);
+ RasterLevels *levels = (RasterLevels*)data;
+ data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1);
+ levels->numlevels = numlevels;
+ levels->format = format;
+ w = width;
+ h = height;
+ for(int32 i = 0; i < numlevels; i++){
+ levels->levels[i].width = w;
+ levels->levels[i].height = h;
+ levels->levels[i].data = data;
+ levels->levels[i].size = calculateTextureSize(w, h, 1, format);
+ data += levels->levels[i].size;
+ w /= 2;
+ if(w == 0) w = 1;
+ h /= 2;
+ if(h == 0) h = 1;
+ }
+ return levels;
+}
+
+struct RasterFormatInfo
+{
+ uint32 d3dformat;
+ int32 depth;
+ bool32 hasAlpha;
+ uint32 rwFormat;
+};
+
+// indexed directly by RW format
+static RasterFormatInfo formatInfoRW[16] = {
+ { 0, 0, 0, 0},
+ { D3DFMT_A1R5G5B5, 16, 1, Raster::C1555 },
+ { D3DFMT_R5G6B5, 16, 0, Raster::C565 },
+ { D3DFMT_A4R4G4B4, 16, 1, Raster::C4444 },
+ { D3DFMT_L8, 8, 0, Raster::LUM8 },
+ { D3DFMT_A8R8G8B8, 32, 1, Raster::C8888 },
+ { D3DFMT_X8R8G8B8, 32, 0, Raster::C888 },
+ { D3DFMT_UNKNOWN, 16, 0, Raster::D16 },
+ { D3DFMT_UNKNOWN, 32, 0, Raster::D24 },
+ { D3DFMT_UNKNOWN, 32, 0, Raster::D32 },
+ { D3DFMT_X1R5G5B5, 16, 0, Raster::C555 }
+};
+
+static void
+rasterSetFormat(Raster *raster)
+{
+ assert(raster->format != 0); // no default yet
+
+ XboxRaster *natras = GETXBOXRASTEREXT(raster);
+ if(raster->format & (Raster::PAL4 | Raster::PAL8)){
+ natras->format = D3DFMT_P8;
+ raster->depth = 8;
+ }else{
+ natras->format = formatInfoRW[(raster->format >> 8) & 0xF].d3dformat;
+ raster->depth = formatInfoRW[(raster->format >> 8) & 0xF].depth;
+ }
+ natras->bpp = raster->depth/8;
+ natras->hasAlpha = formatInfoRW[(raster->format >> 8) & 0xF].hasAlpha;
+ raster->stride = raster->width&natras->bpp;
+}
+
+static Raster*
+rasterCreateTexture(Raster *raster)
+{
+ XboxRaster *natras = GETXBOXRASTEREXT(raster);
+ int32 levels;
+
+ if(natras->format == D3DFMT_P8)
+ natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER);
+ levels = Raster::calculateNumLevels(raster->width, raster->height);
+ assert(natras->texture == nil);
+ natras->texture = createTexture(raster->width, raster->height,
+ raster->format & Raster::MIPMAP ? levels : 1,
+ natras->format);
+ if(natras->texture == nil){
+ RWERROR((ERR_NOTEXTURE));
+ return nil;
+ }
+ return raster;
+}
+
+Raster*
+rasterCreate(Raster *raster)
+{
+ rasterSetFormat(raster);
+
+ Raster *ret = raster;
+
+ // Dummy to use as subraster
+ if(raster->width == 0 || raster->height == 0){
+ raster->flags |= Raster::DONTALLOCATE;
+ raster->stride = 0;
+ goto ret;
+ }
+ if(raster->flags & Raster::DONTALLOCATE)
+ goto ret;
+
+ switch(raster->type){
+ case Raster::NORMAL:
+ case Raster::TEXTURE:
+ ret = rasterCreateTexture(raster);
+ break;
+ default:
+ RWERROR((ERR_INVRASTER));
+ return nil;
+ }
+
+ret:
+ raster->originalWidth = raster->width;
+ raster->originalHeight = raster->height;
+ raster->originalStride = raster->stride;
+ raster->originalPixels = raster->pixels;
+ return ret;
+}
+
+uint8*
+rasterLock(Raster *raster, int32 level, int32 lockMode)
+{
+ XboxRaster *natras = GETXBOXRASTEREXT(raster);
+
+ // check if already locked
+ if(raster->privateFlags & (Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE))
+ return nil;
+
+ RasterLevels *levels = (RasterLevels*)natras->texture;
+ raster->pixels = levels->levels[level].data;
+ raster->width = levels->levels[level].width;
+ raster->height = levels->levels[level].height;
+ raster->stride = raster->width*natras->bpp;
+
+ if(lockMode & Raster::LOCKREAD) raster->privateFlags |= Raster::PRIVATELOCK_READ;
+ if(lockMode & Raster::LOCKWRITE) raster->privateFlags |= Raster::PRIVATELOCK_WRITE;
+
+ return raster->pixels;
+}
+
+void
+rasterUnlock(Raster *raster, int32 level)
+{
+ raster->width = raster->originalWidth;
+ raster->height = raster->originalHeight;
+ raster->stride = raster->originalStride;
+ raster->pixels = raster->originalPixels;
+
+ raster->privateFlags &= ~(Raster::PRIVATELOCK_READ|Raster::PRIVATELOCK_WRITE);
+}
+
+int32
+rasterNumLevels(Raster *raster)
+{
+ XboxRaster *natras = GETXBOXRASTEREXT(raster);
+ RasterLevels *levels = (RasterLevels*)natras->texture;
+ return levels->numlevels;
+}
+
+static void
+unswizzle(uint8 *dst, uint8 *src, int32 w, int32 h, int32 bpp)
+{
+ uint32 maskU = 0;
+ uint32 maskV = 0;
+ int32 i = 1;
+ int32 j = 1;
+ int32 c;
+ do{
+ c = 0;
+ if(i < w){
+ maskU |= j;
+ j <<= 1;
+ c = j;
+ }
+ if(i < h){
+ maskV |= j;
+ j <<= 1;
+ c = j;
+ }
+ i <<= 1;
+ }while(c);
+ int32 x, y, u, v;
+ v = 0;
+ for(y = 0; y < h; y++){
+ u = 0;
+ for(x = 0; x < w; x++){
+ memcpy(&dst[(y*w + x)*bpp], &src[(u|v)*bpp], bpp);
+ u = (u - maskU) & maskU;
+ }
+ v = (v - maskV) & maskV;
+ }
+}
+
+Image*
+rasterToImage(Raster *raster)
+{
+ int32 depth;
+ Image *image;
+
+ bool unlock = false;
+ if(raster->pixels == nil){
+ raster->lock(0, Raster::LOCKREAD);
+ unlock = true;
+ }
+
+ XboxRaster *natras = GETXBOXRASTEREXT(raster);
+ if(natras->customFormat){
+ int w = raster->width;
+ int h = raster->height;
+ // pixels are in the upper right corner
+ if(w < 4) w = 4;
+ if(h < 4) h = 4;
+ image = Image::create(w, h, 32);
+ image->allocate();
+ uint8 *pix = raster->pixels;
+ switch(natras->format){
+ case D3DFMT_DXT1:
+ image->setPixelsDXT(1, pix);
+ // TODO: is this correct?
+ if(!natras->hasAlpha)
+ image->removeMask();
+ break;
+ case D3DFMT_DXT3:
+ image->setPixelsDXT(3, pix);
+ break;
+ case D3DFMT_DXT5:
+ image->setPixelsDXT(5, pix);
+ break;
+ default:
+ assert(0 && "unknown format");
+ image->destroy();
+ if(unlock)
+ raster->unlock(0);
+ return nil;
+ }
+ // fix it up again
+ image->width = raster->width;
+ image->height = raster->height;
+
+ if(unlock)
+ raster->unlock(0);
+ return image;
+ }
+
+ switch(raster->format & 0xF00){
+ case Raster::C1555:
+ depth = 16;
+ break;
+ case Raster::C8888:
+ depth = 32;
+ break;
+ case Raster::C888:
+ depth = 24;
+ break;
+ case Raster::C555:
+ depth = 16;
+ break;
+
+ default:
+ case Raster::C565:
+ case Raster::C4444:
+ case Raster::LUM8:
+ assert(0 && "unsupported raster format");
+ }
+ int32 pallength = 0;
+ if((raster->format & Raster::PAL4) == Raster::PAL4){
+ depth = 4;
+ pallength = 16;
+ }else if((raster->format & Raster::PAL8) == Raster::PAL8){
+ depth = 8;
+ pallength = 256;
+ }
+
+ image = Image::create(raster->width, raster->height, depth);
+ image->allocate();
+
+ if(pallength){
+ uint8 *out = image->palette;
+ uint8 *in = (uint8*)natras->palette;
+ // bytes are BGRA unlike regular d3d!
+ for(int32 i = 0; i < pallength; i++){
+ conv_BGRA8888_from_RGBA8888(out, in);
+ in += 4;
+ out += 4;
+ }
+ }
+
+ uint8 *imgpixels = image->pixels;
+ uint8 *pixels = raster->pixels;
+
+ // NB:
+ assert(image->bpp == (int)natras->bpp);
+ assert(image->stride == raster->stride);
+ unswizzle(imgpixels, pixels, image->width, image->height, image->bpp);
+ // Fix RGB order
+ uint8 tmp;
+ if(depth > 8)
+ for(int32 y = 0; y < image->height; y++){
+ uint8 *imgrow = imgpixels;
+ // uint8 *rasrow = pixels;
+ for(int32 x = 0; x < image->width; x++){
+ switch(raster->format & 0xF00){
+ case Raster::C8888:
+ case Raster::C888:
+ tmp = imgrow[0];
+ imgrow[0] = imgrow[2];
+ imgrow[2] = tmp;
+ imgrow += image->bpp;
+ break;
+ }
+ }
+ imgpixels += image->stride;
+ // pixels += raster->stride;
+ }
+ image->compressPalette();
+
+ if(unlock)
+ raster->unlock(0);
+
+ return image;
+}
+
+int32
+getLevelSize(Raster *raster, int32 level)
+{
+ XboxRaster *ras = GETXBOXRASTEREXT(raster);
+ RasterLevels *levels = (RasterLevels*)ras->texture;
+ return levels->levels[level].size;
+}
+
+static void*
+createNativeRaster(void *object, int32 offset, int32)
+{
+ XboxRaster *raster = PLUGINOFFSET(XboxRaster, object, offset);
+ raster->texture = nil;
+ raster->palette = nil;
+ raster->format = 0;
+ raster->hasAlpha = 0;
+ raster->customFormat = 0;
+ raster->unknownFlag = 0;
+ return object;
+}
+
+static void*
+destroyNativeRaster(void *object, int32, int32)
+{
+ // TODO:
+ return object;
+}
+
+static void*
+copyNativeRaster(void *dst, void *, int32 offset, int32)
+{
+ XboxRaster *raster = PLUGINOFFSET(XboxRaster, dst, offset);
+ raster->texture = nil;
+ raster->palette = nil;
+ raster->format = 0;
+ raster->hasAlpha = 0;
+ raster->unknownFlag = 0;
+ return dst;
+}
+
+void
+registerNativeRaster(void)
+{
+ nativeRasterOffset = Raster::registerPlugin(sizeof(XboxRaster),
+ ID_RASTERXBOX,
+ createNativeRaster,
+ destroyNativeRaster,
+ copyNativeRaster);
+}
+
+Texture*
+readNativeTexture(Stream *stream)
+{
+ uint32 vers, platform;
+ if(!findChunk(stream, ID_STRUCT, nil, &vers)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_XBOX){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ if(vers < 0x34001){
+ RWERROR((ERR_VERSION, vers));
+ return nil;
+ }
+ Texture *tex = Texture::create(nil);
+ if(tex == nil)
+ return nil;
+
+
+ // Texture
+ tex->filterAddressing = stream->readU32();
+ stream->read8(tex->name, 32);
+ stream->read8(tex->mask, 32);
+
+//if(strcmp(tex->name, "bluallu") == 0)
+//__debugbreak();
+
+ // Raster
+ int32 format = stream->readI32();
+ bool32 hasAlpha = stream->readI16();
+ bool32 unknownFlag = stream->readI16();
+ int32 width = stream->readU16();
+ int32 height = stream->readU16();
+ int32 depth = stream->readU8();
+ int32 numLevels = stream->readU8();
+ int32 type = stream->readU8();
+ int32 compression = stream->readU8();
+ int32 totalSize = stream->readI32();
+
+ // isn't this the cube map flag?
+ assert(unknownFlag == 0);
+ Raster *raster;
+ if(compression){
+ raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_XBOX);
+ XboxRaster *ras = GETXBOXRASTEREXT(raster);
+ ras->format = compression;
+ ras->hasAlpha = hasAlpha;
+ ras->texture = createTexture(raster->width, raster->height,
+ raster->format & Raster::MIPMAP ? numLevels : 1,
+ ras->format);
+ ras->customFormat = 1;
+ raster->flags &= ~Raster::DONTALLOCATE;
+ }else
+ raster = Raster::create(width, height, depth, format | type, PLATFORM_XBOX);
+ XboxRaster *ras = GETXBOXRASTEREXT(raster);
+ tex->raster = raster;
+
+ if(raster->format & Raster::PAL4)
+ stream->read8(ras->palette, 4*32);
+ else if(raster->format & Raster::PAL8)
+ stream->read8(ras->palette, 4*256);
+
+ // exploit the fact that mipmaps are allocated consecutively
+ uint8 *data = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
+ stream->read8(data, totalSize);
+ raster->unlock(0);
+
+ return tex;
+}
+
+void
+writeNativeTexture(Texture *tex, Stream *stream)
+{
+ int32 chunksize = getSizeNativeTexture(tex);
+ writeChunkHeader(stream, ID_STRUCT, chunksize-12);
+ stream->writeU32(PLATFORM_XBOX);
+
+ // Texture
+ stream->writeU32(tex->filterAddressing);
+ stream->write8(tex->name, 32);
+ stream->write8(tex->mask, 32);
+
+ // Raster
+ Raster *raster = tex->raster;
+ XboxRaster *ras = GETXBOXRASTEREXT(raster);
+ int32 numLevels = raster->getNumLevels();
+ stream->writeI32(raster->format);
+ stream->writeI16(ras->hasAlpha);
+ stream->writeI16(ras->unknownFlag);
+ stream->writeU16(raster->width);
+ stream->writeU16(raster->height);
+ stream->writeU8(raster->depth);
+ stream->writeU8(numLevels);
+ stream->writeU8(raster->type);
+ stream->writeU8(ras->format);
+
+ int32 totalSize = 0;
+ for(int32 i = 0; i < numLevels; i++)
+ totalSize += getLevelSize(tex->raster, i);
+ totalSize = (totalSize+3)&~3;
+ stream->writeI32(totalSize);
+
+ if(raster->format & Raster::PAL4)
+ stream->write8(ras->palette, 4*32);
+ else if(raster->format & Raster::PAL8)
+ stream->write8(ras->palette, 4*256);
+
+ // exploit the fact that mipmaps are allocated consecutively
+ uint8 *data = raster->lock(0, Raster::LOCKREAD);
+ stream->write8(data, totalSize);
+ raster->unlock(0);
+}
+
+uint32
+getSizeNativeTexture(Texture *tex)
+{
+ uint32 size = 12 + 72 + 16 + 4;
+ int32 levels = tex->raster->getNumLevels();
+ for(int32 i = 0; i < levels; i++)
+ size += getLevelSize(tex->raster, i);
+ size = (size+3)&~3;
+ if(tex->raster->format & Raster::PAL4)
+ size += 4*32;
+ else if(tex->raster->format & Raster::PAL8)
+ size += 4*256;
+ return size;
+}
+
+}
+}
diff --git a/src/d3d/xboxmatfx.cpp b/src/d3d/xboxmatfx.cpp
new file mode 100644
index 0000000..a6b8718
--- /dev/null
+++ b/src/d3d/xboxmatfx.cpp
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwxbox.h"
+
+namespace rw {
+namespace xbox {
+
+static void*
+matfxOpen(void *o, int32, int32)
+{
+ matFXGlobals.pipelines[PLATFORM_XBOX] = makeMatFXPipeline();
+ return o;
+}
+
+static void*
+matfxClose(void *o, int32, int32)
+{
+ ((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_XBOX])->destroy();
+ matFXGlobals.pipelines[PLATFORM_XBOX] = nil;
+ return o;
+}
+
+void
+initMatFX(void)
+{
+ Driver::registerPlugin(PLATFORM_XBOX, 0, ID_MATFX,
+ matfxOpen, matfxClose);
+}
+
+ObjPipeline*
+makeMatFXPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->uninstanceCB = defaultUninstanceCB;
+ pipe->pluginID = ID_MATFX;
+ pipe->pluginData = 0;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/xboxskin.cpp b/src/d3d/xboxskin.cpp
new file mode 100644
index 0000000..0ce5cba
--- /dev/null
+++ b/src/d3d/xboxskin.cpp
@@ -0,0 +1,252 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwxbox.h"
+
+#define PLUGIN_ID ID_SKIN
+
+namespace rw {
+namespace xbox {
+
+struct NativeSkin
+{
+ int32 table1[256]; // maps indices to bones
+ int32 table2[256]; // maps bones to indices
+ int32 numUsedBones;
+ void *vertexBuffer;
+ int32 stride;
+};
+
+Stream*
+readNativeSkin(Stream *stream, int32, void *object, int32 offset)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ uint32 vers, platform;
+ if(!findChunk(stream, ID_STRUCT, nil, &vers)){
+ RWERROR((ERR_CHUNK, "STRUCT"));
+ return nil;
+ }
+ platform = stream->readU32();
+ if(platform != PLATFORM_XBOX){
+ RWERROR((ERR_PLATFORM, platform));
+ return nil;
+ }
+ if(vers < 0x35000){
+ RWERROR((ERR_VERSION, vers));
+ return nil;
+ }
+
+ Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN);
+ *PLUGINOFFSET(Skin*, geometry, offset) = skin;
+
+ int32 numBones = stream->readI32();
+ skin->init(numBones, 0, 0);
+ NativeSkin *natskin = rwNewT(NativeSkin, 1, MEMDUR_EVENT | ID_SKIN);
+ skin->platformData = natskin;
+ stream->read32(natskin->table1, 256*sizeof(int32));
+ stream->read32(natskin->table2, 256*sizeof(int32));
+ natskin->numUsedBones = stream->readI32();
+ skin->numWeights = stream->readI32();
+ stream->seek(4); // skip pointer to vertexBuffer
+ natskin->stride = stream->readI32();
+ int32 size = geometry->numVertices*natskin->stride;
+ natskin->vertexBuffer = rwNewT(uint8, size, MEMDUR_EVENT | ID_SKIN);
+ stream->read8(natskin->vertexBuffer, size);
+ stream->read32(skin->inverseMatrices, skin->numBones*64);
+
+ readSkinSplitData(stream, skin);
+ return stream;
+}
+
+Stream*
+writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset)
+{
+ ASSERTLITTLE;
+ Geometry *geometry = (Geometry*)object;
+ Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
+ assert(skin->platformData);
+ assert(rw::version >= 0x35000 && "can't handle native xbox skin < 0x35000");
+ NativeSkin *natskin = (NativeSkin*)skin->platformData;
+
+ writeChunkHeader(stream, ID_STRUCT, len-12);
+ stream->writeU32(PLATFORM_XBOX);
+ stream->writeI32(skin->numBones);
+ stream->write32(natskin->table1, 256*sizeof(int32));
+ stream->write32(natskin->table2, 256*sizeof(int32));
+ stream->writeI32(natskin->numUsedBones);
+ stream->writeI32(skin->numWeights);
+ stream->writeU32(0xBADEAFFE); // pointer to vertexBuffer
+ stream->writeI32(natskin->stride);
+ stream->write8(natskin->vertexBuffer,
+ geometry->numVertices*natskin->stride);
+ stream->write32(skin->inverseMatrices, skin->numBones*64);
+
+ writeSkinSplitData(stream, skin);
+ return stream;
+}
+
+int32
+getSizeNativeSkin(void *object, int32 offset)
+{
+ Geometry *geometry = (Geometry*)object;
+ Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
+ if(skin == nil)
+ return -1;
+ if(skin->platformData == nil)
+ return -1;
+ NativeSkin *natskin = (NativeSkin*)skin->platformData;
+ return 12 + 8 + 2*256*4 + 4*4 +
+ natskin->stride*geometry->numVertices + skin->numBones*64 +
+ skinSplitDataSize(skin);
+}
+
+void
+skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ defaultInstanceCB(geo, header);
+
+ Skin *skin = Skin::get(geo);
+ if(skin == nil)
+ return;
+ NativeSkin *natskin = rwNewT(NativeSkin, 1, MEMDUR_EVENT | ID_SKIN);
+ skin->platformData = natskin;
+
+ natskin->numUsedBones = skin->numUsedBones;
+ memset(natskin->table1, 0xFF, sizeof(natskin->table1));
+ memset(natskin->table2, 0x00, sizeof(natskin->table2));
+ for(int32 i = 0; i < skin->numUsedBones; i++){
+ natskin->table1[i] = skin->usedBones[i];
+ natskin->table2[skin->usedBones[i]] = i;
+ }
+
+ natskin->stride = 3*skin->numWeights;
+ uint8 *vbuf = rwNewT(uint8, header->numVertices*natskin->stride, MEMDUR_EVENT | ID_SKIN);
+ natskin->vertexBuffer = vbuf;
+
+ int32 w[4];
+ int sum;
+ float32 *weights = skin->weights;
+ uint8 *p = vbuf;
+ int32 numVertices = header->numVertices;
+ while(numVertices--){
+ sum = 0;
+ for(int i = 1; i < skin->numWeights; i++){
+ w[i] = (int32)(weights[i]*255.0f + 0.5f);
+ sum += w[i];
+ }
+ w[0] = 255 - sum;
+ for(int i = 0; i < skin->numWeights; i++)
+ p[i] = w[i];
+ p += natskin->stride;
+ weights += 4;
+ }
+
+ numVertices = header->numVertices;
+ p = vbuf + skin->numWeights;
+ uint8 *indices = skin->indices;
+ uint16 *idx;
+ while(numVertices--){
+ idx = (uint16*)p;
+ for(int i = 0; i < skin->numWeights; i++)
+ idx[i] = 3*natskin->table2[indices[i]];
+ p += natskin->stride;
+ indices += 4;
+ }
+}
+
+void
+skinUninstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ defaultUninstanceCB(geo, header);
+
+ Skin *skin = Skin::get(geo);
+ if(skin == nil)
+ return;
+ NativeSkin *natskin = (NativeSkin*)skin->platformData;
+
+ uint8 *data = skin->data;
+ float *invMats = skin->inverseMatrices;
+ skin->init(skin->numBones, natskin->numUsedBones, geo->numVertices);
+ memcpy(skin->inverseMatrices, invMats, skin->numBones*64);
+ rwFree(data);
+
+ for(int32 j = 0; j < skin->numUsedBones; j++)
+ skin->usedBones[j] = natskin->table1[j];
+
+ float *weights = skin->weights;
+ uint8 *indices = skin->indices;
+ uint8 *p = (uint8*)natskin->vertexBuffer;
+ int32 numVertices = header->numVertices;
+ float w[4];
+ uint8 i[4];
+ uint16 *ip;
+ while(numVertices--){
+ w[0] = w[1] = w[2] = w[3] = 0.0f;
+ i[0] = i[1] = i[2] = i[3] = 0;
+
+ for(int32 j = 0; j < skin->numWeights; j++)
+ w[j] = *p++/255.0f;
+
+ ip = (uint16*)p;
+ for(int32 j = 0; j < skin->numWeights; j++){
+ i[j] = natskin->table1[*ip++/3];
+ if(w[j] == 0.0f) i[j] = 0; // clean up a bit
+ }
+ p = (uint8*)ip;
+
+ for(int32 j = 0; j < 4; j++){
+ *weights++ = w[j];
+ *indices++ = i[j];
+ }
+ }
+
+ rwFree(natskin->vertexBuffer);
+ rwFree(natskin);
+}
+
+static void*
+skinOpen(void *o, int32, int32)
+{
+ skinGlobals.pipelines[PLATFORM_XBOX] = makeSkinPipeline();
+ return o;
+}
+
+static void*
+skinClose(void *o, int32, int32)
+{
+ ((ObjPipeline*)skinGlobals.pipelines[PLATFORM_XBOX])->destroy();
+ skinGlobals.pipelines[PLATFORM_XBOX] = nil;
+ return o;
+}
+
+void
+initSkin(void)
+{
+ Driver::registerPlugin(PLATFORM_XBOX, 0, ID_SKIN,
+ skinOpen, skinClose);
+}
+
+ObjPipeline*
+makeSkinPipeline(void)
+{
+ ObjPipeline *pipe = ObjPipeline::create();
+ pipe->instanceCB = skinInstanceCB;
+ pipe->uninstanceCB = skinUninstanceCB;
+ pipe->pluginID = ID_SKIN;
+ pipe->pluginData = 1;
+ return pipe;
+}
+
+}
+}
diff --git a/src/d3d/xboxvfmt.cpp b/src/d3d/xboxvfmt.cpp
new file mode 100644
index 0000000..b6569dc
--- /dev/null
+++ b/src/d3d/xboxvfmt.cpp
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "../rwbase.h"
+#include "../rwerror.h"
+#include "../rwplg.h"
+#include "../rwpipeline.h"
+#include "../rwobjects.h"
+#include "../rwanim.h"
+#include "../rwengine.h"
+#include "../rwplugins.h"
+#include "rwxbox.h"
+
+namespace rw {
+namespace xbox {
+
+static int32 vertexFmtOffset;
+
+uint32 vertexFormatSizes[6] = {
+ 0, 1, 2, 2, 4, 4
+};
+
+uint32*
+getVertexFmt(Geometry *g)
+{
+ return PLUGINOFFSET(uint32, g, vertexFmtOffset);
+}
+
+uint32
+makeVertexFmt(int32 flags, uint32 numTexSets)
+{
+ if(numTexSets > 4)
+ numTexSets = 4;
+ uint32 fmt = 0x5; // FLOAT3
+ if(flags & Geometry::NORMALS)
+ fmt |= 0x40; // NORMPACKED3
+ for(uint32 i = 0; i < numTexSets; i++)
+ fmt |= 0x500 << i*4; // FLOAT2
+ if(flags & Geometry::PRELIT)
+ fmt |= 0x1000000; // D3DCOLOR
+ return fmt;
+}
+
+uint32
+getVertexFmtStride(uint32 fmt)
+{
+ uint32 stride = 0;
+ uint32 v = fmt & 0xF;
+ uint32 n = (fmt >> 4) & 0xF;
+ stride += v == 4 ? 4 : 3*vertexFormatSizes[v];
+ stride += n == 4 ? 4 : 3*vertexFormatSizes[n];
+ if(fmt & 0x1000000)
+ stride += 4;
+ for(int i = 0; i < 4; i++){
+ uint32 t = (fmt >> (i*4 + 8)) & 0xF;
+ stride += t == 4 ? 4 : 2*vertexFormatSizes[t];
+ }
+ if(fmt & 0xE000000)
+ stride += 8;
+ return stride;
+}
+
+static void*
+createVertexFmt(void *object, int32 offset, int32)
+{
+ *PLUGINOFFSET(uint32, object, offset) = 0;
+ return object;
+}
+
+static void*
+copyVertexFmt(void *dst, void *src, int32 offset, int32)
+{
+ *PLUGINOFFSET(uint32, dst, offset) = *PLUGINOFFSET(uint32, src, offset);
+ return dst;
+}
+
+static Stream*
+readVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ uint32 fmt = stream->readU32();
+ *PLUGINOFFSET(uint32, object, offset) = fmt;
+ // TODO: ? create and attach "vertex shader"
+ return stream;
+}
+
+static Stream*
+writeVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ stream->writeI32(*PLUGINOFFSET(uint32, object, offset));
+ return stream;
+}
+
+static int32
+getSizeVertexFmt(void*, int32, int32)
+{
+ if(rw::platform != PLATFORM_XBOX)
+ return -1;
+ return 4;
+}
+
+void
+registerVertexFormatPlugin(void)
+{
+ vertexFmtOffset = Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT,
+ createVertexFmt, nil, copyVertexFmt);
+ Geometry::registerPluginStream(ID_VERTEXFMT,
+ readVertexFmt,
+ writeVertexFmt,
+ getSizeVertexFmt);
+}
+
+}
+}