1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-14 22:03:27 +01:00

separate blitters into a different file

This commit is contained in:
FunkyFr3sh 2022-09-08 02:19:15 +02:00
parent 15221b3120
commit 0997f514c4
6 changed files with 935 additions and 619 deletions

View File

@ -15,6 +15,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\blt.c" />
<ClCompile Include="src\crc32.c" />
<ClCompile Include="src\ddclipper.c" />
<ClCompile Include="src\debug.c" />
@ -61,6 +62,7 @@
<ClCompile Include="src\wndproc.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="inc\blt.h" />
<ClInclude Include="inc\crc32.h" />
<ClInclude Include="inc\d3d9shader.h" />
<ClInclude Include="inc\ddclipper.h" />

View File

@ -153,6 +153,9 @@
<ClCompile Include="src\crc32.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\blt.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="inc\debug.h">
@ -263,6 +266,9 @@
<ClInclude Include="inc\crc32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\blt.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ddraw.rc">

93
inc/blt.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef BLT_H
#define BLT_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void blt_clean(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
int bpp);
void blt_overlap(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
int bpp);
void blt_colorkey(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
unsigned int key_low,
unsigned int key_high,
int bpp);
void blt_colorkey_mirror_stretch(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_w,
int src_h,
int src_p,
unsigned int key_low,
unsigned int key_high,
BOOL mirror_up_down,
BOOL mirror_left_right,
int bpp);
void blt_colorfill(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned int color,
int bpp);
void blt_stretch(
unsigned char* dst_buf,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src_buf,
int src_x,
int src_y,
int src_w,
int src_h,
int src_p,
int bpp);
#endif

660
src/blt.c Normal file
View File

@ -0,0 +1,660 @@
#include <windows.h>
#include "debug.h"
#include "scale_pattern.h"
#include "blt.h"
void blt_clean(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
int bpp)
{
int bytes_pp = bpp / 8;
size_t size = dst_w * bytes_pp;
src += (src_x * bytes_pp) + (src_p * src_y);
dst += (dst_x * bytes_pp) + (dst_p * dst_y);
for (int i = 0; i < dst_h; i++)
{
memcpy(dst, src, size);
src += src_p;
dst += dst_p;
}
}
void blt_overlap(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
int bpp)
{
int bytes_pp = bpp / 8;
size_t size = dst_w * bytes_pp;
src += (src_x * bytes_pp) + (src_p * src_y);
dst += (dst_x * bytes_pp) + (dst_p * dst_y);
if (dst_y > src_y)
{
src += src_p * dst_h;
dst += dst_p * dst_h;
for (int i = dst_h; i-- > 0;)
{
src -= src_p;
dst -= dst_p;
memmove(dst, src, size);
}
}
else
{
for (int i = 0; i < dst_h; i++)
{
memmove(dst, src, size);
src += src_p;
dst += dst_p;
}
}
}
void blt_colorkey(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_p,
unsigned int key_low,
unsigned int key_high,
int bpp)
{
int bytes_pp = bpp / 8;
size_t d_p = dst_p - (dst_w * bytes_pp);
size_t s_p = src_p - (dst_w * bytes_pp);
src += (src_x * bytes_pp) + (src_p * src_y);
dst += (dst_x * bytes_pp) + (dst_p * dst_y);
if (bpp == 8)
{
unsigned char key_l = (unsigned char)key_low;
unsigned char key_h = (unsigned char)key_high;
if (key_l == key_h)
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned char c = *src++;
if (c != key_l)
{
*dst = c;
}
dst++;
}
src += s_p;
dst += d_p;
}
}
else
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned char c = *src++;
if (c < key_l || c > key_h)
{
*dst = c;
}
dst++;
}
src += s_p;
dst += d_p;
}
}
}
else if (bpp == 16)
{
unsigned short key_l = (unsigned short)key_low;
unsigned short key_h = (unsigned short)key_high;
if (key_l == key_h)
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned short c = *((unsigned short*)src)++;
if (c != key_l)
{
*((unsigned short*)dst) = c;
}
((unsigned short*)dst)++;
}
src += s_p;
dst += d_p;
}
}
else
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned short c = *((unsigned short*)src)++;
if (c < key_l || c > key_h)
{
*((unsigned short*)dst) = c;
}
((unsigned short*)dst)++;
}
src += s_p;
dst += d_p;
}
}
}
else if (bpp == 32)
{
unsigned int key_l = (unsigned int)key_low;
unsigned int key_h = (unsigned int)key_high;
if (key_l == key_h)
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned int c = *((unsigned int*)src)++;
if (c != key_l)
{
*((unsigned int*)dst) = c;
}
((unsigned int*)dst)++;
}
src += s_p;
dst += d_p;
}
}
else
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned int c = *((unsigned int*)src)++;
if (c < key_l || c > key_h)
{
*((unsigned int*)dst) = c;
}
((unsigned int*)dst)++;
}
src += s_p;
dst += d_p;
}
}
}
}
void blt_colorkey_mirror_stretch(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src,
int src_x,
int src_y,
int src_w,
int src_h,
int src_p,
unsigned int key_low,
unsigned int key_high,
BOOL mirror_up_down,
BOOL mirror_left_right,
int bpp)
{
int bytes_pp = bpp / 8;
int dst_surf_w = dst_p / bytes_pp;
int src_surf_w = src_p / bytes_pp;
float scale_w = (float)src_w / dst_w;
float scale_h = (float)src_h / dst_h;
if (bpp == 8)
{
unsigned char key_l = (unsigned char)key_low;
unsigned char key_h = (unsigned char)key_high;
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surf_w * (scaled_y + src_y);
int dst_row = dst_surf_w * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned char c = ((unsigned char*)src)[scaled_x + src_x + src_row];
if (c < key_l || c > key_h)
{
((unsigned char*)dst)[x + dst_x + dst_row] = c;
}
}
}
}
else if (bpp == 16)
{
unsigned short key_l = (unsigned short)key_low;
unsigned short key_h = (unsigned short)key_high;
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surf_w * (scaled_y + src_y);
int dst_row = dst_surf_w * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned short c = ((unsigned short*)src)[scaled_x + src_x + src_row];
if (c < key_l || c > key_h)
{
((unsigned short*)dst)[x + dst_x + dst_row] = c;
}
}
}
}
else if (bpp == 32)
{
unsigned int key_l = (unsigned int)key_low;
unsigned int key_h = (unsigned int)key_high;
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surf_w * (scaled_y + src_y);
int dst_row = dst_surf_w * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned int c = ((unsigned int*)src)[scaled_x + src_x + src_row];
if (c < key_l || c > key_h)
{
((unsigned int*)dst)[x + dst_x + dst_row] = c;
}
}
}
}
}
void blt_colorfill(
unsigned char* dst,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned int color,
int bpp)
{
int bytes_pp = bpp / 8;
size_t size = dst_w * bytes_pp;
dst += (dst_x * bytes_pp) + (dst_p * dst_y);
if (bpp == 8)
{
for (int i = 0; i < dst_h; i++)
{
memset(dst, color, size);
dst += dst_p;
}
}
else if (bpp == 16)
{
if ((color & 0xFF) == ((color >> 8) & 0xFF))
{
for (int i = 0; i < dst_h; i++)
{
memset(dst, color, size);
dst += dst_p;
}
}
else
{
unsigned short* first_row = (unsigned short*)dst;
for (int x = 0; x < dst_w; x++)
{
first_row[x] = (unsigned short)color;
}
for (int i = 1; i < dst_h; i++)
{
dst += dst_p;
memcpy(dst, first_row, size);
}
}
}
else if (bpp == 32)
{
if ((color & 0xFF) == ((color >> 8) & 0xFF) &&
(color & 0xFF) == ((color >> 16) & 0xFF) &&
(color & 0xFF) == ((color >> 24) & 0xFF))
{
for (int i = 0; i < dst_h; i++)
{
memset(dst, color, size);
dst += dst_p;
}
}
else
{
unsigned int* first_row = (unsigned int*)dst;
for (int x = 0; x < dst_w; x++)
{
first_row[x] = color;
}
for (int i = 1; i < dst_h; i++)
{
dst += dst_p;
memcpy(dst, first_row, size);
}
}
}
}
void blt_stretch(
unsigned char* dst_buf,
int dst_x,
int dst_y,
int dst_w,
int dst_h,
int dst_p,
unsigned char* src_buf,
int src_x,
int src_y,
int src_w,
int src_h,
int src_p,
int bpp)
{
/* Linear scaling using integer math
* Since the scaling pattern for x will aways be the same, the pattern itself gets pre-calculated
* and stored in an array.
* Y scaling pattern gets calculated during the blit loop
*/
unsigned int x_ratio = (unsigned int)((src_w << 16) / dst_w) + 1;
unsigned int y_ratio = (unsigned int)((src_h << 16) / dst_h) + 1;
unsigned int s_src_x, s_src_y;
unsigned int dest_base, source_base;
scale_pattern* pattern = malloc((dst_w + 1) * (sizeof(scale_pattern)));
int pattern_idx = 0;
unsigned int last_src_x = 0;
if (pattern != NULL)
{
pattern[pattern_idx] = (scale_pattern){ ONCE, 0, 0, 1 };
/* Build the pattern! */
int x;
for (x = 1; x < dst_w; x++) {
s_src_x = (x * x_ratio) >> 16;
if (s_src_x == last_src_x)
{
if (pattern[pattern_idx].type == REPEAT || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = REPEAT;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == SEQUENCE)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ REPEAT, x, s_src_x, 1 };
}
}
else if (s_src_x == last_src_x + 1)
{
if (pattern[pattern_idx].type == SEQUENCE || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = SEQUENCE;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == REPEAT)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 };
}
}
else
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 };
}
last_src_x = s_src_x;
}
pattern[pattern_idx + 1] = (scale_pattern){ END, 0, 0, 0 };
/* Do the actual blitting */
int bytes_pp = bpp / 8;
int dst_surf_w = dst_p / bytes_pp;
int src_surf_w = src_p / bytes_pp;
int count = 0;
int y;
for (y = 0; y < dst_h; y++) {
dest_base = dst_x + dst_surf_w * (y + dst_y);
s_src_y = (y * y_ratio) >> 16;
source_base = src_x + src_surf_w * (s_src_y + src_y);
pattern_idx = 0;
scale_pattern* current = &pattern[pattern_idx];
if (bpp == 8)
{
unsigned char* d, * s, v;
unsigned char* src = (unsigned char*)src_buf;
unsigned char* dst = (unsigned char*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
else if (bpp == 16)
{
unsigned short* d, * s, v;
unsigned short* src = (unsigned short*)src_buf;
unsigned short* dst = (unsigned short*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count * bytes_pp);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
else if (bpp == 32)
{
unsigned int* d, * s, v;
unsigned int* src = (unsigned int*)src_buf;
unsigned int* dst = (unsigned int*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count * bytes_pp);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
}
free(pattern);
}
}

View File

@ -5,11 +5,11 @@
#include "hook.h"
#include "ddsurface.h"
#include "mouse.h"
#include "scale_pattern.h"
#include "IDirectDrawSurface.h"
#include "winapi_hooks.h"
#include "debug.h"
#include "utils.h"
#include "blt.h"
HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurface)
@ -29,11 +29,11 @@ HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceI
}
HRESULT dds_Blt(
IDirectDrawSurfaceImpl* This,
LPRECT lpDestRect,
IDirectDrawSurfaceImpl* lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
IDirectDrawSurfaceImpl* This,
LPRECT lpDestRect,
IDirectDrawSurfaceImpl* lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
LPDDBLTFX lpDDBltFx)
{
dbg_dump_dds_blt_flags(dwFlags);
@ -121,79 +121,17 @@ HRESULT dds_Blt(
void* dst_buf = dds_GetBuffer(This);
void* src_buf = dds_GetBuffer(src_surface);
if (dst_buf && (dwFlags & DDBLT_COLORFILL) && dst_w > 0 && dst_h > 0)
if (dst_buf && (dwFlags & DDBLT_COLORFILL) && lpDDBltFx && dst_w > 0 && dst_h > 0)
{
unsigned char* dst = (unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned char* first_row = dst;
unsigned int dst_pitch = dst_w * This->lx_pitch;
int x, i;
if (This->bpp == 8)
{
unsigned char color = (unsigned char)lpDDBltFx->dwFillColor;
for (i = 0; i < dst_h; i++)
{
memset(dst, color, dst_pitch);
dst += This->l_pitch;
}
}
else if (This->bpp == 16)
{
unsigned short* row1 = (unsigned short*)dst;
unsigned short color = (unsigned short)lpDDBltFx->dwFillColor;
if ((color & 0xFF) == (color >> 8))
{
unsigned char c8 = (unsigned char)(color & 0xFF);
for (i = 0; i < dst_h; i++)
{
memset(dst, c8, dst_pitch);
dst += This->l_pitch;
}
}
else
{
for (x = 0; x < dst_w; x++)
row1[x] = color;
for (i = 1; i < dst_h; i++)
{
dst += This->l_pitch;
memcpy(dst, first_row, dst_pitch);
}
}
}
else if (This->bpp == 32)
{
unsigned int* row1 = (unsigned int*)dst;
unsigned int color = lpDDBltFx->dwFillColor;
if ((color & 0xFF) == ((color >> 8) & 0xFF) &&
(color & 0xFF) == ((color >> 16) & 0xFF) &&
(color & 0xFF) == ((color >> 24) & 0xFF))
{
unsigned char c8 = (unsigned char)(color & 0xFF);
for (i = 0; i < dst_h; i++)
{
memset(dst, c8, dst_pitch);
dst += This->l_pitch;
}
}
else
{
for (x = 0; x < dst_w; x++)
row1[x] = color;
for (i = 1; i < dst_h; i++)
{
dst += This->l_pitch;
memcpy(dst, first_row, dst_pitch);
}
}
}
blt_colorfill(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
lpDDBltFx->dwFillColor,
This->bpp);
}
if (src_surface && src_w > 0 && src_h > 0 && dst_w > 0 && dst_h > 0)
@ -215,8 +153,8 @@ HRESULT dds_Blt(
StretchBlt(dst_dc, dst_x, dst_y, dst_w, dst_h, src_dc, src_x, src_y, src_w, src_h, SRCCOPY);
}
else if (
(dwFlags & DDBLT_KEYSRC) ||
(dwFlags & DDBLT_KEYSRCOVERRIDE) ||
(dwFlags & DDBLT_KEYSRC) ||
(dwFlags & DDBLT_KEYSRCOVERRIDE) ||
mirror_left_right ||
mirror_up_down)
{
@ -236,410 +174,91 @@ HRESULT dds_Blt(
color_key.dwColorSpaceHighValue = color_key.dwColorSpaceLowValue;
}
float scale_w = (float)src_w / dst_w;
float scale_h = (float)src_h / dst_h;
if (This->bpp == 8)
if (src_w == dst_w && src_h == dst_h && !mirror_left_right && !mirror_up_down)
{
unsigned char key_low = (unsigned char)color_key.dwColorSpaceLowValue;
unsigned char key_high = (unsigned char)color_key.dwColorSpaceHighValue;
/*
if (src_w == dst_w && src_h == dst_h && !mirror_left_right && !mirror_up_down)
{
unsigned char* src =
(unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y);
unsigned char* dst =
(unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned int dst_p = This->l_pitch - (dst_w * This->lx_pitch);
unsigned int src_p = src_surface->l_pitch - (dst_w * src_surface->lx_pitch);
if (key_low == key_high)
{
for (int y = 0; y < dst_h; y++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned char c = *src++;
if (c != key_low)
{
*dst = c;
}
dst++;
}
src += src_p;
dst += dst_p;
}
}
else
{
for (int i = 0; i < dst_h; i++)
{
for (int x = 0; x < dst_w; x++)
{
unsigned char c = *src++;
if (c < key_low || c > key_high)
{
*dst = c;
}
dst++;
}
src += src_p;
dst += dst_p;
}
}
}
else
{
*/
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surface->width * (scaled_y + src_y);
int dst_row = This->width * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned char c = ((unsigned char*)src_buf)[scaled_x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned char*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
//}
}
else if (This->bpp == 16)
{
unsigned short key_low = (unsigned short)color_key.dwColorSpaceLowValue;
unsigned short key_high = (unsigned short)color_key.dwColorSpaceHighValue;
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surface->width * (scaled_y + src_y);
int dst_row = This->width * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned short c = ((unsigned short*)src_buf)[scaled_x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned short*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
}
else if (This->bpp == 32)
{
unsigned int key_low = color_key.dwColorSpaceLowValue;
unsigned int key_high = color_key.dwColorSpaceHighValue;
for (int y = 0; y < dst_h; y++)
{
int scaled_y = (int)(y * scale_h);
if (mirror_up_down)
scaled_y = src_h - 1 - scaled_y;
int src_row = src_surface->width * (scaled_y + src_y);
int dst_row = This->width * (y + dst_y);
for (int x = 0; x < dst_w; x++)
{
int scaled_x = (int)(x * scale_w);
if (mirror_left_right)
scaled_x = src_w - 1 - scaled_x;
unsigned int c = ((unsigned int*)src_buf)[scaled_x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned int*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
}
}
else
{
if (!is_stretch_blt)
{
int width = dst_w > src_w ? src_w : dst_w;
int height = dst_h > src_h ? src_h : dst_h;
unsigned char* src =
(unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y);
unsigned char* dst =
(unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned int dst_pitch = width * This->lx_pitch;
if (This == src_surface)
{
if (dst_y > src_y)
{
src += src_surface->l_pitch * height;
dst += This->l_pitch * height;
for (int i = height; i-- > 0;)
{
src -= src_surface->l_pitch;
dst -= This->l_pitch;
memmove(dst, src, dst_pitch);
}
}
else
{
for (int i = 0; i < height; i++)
{
memmove(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
}
else
{
for (int i = 0; i < height; i++)
{
memcpy(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
blt_colorkey(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
color_key.dwColorSpaceLowValue,
color_key.dwColorSpaceHighValue,
This->bpp);
}
else
{
/* Linear scaling using integer math
* Since the scaling pattern for x will aways be the same, the pattern itself gets pre-calculated
* and stored in an array.
* Y scaling pattern gets calculated during the blit loop
*/
unsigned int x_ratio = (unsigned int)((src_w << 16) / dst_w) + 1;
unsigned int y_ratio = (unsigned int)((src_h << 16) / dst_h) + 1;
unsigned int s_src_x, s_src_y;
unsigned int dest_base, source_base;
scale_pattern* pattern = malloc((dst_w + 1) * (sizeof(scale_pattern)));
int pattern_idx = 0;
unsigned int last_src_x = 0;
if (pattern != NULL)
{
pattern[pattern_idx] = (scale_pattern){ ONCE, 0, 0, 1 };
/* Build the pattern! */
int x;
for (x = 1; x < dst_w; x++) {
s_src_x = (x * x_ratio) >> 16;
if (s_src_x == last_src_x)
{
if (pattern[pattern_idx].type == REPEAT || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = REPEAT;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == SEQUENCE)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ REPEAT, x, s_src_x, 1 };
}
}
else if (s_src_x == last_src_x + 1)
{
if (pattern[pattern_idx].type == SEQUENCE || pattern[pattern_idx].type == ONCE)
{
pattern[pattern_idx].type = SEQUENCE;
pattern[pattern_idx].count++;
}
else if (pattern[pattern_idx].type == REPEAT)
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 };
}
}
else
{
pattern_idx++;
pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 };
}
last_src_x = s_src_x;
}
pattern[pattern_idx + 1] = (scale_pattern){ END, 0, 0, 0 };
/* Do the actual blitting */
int count = 0;
int y;
for (y = 0; y < dst_h; y++) {
dest_base = dst_x + This->width * (y + dst_y);
s_src_y = (y * y_ratio) >> 16;
source_base = src_x + src_surface->width * (s_src_y + src_y);
pattern_idx = 0;
scale_pattern* current = &pattern[pattern_idx];
if (This->bpp == 8)
{
unsigned char* d, * s, v;
unsigned char* src = (unsigned char*)src_buf;
unsigned char* dst = (unsigned char*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count * This->lx_pitch);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
else if (This->bpp == 16)
{
unsigned short* d, * s, v;
unsigned short* src = (unsigned short*)src_buf;
unsigned short* dst = (unsigned short*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count * This->lx_pitch);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
else if (This->bpp == 32)
{
unsigned int* d, * s, v;
unsigned int* src = (unsigned int*)src_buf;
unsigned int* dst = (unsigned int*)dst_buf;
do {
switch (current->type)
{
case ONCE:
dst[dest_base + current->dst_index] =
src[source_base + current->src_index];
break;
case REPEAT:
d = (dst + dest_base + current->dst_index);
v = src[source_base + current->src_index];
count = current->count;
while (count-- > 0)
*d++ = v;
break;
case SEQUENCE:
d = dst + dest_base + current->dst_index;
s = src + source_base + current->src_index;
memcpy((void*)d, (void*)s, current->count * This->lx_pitch);
break;
case END:
default:
break;
}
current = &pattern[++pattern_idx];
} while (current->type != END);
}
}
free(pattern);
}
blt_colorkey_mirror_stretch(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_w,
src_h,
src_surface->l_pitch,
color_key.dwColorSpaceLowValue,
color_key.dwColorSpaceHighValue,
mirror_up_down,
mirror_left_right,
This->bpp);
}
}
else if (is_stretch_blt)
{
blt_stretch(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_w,
src_h,
src_surface->l_pitch,
This->bpp);
}
else if (This == src_surface)
{
blt_overlap(
dst_buf,
dst_x,
dst_y,
min(dst_w, src_w),
min(dst_h, src_h),
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
This->bpp);
}
else
{
blt_clean(
dst_buf,
dst_x,
dst_y,
min(dst_w, src_w),
min(dst_h, src_h),
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
This->bpp);
}
}
@ -666,11 +285,11 @@ HRESULT dds_Blt(
}
HRESULT dds_BltFast(
IDirectDrawSurfaceImpl* This,
DWORD dwX,
DWORD dwY,
IDirectDrawSurfaceImpl* lpDDSrcSurface,
LPRECT lpSrcRect,
IDirectDrawSurfaceImpl* This,
DWORD dwX,
DWORD dwY,
IDirectDrawSurfaceImpl* lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags)
{
dbg_dump_dds_blt_fast_flags(dwFlags);
@ -772,116 +391,50 @@ HRESULT dds_BltFast(
}
else if (dwFlags & DDBLTFAST_SRCCOLORKEY)
{
if (This->bpp == 8)
{
unsigned char key_low = (unsigned char)src_surface->color_key.dwColorSpaceLowValue;
unsigned char key_high = (unsigned char)src_surface->color_key.dwColorSpaceHighValue;
for (int y = 0; y < dst_h; y++)
{
int dst_row = This->width * (y + dst_y);
int src_row = src_surface->width * (y + src_y);
for (int x = 0; x < dst_w; x++)
{
unsigned char c = ((unsigned char*)src_buf)[x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned char*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
}
else if (This->bpp == 16)
{
unsigned short key_low = (unsigned short)src_surface->color_key.dwColorSpaceLowValue;
unsigned short key_high = (unsigned short)src_surface->color_key.dwColorSpaceHighValue;
for (int y = 0; y < dst_h; y++)
{
int dst_row = This->width * (y + dst_y);
int src_row = src_surface->width * (y + src_y);
for (int x = 0; x < dst_w; x++)
{
unsigned short c = ((unsigned short*)src_buf)[x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned short*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
}
else if (This->bpp == 32)
{
unsigned int key_low = src_surface->color_key.dwColorSpaceLowValue;
unsigned int key_high = src_surface->color_key.dwColorSpaceHighValue;
for (int y = 0; y < dst_h; y++)
{
int dst_row = This->width * (y + dst_y);
int src_row = src_surface->width * (y + src_y);
for (int x = 0; x < dst_w; x++)
{
unsigned int c = ((unsigned int*)src_buf)[x + src_x + src_row];
if (c < key_low || c > key_high)
{
((unsigned int*)dst_buf)[x + dst_x + dst_row] = c;
}
}
}
}
blt_colorkey(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
src_surface->color_key.dwColorSpaceLowValue,
src_surface->color_key.dwColorSpaceHighValue,
This->bpp);
}
else if (This == src_surface)
{
blt_overlap(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
This->bpp);
}
else
{
unsigned char* src =
(unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y);
unsigned char* dst =
(unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y);
unsigned int dst_pitch = dst_w * This->lx_pitch;
if (This == src_surface)
{
if (dst_y > src_y)
{
src += src_surface->l_pitch * dst_h;
dst += This->l_pitch * dst_h;
for (int i = dst_h; i-- > 0;)
{
src -= src_surface->l_pitch;
dst -= This->l_pitch;
memmove(dst, src, dst_pitch);
}
}
else
{
for (int i = 0; i < dst_h; i++)
{
memmove(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
}
else
{
for (int i = 0; i < dst_h; i++)
{
memcpy(dst, src, dst_pitch);
src += src_surface->l_pitch;
dst += This->l_pitch;
}
}
blt_clean(
dst_buf,
dst_x,
dst_y,
dst_w,
dst_h,
This->l_pitch,
src_buf,
src_x,
src_y,
src_surface->l_pitch,
This->bpp);
}
}
@ -960,8 +513,8 @@ HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC lpDDSur
}
HRESULT dds_EnumAttachedSurfaces(
IDirectDrawSurfaceImpl* This,
LPVOID lpContext,
IDirectDrawSurfaceImpl* This,
LPVOID lpContext,
LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{
static DDSURFACEDESC2 desc;
@ -1163,10 +716,10 @@ HRESULT dds_GetPixelFormat(IDirectDrawSurfaceImpl* This, LPDDPIXELFORMAT ddpfPix
}
HRESULT dds_Lock(
IDirectDrawSurfaceImpl* This,
LPRECT lpDestRect,
LPDDSURFACEDESC lpDDSurfaceDesc,
DWORD dwFlags,
IDirectDrawSurfaceImpl* This,
LPRECT lpDestRect,
LPDDSURFACEDESC lpDDSurfaceDesc,
DWORD dwFlags,
HANDLE hEvent)
{
dbg_dump_dds_lock_flags(dwFlags);
@ -1409,9 +962,9 @@ void* dds_GetBuffer(IDirectDrawSurfaceImpl* This)
}
HRESULT dd_CreateSurface(
IDirectDrawImpl* This,
LPDDSURFACEDESC lpDDSurfaceDesc,
IDirectDrawSurfaceImpl** lpDDSurface,
IDirectDrawImpl* This,
LPDDSURFACEDESC lpDDSurfaceDesc,
IDirectDrawSurfaceImpl** lpDDSurface,
IUnknown FAR* unkOuter)
{
dbg_dump_dds_flags(lpDDSurfaceDesc->dwFlags);
@ -1429,7 +982,7 @@ HRESULT dd_CreateSurface(
return DD_OK;
}
IDirectDrawSurfaceImpl* dst_surface =
IDirectDrawSurfaceImpl* dst_surface =
(IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
dst_surface->lpVtbl = &g_dds_vtbl;
@ -1490,7 +1043,7 @@ HRESULT dd_CreateSurface(
}
}
dst_surface->bmi =
dst_surface->bmi =
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
dst_surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@ -1507,7 +1060,7 @@ HRESULT dd_CreateSurface(
dst_surface->bmi->bmiHeader.biClrUsed = (1 << clr_bits);
}
dst_surface->bmi->bmiHeader.biSizeImage =
dst_surface->bmi->bmiHeader.biSizeImage =
((dst_surface->width * clr_bits + 31) & ~31) / 8 * dst_surface->height;
if (dst_surface->bpp == 8)
@ -1534,7 +1087,7 @@ HRESULT dd_CreateSurface(
}
dst_surface->hdc = CreateCompatibleDC(g_ddraw->render.hdc);
dst_surface->bitmap =
dst_surface->bitmap =
CreateDIBSection(dst_surface->hdc, dst_surface->bmi, DIB_RGB_COLORS, (void**)&dst_surface->surface, NULL, 0);
dst_surface->bmi->bmiHeader.biHeight = -((int)dst_surface->height);
@ -1579,10 +1132,10 @@ HRESULT dd_CreateSurface(
}
TRACE(
" surface = %p (%ux%u@%u)\n",
dst_surface,
dst_surface->width,
dst_surface->height,
" surface = %p (%ux%u@%u)\n",
dst_surface,
dst_surface->width,
dst_surface->height,
dst_surface->bpp);
*lpDDSurface = dst_surface;

View File

@ -8,6 +8,7 @@
#include "render_d3d9.h"
#include "utils.h"
#include "wndproc.h"
#include "blt.h"
#include "debug.h"
@ -388,17 +389,18 @@ DWORD WINAPI d3d9_render_main(void)
if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[tex_index])) &&
SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0)))
{
unsigned char* src = (unsigned char*)g_ddraw->primary->surface;
unsigned char* dst = (unsigned char*)lock_rc.pBits;
int i;
for (i = 0; i < g_ddraw->height; i++)
{
memcpy(dst, src, g_ddraw->primary->l_pitch);
src += g_ddraw->primary->l_pitch;
dst += lock_rc.Pitch;
}
blt_clean(
lock_rc.pBits,
0,
0,
min(g_ddraw->width, g_ddraw->primary->width),
min(g_ddraw->height, g_ddraw->primary->height),
lock_rc.Pitch,
g_ddraw->primary->surface,
0,
0,
g_ddraw->primary->l_pitch,
g_ddraw->primary->bpp);
IDirect3DTexture9_UnlockRect(g_d3d9.surface_tex[tex_index], 0);
}