Complex Surfaces patch
Marius Grigoriu <[email protected]> Mon, 09 Aug 2004 21:13:14 -0400
| Newsgroups | gmane.comp.emulators.winex.devel |
|---|---|
| Message-ID | <[email protected]> |
With this patch, Anarchy Online seems to work 100%, thout it is a bit slow when there is more geometry, but i'll blame ATI for now. AO creates complex surfaces for its mipmaps, but does not set dwMipMapCount. Before the patch, the additional surfaces are not created causing the game to crash when it loads an outdoor zone because it expects a certain number of surfaces in the chain. In newer documentation, it states that DDSCAPS_COMPLEX is used to create a chain of surfaces during the CreateSurface call. According to DX3 documentation, "It is permissible to omit the number of mipmaps levels, in which case CreateSurface() will create a chain of surfaces each a power of two smaller than the previous one down to the smallest possible size." Using a test app shows that it is still true in DX7. A 128x128 sized surface creates a chain of 8 surfaces (7 mipmaps + original surface). The attached patch doesn't quite do this (because of a problem) but comes close. According to the test app the length of a chain is based on the largest dimension of the first surface. 128x64 -> 8 total surfaces, 64x64 -> 7 total surfaces. Initially, I set the mipmap count dynamically to behave like this. Thought it worked properly in the test app--which just creates the surface and counts attached surfaces then quits--the game seems to deadlock at a later point if there are more than 6 attached surfaces, so I limit the total chain length to 7. You can see this in the patch. I hope that this patch is approved. It's exciting to see that I've been able to bring this game such a far way, to the point where it can actually be played. Marius Grigoriu
complex_mipmap.patch
(text/x-patch, 1.6 KB)
? complex_mipmap.patch
Index: main.c
===================================================================
RCS file: /cvsroot/winex/dlls/ddraw/ddraw/main.c,v
retrieving revision 1.77
diff -r1.77 main.c
325a326,347
> DWORD max;
> DDSURFACEDESC2 mipmap_surface_desc;
>
> mipmap_surface_desc = *pDDSD;
>
> /* A somewhat undocumented feature, if DDSCAPS_COMPLEX is set,
> * "It is permissible to omit the number of mipmaps levels, in which case
> * CreateSurface() will create a chain of surfaces each a power of two
> * smaller than the previous one down to the smallest possible size."
> */
> if(!(mipmap_surface_desc.dwFlags & DDSD_MIPMAPCOUNT) &&
> (mipmap_surface_desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX) &&
> (mipmap_surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)){
> DDRAW_dump_surface_desc(pDDSD);
> max = (mipmap_surface_desc.dwWidth > mipmap_surface_desc.dwHeight) ?
> mipmap_surface_desc.dwWidth : mipmap_surface_desc.dwHeight;
> /* FIXME: Adding more than 6 surfaces seems to break things, regardless
> * of original size so we deviate a little from what windows does
> */
> mipmap_surface_desc.u2.dwMipMapCount = 7;//log(max)/log(2) + 2;
> mipmap_surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
> }
327c349
< hr = This->create_texture(This, pDDSD, ppSurf, pUnkOuter, mipmap_level);
---
> hr = This->create_texture(This, &mipmap_surface_desc, ppSurf, pUnkOuter, mipmap_level);
331c353
< if (more_mipmaps(pDDSD))
---
> if (more_mipmaps(&mipmap_surface_desc))
335d356
< DDSURFACEDESC2 mipmap_surface_desc;
339d359
< mipmap_surface_desc = *pDDSD;