#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); } }