Also log error description

This commit is contained in:
UnknownShadow200 2019-03-08 09:26:34 +11:00
parent f4a2485144
commit b7c43bbe8a
13 changed files with 150 additions and 62 deletions

View File

@ -206,7 +206,7 @@ static struct SoundOutput monoOutputs[AUDIO_MAX_HANDLES] = { SOUND_INV, SOUND_
static struct SoundOutput stereoOutputs[AUDIO_MAX_HANDLES] = { SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV, SOUND_INV };
CC_NOINLINE static void Sounds_Fail(ReturnCode res) {
Logger_Warn(res, "playing sounds");
Logger_OldWarn(res, "playing sounds");
Chat_AddRaw("&cDisabling sounds");
Audio_SetSounds(0);
}
@ -470,7 +470,8 @@ static void Music_RunLoop(void) {
res = Music_PlayOgg(&stream);
if (res) {
Logger_Warn2(res, "playing", &path); stream.Close(&stream); break;
Logger_OldWarn2(res, "playing", &path);
stream.Close(&stream); break;
}
res = stream.Close(&stream);

View File

@ -113,7 +113,8 @@ static void Chat_OpenLog(struct DateTime* now) {
res = File_Append(&file, path);
if (res && res != ReturnCode_FileShareViolation) {
Chat_DisableLogging();
Logger_Warn2(res, "appending to", path); return;
Logger_Warn2(res, "appending to", path);
return;
}
if (res == ReturnCode_FileShareViolation) continue;

View File

@ -70,7 +70,7 @@ void Map_LoadFrom(const String* path) {
}
res = stream.Close(&stream);
if (res) { Logger_Warn2(res, "closing", path); }
if (res) { Logger_Warn2(res, "closing", path, Platform_DescribeError); }
World_SetNewMap(World.Blocks, World.Width, World.Height, World.Length);
Event_RaiseVoid(&WorldEvents.MapLoaded);

View File

@ -363,7 +363,7 @@ static void Game_LoadOptions(void) {
}*/
}
static void Game_LoadPlugin(const String* filename, void* obj) {
static void Game_LoadPlugin(const String* path, void* obj) {
#if defined CC_BUILD_WIN
const static String ext = String_FromConst(".dll");
#elif defined CC_BUILD_OSX
@ -379,21 +379,21 @@ static void Game_LoadPlugin(const String* filename, void* obj) {
ReturnCode res;
/* ignore accepted.txt, deskop.ini, .pdb files, etc */
if (!String_CaselessEnds(filename, &ext)) return;
res = DynamicLib_Load(filename, &lib);
if (res) { Logger_Warn2(res, "loading plugin", filename); return; }
if (!String_CaselessEnds(path, &ext)) return;
res = DynamicLib_Load(path, &lib);
if (res) { Logger_DynamicLibWarn2(res, "loading plugin", path); return; }
res = DynamicLib_Get(lib, "Plugin_ApiVersion", &verSymbol);
if (res) { Logger_Warn2(res, "getting version of", filename); return; }
if (res) { Logger_DynamicLibWarn2(res, "getting version of", path); return; }
res = DynamicLib_Get(lib, "Plugin_Component", &compSymbol);
if (res) { Logger_Warn2(res, "initing", filename); return; }
if (res) { Logger_DynamicLibWarn2(res, "initing", path); return; }
ver = *((int*)verSymbol);
if (ver < GAME_API_VER) {
Chat_Add1("&c%s plugin is outdated! Try getting a more recent version.", filename);
Chat_Add1("&c%s plugin is outdated! Try getting a more recent version.", path);
return;
} else if (ver > GAME_API_VER) {
Chat_Add1("&cYour game is too outdated to use %s plugin! Try updating it.", filename);
Chat_Add1("&cYour game is too outdated to use %s plugin! Try updating it.", path);
return;
}
@ -405,7 +405,7 @@ static void Game_LoadPlugins(void) {
ReturnCode res;
res = Directory_Enum(&dir, NULL, Game_LoadPlugin);
if (res) Logger_Warn(res, "enumerating plugins directory");
if (res) Logger_OldWarn(res, "enumerating plugins directory");
}
void Game_Free(void* obj);
@ -727,9 +727,6 @@ static void Game_RunLoop(void) {
#endif
void Game_Run(int width, int height, const String* title) {
uint64_t lastRender, render;
double time;
Window_CreateSimple(width, height);
Window_SetTitle(title);
Window_SetVisible(true);

View File

@ -1567,10 +1567,10 @@ static void UpdatesScreen_Init(struct LScreen* s_) {
String_InitArray(path, pathBuffer);
res = Process_GetExePath(&path);
if (res) { Logger_Warn(res, "getting .exe path"); return; }
if (res) { Logger_OldWarn(res, "getting .exe path"); return; }
res = File_GetModifiedTime(&path, &buildTime);
if (res) { Logger_Warn(res, "getting build time"); return; }
if (res) { Logger_OldWarn(res, "getting build time"); return; }
UpdatesScreen_Format(&s->LblYour, "Your build: ", buildTime);
}

View File

@ -494,13 +494,13 @@ static void FetchUpdateTask_Handle(uint8_t* data, uint32_t len) {
ReturnCode res;
res = Stream_WriteAllTo(&path, data, len);
if (res) { Logger_Warn(res, "saving update"); return; }
if (res) { Logger_OldWarn(res, "saving update"); return; }
res = File_SetModifiedTime(&path, FetchUpdateTask.Timestamp);
if (res) Logger_Warn(res, "setting update time");
if (res) Logger_OldWarn(res, "setting update time");
res = Platform_MarkExecutable(&path);
if (res) Logger_Warn(res, "making update executable");
if (res) Logger_OldWarn(res, "making update executable");
}
void FetchUpdateTask_Run(bool release, bool d3d9) {
@ -565,7 +565,7 @@ static void FetchFlagsTask_Handle(uint8_t* data, uint32_t len) {
Stream_ReadonlyMemory(&s, data, len);
res = Png_Decode(&flags[FetchFlagsTask.Count].Bmp, &s);
if (res) Logger_Warn(res, "decoding flag");
if (res) Logger_OldWarn(res, "decoding flag");
FetchFlagsTask.Count++;
FetchFlagsTask_DownloadNext();

View File

@ -75,10 +75,10 @@ bool Launcher_ConnectToServer(const String* hash) {
Launcher_StartFromInfo(&FetchServerTask.Server);
return true;
} else if (FetchServerTask.Base.Res) {
Logger_Warn(FetchServerTask.Base.Res, "fetching server info");
Logger_OldWarn(FetchServerTask.Base.Res, "fetching server info");
} else if (FetchServerTask.Base.Status != 200) {
/* TODO: Use a better dialog message.. */
Logger_Warn(FetchServerTask.Base.Status, "fetching server info");
Logger_OldWarn(FetchServerTask.Base.Status, "fetching server info");
} else {
Window_ShowDialog("Failed to connect", "No server has that hash");
}
@ -364,7 +364,7 @@ static ReturnCode Launcher_ProcessZipEntry(const String* path, struct Stream* da
res = Png_Decode(&fontBmp, data);
if (res) {
Logger_Warn(res, "decoding default.png"); return res;
Logger_OldWarn(res, "decoding default.png"); return res;
} else {
Drawer2D_SetFontBitmap(&fontBmp);
useBitmappedFont = !Options_GetBool(OPT_USE_CHAT_FONT, false);
@ -374,7 +374,7 @@ static ReturnCode Launcher_ProcessZipEntry(const String* path, struct Stream* da
res = Png_Decode(&bmp, data);
if (res) {
Logger_Warn(res, "decoding terrain.png"); return res;
Logger_OldWarn(res, "decoding terrain.png"); return res;
} else {
Launcher_LoadTextures(&bmp);
}
@ -389,7 +389,7 @@ static void Launcher_ExtractTexturePack(const String* path) {
res = Stream_OpenFile(&stream, path);
if (res) {
Logger_Warn(res, "opening texture pack"); return;
Logger_OldWarn(res, "opening texture pack"); return;
}
Zip_Init(&state, &stream);
@ -398,7 +398,7 @@ static void Launcher_ExtractTexturePack(const String* path) {
res = Zip_Extract(&state);
if (res) {
Logger_Warn(res, "extracting texture pack");
Logger_OldWarn(res, "extracting texture pack");
}
stream.Close(&stream);
}
@ -534,7 +534,7 @@ bool Launcher_StartGame(const String* user, const String* mppass, const String*
String_InitArray(path, pathBuffer);
res = Process_GetExePath(&path);
if (res) { Logger_Warn(res, "getting .exe path"); return false; }
if (res) { Logger_OldWarn(res, "getting .exe path"); return false; }
String_InitArray(args, argsBuffer);
String_AppendString(&args, user);
@ -546,7 +546,7 @@ bool Launcher_StartGame(const String* user, const String* mppass, const String*
/* HRESULT when user clicks 'cancel' to 'are you sure you want to run ClassiCube.exe' */
if (res == 0x80004005) return;
#endif
if (res) { Logger_Warn(res, "starting game"); return false; }
if (res) { Logger_OldWarn(res, "starting game"); return false; }
Launcher_ShouldExit = Options_GetBool(OPT_AUTO_CLOSE_LAUNCHER, false);
return true;
@ -614,7 +614,7 @@ static void Launcher_ApplyUpdate(void) {
String_InitArray(exe, exeBuffer);
res = Process_GetExePath(&exe);
if (res) { Logger_Warn(res, "getting executable path"); return; }
if (res) { Logger_OldWarn(res, "getting executable path"); return; }
Utils_UNSAFE_GetFilename(&exe);
String_InitArray(str, strBuffer);
@ -622,12 +622,12 @@ static void Launcher_ApplyUpdate(void) {
/* Can't use WriteLine, want \n as actual newline not code page 437 */
res = Stream_WriteAllTo(&scriptPath, (const uint8_t*)str.buffer, str.length);
if (res) { Logger_Warn(res, "saving update script"); return; }
if (res) { Logger_OldWarn(res, "saving update script"); return; }
res = Platform_MarkExecutable(&scriptPath);
if (res) Logger_Warn(res, "making update script executable");
if (res) Logger_OldWarn(res, "making update script executable");
res = Process_Start(&scriptName, &scriptArgs);
if (res) { Logger_Warn(res, "starting update script"); return; }
if (res) { Logger_OldWarn(res, "starting update script"); return; }
}
#endif

View File

@ -480,7 +480,7 @@ static void Logger_DumpMisc(void* ctx) { }
/*########################################################################################################################*
*----------------------------------------------------------Common---------------------------------------------------------*
*#########################################################################################################################*/
void Logger_Warn(ReturnCode res, const char* place) {
void Logger_OldWarn(ReturnCode res, const char* place) {
String msg; char msgBuffer[128];
String_InitArray(msg, msgBuffer);
@ -488,7 +488,7 @@ void Logger_Warn(ReturnCode res, const char* place) {
Logger_WarnFunc(&msg);
}
void Logger_Warn2(ReturnCode res, const char* place, const String* path) {
void Logger_OldWarn2(ReturnCode res, const char* place, const String* path) {
String msg; char msgBuffer[256];
String_InitArray(msg, msgBuffer);
@ -496,6 +496,41 @@ void Logger_Warn2(ReturnCode res, const char* place, const String* path) {
Logger_WarnFunc(&msg);
}
void Logger_SysWarn(ReturnCode res, const char* place, Logger_DescribeError describeErr) {
String msg; char msgBuffer[256];
String_InitArray(msg, msgBuffer);
String_Append(&msg, '"');
if (describeErr(res, &msg)) {
String_Format2(&msg, "\" (i) error when %c", &res, place);
} else {
String_DeleteAt(&msg, 0);
String_Format2(&msg, "Error %h when %c", &res, place);
}
Logger_WarnFunc(&msg);
}
void Logger_SysWarn2(ReturnCode res, const char* place, const String* path, Logger_DescribeError describeErr) {
String msg; char msgBuffer[256];
String_InitArray(msg, msgBuffer);
String_Append(&msg, '"');
if (describeErr(res, &msg)) {
String_Format3(&msg, "\" (%i) error when %c '%s'", &res, place, path);
} else {
String_DeleteAt(&msg, 0);
String_Format3(&msg, "Error %h when %c '%s'", &res, place, path);
}
Logger_WarnFunc(&msg);
}
void Logger_DynamicLibWarn2(ReturnCode res, const char* place, const String* path) {
Logger_SysWarn2(res, place, path, DynamicLib_DescribeError);
}
void Logger_Warn2(ReturnCode res, const char* place, const String* path) {
Logger_SysWarn2(res, place, path, Platform_DescribeError);
}
void Logger_DialogWarn(const String* msg) {
String dst; char dstBuffer[256];
String_InitArray_NT(dst, dstBuffer);

View File

@ -5,6 +5,7 @@
Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/
typedef bool (*Logger_DescribeError)(ReturnCode res, String* dst);
typedef void (*Logger_DoWarn)(const String* msg);
/* Informs the user about a non-fatal error. */
/* By default this shows a message box, but changes to in-game chat when game is running. */
@ -14,8 +15,19 @@ extern const char* Logger_DialogTitle;
void Logger_DialogWarn(const String* msg);
/* Informs the user about a non-fatal error, with a message of form: "Error [result] when [place] */
void Logger_Warn(ReturnCode res, const char* place);
/* Informs the user about a non-fatal error, with a message of form: "Error [result] when [place] 'path' */
void Logger_OldWarn(ReturnCode res, const char* place);
/* Informs the user about a non-fatal error, with a message of form: "Error [result] when [place] '[path]' */
void Logger_OldWarn2(ReturnCode res, const char* place, const String* path);
/* Informs the user about a non-fatal error, with a message of either:
"Error [error desc] ([result]) when [place] or "Error [result] when [place] */
void Logger_SysWarn(ReturnCode res, const char* place, Logger_DescribeError describeErr);
/* Informs the user about a non-fatal error, with a message of either:
"Error [error desc] ([result]) when [place] 'path' or "Error [result] when [place] 'path' */
void Logger_SysWarn2(ReturnCode res, const char* place, const String* path, Logger_DescribeError describeErr);
/* Shortcut for Logger_SysWarn2 with DynamicLib_DescribeError */
void Logger_DynamicLibWarn2(ReturnCode res, const char* place, const String* path);
/* Shortcut for Logger_SysWarn2 with Platform_DescribeError */
void Logger_Warn2(ReturnCode res, const char* place, const String* path);
/* Hooks the operating system's unhandled error callback/signal. */

View File

@ -26,6 +26,12 @@
#define _UNICODE
#endif
#ifdef UNICODE
#define Platform_DecodeString(dst, src, len) Convert_DecodeUtf16(dst, src, (len) * 2)
#else
#define Platform_DecodeString(dst, src, len) Convert_DecodeAscii(dst, src, len)
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
@ -1765,11 +1771,7 @@ ReturnCode Process_GetExePath(String* path) {
DWORD len = GetModuleFileName(NULL, chars, FILENAME_SIZE);
if (!len) return GetLastError();
#ifdef UNICODE
Convert_DecodeUtf16(path, chars, len * 2);
#else
Convert_DecodeAscii(path, chars, len);
#endif
Platform_DecodeString(path, chars, len);
return 0;
}
@ -1817,6 +1819,10 @@ ReturnCode DynamicLib_Get(void* lib, const char* name, void** symbol) {
*symbol = GetProcAddress(lib, name);
return *symbol ? 0 : GetLastError();
}
bool DynamicLib_DescribeError(ReturnCode res, String* dst) {
return Platform_DescribeError(res, dst);
}
#endif
#ifdef CC_BUILD_POSIX
ReturnCode Process_Start(const String* path, const String* args) {
@ -1866,6 +1872,12 @@ ReturnCode DynamicLib_Get(void* lib, const char* name, void** symbol) {
*symbol = dlsym(lib, name);
return *symbol == NULL; /* dlerror would be proper, but eh */
}
bool DynamicLib_DescribeError(ReturnCode res, String* dst) {
char* err = dlerror();
if (err) String_AppendConst(dst, err);
return err && err[0];
}
#endif
#ifdef CC_BUILD_UNIX
ReturnCode Process_StartOpen(const String* args) {
@ -2016,7 +2028,7 @@ void Platform_Init(void) {
heap = GetProcessHeap();
res = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (res) Logger_Warn(res, "starting WSA");
if (res) Logger_OldWarn(res, "starting WSA");
hasDebugger = IsDebuggerPresent();
/* For when user runs from command prompt */
@ -2106,6 +2118,16 @@ ReturnCode Platform_Decrypt(const uint8_t* data, int len, uint8_t** dec, int* de
LocalFree(dataOut.pbData);
return 0;
}
bool Platform_DescribeError(ReturnCode res, String* dst) {
TCHAR chars[600];
res = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), chars, 600, NULL);
if (!res) return false;
Platform_DecodeString(dst, chars, res);
return true;
}
#endif
#ifdef CC_BUILD_POSIX
int Platform_ConvertString(void* data, const String* src) {
@ -2169,6 +2191,18 @@ ReturnCode Platform_Encrypt(const uint8_t* data, int len, uint8_t** enc, int* en
ReturnCode Platform_Decrypt(const uint8_t* data, int len, uint8_t** dec, int* decLen) {
return ReturnCode_NotSupported;
}
bool Platform_DescribeError(ReturnCode res, String* dst) {
char chars[600];
int len;
len = strerror_r(res, chars, 600);
if (len === -1) return false;
len = String_CalcLen(chars, 600);
Convert_DecodeUtf8(dst, chars, len);
return true;
}
#endif
#ifdef CC_BUILD_UNIX
void Platform_Init(void) {

View File

@ -54,6 +54,10 @@ ReturnCode Platform_Encrypt(const uint8_t* data, int len, uint8_t** enc, int* en
/* Decrypts data in a platform-specific manner. (may not be supported) */
/* NOTE: Should only be implemented when platform natively supports it. */
ReturnCode Platform_Decrypt(const uint8_t* data, int len, uint8_t** dec, int* decLen);
/* Outputs more detailed information about errors with operating system functions. */
/* NOTE: This is for general functions like file I/O. If a more specific
describe exists (e.g. DynamicLib_DescribeError), that should be preferred. */
bool Platform_DescribeError(ReturnCode res, String* dst);
/* Returns the full path of the application's executable. */
ReturnCode Process_GetExePath(String* path);
@ -74,6 +78,10 @@ CC_API ReturnCode DynamicLib_Get(void* lib, const char* name, void** symbol);
/* NOTE: This should ONLY be used for dynamically loading platform-specific symbols. */
/* (e.g. functionality that only exists on recent operating system versions) */
void* DynamicLib_GetFrom(const char* filename, const char* name);
/* Outputs more detailed information about errors with the DynamicLib functions. */
/* NOTE: You must call this immediately after DynamicLib_Load/DynamicLib_Get,
because on some platforms, the error is a static string instead of from error code. */
bool DynamicLib_DescribeError(ReturnCode res, String* dst);
/* Allocates a block of memory, with undetermined contents. Exits process on allocation failure. */
CC_API void* Mem_Alloc(uint32_t numElems, uint32_t elemsSize, const char* place);

View File

@ -72,15 +72,15 @@ static void Program_SetCurrentDirectory(void) {
String_InitArray(path, pathBuffer);
res = Process_GetExePath(&path);
if (res) { Logger_Warn(res, "getting exe path"); return; }
if (res) { Logger_OldWarn(res, "getting exe path"); return; }
/* get rid of filename at end of directory */
for (i = path.length - 1; i >= 0; i--, path.length--) {
if (path.buffer[i] == '/' || path.buffer[i] == '\\') break;
}
res = Platform_SetCurrentDirectory(&path);
res = Platform_SetCurrentDirectory(&path);
if (res) { Logger_Warn(res, "setting current directory"); return; }
#endif
#endif
}
/* Terminates the program due to an invalid command line argument */

View File

@ -83,13 +83,13 @@ static void Resources_CheckTextures(void) {
if (!File_Exists(&path)) return;
res = Stream_OpenFile(&stream, &path);
if (res) { Logger_Warn(res, "checking default.zip"); return; }
if (res) { Logger_OldWarn(res, "checking default.zip"); return; }
Zip_Init(&state, &stream);
state.SelectEntry = Resources_SelectZipEntry;
res = Zip_Extract(&state);
stream.Close(&stream);
if (res) Logger_Warn(res, "inspecting default.zip");
if (res) Logger_OldWarn(res, "inspecting default.zip");
/* if somehow have say "gui.png", "GUI.png" */
Textures_AllExist = texturesFound >= Array_Elems(Resources_Textures);
@ -558,13 +558,13 @@ static void TexPatcher_MakeDefaultZip(void) {
res = Stream_CreateFile(&s, &path);
if (res) {
Logger_Warn(res, "creating default.zip");
Logger_OldWarn(res, "creating default.zip");
} else {
res = TexPatcher_WriteEntries(&s);
if (res) Logger_Warn(res, "making default.zip");
if (res) Logger_OldWarn(res, "making default.zip");
res = s.Close(&s);
if (res) Logger_Warn(res, "closing default.zip");
if (res) Logger_OldWarn(res, "closing default.zip");
}
for (i = 0; i < Array_Elems(Resources_Files); i++) {
@ -585,9 +585,9 @@ static void SoundPatcher_FixupHeader(struct Stream* s, struct VorbisState* ctx)
ReturnCode res;
res = s->Length(s, &length);
if (res) { Logger_Warn(res, "getting .wav length"); return; }
if (res) { Logger_OldWarn(res, "getting .wav length"); return; }
res = s->Seek(s, 0);
if (res) { Logger_Warn(res, "seeking to .wav start"); return; }
if (res) { Logger_OldWarn(res, "seeking to .wav start"); return; }
Stream_SetU32_BE(&header[0], WAV_FourCC('R','I','F','F'));
Stream_SetU32_LE(&header[4], length - 8);
@ -605,7 +605,7 @@ static void SoundPatcher_FixupHeader(struct Stream* s, struct VorbisState* ctx)
Stream_SetU32_LE(&header[40], length - sizeof(header));
res = Stream_Write(s, header, sizeof(header));
if (res) Logger_Warn(res, "fixing .wav header");
if (res) Logger_OldWarn(res, "fixing .wav header");
}
static void SoundPatcher_DecodeAudio(struct Stream* s, struct VorbisState* ctx) {
@ -615,21 +615,21 @@ static void SoundPatcher_DecodeAudio(struct Stream* s, struct VorbisState* ctx)
/* ctx is all 0, so reuse it here for header */
res = Stream_Write(s, ctx, 44);
if (res) { Logger_Warn(res, "writing .wav header"); return; }
if (res) { Logger_OldWarn(res, "writing .wav header"); return; }
res = Vorbis_DecodeHeaders(ctx);
if (res) { Logger_Warn(res, "decoding .ogg header"); return; }
if (res) { Logger_OldWarn(res, "decoding .ogg header"); return; }
samples = Mem_Alloc(ctx->BlockSizes[1] * ctx->Channels, 2, ".ogg samples");
for (;;) {
res = Vorbis_DecodeFrame(ctx);
if (res == ERR_END_OF_STREAM) break;
if (res) { Logger_Warn(res, "decoding .ogg"); break; }
if (res) { Logger_OldWarn(res, "decoding .ogg"); break; }
count = Vorbis_OutputFrame(ctx, samples);
/* TODO: Do we need to account for big endian */
res = Stream_Write(s, samples, count * 2);
if (res) { Logger_Warn(res, "writing samples"); break; }
if (res) { Logger_OldWarn(res, "writing samples"); break; }
}
Mem_Free(samples);
}
@ -646,7 +646,7 @@ static void SoundPatcher_Save(struct ResourceSound* sound, struct HttpRequest* r
String_Format1(&path, "audio/%c.wav", sound->Name);
res = Stream_CreateFile(&dst, &path);
if (res) { Logger_Warn(res, "creating .wav file"); return; }
if (res) { Logger_OldWarn(res, "creating .wav file"); return; }
Ogg_MakeStream(&ogg, buffer, &src);
ctx.Source = &ogg;
@ -655,7 +655,7 @@ static void SoundPatcher_Save(struct ResourceSound* sound, struct HttpRequest* r
SoundPatcher_FixupHeader(&dst, &ctx);
res = dst.Close(&dst);
if (res) Logger_Warn(res, "closing .wav file");
if (res) Logger_OldWarn(res, "closing .wav file");
}
static void MusicPatcher_Save(struct ResourceMusic* music, struct HttpRequest* req) {
@ -666,7 +666,7 @@ static void MusicPatcher_Save(struct ResourceMusic* music, struct HttpRequest* r
String_Format1(&path, "audio/%c", music->Name);
res = Stream_WriteAllTo(&path, req->Data, req->Size);
if (res) Logger_Warn(res, "saving music file");
if (res) Logger_OldWarn(res, "saving music file");
}