From 67239cd6236e58a591123523d9a1b361b50c5369 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 21 Sep 2016 09:01:12 +0200 Subject: [PATCH] - added a FileWriter class (taken from another project of mine) and changed m_png.cpp to use it. This is so that PNGs can be written to memory, not just to an external file. stdio's FILE cannot be easily redirected but a C++ class can. The writer is very simple and primitive right now, allowing no seeking, but for the job at hand it is sufficient. Note that large parts of savegame creation have been disabled, because they are about to be rewritten and it makes no sense to adjust them all before. --- src/files.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++ src/files.h | 42 +++++++++++++++++++++++++++++++++ src/g_game.cpp | 13 +++++++++-- src/m_misc.cpp | 17 +++++++++----- src/m_png.cpp | 40 ++++++++++++++++---------------- src/m_png.h | 13 ++++++----- src/r_renderer.h | 3 ++- src/r_swrenderer.cpp | 2 +- src/r_swrenderer.h | 32 +++++++++++++------------- 9 files changed, 165 insertions(+), 52 deletions(-) diff --git a/src/files.cpp b/src/files.cpp index 0b72032361..6bf38274b9 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -600,3 +600,58 @@ char *MemoryArrayReader::Gets(char *strbuf, int len) { return GetsFromBuffer((char*)&buf[0], strbuf, len); } + +//========================================================================== +// +// FileWriter (the motivation here is to have a buffer writing subclass) +// +//========================================================================== + +bool FileWriter::OpenDirect(const char *filename) +{ + File = fopen(filename, "wb"); + return (File != NULL); +} + +FileWriter *FileWriter::Open(const char *filename) +{ + FileWriter *fwrit = new FileWriter(); + if (fwrit->OpenDirect(filename)) + { + return fwrit; + } + delete fwrit; + return NULL; +} + +size_t FileWriter::Write(const void *buffer, size_t len) +{ + if (File != NULL) + { + return fwrite(buffer, 1, len, File); + } + else + { + return 0; + } +} + + +size_t FileWriter::Printf(const char *fmt, ...) +{ + va_list ap; + FString out; + + va_start(ap, fmt); + out.VFormat(fmt, ap); + va_end(ap); + return Write(out.GetChars(), out.Len()); +} + +size_t BufferWriter::Write(const void *buffer, size_t len) +{ + unsigned int ofs = mBuffer.Reserve((unsigned)len); + memcpy(&mBuffer[ofs], buffer, len); + return len; +} + diff --git a/src/files.h b/src/files.h index 5889eb6fe7..4c12550c80 100644 --- a/src/files.h +++ b/src/files.h @@ -356,4 +356,46 @@ protected: }; +class FileWriter +{ +protected: + bool OpenDirect(const char *filename); + + FileWriter() + { + File = NULL; + } +public: + virtual ~FileWriter() + { + if (File != NULL) fclose(File); + } + + static FileWriter *Open(const char *filename); + + virtual size_t Write(const void *buffer, size_t len); + size_t Printf(const char *fmt, ...); + +protected: + + FILE *File; + +protected: + bool CloseOnDestruct; +}; + +class BufferWriter : public FileWriter +{ +protected: + TArray mBuffer; +public: + + BufferWriter() {} + virtual size_t Write(const void *buffer, size_t len) override; + TArray *GetBuffer() { return &mBuffer; } +}; + + + + #endif diff --git a/src/g_game.cpp b/src/g_game.cpp index 73293a15e9..a221d3a5a8 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1828,6 +1828,7 @@ bool G_CheckSaveGameWads (PNGHandle *png, bool printwarn) void G_DoLoadGame () { +#if 0 // SAVEGAME char sigcheck[20]; char *text = NULL; char *map; @@ -1981,6 +1982,7 @@ void G_DoLoadGame () // amount of memory in use, so bring it down now by starting a // collection. GC::StartCollection(); +#endif } @@ -2102,6 +2104,7 @@ void G_DoAutoSave () static void PutSaveWads (FILE *file) { +#if 0 // SAVEGAME const char *name; // Name of IWAD @@ -2114,10 +2117,12 @@ static void PutSaveWads (FILE *file) name = Wads.GetWadName (Wads.GetLumpFile (level.lumpnum)); M_AppendPNGText (file, "Map WAD", name); } +#endif } static void PutSaveComment (FILE *file) { +#if 0 // SAVEGAME char comment[256]; const char *readableTime; WORD len; @@ -2147,9 +2152,10 @@ static void PutSaveComment (FILE *file) // Write out the comment M_AppendPNGText (file, "Comment", comment); +#endif } -static void PutSavePic (FILE *file, int width, int height) +static void PutSavePic (FileWriter *file, int width, int height) { if (width <= 0 || height <= 0 || !storesavepic) { @@ -2194,6 +2200,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio } SaveVersion = SAVEVER; +#if 0 // SAVEGAME PutSavePic (stdfile, SAVEPICWIDTH, SAVEPICHEIGHT); mysnprintf(buf, countof(buf), GAMENAME " %s", GetVersionString()); M_AppendPNGText (stdfile, "Software", buf); @@ -2249,7 +2256,9 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio } fclose(stdfile); } - if (success) +#endif + bool success = true; + if (success) { if (longsavemessages) Printf ("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars()); else Printf ("%s\n", GStrings("GGSAVED")); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 87f61f2539..a37c320946 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -449,10 +449,15 @@ struct pcx_t }; +inline void putc(char chr, FileWriter *file) +{ + file->Write(&chr, 1); +} + // // WritePCXfile // -void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette, +void WritePCXfile (FileWriter *file, const BYTE *buffer, const PalEntry *palette, ESSType color_type, int width, int height, int pitch) { BYTE temprow[MAXWIDTH * 3]; @@ -480,7 +485,7 @@ void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette, pcx.palette_type = 1; // not a grey scale memset (pcx.filler, 0, sizeof(pcx.filler)); - fwrite (&pcx, 128, 1, file); + file->Write(&pcx, 128); bytes_per_row_minus_one = ((color_type == SS_PAL) ? width : width * 3) - 1; @@ -593,7 +598,7 @@ void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette, // // WritePNGfile // -void WritePNGfile (FILE *file, const BYTE *buffer, const PalEntry *palette, +void WritePNGfile (FileWriter *file, const BYTE *buffer, const PalEntry *palette, ESSType color_type, int width, int height, int pitch) { char software[100]; @@ -655,7 +660,7 @@ static bool FindFreeName (FString &fullname, const char *extension) void M_ScreenShot (const char *filename) { - FILE *file; + FileWriter *file; FString autoname; bool writepcx = (stricmp (screenshot_type, "pcx") == 0); // PNG is the default @@ -709,7 +714,7 @@ void M_ScreenShot (const char *filename) { screen->GetFlashedPalette(palette); } - file = fopen (autoname, "wb"); + file = FileWriter::Open(autoname); if (file == NULL) { Printf ("Could not open %s\n", autoname.GetChars()); @@ -726,7 +731,7 @@ void M_ScreenShot (const char *filename) WritePNGfile(file, buffer, palette, color_type, screen->GetWidth(), screen->GetHeight(), pitch); } - fclose(file); + delete file; screen->ReleaseScreenshotBuffer(); if (!screenshot_quiet) diff --git a/src/m_png.cpp b/src/m_png.cpp index 22a9a657d1..35cd8587e7 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -101,7 +101,7 @@ PNGHandle::~PNGHandle () static inline void MakeChunk (void *where, DWORD type, size_t len); static inline void StuffPalette (const PalEntry *from, BYTE *to); -static bool WriteIDAT (FILE *file, const BYTE *data, int len); +static bool WriteIDAT (FileWriter *file, const BYTE *data, int len); static void UnfilterRow (int width, BYTE *dest, BYTE *stream, BYTE *prev, int bpp); static void UnpackPixels (int width, int bytesPerRow, int bitdepth, const BYTE *rowin, BYTE *rowout, bool grayscale); @@ -131,7 +131,7 @@ CVAR(Float, png_gamma, 0.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //========================================================================== -bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette, +bool M_CreatePNG (FileWriter *file, const BYTE *buffer, const PalEntry *palette, ESSType color_type, int width, int height, int pitch) { BYTE work[8 + // signature @@ -171,7 +171,7 @@ bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette, work_len = sizeof(work) - (12+256*3); } - if (fwrite (work, 1, work_len, file) != work_len) + if (file->Write (work, work_len) != work_len) return false; return M_SaveBitmap (buffer, color_type, width, height, pitch, file); @@ -185,7 +185,7 @@ bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette, // //========================================================================== -bool M_CreateDummyPNG (FILE *file) +bool M_CreateDummyPNG (FileWriter *file) { static const BYTE dummyPNG[] = { @@ -195,7 +195,7 @@ bool M_CreateDummyPNG (FILE *file) 0,0,0,10,'I','D','A','T', 104,222,99,96,0,0,0,2,0,1,0x9f,0x65,0x0e,0x18 }; - return fwrite (dummyPNG, 1, sizeof(dummyPNG), file) == sizeof(dummyPNG); + return file->Write (dummyPNG, sizeof(dummyPNG)) == sizeof(dummyPNG); } @@ -207,10 +207,10 @@ bool M_CreateDummyPNG (FILE *file) // //========================================================================== -bool M_FinishPNG (FILE *file) +bool M_FinishPNG (FileWriter *file) { static const BYTE iend[12] = { 0,0,0,0,73,69,78,68,174,66,96,130 }; - return fwrite (iend, 1, 12, file) == 12; + return file->Write (iend, 12) == 12; } //========================================================================== @@ -221,13 +221,13 @@ bool M_FinishPNG (FILE *file) // //========================================================================== -bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD len) +bool M_AppendPNGChunk (FileWriter *file, DWORD chunkID, const BYTE *chunkData, DWORD len) { DWORD head[2] = { BigLong((unsigned int)len), chunkID }; DWORD crc; - if (fwrite (head, 1, 8, file) == 8 && - (len == 0 || fwrite (chunkData, 1, len, file) == len)) + if (file->Write (head, 8) == 8 && + (len == 0 || file->Write (chunkData, len) == len)) { crc = CalcCRC32 ((BYTE *)&head[1], 4); if (len != 0) @@ -235,7 +235,7 @@ bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD l crc = AddCRC32 (crc, chunkData, len); } crc = BigLong((unsigned int)crc); - return fwrite (&crc, 1, 4, file) == 4; + return file->Write (&crc, 4) == 4; } return false; } @@ -248,7 +248,7 @@ bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD l // //========================================================================== -bool M_AppendPNGText (FILE *file, const char *keyword, const char *text) +bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text) { struct { DWORD len, id; char key[80]; } head; int len = (int)strlen (text); @@ -261,8 +261,8 @@ bool M_AppendPNGText (FILE *file, const char *keyword, const char *text) strncpy (head.key, keyword, keylen); head.key[keylen] = 0; - if ((int)fwrite (&head, 1, keylen + 9, file) == keylen + 9 && - (int)fwrite (text, 1, len, file) == len) + if ((int)file->Write (&head, keylen + 9) == keylen + 9 && + (int)file->Write (text, len) == len) { crc = CalcCRC32 ((BYTE *)&head+4, keylen + 5); if (len != 0) @@ -270,7 +270,7 @@ bool M_AppendPNGText (FILE *file, const char *keyword, const char *text) crc = AddCRC32 (crc, (BYTE *)text, len); } crc = BigLong((unsigned int)crc); - return fwrite (&crc, 1, 4, file) == 4; + return file->Write (&crc, 4) == 4; } return false; } @@ -900,7 +900,7 @@ static int SelectFilter(Byte row[5][1 + MAXWIDTH*3], Byte prior[MAXWIDTH*3], int // //========================================================================== -bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FILE *file) +bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FileWriter *file) { #if USE_FILTER_HEURISTIC Byte prior[MAXWIDTH*3]; @@ -1040,7 +1040,7 @@ bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, i // //========================================================================== -static bool WriteIDAT (FILE *file, const BYTE *data, int len) +static bool WriteIDAT (FileWriter *file, const BYTE *data, int len) { DWORD foo[2], crc; @@ -1049,9 +1049,9 @@ static bool WriteIDAT (FILE *file, const BYTE *data, int len) crc = CalcCRC32 ((BYTE *)&foo[1], 4); crc = BigLong ((unsigned int)AddCRC32 (crc, data, len)); - if (fwrite (foo, 1, 8, file) != 8 || - fwrite (data, 1, len, file) != (size_t)len || - fwrite (&crc, 1, 4, file) != 4) + if (file->Write (foo, 8) != 8 || + file->Write (data, len) != (size_t)len || + file->Write (&crc, 4) != 4) { return false; } diff --git a/src/m_png.h b/src/m_png.h index 6434031d28..ef25d70d43 100644 --- a/src/m_png.h +++ b/src/m_png.h @@ -36,6 +36,7 @@ #include #include "doomtype.h" #include "v_video.h" +#include "files.h" // PNG Writing -------------------------------------------------------------- @@ -43,22 +44,22 @@ // The passed file should be a newly created file. // This function writes the PNG signature and the IHDR, gAMA, PLTE, and IDAT // chunks. -bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *pal, +bool M_CreatePNG (FileWriter *file, const BYTE *buffer, const PalEntry *pal, ESSType color_type, int width, int height, int pitch); // Creates a grayscale 1x1 PNG file. Used for savegames without savepics. -bool M_CreateDummyPNG (FILE *file); +bool M_CreateDummyPNG (FileWriter *file); // Appends any chunk to a PNG file started with M_CreatePNG. -bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD len); +bool M_AppendPNGChunk (FileWriter *file, DWORD chunkID, const BYTE *chunkData, DWORD len); // Adds a tEXt chunk to a PNG file started with M_CreatePNG. -bool M_AppendPNGText (FILE *file, const char *keyword, const char *text); +bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text); // Appends the IEND chunk to a PNG file. -bool M_FinishPNG (FILE *file); +bool M_FinishPNG (FileWriter *file); -bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FILE *file); +bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FileWriter *file); // PNG Reading -------------------------------------------------------------- diff --git a/src/r_renderer.h b/src/r_renderer.h index c5385aadcd..4236993d63 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -11,6 +11,7 @@ class AActor; class player_t; struct sector_t; class FCanvasTexture; +class FileWriter; struct FRenderer { @@ -37,7 +38,7 @@ struct FRenderer virtual void RemapVoxels() {} // renders view to a savegame picture - virtual void WriteSavePic (player_t *player, FILE *file, int width, int height) = 0; + virtual void WriteSavePic (player_t *player, FileWriter *file, int width, int height) = 0; // draws player sprites with hardware acceleration (only useful for software rendering) virtual void DrawRemainingPlayerSprites() {} diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index ccf12e7ed5..3c33134301 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -179,7 +179,7 @@ void FSoftwareRenderer::RemapVoxels() // //=========================================================================== -void FSoftwareRenderer::WriteSavePic (player_t *player, FILE *file, int width, int height) +void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height) { DCanvas *pic = new DSimpleCanvas (width, height); PalEntry palette[256]; diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 2856d9586a..f9d5609a0d 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -6,35 +6,35 @@ struct FSoftwareRenderer : public FRenderer { // Can be overridden so that the colormaps for sector color/fade won't be built. - virtual bool UsesColormap() const; + virtual bool UsesColormap() const override; // precache one texture void PrecacheTexture(FTexture *tex, int cache); - virtual void Precache(BYTE *texhitlist, TMap &actorhitlist); + virtual void Precache(BYTE *texhitlist, TMap &actorhitlist) override; // render 3D view - virtual void RenderView(player_t *player); + virtual void RenderView(player_t *player) override; // Remap voxel palette - virtual void RemapVoxels(); + virtual void RemapVoxels() override; // renders view to a savegame picture - virtual void WriteSavePic (player_t *player, FILE *file, int width, int height); + virtual void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override; // draws player sprites with hardware acceleration (only useful for software rendering) - virtual void DrawRemainingPlayerSprites(); + virtual void DrawRemainingPlayerSprites() override; - virtual int GetMaxViewPitch(bool down); + virtual int GetMaxViewPitch(bool down) override; - void OnModeSet (); - void ErrorCleanup (); - void ClearBuffer(int color); - void Init(); - void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); - void SetupFrame(player_t *player); - void CopyStackedViewParameters(); - void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov); - sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back); + void OnModeSet () override; + void ErrorCleanup () override; + void ClearBuffer(int color) override; + void Init() override; + void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) override; + void SetupFrame(player_t *player) override; + void CopyStackedViewParameters() override; + void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) override; + sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) override; };