883 lines
21 KiB
C++
883 lines
21 KiB
C++
#include "Draw.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <ddraw.h>
|
|
|
|
#include "WindowsWrapper.h"
|
|
|
|
#include "CommonDefines.h"
|
|
#include "Ending.h"
|
|
#include "Generic.h"
|
|
#include "Main.h"
|
|
#include "MapName.h"
|
|
#include "Tags.h"
|
|
#include "TextScr.h"
|
|
|
|
typedef enum SurfaceType
|
|
{
|
|
SURFACE_SOURCE_NONE = 1,
|
|
SURFACE_SOURCE_RESOURCE,
|
|
SURFACE_SOURCE_FILE
|
|
} SurfaceType;
|
|
|
|
RECT grcGame = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
|
RECT grcFull = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
|
|
|
int magnification;
|
|
BOOL fullscreen;
|
|
|
|
static LPDIRECTDRAW lpDD;
|
|
static LPDIRECTDRAWSURFACE frontbuffer;
|
|
static LPDIRECTDRAWSURFACE backbuffer;
|
|
|
|
static LPDIRECTDRAWCLIPPER clipper;
|
|
|
|
static LPDIRECTDRAWSURFACE surf[SURFACE_ID_MAX];
|
|
|
|
static RECT backbuffer_rect;
|
|
|
|
static int scaled_window_width;
|
|
static int scaled_window_height;
|
|
|
|
static HFONT font;
|
|
|
|
// This doesn't exist in the Linux port, so none of these symbol names are accurate
|
|
static struct
|
|
{
|
|
char name[20];
|
|
unsigned int width;
|
|
unsigned int height;
|
|
SurfaceType type;
|
|
BOOL bSystem; // Basically a 'do not regenerate' flag
|
|
} surface_metadata[SURFACE_ID_MAX];
|
|
|
|
// The original names for these variables are unknown
|
|
static int x_offset;
|
|
static int y_offset;
|
|
|
|
#define FRAMERATE 20
|
|
|
|
// The original name for this function is unknown
|
|
void SetWindowPadding(int width, int height)
|
|
{
|
|
x_offset = width;
|
|
y_offset = height;
|
|
}
|
|
|
|
BOOL Flip_SystemTask(HWND hWnd)
|
|
{
|
|
static DWORD timePrev;
|
|
static DWORD timeNow;
|
|
|
|
while (TRUE)
|
|
{
|
|
if (!SystemTask())
|
|
return FALSE;
|
|
|
|
// Framerate limiter
|
|
timeNow = GetTickCount();
|
|
|
|
if (timeNow >= timePrev + FRAMERATE)
|
|
break;
|
|
|
|
Sleep(1);
|
|
}
|
|
|
|
if (timeNow >= timePrev + 100)
|
|
timePrev = timeNow; // If the timer is freakishly out of sync, panic and reset it, instead of spamming frames for who-knows how long
|
|
else
|
|
timePrev += FRAMERATE;
|
|
|
|
static RECT dst_rect;
|
|
GetWindowRect(hWnd, &dst_rect);
|
|
dst_rect.left += x_offset;
|
|
dst_rect.top += y_offset;
|
|
dst_rect.right = dst_rect.left + scaled_window_width;
|
|
dst_rect.bottom = dst_rect.top + scaled_window_height;
|
|
|
|
frontbuffer->Blt(&dst_rect, backbuffer, &backbuffer_rect, DDBLT_WAIT, NULL);
|
|
|
|
if (RestoreSurfaces())
|
|
{
|
|
RestoreStripper();
|
|
RestoreMapName();
|
|
RestoreTextScript();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL StartDirectDraw(HWND hWnd, int lMagnification, int lColourDepth)
|
|
{
|
|
DDSURFACEDESC ddsd;
|
|
|
|
if (DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
|
|
return FALSE;
|
|
|
|
memset(surface_metadata, 0, sizeof(surface_metadata));
|
|
|
|
switch (lMagnification)
|
|
{
|
|
case 0:
|
|
magnification = 1;
|
|
fullscreen = FALSE;
|
|
lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
|
|
break;
|
|
|
|
case 1:
|
|
magnification = 2;
|
|
fullscreen = FALSE;
|
|
lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
|
|
break;
|
|
|
|
case 2:
|
|
magnification = 2;
|
|
fullscreen = TRUE;
|
|
lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
|
|
lpDD->SetDisplayMode(WINDOW_WIDTH * magnification, WINDOW_HEIGHT * magnification, lColourDepth);
|
|
break;
|
|
}
|
|
|
|
backbuffer_rect.left = 0;
|
|
backbuffer_rect.top = 0;
|
|
backbuffer_rect.right = WINDOW_WIDTH * magnification;
|
|
backbuffer_rect.bottom = WINDOW_HEIGHT * magnification;
|
|
|
|
scaled_window_width = WINDOW_WIDTH * magnification;
|
|
scaled_window_height = WINDOW_HEIGHT * magnification;
|
|
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
ddsd.dwFlags = DDSD_CAPS;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
ddsd.dwBackBufferCount = 0;
|
|
|
|
if (lpDD->CreateSurface(&ddsd, &frontbuffer, NULL) != DD_OK)
|
|
return FALSE;
|
|
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.dwWidth = WINDOW_WIDTH * magnification;
|
|
ddsd.dwHeight = WINDOW_HEIGHT * magnification;
|
|
|
|
if (lpDD->CreateSurface(&ddsd, &backbuffer, NULL) != DD_OK)
|
|
return FALSE;
|
|
|
|
lpDD->CreateClipper(0, &clipper, NULL);
|
|
clipper->SetHWnd(0, hWnd);
|
|
frontbuffer->SetClipper(clipper);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void EndDirectDraw(HWND hWnd)
|
|
{
|
|
// Release all surfaces
|
|
for (int i = 0; i < SURFACE_ID_MAX; ++i)
|
|
{
|
|
if (surf[i] != NULL)
|
|
{
|
|
surf[i]->Release();
|
|
surf[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if (frontbuffer != NULL)
|
|
{
|
|
frontbuffer->Release();
|
|
frontbuffer = NULL;
|
|
backbuffer = NULL;
|
|
}
|
|
|
|
if (fullscreen)
|
|
lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
|
|
|
|
if (lpDD != NULL)
|
|
{
|
|
lpDD->Release();
|
|
lpDD = NULL;
|
|
}
|
|
|
|
memset(surface_metadata, 0, sizeof(surface_metadata));
|
|
}
|
|
|
|
void ReleaseSurface(SurfaceID s)
|
|
{
|
|
// Release the surface we want to release
|
|
if (surf[s] != NULL)
|
|
{
|
|
surf[s]->Release();
|
|
surf[s] = NULL;
|
|
}
|
|
|
|
memset(&surface_metadata[s], 0, sizeof(surface_metadata[0]));
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
BOOL MakeSurface_Resource(const char *name, SurfaceID surf_no)
|
|
{
|
|
if (surf_no >= SURFACE_ID_MAX)
|
|
return FALSE;
|
|
|
|
if (surf[surf_no] != NULL)
|
|
return FALSE;
|
|
|
|
HANDLE handle = LoadImageA(GetModuleHandleA(NULL), name, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
|
|
if (handle == NULL)
|
|
return FALSE;
|
|
|
|
BITMAP bitmap;
|
|
GetObjectA(handle, sizeof(BITMAP), &bitmap);
|
|
|
|
DDSURFACEDESC ddsd;
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.dwWidth = bitmap.bmWidth * magnification;
|
|
ddsd.dwHeight = bitmap.bmHeight * magnification;
|
|
|
|
if (lpDD->CreateSurface(&ddsd, &surf[surf_no], NULL) != DD_OK)
|
|
return FALSE;
|
|
|
|
int src_x = 0;
|
|
int src_y = 0;
|
|
int src_w = bitmap.bmWidth;
|
|
int src_h = bitmap.bmHeight;
|
|
|
|
int dst_x = 0;
|
|
int dst_y = 0;
|
|
int dst_w = bitmap.bmWidth * magnification;
|
|
int dst_h = bitmap.bmHeight * magnification;
|
|
|
|
HDC hdc = CreateCompatibleDC(NULL);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, handle);
|
|
|
|
HDC hdc2;
|
|
surf[surf_no]->GetDC(&hdc2);
|
|
StretchBlt(hdc2, dst_x, dst_y, dst_w, dst_h, hdc, src_x, src_y, src_w, src_h, SRCCOPY);
|
|
surf[surf_no]->ReleaseDC(hdc2);
|
|
|
|
SelectObject(hdc, hgdiobj);
|
|
DeleteDC(hdc);
|
|
|
|
DDCOLORKEY ddcolorkey;
|
|
ddcolorkey.dwColorSpaceLowValue = 0;
|
|
ddcolorkey.dwColorSpaceHighValue = 0;
|
|
|
|
surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
|
|
surf[surf_no]->SetClipper(clipper);
|
|
|
|
#ifdef FIX_BUGS
|
|
DeleteObject(handle);
|
|
#endif
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_RESOURCE;
|
|
surface_metadata[surf_no].width = bitmap.bmWidth;
|
|
surface_metadata[surf_no].height = bitmap.bmHeight;
|
|
surface_metadata[surf_no].bSystem = FALSE;
|
|
strcpy(surface_metadata[surf_no].name, name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
BOOL MakeSurface_File(const char *name, SurfaceID surf_no)
|
|
{
|
|
char path[MAX_PATH];
|
|
sprintf(path, "%s\\%s.pbm", gDataPath, name);
|
|
|
|
if (!IsEnableBitmap(path))
|
|
{
|
|
PrintBitmapError(path, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef FIX_BUGS
|
|
if (surf_no >= SURFACE_ID_MAX)
|
|
#else
|
|
if (surf_no > SURFACE_ID_MAX)
|
|
#endif
|
|
{
|
|
PrintBitmapError("surface no", surf_no);
|
|
return FALSE;
|
|
}
|
|
|
|
if (surf[surf_no] != NULL)
|
|
{
|
|
PrintBitmapError("existing", surf_no);
|
|
return FALSE;
|
|
}
|
|
|
|
HANDLE handle = LoadImageA(GetModuleHandleA(NULL), path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
|
|
if (handle == NULL)
|
|
{
|
|
PrintBitmapError(path, 1);
|
|
return FALSE;
|
|
}
|
|
|
|
BITMAP bitmap;
|
|
GetObjectA(handle, sizeof(BITMAP), &bitmap);
|
|
|
|
DDSURFACEDESC ddsd;
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.dwWidth = bitmap.bmWidth * magnification;
|
|
ddsd.dwHeight = bitmap.bmHeight * magnification;
|
|
|
|
lpDD->CreateSurface(&ddsd, &surf[surf_no], NULL);
|
|
|
|
int src_x = 0;
|
|
int src_y = 0;
|
|
int src_w = bitmap.bmWidth;
|
|
int src_h = bitmap.bmHeight;
|
|
|
|
int dst_x = 0;
|
|
int dst_y = 0;
|
|
int dst_w = bitmap.bmWidth * magnification;
|
|
int dst_h = bitmap.bmHeight * magnification;
|
|
|
|
HDC hdc = CreateCompatibleDC(NULL);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, handle);
|
|
|
|
HDC hdc2;
|
|
surf[surf_no]->GetDC(&hdc2);
|
|
StretchBlt(hdc2, dst_x, dst_y, dst_w, dst_h, hdc, src_x, src_y, src_w, src_h, SRCCOPY);
|
|
surf[surf_no]->ReleaseDC(hdc2);
|
|
|
|
SelectObject(hdc, hgdiobj);
|
|
DeleteDC(hdc);
|
|
|
|
DDCOLORKEY ddcolorkey;
|
|
ddcolorkey.dwColorSpaceLowValue = 0;
|
|
ddcolorkey.dwColorSpaceHighValue = 0;
|
|
|
|
surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
|
|
surf[surf_no]->SetClipper(clipper);
|
|
|
|
DeleteObject(handle);
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_FILE;
|
|
surface_metadata[surf_no].width = bitmap.bmWidth;
|
|
surface_metadata[surf_no].height = bitmap.bmHeight;
|
|
surface_metadata[surf_no].bSystem = FALSE;
|
|
strcpy(surface_metadata[surf_no].name, name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
BOOL ReloadBitmap_Resource(const char *name, SurfaceID surf_no)
|
|
{
|
|
if (surf_no >= SURFACE_ID_MAX)
|
|
return FALSE;
|
|
|
|
HANDLE handle = LoadImageA(GetModuleHandleA(NULL), name, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
|
|
if (handle == NULL)
|
|
return FALSE;
|
|
|
|
BITMAP bitmap;
|
|
GetObjectA(handle, sizeof(BITMAP), &bitmap);
|
|
|
|
int src_x = 0;
|
|
int src_y = 0;
|
|
int src_w = bitmap.bmWidth;
|
|
int src_h = bitmap.bmHeight;
|
|
|
|
int dst_x = 0;
|
|
int dst_y = 0;
|
|
int dst_w = bitmap.bmWidth * magnification;
|
|
int dst_h = bitmap.bmHeight * magnification;
|
|
|
|
HDC hdc = CreateCompatibleDC(NULL);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, handle);
|
|
|
|
HDC hdc2;
|
|
surf[surf_no]->GetDC(&hdc2);
|
|
StretchBlt(hdc2, dst_x, dst_y, dst_w, dst_h, hdc, src_x, src_y, src_w, src_h, SRCCOPY);
|
|
surf[surf_no]->ReleaseDC(hdc2);
|
|
|
|
SelectObject(hdc, hgdiobj);
|
|
DeleteDC(hdc);
|
|
|
|
DDCOLORKEY ddcolorkey;
|
|
ddcolorkey.dwColorSpaceLowValue = 0;
|
|
ddcolorkey.dwColorSpaceHighValue = 0;
|
|
|
|
surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
|
|
surf[surf_no]->SetClipper(clipper);
|
|
|
|
#ifdef FIX_BUGS
|
|
DeleteObject(handle);
|
|
#endif
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_RESOURCE;
|
|
strcpy(surface_metadata[surf_no].name, name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
BOOL ReloadBitmap_File(const char *name, SurfaceID surf_no)
|
|
{
|
|
char path[MAX_PATH];
|
|
sprintf(path, "%s\\%s.pbm", gDataPath, name);
|
|
|
|
if (!IsEnableBitmap(path))
|
|
{
|
|
PrintBitmapError(path, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef FIX_BUGS
|
|
if (surf_no >= SURFACE_ID_MAX)
|
|
#else
|
|
if (surf_no > SURFACE_ID_MAX)
|
|
#endif
|
|
{
|
|
PrintBitmapError("surface no", surf_no);
|
|
return FALSE;
|
|
}
|
|
|
|
HANDLE handle = LoadImageA(GetModuleHandleA(NULL), path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
|
|
if (handle == NULL)
|
|
{
|
|
PrintBitmapError(path, 1);
|
|
return FALSE;
|
|
}
|
|
|
|
BITMAP bitmap;
|
|
GetObjectA(handle, sizeof(BITMAP), &bitmap);
|
|
|
|
int src_x = 0;
|
|
int src_y = 0;
|
|
int src_w = bitmap.bmWidth;
|
|
int src_h = bitmap.bmHeight;
|
|
|
|
int dst_x = 0;
|
|
int dst_y = 0;
|
|
int dst_w = bitmap.bmWidth * magnification;
|
|
int dst_h = bitmap.bmHeight * magnification;
|
|
|
|
HDC hdc = CreateCompatibleDC(NULL);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, handle);
|
|
|
|
HDC hdc2;
|
|
surf[surf_no]->GetDC(&hdc2);
|
|
StretchBlt(hdc2, dst_x, dst_y, dst_w, dst_h, hdc, src_x, src_y, src_w, src_h, SRCCOPY);
|
|
surf[surf_no]->ReleaseDC(hdc2);
|
|
|
|
SelectObject(hdc, hgdiobj);
|
|
DeleteDC(hdc);
|
|
|
|
// No colour-keying
|
|
|
|
DeleteObject(handle);
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_FILE;
|
|
strcpy(surface_metadata[surf_no].name, name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
BOOL MakeSurface_Generic(int bxsize, int bysize, SurfaceID surf_no, BOOL bSystem)
|
|
{
|
|
#ifdef FIX_BUGS
|
|
if (surf_no >= SURFACE_ID_MAX)
|
|
#else
|
|
if (surf_no > SURFACE_ID_MAX) // OOPS (should be '>=')
|
|
#endif
|
|
return FALSE;
|
|
|
|
if (surf[surf_no] != NULL)
|
|
return FALSE;
|
|
|
|
DDSURFACEDESC ddsd;
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
|
|
if (bSystem)
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
else
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
|
|
ddsd.dwWidth = bxsize * magnification;
|
|
ddsd.dwHeight = bysize * magnification;
|
|
|
|
lpDD->CreateSurface(&ddsd, &surf[surf_no], NULL);
|
|
|
|
DDCOLORKEY ddcolorkey;
|
|
ddcolorkey.dwColorSpaceLowValue = 0;
|
|
ddcolorkey.dwColorSpaceHighValue = 0;
|
|
|
|
surf[surf_no]->SetColorKey(DDCKEY_SRCBLT, &ddcolorkey);
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_NONE;
|
|
surface_metadata[surf_no].width = ddsd.dwWidth / magnification;
|
|
surface_metadata[surf_no].height = ddsd.dwHeight / magnification;
|
|
|
|
if (bSystem)
|
|
surface_metadata[surf_no].bSystem = TRUE;
|
|
else
|
|
surface_metadata[surf_no].bSystem = FALSE;
|
|
|
|
strcpy(surface_metadata[surf_no].name, "generic");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void BackupSurface(SurfaceID surf_no, const RECT *rect)
|
|
{
|
|
static DDBLTFX ddbltfx;
|
|
|
|
memset(&ddbltfx, 0, sizeof(DDBLTFX));
|
|
ddbltfx.dwSize = sizeof(DDBLTFX);
|
|
|
|
static RECT scaled_rect;
|
|
scaled_rect.left = rect->left * magnification;
|
|
scaled_rect.top = rect->top * magnification;
|
|
scaled_rect.right = rect->right * magnification;
|
|
scaled_rect.bottom = rect->bottom * magnification;
|
|
|
|
surf[surf_no]->Blt(&scaled_rect, backbuffer, &scaled_rect, DDBLT_WAIT, &ddbltfx);
|
|
}
|
|
|
|
void PutBitmap3(const RECT *rcView, int x, int y, const RECT *rect, SurfaceID surf_no) // Transparency
|
|
{
|
|
static RECT src_rect;
|
|
static RECT dst_rect;
|
|
|
|
src_rect = *rect;
|
|
|
|
if (x + rect->right - rect->left > rcView->right)
|
|
src_rect.right -= (x + rect->right - rect->left) - rcView->right;
|
|
|
|
if (x < rcView->left)
|
|
{
|
|
src_rect.left += rcView->left - x;
|
|
x = rcView->left;
|
|
}
|
|
|
|
if (y + rect->bottom - rect->top > rcView->bottom)
|
|
src_rect.bottom -= (y + rect->bottom - rect->top) - rcView->bottom;
|
|
|
|
if (y < rcView->top)
|
|
{
|
|
src_rect.top += rcView->top - y;
|
|
y = rcView->top;
|
|
}
|
|
|
|
dst_rect.left = x;
|
|
dst_rect.top = y;
|
|
dst_rect.right = x + src_rect.right - src_rect.left;
|
|
dst_rect.bottom = y + src_rect.bottom - src_rect.top;
|
|
|
|
src_rect.left *= magnification;
|
|
src_rect.top *= magnification;
|
|
src_rect.right *= magnification;
|
|
src_rect.bottom *= magnification;
|
|
|
|
dst_rect.left *= magnification;
|
|
dst_rect.top *= magnification;
|
|
dst_rect.right *= magnification;
|
|
dst_rect.bottom *= magnification;
|
|
|
|
backbuffer->Blt(&dst_rect, surf[surf_no], &src_rect, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
|
|
}
|
|
|
|
void PutBitmap4(const RECT *rcView, int x, int y, const RECT *rect, SurfaceID surf_no) // No Transparency
|
|
{
|
|
static RECT src_rect;
|
|
static RECT dst_rect;
|
|
|
|
src_rect = *rect;
|
|
|
|
if (x + rect->right - rect->left > rcView->right)
|
|
src_rect.right -= (x + rect->right - rect->left) - rcView->right;
|
|
|
|
if (x < rcView->left)
|
|
{
|
|
src_rect.left += rcView->left - x;
|
|
x = rcView->left;
|
|
}
|
|
|
|
if (y + rect->bottom - rect->top > rcView->bottom)
|
|
src_rect.bottom -= (y + rect->bottom - rect->top) - rcView->bottom;
|
|
|
|
if (y < rcView->top)
|
|
{
|
|
src_rect.top += rcView->top - y;
|
|
y = rcView->top;
|
|
}
|
|
|
|
dst_rect.left = x;
|
|
dst_rect.top = y;
|
|
dst_rect.right = x + src_rect.right - src_rect.left;
|
|
dst_rect.bottom = y + src_rect.bottom - src_rect.top;
|
|
|
|
src_rect.left *= magnification;
|
|
src_rect.top *= magnification;
|
|
src_rect.right *= magnification;
|
|
src_rect.bottom *= magnification;
|
|
|
|
dst_rect.left *= magnification;
|
|
dst_rect.top *= magnification;
|
|
dst_rect.right *= magnification;
|
|
dst_rect.bottom *= magnification;
|
|
|
|
backbuffer->Blt(&dst_rect, surf[surf_no], &src_rect, DDBLT_WAIT, NULL);
|
|
}
|
|
|
|
void Surface2Surface(int x, int y, const RECT *rect, int to, int from)
|
|
{
|
|
static RECT src_rect;
|
|
static RECT dst_rect;
|
|
|
|
src_rect.left = rect->left * magnification;
|
|
src_rect.top = rect->top * magnification;
|
|
src_rect.right = rect->right * magnification;
|
|
src_rect.bottom = rect->bottom * magnification;
|
|
|
|
dst_rect.left = x;
|
|
dst_rect.top = y;
|
|
dst_rect.right = x + rect->right - rect->left;
|
|
dst_rect.bottom = y + rect->bottom - rect->top;
|
|
|
|
dst_rect.left *= magnification;
|
|
dst_rect.top *= magnification;
|
|
dst_rect.right *= magnification;
|
|
dst_rect.bottom *= magnification;
|
|
|
|
surf[to]->Blt(&dst_rect, surf[from], &src_rect, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
|
|
}
|
|
|
|
// This converts a colour to the 'native' format by writing it
|
|
// straight to the framebuffer, and then reading it back
|
|
unsigned long GetCortBoxColor(COLORREF col)
|
|
{
|
|
HDC hdc;
|
|
|
|
if (backbuffer->GetDC(&hdc) != DD_OK)
|
|
return 0xFFFFFFFF;
|
|
|
|
COLORREF original_colour = GetPixel(hdc, 0, 0);
|
|
SetPixel(hdc, 0, 0, col);
|
|
backbuffer->ReleaseDC(hdc);
|
|
|
|
DDSURFACEDESC ddsd;
|
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
if (backbuffer->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK)
|
|
return 0xFFFFFFFF;
|
|
|
|
DWORD native_colour = *(DWORD*)ddsd.lpSurface;
|
|
|
|
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
|
|
native_colour &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
|
|
|
|
backbuffer->Unlock(0);
|
|
|
|
if (backbuffer->GetDC(&hdc) != DD_OK)
|
|
return 0xFFFFFFFF;
|
|
|
|
SetPixel(hdc, 0, 0, original_colour);
|
|
backbuffer->ReleaseDC(hdc);
|
|
|
|
return native_colour;
|
|
}
|
|
|
|
void CortBox(const RECT *rect, unsigned long col)
|
|
{
|
|
static DDBLTFX ddbltfx;
|
|
memset(&ddbltfx, 0, sizeof(DDBLTFX));
|
|
ddbltfx.dwSize = sizeof(DDBLTFX);
|
|
ddbltfx.dwFillColor = col;
|
|
|
|
static RECT dst_rect;
|
|
dst_rect.left = rect->left * magnification;
|
|
dst_rect.top = rect->top * magnification;
|
|
dst_rect.right = rect->right * magnification;
|
|
dst_rect.bottom = rect->bottom * magnification;
|
|
|
|
backbuffer->Blt(&dst_rect, 0, 0, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
|
|
}
|
|
|
|
void CortBox2(const RECT *rect, unsigned long col, SurfaceID surf_no)
|
|
{
|
|
static DDBLTFX ddbltfx;
|
|
memset(&ddbltfx, 0, sizeof(DDBLTFX));
|
|
ddbltfx.dwSize = sizeof(DDBLTFX);
|
|
ddbltfx.dwFillColor = col;
|
|
|
|
static RECT dst_rect;
|
|
dst_rect.left = rect->left * magnification;
|
|
dst_rect.top = rect->top * magnification;
|
|
dst_rect.right = rect->right * magnification;
|
|
dst_rect.bottom = rect->bottom * magnification;
|
|
|
|
surface_metadata[surf_no].type = SURFACE_SOURCE_NONE;
|
|
|
|
surf[surf_no]->Blt(&dst_rect, 0, 0, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
|
|
}
|
|
|
|
BOOL DummiedOutLogFunction(int unknown)
|
|
{
|
|
char unknown2[0x100];
|
|
int unknown3;
|
|
int unknown4;
|
|
int unknown5;
|
|
|
|
(void)unknown;
|
|
(void)unknown2;
|
|
(void)unknown3;
|
|
(void)unknown4;
|
|
(void)unknown5;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int RestoreSurfaces(void) // Guessed function name - this doesn't exist in the Linux port
|
|
{
|
|
RECT rect;
|
|
int surfaces_regenerated = 0;
|
|
|
|
if (frontbuffer == NULL)
|
|
return surfaces_regenerated;
|
|
|
|
if (backbuffer == NULL)
|
|
return surfaces_regenerated;
|
|
|
|
if (frontbuffer->IsLost() == DDERR_SURFACELOST)
|
|
{
|
|
++surfaces_regenerated;
|
|
frontbuffer->Restore();
|
|
DummiedOutLogFunction(0x66);
|
|
}
|
|
|
|
if (backbuffer->IsLost() == DDERR_SURFACELOST)
|
|
{
|
|
++surfaces_regenerated;
|
|
backbuffer->Restore();
|
|
DummiedOutLogFunction(0x62);
|
|
}
|
|
|
|
for (int s = 0; s < SURFACE_ID_MAX; ++s )
|
|
{
|
|
if (surf[s] != NULL)
|
|
{
|
|
if (surf[s]->IsLost() == DDERR_SURFACELOST)
|
|
{
|
|
++surfaces_regenerated;
|
|
surf[s]->Restore();
|
|
DummiedOutLogFunction(0x30 + s);
|
|
|
|
if (!surface_metadata[s].bSystem)
|
|
{
|
|
switch (surface_metadata[s].type)
|
|
{
|
|
case SURFACE_SOURCE_NONE:
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = surface_metadata[s].width;
|
|
rect.bottom = surface_metadata[s].height;
|
|
CortBox2(&rect, 0, (SurfaceID)s);
|
|
break;
|
|
|
|
case SURFACE_SOURCE_RESOURCE:
|
|
ReloadBitmap_Resource(surface_metadata[s].name, (SurfaceID)s);
|
|
break;
|
|
|
|
case SURFACE_SOURCE_FILE:
|
|
ReloadBitmap_File(surface_metadata[s].name, (SurfaceID)s);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return surfaces_regenerated;
|
|
}
|
|
|
|
// TODO - Inaccurate stack frame
|
|
void InitTextObject(const char *name)
|
|
{
|
|
// Get font size
|
|
unsigned int width, height;
|
|
|
|
switch (magnification)
|
|
{
|
|
case 1:
|
|
height = 12;
|
|
width = 6;
|
|
break;
|
|
|
|
case 2:
|
|
height = 20;
|
|
width = 10;
|
|
break;
|
|
}
|
|
|
|
// The game uses DEFAULT_CHARSET when it should have used SHIFTJIS_CHARSET.
|
|
// This breaks the Japanese text on English Windows installations.
|
|
|
|
// Also, the game uses DEFAULT_QUALITY instead of NONANTIALIASED_QUALITY,
|
|
// causing font antialiasing to blend with the colour-key, giving text ab
|
|
// ugly black outline.
|
|
#ifdef FIX_BUGS
|
|
#define QUALITY NONANTIALIASED_QUALITY
|
|
#ifdef JAPANESE
|
|
#define CHARSET SHIFTJIS_CHARSET
|
|
#else
|
|
#define CHARSET DEFAULT_CHARSET
|
|
#endif
|
|
#else
|
|
#define QUALITY DEFAULT_QUALITY
|
|
#define CHARSET DEFAULT_CHARSET
|
|
#endif
|
|
|
|
font = CreateFontA(height, width, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, QUALITY, FIXED_PITCH | FF_DONTCARE, name);
|
|
|
|
if (font == NULL)
|
|
font = CreateFontA(height, width, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, QUALITY, FIXED_PITCH | FF_DONTCARE, NULL);
|
|
}
|
|
|
|
void PutText(int x, int y, const char *text, unsigned long color)
|
|
{
|
|
HDC hdc;
|
|
backbuffer->GetDC(&hdc);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, font);
|
|
SetBkMode(hdc, 1);
|
|
SetTextColor(hdc, color);
|
|
TextOutA(hdc, x * magnification, y * magnification, text, (int)strlen(text));
|
|
SelectObject(hdc, hgdiobj);
|
|
backbuffer->ReleaseDC(hdc);
|
|
}
|
|
|
|
void PutText2(int x, int y, const char *text, unsigned long color, SurfaceID surf_no)
|
|
{
|
|
HDC hdc;
|
|
surf[surf_no]->GetDC(&hdc);
|
|
HGDIOBJ hgdiobj = SelectObject(hdc, font);
|
|
SetBkMode(hdc, 1);
|
|
SetTextColor(hdc, color);
|
|
TextOutA(hdc, x * magnification, y * magnification, text, (int)strlen(text));
|
|
SelectObject(hdc, hgdiobj);
|
|
surf[surf_no]->ReleaseDC(hdc);
|
|
}
|
|
|
|
void EndTextObject(void)
|
|
{
|
|
DeleteObject(font);
|
|
}
|