1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-15 06:04:49 +01:00

experimental 16bit color support (Dune 2000)

This commit is contained in:
FunkyFr3sh 2018-11-14 05:35:59 +01:00
parent a9ce4ac13c
commit 806746d364
7 changed files with 451 additions and 200 deletions

View File

@ -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";

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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]);

View File

@ -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;

View File

@ -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])
{

View File

@ -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;