From 41b116e2f2b847d7120372f082b3758d3cb6b97a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Nov 2019 22:46:00 +0100 Subject: [PATCH] - save menu in Duke Nukem is working. --- source/common/filesystem/filesystem.cpp | 3 +- source/common/menu/loadsavemenu.cpp | 5 +- source/common/menu/menu.cpp | 13 ++- source/common/menu/menu.h | 4 +- source/common/menu/messagebox.cpp | 2 +- source/common/menu/savegamemanager.cpp | 28 +++-- source/common/savegamehelp.cpp | 41 ++++--- source/common/savegamehelp.h | 1 - source/duke3d/src/savegame.cpp | 6 +- source/rr/src/savegame.cpp | 9 +- wadsrc/static/demolition/language.csv | 140 +++++++++++++++++++++++- 11 files changed, 204 insertions(+), 48 deletions(-) diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 9525f6081..1a508f6d4 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -230,7 +230,8 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { for (i = 0; i < Files.Size(); ++i) { - if (stricmp (GetResourceFileName (i), name) == 0) + auto pth = ExtractFileBase(GetResourceFileName(i), true); + if (stricmp (pth.GetChars(), name) == 0) { return i; } diff --git a/source/common/menu/loadsavemenu.cpp b/source/common/menu/loadsavemenu.cpp index f3d21487f..0ad22f5f9 100644 --- a/source/common/menu/loadsavemenu.cpp +++ b/source/common/menu/loadsavemenu.cpp @@ -57,8 +57,8 @@ class DLoadSaveMenu : public DListMenu protected: - int Selected; - int TopItem; + int Selected = 0; + int TopItem = 0; int savepicLeft; @@ -576,7 +576,6 @@ public: if (mSaveName.Len() > 0) { savegameManager.DoSave(Selected, mSaveName); - mSaveName = ""; } } diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp index e16d7634c..5e9c4d96f 100644 --- a/source/common/menu/menu.cpp +++ b/source/common/menu/menu.cpp @@ -849,12 +849,17 @@ void M_Drawer (void) void M_ClearMenus () { M_DemoNoPlay = false; - if (DMenu::CurrentMenu != NULL) + transition.previous = transition.current = nullptr; + transition.dir = 0; + auto menu = DMenu::CurrentMenu; + while (menu != nullptr) { - DMenu::CurrentMenu->Destroy(); - delete DMenu::CurrentMenu; - DMenu::CurrentMenu = NULL; + auto nextm = menu->mParentMenu; + menu->Destroy(); + delete menu; + menu = nextm; } + DMenu::CurrentMenu = nullptr; menuactive = MENU_Off; GUICapture &= ~1; gi->MenuClosed(); diff --git a/source/common/menu/menu.h b/source/common/menu/menu.h index 035cda2c6..8727f2767 100644 --- a/source/common/menu/menu.h +++ b/source/common/menu/menu.h @@ -816,8 +816,8 @@ public: void InsertNewSaveNode(); bool RemoveNewSaveNode(); - void LoadGame(FSaveGameNode* node, bool ok4q, bool forceq); - void SaveGame(FSaveGameNode* node); + void LoadGame(FSaveGameNode* node); + void SaveGame(FSaveGameNode* node, bool ok4q, bool forceq); }; diff --git a/source/common/menu/messagebox.cpp b/source/common/menu/messagebox.cpp index d0e75cd5d..06f59b59a 100644 --- a/source/common/menu/messagebox.cpp +++ b/source/common/menu/messagebox.cpp @@ -371,7 +371,7 @@ void M_StartMessage(const char *message, int messagemode, int scriptId, FName ac // //============================================================================= -DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, int scriptId, bool playsound, FName action = NAME_None, hFunc handler) +DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, int scriptId, bool playsound, FName action, hFunc handler) { auto newmenu = new DMessageBoxMenu(DMenu::CurrentMenu, message, messagemode, false, action, handler); newmenu->scriptID = scriptId; diff --git a/source/common/menu/savegamemanager.cpp b/source/common/menu/savegamemanager.cpp index 7a8b4ae67..694157f9e 100644 --- a/source/common/menu/savegamemanager.cpp +++ b/source/common/menu/savegamemanager.cpp @@ -55,19 +55,22 @@ FSavegameManager savegameManager; -void FSavegameManager::LoadGame(FSaveGameNode* node, bool ok4q, bool forceq) +void FSavegameManager::LoadGame(FSaveGameNode* node) { if (gi->LoadGame(node)) + { + } +} + +void FSavegameManager::SaveGame(FSaveGameNode* node, bool ok4q, bool forceq) +{ + if (gi->SaveGame(node)) { FString fn = node->Filename; FString desc = node->SaveTitle; NotifyNewSave(fn, desc, ok4q, forceq); } -} -void FSavegameManager::SaveGame(FSaveGameNode* node) -{ - gi->SaveGame(node); } //============================================================================= @@ -196,6 +199,7 @@ void FSavegameManager::ReadSaveStrings() auto fr = info->NewReader(); FString title; int check = G_ValidateSavegame(fr, &title); + fr.Close(); delete savegame; if (check != 0) { @@ -299,7 +303,7 @@ void FSavegameManager::DoSave(int Selected, const char *savegamestring) { auto node = *SaveGames[Selected]; node.SaveTitle = savegamestring; - savegameManager.SaveGame(&node); + savegameManager.SaveGame(&node, true, false); } else { @@ -316,7 +320,7 @@ void FSavegameManager::DoSave(int Selected, const char *savegamestring) } } FSaveGameNode sg{ savegamestring, filename }; - savegameManager.SaveGame(&sg); + savegameManager.SaveGame(&sg, true, false); } M_ClearMenus(); } @@ -501,7 +505,7 @@ FSaveGameNode *FSavegameManager::GetSavegame(int i) void FSavegameManager::InsertNewSaveNode() { - NewSaveNode.SaveTitle = GStrings["NEWSAVE"]; + NewSaveNode.SaveTitle = GStrings("NEWSAVE"); NewSaveNode.bNoDelete = true; SaveGames.Insert(0, &NewSaveNode); } @@ -571,7 +575,7 @@ void M_Autosave() readableTime = myasctime(); sg.SaveTitle.Format("Autosave %s", readableTime); nextautosave = (nextautosave + 1) % count; - savegameManager.SaveGame(&sg); + savegameManager.SaveGame(&sg, false, false); } CCMD(autosave) @@ -603,7 +607,7 @@ CCMD(rotatingquicksave) readableTime = myasctime(); sg.SaveTitle.Format("Quicksave %s", readableTime); nextquicksave = (nextquicksave + 1) % count; - savegameManager.SaveGame(&sg); + savegameManager.SaveGame(&sg, false, false); } @@ -629,7 +633,7 @@ CCMD(quicksave) // [mxd]. Just save the game, no questions asked. if (!saveloadconfirmation) { - savegameManager.SaveGame(savegameManager.quickSaveSlot); + savegameManager.SaveGame(savegameManager.quickSaveSlot, true, true); return; } @@ -642,7 +646,7 @@ CCMD(quicksave) { if (res) { - savegameManager.SaveGame(savegameManager.quickSaveSlot); + savegameManager.SaveGame(savegameManager.quickSaveSlot, true, true); } }); diff --git a/source/common/savegamehelp.cpp b/source/common/savegamehelp.cpp index b0eae5d96..7061245ff 100644 --- a/source/common/savegamehelp.cpp +++ b/source/common/savegamehelp.cpp @@ -126,10 +126,16 @@ void G_WriteSaveHeader(const char *name, const char*mapname, const char *maptitl sjson_put_int(ctx, root, "Save Version", savesig.currentsavever); sjson_put_string(ctx, root, "Engine", savesig.savesig); sjson_put_string(ctx, root, "Game Resource", fileSystem.GetResourceFileName(1)); - sjson_put_string(ctx, root, "map", mapname); - sjson_put_string(ctx, root, "Title", maptitle); + sjson_put_string(ctx, root, "Map Name", maptitle); + sjson_put_string(ctx, root, "Title", name); if (*mapname == '/') mapname++; - sjson_put_string(ctx, root, "Map Resource", mapname); + sjson_put_string(ctx, root, "Map File", mapname); + auto fileno = fileSystem.FindFile(mapname); + auto mapfile = fileSystem.GetFileContainer(fileno); + auto mapcname = fileSystem.GetResourceFileName(mapfile); + if (mapcname) sjson_put_string(ctx, root, "Map Resource", mapcname); + else return; // this should never happen. Saving on a map that isn't present is impossible. + char* encoded = sjson_stringify(ctx, root, " "); @@ -188,13 +194,11 @@ static bool CheckSingleFile (const char *name, bool &printRequires, bool printwa // //============================================================================= -bool G_CheckSaveGameWads (sjson_node* root, bool printwarn) +static bool G_CheckSaveGameWads (const char *gamegrp, const char *mapgrp, bool printwarn) { bool printRequires = false; - auto text = sjson_get_string(root, "Game Resource", ""); - CheckSingleFile (text, printRequires, printwarn); - text = sjson_get_string(root, "MAP Resource", ""); - CheckSingleFile (text, printRequires, printwarn); + CheckSingleFile (gamegrp, printRequires, printwarn); + CheckSingleFile (mapgrp, printRequires, printwarn); if (printRequires) { @@ -228,6 +232,7 @@ int G_ValidateSavegame(FileReader &fr, FString *savetitle) int savever = sjson_get_int(root, "Save Version", -1); FString engine = sjson_get_string(root, "Engine", ""); FString gamegrp = sjson_get_string(root, "Game Resource", ""); + FString mapgrp = sjson_get_string(root, "Map Resource", ""); FString title = sjson_get_string(root, "Title", ""); auto savesig = gi->GetSaveSig(); @@ -241,22 +246,27 @@ int G_ValidateSavegame(FileReader &fr, FString *savetitle) return 0; } + if (savever < savesig.minsavever) { // old, incompatible savegame. List as not usable. return -1; } - else if (gamegrp.CompareNoCase(fileSystem.GetResourceFileName(1)) == 0) - { - return G_CheckSaveGameWads(root, false)? 0 : -2; - } else { - // different game. Skip this. - return 0; + auto ggfn = ExtractFileBase(fileSystem.GetResourceFileName(1), true); + if (gamegrp.CompareNoCase(ggfn) == 0) + { + return G_CheckSaveGameWads(gamegrp, mapgrp, false) ? 1 : -2; + } + else + { + // different game. Skip this. + return 0; + } } } - return 1; + return 0; } //============================================================================= @@ -277,7 +287,6 @@ FString G_BuildSaveName (const char *prefix) if (!strchr(prefix, '.')) name << SAVEGAME_EXT; // only add an extension if the prefix doesn't have one already. name = NicePath(name); name.Substitute("\\", "/"); - CreatePath(name); return name; } diff --git a/source/common/savegamehelp.h b/source/common/savegamehelp.h index 78c368e1f..5410a54ee 100644 --- a/source/common/savegamehelp.h +++ b/source/common/savegamehelp.h @@ -15,7 +15,6 @@ void FinishSavegameRead(); class FileReader; FString G_BuildSaveName (const char *prefix); -bool G_CheckSaveGameWads (struct sjson_node* root, bool printwarn); int G_ValidateSavegame(FileReader &fr, FString *savetitle); void G_WriteSaveHeader(const char *name, const char*mapname, const char *title); diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index b5b986209..4ca22833e 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -594,8 +594,7 @@ bool G_SavePlayer(FSaveGameNode *sv) errno = 0; FileWriter *fil; - fn = G_BuildSaveName(sv->Filename); - OpenSaveGameForWrite(fn); + OpenSaveGameForWrite(sv->Filename); fil = WriteSavegameChunk("snapshot.dat"); // The above call cannot fail. { @@ -1490,7 +1489,8 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i auto fw = WriteSavegameChunk("header.dat"); fw->Write(&h, sizeof(savehead_t)); - G_WriteSaveHeader(name, currentboardfilename, g_mapInfo[(MAXLEVELS * ud.volume_number) + ud.level_number].name); + auto& mi = g_mapInfo[(MAXLEVELS * ud.volume_number) + ud.level_number]; + G_WriteSaveHeader(name, mi.filename, mi.name); } else { diff --git a/source/rr/src/savegame.cpp b/source/rr/src/savegame.cpp index bfab8e3a8..c5cd7aa4f 100644 --- a/source/rr/src/savegame.cpp +++ b/source/rr/src/savegame.cpp @@ -342,8 +342,7 @@ bool G_SavePlayer(FSaveGameNode *sv) errno = 0; FileWriter *fil; - fn = G_BuildSaveName(sv->Filename); - OpenSaveGameForWrite(fn); + OpenSaveGameForWrite(sv->Filename); fil = WriteSavegameChunk("snapshot.dat"); // The above call cannot fail. { @@ -402,6 +401,7 @@ bool GameInterface::SaveGame(FSaveGameNode* sv) { Bstrcpy(apStrings[QUOTE_RESERVED4], "Multiplayer Saving Not Yet Supported"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); + return false; } else { @@ -411,7 +411,7 @@ bool GameInterface::SaveGame(FSaveGameNode* sv) G_DrawRooms(myconnectindex, 65536); g_screenCapture = 0; - G_SavePlayer(sv); + return G_SavePlayer(sv); } } @@ -1179,7 +1179,8 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i auto fw = WriteSavegameChunk("header.dat"); fw->Write(&h, sizeof(savehead_t)); - G_WriteSaveHeader(name, currentboardfilename, g_mapInfo[(MAXLEVELS * ud.volume_number) + ud.level_number].name); + auto& mi = g_mapInfo[(MAXLEVELS * ud.volume_number) + ud.level_number]; + G_WriteSaveHeader(name, mi.filename, mi.name); } else { diff --git a/wadsrc/static/demolition/language.csv b/wadsrc/static/demolition/language.csv index 4ddf96f7c..fcd7b65f3 100644 --- a/wadsrc/static/demolition/language.csv +++ b/wadsrc/static/demolition/language.csv @@ -72,4 +72,142 @@ Carrega numa tecla qualquer.",,"Невозможно сохранить игру Притисните тастер." Do you really want to do this?,SAFEMESSAGE,,,,Vážně to chceš udělat?,Möchtest du das wirklich tun?,,Ĉu vi vere volas fari tion?,¿Realmente quieres hacer esto?,¿Realmente quieres hacerlo?,Haluatko varmasti tehdä tämän?,Voulez-vous vraiment faire ça?,Biztos megakarod tenni?,Sei sicuro di volerlo fare?,本当に実行するのか?,정말로 정하시겠습니까?,Wil je dit echt doen?,Naprawdę chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,,Вы уверены?,Да ли заиста желите то да урадите? -Not set,NOTSET,,,,Není nastavené,Nicht gesetzt,,Ne agordita,No Asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Nie ustawiono,Não definido,,,Не задан,Није намештено \ No newline at end of file +Not set,NOTSET,,,,Není nastavené,Nicht gesetzt,,Ne agordita,No Asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Nie ustawiono,Não definido,,,Не задан,Није намештено +"Quicksave over your game named + +'%s'? + +Press Y or N.",QSPROMPT,,,,"Rychle uložit přes tvoji hru s názvem + +'%s'? + +Stiskni Y nebo N.","Überschreibe %s mit einem Schnellspeicherspielstand? + +Drücke Y oder N.",,"Ĉu rapidkonservu super via ludo, ke nomita + +'%s'? + +Premu Y aŭ N.","¿Deseas guardar sobre tu partida llamada + +'%s'? + +Presiona Y ó N.",,"Haluatko tallentaa pelin %s päälle? + +Paina Y tai N.","Sauvegarde rapide sur le fichier + +'%s'? + +Appuyez sur Y ou N.","Gyorsmenteni akarsz az alábbi mentésed alatt + +'%s'? + +Nyomj Y-t vagy N-t.","Sovrascrivere il salvataggio + +'%s'? + +Premi Y oppure N.","この名前で上書きするのか? + +'%s' + +Y か N で答えろ","빠른 저장을 하시겠습니까? + +'%s' + +Y키 또는 N키를 누르시오.","Snel opslaan over je spel genaamd + +'%s'? + +Druk op Y of N.","Szybko nadpisać grę + +„%s”? + +Wciśnij Y lub N.","Salvar sobre seu jogo chamado + +'%s'? + +Aperte Y ou N.","Gravar sobre o seu jogo chamado + +'%s'? + +Carrega Y ou N.",,"Перезаписать быстрое сохранение + +«%s»? + +Нажмите Y или N.","Желите брзо чување за игру под именом + +„%s“? + +Притисните Y или N." +"Do you want to quickload the game named + +'%s'? + +Press Y or N.",QLPROMPT,,,,"Přeješ si rychle načíst hru s názvem + +'%s'? + +Stiskni Y nebo N.","Möchtest du den Spielstand %s schnellladen? + +Drücke Y oder N.",,"Ĉu vi volas rapidŝargi la ludon, ke nomita + +'%s'? + +Premu Y aŭ N.","¿Quieres cargar la partida llamada + +'%s'? + +Presiona Y ó N.",,"Haluatko pikaladata pelin %s? + +Paina Y tai N.","Voulez-vous charger la sauvegarde + +'%s'? + +Appuyez sur Y ou N.","Gyorstölteni akarod ezt a mentést + +'%s'? + +Nyomj Y-t vagy N-t.","Vuoi fare un quickload della partita + +'%s'? + +Premi Y oppure N.","この名前のデータをロードするのか? + +'%s' + +Y か N で答えろ","빠른 불러오기를 하시겠습니까? + +'%s' + +Y키 또는 N키를 누르시오.","Wil je het spel snel laden met de naam + +'%s'? + +Druk op Y of N.","Czy chcesz wczytać szybki zapis + +„%s”? + +Wciśnij Y lub N.","Deseja carregar o jogo chamado + +'%s'? + +Aperte Y ou N.","Deseja carregar o jogo chamado + +'%s'? + +Carrega Y ou N.",,"Загрузить быстрое сохранение + +«%s»? + +Нажмите Y или N.","Желите брзо учитавање за игру под именом + +„%s“? + +Притисните Y или N." +Yes,TXT_YES,,,,Ano,Ja,Ναι,Jes,Sí,,Kyllä,Oui,Igen,Si,はい,네,Ja,Tak,Sim,,,Да,Да +No,TXT_NO,,,,Ne,Nein,Όχι,Ne,No,,Ei,Non,Nem,No,いいえ,아니요,Nee,Nie,Não,,,Нет,Не +,,Savegame,,,,,,,,,,,,,,,,,,,,, +Empty slot,EMPTYSTRING,,,,Prázdný slot,nicht belegt,,Malplena Ingo,Ranura Vacía,,Tyhjä lokero,Emplacement Vide,Üres,Slot libero,空きスロット,빈 슬롯,Lege sleuf,Puste miejsce,Vazio,,,Пустой слот,Празни слот +,NEWSAVE,,,,,,,,,,,,<Új mentés>,,<新規セーブ>,<새로운 게임 저장>,,,,,,<Новое сохранение>,<Нова сачувана игра> +Game saved.,GGSAVED,,,,Hra uložena.,Spielstand gespeichert.,,Ludo konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Gioco salvato.,セーブ完了。,게임이 저장됨.,Spel opgeslagen.,Gra zapisana.,Jogo salvo.,Jogo gravado.,,Игра сохранена.,Игра сачувана. +Time,SAVECOMMENT_TIME,,,,Čas,Zeit,,Tempo,Tiempo,,Aika,Temps,Idő,Tempo,"時間 +",시간,Tijd,Czas,Tempo,,,Время,Време \ No newline at end of file