From 806746d364a8a1f56fa36bdb3d61b675994dbf82 Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Wed, 14 Nov 2018 05:35:59 +0100 Subject: [PATCH] experimental 16bit color support (Dune 2000) --- inc/openglshader.h | 23 ++++ src/debug.c | 4 +- src/main.c | 18 ++- src/render.c | 223 +++++++++++++++++++------------ src/render_d3d9.c | 56 ++++++-- src/render_soft.c | 2 +- src/surface.c | 325 ++++++++++++++++++++++++++++++++------------- 7 files changed, 451 insertions(+), 200 deletions(-) diff --git a/inc/openglshader.h b/inc/openglshader.h index dad8f24..3edd3a6 100644 --- a/inc/openglshader.h +++ b/inc/openglshader.h @@ -23,6 +23,17 @@ const char PaletteFragShader110Src[] = "}\n"; +const char PassthroughFragShader110Src[] = + "#version 110\n" + "uniform sampler2D SurfaceTex; \n" + "varying vec2 TEX0; \n" + "\n" + "void main()\n" + "{\n" + " vec4 texel = texture2D(SurfaceTex, TEX0); \n" + " gl_FragColor = texel; \n" + "}\n"; + // new const char PassthroughVertShaderSrc[] = @@ -55,3 +66,15 @@ const char PaletteFragShaderSrc[] = " FragColor = texture(PaletteTex, vec2(pIndex.r * (255.0/256.0) + (0.5/256.0), 0));\n" "}\n"; + +const char PassthroughFragShaderSrc[] = + "#version 130\n" + "out vec4 FragColor;\n" + "uniform sampler2D SurfaceTex;\n" + "in vec4 TEX0;\n" + "\n" + "void main()\n" + "{\n" + " vec4 texel = texture(SurfaceTex, TEX0.xy);\n" + " FragColor = texel;\n" + "}\n"; diff --git a/src/debug.c b/src/debug.c index c27644d..f43b7aa 100644 --- a/src/debug.c +++ b/src/debug.c @@ -42,9 +42,9 @@ void DrawFrameInfoStart() RECT debugrc = { 0, 0, ddraw->width, ddraw->height }; - if (ddraw->primary && ddraw->primary->palette) + if (ddraw->primary) { - if (ddraw->primary->palette->data_rgb) + if (ddraw->primary->palette && ddraw->primary->palette->data_rgb) SetDIBColorTable(ddraw->primary->hDC, 0, 256, ddraw->primary->palette->data_rgb); DrawText(ddraw->primary->hDC, debugText, -1, &debugrc, DT_NOCLIP); diff --git a/src/main.c b/src/main.c index 550a369..19ed80e 100644 --- a/src/main.c +++ b/src/main.c @@ -215,6 +215,18 @@ HRESULT __stdcall ddraw_EnumDisplayModes(IDirectDrawImpl *This, DWORD dwFlags, L printf(" DDENUMRET_CANCEL returned, stopping\n"); break; } + + s.ddpfPixelFormat.dwFlags = DDPF_RGB; + s.ddpfPixelFormat.dwRGBBitCount = 16; + s.ddpfPixelFormat.dwRBitMask = 0xF800; + s.ddpfPixelFormat.dwGBitMask = 0x07E0; + s.ddpfPixelFormat.dwBBitMask = 0x001F; + + if (lpEnumModesCallback(&s, lpContext) == DDENUMRET_CANCEL) + { + printf(" DDENUMRET_CANCEL returned, stopping\n"); + break; + } } /* Some games crash when you feed them with too many resolutions... @@ -384,7 +396,7 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD { printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp); - if (bpp != 8) + if (bpp != 8 && bpp != 16) return DDERR_INVALIDMODE; if (This->render.thread) @@ -660,7 +672,7 @@ void ToggleFullscreen() WindowState = ddraw->windowed = FALSE; SetWindowLong(ddraw->hWnd, GWL_STYLE, GetWindowLong(ddraw->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU)); ddraw->altenter = TRUE; - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, 8); + ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); mouse_lock(); } else @@ -673,7 +685,7 @@ void ToggleFullscreen() else ChangeDisplaySettings(&ddraw->mode, 0); - ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, 8); + ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp); mouse_lock(); } } diff --git a/src/render.c b/src/render.c index 1390ab5..886ea2e 100644 --- a/src/render.c +++ b/src/render.c @@ -27,13 +27,14 @@ static HGLRC OpenGLContext; static int MaxFPS; static DWORD FrameLength; -static GLuint PaletteProgram; +static GLuint MainProgram; static GLuint ScaleProgram; static BOOL GotError; static int SurfaceTexWidth; static int SurfaceTexHeight; static int *SurfaceTex; static GLenum SurfaceFormat = GL_LUMINANCE; +static GLenum SurfaceType = GL_UNSIGNED_BYTE; static GLuint SurfaceTexIds[TEXTURE_COUNT]; static GLuint PaletteTexIds[TEXTURE_COUNT]; static float ScaleW; @@ -52,7 +53,7 @@ static HGLRC CreateContext(HDC hdc); static void SetMaxFPS(int baseMaxFPS); static void BuildPrograms(); static void CreateTextures(int width, int height); -static void InitPaletteProgram(); +static void InitMainProgram(); static void InitScaleProgram(); static void Render(); static void DeleteContext(HGLRC context); @@ -71,13 +72,13 @@ DWORD WINAPI render_main(void) SetMaxFPS(ddraw->render.maxfps); BuildPrograms(); CreateTextures(ddraw->width, ddraw->height); - InitPaletteProgram(); + InitMainProgram(); InitScaleProgram(); GotError = GotError || !TextureUploadTest(); GotError = GotError || !ShaderTest(); GotError = GotError || glGetError() != GL_NO_ERROR; - UseOpenGL = PaletteProgram && !GotError; + UseOpenGL = MainProgram && !GotError; Render(); @@ -156,21 +157,27 @@ static void SetMaxFPS(int baseMaxFPS) static void BuildPrograms() { - PaletteProgram = ScaleProgram = 0; + MainProgram = ScaleProgram = 0; if (OpenGL_GotVersion3) { - PaletteProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc); + if (ddraw->bpp == 8) + MainProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc); + else if (ddraw->bpp == 16) + MainProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PassthroughFragShaderSrc); - if (PaletteProgram) + if (MainProgram) ScaleProgram = OpenGL_BuildProgramFromFile(ddraw->shader); else OpenGL_GotVersion3 = FALSE; } - if (OpenGL_GotVersion2 && !PaletteProgram) + if (OpenGL_GotVersion2 && !MainProgram) { - PaletteProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PaletteFragShader110Src); + if (ddraw->bpp == 8) + MainProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PaletteFragShader110Src); + else if (ddraw->bpp == 16) + MainProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PassthroughFragShader110Src); } } @@ -202,74 +209,110 @@ static void CreateTextures(int width, int height) while (glGetError() != GL_NO_ERROR); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_LUMINANCE8, - SurfaceTexWidth, - SurfaceTexHeight, - 0, - SurfaceFormat = GL_LUMINANCE, - GL_UNSIGNED_BYTE, - 0); - - - if (glGetError() != GL_NO_ERROR) + if (ddraw->bpp == 16) { glTexImage2D( GL_TEXTURE_2D, 0, - GL_R8, + GL_RGB565, SurfaceTexWidth, SurfaceTexHeight, 0, - SurfaceFormat = GL_RED, - GL_UNSIGNED_BYTE, + SurfaceFormat = GL_RGB, + SurfaceType = GL_UNSIGNED_SHORT_5_6_5, 0); + + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB5, + SurfaceTexWidth, + SurfaceTexHeight, + 0, + SurfaceFormat = GL_RGB, + SurfaceType = GL_UNSIGNED_SHORT_5_6_5, + 0); + } } - - if (glGetError() != GL_NO_ERROR) + else if (ddraw->bpp == 8) { glTexImage2D( GL_TEXTURE_2D, 0, - GL_RED, + GL_LUMINANCE8, SurfaceTexWidth, SurfaceTexHeight, 0, - SurfaceFormat = GL_RED, - GL_UNSIGNED_BYTE, + SurfaceFormat = GL_LUMINANCE, + SurfaceType = GL_UNSIGNED_BYTE, 0); + + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_R8, + SurfaceTexWidth, + SurfaceTexHeight, + 0, + SurfaceFormat = GL_RED, + SurfaceType = GL_UNSIGNED_BYTE, + 0); + } + + if (glGetError() != GL_NO_ERROR) + { + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RED, + SurfaceTexWidth, + SurfaceTexHeight, + 0, + SurfaceFormat = GL_RED, + SurfaceType = GL_UNSIGNED_BYTE, + 0); + } } } - glGenTextures(TEXTURE_COUNT, PaletteTexIds); - - for (i = 0; i < TEXTURE_COUNT; i++) + if (ddraw->bpp == 8) { - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glGenTextures(TEXTURE_COUNT, PaletteTexIds); + + for (i = 0; i < TEXTURE_COUNT; i++) + { + glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } } } -static void InitPaletteProgram() +static void InitMainProgram() { - if (!PaletteProgram) + if (!MainProgram) return; - glUseProgram(PaletteProgram); + glUseProgram(MainProgram); - glUniform1i(glGetUniformLocation(PaletteProgram, "SurfaceTex"), 0); - glUniform1i(glGetUniformLocation(PaletteProgram, "PaletteTex"), 1); + glUniform1i(glGetUniformLocation(MainProgram, "SurfaceTex"), 0); + + if (ddraw->bpp == 8) + glUniform1i(glGetUniformLocation(MainProgram, "PaletteTex"), 1); if (OpenGL_GotVersion3) { - MainVertexCoordAttrLoc = glGetAttribLocation(PaletteProgram, "VertexCoord"); - MainTexCoordAttrLoc = glGetAttribLocation(PaletteProgram, "TexCoord"); + MainVertexCoordAttrLoc = glGetAttribLocation(MainProgram, "VertexCoord"); + MainTexCoordAttrLoc = glGetAttribLocation(MainProgram, "TexCoord"); glGenBuffers(3, MainVBOs); @@ -347,7 +390,7 @@ static void InitPaletteProgram() 0,0,1,0, 0,0,0,1, }; - glUniformMatrix4fv(glGetUniformLocation(PaletteProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix); + glUniformMatrix4fv(glGetUniformLocation(MainProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix); } } @@ -463,7 +506,7 @@ static void InitScaleProgram() if (glDeleteVertexArrays) glDeleteVertexArrays(1, &ScaleVAO); - if (PaletteProgram) + if (MainProgram) { glBindVertexArray(MainVAO); glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[0]); @@ -507,8 +550,8 @@ static void Render() ddraw->render.viewport.x, ddraw->render.viewport.y, ddraw->render.viewport.width, ddraw->render.viewport.height); - if (PaletteProgram) - glUseProgram(PaletteProgram); + if (MainProgram) + glUseProgram(MainProgram); while (UseOpenGL && ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED) { @@ -528,7 +571,7 @@ static void Render() EnterCriticalSection(&ddraw->cs); - if (ddraw->primary && ddraw->primary->palette) + if (ddraw->primary && (ddraw->bpp == 16 || ddraw->primary->palette)) { if (ddraw->vhack) { @@ -547,7 +590,7 @@ static void Render() } } - if (InterlockedExchange(&ddraw->render.paletteUpdated, FALSE)) + if (ddraw->bpp == 8 && InterlockedExchange(&ddraw->render.paletteUpdated, FALSE)) { if (++palIndex >= TEXTURE_COUNT) palIndex = 0; @@ -584,7 +627,7 @@ static void Render() ddraw->width, ddraw->height, SurfaceFormat, - GL_UNSIGNED_BYTE, + SurfaceType, ddraw->primary->surface); if (AdjustAlignment) @@ -605,7 +648,7 @@ static void Render() if (scaleChanged) { - if (ScaleProgram && PaletteProgram) + if (ScaleProgram && MainProgram) { glBindVertexArray(MainVAO); glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); @@ -621,7 +664,7 @@ static void Render() glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - else if (OpenGL_GotVersion3 && PaletteProgram) + else if (OpenGL_GotVersion3 && MainProgram) { glBindVertexArray(MainVAO); glBindBuffer(GL_ARRAY_BUFFER, MainVBOs[1]); @@ -642,15 +685,18 @@ static void Render() glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, SurfaceTexIds[texIndex]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[palIndex]); + if (ddraw->bpp == 8) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, PaletteTexIds[palIndex]); + } glActiveTexture(GL_TEXTURE0); - if (ScaleProgram && PaletteProgram) + if (ScaleProgram && MainProgram) { // draw surface into framebuffer - glUseProgram(PaletteProgram); + glUseProgram(MainProgram); glViewport(0, 0, ddraw->width, ddraw->height); @@ -683,7 +729,7 @@ static void Render() glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); glBindVertexArray(0); } - else if (OpenGL_GotVersion3 && PaletteProgram) + else if (OpenGL_GotVersion3 && MainProgram) { glBindVertexArray(MainVAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); @@ -719,7 +765,9 @@ static void DeleteContext(HGLRC context) { HeapFree(GetProcessHeap(), 0, SurfaceTex); glDeleteTextures(TEXTURE_COUNT, SurfaceTexIds); - glDeleteTextures(TEXTURE_COUNT, PaletteTexIds); + + if (ddraw->bpp == 8) + glDeleteTextures(TEXTURE_COUNT, PaletteTexIds); if (glUseProgram) glUseProgram(0); @@ -740,8 +788,8 @@ static void DeleteContext(HGLRC context) if (glDeleteProgram) { - if (PaletteProgram) - glDeleteProgram(PaletteProgram); + if (MainProgram) + glDeleteProgram(MainProgram); if (ScaleProgram) glDeleteProgram(ScaleProgram); @@ -749,7 +797,7 @@ static void DeleteContext(HGLRC context) if (OpenGL_GotVersion3) { - if (PaletteProgram) + if (MainProgram) { if (glDeleteBuffers) glDeleteBuffers(3, MainVBOs); @@ -782,40 +830,42 @@ static BOOL TextureUploadTest() ddraw->width, ddraw->height, SurfaceFormat, - GL_UNSIGNED_BYTE, + SurfaceType, SurfaceTex); memset(SurfaceTex, 0, sizeof(testData)); - glGetTexImage(GL_TEXTURE_2D, 0, SurfaceFormat, GL_UNSIGNED_BYTE, SurfaceTex); + glGetTexImage(GL_TEXTURE_2D, 0, SurfaceFormat, SurfaceType, SurfaceTex); if (memcmp(SurfaceTex, testData, sizeof(testData)) != 0) return FALSE; } - for (i = 0; i < TEXTURE_COUNT; i++) + if (ddraw->bpp == 8) { - glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); + for (i = 0; i < TEXTURE_COUNT; i++) + { + glBindTexture(GL_TEXTURE_2D, PaletteTexIds[i]); - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - 0, - 0, - 256, - 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - SurfaceTex); + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + 256, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + SurfaceTex); - memset(SurfaceTex, 0, sizeof(testData)); + memset(SurfaceTex, 0, sizeof(testData)); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, SurfaceTex); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, SurfaceTex); - if (memcmp(SurfaceTex, testData, sizeof(testData)) != 0) - return FALSE; + if (memcmp(SurfaceTex, testData, sizeof(testData)) != 0) + return FALSE; + } } - return TRUE; } @@ -823,7 +873,10 @@ static BOOL ShaderTest() { BOOL result = TRUE; - if (OpenGL_GotVersion3 && PaletteProgram) + if (ddraw->bpp != 8) + return result; + + if (OpenGL_GotVersion3 && MainProgram) { memset(SurfaceTex, 0, SurfaceTexHeight * SurfaceTexWidth * sizeof(int)); @@ -876,7 +929,7 @@ static BOOL ShaderTest() glViewport(0, 0, SurfaceTexWidth, SurfaceTexHeight); - glUseProgram(PaletteProgram); + glUseProgram(MainProgram); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, PaletteTexIds[0]); diff --git a/src/render_d3d9.c b/src/render_d3d9.c index ade50ed..7dbd53e 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -176,20 +176,44 @@ static BOOL CreateResources() for (i = 0; i < TEXTURE_COUNT; i++) { err = err || FAILED( - IDirect3DDevice9_CreateTexture(D3dDev, texWidth, texHeight, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &SurfaceTex[i], 0)); + IDirect3DDevice9_CreateTexture( + D3dDev, + texWidth, + texHeight, + 1, + 0, + ddraw->bpp == 16 ? D3DFMT_R5G6B5 : D3DFMT_L8, + D3DPOOL_MANAGED, + &SurfaceTex[i], + 0)); err = err || !SurfaceTex[i]; - err = err || FAILED( - IDirect3DDevice9_CreateTexture(D3dDev, 256, 256, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &PaletteTex[i], 0)); - - err = err || !PaletteTex[i]; + if (ddraw->bpp == 8) + { + err = err || FAILED( + IDirect3DDevice9_CreateTexture( + D3dDev, + 256, + 256, + 1, + 0, + D3DFMT_X8R8G8B8, + D3DPOOL_MANAGED, + &PaletteTex[i], + 0)); + + err = err || !PaletteTex[i]; + } } - err = err || FAILED( - IDirect3DDevice9_CreatePixelShader(D3dDev, (DWORD *)PalettePixelShaderSrc, &PixelShader)); + if (ddraw->bpp == 8) + { + err = err || FAILED( + IDirect3DDevice9_CreatePixelShader(D3dDev, (DWORD *)PalettePixelShaderSrc, &PixelShader)); + } - return VertexBuf && PixelShader && !err; + return VertexBuf && (PixelShader || ddraw->bpp == 16) && !err; } static BOOL SetStates() @@ -199,8 +223,12 @@ static BOOL SetStates() err = err || FAILED(IDirect3DDevice9_SetFVF(D3dDev, D3DFVF_XYZRHW | D3DFVF_TEX1)); err = err || FAILED(IDirect3DDevice9_SetStreamSource(D3dDev, 0, VertexBuf, 0, sizeof(CUSTOMVERTEX))); err = err || FAILED(IDirect3DDevice9_SetTexture(D3dDev, 0, (IDirect3DBaseTexture9 *)SurfaceTex[0])); - err = err || FAILED(IDirect3DDevice9_SetTexture(D3dDev, 1, (IDirect3DBaseTexture9 *)PaletteTex[0])); - err = err || FAILED(IDirect3DDevice9_SetPixelShader(D3dDev, PixelShader)); + + if (ddraw->bpp == 8) + { + err = err || FAILED(IDirect3DDevice9_SetTexture(D3dDev, 1, (IDirect3DBaseTexture9 *)PaletteTex[0])); + err = err || FAILED(IDirect3DDevice9_SetPixelShader(D3dDev, PixelShader)); + } D3DVIEWPORT9 viewData = { ddraw->render.viewport.x, @@ -288,7 +316,7 @@ DWORD WINAPI render_d3d9_main(void) EnterCriticalSection(&ddraw->cs); - if (ddraw->primary && ddraw->primary->palette && ddraw->primary->palette->data_rgb) + if (ddraw->primary && (ddraw->bpp == 16 || (ddraw->primary->palette && ddraw->primary->palette->data_rgb))) { if (ddraw->vhack) { @@ -322,9 +350,9 @@ DWORD WINAPI render_d3d9_main(void) int i; for (i = 0; i < ddraw->height; i++) { - memcpy(dst, src, ddraw->width); + memcpy(dst, src, ddraw->width * ddraw->primary->lXPitch); - src += ddraw->width; + src += ddraw->primary->lPitch; dst += lock_rc.Pitch; } @@ -332,7 +360,7 @@ DWORD WINAPI render_d3d9_main(void) } } - if (InterlockedExchange(&ddraw->render.paletteUpdated, FALSE)) + if (ddraw->bpp == 8 && InterlockedExchange(&ddraw->render.paletteUpdated, FALSE)) { if (++palIndex >= TEXTURE_COUNT) palIndex = 0; diff --git a/src/render_soft.c b/src/render_soft.c index 087477d..dfe0dcf 100644 --- a/src/render_soft.c +++ b/src/render_soft.c @@ -48,7 +48,7 @@ DWORD WINAPI render_soft_main(void) EnterCriticalSection(&ddraw->cs); - if (ddraw->primary && ddraw->primary->palette && ddraw->primary->palette->data_rgb) + if (ddraw->primary && (ddraw->bpp == 16 || (ddraw->primary->palette && ddraw->primary->palette->data_rgb))) { if (warningText[0]) { diff --git a/src/surface.c b/src/surface.c index fe623c8..83ea4d0 100644 --- a/src/surface.c +++ b/src/surface.c @@ -109,21 +109,68 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR } #endif + RECT srcRect = { 0, 0, Source ? Source->width : 0, Source ? Source->height : 0 }; + RECT dstRect = { 0, 0, This->width, This->height }; + + if (lpSrcRect && Source) + { + memcpy(&srcRect, lpSrcRect, sizeof(srcRect)); + + if (srcRect.right > Source->width) + srcRect.right = Source->width; + + if (srcRect.bottom > Source->height) + srcRect.bottom = Source->height; + } + + if (lpDestRect) + { + memcpy(&dstRect, lpDestRect, sizeof(dstRect)); + + if (dstRect.right > This->width) + dstRect.right = This->width; + + if (dstRect.bottom > This->height) + dstRect.bottom = This->height; + } + + int src_w = srcRect.right - srcRect.left; + int src_h = srcRect.bottom - srcRect.top; + int src_x = srcRect.left; + int src_y = srcRect.top; + + int dst_w = dstRect.right - dstRect.left; + int dst_h = dstRect.bottom - dstRect.top; + int dst_x = dstRect.left; + int dst_y = dstRect.top; + + if (This->surface && (dwFlags & DDBLT_COLORFILL)) { - int dst_w = lpDestRect ? lpDestRect->right - lpDestRect->left : This->width; - int dst_h = lpDestRect ? lpDestRect->bottom - lpDestRect->top : This->height; - int dst_x = lpDestRect ? lpDestRect->left : 0; - int dst_y = lpDestRect ? lpDestRect->top : 0; - - int y, x; - for (y = 0; y < dst_h; y++) + if (This->bpp == 8) { - int ydst = This->width * (y + dst_y); - - for (x = 0; x < dst_w; x++) + int y, x; + for (y = 0; y < dst_h; y++) { - ((unsigned char *)This->surface)[x + dst_x + ydst] = lpDDBltFx->dwFillColor; + int ydst = This->width * (y + dst_y); + + for (x = 0; x < dst_w; x++) + { + ((unsigned char *)This->surface)[x + dst_x + ydst] = lpDDBltFx->dwFillColor; + } + } + } + else if (This->bpp == 16) + { + int y, x; + for (y = 0; y < dst_h; y++) + { + int ydst = This->width * (y + dst_y); + + for (x = 0; x < dst_w; x++) + { + ((unsigned short *)This->surface)[x + dst_x + ydst] = lpDDBltFx->dwFillColor; + } } } } @@ -132,56 +179,74 @@ HRESULT __stdcall ddraw_surface_Blt(IDirectDrawSurfaceImpl *This, LPRECT lpDestR { if (dwFlags & DDBLT_KEYSRC) { - int src_w = lpSrcRect ? lpSrcRect->right - lpSrcRect->left : Source->width; - int src_h = lpSrcRect ? lpSrcRect->bottom - lpSrcRect->top : Source->height; - int src_x = lpSrcRect ? lpSrcRect->left : 0; - int src_y = lpSrcRect ? lpSrcRect->top : 0; - int dst_x = lpDestRect ? lpDestRect->left : 0; - int dst_y = lpDestRect ? lpDestRect->top : 0; - - unsigned char* dstSurface = (unsigned char *)This->surface; - unsigned char* srcSurface = (unsigned char *)Source->surface; - - int y1, x1; - for (y1 = 0; y1 < src_h; y1++) + if (dst_w == src_w && dst_h == src_h) { - int ydst = This->width * (y1 + dst_y); - int ysrc = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < src_w; x1++) + if (This->bpp == 8) { - unsigned char index = srcSurface[x1 + src_x + ysrc]; + int y1, x1; + for (y1 = 0; y1 < dst_h; y1++) + { + int ydst = This->width * (y1 + dst_y); + int ysrc = Source->width * (y1 + src_y); - if (index != Source->colorKey.dwColorSpaceLowValue) - dstSurface[x1 + dst_x + ydst] = index; + for (x1 = 0; x1 < dst_w; x1++) + { + unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc]; + + if (c != Source->colorKey.dwColorSpaceLowValue) + { + ((unsigned char *)This->surface)[x1 + dst_x + ydst] = c; + } + } + } } + else if (This->bpp == 16) + { + int y1, x1; + for (y1 = 0; y1 < dst_h; y1++) + { + int ydst = This->width * (y1 + dst_y); + int ysrc = Source->width * (y1 + src_y); + + for (x1 = 0; x1 < dst_w; x1++) + { + unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc]; + + if (c != Source->colorKey.dwColorSpaceLowValue) + { + ((unsigned short *)This->surface)[x1 + dst_x + ydst] = c; + } + } + } + } + } + else + { + printf(" DDBLT_KEYSRC does not support stretching"); } } else { - int dx = 0, dy = 0; - if (lpDestRect) + if (dst_w == src_w && dst_h == src_h) { - dx = lpDestRect->left; - dy = lpDestRect->top; - } - int x0 = 0, y0 = 0, x1 = Source->width, y1 = Source->height; - if (lpSrcRect) - { - x0 = max(x0, lpSrcRect->left); - x1 = min(x1, lpSrcRect->right); - y0 = max(y0, lpSrcRect->top); - y1 = min(y1, lpSrcRect->bottom); - } - unsigned char* to = (unsigned char *)This->surface + dy*This->width + dx; - unsigned char* from = (unsigned char *)Source->surface + y0*Source->width + x0; - int s = x1 - x0; + unsigned char *src = + (unsigned char *)Source->surface + ((src_x + (Source->width * src_y)) * Source->lXPitch); - int y; - for (y = y0; y < y1; ++y, to += This->width, from += Source->width) - { - memcpy(to, from, s); + unsigned char *dst = + (unsigned char *)This->surface + ((dst_x + (This->width * dst_y)) * This->lXPitch); + + int i; + for (i = 0; i < dst_h; i++) + { + memcpy(dst, src, dst_w * This->lXPitch); + + src += Source->lPitch; + dst += This->lPitch; + } } + else + StretchBlt(This->hDC, dst_x, dst_y, dst_w, dst_h, Source->hDC, src_x, src_y, src_w, src_h, SRCCOPY); + } } @@ -235,51 +300,93 @@ HRESULT __stdcall ddraw_surface_BltFast(IDirectDrawSurfaceImpl *This, DWORD dst_ } #endif + RECT srcRect = { 0, 0, Source ? Source->width : 0, Source ? Source->height : 0 }; + + if (lpSrcRect && Source) + { + memcpy(&srcRect, lpSrcRect, sizeof(srcRect)); + + if (srcRect.right > Source->width) + srcRect.right = Source->width; + + if (srcRect.bottom > Source->height) + srcRect.bottom = Source->height; + } + + int src_w = srcRect.right - srcRect.left; + int src_h = srcRect.bottom - srcRect.top; + int src_x = srcRect.left; + int src_y = srcRect.top; + + RECT dstRect = { dst_x, dst_y, src_w + dst_x, src_h + dst_y }; + + if (dstRect.right > This->width) + dstRect.right = This->width; + + if (dstRect.bottom > This->height) + dstRect.bottom = This->height; + + int dst_w = dstRect.right - dstRect.left; + int dst_h = dstRect.bottom - dstRect.top; + if (Source) { if (flags & DDBLTFAST_SRCCOLORKEY) { - int src_w = lpSrcRect ? lpSrcRect->right - lpSrcRect->left : Source->width; - int src_h = lpSrcRect ? lpSrcRect->bottom - lpSrcRect->top : Source->height; - int src_x = lpSrcRect ? lpSrcRect->left : 0; - int src_y = lpSrcRect ? lpSrcRect->top : 0; - - unsigned char* dstSurface = (unsigned char *)This->surface; - unsigned char* srcSurface = (unsigned char *)Source->surface; - - int y1, x1; - for (y1 = 0; y1 < src_h; y1++) + if (This->bpp == 8) { - int ydst = This->width * (y1 + dst_y); - int ysrc = Source->width * (y1 + src_y); - - for (x1 = 0; x1 < src_w; x1++) + int y1, x1; + for (y1 = 0; y1 < dst_h; y1++) { - unsigned char index = srcSurface[x1 + src_x + ysrc]; + int ydst = This->width * (y1 + dst_y); + int ysrc = Source->width * (y1 + src_y); - if (index != Source->colorKey.dwColorSpaceLowValue) - dstSurface[x1 + dst_x + ydst] = index; + for (x1 = 0; x1 < dst_w; x1++) + { + unsigned char c = ((unsigned char *)Source->surface)[x1 + src_x + ysrc]; + + if (c != Source->colorKey.dwColorSpaceLowValue) + { + ((unsigned char *)This->surface)[x1 + dst_x + ydst] = c; + } + } + } + } + else if (This->bpp == 16) + { + int y1, x1; + for (y1 = 0; y1 < dst_h; y1++) + { + int ydst = This->width * (y1 + dst_y); + int ysrc = Source->width * (y1 + src_y); + + for (x1 = 0; x1 < dst_w; x1++) + { + unsigned short c = ((unsigned short *)Source->surface)[x1 + src_x + ysrc]; + + if (c != Source->colorKey.dwColorSpaceLowValue) + { + ((unsigned short *)This->surface)[x1 + dst_x + ydst] = c; + } + } } } } else { - int x0 = 0, y0 = 0, x1 = Source->width, y1 = Source->height; - if (lpSrcRect) - { - x0 = max(x0, lpSrcRect->left); - x1 = min(x1, lpSrcRect->right); - y0 = max(y0, lpSrcRect->top); - y1 = min(y1, lpSrcRect->bottom); - } - unsigned char* to = (unsigned char *)This->surface + dst_y*This->width + dst_x; - unsigned char* from = (unsigned char *)Source->surface + y0*Source->width + x0; - int s = x1 - x0; + unsigned char *src = + (unsigned char *)Source->surface + ((src_x + (Source->width * src_y)) * Source->lXPitch); - int y; - for (y = y0; y < y1; ++y, to += This->width, from += Source->width) + unsigned char *dst = + (unsigned char *)This->surface + ((dst_x + (This->width * dst_y)) * This->lXPitch); + + int i; + for (i = 0; i < dst_h; i++) { - memcpy(to, from, s); + memcpy(dst, src, dst_w * This->lXPitch); + + src += Source->lPitch; + dst += This->lPitch; } } } @@ -312,14 +419,18 @@ HRESULT __stdcall ddraw_surface_GetSurfaceDesc(IDirectDrawSurfaceImpl *This, LPD lpDDSurfaceDesc->dwHeight = This->height; lpDDSurfaceDesc->lPitch = This->lPitch; lpDDSurfaceDesc->lpSurface = This->surface; - lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB; lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = This->bpp; - if (This->bpp == 16) + if (This->bpp == 8) { - /* RGB 555 */ - lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x7C00; - lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x03E0; + lpDDSurfaceDesc->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; + } + else if (This->bpp == 16) + { + lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xF800; + lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x07E0; lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x001F; } @@ -467,8 +578,19 @@ HRESULT __stdcall ddraw_surface_GetPixelFormat(IDirectDrawSurfaceImpl *This, LPD memset(ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT)); ddpfPixelFormat->dwSize = size; - ddpfPixelFormat->dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; - ddpfPixelFormat->dwRGBBitCount = 8; + ddpfPixelFormat->dwFlags = DDPF_RGB; + ddpfPixelFormat->dwRGBBitCount = This->bpp; + + if (This->bpp == 8) + { + ddpfPixelFormat->dwFlags |= DDPF_PALETTEINDEXED8; + } + else if (This->bpp == 16) + { + ddpfPixelFormat->dwRBitMask = 0xF800; + ddpfPixelFormat->dwGBitMask = 0x07E0; + ddpfPixelFormat->dwBBitMask = 0x001F; + } return DD_OK; } @@ -530,7 +652,9 @@ HRESULT __stdcall ddraw_surface_ReleaseDC(IDirectDrawSurfaceImpl *This, HDC a) HRESULT __stdcall ddraw_surface_Restore(IDirectDrawSurfaceImpl *This) { +#if _DEBUG_X printf("DirectDrawSurface::Restore(This=%p) ???\n", This); +#endif return DD_OK; } @@ -682,6 +806,8 @@ HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpD Surface->lpVtbl = &siface; + lpDDSurfaceDesc->dwFlags |= DDSD_CAPS; + /* private stuff */ Surface->bpp = This->bpp; Surface->flags = lpDDSurfaceDesc->dwFlags; @@ -716,7 +842,7 @@ HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpD Surface->bmi->bmiHeader.biHeight = -Surface->height; Surface->bmi->bmiHeader.biPlanes = 1; Surface->bmi->bmiHeader.biBitCount = Surface->bpp; - Surface->bmi->bmiHeader.biCompression = BI_RGB; + Surface->bmi->bmiHeader.biCompression = Surface->bpp == 16 ? BI_BITFIELDS : BI_RGB; WORD cClrBits = (WORD)(Surface->bmi->bmiHeader.biPlanes * Surface->bmi->bmiHeader.biBitCount); if (cClrBits < 24) @@ -724,13 +850,22 @@ HRESULT __stdcall ddraw_CreateSurface(IDirectDrawImpl *This, LPDDSURFACEDESC lpD Surface->bmi->bmiHeader.biSizeImage = ((Surface->width * cClrBits + 31) & ~31) / 8 * Surface->height; - int i; - for (i = 0; i < 256; i++) + if (Surface->bpp == 8) { - Surface->bmi->bmiColors[i].rgbRed = i; - Surface->bmi->bmiColors[i].rgbGreen = i; - Surface->bmi->bmiColors[i].rgbBlue = i; - Surface->bmi->bmiColors[i].rgbReserved = 0; + int i; + for (i = 0; i < 256; i++) + { + Surface->bmi->bmiColors[i].rgbRed = i; + Surface->bmi->bmiColors[i].rgbGreen = i; + Surface->bmi->bmiColors[i].rgbBlue = i; + Surface->bmi->bmiColors[i].rgbReserved = 0; + } + } + else if (Surface->bpp == 16) + { + ((DWORD *)Surface->bmi->bmiColors)[0] = 0xF800; + ((DWORD *)Surface->bmi->bmiColors)[1] = 0x07E0; + ((DWORD *)Surface->bmi->bmiColors)[2] = 0x001F; } Surface->lXPitch = Surface->bpp / 8;