diff --git a/liberty/Makefile b/liberty/Makefile index 24b7d5b6..a3adc51a 100644 --- a/liberty/Makefile +++ b/liberty/Makefile @@ -187,6 +187,10 @@ $(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR mkdir -p $(@D) cp $< $@ +$(REPACK_GTA_DIR)/%.ico: assets/%.ico + mkdir -p $(@D) + cp $< $@ + 1ST_READ.BIN: $(TARGET) rm -f $(TARGET).bin rm -f 1ST_READ.BIN @@ -202,20 +206,20 @@ IP.BIN: rm -f IP.BIN $(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN -$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME).iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ.BIN $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) -$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME)-no-repack.iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ.BIN $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR) -$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME).ds.iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN @@ -226,7 +230,7 @@ $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_ $(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN mkdir -p $(REPACK_GTA_DIR) -$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) @@ -245,15 +249,15 @@ $(PROJECT_NAME)-prebuilt.cdi: $(PROJECT_NAME)-prebuilt.iso rm 1ST_READ_PREBUILT.BIN @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo else -$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo -$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo -$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo endif diff --git a/liberty/assets/settings.ico b/liberty/assets/settings.ico new file mode 100644 index 00000000..5230be86 Binary files /dev/null and b/liberty/assets/settings.ico differ diff --git a/miami/Makefile b/miami/Makefile index 45f11bbd..b36e127e 100644 --- a/miami/Makefile +++ b/miami/Makefile @@ -191,6 +191,10 @@ $(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR mkdir -p $(@D) cp $< $@ +$(REPACK_GTA_DIR)/%.ico: assets/%.ico + mkdir -p $(@D) + cp $< $@ + 1ST_READ.BIN: $(TARGET) rm -f $(TARGET).bin rm -f 1ST_READ.BIN @@ -206,20 +210,20 @@ IP.BIN: rm -f IP.BIN $(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN -$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME).iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ.BIN $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) -$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME)-no-repack.iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ.BIN $(REPACK_GTA_DIR) mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR) -$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(PROJECT_NAME).ds.iso rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN @@ -230,7 +234,7 @@ $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_ $(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN mkdir -p $(REPACK_GTA_DIR) -$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR) @@ -249,15 +253,15 @@ $(PROJECT_NAME)-prebuilt.cdi: $(PROJECT_NAME)-prebuilt.iso rm 1ST_READ_PREBUILT.BIN @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo else -$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo -$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo -$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR +$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE) @echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo endif diff --git a/miami/assets/settings.ico b/miami/assets/settings.ico new file mode 100644 index 00000000..3e49b097 Binary files /dev/null and b/miami/assets/settings.ico differ diff --git a/src/liberty/extras/ini.h b/src/liberty/extras/ini.h index 44dd3d57..6e156e12 100644 --- a/src/liberty/extras/ini.h +++ b/src/liberty/extras/ini.h @@ -94,6 +94,10 @@ #include #include +#ifdef DC_SH4 +#include +#endif + namespace mINI { namespace INIStringUtil @@ -335,6 +339,7 @@ namespace mINI private: std::ifstream fileReadStream; T_LineDataPtr lineData; + std::size_t start_offt; T_LineData readFile() { @@ -343,7 +348,7 @@ namespace mINI fileContents.resize(fileReadStream.tellg()); fileReadStream.seekg(0, std::ios::beg); std::size_t fileSize = fileContents.size(); - fileReadStream.read(&fileContents[0], fileSize); + fileReadStream.read(const_cast(fileContents.c_str()), fileSize); fileReadStream.close(); T_LineData output; if (fileSize == 0) @@ -352,7 +357,19 @@ namespace mINI } std::string buffer; buffer.reserve(50); - for (std::size_t i = 0; i < fileSize; ++i) +#ifdef DC_SH4 + { + vmu_pkg_t vmu_pkg; + if(vmu_pkg_parse(reinterpret_cast(const_cast(fileContents.c_str())), &vmu_pkg) != 0) { + // If we failed to parse, we assume it's raw with no VMS header. + start_offt = 0; + } else { + start_offt = reinterpret_cast(vmu_pkg.data) + - reinterpret_cast(fileContents.c_str()); + } + } +#endif + for (std::size_t i = start_offt; i < fileSize; ++i) { char& c = fileContents[i]; if (c == '\n') @@ -378,6 +395,8 @@ namespace mINI { lineData = std::make_shared(); } + + start_offt = 0; } ~INIReader() { } @@ -426,22 +445,71 @@ namespace mINI { private: std::ofstream fileWriteStream; - + std::stringstream memStream; + inline static std::ios_base::iostate lastError_; public: bool prettyPrint = false; - INIGenerator(std::string const& filename) + INIGenerator(std::string const& filename, bool prettyPrint_=false) + : fileWriteStream(filename, std::ios::out | std::ios::binary), + prettyPrint(prettyPrint_) { - fileWriteStream.open(filename, std::ios::out | std::ios::binary); + lastError_ = fileWriteStream.rdstate(); + } + + ~INIGenerator() + { + if(!fileWriteStream.good()) { + return; + } + + std::string str = memStream.str(); + const char *buf = str.c_str(); + int buf_size = memStream.tellp(); + +#ifdef DC_SH4 + uint8_t *data; + uint8_t icon_buf[512 * 1]; + vmu_pkg_t vmu_pkg = { + .desc_short = "DCA-L Config", + .desc_long = "DCA-L Settings File", + .app_id = "The Gang", + .icon_cnt = 1, + .icon_anim_speed = 0, + .data_len = buf_size, + .icon_data = icon_buf, + .data = reinterpret_cast(buf), + }; + + if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) { + vmu_pkg.icon_cnt = 0; + } + + if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) { + lastError_ = std::ios_base::badbit; + return; + } + + buf = reinterpret_cast(data); +#endif + + fileWriteStream.write(buf, buf_size); + lastError_ = fileWriteStream.rdstate(); + +#ifdef DC_SH4 + // Must free the internal buffer allocated by vmu_pkg_build(). + free(data); +#endif + } + + bool operator<<(const std::string& str) + { + memStream << str; + return true; } - ~INIGenerator() { } bool operator<<(INIStructure const& data) { - if (!fileWriteStream.is_open()) - { - return false; - } if (!data.size()) { return true; @@ -451,13 +519,13 @@ namespace mINI { auto const& section = it->first; auto const& collection = it->second; - fileWriteStream + memStream << "[" << section << "]"; if (collection.size()) { - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; auto it2 = collection.begin(); for (;;) { @@ -465,7 +533,7 @@ namespace mINI INIStringUtil::replace(key, "=", "\\="); auto value = it2->second; INIStringUtil::trim(value); - fileWriteStream + memStream << key << ((prettyPrint) ? " = " : "=") << value; @@ -473,21 +541,29 @@ namespace mINI { break; } - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; } } if (++it == data.end()) { break; } - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; if (prettyPrint) { - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; } } return true; } + + operator bool() const + { + return fileWriteStream.rdstate() == fileWriteStream.goodbit; + } + + static std::ios_base::iostate lastError() { return lastError_; } + static bool wasGood() { return lastError_ == std::ios_base::goodbit; } }; class INIWriter @@ -667,12 +743,15 @@ namespace mINI { struct stat buf; bool fileExists = (stat(filename.c_str(), &buf) == 0); + if (!fileExists) { - INIGenerator generator(filename); - generator.prettyPrint = prettyPrint; - return generator << data; + if(INIGenerator generator(filename, prettyPrint); generator) { + generator << data; + } + return INIGenerator::wasGood(); } + INIStructure originalData; T_LineDataPtr lineData; bool readSuccess = false; @@ -688,23 +767,21 @@ namespace mINI return false; } T_LineData output = getLazyOutput(lineData, data, originalData); - std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); - if (fileWriteStream.is_open()) { - if (output.size()) + if (INIGenerator generator(filename, prettyPrint); generator && output.size()) { auto line = output.begin(); for (;;) { - fileWriteStream << *line; + generator << *line; if (++line == output.end()) { break; } - fileWriteStream << INIStringUtil::endl; + generator << INIStringUtil::endl; } } - return true; + return INIGenerator::wasGood(); } return false; } @@ -741,9 +818,10 @@ namespace mINI { return false; } - INIGenerator generator(filename); - generator.prettyPrint = pretty; - return generator << data; + if(INIGenerator generator(filename, pretty); generator) { + generator << data; + } + return INIGenerator::wasGood(); } bool write(INIStructure& data, bool pretty = false) const { diff --git a/src/miami/core/re3.cpp b/src/miami/core/re3.cpp index d3a6b471..78b60402 100644 --- a/src/miami/core/re3.cpp +++ b/src/miami/core/re3.cpp @@ -59,6 +59,8 @@ #include +#include "vmu/vmu.h" + #ifdef RWLIBS extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList); #endif @@ -195,7 +197,13 @@ CustomFrontendOptionsPopulate(void) #define MINI_CASE_SENSITIVE #include "ini.h" -mINI::INIFile ini("reVC.ini"); +mINI::INIFile ini( +#ifdef DC_SIM + "reVC.ini" +#else + "/vmu/" VMU_DEFAULT_PATH "/reVCini" +#endif +); mINI::INIStructure cfg; bool ReadIniIfExists(const char *cat, const char *key, uint32 *out) @@ -483,13 +491,19 @@ void SaveINIControllerSettings() #endif StoreIni("Controller", "PadButtonsInited", ControlsManager.ms_padButtonsInited); - ini.write(cfg); + { + RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f); + ini.write(cfg); + } } bool LoadINISettings() { - if (!ini.read(cfg)) - return false; + { + RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f); + if (!ini.read(cfg)) + return false; + } #ifdef IMPROVED_VIDEOMODE ReadIniIfExists("VideoMode", "Width", &FrontEndMenuManager.m_nPrefsWidth); diff --git a/src/miami/extras/ini.h b/src/miami/extras/ini.h index 44dd3d57..b4c9d6a2 100644 --- a/src/miami/extras/ini.h +++ b/src/miami/extras/ini.h @@ -94,6 +94,10 @@ #include #include +#ifdef DC_SH4 +#include +#endif + namespace mINI { namespace INIStringUtil @@ -335,6 +339,7 @@ namespace mINI private: std::ifstream fileReadStream; T_LineDataPtr lineData; + std::size_t start_offt; T_LineData readFile() { @@ -343,7 +348,7 @@ namespace mINI fileContents.resize(fileReadStream.tellg()); fileReadStream.seekg(0, std::ios::beg); std::size_t fileSize = fileContents.size(); - fileReadStream.read(&fileContents[0], fileSize); + fileReadStream.read(const_cast(fileContents.c_str()), fileSize); fileReadStream.close(); T_LineData output; if (fileSize == 0) @@ -352,7 +357,19 @@ namespace mINI } std::string buffer; buffer.reserve(50); - for (std::size_t i = 0; i < fileSize; ++i) +#ifdef DC_SH4 + { + vmu_pkg_t vmu_pkg; + if(vmu_pkg_parse(reinterpret_cast(const_cast(fileContents.c_str())), &vmu_pkg) != 0) { + // If we failed to parse, we assume it's raw with no VMS header. + start_offt = 0; + } else { + start_offt = reinterpret_cast(vmu_pkg.data) + - reinterpret_cast(fileContents.c_str()); + } + } +#endif + for (std::size_t i = start_offt; i < fileSize; ++i) { char& c = fileContents[i]; if (c == '\n') @@ -378,6 +395,8 @@ namespace mINI { lineData = std::make_shared(); } + + start_offt = 0; } ~INIReader() { } @@ -426,22 +445,71 @@ namespace mINI { private: std::ofstream fileWriteStream; - + std::stringstream memStream; + inline static std::ios_base::iostate lastError_; public: bool prettyPrint = false; - INIGenerator(std::string const& filename) + INIGenerator(std::string const& filename, bool prettyPrint_=false) + : fileWriteStream(filename, std::ios::out | std::ios::binary), + prettyPrint(prettyPrint_) { - fileWriteStream.open(filename, std::ios::out | std::ios::binary); + lastError_ = fileWriteStream.rdstate(); + } + + ~INIGenerator() + { + if(!fileWriteStream.good()) { + return; + } + + std::string str = memStream.str(); + const char *buf = str.c_str(); + int buf_size = memStream.tellp(); + +#ifdef DC_SH4 + uint8_t *data; + uint8_t icon_buf[512 * 1]; + vmu_pkg_t vmu_pkg = { + .desc_short = "DCA-M Config", + .desc_long = "DCA-M Settings File", + .app_id = "The Gang", + .icon_cnt = 1, + .icon_anim_speed = 0, + .data_len = buf_size, + .icon_data = icon_buf, + .data = reinterpret_cast(buf), + }; + + if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) { + vmu_pkg.icon_cnt = 0; + } + + if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) { + lastError_ = std::ios_base::badbit; + return; + } + + buf = reinterpret_cast(data); +#endif + + fileWriteStream.write(buf, buf_size); + lastError_ = fileWriteStream.rdstate(); + +#ifdef DC_SH4 + // Must free the internal buffer allocated by vmu_pkg_build(). + free(data); +#endif + } + + bool operator<<(const std::string& str) + { + memStream << str; + return true; } - ~INIGenerator() { } bool operator<<(INIStructure const& data) { - if (!fileWriteStream.is_open()) - { - return false; - } if (!data.size()) { return true; @@ -451,13 +519,13 @@ namespace mINI { auto const& section = it->first; auto const& collection = it->second; - fileWriteStream + memStream << "[" << section << "]"; if (collection.size()) { - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; auto it2 = collection.begin(); for (;;) { @@ -465,7 +533,7 @@ namespace mINI INIStringUtil::replace(key, "=", "\\="); auto value = it2->second; INIStringUtil::trim(value); - fileWriteStream + memStream << key << ((prettyPrint) ? " = " : "=") << value; @@ -473,21 +541,29 @@ namespace mINI { break; } - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; } } if (++it == data.end()) { break; } - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; if (prettyPrint) { - fileWriteStream << INIStringUtil::endl; + memStream << INIStringUtil::endl; } } return true; } + + operator bool() const + { + return fileWriteStream.rdstate() == fileWriteStream.goodbit; + } + + static std::ios_base::iostate lastError() { return lastError_; } + static bool wasGood() { return lastError_ == std::ios_base::goodbit; } }; class INIWriter @@ -667,12 +743,15 @@ namespace mINI { struct stat buf; bool fileExists = (stat(filename.c_str(), &buf) == 0); + if (!fileExists) { - INIGenerator generator(filename); - generator.prettyPrint = prettyPrint; - return generator << data; + if(INIGenerator generator(filename, prettyPrint); generator) { + generator << data; + } + return INIGenerator::wasGood(); } + INIStructure originalData; T_LineDataPtr lineData; bool readSuccess = false; @@ -688,23 +767,21 @@ namespace mINI return false; } T_LineData output = getLazyOutput(lineData, data, originalData); - std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); - if (fileWriteStream.is_open()) { - if (output.size()) + if (INIGenerator generator(filename, prettyPrint); generator && output.size()) { auto line = output.begin(); for (;;) { - fileWriteStream << *line; + generator << *line; if (++line == output.end()) { break; } - fileWriteStream << INIStringUtil::endl; + generator << INIStringUtil::endl; } } - return true; + return INIGenerator::wasGood(); } return false; } @@ -741,9 +818,10 @@ namespace mINI { return false; } - INIGenerator generator(filename); - generator.prettyPrint = pretty; - return generator << data; + if(INIGenerator generator(filename, pretty); generator) { + generator << data; + } + return INIGenerator::wasGood(); } bool write(INIStructure& data, bool pretty = false) const {