More cleanups.
Added more languages. Updated SCAT machines (for the Asian demo machines.) Fixed VC project files. Started integrating building of language DLL's into mainline. Added the Award 8088 XT Clone machine.
This commit is contained in:
@@ -8,15 +8,12 @@
|
||||
*
|
||||
* Rendering module for Microsoft DirectDraw 9.
|
||||
*
|
||||
* NOTES: This code should be re-merged into a single init() with a
|
||||
* 'fullscreen' argument, indicating FS mode is requested.
|
||||
*
|
||||
* If configured with USE_LIBPNG, we try to load the external
|
||||
* PNG library and use that if found. Otherwise, we fall back
|
||||
* the original mode, which uses the Windows/DDraw built-in BMP
|
||||
* format.
|
||||
*
|
||||
* Version: @(#)win_ddraw.cpp 1.0.13 2018/05/24
|
||||
* Version: @(#)win_ddraw.cpp 1.0.15 2018/06/11
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -91,6 +88,8 @@ png_structp (*PNG_create_write_struct)(png_const_charp user_png_ver,
|
||||
png_voidp error_ptr,
|
||||
png_error_ptr error_fn,
|
||||
png_error_ptr warn_fn);
|
||||
void (*PNG_destroy_write_struct)(png_structpp png_ptr_ptr,
|
||||
png_infopp info_ptr_ptr);
|
||||
png_infop (*PNG_create_info_struct)(png_const_structrp png_ptr);
|
||||
void (*PNG_init_io)(png_structrp png_ptr, png_FILE_p fp);
|
||||
void (*PNG_set_IHDR)(png_const_structrp png_ptr,
|
||||
@@ -112,6 +111,7 @@ void (*PNG_write_end)(png_structrp png_ptr,
|
||||
|
||||
static const dllimp_t png_imports[] = {
|
||||
{ "png_create_write_struct", &PNG_create_write_struct },
|
||||
{ "png_destroy_write_struct", &PNG_destroy_write_struct },
|
||||
{ "png_create_info_struct", &PNG_create_info_struct },
|
||||
{ "png_init_io", &PNG_init_io },
|
||||
{ "png_set_IHDR", &PNG_set_IHDR },
|
||||
@@ -211,288 +211,6 @@ GetError(HRESULT hr)
|
||||
}
|
||||
|
||||
|
||||
static HBITMAP
|
||||
CopySurface(IDirectDrawSurface4 *pDDSurface)
|
||||
{
|
||||
HBITMAP hbmp, hbmprev;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
HDC hdc, hmemdc;
|
||||
|
||||
pDDSurface->GetDC(&hdc);
|
||||
hmemdc = CreateCompatibleDC(hdc);
|
||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
pDDSurface->GetSurfaceDesc(&ddsd);
|
||||
hbmp = CreateCompatibleBitmap(hdc, xs, ys);
|
||||
hbmprev = (HBITMAP)SelectObject(hmemdc, hbmp);
|
||||
BitBlt(hmemdc, 0, 0, xs, ys, hdc, 0, 0, SRCCOPY);
|
||||
SelectObject(hmemdc, hbmprev);
|
||||
DeleteDC(hmemdc);
|
||||
pDDSurface->ReleaseDC(hdc);
|
||||
|
||||
return(hbmp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DoubleLines(uint8_t *dst, uint8_t *src)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < ys; i++) {
|
||||
memcpy(dst + (i * xs * 8), src + (i * xs * 4), xs * 4);
|
||||
memcpy(dst + ((i * xs * 8) + (xs * 4)), src + (i * xs * 4), xs * 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_LIBPNG
|
||||
static void
|
||||
bgra_to_rgb(png_bytep *b_rgb, uint8_t *bgra, int width, int height)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *r, *b;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
for (j = 0; j < width; j++) {
|
||||
r = &b_rgb[(height - 1) - i][j * 3];
|
||||
b = &bgra[((i * width) + j) * 4];
|
||||
r[0] = b[2];
|
||||
r[1] = b[1];
|
||||
r[2] = b[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Not strictly needed, but hey.. */
|
||||
static void
|
||||
png_error_handler(png_structp arg, const char *str)
|
||||
{
|
||||
pclog("DDraw: PNG error '%08lx'\n", str);
|
||||
}
|
||||
|
||||
|
||||
/* Not strictly needed, but hey.. */
|
||||
static void
|
||||
png_warning_handler(png_structp arg, const char *str)
|
||||
{
|
||||
pclog("DDraw: PNG warning '%08lx'\n", str);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SavePNG(const wchar_t *fn, HBITMAP hBitmap)
|
||||
{
|
||||
wchar_t temp[512];
|
||||
BITMAPINFO bmpInfo;
|
||||
HDC hdc;
|
||||
LPVOID pBuf = NULL;
|
||||
LPVOID pBuf2 = NULL;
|
||||
png_bytep *b_rgb = NULL;
|
||||
png_infop info_ptr;
|
||||
png_structp png_ptr;
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
/* Create file. */
|
||||
fp = plat_fopen(fn, L"wb");
|
||||
if (fp == NULL) {
|
||||
pclog("[SavePNG] File %ls could not be opened for writing!\n", fn);
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize PNG stuff. */
|
||||
png_ptr = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, (char *)1234,
|
||||
png_error_handler, png_warning_handler);
|
||||
if (png_ptr == NULL) {
|
||||
(void)fclose(fp);
|
||||
pclog("[SavePNG] png_create_write_struct failed!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr = PNGFUNC(create_info_struct)(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
// PNGFUNC(destroy_write_struct)(&png_ptr, NULL, NULL);
|
||||
(void)fclose(fp);
|
||||
pclog("[SavePNG] png_create_info_struct failed!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
PNGFUNC(init_io)(png_ptr, fp);
|
||||
|
||||
hdc = GetDC(NULL);
|
||||
|
||||
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
|
||||
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
|
||||
if (bmpInfo.bmiHeader.biSizeImage <= 0)
|
||||
bmpInfo.bmiHeader.biSizeImage =
|
||||
bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
|
||||
|
||||
if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
|
||||
// PNGFUNC(destroy_write_struct)(&png_ptr, &info_ptr, NULL);
|
||||
(void)fclose(fp);
|
||||
pclog("[SavePNG] Unable to allocate bitmap memory!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ys2 <= 250) {
|
||||
bmpInfo.bmiHeader.biSizeImage <<= 1;
|
||||
|
||||
if ((pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
|
||||
// PNGFUNC(destroy_write_struct)(&png_ptr, &info_ptr, NULL);
|
||||
(void)fclose(fp);
|
||||
free(pBuf);
|
||||
pclog("[SavePNG] Unable to allocate secondary bitmap memory!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
bmpInfo.bmiHeader.biHeight <<= 1;
|
||||
}
|
||||
#if 1
|
||||
pclog("save png w=%i h=%i\n",
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
#endif
|
||||
|
||||
bmpInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0,
|
||||
bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS);
|
||||
|
||||
PNGFUNC(set_IHDR)(png_ptr, info_ptr,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight,
|
||||
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
b_rgb = (png_bytep *)malloc(sizeof(png_bytep)*bmpInfo.bmiHeader.biHeight);
|
||||
if (b_rgb == NULL) {
|
||||
// PNGFUNC(destroy_write_struct)(&png_ptr, NULL, NULL);
|
||||
(void)fclose(fp);
|
||||
free(pBuf);
|
||||
free(pBuf2);
|
||||
pclog("[SavePNG] Unable to allocate RGB bitmap memory!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++)
|
||||
b_rgb[i] = (png_byte *)malloc(PNGFUNC(get_rowbytes)(png_ptr, info_ptr));
|
||||
|
||||
if (pBuf2) {
|
||||
DoubleLines((uint8_t *)pBuf2, (uint8_t *)pBuf);
|
||||
bgra_to_rgb(b_rgb, (uint8_t *)pBuf2,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
} else
|
||||
bgra_to_rgb(b_rgb, (uint8_t *)pBuf,
|
||||
bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight);
|
||||
|
||||
PNGFUNC(write_info)(png_ptr, info_ptr);
|
||||
|
||||
PNGFUNC(write_image)(png_ptr, b_rgb);
|
||||
|
||||
PNGFUNC(write_end)(png_ptr, NULL);
|
||||
|
||||
/* Clean up. */
|
||||
if (fp != NULL) fclose(fp);
|
||||
// PNGFUNC(destroy_write_struct)(&png_ptr, &info_ptr, NULL);
|
||||
if (hdc) ReleaseDC(NULL, hdc);
|
||||
|
||||
if (b_rgb != NULL) {
|
||||
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++)
|
||||
free(b_rgb[i]);
|
||||
free(b_rgb);
|
||||
}
|
||||
|
||||
if (pBuf != NULL) free(pBuf);
|
||||
if (pBuf2 != NULL) free(pBuf2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
SaveBMP(const wchar_t *fn, HBITMAP hBitmap)
|
||||
{
|
||||
wchar_t temp[512];
|
||||
BITMAPFILEHEADER bmpFileHeader;
|
||||
BITMAPINFO bmpInfo;
|
||||
HDC hdc;
|
||||
FILE *fp = NULL;
|
||||
LPVOID pBuf = NULL;
|
||||
LPVOID pBuf2 = NULL;
|
||||
|
||||
hdc = GetDC(NULL);
|
||||
|
||||
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
|
||||
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
|
||||
|
||||
if (bmpInfo.bmiHeader.biSizeImage <= 0)
|
||||
bmpInfo.bmiHeader.biSizeImage =
|
||||
bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
|
||||
|
||||
if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
|
||||
pclog("[SaveBMP] Unable to allocate bitmap memory!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ys2 <= 250)
|
||||
pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage * 2);
|
||||
|
||||
bmpInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
|
||||
pBuf, &bmpInfo, DIB_RGB_COLORS);
|
||||
|
||||
if ((fp = plat_fopen(fn, L"wb")) == NULL) {
|
||||
pclog("[SaveBMP] File %ls could not be opened for writing!\n", fn);
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
return;
|
||||
}
|
||||
|
||||
bmpFileHeader.bfReserved1 = 0;
|
||||
bmpFileHeader.bfReserved2 = 0;
|
||||
if (pBuf2) {
|
||||
bmpInfo.bmiHeader.biSizeImage <<= 1;
|
||||
bmpInfo.bmiHeader.biHeight <<= 1;
|
||||
}
|
||||
bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
|
||||
bmpFileHeader.bfType=0x4D42;
|
||||
bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
|
||||
|
||||
(void)fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
|
||||
(void)fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
|
||||
if (pBuf2) {
|
||||
DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf);
|
||||
(void)fwrite(pBuf2,bmpInfo.bmiHeader.biSizeImage,1,fp);
|
||||
} else {
|
||||
(void)fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
if (fp != NULL) fclose(fp);
|
||||
if (hdc != NULL) ReleaseDC(NULL, hdc);
|
||||
if (pBuf2 != NULL) free(pBuf2);
|
||||
if (pBuf != NULL) free(pBuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ddraw_fs_size_default(RECT w_rect, RECT *r_dest)
|
||||
{
|
||||
@@ -735,23 +453,23 @@ ddraw_close(void)
|
||||
|
||||
video_setblit(NULL);
|
||||
|
||||
if (lpdds_back2) {
|
||||
if (lpdds_back2 != NULL) {
|
||||
lpdds_back2->Release();
|
||||
lpdds_back2 = NULL;
|
||||
}
|
||||
if (lpdds_back) {
|
||||
if (lpdds_back != NULL) {
|
||||
lpdds_back->Release();
|
||||
lpdds_back = NULL;
|
||||
}
|
||||
if (lpdds_pri) {
|
||||
if (lpdds_pri != NULL) {
|
||||
lpdds_pri->Release();
|
||||
lpdds_pri = NULL;
|
||||
}
|
||||
if (lpdd_clipper) {
|
||||
if (lpdd_clipper != NULL) {
|
||||
lpdd_clipper->Release();
|
||||
lpdd_clipper = NULL;
|
||||
}
|
||||
if (lpdd4) {
|
||||
if (lpdd4 != NULL) {
|
||||
lpdd4->Release();
|
||||
lpdd4 = NULL;
|
||||
}
|
||||
@@ -766,66 +484,6 @@ ddraw_close(void)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int
|
||||
ddraw_init_fs(HWND h)
|
||||
{
|
||||
ddraw_w = GetSystemMetrics(SM_CXSCREEN);
|
||||
ddraw_h = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
cgapal_rebuild();
|
||||
|
||||
if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) return 0;
|
||||
|
||||
if (FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4))) return 0;
|
||||
|
||||
lpdd->Release();
|
||||
lpdd = NULL;
|
||||
|
||||
atexit(ddraw_close);
|
||||
|
||||
if (FAILED(lpdd4->SetCooperativeLevel(h,
|
||||
DDSCL_SETFOCUSWINDOW | \
|
||||
DDSCL_CREATEDEVICEWINDOW | \
|
||||
DDSCL_EXCLUSIVE | \
|
||||
DDSCL_FULLSCREEN | \
|
||||
DDSCL_ALLOWREBOOT))) return 0;
|
||||
|
||||
if (FAILED(lpdd4->SetDisplayMode(ddraw_w, ddraw_h, 32, 0 ,0))) return 0;
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL))) return 0;
|
||||
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
if (FAILED(lpdds_pri->GetAttachedSurface(&ddsd.ddsCaps, &lpdds_back2))) return 0;
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL))) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL))) return 0;
|
||||
}
|
||||
|
||||
ddraw_hwnd = h;
|
||||
|
||||
video_setblit(ddraw_blit_fs);
|
||||
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
ddraw_init(int fs)
|
||||
{
|
||||
@@ -844,7 +502,6 @@ ddraw_init(int fs)
|
||||
pclog("DDRAW: cannot create an instance (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
hr = lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: no interfaces found (%s)\n", GetError(hr));
|
||||
@@ -868,50 +525,107 @@ ddraw_init(int fs)
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
if (fs) {
|
||||
ddraw_w = GetSystemMetrics(SM_CXSCREEN);
|
||||
ddraw_h = GetSystemMetrics(SM_CYSCREEN);
|
||||
hr = lpdd4->SetDisplayMode(ddraw_w, ddraw_h, 32, 0, 0);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetDisplayMode failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL))) return(0);
|
||||
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL))) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL)))
|
||||
fatal("CreateSurface back failed\n");
|
||||
if (fs) {
|
||||
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX | DDSCAPS_FLIP);
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
}
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
if (fs) {
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
hr = lpdds_pri->GetAttachedSurface(&ddsd.ddsCaps, &lpdds_back2);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: GetAttachedSurface failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL))) {
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
if (FAILED(hr)) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL)))
|
||||
fatal("CreateSurface back failed\n");
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface(back) failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(lpdd4->CreateClipper(0, &lpdd_clipper, NULL))) return(0);
|
||||
if (! fs) {
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL);
|
||||
if (FAILED(hr)) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface(back2) failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(lpdd_clipper->SetHWnd(0, h))) return(0);
|
||||
hr = lpdd4->CreateClipper(0, &lpdd_clipper, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateClipper failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (FAILED(lpdds_pri->SetClipper(lpdd_clipper))) return(0);
|
||||
hr = lpdd_clipper->SetHWnd(0, h);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetHWnd failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
hr = lpdds_pri->SetClipper(lpdd_clipper);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetClipper failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
ddraw_hwnd = h;
|
||||
|
||||
video_setblit(ddraw_blit);
|
||||
if (fs)
|
||||
video_setblit(ddraw_blit_fs);
|
||||
else
|
||||
video_setblit(ddraw_blit);
|
||||
|
||||
#ifdef USE_LIBPNG
|
||||
# if USE_LIBPNG == 2
|
||||
@@ -929,11 +643,197 @@ ddraw_init(int fs)
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_LIBPNG
|
||||
static void
|
||||
bgra_to_rgb(png_bytep *b_rgb, uint8_t *bgra, int width, int height)
|
||||
{
|
||||
int h, w;
|
||||
uint8_t *r, *b;
|
||||
|
||||
for (h = 0; h < height; h++) {
|
||||
for (w = 0; w < width; w++) {
|
||||
/* Get pointer to pixel in bitmap data. */
|
||||
b = &bgra[((h * width) + w) * 4];
|
||||
|
||||
/* Get pointer to png row data. */
|
||||
r = &b_rgb[(height - 1) - h][w * 3];
|
||||
|
||||
/* Copy the pixel data. */
|
||||
r[0] = b[2];
|
||||
r[1] = b[1];
|
||||
r[2] = b[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
error_handler(png_structp arg, const char *str)
|
||||
{
|
||||
pclog("PNG: stream 0x%08lx error '%s'\n", arg, str);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
warning_handler(png_structp arg, const char *str)
|
||||
{
|
||||
pclog("PNG: stream 0x%08lx warning '%s'\n", arg, str);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SavePNG(const wchar_t *fn, BITMAPINFO *bmi, uint8_t *pixels)
|
||||
{
|
||||
png_structp png = NULL;
|
||||
png_infop info = NULL;
|
||||
uint8_t *r, *b;
|
||||
png_bytep row;
|
||||
FILE *fp;
|
||||
int h, w;
|
||||
|
||||
/* Create the image file. */
|
||||
fp = plat_fopen(fn, L"wb");
|
||||
if (fp == NULL) {
|
||||
pclog("[SavePNG] File %ls could not be opened for writing!\n", fn);
|
||||
error:
|
||||
if (png != NULL)
|
||||
PNGFUNC(destroy_write_struct)(&png, &info);
|
||||
if (fp != NULL)
|
||||
(void)fclose(fp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Initialize PNG stuff. */
|
||||
png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL,
|
||||
error_handler, warning_handler);
|
||||
if (png == NULL) {
|
||||
pclog("[SavePNG] create_write_struct failed!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
info = PNGFUNC(create_info_struct)(png);
|
||||
if (info == NULL) {
|
||||
pclog("[SavePNG] create_info_struct failed!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
PNGFUNC(init_io)(png, fp);
|
||||
|
||||
PNGFUNC(set_IHDR)(png, info,
|
||||
bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 8,
|
||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
pclog("PNG: write_info\n");
|
||||
PNGFUNC(write_info)(png, info);
|
||||
|
||||
/* Create a buffer for one scanline of pixels. */
|
||||
row = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info));
|
||||
|
||||
/* Process all scanlines in the image. */
|
||||
pclog("PNG: convert\n");
|
||||
for (h = 0; h < bmi->bmiHeader.biHeight; h++) {
|
||||
r = row;
|
||||
for (w = 0; w < bmi->bmiHeader.biWidth; w++) {
|
||||
/* Get pointer to pixel in bitmap data. */
|
||||
b = &pixels[((h * bmi->bmiHeader.biWidth) + w) * 4];
|
||||
|
||||
/* Copy the pixel data. */
|
||||
r[0] = b[2];
|
||||
r[1] = b[1];
|
||||
r[2] = b[0];
|
||||
|
||||
/* Next pixel on scanline. */
|
||||
r += 3;
|
||||
}
|
||||
|
||||
/* Write this row to the file. */
|
||||
// png_write_row(png, row);
|
||||
}
|
||||
|
||||
/* No longer need the row buffer. */
|
||||
free(row);
|
||||
|
||||
#if 0
|
||||
pclog("PNG: write_end\n");
|
||||
PNGFUNC(write_end)(png, NULL);
|
||||
#endif
|
||||
|
||||
pclog("PNG: destroy\n");
|
||||
PNGFUNC(destroy_write_struct)(&png, &info);
|
||||
|
||||
/* Clean up. */
|
||||
pclog("PNG: fclose\n");
|
||||
(void)fclose(fp);
|
||||
|
||||
pclog("PNG: done!\n");
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
SaveBMP(const wchar_t *fn, BITMAPINFO *bmi, uint8_t *pixels)
|
||||
{
|
||||
BITMAPFILEHEADER bmpHdr;
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = plat_fopen(fn, L"wb")) == NULL) {
|
||||
pclog("[SaveBMP] File %ls could not be opened for writing!\n", fn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(&bmpHdr, 0x00, sizeof(BITMAPFILEHEADER));
|
||||
bmpHdr.bfSize = sizeof(BITMAPFILEHEADER) + \
|
||||
sizeof(BITMAPINFOHEADER) + bmi->bmiHeader.biSizeImage;
|
||||
bmpHdr.bfType = 0x4D42;
|
||||
bmpHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
|
||||
(void)fwrite(&bmpHdr, sizeof(BITMAPFILEHEADER), 1, fp);
|
||||
(void)fwrite(&bmi->bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
|
||||
(void)fwrite(pixels, bmi->bmiHeader.biSizeImage, 1, fp);
|
||||
|
||||
/* Clean up. */
|
||||
(void)fclose(fp);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static HBITMAP
|
||||
CopySurface(IDirectDrawSurface4 *pDDSurface)
|
||||
{
|
||||
HBITMAP hBmp, hOldBmp;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
HDC hDC, hMemDC;
|
||||
|
||||
pDDSurface->GetDC(&hDC);
|
||||
hMemDC = CreateCompatibleDC(hDC);
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
pDDSurface->GetSurfaceDesc(&ddsd);
|
||||
hBmp = CreateCompatibleBitmap(hDC, xs, ys);
|
||||
hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);
|
||||
BitBlt(hMemDC, 0, 0, xs, ys, hDC, 0, 0, SRCCOPY);
|
||||
SelectObject(hMemDC, hOldBmp);
|
||||
DeleteDC(hMemDC);
|
||||
pDDSurface->ReleaseDC(hDC);
|
||||
|
||||
return(hBmp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ddraw_screenshot(const wchar_t *fn)
|
||||
{
|
||||
wchar_t path[512];
|
||||
wchar_t temp[512];
|
||||
HBITMAP hbmp;
|
||||
BITMAPINFO bmi;
|
||||
uint8_t *pixels;
|
||||
uint8_t *pix2;
|
||||
HBITMAP hBmp;
|
||||
HDC hDC;
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
xs = xsize;
|
||||
@@ -962,24 +862,95 @@ ddraw_screenshot(const wchar_t *fn)
|
||||
ys2 >>= 1;
|
||||
}
|
||||
|
||||
hbmp = CopySurface(lpdds_back2);
|
||||
/* Create a surface copy and store it as a bitmap. */
|
||||
hBmp = CopySurface(lpdds_back);
|
||||
|
||||
/* Create a compatible DC. */
|
||||
hDC = GetDC(NULL);
|
||||
|
||||
/* Request the size info from the bitmap. */
|
||||
memset(&bmi, 0x00, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
GetDIBits(hDC, hBmp, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
|
||||
if (bmi.bmiHeader.biSizeImage <= 0) {
|
||||
bmi.bmiHeader.biSizeImage = bmi.bmiHeader.biWidth * abs(bmi.bmiHeader.biHeight) * (bmi.bmiHeader.biBitCount + 7) / 8;
|
||||
}
|
||||
|
||||
/* Allocate a buffer for the pixel data. */
|
||||
if ((pixels = (uint8_t *)malloc(bmi.bmiHeader.biSizeImage)) == NULL) {
|
||||
pclog("DDraw: unable to allocate bitmap memory!\n");
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
ReleaseDC(NULL, hDC);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now get the actual pixel data from the bitmap. */
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
GetDIBits(hDC, hBmp, 0, bmi.bmiHeader.biHeight,
|
||||
pixels, &bmi, DIB_RGB_COLORS);
|
||||
|
||||
/* No longer need the DC. */
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
/*
|
||||
* For some CGA modes (320x200, 640x200 etc) we double-up
|
||||
* the image height so it looks a little better. We simply
|
||||
* copy each real scanline.
|
||||
*/
|
||||
if (ys <= 250) {
|
||||
/* Save current buffer. */
|
||||
pix2 = pixels;
|
||||
|
||||
/* Update bitmap image size. */
|
||||
bmi.bmiHeader.biHeight <<= 1;
|
||||
bmi.bmiHeader.biSizeImage <<= 1;
|
||||
|
||||
/* Allocate new buffer, doubled-up. */
|
||||
pixels = (uint8_t *)malloc(bmi.bmiHeader.biSizeImage);
|
||||
|
||||
/* Copy scanlines. */
|
||||
for (i = 0; i < ys; i++) {
|
||||
/* Copy original line. */
|
||||
memcpy(pixels + (i * xs * 8),
|
||||
pix2 + (i * xs * 4), xs * 4);
|
||||
|
||||
/* And copy it once more, doubling it. */
|
||||
memcpy(pixels + ((i * xs * 8) + (xs * 4)),
|
||||
pix2 + (i * xs * 4), xs * 4);
|
||||
}
|
||||
|
||||
/* No longer need original buffer. */
|
||||
free(pix2);
|
||||
}
|
||||
|
||||
/* Save filename. */
|
||||
wcscpy(path, fn);
|
||||
|
||||
#ifdef USE_LIBPNG
|
||||
/* Save the screenshot, using PNG if available. */
|
||||
if (png_handle != NULL) {
|
||||
/* Use the PNG library. */
|
||||
SavePNG(fn, hbmp);
|
||||
i = SavePNG(path, &bmi, pixels);
|
||||
} else {
|
||||
#endif
|
||||
/* Use BMP, so fix the file name. */
|
||||
wcscpy(temp, fn);
|
||||
temp[wcslen(temp)-3] = L'b';
|
||||
temp[wcslen(temp)-2] = L'm';
|
||||
temp[wcslen(temp)-1] = L'p';
|
||||
SaveBMP(temp, hbmp);
|
||||
path[wcslen(path)-3] = L'b';
|
||||
path[wcslen(path)-2] = L'm';
|
||||
path[wcslen(path)-1] = L'p';
|
||||
i = SaveBMP(path, &bmi, pixels);
|
||||
#ifdef USE_LIBPNG
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Release pixel buffer. */
|
||||
free(pixels);
|
||||
|
||||
/* Show error message if needed. */
|
||||
if (i == 0) {
|
||||
_swprintf(temp, get_string(IDS_ERR_SCRSHOT), path);
|
||||
ui_msgbox(MBX_ERROR, temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -994,114 +965,3 @@ const vidapi_t ddraw_vidapi = {
|
||||
ddraw_screenshot,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
@@@@@
|
||||
|
||||
if (fs) {
|
||||
ddraw_w = GetSystemMetrics(SM_CXSCREEN);
|
||||
ddraw_h = GetSystemMetrics(SM_CYSCREEN);
|
||||
hr = lpdd4->SetDisplayMode(ddraw_w, ddraw_h, 32, 0, 0);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetDisplayMode failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
if (fs) {
|
||||
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX | DDSCAPS_FLIP);
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
}
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
if (FAILED(hr)) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface back failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fs) {
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
hr = lpdds_pri->GetAttachedSurface(&ddsd.ddsCaps, &lpdds_back2);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: GetAttachedSurface failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ddsd, 0x00, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
if (fs)
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
else
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL);
|
||||
if (FAILED(hr)) {
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.dwWidth = 2048;
|
||||
ddsd.dwHeight = 2048;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
if (fs)
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL);
|
||||
else
|
||||
hr = lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateSurface(back) failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (! fs) {
|
||||
hr = lpdd4->CreateClipper(0, &lpdd_clipper, NULL);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: CreateClipper failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
hr = lpdd_clipper->SetHWnd(0, h);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetHWnd failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
|
||||
hr = lpdds_pri->SetClipper(lpdd_clipper);
|
||||
if (FAILED(hr)) {
|
||||
pclog("DDRAW: SetClipper failed (%s)\n", GetError(hr));
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
ddraw_hwnd = h;
|
||||
|
||||
if (fs)
|
||||
video_setblit(ddraw_blit_fs);
|
||||
else
|
||||
video_setblit(ddraw_blit);
|
||||
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user