From dfe2a7c02b5ac3948f3579335186293e4afd2222 Mon Sep 17 00:00:00 2001 From: gho tik Date: Mon, 19 Dec 2016 11:48:46 -0500 Subject: [PATCH] v2_04_00_src_fx2 Former-commit-id: fdaf57d31d2e4aa5223dbc325adef74e73092661 --- Include/dds.h | 237 +++++++++++ Include/dxwnd.h | 1 + build/dxwnd.dll | 4 +- build/dxwnd.exe | 4 +- build/exports/LuXiaoFeng.dxw | 36 ++ build/readme-relnotes.txt | 4 +- dll/d3dtexture.cpp | 748 +++++++++++++++++++++-------------- dll/ddtexture.cpp | 241 +++++++---- dll/dxdds.h | 28 ++ dll/dxemublt.cpp | 16 +- dll/dxwnd.cpp | 2 +- dll/dxwnd.vs2008.suo | Bin 367104 -> 401408 bytes dll/dxwnd.vs2008.vcproj | 4 + host/TabDirect3D.cpp | 2 +- host/TargetDlg.cpp | 3 +- host/TargetDlg.h | 3 +- host/dxwndhost.aps | Bin 255188 -> 222716 bytes host/dxwndhost.rc | Bin 141464 -> 141890 bytes host/dxwndhost.vs2008.suo | Bin 119808 -> 125952 bytes host/dxwndhostView.cpp | 12 +- host/host.aps | Bin 47508 -> 47504 bytes host/resource | Bin 52170 -> 52354 bytes 22 files changed, 955 insertions(+), 390 deletions(-) create mode 100644 Include/dds.h create mode 100644 build/exports/LuXiaoFeng.dxw create mode 100644 dll/dxdds.h diff --git a/Include/dds.h b/Include/dds.h new file mode 100644 index 0000000..4d74620 --- /dev/null +++ b/Include/dds.h @@ -0,0 +1,237 @@ +//-------------------------------------------------------------------------------------- +// dds.h +// +// This header defines constants and structures that are useful when parsing +// DDS files. DDS files were originally designed to use several structures +// and constants that are native to DirectDraw and are defined in ddraw.h, +// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar +// (compatible) constants and structures so that one can use DDS files +// without needing to include ddraw.h. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +// VS 2010's stdint.h conflicts with intsafe.h +#pragma warning(push) +#pragma warning(disable : 4005) +#include +#pragma warning(pop) + +namespace DirectX +{ + +#pragma pack(push,1) + +const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +struct DDS_PIXELFORMAT +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwFourCC; + uint32_t dwRGBBitCount; + uint32_t dwRBitMask; + uint32_t dwGBitMask; + uint32_t dwBBitMask; + uint32_t dwABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 + +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 )) +#endif /* defined(MAKEFOURCC) */ + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 = + { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; + +// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION +enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +}; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +enum DDS_ALPHA_MODE +{ + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, +}; + +struct DDS_HEADER +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwHeight; + uint32_t dwWidth; + uint32_t dwPitchOrLinearSize; + uint32_t dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + uint32_t dwMipMapCount; + uint32_t dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t dwCaps; + uint32_t dwCaps2; + uint32_t dwCaps3; + uint32_t dwCaps4; + uint32_t dwReserved2; +}; + +struct DDS_HEADER_DXT10 +{ + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 +}; + +#pragma pack(pop) + +static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); +static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + +}; // namespace diff --git a/Include/dxwnd.h b/Include/dxwnd.h index 477de08..d318e1d 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -261,6 +261,7 @@ #define RAWFORMAT 0x00000200 // texture dump / hack are performed in raw format, compression / decompression to be made offline #define WININSULATION 0x00000400 // EnumerateWin finds no windows! #define FIXMOUSEHOOK 0x00000800 // fixes mouse coordinates retrieved through MouseProc routine associated to SetWindowsHook(WH_MOUSE,..) +#define DDSFORMAT 0x00001000 // texture dump / hack are performed in MS DDS format // logging Tflags DWORD: #define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general diff --git a/build/dxwnd.dll b/build/dxwnd.dll index ca8bd2d..86a2c37 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3e4a919d94a65a136733126cb2ab2ea7ec6ea20d20d06acc7fc826fb8dd7bce -size 756736 +oid sha256:b75df7287fd454e0b3591e2a03736287d786a51d15bfbdeb71958a1488e4db40 +size 758272 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 678ae18..3c9e984 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4781f62e3b9bbc3cb28f6ab03585167d87e0352520ba25ee7ad0102ad02a244 -size 668160 +oid sha256:0f2265c91f849cbdc3a809b7ff592df41d95806ecd6d9cadb125ddb2e15b48b6 +size 669184 diff --git a/build/exports/LuXiaoFeng.dxw b/build/exports/LuXiaoFeng.dxw new file mode 100644 index 0000000..6e73979 --- /dev/null +++ b/build/exports/LuXiaoFeng.dxw @@ -0,0 +1,36 @@ +[target] +title0=LuXiaoFeng +path0=F:\Games\lxf\core.dat +startfolder0= +launchpath0=F:\Games\lxf\Lxf.exe +module0= +opengllib0= +notes0= +registry0= +ver0=0 +monitorid0=-1 +coord0=0 +flag0=673185826 +flagg0=1207959552 +flagh0=20 +flagi0=138412036 +flagj0=4224 +flagk0=65536 +flagl0=8704 +flagm0=0 +tflag0=0 +dflag0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=0 +swapeffect0=0 +maxddinterface0=7 +slowratio0=2 +scanline0=0 +initresw0=800 +initresh0=600 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index a0c6723..36e81c8 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -1380,7 +1380,7 @@ add: D3DDevice GetCaps hooking and full dump of D3DDevice capabilities add: "No HAL Device" flag, making it unavailable the IID_Direct3DHALDevice device. Fixes "Grand Prix World" when the 3D car models are invisible. add: reorganization of mouse clipper fields, with the addition of LOCK mode (useful for Tribal Rage) -v2.04.00 +v2.04.00/fx2 add: texture management for D3D textures: XCTn compressed textures, raw mode, texture highlight and hack add: Input / "fix MOUSEHOOK callback" option, fixes "Jagged Alliance 2" mouse problems add: GDI / "Pretend Win visible & on top" option: experimental, let the program believe that the main window is visible and on top of z-order as usually happens to full screen applications @@ -1391,3 +1391,5 @@ fix: mouse clipping now selected by radio buttons (default, off, on, locked) fix: bug in D3D device enumeration log fix: bug in Hybrid and GDI ddraw surface rendering fix: missing "No HAL Device" flag default to disabled +fix: improvements in texture handling, dds format support for DirectDraw textures +fix: fixed fast bilinear 2X on 32 bit color depth diff --git a/dll/d3dtexture.cpp b/dll/d3dtexture.cpp index e9bac6b..7c7d0d6 100644 --- a/dll/d3dtexture.cpp +++ b/dll/d3dtexture.cpp @@ -7,13 +7,22 @@ #include "dxhelper.h" #include "syslibs.h" #include "stdio.h" +#include "dxdds.h" #define STB_DXT_IMPLEMENTATION #include "stb_dxt.h" +//#define SOLIDCOLOR + extern unsigned int HashSurface(BYTE *, int, int, int); extern char *GetDxWndPath(); +typedef enum { + FORMAT_BMP = 0, + FORMAT_RAW, + FORMAT_DDS +}; + static unsigned int HashBuffer(BYTE *buf, int len) { unsigned int b = 378551; @@ -166,6 +175,35 @@ static int FormatColorDepth(D3DFORMAT Format) return iColorDepth; } +static DWORD DDSTextureType(D3DFORMAT Format) +{ + int dwFlag = 0; + switch (Format){ + case D3DFMT_X8R8G8B8: + case D3DFMT_X4R4G4B4: + case D3DFMT_X1R5G5B5: + case D3DFMT_R5G6B5: + dwFlag = DDPF_RGB; + break; + case D3DFMT_A8R8G8B8: + case D3DFMT_A4R4G4B4: // AoE III + case D3DFMT_A1R5G5B5: // AoE III + dwFlag = DDPF_RGB|DDPF_ALPHAPIXELS; + break; + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + dwFlag = DDPF_FOURCC; + break; + case D3DFMT_A8: + case D3DFMT_L8: + break; + } + return dwFlag; +} + // FormatColorBytes macro gives color depth in bytes by dividing by 8 (=> lshift 3) #define FormatColorBytes(Format) (FormatColorDepth(Format) >> 3) @@ -200,6 +238,56 @@ static DWORD TextureSize(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) return dwSize; } +static void SetDDSPixelFormat(D3DFORMAT Format, DDS_PIXELFORMAT *pf) +{ + switch (Format){ + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + case D3DFMT_A8: + case D3DFMT_L8: + pf->dwRGBBitCount = 32; + pf->dwRBitMask = 0x00FF0000; + pf->dwGBitMask = 0x0000FF00; + pf->dwBBitMask = 0x000000FF; + pf->dwABitMask = 0xFF000000; + break; + case D3DFMT_DXT1: + pf->dwRGBBitCount = 16; + pf->dwRBitMask = 0xF800; + pf->dwGBitMask = 0x07E0; + pf->dwBBitMask = 0x001F; + pf->dwABitMask = 0x0000; + break; + case D3DFMT_A4R4G4B4: // AoE III + case D3DFMT_X4R4G4B4: + pf->dwRGBBitCount = 16; + pf->dwRBitMask = 0x0F00; + pf->dwGBitMask = 0x00F0; + pf->dwBBitMask = 0x000F; + pf->dwABitMask = 0xF000; + break; + case D3DFMT_A1R5G5B5: // AoE III + case D3DFMT_X1R5G5B5: + pf->dwRGBBitCount = 16; + pf->dwRBitMask = 0x7C00; + pf->dwGBitMask = 0x03E0; + pf->dwBBitMask = 0x001F; + pf->dwABitMask = 0x8000; + break; + case D3DFMT_R5G6B5: + pf->dwRGBBitCount = 16; + pf->dwRBitMask = 0x7C00; + pf->dwGBitMask = 0x03E0; + pf->dwBBitMask = 0x001F; + pf->dwABitMask = 0x0000; + break; + } +} + static DWORD D3DHash(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) { DWORD hash; @@ -337,8 +425,9 @@ void D3DTextureDump(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) int w, h; int iSurfaceSize, iScanLineSize; char pszFile[MAX_PATH]; + char *sExt; DWORD hash; - BOOL IsRaw = (dxw.dwFlags8 & RAWFORMAT); + static int iTextureFileFormat; if(DoOnce){ char sProfilePath[MAX_PATH]; @@ -347,9 +436,12 @@ void D3DTextureDump(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) MaxTexX=GetPrivateProfileInt("Texture", "MaxTexX", 0, sProfilePath); MinTexY=GetPrivateProfileInt("Texture", "MinTexY", 0, sProfilePath); MaxTexY=GetPrivateProfileInt("Texture", "MaxTexY", 0, sProfilePath); - OutTrace("TextureDump: size min=(%dx%d) max=(%dx%d)\n", MinTexX, MinTexY, MaxTexX, MaxTexY); sprintf_s(pszFile, MAX_PATH, "%s\\texture.out", GetDxWndPath()); CreateDirectory(pszFile, NULL); + iTextureFileFormat = FORMAT_BMP; + if(dxw.dwFlags8 & RAWFORMAT) iTextureFileFormat = FORMAT_RAW; + if(dxw.dwFlags8 & DDSFORMAT) iTextureFileFormat = FORMAT_DDS; + OutTrace("TextureDump: size min=(%dx%d) max=(%dx%d) format=%d\n", MinTexX, MinTexY, MaxTexX, MaxTexY, iTextureFileFormat); DoOnce = FALSE; } @@ -379,224 +471,260 @@ void D3DTextureDump(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) break; // almost certainly, an empty black surface! } - // Create the .BMP file. + // Create the file. + switch (iTextureFileFormat){ + case FORMAT_BMP: sExt = "bmp"; break; + case FORMAT_RAW: sExt = "raw"; break; + case FORMAT_DDS: sExt = "dds"; break; + } sprintf_s(pszFile, MAX_PATH, "%s\\texture.out\\texture.%03d.%03d.%s.%08X.%s", - GetDxWndPath(), Desc.Width, Desc.Height, ExplainD3DSurfaceFormat(Desc.Format), - hash, IsRaw ? "raw" : "bmp"); + GetDxWndPath(), Desc.Width, Desc.Height, ExplainD3DSurfaceFormat(Desc.Format), hash, sExt); hf = fopen(pszFile, "wb"); if(!hf) break; - if(IsRaw){ - fwrite((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf); - fclose(hf); - return; - } + switch(iTextureFileFormat){ - // set bmp invariant parameters - if (SetBMPStruct(&pbi, &hdr, Desc)) break; - iScanLineSize = ((pbi.bV4Width * pbi.bV4BitCount + 0x1F) & ~0x1F)/8; + case FORMAT_RAW: - // Copy the BITMAPFILEHEADER into the .BMP file. - fwrite((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf); + if(fwrite((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + fclose(hf); + break; - // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. - fwrite((LPVOID)&pbi, sizeof(BITMAPV4HEADER) + pbi.bV4ClrUsed * sizeof (RGBQUAD), 1, hf); + case FORMAT_DDS: { - switch (Desc.Format){ - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - case D3DFMT_A4R4G4B4: - case D3DFMT_X4R4G4B4: - case D3DFMT_A1R5G5B5: // AoE III - case D3DFMT_R5G6B5: // AoE III - case D3DFMT_X1R5G5B5: - { - // Copy the array of color indices into the .BMP file. - for(int y=0; y<(int)Desc.Height; y++) - fwrite((BYTE *)LockedRect.pBits + (y*LockedRect.Pitch), iScanLineSize, 1, hf); + DDS_HEADER ddsh; + if(fwrite("DDS ", 4, 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + memset(&ddsh, 0, sizeof(ddsh)); + ddsh.dwSize = sizeof(ddsh); + ddsh.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT; + ddsh.dwHeight = Desc.Height; + ddsh.dwWidth = Desc.Width; + ddsh.ddspf.dwSize = sizeof(DDS_PIXELFORMAT); + ddsh.ddspf.dwFlags = DDSTextureType(Desc.Format); + // compressed formats must have 0 pitch + if(ddsh.ddspf.dwFlags & DDPF_RGB) { + ddsh.dwPitchOrLinearSize = LockedRect.Pitch; + ddsh.dwFlags |= DDSD_PITCH; } - break; - case D3DFMT_A8: - case D3DFMT_L8: - { - // Copy the array of color indices into the .BMP file. - BYTE *p = (BYTE *)LockedRect.pBits; - for(int y=0; y<(int)Desc.Height; y++) - for(int x=0; x<(int)Desc.Width; x++){ - DWORD pixel; - pixel = 0xFF000000 | *p | (*p << 8) | (*p << 16); // gray color - fwrite((BYTE *)&pixel, sizeof(DWORD), 1, hf); - p++; - } - } - break; - case D3DFMT_DXT1: - { - // Copy the array of color indices into the .BMP file. - WORD *bm; - WORD *c; - int bmsize; - c = (WORD *)LockedRect.pBits; - bmsize = Desc.Width * Desc.Height * sizeof(WORD); - bm = (WORD *)malloc(bmsize); - for(int y=0; y<(int)Desc.Height; y+=4){ - for(int x=0; x<(int)Desc.Width; x+=4){ - WORD color_0, color_1, color_2, color_3; - color_0 = *c++; - color_1 = *c++; - color_2 = Melt_123(color_1, color_0); - color_3 = Melt_123(color_0, color_1); - for(int n=0; n<2; n++){ - int dy; - WORD color_indexes = *c++; - WORD color; - for (int m=0; m<8; m++){ - switch (color_indexes & 0x3){ - case 0x00: color = color_0; break; - case 0x01: color = color_1; break; - case 0x02: color = color_2; break; - case 0x03: color = color_3; break; + if(ddsh.ddspf.dwFlags & DDPF_FOURCC) ddsh.ddspf.dwFourCC = Desc.Format; + SetDDSPixelFormat(Desc.Format, &ddsh.ddspf); + if(fwrite((BYTE *)&ddsh, sizeof(ddsh), 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + if(fwrite((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + } + break; + + case FORMAT_BMP: + + // set bmp invariant parameters + if (SetBMPStruct(&pbi, &hdr, Desc)) break; + iScanLineSize = ((pbi.bV4Width * pbi.bV4BitCount + 0x1F) & ~0x1F)/8; + + // Copy the BITMAPFILEHEADER into the .BMP file. + fwrite((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf); + + // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. + fwrite((LPVOID)&pbi, sizeof(BITMAPV4HEADER) + pbi.bV4ClrUsed * sizeof (RGBQUAD), 1, hf); + + switch (Desc.Format){ + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_A4R4G4B4: + case D3DFMT_X4R4G4B4: + case D3DFMT_A1R5G5B5: // AoE III + case D3DFMT_R5G6B5: // AoE III + case D3DFMT_X1R5G5B5: + { + // Copy the array of color indices into the .BMP file. + for(int y=0; y<(int)Desc.Height; y++) + fwrite((BYTE *)LockedRect.pBits + (y*LockedRect.Pitch), iScanLineSize, 1, hf); + } + break; + case D3DFMT_A8: + case D3DFMT_L8: + { + // Copy the array of color indices into the .BMP file. + BYTE *p = (BYTE *)LockedRect.pBits; + for(int y=0; y<(int)Desc.Height; y++) + for(int x=0; x<(int)Desc.Width; x++){ + DWORD pixel; + pixel = 0xFF000000 | *p | (*p << 8) | (*p << 16); // gray color + fwrite((BYTE *)&pixel, sizeof(DWORD), 1, hf); + p++; + } + } + break; + case D3DFMT_DXT1: + { + // Copy the array of color indices into the .BMP file. + WORD *bm; + WORD *c; + int bmsize; + c = (WORD *)LockedRect.pBits; + bmsize = Desc.Width * Desc.Height * sizeof(WORD); + bm = (WORD *)malloc(bmsize); + for(int y=0; y<(int)Desc.Height; y+=4){ + for(int x=0; x<(int)Desc.Width; x+=4){ + WORD color_0, color_1, color_2, color_3; + color_0 = *c++; + color_1 = *c++; + color_2 = Melt_123(color_1, color_0); + color_3 = Melt_123(color_0, color_1); + for(int n=0; n<2; n++){ + int dy; + WORD color_indexes = *c++; + WORD color; + for (int m=0; m<8; m++){ + switch (color_indexes & 0x3){ + case 0x00: color = color_0; break; + case 0x01: color = color_1; break; + case 0x02: color = color_2; break; + case 0x03: color = color_3; break; + } + dy = (m<4) ? 0 : 1; + color_indexes >>= 2; + int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); + if(index < bmsize/2) bm[index]=color; } - dy = (m<4) ? 0 : 1; - color_indexes >>= 2; - int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); - if(index < bmsize/2) bm[index]=color; } } } + fwrite((BYTE *)bm, bmsize, 1, hf); + free(bm); } - fwrite((BYTE *)bm, bmsize, 1, hf); - free(bm); - } - break; - case D3DFMT_DXT2: - case D3DFMT_DXT3: - { - // Copy the array of color indices into the .BMP file. - DWORD *bm; - WORD *c; - int bmsize; - c = (WORD *)LockedRect.pBits; - bmsize = Desc.Width * Desc.Height * sizeof(DWORD); - bm = (DWORD *)malloc(bmsize); - memset(bm, 0, bmsize); - for(int y=0; y<(int)Desc.Height; y+=4){ - for(int x=0; x<(int)Desc.Width; x+=4){ - WORD color_0, color_1; - DWORD dwcolor[4]; - BYTE alpha[16]; - WORD *pAlpha; - pAlpha = (WORD *)c; - for(int row=0; row<4; row++){ - WORD a = *c++; - for(int col=0; col<4; col++){ - alpha[(row<<2)+col] = (a & 0xF); - a >>= 4; + break; + case D3DFMT_DXT2: + case D3DFMT_DXT3: + { + // Copy the array of color indices into the .BMP file. + DWORD *bm; + WORD *c; + int bmsize; + c = (WORD *)LockedRect.pBits; + bmsize = Desc.Width * Desc.Height * sizeof(DWORD); + bm = (DWORD *)malloc(bmsize); + memset(bm, 0, bmsize); + for(int y=0; y<(int)Desc.Height; y+=4){ + for(int x=0; x<(int)Desc.Width; x+=4){ + WORD color_0, color_1; + DWORD dwcolor[4]; + BYTE alpha[16]; + WORD *pAlpha; + pAlpha = (WORD *)c; + for(int row=0; row<4; row++){ + WORD a = *c++; + for(int col=0; col<4; col++){ + alpha[(row<<2)+col] = (a & 0xF); + a >>= 4; + } } + color_0 = *c++; + color_1 = *c++; + dwcolor[0] = Conv32(color_0); + dwcolor[1] = Conv32(color_1); + dwcolor[2] = Melt32_123(color_1, color_0); + dwcolor[3] = Melt32_123(color_0, color_1); + for(int n=0; n<2; n++){ + int dy; + WORD color_indexes = *c++; + DWORD color; + for (int m=0; m<8; m++){ + dy = (m<4) ? 0 : 1; + color = dwcolor[color_indexes & 0x3] & 0x00FFFFFF; + dy = (m<4) ? 0 : 1; + color_indexes >>= 2; + int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); + int alpha_index = (((2*n) + dy)<<2) + (m % 4); + //if(index < bmsize/4) bm[index] = color | 0xFF000000; // uncomment to get rid of alpha channel + if(index < bmsize/4) bm[index] = color | (alpha[alpha_index]<<28); + } + } } - color_0 = *c++; - color_1 = *c++; - dwcolor[0] = Conv32(color_0); - dwcolor[1] = Conv32(color_1); - dwcolor[2] = Melt32_123(color_1, color_0); - dwcolor[3] = Melt32_123(color_0, color_1); - for(int n=0; n<2; n++){ - int dy; - WORD color_indexes = *c++; - DWORD color; - for (int m=0; m<8; m++){ - dy = (m<4) ? 0 : 1; - color = dwcolor[color_indexes & 0x3] & 0x00FFFFFF; - dy = (m<4) ? 0 : 1; - color_indexes >>= 2; - int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); - int alpha_index = (((2*n) + dy)<<2) + (m % 4); - //if(index < bmsize/4) bm[index] = color | 0xFF000000; // uncomment to get rid of alpha channel - if(index < bmsize/4) bm[index] = color | (alpha[alpha_index]<<28); - } - } } + fwrite((BYTE *)bm, bmsize, 1, hf); + free(bm); } - fwrite((BYTE *)bm, bmsize, 1, hf); - free(bm); - } - break; - case D3DFMT_DXT4: - case D3DFMT_DXT5: - { - // Copy the array of color indices into the .BMP file. - DWORD *bm; - WORD *c; - int bmsize; - c = (WORD *)LockedRect.pBits; - bmsize = Desc.Width * Desc.Height * sizeof(DWORD); - bm = (DWORD *)malloc(bmsize); - memset(bm, 0, bmsize); - for(int y=0; y<(int)Desc.Height; y+=4){ - for(int x=0; x<(int)Desc.Width; x+=4){ - WORD color_0, color_1; - DWORD dwcolor[4]; - DWORD alpha[8]; - // alpha section (4 words) .... - alpha[1] = ((*c) >> 8) & 0xFF; - alpha[0] = (*c) & 0xFF; - c++; - if(alpha[0] > alpha[1]) - { - // 6 interpolated alpha values. - alpha[2] = ((6*alpha[0]) + (1*alpha[1])) / 7; // bit code 010 - alpha[3] = ((5*alpha[0]) + (2*alpha[1])) / 7; // bit code 011 - alpha[4] = ((4*alpha[0]) + (3*alpha[1])) / 7; // bit code 100 - alpha[5] = ((3*alpha[0]) + (4*alpha[1])) / 7; // bit code 101 - alpha[6] = ((2*alpha[0]) + (5*alpha[1])) / 7; // bit code 110 - alpha[7] = ((1*alpha[0]) + (6*alpha[1])) / 7; // bit code 111 - } - else - { - // 4 interpolated alpha values. - alpha[2] = ((4*alpha[0]) + (1*alpha[1])) / 5; // bit code 010 - alpha[3] = ((3*alpha[0]) + (2*alpha[1])) / 5; // bit code 011 - alpha[4] = ((2*alpha[0]) + (3*alpha[1])) / 5; // bit code 100 - alpha[5] = ((1*alpha[0]) + (4*alpha[1])) / 5; // bit code 101 - alpha[6] = 0x00; // bit code 110 (fully transparent) - alpha[7] = 0xFF; // bit code 111 (fully opaque) - } - BYTE *pAlpha = (BYTE *)c; - c += 3; - color_0 = *c++; - color_1 = *c++; - dwcolor[0] = Conv32(color_0); - dwcolor[1] = Conv32(color_1); - dwcolor[2] = Melt32_123(color_1, color_0); - dwcolor[3] = Melt32_123(color_0, color_1); - for(int n=0; n<2; n++){ - int dy; - DWORD dwAlpha_indexes = (*(pAlpha+0) & 0x0000FF) | ((*(pAlpha+1)<<8) & 0x00FF00) | ((*(pAlpha+2)<<16) & 0xFF0000); - pAlpha += 3; - DWORD alpha_color; - WORD color_indexes = *c++; - DWORD color; - for (int m=0; m<8; m++){ - alpha_color = (alpha[dwAlpha_indexes & 0x7] << 24) & 0xFF000000; - dy = (m<4) ? 0 : 1; - dwAlpha_indexes >>= 3; - color = dwcolor[color_indexes & 0x3] & 0x00FFFFFF; - dy = (m<4) ? 0 : 1; - color_indexes >>= 2; - int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); - if(index < bmsize/4) bm[index] = color | alpha_color; + break; + case D3DFMT_DXT4: + case D3DFMT_DXT5: + { + // Copy the array of color indices into the .BMP file. + DWORD *bm; + WORD *c; + int bmsize; + c = (WORD *)LockedRect.pBits; + bmsize = Desc.Width * Desc.Height * sizeof(DWORD); + bm = (DWORD *)malloc(bmsize); + memset(bm, 0, bmsize); + for(int y=0; y<(int)Desc.Height; y+=4){ + for(int x=0; x<(int)Desc.Width; x+=4){ + WORD color_0, color_1; + DWORD dwcolor[4]; + DWORD alpha[8]; + // alpha section (4 words) .... + alpha[1] = ((*c) >> 8) & 0xFF; + alpha[0] = (*c) & 0xFF; + c++; + if(alpha[0] > alpha[1]) + { + // 6 interpolated alpha values. + alpha[2] = ((6*alpha[0]) + (1*alpha[1])) / 7; // bit code 010 + alpha[3] = ((5*alpha[0]) + (2*alpha[1])) / 7; // bit code 011 + alpha[4] = ((4*alpha[0]) + (3*alpha[1])) / 7; // bit code 100 + alpha[5] = ((3*alpha[0]) + (4*alpha[1])) / 7; // bit code 101 + alpha[6] = ((2*alpha[0]) + (5*alpha[1])) / 7; // bit code 110 + alpha[7] = ((1*alpha[0]) + (6*alpha[1])) / 7; // bit code 111 } - } + else + { + // 4 interpolated alpha values. + alpha[2] = ((4*alpha[0]) + (1*alpha[1])) / 5; // bit code 010 + alpha[3] = ((3*alpha[0]) + (2*alpha[1])) / 5; // bit code 011 + alpha[4] = ((2*alpha[0]) + (3*alpha[1])) / 5; // bit code 100 + alpha[5] = ((1*alpha[0]) + (4*alpha[1])) / 5; // bit code 101 + alpha[6] = 0x00; // bit code 110 (fully transparent) + alpha[7] = 0xFF; // bit code 111 (fully opaque) + } + BYTE *pAlpha = (BYTE *)c; + c += 3; + color_0 = *c++; + color_1 = *c++; + dwcolor[0] = Conv32(color_0); + dwcolor[1] = Conv32(color_1); + dwcolor[2] = Melt32_123(color_1, color_0); + dwcolor[3] = Melt32_123(color_0, color_1); + for(int n=0; n<2; n++){ + int dy; + DWORD dwAlpha_indexes = (*(pAlpha+0) & 0x0000FF) | ((*(pAlpha+1)<<8) & 0x00FF00) | ((*(pAlpha+2)<<16) & 0xFF0000); + pAlpha += 3; + DWORD alpha_color; + WORD color_indexes = *c++; + DWORD color; + for (int m=0; m<8; m++){ + alpha_color = (alpha[dwAlpha_indexes & 0x7] << 24) & 0xFF000000; + dy = (m<4) ? 0 : 1; + dwAlpha_indexes >>= 3; + color = dwcolor[color_indexes & 0x3] & 0x00FFFFFF; + dy = (m<4) ? 0 : 1; + color_indexes >>= 2; + int index = ((y+(2*n)+dy)*Desc.Width) + (x+(m%4)); + if(index < bmsize/4) bm[index] = color | alpha_color; + } + } + } } + fwrite((BYTE *)bm, bmsize, 1, hf); + free(bm); } - fwrite((BYTE *)bm, bmsize, 1, hf); - free(bm); - } - default: - break; + default: + break; + } + // Close the .BMP file. + fclose(hf); } - // Close the .BMP file. - if(hf) fclose(hf); break; } // end of fake loop 1 } @@ -610,9 +738,10 @@ void D3DTextureHack(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) BITMAPV4HEADER pbi; // bitmap info-header int iSurfaceSize, iScanLineSize; char pszFile[MAX_PATH]; + char *sExt; DWORD hash; int w, h; - BOOL IsRaw = (dxw.dwFlags8 & RAWFORMAT); + static int iTextureFileFormat; OutTraceB("TextureHack(D3D)\n"); @@ -623,8 +752,10 @@ void D3DTextureHack(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) MaxTexX=GetPrivateProfileInt("Texture", "MaxTexX", 0, sProfilePath); MinTexY=GetPrivateProfileInt("Texture", "MinTexY", 0, sProfilePath); MaxTexY=GetPrivateProfileInt("Texture", "MaxTexY", 0, sProfilePath); - OutTrace("TextureHack: size min=(%dx%d) max=(%dx%d)\n", MinTexX, MinTexY, MaxTexX, MaxTexY); - sprintf_s(pszFile, MAX_PATH, "%s\\texture.in", GetDxWndPath()); + iTextureFileFormat = FORMAT_BMP; + if(dxw.dwFlags8 & RAWFORMAT) iTextureFileFormat = FORMAT_RAW; + if(dxw.dwFlags8 & DDSFORMAT) iTextureFileFormat = FORMAT_DDS; + OutTrace("TextureHack: size min=(%dx%d) max=(%dx%d) format=%d\n", MinTexX, MinTexY, MaxTexX, MaxTexY, iTextureFileFormat); DoOnce = FALSE; } @@ -649,117 +780,144 @@ void D3DTextureHack(D3DSURFACE_DESC Desc, D3DLOCKED_RECT LockedRect) } // Look for the .BMP file. + // Create the file. + switch (iTextureFileFormat){ + case FORMAT_BMP: sExt = "bmp"; break; + case FORMAT_RAW: sExt = "raw"; break; + case FORMAT_DDS: sExt = "dds"; break; + } sprintf_s(pszFile, MAX_PATH, "%s\\texture.in\\texture.%03d.%03d.%s.%08X.%s", GetDxWndPath(), Desc.Width, Desc.Height, ExplainD3DSurfaceFormat(Desc.Format), - hash, IsRaw ? "raw" : "bmp"); + hash, sExt); hf = fopen(pszFile, "rb"); if(!hf) break; // no updated texture to load OutTrace("TextureHack: IMPORT path=%s\n", pszFile); - if(IsRaw){ - fread((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf); - fclose(hf); - return; - } + switch(iTextureFileFormat){ - int iBitCount = FormatColorDepth(Desc.Format); - if(iBitCount == 0){ - OutTrace("TextureHack: unsupported format=%x\n", Desc.Format); + case FORMAT_RAW: + + if(fread((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + break; + + case FORMAT_DDS: { + + BYTE magic[4]; + DDS_HEADER ddsh; + // assume the file is sane, read and throw away magic and dds header + if(fread(magic, 4, 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + if(fread((BYTE *)&ddsh, sizeof(ddsh), 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + memset(&ddsh, 0, sizeof(ddsh)); + if(fread((BYTE *)LockedRect.pBits, TextureSize(Desc, LockedRect), 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + } break; - } - iScanLineSize = ((Desc.Width * iBitCount + 0x1F) & ~0x1F)/8; - while(TRUE) { // fake loop to ensure final fclose - // Read the BITMAPFILEHEADER from the .BMP file (and throw away ...). - if(fread((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf) != 1)break; + case FORMAT_BMP: - // Read the BITMAPINFOHEADER (and throw away ...). - // If the file contains BITMAPV4HEADER or BITMAPV5HEADER, no problem: next fseek will settle things - if(fread((LPVOID)&pbi, sizeof(BITMAPINFOHEADER), 1, hf) != 1) break; + int iBitCount = FormatColorDepth(Desc.Format); + if(iBitCount == 0){ + OutTrace("TextureHack: unsupported format=%x\n", Desc.Format); + break; + } + iScanLineSize = ((Desc.Width * iBitCount + 0x1F) & ~0x1F)/8; - // skip the RGBQUAD array if the editor inserted one - fseek(hf, hdr.bfOffBits, SEEK_SET); + while(TRUE) { // fake loop to ensure final fclose + // Read the BITMAPFILEHEADER from the .BMP file (and throw away ...). + if(fread((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf) != 1)break; - switch (Desc.Format){ - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - // Read the new texture from the .BMP file. - if(pbi.bV4Height < 0){ - // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention - for(int y=0; y<(int)Desc.Height; y++){ - BYTE *p = (BYTE *)LockedRect.pBits + (LockedRect.Pitch * y); - fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); - if(fread((LPVOID)p, LockedRect.Pitch, 1, hf) != 1) break; - } - } - else { - // biHeight > 0 -> scan lines from bottom to top, inverse order as surface/texture convention - for(int y=0; y<(int)Desc.Height; y++){ - BYTE *p = (BYTE *)LockedRect.pBits + (LockedRect.Pitch * ((Desc.Height-1) - y)); - fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); - if(fread((LPVOID)p, LockedRect.Pitch, 1, hf) != 1) break; - } - } - break; - case D3DFMT_DXT1: - // Read the new texture from the .BMP file. - if(pbi.bV4Height < 0){ - BYTE *p = (BYTE *)LockedRect.pBits; - BYTE *fb; - fb = (BYTE *)malloc(Desc.Width * Desc.Height * sizeof(WORD)); - if(!fb) { - OutTrace("TextureHack: malloc error\n"); - break; - } - fseek(hf, hdr.bfOffBits, SEEK_SET); - if(fread((LPVOID)fb, Desc.Height * Desc.Width * (iBitCount / 8), 1, hf) != 1) { - OutTrace("TextureHack: fread error\n"); - free(fb); - break; - } - // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention - for(int y=0; y<(int)Desc.Height; y+=4){ - for(int x=0; x<(int)Desc.Width; x+=4){ - OutTrace("Compressing line=%d row=%d\n", y, x); - stb_compress_dxt_block(p, fb, FALSE, STB_DXT_NORMAL); - p += (16 * sizeof(DWORD) / 8); - OutTrace("Compression done\n"); - fb += 4 * 2; + // Read the BITMAPINFOHEADER (and throw away ...). + // If the file contains BITMAPV4HEADER or BITMAPV5HEADER, no problem: next fseek will settle things + if(fread((LPVOID)&pbi, sizeof(BITMAPINFOHEADER), 1, hf) != 1) break; + + // skip the RGBQUAD array if the editor inserted one + fseek(hf, hdr.bfOffBits, SEEK_SET); + + switch (Desc.Format){ + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + // Read the new texture from the .BMP file. + if(pbi.bV4Height < 0){ + // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention + for(int y=0; y<(int)Desc.Height; y++){ + BYTE *p = (BYTE *)LockedRect.pBits + (LockedRect.Pitch * y); + fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); + if(fread((LPVOID)p, LockedRect.Pitch, 1, hf) != 1) break; } } - free(fb); - } - break; - case D3DFMT_DXT5: - // Read the new texture from the .BMP file. - if(pbi.bV4Height < 0){ - BYTE *p = (BYTE *)LockedRect.pBits; - BYTE *fb; - fb = (BYTE *)malloc(Desc.Width * Desc.Height * sizeof(DWORD)); - if(!fb) { - OutTrace("TextureHack: malloc error\n"); - break; - } - fseek(hf, hdr.bfOffBits, SEEK_SET); - if(fread((LPVOID)fb, Desc.Height * Desc.Width * (iBitCount / 8), 1, hf) != 1) { - OutTrace("TextureHack: fread error\n"); - free(fb); - break; - } - // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention - for(int y=0; y<(int)Desc.Height; y+=4){ - for(int x=0; x<(int)Desc.Width; x+=4){ - OutTrace("Compressing line=%d row=%d\n", y, x); - stb_compress_dxt_block(p, fb, FALSE, STB_DXT_NORMAL); - p += (16 * sizeof(DWORD) / 4); - OutTrace("Compression done\n"); - fb += 4 * 4; + else { + // biHeight > 0 -> scan lines from bottom to top, inverse order as surface/texture convention + for(int y=0; y<(int)Desc.Height; y++){ + BYTE *p = (BYTE *)LockedRect.pBits + (LockedRect.Pitch * ((Desc.Height-1) - y)); + fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); + if(fread((LPVOID)p, LockedRect.Pitch, 1, hf) != 1) break; } } - free(fb); - } - break; + break; + case D3DFMT_DXT1: + // Read the new texture from the .BMP file. + if(pbi.bV4Height < 0){ + BYTE *p = (BYTE *)LockedRect.pBits; + BYTE *fb; + fb = (BYTE *)malloc(Desc.Width * Desc.Height * sizeof(WORD)); + if(!fb) { + OutTrace("TextureHack: malloc error\n"); + break; + } + fseek(hf, hdr.bfOffBits, SEEK_SET); + if(fread((LPVOID)fb, Desc.Height * Desc.Width * (iBitCount / 8), 1, hf) != 1) { + OutTrace("TextureHack: fread error\n"); + free(fb); + break; + } + // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention + for(int y=0; y<(int)Desc.Height; y+=4){ + for(int x=0; x<(int)Desc.Width; x+=4){ + OutTrace("Compressing line=%d row=%d\n", y, x); + stb_compress_dxt_block(p, fb, FALSE, STB_DXT_NORMAL); + p += (16 * sizeof(DWORD) / 8); + OutTrace("Compression done\n"); + fb += 4 * 2; + } + } + free(fb); + } + break; + case D3DFMT_DXT5: + // Read the new texture from the .BMP file. + if(pbi.bV4Height < 0){ + BYTE *p = (BYTE *)LockedRect.pBits; + BYTE *fb; + fb = (BYTE *)malloc(Desc.Width * Desc.Height * sizeof(DWORD)); + if(!fb) { + OutTrace("TextureHack: malloc error\n"); + break; + } + fseek(hf, hdr.bfOffBits, SEEK_SET); + if(fread((LPVOID)fb, Desc.Height * Desc.Width * (iBitCount / 8), 1, hf) != 1) { + OutTrace("TextureHack: fread error\n"); + free(fb); + break; + } + // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention + for(int y=0; y<(int)Desc.Height; y+=4){ + for(int x=0; x<(int)Desc.Width; x+=4){ + OutTrace("Compressing line=%d row=%d\n", y, x); + stb_compress_dxt_block(p, fb, FALSE, STB_DXT_NORMAL); + p += (16 * sizeof(DWORD) / 4); + OutTrace("Compression done\n"); + fb += 4 * 4; + } + } + free(fb); + } + break; + } + break; } OutTrace("TextureHack: TEXTURE LOAD DONE\n"); diff --git a/dll/ddtexture.cpp b/dll/ddtexture.cpp index 1d3e915..b128f1b 100644 --- a/dll/ddtexture.cpp +++ b/dll/ddtexture.cpp @@ -8,6 +8,7 @@ #include "dxhook.h" #include "syslibs.h" #include "dxhelper.h" +#include "dxdds.h" extern char *ExplainDDError(DWORD); @@ -21,6 +22,12 @@ extern int Set_dwSize_From_Surface(); #define GRIDSIZE 16 +typedef enum { + FORMAT_BMP = 0, + FORMAT_RAW, + FORMAT_DDS +}; + /* RS Hash Function */ static unsigned int Hash(BYTE *buf, int len) @@ -187,7 +194,8 @@ static void TextureDump(LPDIRECTDRAWSURFACE s, int dxversion) static int MinTexX, MinTexY, MaxTexX, MaxTexY; static BOOL DoOnce = TRUE; char pszFile[MAX_PATH]; - BOOL IsRaw = (dxw.dwFlags8 & RAWFORMAT); + char *sExt; + static int iTextureFileFormat; OutTraceB("TextureDump(%d): lpdds=%x\n", dxversion, s); @@ -198,9 +206,12 @@ static void TextureDump(LPDIRECTDRAWSURFACE s, int dxversion) MaxTexX=GetPrivateProfileInt("Texture", "MaxTexX", 0, sProfilePath); MinTexY=GetPrivateProfileInt("Texture", "MinTexY", 0, sProfilePath); MaxTexY=GetPrivateProfileInt("Texture", "MaxTexY", 0, sProfilePath); - OutTrace("TextureDump: size min=(%dx%d) max=(%dx%d)\n", MinTexX, MinTexY, MaxTexX, MaxTexY); sprintf_s(pszFile, MAX_PATH, "%s\\texture.out", GetDxWndPath()); CreateDirectory(pszFile, NULL); + iTextureFileFormat = FORMAT_BMP; + if(dxw.dwFlags8 & RAWFORMAT) iTextureFileFormat = FORMAT_RAW; + if(dxw.dwFlags8 & DDSFORMAT) iTextureFileFormat = FORMAT_DDS; + OutTrace("TextureDump: size min=(%dx%d) max=(%dx%d) format=%d\n", MinTexX, MinTexY, MaxTexX, MaxTexY, iTextureFileFormat); DoOnce = FALSE; } @@ -271,43 +282,79 @@ static void TextureDump(LPDIRECTDRAWSURFACE s, int dxversion) } // Create the .BMP file. + switch (iTextureFileFormat){ + case FORMAT_BMP: sExt = "bmp"; break; + case FORMAT_RAW: sExt = "raw"; break; + case FORMAT_DDS: sExt = "dds"; break; + } sprintf_s(pszFile, MAX_PATH, "%s\\texture.out\\texture.%03d.%03d.%s.%08X.%s", - GetDxWndPath(), ddsd.dwWidth, ddsd.dwHeight, SurfaceType(ddsd.ddpfPixelFormat), - hash, IsRaw ? "raw" : "bmp"); + GetDxWndPath(), ddsd.dwWidth, ddsd.dwHeight, SurfaceType(ddsd.ddpfPixelFormat), hash, sExt); hf = fopen(pszFile, "wb"); if(!hf) break; - if(IsRaw){ - fwrite((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf); - fclose(hf); - return; + switch(iTextureFileFormat){ + + case FORMAT_RAW: + + if(fwrite((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + break; + + case FORMAT_DDS: { + + // no good for 8bpp textured bitmaps !!! + DDS_HEADER ddsh; + if(fwrite("DDS ", 4, 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + memset(&ddsh, 0, sizeof(ddsh)); + ddsh.dwSize = sizeof(ddsh); + ddsh.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH; + ddsh.dwHeight = ddsd.dwHeight; + ddsh.dwWidth = ddsd.dwWidth; + ddsh.ddspf.dwSize = sizeof(DDS_PIXELFORMAT); + ddsh.ddspf.dwFlags = DDPF_RGB; + ddsh.dwPitchOrLinearSize = (DWORD)ddsd.lPitch; + ddsh.ddspf.dwABitMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; + ddsh.ddspf.dwRBitMask = ddsd.ddpfPixelFormat.dwRBitMask; + ddsh.ddspf.dwGBitMask = ddsd.ddpfPixelFormat.dwGBitMask; + ddsh.ddspf.dwBBitMask = ddsd.ddpfPixelFormat.dwBBitMask; + ddsh.ddspf.dwRGBBitCount = ddsd.ddpfPixelFormat.dwRGBBitCount; + if(fwrite((BYTE *)&ddsh, sizeof(ddsh), 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + if(fwrite((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf)!=1) + OutTraceE("TextureHack: fwrite ERROR err=%d\n", GetLastError()); + } + break; + + case FORMAT_BMP: + + hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" + // Compute the size of the entire file. + hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbi.bV4Size + pbi.bV4ClrUsed * sizeof(RGBQUAD) + pbi.bV4SizeImage); + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + // Compute the offset to the array of color indices. + hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbi.bV4Size + pbi.bV4ClrUsed * sizeof (RGBQUAD); + + // Copy the BITMAPFILEHEADER into the .BMP file. + fwrite((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf); + + // Copy the BITMAPINFOHEADER array into the file. + fwrite((LPVOID)&pbi, sizeof(BITMAPV4HEADER), 1, hf); + + // Copy the RGBQUAD array into the file. + if(pbi.bV4ClrUsed){ + extern DWORD PaletteEntries[256]; + fwrite((LPVOID)PaletteEntries, pbi.bV4ClrUsed * sizeof (RGBQUAD), 1, hf); + } + + // Copy the array of color indices into the .BMP file. + for(int y=0; y<(int)ddsd.dwHeight; y++) + fwrite((BYTE *)ddsd.lpSurface + (y*ddsd.lPitch), iScanLineSize, 1, hf); + break; } - hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" - // Compute the size of the entire file. - hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbi.bV4Size + pbi.bV4ClrUsed * sizeof(RGBQUAD) + pbi.bV4SizeImage); - hdr.bfReserved1 = 0; - hdr.bfReserved2 = 0; - - // Compute the offset to the array of color indices. - hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbi.bV4Size + pbi.bV4ClrUsed * sizeof (RGBQUAD); - - // Copy the BITMAPFILEHEADER into the .BMP file. - fwrite((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf); - - // Copy the BITMAPINFOHEADER array into the file. - fwrite((LPVOID)&pbi, sizeof(BITMAPV4HEADER), 1, hf); - - // Copy the RGBQUAD array into the file. - if(pbi.bV4ClrUsed){ - extern DWORD PaletteEntries[256]; - fwrite((LPVOID)PaletteEntries, pbi.bV4ClrUsed * sizeof (RGBQUAD), 1, hf); - } - - // Copy the array of color indices into the .BMP file. - for(int y=0; y<(int)ddsd.dwHeight; y++) - fwrite((BYTE *)ddsd.lpSurface + (y*ddsd.lPitch), iScanLineSize, 1, hf); - // Close the .BMP file. fclose(hf); break; @@ -318,10 +365,27 @@ static void TextureDump(LPDIRECTDRAWSURFACE s, int dxversion) static void TextureHack(LPDIRECTDRAWSURFACE s, int dxversion) { + static BOOL DoOnce = TRUE; DDSURFACEDESC2 ddsd; int w, h, iSurfaceSize, iScanLineSize; HRESULT res; - BOOL IsRaw = (dxw.dwFlags8 & RAWFORMAT); + char *sExt; + static int iTextureFileFormat; + + if(DoOnce){ + //char sProfilePath[MAX_PATH]; + //sprintf(sProfilePath, "%s\\dxwnd.ini", GetDxWndPath()); + //MinTexX=GetPrivateProfileInt("Texture", "MinTexX", 0, sProfilePath); + //MaxTexX=GetPrivateProfileInt("Texture", "MaxTexX", 0, sProfilePath); + //MinTexY=GetPrivateProfileInt("Texture", "MinTexY", 0, sProfilePath); + //MaxTexY=GetPrivateProfileInt("Texture", "MaxTexY", 0, sProfilePath); + //sprintf_s(pszFile, MAX_PATH, "%s\\texture.in", GetDxWndPath()); + iTextureFileFormat = FORMAT_BMP; + if(dxw.dwFlags8 & RAWFORMAT) iTextureFileFormat = FORMAT_RAW; + if(dxw.dwFlags8 & DDSFORMAT) iTextureFileFormat = FORMAT_DDS; + //OutTrace("TextureHack: size min=(%dx%d) max=(%dx%d) format=%d\n", MinTexX, MinTexY, MaxTexX, MaxTexY, iTextureFileFormat); + OutTrace("TextureHack: format=%d\n", iTextureFileFormat); + } OutTraceB("TextureHack(%d): lpdds=%x\n", dxversion, s); @@ -351,61 +415,86 @@ static void TextureHack(LPDIRECTDRAWSURFACE s, int dxversion) if(!hash) break; // almost certainly, an empty black surface! // Look for the .BMP file. + switch (iTextureFileFormat){ + case FORMAT_BMP: sExt = "bmp"; break; + case FORMAT_RAW: sExt = "raw"; break; + case FORMAT_DDS: sExt = "dds"; break; + } sprintf_s(pszFile, MAX_PATH, "%s\\texture.in\\texture.%03d.%03d.%s.%08X.%s", - GetDxWndPath(), ddsd.dwWidth, ddsd.dwHeight, SurfaceType(ddsd.ddpfPixelFormat), - hash, IsRaw ? "raw" : "bmp"); + GetDxWndPath(), ddsd.dwWidth, ddsd.dwHeight, SurfaceType(ddsd.ddpfPixelFormat), hash, sExt); hf = fopen(pszFile, "rb"); if(!hf) break; // no updated texture to load OutTrace("TextureHack: IMPORT path=%s\n", pszFile); - if(IsRaw){ - fread((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf); - fclose(hf); - return; - } + switch(iTextureFileFormat){ - memset((void *)&pbi, 0, sizeof(BITMAPINFOHEADER)); - pbi.biSize = sizeof(BITMAPINFOHEADER); - pbi.biWidth = ddsd.dwWidth; - pbi.biHeight = ddsd.dwHeight; - pbi.biBitCount = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount; - pbi.biSizeImage = ((pbi.biWidth * pbi.biBitCount + 0x1F) & ~0x1F)/8 * pbi.biHeight; - iSizeImage = pbi.biSizeImage; - iScanLineSize = ((pbi.biWidth * pbi.biBitCount + 0x1F) & ~0x1F)/8; + case FORMAT_RAW: { - while(TRUE) { // fake loop to ensure final fclose - // Read the BITMAPFILEHEADER from the .BMP file (and throw away ...). - if(fread((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf) != 1)break; - - // Read the BITMAPINFOHEADER (and throw away ...). - // If the file contains BITMAPV4HEADER or BITMAPV5HEADER, no problem: next fseek will settle things - if(fread((LPVOID)&pbi, sizeof(BITMAPINFOHEADER), 1, hf) != 1) break; - - // skip the RGBQUAD array if the editor inserted one - fseek(hf, hdr.bfOffBits, SEEK_SET); - - // Read the new texture from the .BMP file. - if(pbi.biHeight < 0){ - // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention - for(int y=0; y<(int)ddsd.dwHeight; y++){ - BYTE *p = (BYTE *)ddsd.lpSurface + (ddsd.lPitch * y); - fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); - if(fread((LPVOID)p, ddsd.lPitch, 1, hf) != 1) break; + if(fread((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); } + break; + + case FORMAT_DDS: { + + BYTE magic[4]; + DDS_HEADER ddsh; + // assume the file is sane, read and throw away magic and dds header + if(fread(magic, 4, 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + if(fread((BYTE *)&ddsh, sizeof(ddsh), 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); + memset(&ddsh, 0, sizeof(ddsh)); + if(fread((BYTE *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight, 1, hf)!=1) + OutTraceE("TextureHack: fread ERROR err=%d\n", GetLastError()); } - else { - // biHeight > 0 -> scan lines from bottom to top, inverse order as surface/texture convention - for(int y=0; y<(int)ddsd.dwHeight; y++){ - BYTE *p = (BYTE *)ddsd.lpSurface + (ddsd.lPitch * ((ddsd.dwHeight-1) - y)); - fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); - if(fread((LPVOID)p, ddsd.lPitch, 1, hf) != 1) break; + break; + + case FORMAT_BMP: + + memset((void *)&pbi, 0, sizeof(BITMAPINFOHEADER)); + pbi.biSize = sizeof(BITMAPINFOHEADER); + pbi.biWidth = ddsd.dwWidth; + pbi.biHeight = ddsd.dwHeight; + pbi.biBitCount = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount; + pbi.biSizeImage = ((pbi.biWidth * pbi.biBitCount + 0x1F) & ~0x1F)/8 * pbi.biHeight; + iSizeImage = pbi.biSizeImage; + iScanLineSize = ((pbi.biWidth * pbi.biBitCount + 0x1F) & ~0x1F)/8; + + while(TRUE) { // fake loop to ensure final fclose + // Read the BITMAPFILEHEADER from the .BMP file (and throw away ...). + if(fread((LPVOID)&hdr, sizeof(BITMAPFILEHEADER), 1, hf) != 1)break; + + // Read the BITMAPINFOHEADER (and throw away ...). + // If the file contains BITMAPV4HEADER or BITMAPV5HEADER, no problem: next fseek will settle things + if(fread((LPVOID)&pbi, sizeof(BITMAPINFOHEADER), 1, hf) != 1) break; + + // skip the RGBQUAD array if the editor inserted one + fseek(hf, hdr.bfOffBits, SEEK_SET); + + // Read the new texture from the .BMP file. + if(pbi.biHeight < 0){ + // biHeight < 0 -> scan lines from top to bottom, same as surface/texture convention + for(int y=0; y<(int)ddsd.dwHeight; y++){ + BYTE *p = (BYTE *)ddsd.lpSurface + (ddsd.lPitch * y); + fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); + if(fread((LPVOID)p, ddsd.lPitch, 1, hf) != 1) break; + } + } + else { + // biHeight > 0 -> scan lines from bottom to top, inverse order as surface/texture convention + for(int y=0; y<(int)ddsd.dwHeight; y++){ + BYTE *p = (BYTE *)ddsd.lpSurface + (ddsd.lPitch * ((ddsd.dwHeight-1) - y)); + fseek(hf, hdr.bfOffBits + (iScanLineSize * y), SEEK_SET); + if(fread((LPVOID)p, ddsd.lPitch, 1, hf) != 1) break; + } + } + OutTrace("TextureHack: TEXTURE LOAD DONE\n"); + break; } - } - OutTrace("TextureHack: TEXTURE LOAD DONE\n"); break; } - // Close the .BMP file. fclose(hf); break; diff --git a/dll/dxdds.h b/dll/dxdds.h new file mode 100644 index 0000000..9549abd --- /dev/null +++ b/dll/dxdds.h @@ -0,0 +1,28 @@ +#ifndef DDS_HEADER +struct DDS_PIXELFORMAT { + DWORD dwSize; + DWORD dwFlags; + DWORD dwFourCC; + DWORD dwRGBBitCount; + DWORD dwRBitMask; + DWORD dwGBitMask; + DWORD dwBBitMask; + DWORD dwABitMask; +}; +typedef struct { + DWORD dwSize; + DWORD dwFlags; + DWORD dwHeight; + DWORD dwWidth; + DWORD dwPitchOrLinearSize; + DWORD dwDepth; + DWORD dwMipMapCount; + DWORD dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + DWORD dwCaps; + DWORD dwCaps2; + DWORD dwCaps3; + DWORD dwCaps4; + DWORD dwReserved2; +} DDS_HEADER; +#endif \ No newline at end of file diff --git a/dll/dxemublt.cpp b/dll/dxemublt.cpp index 2e1584f..e7359fb 100644 --- a/dll/dxemublt.cpp +++ b/dll/dxemublt.cpp @@ -1336,10 +1336,10 @@ static HRESULT WINAPI BilinearBlt_32_to_32(int dxversion, Blt_Type pBlt, LPDIREC Q5 = Melt32(*(src32+1), *(src32+ddsd_src.lPitch+1)); // to be used in next for cycle Q4 = Melt32(Q3, Q5); - *(dest) = (WORD)Q1; - *(dest+1) = (WORD)Q2; - *(dest+ddsd_dst.lPitch) = (WORD)Q3; - *(dest+ddsd_dst.lPitch+1) = (WORD)Q4; + *(dest) = Q1; + *(dest+1) = Q2; + *(dest+ddsd_dst.lPitch) = Q3; + *(dest+ddsd_dst.lPitch+1) = Q4; src32++; dest+=2; } @@ -1351,10 +1351,10 @@ static HRESULT WINAPI BilinearBlt_32_to_32(int dxversion, Blt_Type pBlt, LPDIREC Q1 = *(src32); Q2 = Melt32(Q1, *(src32+1)); - *(dest) = (WORD)Q1; - *(dest+1) = (WORD)Q2; - *(dest+ddsd_dst.lPitch) = (WORD)Q1; - *(dest+ddsd_dst.lPitch+1) = (WORD)Q2; + *(dest) = Q1; + *(dest+1) = Q2; + *(dest+ddsd_dst.lPitch) = Q1; + *(dest+ddsd_dst.lPitch+1) = Q2; src32++; dest+=2; } diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index 3378b3f..ab7c3be 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -27,7 +27,7 @@ along with this program. If not, see . #include "TlHelp32.h" -#define VERSION "2.03.40" +#define VERSION "2.03.40.fx2" #define DDTHREADLOCK 1 diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 64774c14869f67a07accfe91e3f9bb4325163055..79b90e61eddb7854122cec98bab9f9617acba03b 100644 GIT binary patch delta 11653 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 XzF + + diff --git a/host/TabDirect3D.cpp b/host/TabDirect3D.cpp index 663d255..016bf98 100644 --- a/host/TabDirect3D.cpp +++ b/host/TabDirect3D.cpp @@ -42,7 +42,7 @@ void CTabDirect3D::DoDataExchange(CDataExchange* pDX) // Texture management DDX_Radio(pDX, IDC_TEXTURENONE, cTarget->m_TextureHandling); - DDX_Check(pDX, IDC_RAWFORMAT, cTarget->m_RawFormat); + DDX_Radio(pDX, IDC_BMPFORMAT, cTarget->m_TextureFileFormat); // 3D Effects DDX_Check(pDX, IDC_NOTEXTURES, cTarget->m_NoTextures); diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index 7ae61d3..23baa78 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -61,7 +61,8 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_Enum16bitModes = FALSE; m_TrimTextureFormats = FALSE; m_NoHALDevice = FALSE; - m_RawFormat = FALSE; + //m_RawFormat = FALSE; + m_TextureFileFormat = 0; m_SetCompatibility = TRUE; // default true !! m_AEROBoost = TRUE; // default true !! m_DiabloTweak = FALSE; diff --git a/host/TargetDlg.h b/host/TargetDlg.h index 49e2651..fb81bc9 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -264,7 +264,7 @@ public: BOOL m_SuppressD3DExt; BOOL m_Enum16bitModes; BOOL m_TrimTextureFormats; - BOOL m_RawFormat; + //BOOL m_RawFormat; BOOL m_LimitScreenRes; BOOL m_InitialRes; BOOL m_MaximumRes; @@ -285,6 +285,7 @@ public: int m_SwapEffect; int m_ClipperMode; int m_ScanLine; + int m_TextureFileFormat; //}}AFX_DATA diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index 63805106230ecf6f5c9dd9dc57deecb7efead0c9..f846f7086d83bdd62d461f8012079c914d40d9ef 100644 GIT binary patch delta 6988 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 delta 29488 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 L9`leZbmRX6*HgnC diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index 5d44bb4e0395d5c40632abc3843321fecc476fd3..7a2691f7bc62868bf65ffd22c9949a3f53ccae89 100644 GIT binary patch delta 350 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 Vb;}uiplUgTc;>JECt9qYKLc}b)Up5o delta 3326 zcmcgvdr*|u75~oew;vy{>@Mqq3obj0S}8bjes%6 zW)^F!d6WT<@pKYRNa{ewcC2Beq@6LY(MgC+Dq32dO#h&dq#4^$CTe^`&;5YaX4;v~ zbf$Oae0%S?uXE4&o!`A1IiC=DE1}B|iEjrI^zb|`)>q171Y#5rDvrJj5Rif`Ii@-ASLEGlqL)X9Y#&6br zp1bv01$L<3s9)9V6fp35M*LISH0nG6c5F)u8r-Z>?y9b^ip>~Lh^wM)$)|OALN3HM zQxH#1_u>^(&>-`)#P}HHI!MyffLqLLsa$BVa<7WnmSXfFRL!@OdQc;d4aov$J4uaI@>3%t8s zPrpu=B#wPZCoz_^QugFu1VXjqY7uo^ye<99W^?JwRw$*B0Jt!6$r%0fs8hek20q%} z4n;I%gDUdbpqZ`7BbOV>F*0K#ji!N|S}%p9a;c8Lo293v^->7OuYRIVofC(@aydlf z7=unYWvZOu_U~A_n<}EquDv7UuF(Q&$pJUL?}ldj^hL;}h?}>qPGP(1hq>A42h~u= zhpESoyh=){GRSQC17x;vEV|xd z3K_cNrrrS53g5w_6iDF?*K#)8cbIJnwu6(rAAy^#F{gotMmxcQu092WnVHZqWw`@` zH*EB-n5G4MXk9wY&^E!Et9A;9p;qkXpdmBZp#`oNDDJ11q!F1Ul*ugO_-=o80ZtC|p&sf0l@e zM)E+##xYr6E3Fy0l>-YCbzbHk=9bcea?Gl54a7VUG6_$44I(p|89pVn$p@wKQf{Ju zb|a%JyL~d4n$<907&VWad%25&qrxgWs=_l+CtR?A#&)ue-=(9)uz`|{FxXoKNp#i- z6&j^bXA0ZB-2%(V{~*}Op91nkL^ymR%1{>PpE)#I2_{%c9Ts@Bw}vBLX5|)#r~v(= zehQ}X%Hd(iB=*A+cj$E(_H$KT{`5F~cUJiu*SNif!B5Z&WRwcu9v6q$yciC(uolW74WsGIg zbNl$jv0*k(kb+??pQ8?sf4P);+W1zh>E~XT%HWIKPM;(kPM8Wvf`@5EKRhK8)4CfR z1CB2EtDZTyj828X0YQzzL=KCqk1?V`p61O-wzE>u4GLe5f^=Eu#Nd1@r;E5S1$j+y z6nPJWoVa=_mKey*9&qgemyFhOJB?L>cZ!!)_&032jI6DE`NU607hZ*QstSOgx;BE7 zbB!6W9qO>-kp(!m&tOC-^ zy>D{>&kk~g*)K&?p3B6p%jvLCU~jpg@!1opJV~xvaysuKd#J_A$7jnXxLI5c93770 zTymu{_ljo()X;+0VS{0f7OsxK3hXK}K^mo=gJ%W9IVo}kTmvrt==r8G$Con+UTCHZ zzhXzcxtqB=_z}qW-YU>S$4@ef`FTPYf6Wkhe~^jl|9ZthH3ejtMHhNt=fL`7@M!|* z;?Fc{`w&(r(o1}Bb6lC6%&(G-tl~m}cF5P_OO|td0mb=VFsV(WV%q-)sKKPQPCY-Q zvGUFNO3uX8nh<0Le#R6pSl-04f3n^;`77v9)I~YSzk)C)T6e!;@%E}batdM!#lAK9 tlE9wJioE#Dtsxvqvkg?7foi~=Y8n3*F~*-d;=x*lU8rD1 diff --git a/host/dxwndhostView.cpp b/host/dxwndhostView.cpp index 6721961..6448de3 100644 --- a/host/dxwndhostView.cpp +++ b/host/dxwndhostView.cpp @@ -338,6 +338,12 @@ void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) case 2: t->flags |= SUPPRESSCLIPPING; break; } + switch(dlg->m_TextureFileFormat){ + case 0: break; + case 1: t->flags8 |= RAWFORMAT; break; + case 2: t->flags8 |= DDSFORMAT; break; + } + if(dlg->m_HookDI) t->flags |= HOOKDI; if(dlg->m_HookDI8) t->flags |= HOOKDI8; if(dlg->m_EmulateRelMouse) t->flags6 |= EMULATERELMOUSE; @@ -384,7 +390,6 @@ void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_SuppressD3DExt) t->flags3 |= SUPPRESSD3DEXT; if(dlg->m_Enum16bitModes) t->flags7 |= ENUM16BITMODES; if(dlg->m_TrimTextureFormats) t->flags8 |= TRIMTEXTUREFORMATS; - if(dlg->m_RawFormat) t->flags8 |= RAWFORMAT; if(dlg->m_SetCompatibility) t->flags2 |= SETCOMPATIBILITY; if(dlg->m_AEROBoost) t->flags5 |= AEROBOOST; if(dlg->m_DiabloTweak) t->flags5 |= DIABLOTWEAK; @@ -647,6 +652,10 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) if (t->flags3 & FORCECLIPPER) dlg->m_ClipperMode = 1; if (t->flags & SUPPRESSCLIPPING) dlg->m_ClipperMode = 2; + dlg->m_TextureFileFormat = 0; + if( t->flags8 & RAWFORMAT) dlg->m_TextureFileFormat = 1; + if( t->flags8 & DDSFORMAT) dlg->m_TextureFileFormat = 2; + dlg->m_HookDI = t->flags & HOOKDI ? 1 : 0; dlg->m_HookDI8 = t->flags & HOOKDI8 ? 1 : 0; dlg->m_EmulateRelMouse = t->flags6 & EMULATERELMOUSE ? 1 : 0; @@ -674,7 +683,6 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_SuppressD3DExt = t->flags3 & SUPPRESSD3DEXT ? 1 : 0; dlg->m_Enum16bitModes = t->flags7 & ENUM16BITMODES ? 1 : 0; dlg->m_TrimTextureFormats = t->flags8 & TRIMTEXTUREFORMATS ? 1 : 0; - dlg->m_RawFormat = t->flags8 & RAWFORMAT ? 1 : 0; dlg->m_SetCompatibility = t->flags2 & SETCOMPATIBILITY ? 1 : 0; dlg->m_AEROBoost = t->flags5 & AEROBOOST ? 1 : 0; dlg->m_DiabloTweak = t->flags5 & DIABLOTWEAK ? 1 : 0; diff --git a/host/host.aps b/host/host.aps index 66fef52595f861b316bf6437e9f6fc1353897bf9..fbddba3524b51c9749d1477871a39d0eb7a2811b 100644 GIT binary patch delta 577 zcmW;IF=&%P7>Ds(sL}KnI5>3Z z(UyPd?BLMBi>XF!HV20e9ymC3aCC6_K+(a$!6$*^HyrQqyzk-f>OODQ)DN!C)z12r zO6zv9{OG|(tJYfUt+h8hMekO#vCwQZn%i5e#ro!UcS3Dz^`!T>Z|eHhzhRCKp4Klc zm`df3^4FPJk;fSYe5i;+CEQVopJfM`nUzE4aZw(36_9y+sf2%3BJ(GixhRJXfRE|I7aY+F?iug$h>BqaW@5XHozbeORc`OugUlG46AwAfZeLvp9A@{*~ zd3>UP14W!t!bO#MNA^Qz4&|_|9KXn8R{=jNVoM3zDsf)+G&9%b@K`xslE-fflm9p| gVMis-$d1OBaih8FzdhX_U90XKY2)a!c1P3y0ltCZ)c^nh delta 656 zcmXBRKS&!<90&0C9=(#oB4S0tHRL54h}S=<#w->G1(6;U=}_n*Xd#vc#HLgvZXG)G zKuW^bp;M<09!N~|)C7uChaO1j(4m7!#|GLicIY6|Z+y#V_6TyMTyugg4s*RyiFwtm+t zNFn~g+tKQQLQXl>kPspTe@DwA0@^~vaKpli}uh279H1DA5Lq19vz$(Un>oUFoU znUi!25ySHyoc5SwIoZ^504^=SqcN14{Bj?1ea_YH{Bl3$`c3x~B6hq+hkk&)t7Qf5 zu2vrh@qW;BpTuz#H{A{R?D&g--bci~L;@E#%#{~m?`avrrElQvX?2`LJ?U5jW?7aW zA)vf6!;>_Q(k2{*9d`F|X$xMc)vpY`WK1{(pXF5q^fMxc=UJR)P52P@e)sw={SI$m zt82IL=cWl4;j_Gnfc`|pFp9TS#eA9PoCDIfSitJ`Df9W&u8_$-GAXbcg<$pVrE z?#WeVU>|Dv4lXUjqu)@X75MZM0{RRQEu(YDbEnZe?N~)6#0cD$R@<|9JL_0mSA>Y8 k)Y9??d^&>Q(ul62LsPKZ-M4hx!-_wBu013-@S?5%149zkI{*Lx diff --git a/host/resource b/host/resource index b14d3a8457fa9a84e67f0f521ea9c664ff25d8d7..9aed96258ef34546a2ab784e16cf9e4682b5cda0 100644 GIT binary patch delta 92 zcmX>#ow;cy^M<^+lj}^_CSRCqF?r2gIesSwUxok%HwJ%(ARx