2017-02-25 08:15:36 +00:00
|
|
|
#include "compat.h"
|
2016-06-21 00:33:19 +00:00
|
|
|
#include "build.h"
|
2019-09-09 22:07:11 +00:00
|
|
|
#include "baselayer.h"
|
2019-11-02 11:59:59 +00:00
|
|
|
#include "version.h"
|
|
|
|
#include "m_png.h"
|
|
|
|
#include "i_specialpaths.h"
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "gamecontrol.h"
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
#include "vfs.h"
|
2019-10-04 19:13:04 +00:00
|
|
|
#include "../../glbackend/glbackend.h"
|
2019-03-01 08:51:50 +00:00
|
|
|
|
2019-11-02 11:59:59 +00:00
|
|
|
EXTERN_CVAR(Float, png_gamma)
|
2016-06-21 00:33:19 +00:00
|
|
|
//
|
|
|
|
// screencapture
|
|
|
|
//
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_FILE OutputFileCounter::opennextfile(char *fn, char *zeros)
|
2016-06-21 00:33:19 +00:00
|
|
|
{
|
|
|
|
do // JBF 2004022: So we don't overwrite existing screenshots
|
|
|
|
{
|
2017-12-01 06:19:19 +00:00
|
|
|
if (count > 9999) return nullptr;
|
|
|
|
|
|
|
|
zeros[0] = ((count/1000)%10)+'0';
|
|
|
|
zeros[1] = ((count/100)%10)+'0';
|
|
|
|
zeros[2] = ((count/10)%10)+'0';
|
|
|
|
zeros[3] = (count%10)+'0';
|
2019-10-21 11:27:27 +00:00
|
|
|
#ifdef USE_PHYSFS
|
|
|
|
buildvfs_FILE file;
|
2019-03-01 08:51:50 +00:00
|
|
|
if ((file = buildvfs_fopen_read(fn)) == nullptr) break;
|
|
|
|
buildvfs_fclose(file);
|
2019-10-21 11:27:27 +00:00
|
|
|
#else
|
|
|
|
struct Bstat st;
|
|
|
|
if (Bstat(fn, &st) == -1) break;
|
|
|
|
#endif
|
2017-12-01 06:19:19 +00:00
|
|
|
count++;
|
2016-06-21 00:33:19 +00:00
|
|
|
} while (1);
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
return buildvfs_fopen_write(fn);
|
2017-12-01 06:19:19 +00:00
|
|
|
}
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_FILE OutputFileCounter::opennextfile_withext(char *fn, const char *ext)
|
2017-12-01 06:19:19 +00:00
|
|
|
{
|
|
|
|
char *dot = strrchr(fn, '.');
|
|
|
|
strcpy(dot+1, ext);
|
|
|
|
return opennextfile(fn, dot-4);
|
2016-06-21 00:33:19 +00:00
|
|
|
}
|
|
|
|
|
2017-12-01 06:19:19 +00:00
|
|
|
static OutputFileCounter capturecounter;
|
|
|
|
|
2016-06-21 00:33:19 +00:00
|
|
|
# ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
# define HICOLOR (videoGetRenderMode() >= REND_POLYMOST && in3dmode())
|
2016-06-21 00:33:19 +00:00
|
|
|
# else
|
|
|
|
# define HICOLOR 0
|
|
|
|
# endif
|
2016-09-16 21:55:36 +00:00
|
|
|
|
2019-10-04 19:13:04 +00:00
|
|
|
void getScreen(uint8_t* imgBuf)
|
|
|
|
{
|
|
|
|
GLInterface.ReadPixels(xdim, ydim, imgBuf);
|
|
|
|
}
|
|
|
|
|
2019-11-02 11:59:59 +00:00
|
|
|
|
|
|
|
CVAR(String, screenshotname, "", CVAR_ARCHIVE) // not GLOBALCONFIG - allow setting this per game.
|
|
|
|
CVAR(String, screenshot_dir, "", CVAR_ARCHIVE) // same here.
|
|
|
|
|
|
|
|
//
|
|
|
|
// WritePNGfile
|
|
|
|
//
|
|
|
|
void WritePNGfile(FileWriter* file, const uint8_t* buffer, const PalEntry* palette,
|
|
|
|
ESSType color_type, int width, int height, int pitch, float gamma)
|
|
|
|
{
|
|
|
|
FStringf software("Demolition %s", GetVersionString());
|
|
|
|
if (!M_CreatePNG(file, buffer, palette, color_type, width, height, pitch, gamma) ||
|
|
|
|
!M_AppendPNGText(file, "Software", software) ||
|
|
|
|
!M_FinishPNG(file))
|
|
|
|
{
|
|
|
|
OSD_Printf("Failed writing screenshot\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int videoCaptureScreen()
|
2017-07-18 20:53:00 +00:00
|
|
|
{
|
2019-11-02 11:59:59 +00:00
|
|
|
PalEntry Palette[256];
|
|
|
|
|
|
|
|
size_t dirlen;
|
|
|
|
FString autoname = Args->CheckValue("-shotdir");
|
|
|
|
if (autoname.IsEmpty())
|
|
|
|
{
|
|
|
|
autoname = screenshot_dir;
|
|
|
|
}
|
|
|
|
dirlen = autoname.Len();
|
|
|
|
if (dirlen == 0)
|
|
|
|
{
|
|
|
|
autoname = M_GetScreenshotsPath();
|
|
|
|
dirlen = autoname.Len();
|
|
|
|
}
|
|
|
|
if (dirlen > 0)
|
|
|
|
{
|
|
|
|
if (autoname[dirlen - 1] != '/' && autoname[dirlen - 1] != '\\')
|
|
|
|
{
|
|
|
|
autoname += '/';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
autoname = NicePath(autoname);
|
|
|
|
CreatePath(autoname);
|
|
|
|
|
|
|
|
if (**screenshotname) autoname << screenshotname;
|
|
|
|
else autoname << currentGame;
|
|
|
|
autoname << "_0000";
|
|
|
|
char* fn = autoname.LockBuffer();
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_FILE fp = capturecounter.opennextfile_withext(fn, "png");
|
2019-11-02 11:59:59 +00:00
|
|
|
autoname.UnlockBuffer();
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2019-11-02 11:59:59 +00:00
|
|
|
if (fp == nullptr)
|
2016-06-21 00:33:19 +00:00
|
|
|
{
|
2017-12-01 06:19:19 +00:00
|
|
|
return -1;
|
2016-06-21 00:33:19 +00:00
|
|
|
}
|
2019-11-02 11:59:59 +00:00
|
|
|
FileWriter writer(fp);
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
uint8_t * const imgBuf = (uint8_t *) Xmalloc(xdim * ydim * (HICOLOR ? 3 : 1));
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (HICOLOR)
|
|
|
|
{
|
2019-10-04 19:13:04 +00:00
|
|
|
getScreen(imgBuf);
|
2017-07-18 20:53:00 +00:00
|
|
|
int const bytesPerLine = xdim * 3;
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
// flip rows
|
|
|
|
uint8_t* rowBuf = (uint8_t *) Xmalloc(bytesPerLine);
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
for (int i = 0, numRows = ydim >> 1; i < numRows; ++i)
|
|
|
|
{
|
|
|
|
Bmemcpy(rowBuf, imgBuf + i * bytesPerLine, bytesPerLine);
|
|
|
|
Bmemcpy(imgBuf + i * bytesPerLine, imgBuf + (ydim - i - 1) * bytesPerLine, bytesPerLine);
|
|
|
|
Bmemcpy(imgBuf + (ydim - i - 1) * bytesPerLine, rowBuf, bytesPerLine);
|
|
|
|
}
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(rowBuf);
|
2017-07-18 20:53:00 +00:00
|
|
|
}
|
|
|
|
else
|
2016-06-21 00:33:19 +00:00
|
|
|
#endif
|
|
|
|
{
|
2019-11-02 11:59:59 +00:00
|
|
|
for (bssize_t i = 0; i < 256; ++i)
|
|
|
|
{
|
|
|
|
Palette[i].r = curpalettefaded[i].r;
|
|
|
|
Palette[i].g = curpalettefaded[i].g;
|
|
|
|
Palette[i].b = curpalettefaded[i].b;
|
|
|
|
}
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
for (int i = 0; i < ydim; ++i)
|
|
|
|
Bmemcpy(imgBuf + i * xdim, (uint8_t *)frameplace + ylookup[i], xdim);
|
2016-06-21 00:33:19 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2016-06-21 00:33:19 +00:00
|
|
|
|
2019-11-02 11:59:59 +00:00
|
|
|
WritePNGfile(&writer, imgBuf, Palette, HICOLOR ? SS_RGB : SS_PAL, xdim, ydim, HICOLOR? xdim*3 : xdim, png_gamma);
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(imgBuf);
|
2019-11-02 11:59:59 +00:00
|
|
|
OSD_Printf("Saved screenshot to %s\n", fn);
|
|
|
|
capturecounter.count++;
|
2016-06-21 00:33:19 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-18 20:53:00 +00:00
|
|
|
#undef HICOLOR
|
2016-06-21 00:33:19 +00:00
|
|
|
|