From 68cc37792ef5401addfd2e2e1327a4298dbdbd74 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 30 Jul 2025 18:46:16 +0200 Subject: [PATCH 1/3] Add EasyRPG Clone Event Name chunk This information is currently not preserved --- generator/csv/fields_easyrpg.csv | 1 + src/generated/lcf/lsd/chunks.h | 10 +++++++++- src/generated/lcf/rpg/savemapeventbase.h | 7 ++++++- src/generated/lsd_savemapevent.cpp | 8 ++++++++ src/generated/lsd_savemapeventbase.cpp | 8 ++++++++ src/generated/lsd_savepartylocation.cpp | 8 ++++++++ src/generated/lsd_savevehiclelocation.cpp | 8 ++++++++ src/generated/rpg_savemapeventbase.cpp | 1 + 8 files changed, 49 insertions(+), 2 deletions(-) diff --git a/generator/csv/fields_easyrpg.csv b/generator/csv/fields_easyrpg.csv index 98f8d278..3045f228 100644 --- a/generator/csv/fields_easyrpg.csv +++ b/generator/csv/fields_easyrpg.csv @@ -36,6 +36,7 @@ SaveMapEventBase,easyrpg_move_failure_count,f,Int32,0xC9,0,0,0,Tracks how often SaveMapEventBase,easyrpg_clone_map_id,f,UInt32,0xCA,0,0,0,The original map id of a cloned event SaveMapEventBase,easyrpg_clone_event_id,f,UInt32,0xCB,0,0,0,The original event id of a cloned event SaveMapEventBase,easyrpg_runtime_flags,f,EasyRpgEventRuntime_Flags,0xCC,0,0,0,Runtime changes to the engine config +SaveMapEventBase,easyrpg_clone_event_name,f,DBString,0xCD,,0,0,Name of the cloned event SavePartyLocation,maniac_horizontal_pan_speed,f,Double,0x8D,0,0,0,horizontal speed in the scrolls of the screen SavePartyLocation,maniac_vertical_pan_speed,f,Double,0x8E,0,0,0,vertical speed in the scrolls of the screen SaveSystem,maniac_strings,f,Vector,0x24,,0,0,rpg::Strings diff --git a/src/generated/lcf/lsd/chunks.h b/src/generated/lcf/lsd/chunks.h index ab4e6c04..7a6cbb4f 100644 --- a/src/generated/lcf/lsd/chunks.h +++ b/src/generated/lcf/lsd/chunks.h @@ -440,6 +440,8 @@ namespace LSD_Reader { easyrpg_clone_event_id = 0xCB, /** Runtime changes to the engine config */ easyrpg_runtime_flags = 0xCC, + /** Name of the cloned event */ + easyrpg_clone_event_name = 0xCD, /** */ boarding = 0x65, /** */ @@ -566,6 +568,8 @@ namespace LSD_Reader { easyrpg_clone_event_id = 0xCB, /** Runtime changes to the engine config */ easyrpg_runtime_flags = 0xCC, + /** Name of the cloned event */ + easyrpg_clone_event_name = 0xCD, /** Which vehicle */ vehicle = 0x65, /** From 0 to 255 - In flying vehicles; remaining distance to ascend */ @@ -877,7 +881,9 @@ namespace LSD_Reader { /** The original event id of a cloned event */ easyrpg_clone_event_id = 0xCB, /** Runtime changes to the engine config */ - easyrpg_runtime_flags = 0xCC + easyrpg_runtime_flags = 0xCC, + /** Name of the cloned event */ + easyrpg_clone_event_name = 0xCD }; }; struct ChunkSaveMapEvent { @@ -968,6 +974,8 @@ namespace LSD_Reader { easyrpg_clone_event_id = 0xCB, /** Runtime changes to the engine config */ easyrpg_runtime_flags = 0xCC, + /** Name of the cloned event */ + easyrpg_clone_event_name = 0xCD, /** If true; this event is waiting for foreground execution. */ waiting_execution = 0x65, /** Index of custom move route */ diff --git a/src/generated/lcf/rpg/savemapeventbase.h b/src/generated/lcf/rpg/savemapeventbase.h index e31c2928..e6c95105 100644 --- a/src/generated/lcf/rpg/savemapeventbase.h +++ b/src/generated/lcf/rpg/savemapeventbase.h @@ -16,6 +16,7 @@ #include #include #include +#include "lcf/dbstring.h" #include "lcf/enum_tags.h" #include "lcf/rpg/moveroute.h" #include "lcf/context.h" @@ -81,6 +82,7 @@ namespace rpg { EasyRpgEventRuntime_Flags() noexcept: reserved_1(false) {} } easyrpg_runtime_flags; + DBString easyrpg_clone_event_name; }; inline bool operator==(const SaveMapEventBase::EasyRpgEventRuntime_Flags& l, const SaveMapEventBase::EasyRpgEventRuntime_Flags& r) { @@ -136,7 +138,8 @@ namespace rpg { && l.easyrpg_move_failure_count == r.easyrpg_move_failure_count && l.easyrpg_clone_map_id == r.easyrpg_clone_map_id && l.easyrpg_clone_event_id == r.easyrpg_clone_event_id - && l.easyrpg_runtime_flags == r.easyrpg_runtime_flags; + && l.easyrpg_runtime_flags == r.easyrpg_runtime_flags + && l.easyrpg_clone_event_name == r.easyrpg_clone_event_name; } inline bool operator!=(const SaveMapEventBase& l, const SaveMapEventBase& r) { @@ -149,6 +152,8 @@ namespace rpg { void ForEachString(SaveMapEventBase& obj, const F& f, const ParentCtx* parent_ctx = nullptr) { const auto ctx16 = Context{ "move_route", -1, &obj, parent_ctx }; ForEachString(obj.move_route, f, &ctx16); + const auto ctx44 = Context{ "easyrpg_clone_event_name", -1, &obj, parent_ctx }; + f(obj.easyrpg_clone_event_name, ctx44); (void)obj; (void)f; (void)parent_ctx; diff --git a/src/generated/lsd_savemapevent.cpp b/src/generated/lsd_savemapevent.cpp index a7242406..d4fe5a0a 100644 --- a/src/generated/lsd_savemapevent.cpp +++ b/src/generated/lsd_savemapevent.cpp @@ -321,6 +321,13 @@ static TypedField static_easyrpg_clone_event_name( + &rpg::SaveMapEvent::easyrpg_clone_event_name, + LSD_Reader::ChunkSaveMapEvent::easyrpg_clone_event_name, + "easyrpg_clone_event_name", + 0, + 0 +); static TypedField static_waiting_execution( &rpg::SaveMapEvent::waiting_execution, LSD_Reader::ChunkSaveMapEvent::waiting_execution, @@ -396,6 +403,7 @@ Field const* Struct::fields[] = { &static_easyrpg_clone_map_id, &static_easyrpg_clone_event_id, &static_easyrpg_runtime_flags, + &static_easyrpg_clone_event_name, &static_waiting_execution, &static_original_move_route_index, &static_triggered_by_decision_key, diff --git a/src/generated/lsd_savemapeventbase.cpp b/src/generated/lsd_savemapeventbase.cpp index 5fbc48c2..71e294ed 100644 --- a/src/generated/lsd_savemapeventbase.cpp +++ b/src/generated/lsd_savemapeventbase.cpp @@ -321,6 +321,13 @@ static TypedField static_easyrpg_clone_event_name( + &rpg::SaveMapEventBase::easyrpg_clone_event_name, + LSD_Reader::ChunkSaveMapEventBase::easyrpg_clone_event_name, + "easyrpg_clone_event_name", + 0, + 0 +); template <> @@ -368,6 +375,7 @@ Field const* Struct::fields[] = { &static_easyrpg_clone_map_id, &static_easyrpg_clone_event_id, &static_easyrpg_runtime_flags, + &static_easyrpg_clone_event_name, NULL }; diff --git a/src/generated/lsd_savepartylocation.cpp b/src/generated/lsd_savepartylocation.cpp index f532cf52..e3c0946f 100644 --- a/src/generated/lsd_savepartylocation.cpp +++ b/src/generated/lsd_savepartylocation.cpp @@ -321,6 +321,13 @@ static TypedField static_easyrpg_clone_event_name( + &rpg::SavePartyLocation::easyrpg_clone_event_name, + LSD_Reader::ChunkSavePartyLocation::easyrpg_clone_event_name, + "easyrpg_clone_event_name", + 0, + 0 +); static TypedField static_boarding( &rpg::SavePartyLocation::boarding, LSD_Reader::ChunkSavePartyLocation::boarding, @@ -494,6 +501,7 @@ Field const* Struct::fields[] = &static_easyrpg_clone_map_id, &static_easyrpg_clone_event_id, &static_easyrpg_runtime_flags, + &static_easyrpg_clone_event_name, &static_boarding, &static_aboard, &static_vehicle, diff --git a/src/generated/lsd_savevehiclelocation.cpp b/src/generated/lsd_savevehiclelocation.cpp index 71a64faa..cc64eaa8 100644 --- a/src/generated/lsd_savevehiclelocation.cpp +++ b/src/generated/lsd_savevehiclelocation.cpp @@ -321,6 +321,13 @@ static TypedField static_easyrpg_clone_event_name( + &rpg::SaveVehicleLocation::easyrpg_clone_event_name, + LSD_Reader::ChunkSaveVehicleLocation::easyrpg_clone_event_name, + "easyrpg_clone_event_name", + 0, + 0 +); static TypedField static_vehicle( &rpg::SaveVehicleLocation::vehicle, LSD_Reader::ChunkSaveVehicleLocation::vehicle, @@ -403,6 +410,7 @@ Field const* Struct::fields[ &static_easyrpg_clone_map_id, &static_easyrpg_clone_event_id, &static_easyrpg_runtime_flags, + &static_easyrpg_clone_event_name, &static_vehicle, &static_remaining_ascent, &static_remaining_descent, diff --git a/src/generated/rpg_savemapeventbase.cpp b/src/generated/rpg_savemapeventbase.cpp index 430b6d92..f3948e9d 100644 --- a/src/generated/rpg_savemapeventbase.cpp +++ b/src/generated/rpg_savemapeventbase.cpp @@ -68,6 +68,7 @@ std::ostream& operator<<(std::ostream& os, const SaveMapEventBase& obj) { os << ", easyrpg_clone_map_id="<< obj.easyrpg_clone_map_id; os << ", easyrpg_clone_event_id="<< obj.easyrpg_clone_event_id; os << ", easyrpg_runtime_flags="<< obj.easyrpg_runtime_flags; + os << ", easyrpg_clone_event_name="<< obj.easyrpg_clone_event_name; os << "}"; return os; } From e3f7ae488a969bacb38caff56e927183d8664414 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 30 Jul 2025 19:01:25 +0200 Subject: [PATCH 2/3] ATB Mode: Set to -1 by default. Requires engine specific handling to determie the real default. --- generator/csv/enums.csv | 1 + generator/csv/fields.csv | 2 +- generator/csv/fields_easyrpg.csv | 2 +- src/generated/lcf/lsd/chunks.h | 2 +- src/generated/lcf/rpg/battlecommands.h | 2 +- src/generated/lcf/rpg/savesystem.h | 12 +++++++----- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/generator/csv/enums.csv b/generator/csv/enums.csv index 542aa5bc..3d31b473 100644 --- a/generator/csv/enums.csv +++ b/generator/csv/enums.csv @@ -160,6 +160,7 @@ SaveSystem,Scene,file,5 SaveSystem,Scene,title,6 SaveSystem,Scene,game_over,7 SaveSystem,Scene,debug,8 +SaveSystem,AtbMode,atb_unspecified,-1 SaveSystem,AtbMode,atb_active,0 SaveSystem,AtbMode,atb_wait,1 SaveVehicleLocation,VehicleType,none,0 diff --git a/generator/csv/fields.csv b/generator/csv/fields.csv index 2e82eafd..24122441 100644 --- a/generator/csv/fields.csv +++ b/generator/csv/fields.csv @@ -763,7 +763,7 @@ SaveSystem,menu_allowed,f,Boolean,0x7C,True,0,0, SaveSystem,background,f,String,0x7D,,0,0,string SaveSystem,save_count,f,Int32,0x83,0,0,0, SaveSystem,save_slot,f,Int32,0x84,1,0,0, -SaveSystem,atb_mode,f,Enum,0x8C,0,0,1,ATB mode of RPG 2003 battle system. +SaveSystem,atb_mode,f,Enum,0x8C,-1,0,1,"ATB mode of RPG 2003 battle system. 2k3e sets this to 1, otherwise 0" SaveScreen,tint_finish_red,f,Int32,0x01,100,0,0,int SaveScreen,tint_finish_green,f,Int32,0x02,100,0,0,int SaveScreen,tint_finish_blue,f,Int32,0x03,100,0,0,int diff --git a/generator/csv/fields_easyrpg.csv b/generator/csv/fields_easyrpg.csv index 3045f228..75331fc1 100644 --- a/generator/csv/fields_easyrpg.csv +++ b/generator/csv/fields_easyrpg.csv @@ -56,7 +56,7 @@ SaveSystem,maniac_options,,Vector,0x8A,,0,0,"Various FatalMix options (XX SaveSystem,maniac_joypad_bindings,,Vector,0x8B,,0,0,"JoyLeft, JoyRight, JoyUp, JoyDown, Joy1, ... Joy12" SaveSystem,maniac_message_spacing_char,f,Int32,0x8E,0,0,0,Additional spacing between characters in the message window (Editor value - 1) SaveSystem,maniac_message_spacing_line,f,Int32,0x8F,0,0,0,Additional spacing between lines in the message window (Editor value - 1) -BattleCommands,easyrpg_default_atb_mode,f,Enum,0xC8,0,0,1,Default ATB mode of RPG 2003 battle system +BattleCommands,easyrpg_default_atb_mode,f,Enum,0xC8,-1,0,1,Default ATB mode of RPG 2003 battle system BattleCommands,easyrpg_enable_battle_row_command,f,Boolean,0xC9,True,0,1,If the row command should be enabled in RPG Maker 2003 battles BattleCommands,easyrpg_sequential_order,f,Boolean,0xCA,False,0,1,If alternative and gauge style battles should behave like traditional style battles BattleCommands,easyrpg_disable_row_feature,f,Boolean,0xCB,False,0,1,If the row feature should be disabled in RPG Maker 2003 games diff --git a/src/generated/lcf/lsd/chunks.h b/src/generated/lcf/lsd/chunks.h index 7a6cbb4f..b9052b51 100644 --- a/src/generated/lcf/lsd/chunks.h +++ b/src/generated/lcf/lsd/chunks.h @@ -160,7 +160,7 @@ namespace LSD_Reader { save_count = 0x83, /** */ save_slot = 0x84, - /** ATB mode of RPG 2003 battle system. */ + /** ATB mode of RPG 2003 battle system. 2k3e sets this to 1, otherwise 0 */ atb_mode = 0x8C, /** rpg::Strings */ maniac_strings = 0x24, diff --git a/src/generated/lcf/rpg/battlecommands.h b/src/generated/lcf/rpg/battlecommands.h index a4e0cbe9..4190ce44 100644 --- a/src/generated/lcf/rpg/battlecommands.h +++ b/src/generated/lcf/rpg/battlecommands.h @@ -100,7 +100,7 @@ namespace rpg { int32_t death_teleport_x = 0; int32_t death_teleport_y = 0; int32_t death_teleport_face = 0; - int32_t easyrpg_default_atb_mode = 0; + int32_t easyrpg_default_atb_mode = -1; bool easyrpg_enable_battle_row_command = true; bool easyrpg_sequential_order = false; bool easyrpg_disable_row_feature = false; diff --git a/src/generated/lcf/rpg/savesystem.h b/src/generated/lcf/rpg/savesystem.h index 8afd2101..8acd5f31 100644 --- a/src/generated/lcf/rpg/savesystem.h +++ b/src/generated/lcf/rpg/savesystem.h @@ -55,13 +55,15 @@ namespace rpg { "debug" ); enum AtbMode { + AtbMode_atb_unspecified = -1, AtbMode_atb_active = 0, AtbMode_atb_wait = 1 }; - static constexpr auto kAtbModeTags = lcf::makeEnumTags( - "atb_active", - "atb_wait" - ); + static constexpr auto kAtbModeTags = lcf::EnumTags{ + AtbMode_atb_unspecified, "atb_unspecified", + AtbMode_atb_active, "atb_active", + AtbMode_atb_wait, "atb_wait" + }; int32_t scene = 0; int32_t frame_count = 0; @@ -117,7 +119,7 @@ namespace rpg { std::string background; int32_t save_count = 0; int32_t save_slot = 1; - int32_t atb_mode = 0; + int32_t atb_mode = -1; std::vector maniac_strings; int32_t maniac_message_window_width = 0; int32_t maniac_message_window_height = 0; From b08f79d726ec8b9fd037bb46780df0eca2979c08 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Wed, 30 Jul 2025 20:27:38 +0200 Subject: [PATCH 3/3] Rename SaveOpt to LcfOpt (in a backward compatible way) and add Opt to both LSD save and load Is used to determine the correct default for the AtbMode depending on the engine version (2k3e or not) To ensure that the chunk is not always written conditionally set it to -1 when it is the default --- src/lcf/lsd/reader.h | 16 ++++++------ src/lcf/saveopt.h | 7 ++++-- src/lsd_reader.cpp | 59 +++++++++++++++++++++++++++++++++----------- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/lcf/lsd/reader.h b/src/lcf/lsd/reader.h index be7a8a18..edb32f6b 100644 --- a/src/lcf/lsd/reader.h +++ b/src/lcf/lsd/reader.h @@ -47,42 +47,42 @@ namespace LSD_Reader { /** * Loads Savegame. */ - std::unique_ptr Load(std::string_view filename, std::string_view encoding = ""); + std::unique_ptr Load(std::string_view filename, std::string_view encoding = "", LcfOpt opt = LcfOpt::eNone); /** * Saves Savegame. */ - bool Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding = ""); + bool Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding = "", LcfOpt opt = LcfOpt::eNone); /* * Saves Savegame as XML. */ - bool SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine); + bool SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine, LcfOpt opt = LcfOpt::eNone); /** * Loads Savegame as XML. */ - std::unique_ptr LoadXml(std::string_view filename); + std::unique_ptr LoadXml(std::string_view filename, LcfOpt opt = LcfOpt::eNone); /** * Loads Savegame. */ - std::unique_ptr Load(std::istream& filestream, std::string_view encoding = ""); + std::unique_ptr Load(std::istream& filestream, std::string_view encoding = "", LcfOpt opt = LcfOpt::eNone); /** * Saves Savegame. */ - bool Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding = ""); + bool Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding = "", LcfOpt opt = LcfOpt::eNone); /* * Saves Savegame as XML. */ - bool SaveXml(std::ostream& filestream, const rpg::Save& save, EngineVersion engine); + bool SaveXml(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, LcfOpt opt = LcfOpt::eNone); /** * Loads Savegame as XML. */ - std::unique_ptr LoadXml(std::istream& filestream); + std::unique_ptr LoadXml(std::istream& filestream, LcfOpt opt = LcfOpt::eNone); } } //namespace lcf diff --git a/src/lcf/saveopt.h b/src/lcf/saveopt.h index 7e7ae538..8b2070ff 100644 --- a/src/lcf/saveopt.h +++ b/src/lcf/saveopt.h @@ -16,11 +16,12 @@ class Database; }; /** - * Options to configure how LDB file is saved + * Options to configure how files are saved/loaded */ enum class SaveOpt { eNone = 0, - ePreserveHeader = 1 + ePreserveHeader = 1, + eEngine2k3e = 2 }; constexpr SaveOpt operator|(SaveOpt l, SaveOpt r) { return SaveOpt(int(l) | int(r)); } @@ -28,6 +29,8 @@ constexpr SaveOpt operator&(SaveOpt l, SaveOpt r) { return SaveOpt(int(l) & int( constexpr SaveOpt operator^(SaveOpt l, SaveOpt r) { return SaveOpt(int(l) ^ int(r)); } constexpr SaveOpt operator~(SaveOpt l) { return SaveOpt(~int(l)); } +using LcfOpt = SaveOpt; + /** * Which LCF file format to write */ diff --git a/src/lsd_reader.cpp b/src/lsd_reader.cpp index e26d3cc7..96c6aec4 100644 --- a/src/lsd_reader.cpp +++ b/src/lsd_reader.cpp @@ -16,6 +16,8 @@ #include "lcf/lsd/chunks.h" #include "lcf/rpg/save.h" #include "lcf/reader_util.h" +#include "lcf/rpg/savesystem.h" +#include "lcf/saveopt.h" #include "log.h" #include "reader_struct.h" @@ -41,43 +43,43 @@ void LSD_Reader::PrepareSave(rpg::Save& save, int32_t version, int32_t codepage) save.easyrpg_data.codepage = codepage; } -std::unique_ptr LSD_Reader::Load(std::string_view filename, std::string_view encoding) { +std::unique_ptr LSD_Reader::Load(std::string_view filename, std::string_view encoding, LcfOpt opt) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); return nullptr; } - return LSD_Reader::Load(stream, encoding); + return LSD_Reader::Load(stream, encoding, opt); } -bool LSD_Reader::Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding) { +bool LSD_Reader::Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding, LcfOpt opt) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); return false; } - return LSD_Reader::Save(stream, save, engine, encoding); + return LSD_Reader::Save(stream, save, engine, encoding, opt); } -bool LSD_Reader::SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine) { +bool LSD_Reader::SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine, LcfOpt opt) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD XML file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); return false; } - return LSD_Reader::SaveXml(stream, save, engine); + return LSD_Reader::SaveXml(stream, save, engine, opt); } -std::unique_ptr LSD_Reader::LoadXml(std::string_view filename) { +std::unique_ptr LSD_Reader::LoadXml(std::string_view filename, LcfOpt opt) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD XML file `%s' for reading : %s", ToString(filename).c_str(), strerror(errno)); return nullptr; } - return LSD_Reader::LoadXml(stream); + return LSD_Reader::LoadXml(stream, opt); } -std::unique_ptr LSD_Reader::Load(std::istream& filestream, std::string_view encoding) { +std::unique_ptr LSD_Reader::Load(std::istream& filestream, std::string_view encoding, LcfOpt opt) { LcfReader reader(filestream, ToString(encoding)); if (!reader.IsOk()) { @@ -111,10 +113,14 @@ std::unique_ptr LSD_Reader::Load(std::istream& filestream, std::strin Struct::ReadLcf(*save, reader2); } + if (save->system.atb_mode == rpg::SaveSystem::AtbMode_atb_unspecified) { + save->system.atb_mode = ((opt & LcfOpt::eEngine2k3e) == LcfOpt::eEngine2k3e) ? rpg::SaveSystem::AtbMode_atb_wait : rpg::SaveSystem::AtbMode_atb_active; + } + return save; } -bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding) { +bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding, LcfOpt opt) { std::string enc; if (save.easyrpg_data.codepage > 0) { @@ -132,24 +138,44 @@ bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVer writer.WriteInt(header.size()); writer.Write(header); - Struct::WriteLcf(save, writer); + auto savegame = save; + + if ((opt & LcfOpt::eEngine2k3e) == LcfOpt::eEngine2k3e) { + if (savegame.system.atb_mode == rpg::SaveSystem::AtbMode_atb_wait) { + savegame.system.atb_mode = rpg::SaveSystem::AtbMode_atb_unspecified; + } + } else if (savegame.system.atb_mode == rpg::SaveSystem::AtbMode_atb_active) { + savegame.system.atb_mode = rpg::SaveSystem::AtbMode_atb_unspecified; + } + + Struct::WriteLcf(savegame, writer); return true; } -bool LSD_Reader::SaveXml(std::ostream& filestream, const rpg::Save& save, EngineVersion engine) { +bool LSD_Reader::SaveXml(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, LcfOpt opt) { XmlWriter writer(filestream, engine); if (!writer.IsOk()) { LcfReader::SetError("Couldn't parse save file."); return false; } + auto savegame = save; + + if ((opt & LcfOpt::eEngine2k3e) == LcfOpt::eEngine2k3e) { + if (savegame.system.atb_mode == rpg::SaveSystem::AtbMode_atb_wait) { + savegame.system.atb_mode = rpg::SaveSystem::AtbMode_atb_unspecified; + } + } else if (savegame.system.atb_mode == rpg::SaveSystem::AtbMode_atb_active) { + savegame.system.atb_mode = rpg::SaveSystem::AtbMode_atb_unspecified; + } + writer.BeginElement("LSD"); - Struct::WriteXml(save, writer); + Struct::WriteXml(savegame, writer); writer.EndElement("LSD"); return true; } -std::unique_ptr LSD_Reader::LoadXml(std::istream& filestream) { +std::unique_ptr LSD_Reader::LoadXml(std::istream& filestream, LcfOpt opt) { XmlReader reader(filestream); if (!reader.IsOk()) { LcfReader::SetError("Couldn't parse save file."); @@ -159,6 +185,11 @@ std::unique_ptr LSD_Reader::LoadXml(std::istream& filestream) { rpg::Save* save = new rpg::Save(); reader.SetHandler(new RootXmlHandler(*save, "LSD")); reader.Parse(); + + if (save->system.atb_mode == rpg::SaveSystem::AtbMode_atb_unspecified) { + save->system.atb_mode = ((opt & LcfOpt::eEngine2k3e) == LcfOpt::eEngine2k3e) ? rpg::SaveSystem::AtbMode_atb_wait : rpg::SaveSystem::AtbMode_atb_active; + } + return std::unique_ptr(save); }