mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-11 23:40:51 +02:00
264 lines
6.6 KiB
C++
264 lines
6.6 KiB
C++
//***************************************************************************
|
|
// capture.c
|
|
// created 4.14.95
|
|
// written by Patrick Wyatt
|
|
//***************************************************************************
|
|
|
|
|
|
#include "diablo.h"
|
|
#pragma hdrstop
|
|
#include <io.h>
|
|
#include <ctype.h>
|
|
#include "engine.h"
|
|
|
|
|
|
//***************************************************************************
|
|
// externs
|
|
//***************************************************************************
|
|
void DrawAndBlit();
|
|
|
|
|
|
//***************************************************************************
|
|
// constants
|
|
//***************************************************************************
|
|
#define PCX_HEADER 10
|
|
#define PCX_VERSION 5
|
|
#define PCX_ENCODE 1
|
|
|
|
#define PCX_MAX_REP 63
|
|
|
|
#define PCX_X_PAL 12
|
|
#define PCX_COLORS 16
|
|
#define X_PCX_COLORS 256
|
|
|
|
|
|
//***************************************************************************
|
|
// types
|
|
//***************************************************************************
|
|
#pragma pack(push,1)
|
|
typedef struct PCXHeader {
|
|
BYTE nHeader; // 10 for valid PCX files
|
|
BYTE nVersion; // 5 for version 3.0 with palette
|
|
BYTE nEncode; // file encoding mode
|
|
BYTE nBits; // 8 for 256 color mode
|
|
WORD x1;
|
|
WORD y1;
|
|
WORD x2;
|
|
WORD y2;
|
|
WORD nScrWid;
|
|
WORD nScrHgt;
|
|
} PCXHeader;
|
|
|
|
typedef struct PCXInfo {
|
|
BYTE nMode; // always 0
|
|
BYTE nPlanes; // number of bit planes
|
|
WORD nLine; // bytes per line
|
|
BYTE unused[60]; // fill out to 128 bytes
|
|
} PCXInfo;
|
|
|
|
typedef struct TPCX_RGB {
|
|
BYTE r;
|
|
BYTE g;
|
|
BYTE b;
|
|
} TPCX_RGB;
|
|
|
|
typedef struct TPCX_XPal {
|
|
BYTE nPal;
|
|
TPCX_RGB rgb[X_PCX_COLORS];
|
|
} TPCX_XPal;
|
|
|
|
typedef struct TPCX {
|
|
PCXHeader Header;
|
|
TPCX_RGB Pal16[PCX_COLORS];
|
|
PCXInfo Info;
|
|
} TPCX;
|
|
#pragma pack(pop)
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
static BOOL pcx_write_header(HANDLE hFile,WORD wWdt,WORD wHgt) {
|
|
TPCX pcx;
|
|
|
|
ZeroMemory(&pcx,sizeof(pcx));
|
|
|
|
// initialize header
|
|
pcx.Header.nHeader = PCX_HEADER;
|
|
pcx.Header.nVersion = PCX_VERSION;
|
|
pcx.Header.nEncode = PCX_ENCODE;
|
|
pcx.Header.nBits = 8;
|
|
//pcx.Header.x1 = 0;
|
|
//pcx.Header.y1 = 0;
|
|
pcx.Header.x2 = wWdt - 1;
|
|
pcx.Header.y2 = wHgt - 1;
|
|
pcx.Header.nScrWid = wWdt;
|
|
pcx.Header.nScrHgt = wHgt;
|
|
|
|
//pcx.Info.nMode = 0;
|
|
pcx.Info.nPlanes = 1;
|
|
pcx.Info.nLine = wWdt;
|
|
|
|
DWORD dwBytes;
|
|
return WriteFile(hFile,&pcx,sizeof(pcx),&dwBytes,NULL)
|
|
&& (dwBytes == sizeof(pcx));
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
static BOOL pcx_write_pal(HANDLE hFile,const PALETTEENTRY pal[256]) {
|
|
// setup extended palette header
|
|
TPCX_XPal xpal;
|
|
xpal.nPal = PCX_X_PAL;
|
|
|
|
// copy palette colors
|
|
for (int i = 0; i < X_PCX_COLORS; i++) {
|
|
xpal.rgb[i].r = pal[i].peRed;
|
|
xpal.rgb[i].g = pal[i].peGreen;
|
|
xpal.rgb[i].b = pal[i].peBlue;
|
|
}
|
|
|
|
// write it
|
|
DWORD dwBytes;
|
|
return WriteFile(hFile,&xpal,sizeof(xpal),&dwBytes,NULL)
|
|
&& (dwBytes == sizeof(xpal));
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
static BYTE * pcx_compress_line(const BYTE * pSrc,BYTE * pDst,int nWdt) {
|
|
BYTE c;
|
|
int nCount;
|
|
|
|
do {
|
|
// get next character
|
|
c = *pSrc++;
|
|
nCount = 1;
|
|
nWdt--;
|
|
|
|
// see how long the sequence is
|
|
while ((c == *pSrc) && (nCount < PCX_MAX_REP) && nWdt) {
|
|
nCount++;
|
|
nWdt--;
|
|
pSrc++;
|
|
}
|
|
|
|
// write repeat count (if needed)
|
|
if ((nCount > 1) || (c > 0xbf)) {
|
|
nCount |= 0xc0;
|
|
*pDst++ = (BYTE) nCount;
|
|
}
|
|
|
|
*pDst++ = c;
|
|
} while (nWdt);
|
|
|
|
return pDst;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
static BOOL pcx_write_image(HANDLE hFile,WORD wDstWdt,WORD wDstHgt,WORD wSrcWdt,const BYTE * pSrc) {
|
|
BYTE * pDstEnd;
|
|
BYTE * pDstBase;
|
|
DWORD dwWrite;
|
|
DWORD dwBytes;
|
|
|
|
// allocate line buffer -- line cannot be more than 2x larger
|
|
pDstBase = (BYTE *) DiabloAllocPtrSig(2 * wDstWdt,'CAPt');
|
|
|
|
while (wDstHgt--) {
|
|
pDstEnd = pcx_compress_line(pSrc,pDstBase,wDstWdt);
|
|
pSrc += wSrcWdt;
|
|
dwWrite = pDstEnd - pDstBase;
|
|
if (! WriteFile(hFile,pDstBase,dwWrite,&dwBytes,NULL)) return FALSE;
|
|
if (dwBytes != dwWrite) return FALSE;
|
|
}
|
|
|
|
DiabloFreePtr(pDstBase);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
#define MAX_CAPTURE 100
|
|
#define DIG_OFF 6
|
|
static const char szCAPTURE[] = "screen??.PCX";
|
|
static const char szCAPTUREfmt[] = "screen%02d.PCX";
|
|
static HANDLE open_capture_file(char szFileName[MAX_PATH]) {
|
|
int nValue;
|
|
BYTE bUsedTbl[MAX_CAPTURE];
|
|
|
|
ZeroMemory(bUsedTbl,sizeof(bUsedTbl));
|
|
struct _finddata_t ffblk;
|
|
long lHandle = _findfirst(szCAPTURE,&ffblk);
|
|
if (lHandle != -1) {
|
|
do {
|
|
if (! isdigit(ffblk.name[DIG_OFF+0]))
|
|
continue;
|
|
if (! isdigit(ffblk.name[DIG_OFF+1]))
|
|
continue;
|
|
|
|
nValue = (ffblk.name[DIG_OFF + 0] - '0') * 10;
|
|
nValue += ffblk.name[DIG_OFF + 1] - '0';
|
|
bUsedTbl[nValue] = 1;
|
|
} while (! _findnext(lHandle,&ffblk));
|
|
}
|
|
|
|
for (nValue = 0; nValue < MAX_CAPTURE; nValue++) {
|
|
if (bUsedTbl[nValue]) continue;
|
|
sprintf(szFileName,szCAPTUREfmt,nValue);
|
|
return CreateFile(szFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
}
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
static void red_palette(const PALETTEENTRY src[256]) {
|
|
PALETTEENTRY dst[256];
|
|
for (int i = 0; i < 256; i++) {
|
|
dst[i].peRed = src[i].peRed;
|
|
dst[i].peGreen = 0;
|
|
dst[i].peBlue = 0;
|
|
dst[i].peFlags = 0;
|
|
}
|
|
lpDDPal->SetEntries(0,0,256,dst);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void screen_capture(void) {
|
|
HANDLE hFile;
|
|
char szFileName[MAX_PATH];
|
|
PALETTEENTRY pal[256];
|
|
|
|
if (INVALID_HANDLE_VALUE == (hFile = open_capture_file(szFileName)))
|
|
return;
|
|
|
|
// get the current palette, then flash the screen red
|
|
DrawAndBlit();
|
|
lpDDPal->GetEntries(0,0,256,pal);
|
|
red_palette(pal);
|
|
|
|
lock_buf(2);
|
|
app_assert(gpBuffer);
|
|
BOOL bOK = pcx_write_header(hFile,TOTALX,TOTALY);
|
|
if (bOK) bOK = pcx_write_image(hFile,TOTALX,TOTALY,BUFFERX,gpBuffer + 122944);
|
|
if (bOK) bOK = pcx_write_pal(hFile,pal);
|
|
unlock_buf(2);
|
|
|
|
CloseHandle(hFile);
|
|
if (! bOK)
|
|
DeleteFile(szFileName);
|
|
|
|
// restore palette
|
|
Sleep(300);
|
|
lpDDPal->SetEntries(0,0,256,pal);
|
|
}
|