/**
* @file dd2.cpp
* @brief DirectDraw 2 surface
*
* @author $Author: yui $
* @date $Date: 2011/03/07 09:54:11 $
*/
#include "compiler.h"
#include <ddraw.h>
#include "dd2.h"
#if !defined(__GNUC__)
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")
#endif // !defined(__GNUC__)
typedef struct {
HWND hwnd;
LPDIRECTDRAW ddraw1;
LPDIRECTDRAW2 ddraw;
LPDIRECTDRAWSURFACE primsurf;
LPDIRECTDRAWSURFACE backsurf;
DDPIXELFORMAT ddpf;
LPDIRECTDRAWCLIPPER clipper;
LPDIRECTDRAWPALETTE palette;
int cliping;
RGB32 pal16;
UINT8 r16b;
UINT8 l16r;
UINT8 l16g;
CMNVRAM vram;
PALETTEENTRY pal[256];
} _DD2SURF, *DD2SURF;
DD2HDL dd2_create(HWND hwnd, int width, int height) {
DD2SURF dd2;
DDSURFACEDESC ddsd;
HDC hdc;
dd2 = (DD2SURF)_MALLOC(sizeof(_DD2SURF), "dd2surf");
if (dd2 == NULL) {
goto dd2cre_err1;
}
ZeroMemory(dd2, sizeof(_DD2SURF));
dd2->hwnd = hwnd;
if (DirectDrawCreate(NULL, &dd2->ddraw1, NULL) != DD_OK) {
goto dd2cre_err2;
}
dd2->ddraw1->QueryInterface(IID_IDirectDraw2, (void **)&dd2->ddraw);
dd2->ddraw->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (dd2->ddraw->CreateSurface(&ddsd, &dd2->primsurf, NULL) != DD_OK) {
goto dd2cre_err2;
}
dd2->ddraw->CreateClipper(0, &dd2->clipper, NULL);
dd2->clipper->SetHWnd(0, hwnd);
dd2->primsurf->SetClipper(dd2->clipper);
ZeroMemory(&dd2->ddpf, sizeof(DDPIXELFORMAT));
dd2->ddpf.dwSize = sizeof(DDPIXELFORMAT);
if (dd2->primsurf->GetPixelFormat(&dd2->ddpf) != DD_OK) {
goto dd2cre_err2;
}
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = width;
ddsd.dwHeight = height;
if (dd2->ddraw->CreateSurface(&ddsd, &dd2->backsurf, NULL) != DD_OK) {
goto dd2cre_err2;
}
if (dd2->ddpf.dwRGBBitCount == 8) {
hdc = GetDC(hwnd);
GetSystemPaletteEntries(hdc, 0, 256, dd2->pal);
ReleaseDC(hwnd, hdc);
dd2->ddraw->CreatePalette(DDPCAPS_8BIT, dd2->pal, &dd2->palette, 0);
dd2->primsurf->SetPalette(dd2->palette);
}
else if (dd2->ddpf.dwRGBBitCount == 16) {
WORD bit;
UINT8 cnt;
dd2->pal16.d = 0;
for (bit=1; (bit) && (!(dd2->ddpf.dwBBitMask & bit)); bit<<=1);
for (dd2->r16b=8; (dd2->r16b) && (dd2->ddpf.dwBBitMask & bit);
dd2->r16b--, bit<<=1) {
dd2->pal16.p.b >>= 1;
dd2->pal16.p.b |= 0x80;
}
for (dd2->l16r=0, bit=1; (bit) && (!(dd2->ddpf.dwRBitMask & bit));
dd2->l16r++, bit<<=1);
for (cnt=0x80; (cnt) && (dd2->ddpf.dwRBitMask & bit);
cnt>>=1, bit<<=1) {
dd2->pal16.p.r |= cnt;
}
for (; cnt; cnt>>=1) dd2->l16r--;
for (dd2->l16g=0, bit=1; (bit) && (!(dd2->ddpf.dwGBitMask & bit));
dd2->l16g++, bit<<=1);
for (cnt=0x80; (cnt) && (dd2->ddpf.dwGBitMask & bit);
cnt>>=1, bit<<=1) {
dd2->pal16.p.g |= cnt;
}
for (; cnt; cnt>>=1) dd2->l16g--;
}
else if (dd2->ddpf.dwRGBBitCount == 24) {
}
else if (dd2->ddpf.dwRGBBitCount == 32) {
}
else {
goto dd2cre_err2;
}
dd2->cliping = 0;
dd2->vram.width = width;
dd2->vram.height = height;
dd2->vram.xalign = dd2->ddpf.dwRGBBitCount / 8;
dd2->vram.bpp = dd2->ddpf.dwRGBBitCount;
return((DD2HDL)dd2);
dd2cre_err2:
dd2_release(dd2);
_MFREE(dd2);
dd2cre_err1:
return(NULL);
}
void dd2_release(DD2HDL dd2hdl) {
DD2SURF dd2;
dd2 = (DD2SURF)dd2hdl;
if (dd2) {
RELEASE(dd2->palette);
RELEASE(dd2->clipper);
RELEASE(dd2->backsurf);
RELEASE(dd2->primsurf);
RELEASE(dd2->ddraw);
RELEASE(dd2->ddraw1);
_MFREE(dd2);
}
}
CMNVRAM *dd2_bsurflock(DD2HDL dd2hdl) {
DD2SURF dd2;
DDSURFACEDESC surface;
HRESULT r;
dd2 = (DD2SURF)dd2hdl;
if ((dd2 == NULL) || (dd2->backsurf == NULL)) {
return(NULL);
}
ZeroMemory(&surface, sizeof(DDSURFACEDESC));
surface.dwSize = sizeof(DDSURFACEDESC);
r = dd2->backsurf->Lock(NULL, &surface, DDLOCK_WAIT, NULL);
if (r == DDERR_SURFACELOST) {
dd2->backsurf->Restore();
r = dd2->backsurf->Lock(NULL, &surface, DDLOCK_WAIT, NULL);
}
if (r != DD_OK) {
return(NULL);
}
dd2->vram.ptr = (UINT8 *)surface.lpSurface;
dd2->vram.yalign = surface.lPitch;
return(&dd2->vram);
}
void dd2_bsurfunlock(DD2HDL dd2hdl) {
DD2SURF dd2;
dd2 = (DD2SURF)dd2hdl;
if ((dd2) && (dd2->backsurf)) {
dd2->backsurf->Unlock(NULL);
}
}
void dd2_blt(DD2HDL dd2hdl, const POINT *pt, const RECT *rect) {
DD2SURF dd2;
POINT clipt;
RECT scrn;
dd2 = (DD2SURF)dd2hdl;
if ((dd2) && (dd2->backsurf)) {
if (pt) {
clipt = *pt;
}
else {
clipt.x = 0;
clipt.y = 0;
}
ClientToScreen(dd2->hwnd, &clipt);
scrn.left = clipt.x;
scrn.top = clipt.y;
scrn.right = clipt.x + rect->right - rect->left;
scrn.bottom = clipt.y + rect->bottom - rect->top;
if (dd2->primsurf->Blt(&scrn, dd2->backsurf, (RECT *)rect,
DDBLT_WAIT, NULL) == DDERR_SURFACELOST) {
dd2->backsurf->Restore();
dd2->primsurf->Restore();
}
}
}
UINT16 dd2_get16pal(DD2HDL dd2hdl, RGB32 pal) {
DD2SURF dd2;
dd2 = (DD2SURF)dd2hdl;
if (dd2) {
pal.d &= dd2->pal16.d;
return((((UINT16)pal.p.g) << dd2->l16g) |
(((UINT16)pal.p.r) << dd2->l16r) | (pal.p.b >> dd2->r16b));
}
else {
return(0);
}
}
RetroPC.NET-CVS <cvs@retropc.net>