1
0
Fork 0
mirror of https://github.com/galaxyhaxz/devilution synced 2025-02-23 12:44:54 +00:00
devilution/2020_03_31/Source/capture.cpp

172 lines
3.2 KiB
C++
Raw Normal View History

2020-11-28 18:24:54 -06:00
#include "diablo.h"
static _bool CaptureHdr(HANDLE hFile, short width, short height)
{
PCXHEADER Buffer;
memset(&Buffer, 0, sizeof(Buffer));
Buffer.Manufacturer = 10;
Buffer.Version = 5;
Buffer.Encoding = 1;
Buffer.BitsPerPixel = 8;
Buffer.Xmax = width - 1;
Buffer.Ymax = height - 1;
Buffer.HDpi = width;
Buffer.VDpi = height;
Buffer.NPlanes = 1;
Buffer.BytesPerLine = width;
DWORD lpNumBytes;
return WriteFile(hFile, &Buffer, sizeof(Buffer), &lpNumBytes, NULL) && lpNumBytes == sizeof(Buffer);
}
static _bool CapturePal(HANDLE hFile, PALETTEENTRY *palette)
{
char *v3;
char Buffer[769];
Buffer[0] = 12;
v3 = &Buffer[1];
for (int i = 256; i != 0; --i)
{
v3[0] = palette->peRed;
v3[1] = palette->peGreen;
v3[2] = palette->peBlue;
palette++;
v3 += 3;
}
DWORD lpNumBytes;
return WriteFile(hFile, Buffer, sizeof(Buffer), &lpNumBytes, NULL) && lpNumBytes == sizeof(Buffer);
}
static BYTE *CaptureEnc(BYTE *src, BYTE *dst, int width)
{
do
{
BYTE rlePixel = *src++;
--width;
int rleLength = 1;
while (rlePixel == *src)
{
if (rleLength >= 63)
break;
if (!width)
break;
++rleLength;
--width;
++src;
}
if (rlePixel > 0xBF || rleLength > 1)
{
*dst++ = rleLength | 0xC0;
}
*dst++ = rlePixel;
} while (width);
return dst;
}
static _bool CapturePix(HANDLE hFile, WORD width, WORD height, WORD stride, BYTE *pixels)
{
int writeSize;
DWORD lpNumBytes;
BYTE *pBuffer = (BYTE *)DiabloAllocPtr(2 * width);
do
{
if ( !height )
{
mem_free_dbg(pBuffer);
return 1;
}
height--;
BYTE *pBufferEnd = CaptureEnc(pixels, pBuffer, width);
pixels += stride;
writeSize = pBufferEnd - pBuffer;
}
while (WriteFile(hFile, pBuffer, writeSize, &lpNumBytes, 0) && lpNumBytes == writeSize);
return 0;
}
static HANDLE CaptureFile(char *dst_path)
{
_bool num_used[100] = { false };
_finddata_t finder;
int hFind = _findfirst("screen??.PCX", &finder);
if (hFind != -1)
{
do
{
if (isdigit(finder.name[6]) && isdigit(finder.name[7]))
{
num_used[10 * (finder.name[6] - '0') + (finder.name[7] - '0')] = true;
}
}
while (_findnext(hFind, &finder) == 0);
}
int free_num = 0;
while (num_used[free_num])
{
++free_num;
if (free_num >= 100)
return INVALID_HANDLE_VALUE;
}
sprintf(dst_path, "screen%02d.PCX", free_num);
return CreateFile(dst_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
static void RedPalette(PALETTEENTRY *pal)
{
PALETTEENTRY red[256];
for(int i = 0; i < 256; i++)
{
red[i].peRed = pal[i].peRed;
red[i].peGreen = 0;
red[i].peBlue = 0;
red[i].peFlags = 0;
}
lpDDPalette->SetEntries(0, 0, 256, red);
}
void CaptureScreen()
{
PALETTEENTRY palette[256];
char FileName[MAX_PATH];
HANDLE hObject = CaptureFile(FileName);
if ( hObject != INVALID_HANDLE_VALUE)
{
DrawAndBlit();
lpDDPalette->GetEntries(0, 0, 256, palette);
RedPalette(palette);
lock_buf(2);
_bool success = CaptureHdr(hObject, 640, 480);
if (success)
{
success = CapturePix(hObject, 640, 480, 768, &gpBuffer[SCREENXY(0, 0)]);
if (success)
{
success = CapturePal(hObject, palette);
}
}
unlock_buf(2);
CloseHandle(hObject);
if (!success)
DeleteFile(FileName);
Sleep(300);
lpDDPalette->SetEntries(0, 0, 256, palette);
}
}