From 0d05b41f22d6e07ff74020d086cfe1c456083afb Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 2 Dec 2017 11:51:52 +0200 Subject: [PATCH 01/36] Fixed incomplete ACS string pool state after loading of saved game https://forum.zdoom.org/viewtopic.php?t=58571 --- src/p_acs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2dfbec49b..3d93e7a0a 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1365,6 +1365,8 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key) } } } + + FindFirstFreeEntry(FirstFreeEntry); } //============================================================================ From cbd2fd34a0d267348da3d7b6c924cde0dbec2c9c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 11:51:37 +0100 Subject: [PATCH 02/36] - added seeking capabilities to FileWriter class. --- src/files.cpp | 24 ++++++++++++++++++++++++ src/files.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/src/files.cpp b/src/files.cpp index 0de13e8ea..5bcc3d7bb 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -634,6 +634,30 @@ size_t FileWriter::Write(const void *buffer, size_t len) } } +long FileWriter::Tell() +{ + if (File != NULL) + { + return ftell(File); + } + else + { + return 0; + } +} + +long FileWriter::Seek(long offset, int mode) +{ + if (File != NULL) + { + return fseek(File, offset, mode); + } + else + { + return 0; + } +} + size_t FileWriter::Printf(const char *fmt, ...) { diff --git a/src/files.h b/src/files.h index 4c73273a1..94255b1a0 100644 --- a/src/files.h +++ b/src/files.h @@ -409,6 +409,8 @@ public: static FileWriter *Open(const char *filename); virtual size_t Write(const void *buffer, size_t len); + virtual long Tell(); + virtual long Seek(long offset, int mode); size_t Printf(const char *fmt, ...) GCCPRINTF(2,3); protected: From 9cc8bab102b47b7f8fd8ac77e6f629f7cff71b7b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 11:55:50 +0100 Subject: [PATCH 03/36] - only have one fopen call in the entire FileReader hierarchy This is for an eventual implementation of UTF-8 handling. On Windows this will require replacement of fopen with _wfopen so let's try to keep the number of fopen calls low. --- src/files.cpp | 7 ++++++- src/files.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/files.cpp b/src/files.cpp index 5bcc3d7bb..b42aefece 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -50,6 +50,11 @@ // //========================================================================== +FILE *FileReader::openfd(const char *filename) +{ + return fopen(filename, "rb"); +} + FileReader::FileReader () : File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) { @@ -93,7 +98,7 @@ FileReader::~FileReader () bool FileReader::Open (const char *filename) { - File = fopen (filename, "rb"); + File = openfd (filename); if (File == NULL) return false; FilePos = 0; StartPos = 0; diff --git a/src/files.h b/src/files.h index 94255b1a0..d0c769ba1 100644 --- a/src/files.h +++ b/src/files.h @@ -93,6 +93,8 @@ public: class FileReader : public FileReaderBase { +protected: + FILE *openfd(const char *filename); public: FileReader (); FileReader (const char *filename); From e1edb46bbbde70733cdd6843a16a6f127dd35330 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 11:56:26 +0100 Subject: [PATCH 04/36] - - let FWadLump use the newly added fdopen function. --- src/w_wad.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 412450d0a..ae52725d2 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1554,7 +1554,7 @@ FWadLump::FWadLump(int lumpnum, FResourceLump *lump) // Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming int fileno = Wads.GetLumpFile(lumpnum); const char *filename = Wads.GetWadFullName(fileno); - File = fopen(filename, "rb"); + File = openfd(filename); if (File != NULL) { Length = lump->LumpSize; From 20b8c1ef70720296dd618f422e669fe3acd76d1e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 11:57:32 +0100 Subject: [PATCH 05/36] - moved buildtexture.cpp from using stdio-based file IO to FileReader. --- src/textures/buildtexture.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index cb7786200..d23e5e6f2 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -306,15 +306,16 @@ int FTextureManager::CountBuildTiles () FString artpath = rffpath; artpath += artfile; - FILE *f = fopen (artpath, "rb"); - if (f == NULL) + FileReader fr; + + if (!fr.Open(artpath)) { break; } - size_t len = Q_filelength (f); + long len = fr.GetLength(); uint8_t *art = new uint8_t[len]; - if (fread (art, 1, len, f) != len || (numtiles = CountTiles(art)) == 0) + if (fr.Read (art, len) != len || (numtiles = CountTiles(art)) == 0) { delete[] art; } @@ -323,7 +324,6 @@ int FTextureManager::CountBuildTiles () BuildTileFiles.Push (art); totaltiles += numtiles; } - fclose (f); } } From e8735e27826b4489f5fd6a736130adbb5e21ef0c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 11:59:31 +0100 Subject: [PATCH 06/36] - use FileWriter to save the statistics file. --- src/statistics.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/statistics.cpp b/src/statistics.cpp index 2abd0bf12..e70642cf4 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -72,6 +72,7 @@ #include "m_crc32.h" #include "serializer.h" #include "g_levellocals.h" +#include "files.h" CVAR(Int, savestatistics, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(String, statfile, "zdoomstat.txt", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -260,8 +261,8 @@ static void SaveStatistics(const char *fn, TArray &statlist) { unsigned int j; - FILE * f = fopen(fn, "wt"); - if (f==NULL) return; + FileWriter *fw = FileWriter::Open(fn); + if (fw == nullptr) return; qsort(&statlist[0], statlist.Size(), sizeof(statlist[0]), compare_episode_names); for(unsigned i=0;i &statlist) qsort(&ep_stats.stats[0], ep_stats.stats.Size(), sizeof(ep_stats.stats[0]), compare_dates); - fprintf(f, "%s \"%s\"\n{\n", ep_stats.epi_header.GetChars(), ep_stats.epi_name.GetChars()); + fw->Printf("%s \"%s\"\n{\n", ep_stats.epi_header.GetChars(), ep_stats.epi_name.GetChars()); for(j=0;jinfo[0]>0) { - fprintf(f,"\t%2i. %10s \"%-22s\" %02d:%02d:%02d %i\n", j+1, sst->name, sst->info, + fw->Printf("\t%2i. %10s \"%-22s\" %02d:%02d:%02d %i\n", j+1, sst->name, sst->info, hours(sst->timeneeded), minutes(sst->timeneeded), seconds(sst->timeneeded), sst->skill); TArray &ls = sst->levelstats; if (ls.Size() > 0) { - fprintf(f,"\t{\n"); + fw->Printf("\t{\n"); qsort(&ls[0], ls.Size(), sizeof(ls[0]), compare_level_names); for(unsigned k=0;kPrintf("\t\t%-8s \"%-22s\" %02d:%02d:%02d\n", ls[k].name, ls[k].info, hours(ls[k].timeneeded), minutes(ls[k].timeneeded), seconds(ls[k].timeneeded)); } - fprintf(f,"\t}\n"); + fw->Printf("\t}\n"); } } } - fprintf(f,"}\n\n"); + fw->Printf("}\n\n"); } - fclose(f); + delete fw; } From 5e7dfa7cce24dfa7149f551559f963151fa3a471 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:01:19 +0100 Subject: [PATCH 07/36] - use FileWriter for the Timidity MIDI dumper --- src/sound/i_musicinterns.h | 2 +- .../mididevices/music_timidity_mididevice.cpp | 38 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 7bc5a31e5..4c796ead5 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -239,7 +239,7 @@ public: void Stop(); protected: - FILE *File; + FileWriter *File; }; // WildMidi implementation of a MIDI device --------------------------------- diff --git a/src/sound/mididevices/music_timidity_mididevice.cpp b/src/sound/mididevices/music_timidity_mididevice.cpp index cacddf542..474c0efa9 100644 --- a/src/sound/mididevices/music_timidity_mididevice.cpp +++ b/src/sound/mididevices/music_timidity_mididevice.cpp @@ -89,7 +89,7 @@ struct FmtChunk TimidityMIDIDevice::TimidityMIDIDevice(const char *args) { - Renderer = NULL; + Renderer = nullptr; Renderer = new Timidity::Renderer((float)SampleRate, args); } @@ -102,7 +102,7 @@ TimidityMIDIDevice::TimidityMIDIDevice(const char *args) TimidityMIDIDevice::~TimidityMIDIDevice() { Close(); - if (Renderer != NULL) + if (Renderer != nullptr) { delete Renderer; } @@ -246,10 +246,10 @@ FString TimidityMIDIDevice::GetStats() //========================================================================== TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename, int rate) - :TimidityMIDIDevice(NULL) + :TimidityMIDIDevice(nullptr) { - File = fopen(filename, "wb"); - if (File != NULL) + File = FileWriter::Open(filename); + if (File != nullptr) { // Write wave header uint32_t work[3]; FmtChunk fmt; @@ -257,7 +257,7 @@ TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename, work[0] = MAKE_ID('R','I','F','F'); work[1] = 0; // filled in later work[2] = MAKE_ID('W','A','V','E'); - if (3 != fwrite(work, 4, 3, File)) goto fail; + if (4*3 != File->Write(work, 4 * 3)) goto fail; fmt.ChunkID = MAKE_ID('f','m','t',' '); fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8)); @@ -281,17 +281,17 @@ TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename, fmt.SubFormatD[5] = 0x38; fmt.SubFormatD[6] = 0x9b; fmt.SubFormatD[7] = 0x71; - if (1 != fwrite(&fmt, sizeof(fmt), 1, File)) goto fail; + if (sizeof(fmt) != File->Write(&fmt, sizeof(fmt))) goto fail; work[0] = MAKE_ID('d','a','t','a'); work[1] = 0; // filled in later - if (2 != fwrite(work, 4, 2, File)) goto fail; + if (8 !=File->Write(work, 8)) goto fail; return; fail: Printf("Failed to write %s: %s\n", filename, strerror(errno)); - fclose(File); - File = NULL; + delete File; + File = nullptr; } } @@ -303,30 +303,30 @@ fail: TimidityWaveWriterMIDIDevice::~TimidityWaveWriterMIDIDevice() { - if (File != NULL) + if (File != nullptr) { - long pos = ftell(File); + long pos = File->Tell(); uint32_t size; // data chunk size size = LittleLong(uint32_t(pos - 8)); - if (0 == fseek(File, 4, SEEK_SET)) + if (0 == File->Seek(4, SEEK_SET)) { - if (1 == fwrite(&size, 4, 1, File)) + if (4 == File->Write(&size, 4)) { size = LittleLong(uint32_t(pos - 12 - sizeof(FmtChunk) - 8)); - if (0 == fseek(File, 4 + sizeof(FmtChunk) + 4, SEEK_CUR)) + if (0 == File->Seek(4 + sizeof(FmtChunk) + 4, SEEK_CUR)) { - if (1 == fwrite(&size, 4, 1, File)) + if (1 == File->Write(&size, 4)) { - fclose(File); + delete File; return; } } } } Printf("Could not finish writing wave file: %s\n", strerror(errno)); - fclose(File); + delete File; } } @@ -342,7 +342,7 @@ int TimidityWaveWriterMIDIDevice::Resume() while (ServiceStream(writebuffer, sizeof(writebuffer))) { - if (fwrite(writebuffer, sizeof(writebuffer), 1, File) != 1) + if (File->Write(writebuffer, sizeof(writebuffer)) != sizeof(writebuffer)) { Printf("Could not write entire wave file: %s\n", strerror(errno)); return 1; From ab58e4acb05cec76106fa8052b18129346cdf93c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:01:55 +0100 Subject: [PATCH 08/36] - use FileWriter for the AST dump. --- src/scripting/zscript/zcc_parser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index a0af21c14..cb927bb50 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -462,11 +462,11 @@ static void DoParse(int lumpnum) FString filename = Wads.GetLumpFullPath(lumpnum); filename.ReplaceChars(":\\/?|", '.'); filename << ".ast"; - FILE *ff = fopen(filename, "w"); + FileWriter *ff = FileWriter::Open(filename); if (ff != NULL) { - fputs(ast.GetChars(), ff); - fclose(ff); + ff->Write(ast.GetChars(), ast.Len()); + delete ff; } } From 37dc3211f73586795d5f607cbf0be5a447e9d391 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:02:36 +0100 Subject: [PATCH 09/36] - use FileReader for reading the play list. --- src/s_playlist.cpp | 13 ++++++------- src/s_playlist.h | 4 +++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/s_playlist.cpp b/src/s_playlist.cpp index e1b0fd5b6..315a2ac76 100644 --- a/src/s_playlist.cpp +++ b/src/s_playlist.cpp @@ -39,6 +39,7 @@ #include "s_playlist.h" #include "templates.h" #include "v_text.h" +#include "files.h" FPlayList::FPlayList (const char *path) { @@ -53,7 +54,7 @@ bool FPlayList::ChangeList (const char *path) { FString playlistdir; FString song; - FILE *file; + FileReader fr; bool first; bool pls; int i; @@ -61,7 +62,7 @@ bool FPlayList::ChangeList (const char *path) Songs.Clear(); Position = 0; - if ( (file = fopen (path, "rb")) == NULL) + if (!fr.Open(path)) { Printf ("Could not open " TEXTCOLOR_BOLD "%s" TEXTCOLOR_NORMAL ": %s\n", path, strerror(errno)); return false; @@ -70,7 +71,7 @@ bool FPlayList::ChangeList (const char *path) first = true; pls = false; playlistdir = ExtractFilePath(path); - while ((song = NextLine(file)).IsNotEmpty()) + while ((song = NextLine(&fr)).IsNotEmpty()) { if (first) { @@ -129,19 +130,17 @@ bool FPlayList::ChangeList (const char *path) Songs.Push(song); } } - fclose (file); - return Songs.Size() != 0; } -FString FPlayList::NextLine (FILE *file) +FString FPlayList::NextLine (FileReader *file) { char buffer[512]; char *skipper; do { - if (NULL == fgets (buffer, countof(buffer), file)) + if (NULL == file->Gets (buffer, countof(buffer))) return ""; for (skipper = buffer; *skipper != 0 && *skipper <= ' '; skipper++) diff --git a/src/s_playlist.h b/src/s_playlist.h index 74c06f857..859f0bce4 100644 --- a/src/s_playlist.h +++ b/src/s_playlist.h @@ -34,6 +34,8 @@ #ifndef __S_PLAYLIST_H__ #define __S_PLAYLIST_H__ +class FileReader; + class FPlayList { public: @@ -51,7 +53,7 @@ public: const char *GetSong (int position) const; private: - static FString NextLine (FILE *file); + static FString NextLine (FileReader *file); unsigned int Position; TArray Songs; From 623f35073c8a3936a4bb51d680e0df95399cecd3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:08:28 +0100 Subject: [PATCH 10/36] - use FileReader consistently for loading cached nodes. --- src/p_glnodes.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index e1510145e..977426e57 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1133,16 +1133,15 @@ static void CreateCachedNodes(MapData *map) memcpy(compressed + offset - 4, "ZGL3", 4); FString path = CreateCacheName(map, true); - FILE *f = fopen(path, "wb"); + FileWriter *fw = FileWriter::Open(path); - if (f != NULL) + if (fw != nullptr) { - if (fwrite(compressed, outlen+offset, 1, f) != 1) + if (fw->Write(compressed, outlen+offset) != 1) { Printf("Error saving nodes to file %s\n", path.GetChars()); } - - fclose(f); + delete fw; } else { @@ -1162,32 +1161,30 @@ static bool CheckCachedNodes(MapData *map) uint32_t *verts = NULL; FString path = CreateCacheName(map, false); - FILE *f = fopen(path, "rb"); - if (f == NULL) return false; + FileReader fr; - if (fread(magic, 1, 4, f) != 4) goto errorout; + if (!fr.Open(path)) return false; + + if (fr.Read(magic, 4) != 4) goto errorout; if (memcmp(magic, "CACH", 4)) goto errorout; - if (fread(&numlin, 4, 1, f) != 1) goto errorout; + if (fr.Read(&numlin, 4) != 4) goto errorout; numlin = LittleLong(numlin); if (numlin != level.lines.Size()) goto errorout; - if (fread(md5, 1, 16, f) != 16) goto errorout; + if (fr.Read(md5, 16) != 16) goto errorout; map->GetChecksum(md5map); if (memcmp(md5, md5map, 16)) goto errorout; verts = new uint32_t[numlin * 8]; - if (fread(verts, 8, numlin, f) != numlin) goto errorout; + if (fr.Read(verts, 8 * numlin) != 8 * numlin) goto errorout; - if (fread(magic, 1, 4, f) != 4) goto errorout; + if (fr.Read(magic, 4) != 4) goto errorout; if (memcmp(magic, "ZGL2", 4) && memcmp(magic, "ZGL3", 4)) goto errorout; try { - long pos = ftell(f); - FileReader fr(f); - fr.Seek(pos, SEEK_SET); P_LoadZNodes (fr, MAKE_ID(magic[0],magic[1],magic[2],magic[3])); } catch (CRecoverableError &error) @@ -1208,7 +1205,6 @@ static bool CheckCachedNodes(MapData *map) } delete [] verts; - fclose(f); return true; errorout: @@ -1216,7 +1212,6 @@ errorout: { delete[] verts; } - fclose(f); return false; } From ebf5c5763e5c11c01a76e61990264693e5502943 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:15:26 +0100 Subject: [PATCH 11/36] - removed the unused bitmap loading and saving features from hqnx_asm/hqnx_asm_Image. --- src/gl/hqnx_asm/hqnx_asm_Image.cpp | 1072 ---------------------------- src/gl/hqnx_asm/hqnx_asm_Image.h | 75 -- 2 files changed, 1147 deletions(-) diff --git a/src/gl/hqnx_asm/hqnx_asm_Image.cpp b/src/gl/hqnx_asm/hqnx_asm_Image.cpp index 7af120173..31adda874 100644 --- a/src/gl/hqnx_asm/hqnx_asm_Image.cpp +++ b/src/gl/hqnx_asm/hqnx_asm_Image.cpp @@ -106,1078 +106,6 @@ int DLL CImage::Convert32To17( void ) return nRes; } -int DLL CImage::ConvertTo32( void ) -{ - int nRes = eConvUnknownFormat; - if ( m_pBitmap == NULL ) - return eConvSourceMemory; - - switch ( m_BitPerPixel ) - { - case 8: - { - nRes = 0; - m_BitPerPixel = 32; - unsigned char * pNewBitmap = (unsigned char *)malloc(m_NumPixel*4); - if ( pNewBitmap != NULL ) - { - unsigned char * pTemp8 = m_pBitmap; - unsigned char * pTemp32 = pNewBitmap; - unsigned char c; - for ( int i=0; i> 3); - *(pTemp24++) = ((rgb & 0xF800) >> 8); - } - free(m_pBitmap); - m_pBitmap = pNewBitmap; - } - else - nRes = eConvDestMemory; - - break; - } - case 32: - { - nRes = 0; - m_BitPerPixel = 24; - unsigned char * pNewBitmap = (unsigned char *)malloc(m_NumPixel*3); - if ( pNewBitmap != NULL ) - { - unsigned char * pTemp32 = m_pBitmap; - unsigned char * pTemp24 = pNewBitmap; - for ( int i=0; i> 3; - g = m_Pal[c].g >> 2; - b = m_Pal[c].b >> 3; - *(pTemp16++) = (r << 11) + (g << 5) + b; - } - free(m_pBitmap); - m_pBitmap = pNewBitmap; - } - else - nRes = eConvDestMemory; - - break; - } - case 24: - { - nRes = 0; - m_BitPerPixel = 16; - unsigned char * pNewBitmap = (unsigned char *)malloc(m_NumPixel*2); - if ( pNewBitmap != NULL ) - { - unsigned char * pTemp24 = m_pBitmap; - unsigned short * pTemp16 = (unsigned short *)pNewBitmap; - unsigned short r, g, b; - for ( int i=0; i> 3; - g = (*(pTemp24++)) >> 2; - r = (*(pTemp24++)) >> 3; - *(pTemp16++) = (r << 11) + (g << 5) + b; - } - free(m_pBitmap); - m_pBitmap = pNewBitmap; - } - else - nRes = eConvDestMemory; - - break; - } - case 32: - { - nRes = 0; - m_BitPerPixel = 16; - unsigned char * pNewBitmap = (unsigned char *)malloc(m_NumPixel*2); - if ( pNewBitmap != NULL ) - { - unsigned char * pTemp32 = m_pBitmap; - unsigned short * pTemp16 = (unsigned short *)pNewBitmap; - unsigned short r, g, b; - for ( int i=0; i> 3; - g = (*(pTemp32++)) >> 2; - r = (*(pTemp32++)) >> 3; - pTemp32++; - *(pTemp16++) = (r << 11) + (g << 5) + b; - } - free(m_pBitmap); - m_pBitmap = pNewBitmap; - } - else - nRes = eConvDestMemory; - - break; - } - } - - return nRes; -} - -int CImage::Convert8To17( int transindex ) -{ - int nRes = eConvUnknownFormat; - - if ( m_BitPerPixel == 8 ) - { - m_BitPerPixel = 32; - unsigned char * pNewBitmap = (unsigned char *)malloc(m_NumPixel*4); - if ( pNewBitmap != NULL ) - { - unsigned char * pTemp8 = m_pBitmap; - unsigned int * pTemp32 = (unsigned int *)pNewBitmap; - unsigned int r, g, b; - unsigned char c; - for ( int i=0; i> 3; - g = m_Pal[c].g >> 2; - b = m_Pal[c].b >> 3; - *(pTemp32++) = (r << 11) + (g << 5) + b + (transindex != c ? 0x10000 : 0); - } - free(m_pBitmap); - m_pBitmap = pNewBitmap; - } - else - nRes = eConvDestMemory; - - nRes = 0; - } - - return nRes; -} - -int CImage::SaveBmp(char *szFilename) -{ - _BMPFILEHEADER fh; - _BMPIMAGEHEADER ih; - unsigned char BmpPal[256][4]; - long int SuffLen; - long int Dummy = 0; - unsigned char * pBuf; - short i; - - if (!(f = fopen(szFilename, "wb"))) return eSaveBmpFileOpen; - if ( m_pBitmap == NULL ) return eSaveBmpSourceMemory; - - fh.bfType=0x4D42; - if (m_BitPerPixel==8) - { - SuffLen=((m_Xres+3)/4)*4-m_Xres; - ih.biSize=0x28; - ih.biWidth=m_Xres; - ih.biHeight=m_Yres; - ih.biPlanes=1; - ih.biBitCount=8; - ih.biCompression=0; - ih.biSizeImage=(m_Xres+SuffLen)*m_Yres; - ih.biXPelsPerMeter=ih.biYPelsPerMeter=0x2E23; // 300dpi (pixels per meter) - ih.biClrUsed=ih.biClrImportant=0; - fh.bfSize=(ih.biSizeImage)+0x0436; - fh.bfRes1=0; - fh.bfOffBits=0x0436; - if (fwrite(&fh, 14, 1, f) != 1) return eSaveBmpFileWrite; - if (fwrite(&ih, 40, 1, f) != 1) return eSaveBmpFileWrite; - for (i=0; i<256; i++) - { - BmpPal[i][0]=m_Pal[i].b; - BmpPal[i][1]=m_Pal[i].g; - BmpPal[i][2]=m_Pal[i].r; - BmpPal[i][3]=0; - } - if (fwrite(&BmpPal, 1024, 1, f) != 1) return eSaveBmpFileWrite; - pBuf=m_pBitmap; - pBuf+=m_NumPixel; - for (i=0; i0) - { - if (fwrite(&Dummy, SuffLen, 1, f) != 1) return eSaveBmpFileWrite; - } - } - } - else - if (m_BitPerPixel==24) - { - SuffLen=((m_Xres*3+3)/4)*4-m_Xres*3; - ih.biSize=0x28; - ih.biWidth=m_Xres; - ih.biHeight=m_Yres; - ih.biPlanes=1; - ih.biBitCount=24; - ih.biCompression=0; - ih.biSizeImage=(m_Xres*3+SuffLen)*m_Yres; - ih.biXPelsPerMeter=ih.biYPelsPerMeter=0x2E23; // 300dpi (pixels per meter) - ih.biClrUsed=ih.biClrImportant=0; - fh.bfSize=(ih.biSizeImage)+0x0036; - fh.bfRes1=0; - fh.bfOffBits=0x0036; - if (fwrite(&fh, 14, 1, f) != 1) return eSaveBmpFileWrite; - if (fwrite(&ih, 40, 1, f) != 1) return eSaveBmpFileWrite; - pBuf=m_pBitmap; - pBuf+=m_NumPixel*3; - for (i=0; i0) - { - if (fwrite(&Dummy, SuffLen, 1, f) != 1) return eSaveBmpFileWrite; - } - } - } - else - return eSaveBmpColorDepth; - - fclose(f); - - return 0; -} - -int CImage::LoadBmp(char *szFilename) -{ - _BMPFILEHEADER fh; - _BMPIMAGEHEADEROLD ih_old; - _BMPIMAGEHEADER ih; - unsigned char BmpPal[256][4]; - long int biSize; - long int SuffLen; - long int Dummy = 0; - unsigned char * pBuf; - short i; - long int xres, yres; - unsigned short bits; - - if (!(f = fopen(szFilename, "rb"))) return eLoadBmpFileOpen; - if (fread(&fh, 14, 1, f) != 1) return eLoadBmpFileRead; - if (fh.bfType != 0x4D42) return eLoadBmpBadFormat; - if (fread(&biSize, 4, 1, f) != 1) return eLoadBmpFileRead; - if (biSize > 12) - { - fseek( f, -4, SEEK_CUR ); - if (fread(&ih, biSize, 1, f) != 1) return eLoadBmpFileRead; - xres = ih.biWidth; - yres = ih.biHeight; - bits = ih.biBitCount; - } - else - { - fseek( f, -4, SEEK_CUR ); - if (fread(&ih_old, biSize, 1, f) != 1) return eLoadBmpFileRead; - xres = ih_old.biWidth; - yres = ih_old.biHeight; - bits = ih_old.biBitCount; - } - - if ( Init( xres, yres, bits ) != 0 ) return eLoadBmpInit; - if (m_BitPerPixel==8) - { - SuffLen=((m_Xres+3)/4)*4-m_Xres; - if (fread(&BmpPal, 1024, 1, f) != 1) return eLoadBmpFileRead; - for (i=0; i<256; i++) - { - m_Pal[i].b=BmpPal[i][0]; - m_Pal[i].g=BmpPal[i][1]; - m_Pal[i].r=BmpPal[i][2]; - } - pBuf=m_pBitmap; - pBuf+=m_NumPixel; - for (i=0; i0) - { - if (fread(&Dummy, SuffLen, 1, f) != 1) return eLoadBmpFileRead; - } - } - } - else - if (m_BitPerPixel==24) - { - SuffLen=((m_Xres*3+3)/4)*4-(m_Xres*3); - pBuf=m_pBitmap; - pBuf+=m_NumPixel*3; - for (i=0; i0) - { - if (fread(&Dummy, SuffLen, 1, f) != 1) return eLoadBmpFileRead; - } - } - } - else - return eLoadBmpColorDepth; - - fclose(f); - - return 0; -} - -void CImage::Output( void ) -{ - fwrite(m_cBuf, m_nCount, 1, f); - m_nCount=0; -} - -void CImage::Output( char c ) -{ - if ( m_nCount == sizeof(m_cBuf) ) - { - fwrite(m_cBuf, m_nCount, 1, f); - m_nCount=0; - } - m_cBuf[m_nCount++] = c; -} - -void CImage::Output( char * pcData, int nSize ) -{ - for ( int i=0; i 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+i-nDif-nRep), nDif ); - } - nDif = 1; - } - } - else - { - if ( bEqual && (nRep<127) ) - nRep++; - else - { - Output( nRep+128 ); - Output( (char*)&colOld, 1 ); - nRep = 0; - nDif = 1; - } - } - } - - if ( nRep == 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+m_Xres-nDif), nDif ); - } - else - { - Output( nRep+128 ); - Output( (char*)&colOld, 1 ); - } - Output(); - } - } - } - else - if (m_BitPerPixel==24) - { - fh.tiImageType = bCompressed ? 10 : 2; - if (fwrite(&fh, sizeof(fh), 1, f) != 1) return eSaveTgaFileWrite; - - _BGR * pcolBuf = (_BGR *)m_pBitmap; - pcolBuf += m_NumPixel; - - if ( !bCompressed ) - { - for (j=0; j 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+i-nDif-nRep), sizeof(_BGR)*nDif ); - } - nDif = 1; - } - } - else - { - if ( bEqual && (nRep<127) ) - nRep++; - else - { - Output( nRep+128 ); - Output( (char*)&colOld, sizeof(_BGR) ); - nRep = 0; - nDif = 1; - } - } - } - - if ( nRep == 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+m_Xres-nDif), sizeof(_BGR)*nDif ); - } - else - { - Output( nRep+128 ); - Output( (char*)&colOld, sizeof(_BGR) ); - } - Output(); - } - } - } - else - if (m_BitPerPixel==32) - { - fh.tiImageType = bCompressed ? 10 : 2; - fh.tiAttrBits = 8; - if (fwrite(&fh, sizeof(fh), 1, f) != 1) return eSaveTgaFileWrite; - - _BGRA * pcolBuf = (_BGRA *)m_pBitmap; - pcolBuf += m_NumPixel; - - if ( !bCompressed ) - { - for (j=0; j 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+i-nDif-nRep), sizeof(_BGRA)*nDif ); - } - nDif = 1; - } - } - else - { - if ( bEqual && (nRep<127) ) - nRep++; - else - { - Output( nRep+128 ); - Output( (char*)&colOld, sizeof(_BGRA) ); - nRep = 0; - nDif = 1; - } - } - } - - if ( nRep == 0 ) - { - Output( nDif-1 ); - Output( (char*)(pcolBuf+m_Xres-nDif), sizeof(_BGRA)*nDif ); - } - else - { - Output( nRep+128 ); - Output( (char*)&colOld, sizeof(_BGRA) ); - } - Output(); - } - } - } - else - return eSaveTgaColorDepth; - - fclose(f); - - return 0; -} - -int CImage::LoadTga(char *szFilename) -{ - _TGAHEADER fh; - int i, j, k; - unsigned char nCount; - - if (!(f = fopen(szFilename, "rb"))) return eLoadTgaFileOpen; - if (fread(&fh, sizeof(fh), 1, f) != 1) return eLoadTgaFileRead; - bool bCompressed = (( fh.tiImageType & 8 ) != 0); - if ((fh.tiBitPerPixel<=0) || (fh.tiBitPerPixel>32)) - return eLoadTgaBadFormat; - - if ( Init( fh.tiXres, fh.tiYres, fh.tiBitPerPixel ) != 0 ) - return eLoadTgaInit; - - if ( m_BitPerPixel == 8 ) - { - if ( fh.tiPaletteIncluded == 1 ) - { - if ( fh.tiPaletteBpp == 24) - { - if (fread(&m_Pal, 3, fh.tiPaletteSize, f) != fh.tiPaletteSize) - return eLoadTgaFileRead; - } - else - if ( fh.tiPaletteBpp == 32) - { - unsigned char BmpPal[256][4]; - - if (fread(&BmpPal, 4, fh.tiPaletteSize, f) != fh.tiPaletteSize) - return eLoadTgaFileRead; - - for (i=0; i= m_pBitmap ) - { - nCount = Input(); - if ((nCount & 128)==0) - { - for (k=0; k<=nCount; k++) - { - colCur = Input(); - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - else - { - colCur = Input(); - for (k=0; k<=nCount-128; k++) - { - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - } - } - } - else - if ( m_BitPerPixel == 24 ) - { - _BGR * pcolBuf = (_BGR *)m_pBitmap; - pcolBuf += m_NumPixel; - - if ( !bCompressed ) - { - for (j=0; j= (_BGR *)m_pBitmap ) - { - nCount = Input(); - if ((nCount & 128)==0) - { - for (k=0; k<=nCount; k++) - { - colCur.b = Input(); - colCur.g = Input(); - colCur.r = Input(); - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - else - { - colCur.b = Input(); - colCur.g = Input(); - colCur.r = Input(); - for (k=0; k<=nCount-128; k++) - { - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - } - } - } - else - if ( m_BitPerPixel == 32 ) - { - _BGRA * pcolBuf = (_BGRA *)m_pBitmap; - pcolBuf += m_NumPixel; - - if ( !bCompressed ) - { - for (j=0; j= (_BGRA *)m_pBitmap ) - { - nCount = Input(); - if ((nCount & 128)==0) - { - for (k=0; k<=nCount; k++) - { - colCur.b = Input(); - colCur.g = Input(); - colCur.r = Input(); - colCur.a = Input(); - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - else - { - colCur.b = Input(); - colCur.g = Input(); - colCur.r = Input(); - colCur.a = Input(); - for (k=0; k<=nCount-128; k++) - { - *(pcolBuf+i) = colCur; - if ( (++i) == m_Xres ) - { - i=0; - pcolBuf -= m_Xres; - break; - } - } - } - } - } - } - else - return eLoadTgaColorDepth; - - fclose(f); - - return 0; -} - -int DLL CImage::Load(char *szFilename) -{ - int nRes = 0; - - if ( szFilename != NULL ) - { - char * szExt = strrchr( szFilename, '.' ); - int nNotTGA = 1; - - if ( szExt != NULL ) - nNotTGA = _stricmp( szExt, ".tga" ); - - if ( nNotTGA != 0 ) - nRes = LoadBmp( szFilename ); - else - nRes = LoadTga( szFilename ); - } - else - nRes = eLoadFilename; - - return nRes; -} - -int DLL CImage::Save(char *szFilename) -{ - int nRes = 0; - int nNotTGA = 1; - - if ( szFilename != NULL ) - { - char * szExt = strrchr( szFilename, '.' ); - - if ( szExt != NULL ) - nNotTGA = _stricmp( szExt, ".tga" ); - - if ( nNotTGA != 0 ) - { - if (( m_BitPerPixel == 16 ) || ( m_BitPerPixel == 32 )) - nRes = ConvertTo24(); - - if (nRes == 0) - nRes = SaveBmp( szFilename ); - } - else - { - if ( m_BitPerPixel == 16 ) - nRes = ConvertTo24(); - - if (nRes == 0) - nRes = SaveTga( szFilename, true ); - } - } - else - nRes = eSaveFilename; - - return nRes; -} } \ No newline at end of file diff --git a/src/gl/hqnx_asm/hqnx_asm_Image.h b/src/gl/hqnx_asm/hqnx_asm_Image.h index 38f0f1d6a..918b904fe 100644 --- a/src/gl/hqnx_asm/hqnx_asm_Image.h +++ b/src/gl/hqnx_asm/hqnx_asm_Image.h @@ -47,91 +47,16 @@ class CImage eConvSourceMemory = 11, eConvDestMemory = 12, - eSaveBmpFileOpen = 20, - eSaveBmpFileWrite = 21, - eSaveBmpSourceMemory = 22, - eSaveBmpColorDepth = 23, - - eLoadBmpFileOpen = 30, - eLoadBmpFileRead = 31, - eLoadBmpBadFormat = 32, - eLoadBmpInit = 33, - eLoadBmpColorDepth = 34, - - eSaveTgaFileOpen = 40, - eSaveTgaFileWrite = 41, - eSaveTgaSourceMemory = 42, - eSaveTgaColorDepth = 43, - - eLoadTgaFileOpen = 50, - eLoadTgaFileRead = 51, - eLoadTgaBadFormat = 52, - eLoadTgaInit = 53, - eLoadTgaColorDepth = 54, - - eLoadFilename = 60, - eSaveFilename = 61, }; - struct _BMPFILEHEADER - { - unsigned short bfType; - long int bfSize, bfRes1, bfOffBits; - }; - - struct _BMPIMAGEHEADEROLD - { - long int biSize; - unsigned short biWidth, biHeight; - unsigned short biPlanes, biBitCount; - }; - - struct _BMPIMAGEHEADER - { - long int biSize, biWidth, biHeight; - unsigned short biPlanes, biBitCount; - long int biCompression, biSizeImage; - long int biXPelsPerMeter, biYPelsPerMeter; - long int biClrUsed, biClrImportant; - }; - - struct _TGAHEADER - { - unsigned char tiIdentSize; - unsigned char tiPaletteIncluded; - unsigned char tiImageType; - unsigned short tiPaletteStart; - unsigned short tiPaletteSize; - unsigned char tiPaletteBpp; - unsigned short tiX0; - unsigned short tiY0; - unsigned short tiXres; - unsigned short tiYres; - unsigned char tiBitPerPixel; - unsigned char tiAttrBits; - }; public: int DLL Init( int Xres, int Yres, unsigned short BitPerPixel ); int DLL SetImage(unsigned char *img, int width, int height, int bpp); int DLL Destroy(); - int DLL ConvertTo32( void ); - int DLL ConvertTo24( void ); - int DLL ConvertTo16( void ); - int DLL Convert8To17( int transindex ); int DLL Convert32To17( void ); - int SaveBmp(char *szFilename); - int LoadBmp(char *szFilename); - int SaveTga(char *szFilename, bool bCompressed ); - int LoadTga(char *szFilename); - int DLL Load(char *szFilename); - int DLL Save(char *szFilename); private: - void Output( char * pcData, int nSize ); - void Output( char c ); - void Output( void ); - unsigned char Input( void ); public: int m_Xres, m_Yres; From 1af42b3d501f00ab6cc5e820ea18326ee291af6e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:31:21 +0100 Subject: [PATCH 12/36] - use FileWriter for the OPL dumper. --- .../music_opldumper_mididevice.cpp | 58 ++++++++++--------- src/win32/win32swiface.h | 13 +---- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/sound/mididevices/music_opldumper_mididevice.cpp b/src/sound/mididevices/music_opldumper_mididevice.cpp index e301a3054..3519103e8 100644 --- a/src/sound/mididevices/music_opldumper_mididevice.cpp +++ b/src/sound/mididevices/music_opldumper_mididevice.cpp @@ -40,6 +40,7 @@ #include "m_swap.h" #include "w_wad.h" #include "opl.h" +#include "files.h" // MACROS ------------------------------------------------------------------ @@ -48,7 +49,7 @@ class OPLDump : public OPLEmul { public: - OPLDump(FILE *file) : File(file), TimePerTick(0), CurTime(0), + OPLDump(FileWriter *file) : File(file), TimePerTick(0), CurTime(0), CurIntTime(0), TickMul(1), CurChip(0) {} // If we're doing things right, these should never be reset. @@ -66,7 +67,7 @@ public: virtual void WriteDelay(int ticks) = 0; protected: - FILE *File; + FileWriter *File; double TimePerTick; // in milliseconds double CurTime; int CurIntTime; @@ -91,10 +92,10 @@ protected: class OPL_RDOSdump : public OPLDump { public: - OPL_RDOSdump(FILE *file) : OPLDump(file) + OPL_RDOSdump(FileWriter *file) : OPLDump(file) { assert(File != NULL); - fwrite("RAWADATA\0", 1, 10, File); + file->Write("RAWADATA\0", 10); NeedClockRate = true; } virtual ~OPL_RDOSdump() @@ -102,8 +103,8 @@ public: if (File != NULL) { uint16_t endmark = 0xFFFF; - fwrite(&endmark, 2, 1, File); - fclose(File); + File->Write(&endmark, 2); + delete File; } } @@ -114,13 +115,13 @@ public: if (chipnum != CurChip) { uint8_t switcher[2] = { (uint8_t)(chipnum + 1), 2 }; - fwrite(switcher, 1, 2, File); + File->Write(switcher, 2); } reg &= 255; if (reg != 0 && reg != 2 && (reg != 255 || v != 255)) { uint8_t cmd[2] = { uint8_t(v), uint8_t(reg) }; - fwrite(cmd, 1, 2, File); + File->Write(cmd, 2); } } @@ -146,15 +147,15 @@ public: if (NeedClockRate) { // Set the initial clock rate. clock_word = LittleShort(clock_word); - fseek(File, 8, SEEK_SET); - fwrite(&clock_word, 2, 1, File); - fseek(File, 0, SEEK_END); + File->Seek(8, SEEK_SET); + File->Write(&clock_word, 2); + File->Seek(0, SEEK_END); NeedClockRate = false; } else { // Change the clock rate in the middle of the song. uint8_t clock_change[4] = { 0, 2, uint8_t(clock_word & 255), uint8_t(clock_word >> 8) }; - fwrite(clock_change, 1, 4, File); + File->Write(clock_change, 4); } } virtual void WriteDelay(int ticks) @@ -170,10 +171,10 @@ public: { ticks -= 255; delay[0] = 255; - fwrite(delay, 1, 2, File); + File->Write(delay, 2); } delay[0] = uint8_t(ticks); - fwrite(delay, 1, 2, File); + File->Write(delay, 2); } } protected: @@ -183,30 +184,30 @@ protected: class OPL_DOSBOXdump : public OPLDump { public: - OPL_DOSBOXdump(FILE *file, bool dual) : OPLDump(file), Dual(dual) + OPL_DOSBOXdump(FileWriter *file, bool dual) : OPLDump(file), Dual(dual) { assert(File != NULL); - fwrite("DBRAWOPL" + File->Write("DBRAWOPL" "\0\0" // Minor version number "\1\0" // Major version number "\0\0\0\0" // Total milliseconds "\0\0\0", // Total data - 1, 20, File); + 20); char type[4] = { (char)(Dual * 2), 0, 0, 0 }; // Single or dual OPL-2 - fwrite(type, 1, 4, File); + File->Write(type, 4); } virtual ~OPL_DOSBOXdump() { if (File != NULL) { - long where_am_i = ftell(File); + long where_am_i =File->Tell(); uint32_t len[2]; - fseek(File, 12, SEEK_SET); + File->Seek(12, SEEK_SET); len[0] = LittleLong(CurIntTime); len[1] = LittleLong(uint32_t(where_am_i - 24)); - fwrite(len, 4, 2, File); - fclose(File); + File->Write(len, 8); + delete File; } } virtual void WriteReg(int reg, int v) @@ -216,11 +217,12 @@ public: if (chipnum != CurChip) { CurChip = chipnum; - fputc(chipnum + 2, File); + chipnum += 2; + File->Write(&chipnum, 1); } reg &= 255; uint8_t cmd[3] = { 4, uint8_t(reg), uint8_t(v) }; - fwrite (cmd + (reg > 4), 1, 3 - (reg > 4), File); + File->Write(cmd + (reg > 4), 3 - (reg > 4)); } virtual void WriteDelay(int ticks) { @@ -234,20 +236,20 @@ public: while (delay > 65536) { uint8_t cmd[3] = { 1, 255, 255 }; - fwrite(cmd, 1, 2, File); + File->Write(cmd, 2); delay -= 65536; } delay--; if (delay <= 255) { uint8_t cmd[2] = { 0, uint8_t(delay) }; - fwrite(cmd, 1, 2, File); + File->Write(cmd, 2); } else { assert(delay <= 65535); uint8_t cmd[3] = { 1, uint8_t(delay & 255), uint8_t(delay >> 8) }; - fwrite(cmd, 1, 3, File); + File->Write(cmd, 3); } } } @@ -338,7 +340,7 @@ DiskWriterIO::~DiskWriterIO() int DiskWriterIO::Init(uint32_t numchips, bool, bool initopl3) { - FILE *file = fopen(Filename, "wb"); + FileWriter *file = FileWriter::Open(Filename); if (file == NULL) { Printf("Could not open %s for writing.\n", Filename.GetChars()); diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index 59101c602..657b120a3 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -380,18 +380,7 @@ enum BQS_InGameColormap, }; -#if 0 -#define STARTLOG do { if (!dbg) dbg = fopen ("e:/vid.log", "w"); } while(0) -#define STOPLOG do { if (dbg) { fclose (dbg); dbg=NULL; } } while(0) -#define LOG(x) do { if (dbg) { fprintf (dbg, x); fflush (dbg); } } while(0) -#define LOG1(x,y) do { if (dbg) { fprintf (dbg, x, y); fflush (dbg); } } while(0) -#define LOG2(x,y,z) do { if (dbg) { fprintf (dbg, x, y, z); fflush (dbg); } } while(0) -#define LOG3(x,y,z,zz) do { if (dbg) { fprintf (dbg, x, y, z, zz); fflush (dbg); } } while(0) -#define LOG4(x,y,z,a,b) do { if (dbg) { fprintf (dbg, x, y, z, a, b); fflush (dbg); } } while(0) -#define LOG5(x,y,z,a,b,c) do { if (dbg) { fprintf (dbg, x, y, z, a, b, c); fflush (dbg); } } while(0) -extern FILE *dbg; -#define VID_FILE_DEBUG 1 -#elif _DEBUG && 0 +#if _DEBUG && 0 #define STARTLOG #define STOPLOG #define LOG(x) { OutputDebugString(x); } From 8d26760671f97d5ca13631c597bc0e97fa1f6761 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:33:58 +0100 Subject: [PATCH 13/36] - use FileWriter for 'writemidi' CCMD. --- src/sound/i_music.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index 19db0161d..28f839c6c 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -803,18 +803,17 @@ CCMD (writemidi) } TArray midi; - FILE *f; bool success; static_cast(currSong)->CreateSMF(midi, 1); - f = fopen(argv[1], "wb"); + auto f = FileWriter::Open(argv[1]); if (f == NULL) { Printf("Could not open %s.\n", argv[1]); return; } - success = (fwrite(&midi[0], 1, midi.Size(), f) == (size_t)midi.Size()); - fclose (f); + success = (f->Write(&midi[0], midi.Size()) == (size_t)midi.Size()); + delete f; if (!success) { From 14af7818b8d90286e61e8dba6139e8d84a0f7ab8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:38:38 +0100 Subject: [PATCH 14/36] - use FileReader for all operations on external lumps. --- src/resourcefiles/resourcefile.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 7c9c957e3..96bd50e0f 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -669,12 +669,11 @@ FExternalLump::FExternalLump(const char *_filename, int filesize) if (filesize == -1) { - FILE *f = fopen(_filename,"rb"); - if (f != NULL) + FileReader f; + + if (f.Open(_filename)) { - fseek(f, 0, SEEK_END); - LumpSize = ftell(f); - fclose(f); + LumpSize = f.GetLength(); } else { @@ -703,11 +702,11 @@ FExternalLump::~FExternalLump() int FExternalLump::FillCache() { Cache = new char[LumpSize]; - FILE *f = fopen(filename, "rb"); - if (f != NULL) + FileReader f; + + if (f.Open(filename)) { - fread(Cache, 1, LumpSize, f); - fclose(f); + f.Read(Cache, LumpSize); } else { From e15b23f1324bb3324ce596e0052ed3673cd919a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 12:46:25 +0100 Subject: [PATCH 15/36] - use FileWriter for writing zip files (i.e. savegames.) --- src/resourcefiles/file_zip.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 02e350998..3d842131d 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -542,7 +542,7 @@ static void time_to_dos(struct tm *time, unsigned short *dosdate, unsigned short // //========================================================================== -int AppendToZip(FILE *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time) +int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time) { FZipLocalFileHeader local; int position; @@ -562,12 +562,12 @@ int AppendToZip(FILE *zip_file, const char *filename, FCompressedBuffer &content // Fill in local directory header. - position = (int)ftell(zip_file); + position = (int)zip_file->Tell(); // Write out the header, file name, and file data. - if (fwrite(&local, sizeof(local), 1, zip_file) != 1 || - fwrite(filename, strlen(filename), 1, zip_file) != 1 || - fwrite(content.mBuffer, 1, content.mCompressedSize, zip_file) != content.mCompressedSize) + if (zip_file->Write(&local, sizeof(local)) != sizeof(local) || + zip_file->Write(filename, strlen(filename)) != strlen(filename) || + zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize) { return -1; } @@ -583,7 +583,7 @@ int AppendToZip(FILE *zip_file, const char *filename, FCompressedBuffer &content // //========================================================================== -int AppendCentralDirectory(FILE *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time, int position) +int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time, int position) { FZipCentralDirectoryInfo dir; @@ -607,8 +607,8 @@ int AppendCentralDirectory(FILE *zip_file, const char *filename, FCompressedBuff dir.ExternalAttributes = 0; dir.LocalHeaderOffset = LittleLong(position); - if (fwrite(&dir, sizeof(dir), 1, zip_file) != 1 || - fwrite(filename, strlen(filename), 1, zip_file) != 1) + if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) || + zip_file->Write(filename, strlen(filename)) != strlen(filename)) { return -1; } @@ -629,7 +629,7 @@ bool WriteZip(const char *filename, TArray &filenames, TArray &filenames, TArrayTell(); for (unsigned i = 0; i < filenames.Size(); i++) { if (AppendCentralDirectory(f, filenames[i], content[i], mydate, mytime, positions[i]) < 0) { - fclose(f); + delete f; remove(filename); return false; } @@ -662,15 +662,15 @@ bool WriteZip(const char *filename, TArray &filenames, TArrayTell() - dirofs); dirend.ZipCommentLength = 0; - if (fwrite(&dirend, sizeof(dirend), 1, f) != 1) + if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) { - fclose(f); + delete f; remove(filename); return false; } - fclose(f); + delete f; return true; } return false; From 838e52001cd27b05b2f3d647b5174753587514aa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 13:09:59 +0100 Subject: [PATCH 16/36] - got rid of M_ReadFile(Malloc) which werew each used only once in the entire code. These were still using the low level POSIX-style file interface which shouldn't really be used anymore. - let FScanner::OpenFile return an error instead of throwing an exception. The exception was never used anyway aside from being caught right away to be ignored. --- src/b_game.cpp | 8 ++----- src/g_game.cpp | 12 +++++++++- src/m_misc.cpp | 54 ------------------------------------------- src/m_misc.h | 2 -- src/posix/i_steam.cpp | 23 +++++++++--------- src/sc_man.cpp | 17 ++++++++++---- src/sc_man.h | 2 +- src/statistics.cpp | 2 +- 8 files changed, 39 insertions(+), 81 deletions(-) diff --git a/src/b_game.cpp b/src/b_game.cpp index 1cb91ddf4..4300e0ada 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -532,13 +532,9 @@ bool FCajunMaster::LoadBots () DPrintf (DMSG_ERROR, "No " BOTFILENAME ", so no bots\n"); return false; } - try + if (!sc.OpenFile(tmp)) { - sc.OpenFile(tmp); - } - catch (CRecoverableError &err) - { - Printf("%s. So no bots\n", err.GetMessage()); + Printf("Unable to open %s. So no bots\n"); return false; } diff --git a/src/g_game.cpp b/src/g_game.cpp index ec1a7be50..b2e27eed4 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2798,7 +2798,17 @@ void G_DoPlayDemo (void) { FixPathSeperator (defdemoname); DefaultExtension (defdemoname, ".lmp"); - M_ReadFileMalloc (defdemoname, &demobuffer); + FileReader fr; + if (!fr.Open(defdemoname)) + { + I_Error("Unable to open demo '%s'", defdemoname.GetChars()); + } + auto len = fr.GetLength(); + demobuffer = (uint8_t*)M_Malloc(len); + if (fr.Read(demobuffer, len) != len) + { + I_Error("Unable to read demo '%s'", defdemoname.GetChars()); + } } demo_p = demobuffer; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index bda8dcb80..2b23ef6c2 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -115,60 +115,6 @@ bool M_WriteFile (char const *name, void *source, int length) } -// -// M_ReadFile -// -int M_ReadFile (char const *name, uint8_t **buffer) -{ - int handle, count, length; - struct stat fileinfo; - uint8_t *buf; - - handle = open (name, O_RDONLY | O_BINARY, 0666); - if (handle == -1) - I_Error ("Couldn't read file %s", name); - // [BL] Use stat instead of fstat for v140_xp hack - if (stat (name,&fileinfo) == -1) - I_Error ("Couldn't read file %s", name); - length = fileinfo.st_size; - buf = new uint8_t[length]; - count = read (handle, buf, length); - close (handle); - - if (count < length) - I_Error ("Couldn't read file %s", name); - - *buffer = buf; - return length; -} - -// -// M_ReadFile (same as above but use malloc instead of new to allocate the buffer.) -// -int M_ReadFileMalloc (char const *name, uint8_t **buffer) -{ - int handle, count, length; - struct stat fileinfo; - uint8_t *buf; - - handle = open (name, O_RDONLY | O_BINARY, 0666); - if (handle == -1) - I_Error ("Couldn't read file %s", name); - // [BL] Use stat instead of fstat for v140_xp hack - if (stat (name,&fileinfo) == -1) - I_Error ("Couldn't read file %s", name); - length = fileinfo.st_size; - buf = (uint8_t*)M_Malloc(length); - count = read (handle, buf, length); - close (handle); - - if (count < length) - I_Error ("Couldn't read file %s", name); - - *buffer = buf; - return length; -} - //--------------------------------------------------------------------------- // // PROC M_FindResponseFile diff --git a/src/m_misc.h b/src/m_misc.h index 660eb7a58..2eee63b7d 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -34,8 +34,6 @@ class FIWadManager; extern FGameConfigFile *GameConfig; bool M_WriteFile (char const *name, void *source, int length); -int M_ReadFile (char const *name, uint8_t **buffer); -int M_ReadFileMalloc (char const *name, uint8_t **buffer); void M_FindResponseFile (void); // [RH] M_ScreenShot now accepts a filename parameter. diff --git a/src/posix/i_steam.cpp b/src/posix/i_steam.cpp index 9819bc09e..9542bdd4a 100644 --- a/src/posix/i_steam.cpp +++ b/src/posix/i_steam.cpp @@ -122,27 +122,28 @@ static TArray ParseSteamRegistry(const char* path) // Read registry data FScanner sc; - sc.OpenFile(path); - sc.SetCMode(true); - - // Find the SteamApps listing - if(PSR_FindAndEnterBlock(sc, "InstallConfigStore")) + if (sc.OpenFile(path)) { - if(PSR_FindAndEnterBlock(sc, "Software")) + sc.SetCMode(true); + + // Find the SteamApps listing + if (PSR_FindAndEnterBlock(sc, "InstallConfigStore")) { - if(PSR_FindAndEnterBlock(sc, "Valve")) + if (PSR_FindAndEnterBlock(sc, "Software")) { - if(PSR_FindAndEnterBlock(sc, "Steam")) + if (PSR_FindAndEnterBlock(sc, "Valve")) { - dirs = PSR_ReadBaseInstalls(sc); + if (PSR_FindAndEnterBlock(sc, "Steam")) + { + dirs = PSR_ReadBaseInstalls(sc); + } + PSR_FindEndBlock(sc); } PSR_FindEndBlock(sc); } PSR_FindEndBlock(sc); } - PSR_FindEndBlock(sc); } - return dirs; } diff --git a/src/sc_man.cpp b/src/sc_man.cpp index 2a515d91b..277604d68 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -244,18 +244,25 @@ void FScanner::Open (const char *name) // //========================================================================== -void FScanner::OpenFile (const char *name) +bool FScanner::OpenFile (const char *name) { - uint8_t *filebuf; - int filesize; - Close (); - filesize = M_ReadFile (name, &filebuf); + + FileReader fr(name); + if (!fr.Open(name)) return false; + auto filesize = fr.GetLength(); + auto filebuf = new uint8_t[filesize]; + if (fr.Read(filebuf, filesize) != filesize) + { + delete[] filebuf; + return false; + } ScriptBuffer = FString((const char *)filebuf, filesize); delete[] filebuf; ScriptName = name; // This is used for error messages so the full file name is preferable LumpNum = -1; PrepareScript (); + return true; } //========================================================================== diff --git a/src/sc_man.h b/src/sc_man.h index 44dd9370a..9962cbde0 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -19,7 +19,7 @@ public: FScanner &operator=(const FScanner &other); void Open(const char *lumpname); - void OpenFile(const char *filename); + bool OpenFile(const char *filename); void OpenMem(const char *name, const char *buffer, int size); void OpenString(const char *name, FString buffer); void OpenLumpNum(int lump); diff --git a/src/statistics.cpp b/src/statistics.cpp index e70642cf4..865ba0411 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -137,7 +137,7 @@ static void ParseStatistics(const char *fn, TArray &statlist) try { FScanner sc; - sc.OpenFile(fn); + if (!sc.OpenFile(fn)) return; while (sc.GetString()) { From 690e7d8a84a4cb68aabef3400d15cf97ed217e4d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 13:18:20 +0100 Subject: [PATCH 17/36] - got rid of M_WriteFile as well for the same reasons as M_ReadFile. --- src/g_game.cpp | 10 +++++++++- src/m_misc.cpp | 26 -------------------------- src/m_misc.h | 1 - 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index b2e27eed4..f56bdac8e 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2974,7 +2974,15 @@ bool G_CheckDemoStatus (void) formlen = demobuffer + 4; WriteLong (int(demo_p - demobuffer - 8), &formlen); - bool saved = M_WriteFile (demoname, demobuffer, int(demo_p - demobuffer)); + auto fw = FileWriter::Open(demoname); + bool saved = false; + if (fw != nullptr) + { + auto size = long(demo_p - demobuffer); + saved = fw->Write(demobuffer, size) == size; + delete fw; + if (!saved) remove(demoname); + } M_Free (demobuffer); demorecording = false; stoprecording = false; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 2b23ef6c2..21a0bfc74 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -88,32 +88,6 @@ EXTERN_CVAR(Bool, longsavemessages); static long ParseCommandLine (const char *args, int *argc, char **argv); -// -// M_WriteFile -// -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -bool M_WriteFile (char const *name, void *source, int length) -{ - int handle; - int count; - - handle = open ( name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); - - if (handle == -1) - return false; - - count = write (handle, source, length); - close (handle); - - if (count < length) - return false; - - return true; -} - //--------------------------------------------------------------------------- // diff --git a/src/m_misc.h b/src/m_misc.h index 2eee63b7d..47db77bb7 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -33,7 +33,6 @@ class FIWadManager; extern FGameConfigFile *GameConfig; -bool M_WriteFile (char const *name, void *source, int length); void M_FindResponseFile (void); // [RH] M_ScreenShot now accepts a filename parameter. From 2ba029ec8d21d55bfc0954aa89d7539da70bdbdd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 14:02:51 +0100 Subject: [PATCH 18/36] - fixed potential memory leak in M_VerifyPNG. If the 'takereader' parameter is true, the function must delete the reader if it fails before creating the PNGHandle. --- src/m_png.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/m_png.cpp b/src/m_png.cpp index 28f015e7b..0f4af87e4 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -383,18 +383,22 @@ PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) if (filer->Read(&data, 8) != 8) { + if (takereader) delete filer; return NULL; } if (data[0] != MAKE_ID(137,'P','N','G') || data[1] != MAKE_ID(13,10,26,10)) { // Does not have PNG signature + if (takereader) delete filer; return NULL; } if (filer->Read (&data, 8) != 8) { + if (takereader) delete filer; return NULL; } if (data[1] != MAKE_ID('I','H','D','R')) { // IHDR must be the first chunk + if (takereader) delete filer; return NULL; } From 4003e7ca118780a138779b8adda4a8708af9057c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 14:10:42 +0100 Subject: [PATCH 19/36] - use FileReader for savegame loading in the menu. - simplify the check for existing files here, since a function for doing just that already existed. --- src/m_png.cpp | 6 ------ src/m_png.h | 1 - src/menu/loadsavemenu.cpp | 23 +++++++++-------------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/m_png.cpp b/src/m_png.cpp index 0f4af87e4..08cac8d54 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -456,12 +456,6 @@ PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) return NULL; } -PNGHandle *M_VerifyPNG(FILE *file) -{ - FileReader *fr = new FileReader(file); - return M_VerifyPNG(fr, true); -} - //========================================================================== // // M_FreePNG diff --git a/src/m_png.h b/src/m_png.h index 70c45b710..4182440fb 100644 --- a/src/m_png.h +++ b/src/m_png.h @@ -90,7 +90,6 @@ struct PNGHandle // each chunk is not done. If it is valid, you get a PNGHandle to pass to // the following functions. PNGHandle *M_VerifyPNG (FileReader *file, bool takereader = false); -PNGHandle *M_VerifyPNG (FILE *file); // Finds a chunk in a PNG file. The file pointer will be positioned at the // beginning of the chunk data, and its length will be returned. A return diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index bec3082b1..c9fb7aeba 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -236,8 +236,8 @@ void FSavegameManager::ReadSaveStrings() } else // check for old formats. { - FILE *file = fopen(filepath, "rb"); - if (file != nullptr) + FileReader file; + if (file.Open(filepath)) { PNGHandle *png; char sig[16]; @@ -255,8 +255,7 @@ void FSavegameManager::ReadSaveStrings() title[OLDSAVESTRINGSIZE] = 0; - - if (nullptr != (png = M_VerifyPNG(file))) + if (nullptr != (png = M_VerifyPNG(&file, false))) { char *ver = M_GetPNGText(png, "ZDoom Save Version"); if (ver != nullptr) @@ -273,13 +272,13 @@ void FSavegameManager::ReadSaveStrings() } else { - fseek(file, 0, SEEK_SET); - if (fread(sig, 1, 16, file) == 16) + file.Seek(0, SEEK_SET); + if (file.Read(sig, 16) == 16) { if (strncmp(sig, "ZDOOMSAVE", 9) == 0) { - if (fread(title, 1, OLDSAVESTRINGSIZE, file) == OLDSAVESTRINGSIZE) + if (file.Read(title, OLDSAVESTRINGSIZE) == OLDSAVESTRINGSIZE) { addIt = true; } @@ -287,8 +286,8 @@ void FSavegameManager::ReadSaveStrings() else { memcpy(title, sig, 16); - if (fread(title + 16, 1, OLDSAVESTRINGSIZE - 16, file) == OLDSAVESTRINGSIZE - 16 && - fread(sig, 1, 16, file) == 16 && + if (file.Read(title + 16, OLDSAVESTRINGSIZE - 16) == OLDSAVESTRINGSIZE - 16 && + file.Read(sig, 16) == 16 && strncmp(sig, "ZDOOMSAVE", 9) == 0) { addIt = true; @@ -306,7 +305,6 @@ void FSavegameManager::ReadSaveStrings() node->SaveTitle = title; InsertSaveNode(node); } - fclose(file); } } } while (I_FindNext(filefirst, &c_file) == 0); @@ -418,17 +416,14 @@ void FSavegameManager::DoSave(int Selected, const char *savegamestring) // Find an unused filename and save as that FString filename; int i; - FILE *test; for (i = 0;; ++i) { filename = G_BuildSaveName("save", i); - test = fopen(filename, "rb"); - if (test == nullptr) + if (!FileExists(filename)) { break; } - fclose(test); } G_SaveGame(filename, savegamestring); } From 7d0759e2fa95d0fa2e96ca2c932df0c6d8e7d9e2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 14:24:28 +0100 Subject: [PATCH 20/36] - handled all other uses of fopen that could reasonably converted to FileReader or FileWriter. --- src/d_dehacked.cpp | 11 +++++------ src/files.cpp | 9 +++++++-- src/files.h | 1 + src/m_misc.cpp | 12 ++++-------- src/md5.cpp | 7 +++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 87f1d589e..f68fd1d63 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2488,17 +2488,16 @@ bool D_LoadDehLump(int lumpnum) bool D_LoadDehFile(const char *patchfile) { - FILE *deh; + FileReader fr; - deh = fopen(patchfile, "rb"); - if (deh != NULL) + if (!fr.Open(patchfile)) { - PatchSize = Q_filelength(deh); + PatchSize = fr.GetLength(); PatchName = copystring(patchfile); PatchFile = new char[PatchSize + 1]; - fread(PatchFile, 1, PatchSize, deh); - fclose(deh); + fr.Read(PatchFile, PatchSize); + fr.Close(); PatchFile[PatchSize] = '\0'; // terminate with a '\0' character return DoDehPatch(); } diff --git a/src/files.cpp b/src/files.cpp index b42aefece..8ad4d6329 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -87,13 +87,18 @@ FileReader::FileReader (FILE *file, long length) FilePos = StartPos = ftell (file); } -FileReader::~FileReader () +FileReader::~FileReader() +{ + Close(); +} + +void FileReader::Close() { if (CloseOnDestruct && File != NULL) { fclose (File); - File = NULL; } + File = NULL; } bool FileReader::Open (const char *filename) diff --git a/src/files.h b/src/files.h index d0c769ba1..808f24d94 100644 --- a/src/files.h +++ b/src/files.h @@ -101,6 +101,7 @@ public: FileReader (FILE *file); FileReader (FILE *file, long length); bool Open (const char *filename); + void Close(); virtual ~FileReader (); virtual long Tell () const; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 21a0bfc74..d07415248 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -122,22 +122,18 @@ void M_FindResponseFile (void) if (added_stuff < limit) { // READ THE RESPONSE FILE INTO MEMORY - handle = fopen (Args->GetArg(i) + 1,"rb"); - if (!handle) + FileReader fr; + if (!fr.Open(Args->GetArg(i) + 1)) { // [RH] Make this a warning, not an error. Printf ("No such response file (%s)!\n", Args->GetArg(i) + 1); } else { Printf ("Found response file %s!\n", Args->GetArg(i) + 1); - fseek (handle, 0, SEEK_END); - size = ftell (handle); - fseek (handle, 0, SEEK_SET); + size = fr.GetLength(); file = new char[size+1]; - fread (file, size, 1, handle); + fr.Read (file, size); file[size] = 0; - fclose (handle); - argsize = ParseCommandLine (file, &argc, NULL); } } diff --git a/src/md5.cpp b/src/md5.cpp index aa4b506da..d345e00d6 100644 --- a/src/md5.cpp +++ b/src/md5.cpp @@ -269,8 +269,8 @@ CCMD (md5sum) } for (int i = 1; i < argv.argc(); ++i) { - FILE *file = fopen(argv[i], "rb"); - if (file == NULL) + FileReader fr; + if (!fr.Open(argv[i])) { Printf("%s: %s\n", argv[i], strerror(errno)); } @@ -280,7 +280,7 @@ CCMD (md5sum) uint8_t readbuf[8192]; size_t len; - while ((len = fread(readbuf, 1, sizeof(readbuf), file)) > 0) + while ((len = fr.Read(readbuf, sizeof(readbuf))) > 0) { md5.Update(readbuf, (unsigned int)len); } @@ -290,7 +290,6 @@ CCMD (md5sum) Printf("%02x", readbuf[j]); } Printf(" *%s\n", argv[i]); - fclose (file); } } } From 1afc3b48a196888028d8e49c5957f50669d79a4c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 14:27:49 +0100 Subject: [PATCH 21/36] - removed Q_filelength which is no longer being used. --- src/cmdlib.cpp | 20 -------------------- src/cmdlib.h | 1 - 2 files changed, 21 deletions(-) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index 3c2e7e280..f2d4389d1 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -145,26 +145,6 @@ void ReplaceString (char **ptr, const char *str) */ -//========================================================================== -// -// Q_filelength -// -//========================================================================== - -int Q_filelength (FILE *f) -{ - int pos; - int end; - - pos = ftell (f); - fseek (f, 0, SEEK_END); - end = ftell (f); - fseek (f, pos, SEEK_SET); - - return end; -} - - //========================================================================== // // FileExists diff --git a/src/cmdlib.h b/src/cmdlib.h index e2119ed8a..f168cb910 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -18,7 +18,6 @@ // the dec offsetof macro doesnt work very well... #define myoffsetof(type,identifier) ((size_t)&((type *)alignof(type))->identifier - alignof(type)) -int Q_filelength (FILE *f); bool FileExists (const char *filename); bool DirExists(const char *filename); bool DirEntryExists (const char *pathname); From 8627a48b343d72f7941a554079c00f150c94a1ff Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 16:07:09 +0100 Subject: [PATCH 22/36] - consolidation of 'stat' calls. Since this is a non-standard function it's better kept to as few places as possible, so now DirEntryExists returns an additional flag to say what type an entry is and is being used nearly everywhere where stat was used, excluding a few low level parts in the POSIX code. --- src/c_bind.cpp | 2 +- src/cmdlib.cpp | 34 +++++++++++----------------- src/cmdlib.h | 2 +- src/d_main.cpp | 4 +--- src/m_misc.cpp | 1 - src/posix/cocoa/i_system.mm | 7 +++--- src/posix/i_steam.cpp | 3 ++- src/posix/sdl/i_system.cpp | 11 +++++---- src/resourcefiles/file_directory.cpp | 5 +--- src/w_wad.cpp | 6 ++--- 10 files changed, 31 insertions(+), 44 deletions(-) diff --git a/src/c_bind.cpp b/src/c_bind.cpp index b1a557514..5098b9a95 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -744,7 +744,7 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) dclick = false; // This used level.time which didn't work outside a level. - nowtime = I_msTime(); + nowtime = (unsigned)I_msTime(); if (doublebinds != NULL && int(DClickTime[ev->data1] - nowtime) > 0 && ev->type == EV_KeyDown) { // Key pressed for a double click diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index f2d4389d1..bccb4afcd 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -155,13 +155,9 @@ void ReplaceString (char **ptr, const char *str) bool FileExists (const char *filename) { - struct stat buff; - - // [RH] Empty filenames are never there - if (filename == NULL || *filename == 0) - return false; - - return stat(filename, &buff) == 0 && !(buff.st_mode & S_IFDIR); + bool isdir; + bool res = DirEntryExists(filename, &isdir); + return res && !isdir; } //========================================================================== @@ -174,13 +170,9 @@ bool FileExists (const char *filename) bool DirExists(const char *filename) { - struct stat buff; - - // [RH] Empty filenames are never there - if (filename == NULL || *filename == 0) - return false; - - return stat(filename, &buff) == 0 && (buff.st_mode & S_IFDIR); + bool isdir; + bool res = DirEntryExists(filename, &isdir); + return res && isdir; } //========================================================================== @@ -191,13 +183,16 @@ bool DirExists(const char *filename) // //========================================================================== -bool DirEntryExists(const char *pathname) +bool DirEntryExists(const char *pathname, bool *isdir) { + if (isdir) *isdir = false; if (pathname == NULL || *pathname == 0) return false; struct stat info; - return stat(pathname, &info) == 0; + bool res = stat(pathname, &info) == 0; + if (isdir) *isdir = !!(info.st_mode & S_IFDIR); + return res; } //========================================================================== @@ -550,7 +545,7 @@ void CreatePath(const char *fn) *p = '\0'; } struct stat info; - if (stat(copy, &info) == 0) + if (DirEntryExists(copy)) { if (info.st_mode & S_IFDIR) goto exists; @@ -1009,10 +1004,7 @@ void ScanDirectory(TArray &list, const char *dirpath) FFileList *fl = &list[list.Reserve(1)]; fl->Filename << dirpath << file->d_name; - struct stat fileStat; - stat(fl->Filename, &fileStat); - fl->isDirectory = S_ISDIR(fileStat.st_mode); - + fl->isDirectory = DirExists(fl->Filename); if(fl->isDirectory) { FString newdir = fl->Filename; diff --git a/src/cmdlib.h b/src/cmdlib.h index f168cb910..76a2798da 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -20,7 +20,7 @@ bool FileExists (const char *filename); bool DirExists(const char *filename); -bool DirEntryExists (const char *pathname); +bool DirEntryExists (const char *pathname, bool *isdir = nullptr); extern FString progdir; diff --git a/src/d_main.cpp b/src/d_main.cpp index 301be20f8..9d8055b0d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1946,13 +1946,11 @@ static FString CheckGameInfo(TArray & pwads) const char *filename = pwads[i]; // Does this exist? If so, is it a directory? - struct stat info; - if (stat(pwads[i], &info) != 0) + if (!DirEntryExists(pwads[i], &isdir)) { Printf(TEXTCOLOR_RED "Could not stat %s\n", filename); continue; } - isdir = (info.st_mode & S_IFDIR) != 0; if (!isdir) { diff --git a/src/m_misc.cpp b/src/m_misc.cpp index d07415248..c2fa021f6 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -112,7 +112,6 @@ void M_FindResponseFile (void) char **argv; char *file = NULL; int argc = 0; - FILE *handle; int size; long argsize = 0; int index; diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index bb1ea2e1b..3be9a067c 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -49,6 +49,7 @@ #include "st_console.h" #include "v_text.h" #include "x86.h" +#include "cmdlib.h" EXTERN_CVAR(String, language) @@ -336,11 +337,11 @@ int I_FindClose(void* const handle) int I_FindAttr(findstate_t* const fileinfo) { dirent* const ent = fileinfo->namelist[fileinfo->current]; - struct stat buf; + bool isdir; - if (stat(ent->d_name, &buf) == 0) + if (DirEntryExists(ent->d_name, &isdir)) { - return S_ISDIR(buf.st_mode) ? FA_DIREC : 0; + return isdir ? FA_DIREC : 0; } return 0; diff --git a/src/posix/i_steam.cpp b/src/posix/i_steam.cpp index 9542bdd4a..f233f4ce8 100644 --- a/src/posix/i_steam.cpp +++ b/src/posix/i_steam.cpp @@ -42,6 +42,7 @@ #include "d_main.h" #include "zstring.h" #include "sc_man.h" +#include "cmdlib.h" static void PSR_FindEndBlock(FScanner &sc) { @@ -224,7 +225,7 @@ TArray I_GetSteamPath() { struct stat st; FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath); - if(stat(candidate, &st) == 0 && S_ISDIR(st.st_mode)) + if(DirExists(candidate)) result.Push(candidate); } } diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index 7bf23af11..b71acb8f8 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -397,15 +397,16 @@ int I_FindClose (void *handle) return 0; } -int I_FindAttr (findstate_t *fileinfo) +int I_FindAttr(findstate_t* const fileinfo) { - dirent *ent = fileinfo->namelist[fileinfo->current]; - struct stat buf; + dirent* const ent = fileinfo->namelist[fileinfo->current]; + bool isdir; - if (stat(ent->d_name, &buf) == 0) + if (DirEntryExists(ent->d_name, &isdir)) { - return S_ISDIR(buf.st_mode) ? FA_DIREC : 0; + return isdir ? FA_DIREC : 0; } + return 0; } diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index 77e5d0141..02c70a21e 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -209,10 +209,7 @@ int FDirectory::AddDirectory(const char *dirpath) FString fullFileName = scanDirectories[i] + file->d_name; - struct stat fileStat; - stat(fullFileName.GetChars(), &fileStat); - - if(S_ISDIR(fileStat.st_mode)) + if(DirExists(fullFileName.GetChars())) { scanDirectories.Push(scanDirectories[i] + file->d_name + "/"); continue; diff --git a/src/w_wad.cpp b/src/w_wad.cpp index ae52725d2..1e1de76f0 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -233,14 +233,12 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) if (wadinfo == NULL) { // Does this exist? If so, is it a directory? - struct stat info; - if (stat(filename, &info) != 0) + if (!DirEntryExists(filename, &isdir)) { - Printf(TEXTCOLOR_RED "Could not stat %s\n", filename); + Printf(TEXTCOLOR_RED "%s: File or Directory not found\n", filename); PrintLastError(); return; } - isdir = (info.st_mode & S_IFDIR) != 0; if (!isdir) { From 4ca3acb0e3172a9dc224c2f25be0d3b0f23ccecd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 16:51:53 +0100 Subject: [PATCH 23/36] - made tmpfileplus a .cpp file so that it can access ZDoom's own utility code. --- src/CMakeLists.txt | 2 +- src/{tmpfileplus.c => tmpfileplus.cpp} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/{tmpfileplus.c => tmpfileplus.cpp} (99%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8c90fab42..60d906766 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1169,6 +1169,7 @@ set (PCH_SOURCES events.cpp GuillotineBinPack.cpp SkylineBinPack.cpp + tmpfileplus.cpp ) enable_precompiled_headers( g_pch.h PCH_SOURCES ) @@ -1183,7 +1184,6 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE ${PCH_SOURCES} x86.cpp strnatcmp.c - tmpfileplus.c zstring.cpp math/asin.c math/atan.c diff --git a/src/tmpfileplus.c b/src/tmpfileplus.cpp similarity index 99% rename from src/tmpfileplus.c rename to src/tmpfileplus.cpp index ddb71de09..5475d8f8f 100644 --- a/src/tmpfileplus.c +++ b/src/tmpfileplus.cpp @@ -217,7 +217,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart); DPRINTF1("lentempname=%d\n", lentempname); - tmpname = malloc(lentempname + 1); + tmpname = (char*)malloc(lentempname + 1); if (!tmpname) { errno = ENOMEM; From e78503b7706527802b3bfc69d69e2f0319084eef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 16:54:24 +0100 Subject: [PATCH 24/36] - removed some debug stuff from tmpfileplus. --- src/tmpfileplus.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp index 5475d8f8f..4bb9f4586 100644 --- a/src/tmpfileplus.cpp +++ b/src/tmpfileplus.cpp @@ -113,13 +113,6 @@ #endif -/* DEBUGGING STUFF */ -#if defined(_DEBUG) && defined(SHOW_DPRINTF) -#define DPRINTF1(s, a1) printf(s, a1) -#else -#define DPRINTF1(s, a1) -#endif - #ifdef _WIN32 #define FILE_SEPARATOR "\\" @@ -216,7 +209,6 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp } lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart); - DPRINTF1("lentempname=%d\n", lentempname); tmpname = (char*)malloc(lentempname + 1); if (!tmpname) { @@ -227,11 +219,9 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp for (i = 0; i < 10; i++) { sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart)); - DPRINTF1("[%s]\n", tmpname); fd = OPEN_(tmpname, oflag, pmode); if (fd != -1) break; } - DPRINTF1("strlen(tmpname)=%d\n", strlen(tmpname)); if (fd != -1) { /* Success, so return user a proper ANSI C file pointer */ fp = FDOPEN_(fd, "w+b"); @@ -293,7 +283,6 @@ FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep for (i = 0; i < ntempdirs; i++) { tmpdir = tempdirs[i]; - DPRINTF1("Trying tmpdir=[%s]\n", tmpdir); fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep); if (fp) break; } From f6f17fbfb48a62cc2f499c82cef8698c196879fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 17:05:39 +0100 Subject: [PATCH 25/36] - give tmpfileplus its own RNG. This should not interfere with the global one which can be explicitly seeded. It also seems a bit pointless to constantly re-seed the RNG for something this inconsequential. --- src/tmpfileplus.cpp | 75 +++++---------------------------------------- src/tmpfileplus.h | 20 ------------ 2 files changed, 7 insertions(+), 88 deletions(-) diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp index 4bb9f4586..0ebb23185 100644 --- a/src/tmpfileplus.cpp +++ b/src/tmpfileplus.cpp @@ -67,23 +67,6 @@ * */ -/* ADDED IN v2.0 */ - -/* -* NAME -* tmpfileplus_f - create a unique temporary file with filename stored in a fixed-length buffer -* -* SYNOPSIS -* FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); -* -* DESCRIPTION -* Same as tmpfileplus() except receives filename in a fixed-length buffer. No allocated memory to free. - -* ERRORS -* E2BIG Resulting filename is too big for the buffer `pathnamebuf`. - -*/ - #include "tmpfileplus.h" #include @@ -112,47 +95,32 @@ #define FDOPEN_ fdopen #endif +#include "m_random.h" +#include "cmdlib.h" -#ifdef _WIN32 -#define FILE_SEPARATOR "\\" -#else #define FILE_SEPARATOR "/" -#endif #define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #define NRANDCHARS (sizeof(RANDCHARS) - 1) +static FRandom pr_tmpfile; + /** Replace each byte in string s with a random character from TEMPCHARS */ static char *set_randpart(char *s) { size_t i; unsigned int r; - static unsigned int seed; /* NB static */ - if (seed == 0) - { /* First time set our seed using current time and clock */ - seed = ((unsigned)time(NULL)<<8) ^ (unsigned)clock(); - } - srand(seed++); + for (i = 0; i < strlen(s); i++) { - r = rand() % NRANDCHARS; + r = pr_tmpfile() % NRANDCHARS; s[i] = (RANDCHARS)[r]; } return s; } -/** Return 1 if path is a valid directory otherwise 0 */ -static int is_valid_dir(const char *path) -{ - struct stat st; - if ((stat(path, &st) == 0) && (st.st_mode & S_IFDIR)) - return 1; - - return 0; -} - /** Call getenv and save a copy in buf */ static char *getenv_save(const char *varname, char *buf, size_t bufsize) { @@ -203,7 +171,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp pmode = S_IRUSR|S_IWUSR; #endif - if (!tmpdir || !is_valid_dir(tmpdir)) { + if (!tmpdir || !DirExists(tmpdir)) { errno = ENOENT; return NULL; } @@ -295,32 +263,3 @@ FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep return fp; } -/* Same as tmpfileplus() but with fixed length buffer for output filename and no memory allocation */ -FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep) -{ - char *tmpbuf = NULL; - FILE *fp; - - /* If no buffer provided, do the normal way */ - if (!pathnamebuf || (int)pathsize <= 0) { - return tmpfileplus(dir, prefix, NULL, keep); - } - /* Call with a temporary buffer */ - fp = tmpfileplus(dir, prefix, &tmpbuf, keep); - if (fp && strlen(tmpbuf) > pathsize - 1) { - /* Succeeded but not enough room in output buffer, so clean up and return an error */ - pathnamebuf[0] = 0; - fclose(fp); - if (keep) remove(tmpbuf); - free(tmpbuf); - errno = E2BIG; - return NULL; - } - /* Copy name into buffer */ - strcpy(pathnamebuf, tmpbuf); - free(tmpbuf); - - return fp; -} - - diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h index e32ff5042..07b5ca0d5 100644 --- a/src/tmpfileplus.h +++ b/src/tmpfileplus.h @@ -23,10 +23,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - /** Create a unique temporary file. @param dir (optional) directory to create file. If NULL use default TMP directory. @param prefix (optional) prefix for file name. If NULL use "tmp.". @@ -40,22 +36,6 @@ extern "C" { FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep); -/** Create a unique temporary file with filename stored in a fixed-length buffer. -@param dir (optional) directory to create file. If NULL use default directory. -@param prefix (optional) prefix for file name. If NULL use "tmp.". -@param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL. -@param pathsize Size of buffer to receive filename and its terminating null character. -@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing. - Otherwise file is automatically deleted when closed. -@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. -@exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`. -*/ -FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep); - #define TMPFILE_KEEP 1 -#ifdef __cplusplus -} -#endif - #endif /* end TMPFILEPLUS_H_ */ From 7cbcbe66c06f9b0c9537988311b5119f802c8a28 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 17:33:43 +0100 Subject: [PATCH 26/36] - sanitization of temporary file stuff for Timidity++. * do not use the global temp directory. Instead create one in the AppData folder. * removed lots of unneeded code from tmpfileplus. * use C++ strings in there. --- src/m_misc.h | 1 + src/posix/osx/i_specialpaths.mm | 30 +++++++ src/posix/unix/i_specialpaths.cpp | 20 +++++ .../music_timiditypp_mididevice.cpp | 18 ++-- src/tmpfileplus.cpp | 84 +++---------------- src/tmpfileplus.h | 4 +- src/win32/i_specialpaths.cpp | 31 +++++++ 7 files changed, 105 insertions(+), 83 deletions(-) diff --git a/src/m_misc.h b/src/m_misc.h index 47db77bb7..8f375b930 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -53,6 +53,7 @@ FString M_ZLibError(int zerrnum); #ifdef __unix__ FString GetUserFile (const char *path); // Prepends ~/.zdoom to path #endif +FString M_GetAppDataPath(bool create); FString M_GetCachePath(bool create); FString M_GetAutoexecPath(); FString M_GetCajunPath(const char *filename); diff --git a/src/posix/osx/i_specialpaths.mm b/src/posix/osx/i_specialpaths.mm index 843fb82d6..fbb32cec6 100644 --- a/src/posix/osx/i_specialpaths.mm +++ b/src/posix/osx/i_specialpaths.mm @@ -39,6 +39,35 @@ #include "m_misc.h" #include "version.h" // for GAMENAME +//=========================================================================== +// +// M_GetAppDataPath macOS +// +// Returns the path for the AppData folder. +// +//=========================================================================== + +FString M_GetAppDataPath(bool create) +{ + FString path; + + char pathstr[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) + { + path = pathstr; + } + else + { + path = progdir; + } + path += "/" GAMENAMELOWERCASE; + if (create) CreatePath(path); + return path; +} + //=========================================================================== // // M_GetCachePath macOS @@ -64,6 +93,7 @@ FString M_GetCachePath(bool create) path = progdir; } path += "/zdoom/cache"; + if (create) CreatePath(path); return path; } diff --git a/src/posix/unix/i_specialpaths.cpp b/src/posix/unix/i_specialpaths.cpp index 5dedba057..581fda5d5 100644 --- a/src/posix/unix/i_specialpaths.cpp +++ b/src/posix/unix/i_specialpaths.cpp @@ -98,6 +98,26 @@ FString GetUserFile (const char *file) return path; } +//=========================================================================== +// +// M_GetAppDataPath Unix +// +// Returns the path for the AppData folder. +// +//=========================================================================== + +FString M_GetAppDataPath(bool create) +{ + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + FString path = NicePath("~/.config/" GAMENAMELOWERCASE); + if (create) + { + CreatePath(path); + } + return path; +} + //=========================================================================== // // M_GetCachePath Unix diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index d4c03534d..42733ce38 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -43,6 +43,7 @@ #include "templates.h" #include "version.h" #include "tmpfileplus.h" +#include "m_misc.h" #ifndef _WIN32 #include @@ -82,7 +83,7 @@ public: protected: bool LaunchTimidity(); - char* DiskName; + FString DiskName; #ifdef _WIN32 HANDLE ReadWavePipe; HANDLE WriteWavePipe; @@ -165,8 +166,7 @@ CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //========================================================================== -TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) - : DiskName(nullptr), +TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) : #ifdef _WIN32 ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE), ChildProcess(INVALID_HANDLE_VALUE), @@ -204,10 +204,9 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) TimidityPPMIDIDevice::~TimidityPPMIDIDevice () { - if (nullptr != DiskName) + if (DiskName.IsNotEmpty()) { remove(DiskName); - free(DiskName); } #if _WIN32 @@ -257,7 +256,10 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) // Write MIDI song to temporary file song->CreateSMF(midi, looping ? 0 : 1); - f = tmpfileplus(nullptr, "zmid", &DiskName, 1); + FString path = M_GetAppDataPath(false); + path += "/tmp"; + CreatePath(path); + f = tmpfileplus(path, "zmid", &DiskName, 1); if (f == NULL) { Printf(PRINT_BOLD, "Could not open temp music file\n"); @@ -454,7 +456,7 @@ bool TimidityPPMIDIDevice::ValidateTimidity() bool TimidityPPMIDIDevice::LaunchTimidity () { - if (ExeName.IsEmpty() || nullptr == DiskName) + if (ExeName.IsEmpty() || DiskName.IsEmpty()) { return false; } @@ -565,7 +567,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity () arglist.push_back("-"); arglist.push_back(outmodearg.c_str()); arglist.push_back(ifacearg.c_str()); - arglist.push_back(DiskName); + arglist.push_back(DiskName.GetChars()); DPrintf(DMSG_NOTIFY, "Timidity EXE: \x1cG%s\n", exename); int i = 1; diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp index 0ebb23185..bfe021dbb 100644 --- a/src/tmpfileplus.cpp +++ b/src/tmpfileplus.cpp @@ -97,10 +97,9 @@ #include "m_random.h" #include "cmdlib.h" +#include "zstring.h" -#define FILE_SEPARATOR "/" - #define RANDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #define NRANDCHARS (sizeof(RANDCHARS) - 1) @@ -121,27 +120,13 @@ static char *set_randpart(char *s) return s; } -/** Call getenv and save a copy in buf */ -static char *getenv_save(const char *varname, char *buf, size_t bufsize) -{ - char *ptr = getenv(varname); - buf[0] = '\0'; - if (ptr) - { - strncpy(buf, ptr, bufsize); - buf[bufsize-1] = '\0'; - return buf; - } - return NULL; -} - /** * Try and create a randomly-named file in directory `tmpdir`. * If successful, allocate memory and set `tmpname_ptr` to full filepath, and return file pointer; * otherwise return NULL. * If `keep` is zero then create the file as temporary and it should not exist once closed. */ -static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmpname_ptr, int keep) +static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *tmpname_ptr, int keep) /* PRE: * pfx is not NULL and points to a valid null-terminated string * tmpname_ptr is not NULL. @@ -150,9 +135,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp FILE *fp; int fd; char randpart[] = "1234567890"; - size_t lentempname; int i; - char *tmpname = NULL; int oflag, pmode; /* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed. @@ -176,18 +159,13 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp return NULL; } - lentempname = strlen(tmpdir) + strlen(FILE_SEPARATOR) + strlen(pfx) + strlen(randpart); - tmpname = (char*)malloc(lentempname + 1); - if (!tmpname) - { - errno = ENOMEM; - return NULL; - } + FString tempname; + /* If we don't manage to create a file after 10 goes, there is something wrong... */ for (i = 0; i < 10; i++) { - sprintf(tmpname, "%s%s%s%s", tmpdir, FILE_SEPARATOR, pfx, set_randpart(randpart)); - fd = OPEN_(tmpname, oflag, pmode); + tempname.Format("%s/%s%s", tmpdir, pfx, set_randpart(randpart)); + fd = OPEN_(tempname, oflag, pmode); if (fd != -1) break; } if (fd != -1) @@ -205,13 +183,8 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp { /* We failed */ fp = NULL; } - if (!fp) - { - free(tmpname); - tmpname = NULL; - } - *tmpname_ptr = tmpname; + if (tmpname_ptr) *tmpname_ptr = tempname; return fp; } @@ -219,47 +192,10 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp /* EXPORTED FUNCTIONS */ /**********************/ -FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep) +FILE *tmpfileplus(const char *dir, const char *prefix, FString *pathname, int keep) { - FILE *fp = NULL; - char *tmpname = NULL; - char *tmpdir = NULL; - const char *pfx = (prefix ? prefix : "tmp."); - char *tempdirs[12] = { 0 }; - char env1[FILENAME_MAX+1] = { 0 }; - char env2[FILENAME_MAX+1] = { 0 }; - char env3[FILENAME_MAX+1] = { 0 }; - int ntempdirs = 0; - int i; - - /* Set up a list of temp directories we will try in order */ - i = 0; - tempdirs[i++] = (char *)dir; -#ifdef _WIN32 - tempdirs[i++] = getenv_save("TMP", env1, sizeof(env1)); - tempdirs[i++] = getenv_save("TEMP", env2, sizeof(env2)); -#else - tempdirs[i++] = getenv_save("TMPDIR", env3, sizeof(env3)); - tempdirs[i++] = P_tmpdir; -#endif - tempdirs[i++] = "."; - ntempdirs = i; - - errno = 0; - - /* Work through list we set up before, and break once we are successful */ - for (i = 0; i < ntempdirs; i++) - { - tmpdir = tempdirs[i]; - fp = mktempfile_internal(tmpdir, pfx, &tmpname, keep); - if (fp) break; - } - /* If we succeeded and the user passed a pointer, set it to the alloc'd pathname: the user must free this */ - if (fp && pathname) - *pathname = tmpname; - else /* Otherwise, free the alloc'd memory */ - free(tmpname); - + FILE *fp = mktempfile_internal(dir, (prefix ? prefix : "tmp."), pathname, keep); + if (!fp && pathname) *pathname = ""; return fp; } diff --git a/src/tmpfileplus.h b/src/tmpfileplus.h index 07b5ca0d5..06219edd6 100644 --- a/src/tmpfileplus.h +++ b/src/tmpfileplus.h @@ -23,6 +23,8 @@ #include +class FString; + /** Create a unique temporary file. @param dir (optional) directory to create file. If NULL use default TMP directory. @param prefix (optional) prefix for file name. If NULL use "tmp.". @@ -33,7 +35,7 @@ @return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error. @exception ENOMEM Not enough memory to allocate filename. */ -FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep); +FILE *tmpfileplus(const char *dir, const char *prefix, FString *pathname, int keep); #define TMPFILE_KEEP 1 diff --git a/src/win32/i_specialpaths.cpp b/src/win32/i_specialpaths.cpp index 58c87a8ca..4a790798f 100644 --- a/src/win32/i_specialpaths.cpp +++ b/src/win32/i_specialpaths.cpp @@ -153,6 +153,33 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create } } +//=========================================================================== +// +// M_GetAppDataPath Windows +// +// Returns the path for the AppData folder. +// +//=========================================================================== + +FString M_GetAppDataPath(bool create) +{ + FString path; + + if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) + { // Failed (e.g. On Win9x): use program directory + path = progdir; + } + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + path += "/" GAMENAMELOWERCASE; + path.Substitute("//", "/"); // needed because progdir ends with a slash. + if (create) + { + CreatePath(path); + } + return path; +} + //=========================================================================== // // M_GetCachePath Windows @@ -173,6 +200,10 @@ FString M_GetCachePath(bool create) // share the node cache. path += "/zdoom/cache"; path.Substitute("//", "/"); // needed because progdir ends with a slash. + if (create) + { + CreatePath(path); + } return path; } From cc54db6e6df481e94d669f58fcbf58810a02504a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Dec 2017 21:21:57 +0100 Subject: [PATCH 27/36] - let the 3 relevant text functions handle UTF-8 strings These functions are: DCanvas::DrawTextCommon, V_BreakLines and FFont::StringWidth. This will allow strings from UTF-8 encoded assets to display properly, but also handle the OpenAL device name on international systems, as this will be returned as an UTF-8 string. Due to backwards compatibility needs the decoding function is rather lax to allow both UTF-8 and ISO 8859-1 to pass through correctly - and this also implies that it will allow mixed encodings which may happen if strings from different sources get concatenated. --- src/v_font.cpp | 10 +++---- src/v_text.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/v_text.h | 2 ++ 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/v_font.cpp b/src/v_font.cpp index b475fb558..9716f2744 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -890,9 +890,10 @@ int FFont::StringWidth(const uint8_t *string) const while (*string) { - if (*string == TEXTCOLOR_ESCAPE) + auto chr = GetCharFromString(string); + if (chr == TEXTCOLOR_ESCAPE) { - ++string; + // We do not need to check for UTF-8 in here. if (*string == '[') { while (*string != '\0' && *string != ']') @@ -906,16 +907,15 @@ int FFont::StringWidth(const uint8_t *string) const } continue; } - else if (*string == '\n') + else if (chr == '\n') { if (w > maxw) maxw = w; w = 0; - ++string; } else { - w += GetCharWidth(*string++) + GlobalKerning; + w += GetCharWidth(chr) + GlobalKerning; } } diff --git a/src/v_text.cpp b/src/v_text.cpp index cf8ce8cc7..f4829ec18 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -51,6 +51,78 @@ int ListGetInt(VMVa_List &tags); +//========================================================================== +// +// reads one character from the string. +// This can handle both ISO 8859-1 and UTF-8, as well as mixed strings +// between both encodings, which may happen if inconsistent encoding is +// used between different files in a mod. +// +//========================================================================== + +int GetCharFromString(const uint8_t *&string) +{ + int z, y, x; + + z = *string++; + + if (z < 192) + { + return z; + } + else if (z <= 223) + { + y = *string++; + if (y < 128 || y >= 192) + { + // not an UTF-8 sequence so return the first byte unchanged + string--; + } + else + { + z = (z - 192) * 64 + (y - 128); + } + } + else if (z >= 224 && z <= 239) + { + y = *string++; + if (y < 128 || y >= 192) + { + // not an UTF-8 sequence so return the first byte unchanged + string--; + } + else + { + x = *string++; + if (x < 128 || x >= 192) + { + // not an UTF-8 sequence so return the first byte unchanged + string -= 2; + } + else + { + z = (z - 224) * 4096 + (y - 128) * 64 + (x - 128); + } + } + } + else if (z >= 240) + { + y = *string++; + if (y < 128 || y >= 192) + { + // not an UTF-8 sequence so return the first byte unchanged + string--; + } + else + { + // we do not support 4-Byte UTF-8 here + string += 2; + return '?'; + } + } + return z; +} + //========================================================================== // // DrawChar @@ -170,7 +242,7 @@ void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, c while ((const char *)ch - string < parms.maxstrlen) { - c = *ch++; + c = GetCharFromString(ch); if (!c) break; @@ -288,7 +360,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo w = 0; - while ( (c = *string++) ) + while ( (c = GetCharFromString(string)) ) { if (c == TEXTCOLOR_ESCAPE) { diff --git a/src/v_text.h b/src/v_text.h index b76024fa5..cd7d3e6ad 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -86,4 +86,6 @@ inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, b inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr) { return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor, count); } +int GetCharFromString(const uint8_t *&string); + #endif //__V_TEXT_H__ From 52be9895b74a8de22de128b04f213d18b57fe2dc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 3 Dec 2017 00:23:28 +0100 Subject: [PATCH 28/36] - Disable softpoly models --- src/polyrenderer/scene/poly_playersprite.cpp | 2 +- src/polyrenderer/scene/poly_sprite.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 017396ffb..3c17941ba 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -43,7 +43,7 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread) // // We also can't move it because the model render code relies on it - renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); + //renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 9ea184c35..f3ce12a5e 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -74,7 +74,7 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right) void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) { - int spritenum = thing->sprite; + /*int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); if (modelframe) @@ -83,7 +83,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); PolyRenderModel(thread, worldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); return; - } + }*/ DVector2 line[2]; if (!GetLine(thing, line[0], line[1])) From 8129afdd1f37d086daaf6b9a3446475e4f6671dd Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 3 Dec 2017 10:11:54 +0200 Subject: [PATCH 29/36] Fixed compilation of non-Windows targets These are quick hacks to be improved later --- src/resourcefiles/file_directory.cpp | 5 ++++- src/tmpfileplus.cpp | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index 02c70a21e..77e5d0141 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -209,7 +209,10 @@ int FDirectory::AddDirectory(const char *dirpath) FString fullFileName = scanDirectories[i] + file->d_name; - if(DirExists(fullFileName.GetChars())) + struct stat fileStat; + stat(fullFileName.GetChars(), &fileStat); + + if(S_ISDIR(fileStat.st_mode)) { scanDirectories.Push(scanDirectories[i] + file->d_name + "/"); continue; diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp index bfe021dbb..2085e8be3 100644 --- a/src/tmpfileplus.cpp +++ b/src/tmpfileplus.cpp @@ -172,12 +172,6 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *t { /* Success, so return user a proper ANSI C file pointer */ fp = FDOPEN_(fd, "w+b"); errno = 0; - -#ifndef _WIN32 - /* [Unix only] And make sure the file will be deleted once closed */ - if (!keep) remove(tmpname); -#endif - } else { /* We failed */ From f25c7ef2d519f98f7acd64cfa01c03d3b7781384 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 3 Dec 2017 13:17:28 +0200 Subject: [PATCH 30/36] =?UTF-8?q?Unified=20implementation=20of=20=E2=80=99?= =?UTF-8?q?directory=20as=20resource=20file'=20for=20POSIX=20targets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/resourcefiles/file_directory.cpp | 75 ++++++++-------------------- 1 file changed, 20 insertions(+), 55 deletions(-) diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index 77e5d0141..2e5630169 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -35,27 +35,13 @@ #include -#include #ifdef _WIN32 #include -#define stat _stat #else -#include -#ifndef __sun #include #endif -#endif -#include -#include -#include -#include -#include -#include -#include "doomtype.h" -#include "tarray.h" #include "resourcefile.h" -#include "zstring.h" #include "cmdlib.h" #include "doomerrors.h" @@ -185,46 +171,6 @@ int FDirectory::AddDirectory(const char *dirpath) return count; } -#elif defined(__sun) || defined(__APPLE__) - -int FDirectory::AddDirectory(const char *dirpath) -{ - int count = 0; - TArray scanDirectories; - scanDirectories.Push(dirpath); - for(unsigned int i = 0;i < scanDirectories.Size();i++) - { - DIR* directory = opendir(scanDirectories[i].GetChars()); - if (directory == NULL) - { - Printf("Could not read directory: %s\n", strerror(errno)); - return 0; - } - - struct dirent *file; - while((file = readdir(directory)) != NULL) - { - if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it. - continue; - - FString fullFileName = scanDirectories[i] + file->d_name; - - struct stat fileStat; - stat(fullFileName.GetChars(), &fileStat); - - if(S_ISDIR(fileStat.st_mode)) - { - scanDirectories.Push(scanDirectories[i] + file->d_name + "/"); - continue; - } - AddEntry(scanDirectories[i] + file->d_name, fileStat.st_size); - count++; - } - closedir(directory); - } - return count; -} - #else //========================================================================== @@ -249,6 +195,10 @@ int FDirectory::AddDirectory(const char *dirpath) Printf("Failed to start directory traversal: %s\n", strerror(errno)); return 0; } + + const size_t namepos = strlen(Filename); + FString pathfix; + while ((ent = fts_read(fts)) != NULL) { if (ent->fts_info == FTS_D && ent->fts_name[0] == '.') @@ -266,7 +216,22 @@ int FDirectory::AddDirectory(const char *dirpath) // We're only interested in remembering files. continue; } - AddEntry(ent->fts_path, ent->fts_statp->st_size); + + // Some implementations add an extra separator between + // root of the hierarchy and entity's path. + // It needs to be removed in order to resolve + // lumps' relative paths properly. + const char* path = ent->fts_path; + + if ('/' == path[namepos]) + { + pathfix = FString(path, namepos); + pathfix.AppendCStrPart(&path[namepos + 1], ent->fts_pathlen - namepos - 1); + + path = pathfix.GetChars(); + } + + AddEntry(path, ent->fts_statp->st_size); count++; } fts_close(fts); From 31d1018b9a30dfbc392f7da931ee6efb716d321e Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 3 Dec 2017 13:18:47 +0200 Subject: [PATCH 31/36] Fixed compilation warnings reported by GCC/Clang b_game.cpp:537:27: warning: more '%' conversions than data arguments [-Wformat] g_game.cpp:2982:40: warning: comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'long' [-Wsign-compare] --- src/b_game.cpp | 4 ++-- src/g_game.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/b_game.cpp b/src/b_game.cpp index 4300e0ada..661d09c6e 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -534,7 +534,7 @@ bool FCajunMaster::LoadBots () } if (!sc.OpenFile(tmp)) { - Printf("Unable to open %s. So no bots\n"); + Printf("Unable to open %s. So no bots\n", tmp.GetChars()); return false; } @@ -665,4 +665,4 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, RemoveAllBots) PARAM_BOOL(fromlist); bglobal.RemoveAllBots(fromlist); return 0; -} \ No newline at end of file +} diff --git a/src/g_game.cpp b/src/g_game.cpp index f56bdac8e..0adfa2fc9 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2978,7 +2978,7 @@ bool G_CheckDemoStatus (void) bool saved = false; if (fw != nullptr) { - auto size = long(demo_p - demobuffer); + const size_t size = demo_p - demobuffer; saved = fw->Write(demobuffer, size) == size; delete fw; if (!saved) remove(demoname); From 5f50d60eff3ef0d7a361ce7de3b6a576ce209c40 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 3 Dec 2017 13:23:43 +0200 Subject: [PATCH 32/36] Restored handling of tmpfileplus() keep argument for POSIX targets --- src/tmpfileplus.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tmpfileplus.cpp b/src/tmpfileplus.cpp index 2085e8be3..2c14e1563 100644 --- a/src/tmpfileplus.cpp +++ b/src/tmpfileplus.cpp @@ -139,8 +139,8 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *t int oflag, pmode; /* In Windows, we use the _O_TEMPORARY flag with `open` to ensure the file is deleted when closed. - * In Unix, we use the unlink function after opening the file. (This does not work in Windows, - * which does not allow an open file to be unlinked.) + * In Unix, we use the remove function after opening the file. (This does not work in Windows, + * which does not allow an open file to be deleted.) */ #ifdef _WIN32 /* MSVC flags */ @@ -172,6 +172,12 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, FString *t { /* Success, so return user a proper ANSI C file pointer */ fp = FDOPEN_(fd, "w+b"); errno = 0; + +#ifndef _WIN32 + /* [Unix only] And make sure the file will be deleted once closed */ + if (!keep) remove(tempname); +#endif + } else { /* We failed */ From 31b0fdc9fe1179bfa799e5c43d379933624661ae Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 3 Dec 2017 14:50:32 +0200 Subject: [PATCH 33/36] Fixed directory creation for POSIX targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warning was reported by GCC 7 only: cmdlib.cpp:550:13: warning: ‘info.stat::st_mode’ may be used uninitialized in this function [-Wmaybe-uninitialized] --- src/cmdlib.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index bccb4afcd..e58b3569f 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -544,18 +544,13 @@ void CreatePath(const char *fn) { *p = '\0'; } - struct stat info; - if (DirEntryExists(copy)) + if (!DirEntryExists(copy) && mkdir(copy, 0755) == -1) { - if (info.st_mode & S_IFDIR) - goto exists; - } - if (mkdir(copy, 0755) == -1) - { // failed + // failed free(copy); return; } -exists: if (p != NULL) + if (p != NULL) { *p = '/'; } From 0fa74220c9fe56d106b983e5248ec7b254495b3d Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 3 Dec 2017 12:39:24 -0500 Subject: [PATCH 34/36] - fixed: doublize sky float, in order to make it more smooth --- src/gl/scene/gl_scene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 329ac6484..af03af86e 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -800,8 +800,8 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees; // Scroll the sky - GLRenderer->mSky1Pos = (double)fmod(screen->FrameTime * level.skyspeed1, 1024.f) * 90./256.; - GLRenderer->mSky2Pos = (double)fmod(screen->FrameTime * level.skyspeed2, 1024.f) * 90./256.; + GLRenderer->mSky1Pos = (double)fmod((double)screen->FrameTime * (double)level.skyspeed1, 1024.f) * 90./256.; + GLRenderer->mSky2Pos = (double)fmod((double)screen->FrameTime * (double)level.skyspeed2, 1024.f) * 90./256.; From cea89ba3ae0ec39a7d6ffbc65aa770567bd5699a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Dec 2017 20:02:55 +0100 Subject: [PATCH 35/36] - fix backslashes in MD3 skin names. --- src/r_data/models/models_md3.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_data/models/models_md3.cpp b/src/r_data/models/models_md3.cpp index e504b252a..8a649f713 100644 --- a/src/r_data/models/models_md3.cpp +++ b/src/r_data/models/models_md3.cpp @@ -166,6 +166,8 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le for (int i = 0; i < s->numSkins; i++) { // [BB] According to the MD3 spec, Name is supposed to include the full path. + // ... and since some tools seem to output backslashes, these need to be replaced with forward slashes to work. + FixPathSeperator(shader[i].Name); s->skins[i] = LoadSkin("", shader[i].Name); // [BB] Fall back and check if Name is relative. if (!s->skins[i].isValid()) From a945418ba6c49704a4e9fbcbdda063e653d4c653 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Dec 2017 21:03:44 +0100 Subject: [PATCH 36/36] - added M_GetDocumentsPath function. --- src/m_misc.h | 1 + src/posix/osx/i_specialpaths.mm | 21 +++++++++++++++++ src/posix/unix/i_specialpaths.cpp | 13 +++++++++++ src/win32/i_specialpaths.cpp | 38 +++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/src/m_misc.h b/src/m_misc.h index 8f375b930..f3773659d 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -60,5 +60,6 @@ FString M_GetCajunPath(const char *filename); FString M_GetConfigPath(bool for_reading); FString M_GetScreenshotsPath(); FString M_GetSavegamesPath(); +FString M_GetDocumentsPath(); #endif diff --git a/src/posix/osx/i_specialpaths.mm b/src/posix/osx/i_specialpaths.mm index fbb32cec6..540aaf4b0 100644 --- a/src/posix/osx/i_specialpaths.mm +++ b/src/posix/osx/i_specialpaths.mm @@ -215,3 +215,24 @@ FString M_GetSavegamesPath() return path; } +//=========================================================================== +// +// M_GetDocumentsPath Unix +// +// Returns the path to the default documents directory. +// +//=========================================================================== + +FString M_GetDocumentsPath() +{ + FString path; + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/"; + } + return path; +} diff --git a/src/posix/unix/i_specialpaths.cpp b/src/posix/unix/i_specialpaths.cpp index 581fda5d5..01320548d 100644 --- a/src/posix/unix/i_specialpaths.cpp +++ b/src/posix/unix/i_specialpaths.cpp @@ -218,3 +218,16 @@ FString M_GetSavegamesPath() { return NicePath("~/" GAME_DIR); } + +//=========================================================================== +// +// M_GetDocumentsPath Unix +// +// Returns the path to the default documents directory. +// +//=========================================================================== + +FString M_GetDocumentsPath() +{ + return NicePath("~/" GAME_DIR); +} \ No newline at end of file diff --git a/src/win32/i_specialpaths.cpp b/src/win32/i_specialpaths.cpp index 4a790798f..375f301dd 100644 --- a/src/win32/i_specialpaths.cpp +++ b/src/win32/i_specialpaths.cpp @@ -380,3 +380,41 @@ FString M_GetSavegamesPath() } return path; } + +//=========================================================================== +// +// M_GetDocumentsPath Windows +// +// Returns the path to the default documents directory. +// +//=========================================================================== + +FString M_GetDocumentsPath() +{ + FString path; + + // A portable INI means that this storage location should also be portable. + path.Format("%s" GAMENAME "_portable.ini", progdir.GetChars()); + if (FileExists(path)) + { + return progdir; + } + + if (!UseKnownFolders()) + { + return progdir; + } + // Try defacto My Documents/My Games folder + else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) + { + // I assume since this isn't a standard folder, it doesn't have + // a localized name either. + path << "/My Games/" GAMENAME; + CreatePath(path); + } + else + { + path = progdir; + } + return path; +}