diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 55bbde45..bccb0ee8 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1082,21 +1082,24 @@ UINT8 *HWR_GetScreenshot(void) return buf; } -boolean HWR_Screenshot(const char *lbmname) +boolean HWR_Screenshot(const char *pathname, char **error) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); if (!buf) + { + *error = "Failed to allocate memory for HWR_Screenshot"; return false; + } // returns 24bit 888 RGB HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); #ifdef USE_PNG - ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL); + ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL, &*error); // c_irl #else - ret = saveTGA(lbmname, buf, vid.width, vid.height); + ret = saveTGA(pathname, buf, vid.width, vid.height); #endif free(buf); return ret; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 59042cf3..cf9f2232 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -38,8 +38,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player); void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); -UINT8 *HWR_GetScreenshot(void); -boolean HWR_Screenshot(const char *lbmname); void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); @@ -54,6 +52,9 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right. void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); +UINT8 *HWR_GetScreenshot(void); +boolean HWR_Screenshot(const char *pathname, char **error); + void HWR_AddCommands(void); void HWR_CorrectSWTricks(void); void transform(float *cx, float *cy, float *cz); diff --git a/src/m_misc.c b/src/m_misc.c index 7dd0d822..7b60caff 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -30,6 +30,7 @@ #include "g_game.h" #include "m_misc.h" #include "hu_stuff.h" +#include "st_stuff.h" #include "v_video.h" #include "z_zone.h" #include "g_input.h" @@ -585,6 +586,21 @@ void M_SaveConfig(const char *filename) fclose(f); } +// ========================================================================== +// SCREENSHOTS +// ========================================================================== +static UINT8 screenshot_palette[768]; +static void M_CreateScreenShotPalette(void) +{ + size_t i, j; + for (i = 0, j = 0; i < 768; i += 3, j++) + { + RGBA_t locpal = pLocalPalette[(max(st_palette,0)*256)+j]; + screenshot_palette[i] = locpal.s.red; + screenshot_palette[i+1] = locpal.s.green; + screenshot_palette[i+2] = locpal.s.blue; + } +} #if NUMSCREENS > 2 static const char *Newsnapshotfile(const char *pathname, const char *ext) @@ -1047,6 +1063,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) static inline moviemode_t M_StartMovieAPNG(const char *pathname) { #ifdef USE_APNG + UINT8 *palette; const char *freename = NULL; boolean ret = false; @@ -1062,10 +1079,8 @@ static inline moviemode_t M_StartMovieAPNG(const char *pathname) return MM_OFF; } - if (rendermode == render_soft) - ret = M_SetupaPNG(va(pandf,pathname,freename), W_CacheLumpName(GetPalette(), PU_CACHE)); - else - ret = M_SetupaPNG(va(pandf,pathname,freename), NULL); + if (rendermode == render_soft) M_CreateScreenShotPalette(); + ret = M_SetupaPNG(va(pandf,pathname,freename), (palette = screenshot_palette)); if (!ret) { @@ -1268,10 +1283,11 @@ void M_StopMovie(void) * \param data The image data. * \param width Width of the picture. * \param height Height of the picture. - * \param palette Palette of image data + * \param palette Palette of image data. * \note if palette is NULL, BGR888 format + * \param error Error string to return, if screenshot failed. */ -boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette) +boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette, char **error) { png_structp png_ptr; png_infop png_info_ptr; @@ -1286,15 +1302,14 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const png_FILE = fopen(filename,"wb"); if (!png_FILE) { - CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for write\n", filename); + *error = "Failed to open file for write"; return false; } - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, - PNG_error, PNG_warn); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); if (!png_ptr) { - CONS_Debug(DBG_RENDER, "M_SavePNG: Error on initialize libpng\n"); + *error = "Failed to initialize libpng"; fclose(png_FILE); remove(filename); return false; @@ -1303,7 +1318,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const png_info_ptr = png_create_info_struct(png_ptr); if (!png_info_ptr) { - CONS_Debug(DBG_RENDER, "M_SavePNG: Error on allocate for libpng\n"); + *error = "Failed to allocate memory for libpng"; png_destroy_write_struct(&png_ptr, NULL); fclose(png_FILE); remove(filename); @@ -1316,7 +1331,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const if (setjmp(png_jmpbuf(png_ptr))) #endif { - //CONS_Debug(DBG_RENDER, "libpng write error on %s\n", filename); + *error = "libpng write error"; png_destroy_write_struct(&png_ptr, &png_info_ptr); fclose(png_FILE); remove(filename); @@ -1445,9 +1460,8 @@ void M_ScreenShot(void) } /** Takes a screenshot. - * The screenshot is saved as "srb2xxxx.pcx" (or "srb2xxxx.tga" in hardware - * rendermode) where xxxx is the lowest four-digit number for which a file - * does not already exist. + * The screenshot is saved as "srb2xxxx.png" where xxxx is the lowest + * four-digit number for which a file does not already exist. * * \sa HWR_ScreenShot */ @@ -1456,11 +1470,16 @@ void M_DoScreenShot(void) #if NUMSCREENS > 2 const char *freename = NULL, *pathname = "."; boolean ret = false; + char *error = "Unknown error"; UINT8 *linear = NULL; // Don't take multiple screenshots, obviously takescreenshot = false; + // how does one take a screenshot without a render system? + if (rendermode == render_none) + return; + if (cv_screenshot_option.value == 0) pathname = usehome ? srb2home : srb2path; else if (cv_screenshot_option.value == 1) @@ -1471,16 +1490,13 @@ void M_DoScreenShot(void) pathname = cv_screenshot_folder.string; #ifdef USE_PNG - if (rendermode != render_none) - freename = Newsnapshotfile(pathname,"png"); + freename = Newsnapshotfile(pathname,"png"); #else if (rendermode == render_soft) freename = Newsnapshotfile(pathname,"pcx"); - else if (rendermode != render_none) + else if (rendermode == render_opengl) freename = Newsnapshotfile(pathname,"tga"); #endif - else - I_Error("Can't take a screenshot without a render system"); if (rendermode == render_soft) { @@ -1494,18 +1510,16 @@ void M_DoScreenShot(void) // save the pcx file #ifdef HWRENDER - if (rendermode != render_soft) - ret = HWR_Screenshot(va(pandf,pathname,freename)); + if (rendermode == render_opengl) + ret = HWR_Screenshot(va(pandf,pathname,freename), &error); else #endif - if (rendermode != render_none) { + M_CreateScreenShotPalette(); #ifdef USE_PNG - ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, - W_CacheLumpName(GetPalette(), PU_CACHE)); + ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette, &error); #else - ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, - W_CacheLumpName(GetPalette(), PU_CACHE)); + ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette); #endif } @@ -1513,14 +1527,14 @@ failure: if (ret) { if (moviemode != MM_SCREENSHOT) - CONS_Printf(M_GetText("screen shot %s saved in %s\n"), freename, pathname); + CONS_Printf(M_GetText("Screen shot %s saved in %s\n"), freename, pathname); } else { if (freename) - CONS_Printf(M_GetText("Couldn't create screen shot %s in %s\n"), freename, pathname); + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot %s in %s (%s)\n"), freename, pathname, error); else - CONS_Printf(M_GetText("Couldn't create screen shot (all 10000 slots used!) in %s\n"), pathname); + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create screen shot in %s (all 10000 slots used!)\n"), pathname); if (moviemode == MM_SCREENSHOT) M_StopMovie(); diff --git a/src/m_misc.h b/src/m_misc.h index 7dd8baab..cb4af392 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -64,7 +64,7 @@ void FIL_ForceExtension(char *path, const char *extension); boolean FIL_CheckExtension(const char *in); #ifdef HAVE_PNG -boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette); +boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette, char **error); #endif extern boolean takescreenshot; diff --git a/src/st_stuff.c b/src/st_stuff.c index 1f8dbbf6..287aea13 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -197,7 +197,7 @@ void ST_Ticker(void) } // 0 is default, any others are special palettes. -static INT32 st_palette = 0; +INT32 st_palette = 0; void ST_doPaletteStuff(void) { diff --git a/src/st_stuff.h b/src/st_stuff.h index 6c4140ce..6f05bbf3 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -58,6 +58,7 @@ boolean ST_SameTeam(player_t *a, player_t *b); //-------------------- extern boolean st_overlay; // sb overlay on or off when fullscreen +extern INT32 st_palette; // 0 is default, any others are special palettes. extern lumpnum_t st_borderpatchnum; // patches, also used in intermission