From 7fa0af77dea4c6389c4e3132a73af7338116e3a8 Mon Sep 17 00:00:00 2001 From: BernardoGiordano Date: Thu, 25 Jun 2026 20:08:17 +0200 Subject: [PATCH] Remove cheats feature (fix #539, close #357, close #376, close #361) --- .gitmodules | 3 - 3ds/Makefile | 22 +--- 3ds/include/CheatManagerOverlay.hpp | 66 ----------- 3ds/include/MainScreen.hpp | 3 +- 3ds/include/cheatmanager.hpp | 63 ----------- 3ds/include/main.hpp | 2 - 3ds/source/CheatManagerOverlay.cpp | 150 ------------------------- 3ds/source/MainScreen.cpp | 27 ----- 3ds/source/cheatmanager.cpp | 103 ----------------- 3ds/source/util.cpp | 1 - Makefile | 21 +--- sharkive | 1 - switch/Makefile | 20 +--- switch/include/CheatManagerOverlay.hpp | 63 ----------- switch/include/MainScreen.hpp | 3 +- switch/include/cheatmanager.hpp | 65 ----------- switch/include/main.hpp | 2 - switch/source/CheatManagerOverlay.cpp | 143 ----------------------- switch/source/MainScreen.cpp | 26 ----- switch/source/cheatmanager.cpp | 113 ------------------- 20 files changed, 13 insertions(+), 884 deletions(-) delete mode 100644 3ds/include/CheatManagerOverlay.hpp delete mode 100644 3ds/include/cheatmanager.hpp delete mode 100644 3ds/source/CheatManagerOverlay.cpp delete mode 100644 3ds/source/cheatmanager.cpp delete mode 160000 sharkive delete mode 100644 switch/include/CheatManagerOverlay.hpp delete mode 100644 switch/include/cheatmanager.hpp delete mode 100644 switch/source/CheatManagerOverlay.cpp delete mode 100644 switch/source/cheatmanager.cpp diff --git a/.gitmodules b/.gitmodules index 0533977d..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "sharkive"] - path = sharkive - url = https://github.com/FlagBrew/sharkive diff --git a/3ds/Makefile b/3ds/Makefile index 4a0066a6..ff3a4549 100644 --- a/3ds/Makefile +++ b/3ds/Makefile @@ -46,8 +46,6 @@ INCLUDES := $(FORMATINCLUDES) ../3rd-party/json ../3rd-party/sha256 GRAPHICS := assets/gfx ROMFS := assets/romfs GFXBUILD := $(ROMFS)/gfx -SHARKIVE := ../sharkive -CHEATS := cheats # If left blank, will try to use "icon.png", "$(TARGET).png", or the default ctrulib icon, in that order ICON := assets/icon.png @@ -81,8 +79,7 @@ CFLAGS := -g -gdwarf-4 -Wall -Wextra -Wno-psabi -O3 -mword-relocations -flto=aut -DVERSION_MICRO=${VERSION_MICRO} \ -DGIT_REV=\"${GIT_REV}\" \ -DJSON_HAS_FILESYSTEM=0 \ - -DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0 \ - -DCHEAT_SIZE_DECOMPRESSED=${CHEAT_SIZE_DECOMPRESSED} + -DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0 CFLAGS += $(INCLUDE) -DARM11 -D__3DS__ -D_GNU_SOURCE=1 @@ -91,7 +88,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++23 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lbz2 -lcitro2d -lcitro3d -lctru -lm +LIBS := -lcitro2d -lcitro3d -lctru -lm CCACHE := $(shell command -v ccache 2>/dev/null) ifneq ($(strip $(CCACHE)),) @@ -186,10 +183,10 @@ ifneq ($(ROMFS),) export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) endif -.PHONY: all clean format cheats +.PHONY: all clean format #--------------------------------------------------------------------------------- -all: cheats sprites +all: sprites @mkdir -p $(BUILD) $(GFXBUILD) $(OUTDIR) @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile $(OUTPUT).3dsx @bannertool makebanner -i "$(BANNER_IMAGE)" -a "$(BANNER_AUDIO)" -o $(BUILD)/banner.bnr @@ -198,16 +195,7 @@ all: cheats sprites #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(GFXBUILD) $(OUTDIR) $(ROMFS)/$(CHEATS) -#--------------------------------------------------------------------------------- -cheats: - @mkdir -p $(BUILD) $(ROMFS)/$(CHEATS) -ifeq ($(OS),Windows_NT) - @cd $(SHARKIVE) && py -3 joiner.py 3ds -else - @cd $(SHARKIVE) && python3 joiner.py 3ds -endif - @cd $(SHARKIVE)/$(BUILD) && mv 3ds.json.bz2 ../../3ds/$(ROMFS)/$(CHEATS)/$(CHEATS).json.bz2 + @rm -fr $(BUILD) $(GFXBUILD) $(OUTDIR) #--------------------------------------------------------------------------------- sprites: @mkdir -p $(BUILD) $(GFXBUILD) diff --git a/3ds/include/CheatManagerOverlay.hpp b/3ds/include/CheatManagerOverlay.hpp deleted file mode 100644 index 2e2a27b2..00000000 --- a/3ds/include/CheatManagerOverlay.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#ifndef CHEATMANAGEROVERLAY_HPP -#define CHEATMANAGEROVERLAY_HPP - -#include "Overlay.hpp" -#include "YesNoOverlay.hpp" -#include "cheatmanager.hpp" -#include "colors.hpp" -#include "directory.hpp" -#include "scrollable.hpp" -#include -#include - -class Clickable; -class Scrollable; - -class CheatManagerOverlay : public Overlay { -public: - CheatManagerOverlay(Screen& screen, const std::string& mtext); - ~CheatManagerOverlay(void); - void drawTop(void) const override; - void drawBottom(void) const override; - void update(const InputState& input) override; - -protected: - void save(const std::string& key, Scrollable* s); - -private: - bool multiSelected; - std::string existingCheat; - std::string key; - const size_t MAGIC_LEN = strlen(SELECTED_MAGIC); - std::shared_ptr scrollable; - size_t currentIndex; - const float scale = 0.47f; - - C2D_Text multiSelectText, multiDeselectText; - C2D_TextBuf staticBuf, dynamicBuf; -}; - -#endif \ No newline at end of file diff --git a/3ds/include/MainScreen.hpp b/3ds/include/MainScreen.hpp index adf9a530..617e846b 100644 --- a/3ds/include/MainScreen.hpp +++ b/3ds/include/MainScreen.hpp @@ -27,7 +27,6 @@ #ifndef MAINSCREEN_HPP #define MAINSCREEN_HPP -#include "CheatManagerOverlay.hpp" #include "ErrorOverlay.hpp" #include "InfoOverlay.hpp" #include "Screen.hpp" @@ -68,7 +67,7 @@ class MainScreen : public Screen { private: Hid hid; - std::unique_ptr buttonBackup, buttonRestore, buttonCheats, buttonPlayCoins, buttonTransfer; + std::unique_ptr buttonBackup, buttonRestore, buttonPlayCoins, buttonTransfer; std::unique_ptr directoryList; char ver[10]; diff --git a/3ds/include/cheatmanager.hpp b/3ds/include/cheatmanager.hpp deleted file mode 100644 index 7cc13546..00000000 --- a/3ds/include/cheatmanager.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#ifndef CHEATMANAGER_HPP -#define CHEATMANAGER_HPP - -#include "io.hpp" -#include "json.hpp" -#include "main.hpp" -#include <3ds.h> -#include -#include -#include - -#define SELECTED_MAGIC "\uE071 " - -class CheatManager { -public: - static CheatManager& getInstance(void) - { - static CheatManager mCheatManager; - return mCheatManager; - } - - bool areCheatsAvailable(const std::string& key); - void save(const std::string& key, const std::vector& s); - - std::shared_ptr cheats(void) { return mCheats; } - -private: - CheatManager(void); - ~CheatManager() = default; - - CheatManager(CheatManager const&) = delete; - void operator=(CheatManager const&) = delete; - - std::shared_ptr mCheats; -}; - -#endif \ No newline at end of file diff --git a/3ds/include/main.hpp b/3ds/include/main.hpp index 3bb14103..c9963cac 100644 --- a/3ds/include/main.hpp +++ b/3ds/include/main.hpp @@ -40,7 +40,5 @@ inline std::shared_ptr g_screen = nullptr; inline bool g_bottomScrollEnabled = false; inline float g_timer = 0; -inline std::string g_selectedCheatKey; -inline std::vector g_selectedCheatCodes; #endif diff --git a/3ds/source/CheatManagerOverlay.cpp b/3ds/source/CheatManagerOverlay.cpp deleted file mode 100644 index b81e4480..00000000 --- a/3ds/source/CheatManagerOverlay.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#include "CheatManagerOverlay.hpp" - -CheatManagerOverlay::CheatManagerOverlay(Screen& screen, const std::string& mkey) : Overlay(screen) -{ - key = mkey; - multiSelected = false; - std::string existingCheat = ""; - - FILE* f = fopen(("/cheats/" + key + ".txt").c_str(), "r"); - if (f != NULL) { - fseek(f, 0, SEEK_END); - u32 size = ftell(f); - char* s = new char[size]; - rewind(f); - fread(s, 1, size, f); - existingCheat = std::string(s); - delete[] s; - fclose(f); - } - - size_t i = 0; - currentIndex = i; - scrollable = std::make_unique(2, 2, 396, 220, 11); - auto cheats = *CheatManager::getInstance().cheats().get(); - for (auto it = cheats[key].begin(); it != cheats[key].end(); ++it) { - std::string value = it.key(); - if (existingCheat.find(value) != std::string::npos) { - value = SELECTED_MAGIC + value; - } - scrollable->push_back(COLOR_BLACK_DARK, COLOR_WHITE, value, i == 0); - i++; - } - - staticBuf = C2D_TextBufNew(48); - dynamicBuf = C2D_TextBufNew(16); - C2D_TextParse(&multiSelectText, staticBuf, "\uE003 to select all cheats"); - C2D_TextParse(&multiDeselectText, staticBuf, "\uE003 to deselect all cheats"); - C2D_TextOptimize(&multiSelectText); - C2D_TextOptimize(&multiDeselectText); -} - -CheatManagerOverlay::~CheatManagerOverlay(void) -{ - C2D_TextBufDelete(staticBuf); - C2D_TextBufDelete(dynamicBuf); -} - -void CheatManagerOverlay::drawTop(void) const -{ - C2D_TextBufClear(dynamicBuf); - - C2D_DrawRectSolid(0, 0, 0.5f, 400, 240, COLOR_OVERLAY); - C2D_Text page; - C2D_TextParse(&page, dynamicBuf, StringUtils::format("%d/%d", scrollable->index() + 1, scrollable->size()).c_str()); - C2D_TextOptimize(&page); - C2D_DrawRectSolid(0, 0, 0.5f, 400, 240, COLOR_BLACK_DARKERR); - scrollable->draw(true); - C2D_DrawText(&page, C2D_WithColor, ceilf(396 - page.width * scale), 224, 0.5f, scale, scale, COLOR_WHITE); - C2D_DrawText(multiSelected ? &multiDeselectText : &multiSelectText, C2D_WithColor, 4, 224, 0.5f, scale, scale, COLOR_WHITE); -} - -void CheatManagerOverlay::drawBottom(void) const -{ - C2D_DrawRectSolid(0, 0, 0.5f, 320, 240, COLOR_OVERLAY); -} - -void CheatManagerOverlay::update(const InputState& input) -{ - (void)input; - if (hidKeysDown() & KEY_A) { - std::string cellName = scrollable->cellName(scrollable->index()); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - // cheat was already selected - cellName = cellName.substr(strlen(SELECTED_MAGIC), cellName.length()); - } - else { - cellName = SELECTED_MAGIC + cellName; - } - scrollable->c2dText(scrollable->index(), cellName); - } - - if (hidKeysDown() & KEY_Y) { - if (multiSelected) { - for (size_t j = 0; j < scrollable->size(); j++) { - std::string cellName = scrollable->cellName(j); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - cellName = cellName.substr(strlen(SELECTED_MAGIC), cellName.length()); - scrollable->c2dText(j, cellName); - } - } - multiSelected = false; - } - else { - for (size_t j = 0; j < scrollable->size(); j++) { - std::string cellName = scrollable->cellName(j); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) != 0) { - cellName = SELECTED_MAGIC + cellName; - scrollable->c2dText(j, cellName); - } - } - multiSelected = true; - } - } - - scrollable->updateSelection(); - scrollable->selectRow(currentIndex, false); - scrollable->selectRow(scrollable->index(), true); - currentIndex = scrollable->index(); - - if (hidKeysDown() & KEY_B) { - g_selectedCheatKey = key; - g_selectedCheatCodes.clear(); - for (size_t i = 0; i < scrollable->size(); i++) { - g_selectedCheatCodes.push_back(scrollable->cellName(i)); - } - me = std::make_shared( - screen, "Do you want to store\nthe cheat file?", - []() { - CheatManager::getInstance().save(g_selectedCheatKey, g_selectedCheatCodes); - g_screen->removeOverlay(); - }, - []() { g_screen->removeOverlay(); }); - } -} \ No newline at end of file diff --git a/3ds/source/MainScreen.cpp b/3ds/source/MainScreen.cpp index 03e66594..0acf6953 100644 --- a/3ds/source/MainScreen.cpp +++ b/3ds/source/MainScreen.cpp @@ -121,13 +121,11 @@ MainScreen::MainScreen(void) : hid(rowlen * collen, collen) buttonBackup = std::make_unique(204, 102, 110, 35, COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT, "Backup \uE004", true); buttonRestore = std::make_unique(204, 139, 110, 35, COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT, "Restore \uE005", true); - buttonCheats = std::make_unique(204, 176, 110, 36, COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT, "Cheats", true); buttonPlayCoins = std::make_unique(204, 176, 110, 36, COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT, "\uE075 Coins", true); buttonTransfer = std::make_unique(4, 223, 110, 16, COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT, "Transfer", true); directoryList = std::make_unique(6, 102, 196, 110, 5); buttonBackup->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(true); - buttonCheats->canChangeColorWhenSelected(true); buttonPlayCoins->canChangeColorWhenSelected(true); buttonTransfer->canChangeColorWhenSelected(true); @@ -377,9 +375,6 @@ void MainScreen::drawBottom(void) const if (title.isActivityLog()) { buttonPlayCoins->draw(0.7, COLOR_PURPLE_LIGHT); } - else { - buttonCheats->draw(0.7, COLOR_PURPLE_LIGHT); - } } if (transferEnabled) { @@ -786,23 +781,6 @@ void MainScreen::handleEvents(const InputState& input) currentOverlay = std::make_shared(*this, -1, "Failed to set play coins."); } } - else { - if (buttonCheats->released() && CheatManager::getInstance().cheats() != nullptr) { - if (MS::multipleSelectionEnabled()) { - MS::clearSelectedEntries(); - updateButtons(); - } - else { - std::string key = StringUtils::format("%016llX", title.id()); - if (CheatManager::getInstance().areCheatsAvailable(key)) { - currentOverlay = std::make_shared(*this, key); - } - else { - currentOverlay = std::make_shared(*this, "No available cheat codes for this title."); - } - } - } - } } } @@ -839,27 +817,22 @@ void MainScreen::updateButtons(void) if (MS::multipleSelectionEnabled()) { buttonRestore->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(false); - buttonCheats->canChangeColorWhenSelected(false); buttonPlayCoins->canChangeColorWhenSelected(false); buttonBackup->setColors(COLOR_BLACK_DARKERR, COLOR_WHITE); buttonRestore->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); - buttonCheats->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); buttonPlayCoins->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); } else if (g_bottomScrollEnabled) { buttonBackup->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(true); - buttonCheats->canChangeColorWhenSelected(true); buttonPlayCoins->canChangeColorWhenSelected(true); buttonBackup->setColors(COLOR_BLACK_DARKERR, COLOR_WHITE); buttonRestore->setColors(COLOR_BLACK_DARKERR, COLOR_WHITE); - buttonCheats->setColors(COLOR_BLACK_DARKERR, COLOR_WHITE); buttonPlayCoins->setColors(COLOR_BLACK_DARKERR, COLOR_WHITE); } else { buttonBackup->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); buttonRestore->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); - buttonCheats->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); buttonPlayCoins->setColors(COLOR_BLACK_DARKERR, COLOR_GREY_LIGHT); } } diff --git a/3ds/source/cheatmanager.cpp b/3ds/source/cheatmanager.cpp deleted file mode 100644 index 063245f8..00000000 --- a/3ds/source/cheatmanager.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#include "cheatmanager.hpp" - -CheatManager::CheatManager(void) -{ - mCheats = nullptr; - if (io::fileExists("/3ds/Checkpoint/cheats.json")) { - const std::string path = "/3ds/Checkpoint/cheats.json"; - FILE* in = fopen(path.c_str(), "rt"); - if (in != NULL) { - mCheats = std::make_shared(nlohmann::json::parse(in, nullptr, false)); - fclose(in); - } - else { - Logging::warning("Failed to open {} with errno {}.", path, errno); - } - } - else { - const std::string path = "romfs:/cheats/cheats.json.bz2"; - // load compressed archive in memory - FILE* f = fopen(path.c_str(), "rb"); - if (f != NULL) { - fseek(f, 0, SEEK_END); - u32 size = ftell(f); - unsigned int destLen = CHEAT_SIZE_DECOMPRESSED; - char* s = new char[size]; - char* d = new char[destLen + 1](); - rewind(f); - fread(s, 1, size, f); - - int r = BZ2_bzBuffToBuffDecompress(d, &destLen, s, size, 0, 0); - if (r == BZ_OK) { - mCheats = std::make_shared(nlohmann::json::parse(d)); - } - - delete[] s; - delete[] d; - fclose(f); - } - else { - Logging::warning("Failed to open {} with errno {}.", path, errno); - } - } -} - -bool CheatManager::areCheatsAvailable(const std::string& key) -{ - return mCheats->find(key) != mCheats->end(); -} - -void CheatManager::save(const std::string& key, const std::vector& s) -{ - static size_t MAGIC_LEN = strlen(SELECTED_MAGIC); - - std::string cheatFile = ""; - auto cheats = *CheatManager::getInstance().cheats().get(); - for (size_t i = 0; i < s.size(); i++) { - std::string cellName = s.at(i); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - cellName = cellName.substr(MAGIC_LEN, cellName.length()); - cheatFile += "[" + cellName + "]\n"; - for (auto& it : cheats[key][cellName]) { - cheatFile += it.get() + "\n"; - } - cheatFile += "\n"; - } - } - - const std::string outPath = "/cheats/" + key + ".txt"; - FILE* f = fopen(outPath.c_str(), "w"); - if (f != NULL) { - fwrite(cheatFile.c_str(), 1, cheatFile.length(), f); - fclose(f); - } - else { - Logging::error("Failed to write {} with errno {}.", outPath, errno); - } -} \ No newline at end of file diff --git a/3ds/source/util.cpp b/3ds/source/util.cpp index 5e9bc13c..e39cc006 100644 --- a/3ds/source/util.cpp +++ b/3ds/source/util.cpp @@ -83,7 +83,6 @@ Result servicesInit(void) mkdir("sdmc:/3ds/Checkpoint/saves", 777); mkdir("sdmc:/3ds/Checkpoint/extdata", 777); mkdir("sdmc:/3ds/Checkpoint/logs", 777); - mkdir("sdmc:/cheats", 777); Logging::initFileLogging(); diff --git a/Makefile b/Makefile index d36760fc..42d00098 100644 --- a/Makefile +++ b/Makefile @@ -12,15 +12,12 @@ all: $(SUBDIRS) clean: @for dir in $(SUBDIRS); do $(MAKE) clean -C $$dir; done - @rm -f sharkive/build/*.json - @rm -f 3ds/romfs/cheats/*.bz2 - @rm -f switch/romfs/cheats/*.bz2 -3ds: 3ds_cheats - @$(MAKE) -C 3ds VERSION_MAJOR=${VERSION_MAJOR} VERSION_MINOR=${VERSION_MINOR} VERSION_MICRO=${VERSION_MICRO} GIT_REV=${GIT_REV} CHEAT_SIZE_DECOMPRESSED=$(shell stat -t "sharkive/build/3ds.json" | awk '{print $$2}') +3ds: + @$(MAKE) -C 3ds VERSION_MAJOR=${VERSION_MAJOR} VERSION_MINOR=${VERSION_MINOR} VERSION_MICRO=${VERSION_MICRO} GIT_REV=${GIT_REV} -switch: switch_cheats - @$(MAKE) -C switch VERSION_MAJOR=${VERSION_MAJOR} VERSION_MINOR=${VERSION_MINOR} VERSION_MICRO=${VERSION_MICRO} GIT_REV=${GIT_REV} CHEAT_SIZE_DECOMPRESSED=$(shell stat -t "sharkive/build/switch.json" | awk '{print $$2}') +switch: + @$(MAKE) -C switch VERSION_MAJOR=${VERSION_MAJOR} VERSION_MINOR=${VERSION_MINOR} VERSION_MICRO=${VERSION_MICRO} GIT_REV=${GIT_REV} format: @for dir in $(SUBDIRS); do $(MAKE) -C $$dir format; done @@ -28,12 +25,4 @@ format: cppcheck: @cppcheck . --enable=all --force 2> cppcheck.log -cheats: $(SUBDIRS:=_cheats) - -3ds_cheats: - @$(MAKE) --always-make -C 3ds cheats - -switch_cheats: - @$(MAKE) --always-make -C switch cheats - -.PHONY: $(SUBDIRS) clean format cppcheck cheats 3ds_cheats switch_cheats +.PHONY: $(SUBDIRS) clean format cppcheck diff --git a/sharkive b/sharkive deleted file mode 160000 index 2f8a18cb..00000000 --- a/sharkive +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2f8a18cb980f1056058bb2a93e4679cc83bad1f8 diff --git a/switch/Makefile b/switch/Makefile index 5bf467c0..4d5a53be 100644 --- a/switch/Makefile +++ b/switch/Makefile @@ -44,8 +44,6 @@ FORMATINCLUDES := include ../common INCLUDES := $(FORMATINCLUDES) ../3rd-party/mongoose ../3rd-party/json ../3rd-party/ftp EXEFS_SRC := exefs_src ROMFS := romfs -SHARKIVE := ../sharkive -CHEATS := cheats #--------------------------------------------------------------------------------- # options for code generation @@ -65,7 +63,6 @@ CFLAGS := -g -Wall -Wextra -O3 -ffunction-sections \ -DMG_ENABLE_FILESYSTEM \ -DJSON_HAS_FILESYSTEM=0 \ -DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0 \ - -DCHEAT_SIZE_DECOMPRESSED=${CHEAT_SIZE_DECOMPRESSED} CFLAGS += $(INCLUDE) -D__SWITCH__ -D_GNU_SOURCE=1 @@ -165,16 +162,10 @@ endif .PHONY: $(BUILD) clean all format #--------------------------------------------------------------------------------- -all: cheats $(BUILD) +all: $(BUILD) $(BUILD): @[ -d $@ ] || mkdir -p $@ $(BUILD) $(OUTDIR) -ifeq ($(OS),Windows_NT) - @cd $(SHARKIVE) && py -3 joiner.py switch -else - @cd $(SHARKIVE) && python3 joiner.py switch -endif - @cd $(SHARKIVE)/$(BUILD) && mv switch.json.bz2 ../../switch/$(ROMFS)/$(CHEATS)/$(CHEATS).json.bz2 @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- @@ -182,15 +173,6 @@ clean: @echo clean ... @rm -fr $(BUILD) $(OUTDIR) #--------------------------------------------------------------------------------- -cheats: - @mkdir -p $@ $(ROMFS)/$(CHEATS) -ifeq ($(OS),Windows_NT) - @cd $(SHARKIVE) && py -3 joiner.py switch -else - @cd $(SHARKIVE) && python3 joiner.py switch -endif - @cd $(SHARKIVE)/$(BUILD) && mv switch.json.bz2 ../../switch/$(ROMFS)/$(CHEATS)/$(CHEATS).json.bz2 -#--------------------------------------------------------------------------------- format: clang-format -i -style=file $(foreach dir,$(FORMATSOURCES),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cpp) $(wildcard $(dir)/*.tcc)) $(foreach dir,$(FORMATINCLUDES),$(wildcard $(dir)/*.h) $(wildcard $(dir)/*.hpp)) #--------------------------------------------------------------------------------- diff --git a/switch/include/CheatManagerOverlay.hpp b/switch/include/CheatManagerOverlay.hpp deleted file mode 100644 index 3bf13f9d..00000000 --- a/switch/include/CheatManagerOverlay.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#ifndef CHEATMANAGEROVERLAY_HPP -#define CHEATMANAGEROVERLAY_HPP - -#include "Overlay.hpp" -#include "SDLHelper.hpp" -#include "YesNoOverlay.hpp" -#include "cheatmanager.hpp" -#include "clickable.hpp" -#include "colors.hpp" -#include "directory.hpp" -#include "scrollable.hpp" -#include -#include - -class Clickable; -class Scrollable; - -class CheatManagerOverlay : public Overlay { -public: - CheatManagerOverlay(Screen& screen, const std::string& mtext); - ~CheatManagerOverlay() = default; - void draw(void) const override; - void update(const InputState&) override; - -protected: - void save(const std::string& key, Scrollable* s); - -private: - bool multiSelected; - std::string existingCheat; - std::string key; - const size_t MAGIC_LEN = strlen(SELECTED_MAGIC); - std::shared_ptr scrollable; - size_t currentIndex; -}; - -#endif \ No newline at end of file diff --git a/switch/include/MainScreen.hpp b/switch/include/MainScreen.hpp index 775a61ff..1e6d6cfc 100644 --- a/switch/include/MainScreen.hpp +++ b/switch/include/MainScreen.hpp @@ -27,7 +27,6 @@ #ifndef MAINSCREEN_HPP #define MAINSCREEN_HPP -#include "CheatManagerOverlay.hpp" #include "ErrorOverlay.hpp" #include "InfoOverlay.hpp" #include "Screen.hpp" @@ -87,7 +86,7 @@ class MainScreen : public Screen { saveTypeFilter_t mSaveTypeFilter = FILTER_SAVES; Hid hid; std::unique_ptr backupList; - std::unique_ptr buttonCheats, buttonBackup, buttonRestore; + std::unique_ptr buttonBackup, buttonRestore; // Filter buttons in UI order, indexed by saveTypeFilter_t. std::array, 4> filterButtons; char ver[8]; diff --git a/switch/include/cheatmanager.hpp b/switch/include/cheatmanager.hpp deleted file mode 100644 index 8cecc196..00000000 --- a/switch/include/cheatmanager.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#ifndef CHEATMANAGER_HPP -#define CHEATMANAGER_HPP - -#include "json.hpp" -#include "main.hpp" -#include -#include -#include -#include -#include - -#define SELECTED_MAGIC "\uE071 " - -class Scrollable; - -class CheatManager { -public: - static CheatManager& getInstance(void) - { - static CheatManager mCheatManager; - return mCheatManager; - } - - bool areCheatsAvailable(const std::string& key); - void save(const std::string& key, const std::vector& s); - - std::shared_ptr cheats() { return mCheats; } - -private: - CheatManager(); - ~CheatManager() = default; - - CheatManager(CheatManager const&) = delete; - void operator=(CheatManager const&) = delete; - - std::shared_ptr mCheats; -}; - -#endif \ No newline at end of file diff --git a/switch/include/main.hpp b/switch/include/main.hpp index ee3b0def..b6767155 100644 --- a/switch/include/main.hpp +++ b/switch/include/main.hpp @@ -42,8 +42,6 @@ inline bool g_notificationLedAvailable = false; inline std::shared_ptr g_screen = nullptr; inline bool g_ftpAvailable = false; inline bool g_shouldExitNetworkLoop = false; -inline std::string g_selectedCheatKey; -inline std::vector g_selectedCheatCodes; inline u32 g_username_dotsize; inline const InputState* g_input = nullptr; diff --git a/switch/source/CheatManagerOverlay.cpp b/switch/source/CheatManagerOverlay.cpp deleted file mode 100644 index e596ef2a..00000000 --- a/switch/source/CheatManagerOverlay.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#include "CheatManagerOverlay.hpp" - -CheatManagerOverlay::CheatManagerOverlay(Screen& screen, const std::string& mkey) : Overlay(screen) -{ - key = mkey; - multiSelected = false; - std::string existingCheat = ""; - - std::string root = StringUtils::format("/atmosphere/contents/%s/cheats", key.c_str()); - Directory dir(root); - if (dir.good()) { - for (size_t i = 0; i < dir.size(); i++) { - if (!dir.folder(i)) { - FILE* f = fopen((root + "/" + dir.entry(i)).c_str(), "r"); - if (f != NULL) { - fseek(f, 0, SEEK_END); - u32 size = ftell(f); - char* s = new char[size]; - rewind(f); - fread(s, 1, size, f); - existingCheat += "\n" + std::string(s); - delete[] s; - fclose(f); - } - } - } - } - - size_t i = 0; - currentIndex = i; - scrollable = std::make_shared(90, 20, 1100, 640, 16); - auto cheats = *CheatManager::getInstance().cheats().get(); - for (auto it = cheats[key].begin(); it != cheats[key].end(); ++it) { - std::string buildid = it.key(); - for (auto it2 = cheats[key][buildid].begin(); it2 != cheats[key][buildid].end(); ++it2) { - std::string value = it2.key(); - if (existingCheat.find(value) != std::string::npos) { - value = SELECTED_MAGIC + value; - } - scrollable->push_back(COLOR_BLACK_DARKER, COLOR_WHITE, value, i == 0); - i++; - } - } -} - -void CheatManagerOverlay::draw(void) const -{ - SDLH_DrawRect(0, 0, 1280, 720, COLOR_OVERLAY); - std::string page = StringUtils::format("%d/%d", scrollable->index() + 1, scrollable->size()); - u32 width, height; - SDLH_GetTextDimensions(20, page.c_str(), &width, &height); - - SDLH_DrawRect(86, 16, 1108, 680, COLOR_BLACK_DARK); - scrollable->draw(true); - SDLH_DrawText(20, ceilf(1190 - width), ceilf(664 + (32 - height) / 2), COLOR_WHITE, page.c_str()); - SDLH_DrawText( - 20, 94, ceilf(664 + (32 - height) / 2), COLOR_WHITE, multiSelected ? "\ue003 to deselect all cheats" : "\ue003 to select all cheats"); -} - -void CheatManagerOverlay::update(const InputState& input) -{ - u64 kDown = input.kDown; - if (kDown & HidNpadButton_A) { - std::string cellName = scrollable->cellName(scrollable->index()); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - // cheat was already selected - cellName = cellName.substr(strlen(SELECTED_MAGIC), cellName.length()); - } - else { - cellName = SELECTED_MAGIC + cellName; - } - scrollable->text(scrollable->index(), cellName); - } - - if (kDown & HidNpadButton_Y) { - if (multiSelected) { - for (size_t j = 0; j < scrollable->size(); j++) { - std::string cellName = scrollable->cellName(j); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - cellName = cellName.substr(strlen(SELECTED_MAGIC), cellName.length()); - scrollable->text(j, cellName); - } - } - multiSelected = false; - } - else { - for (size_t j = 0; j < scrollable->size(); j++) { - std::string cellName = scrollable->cellName(j); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) != 0) { - cellName = SELECTED_MAGIC + cellName; - scrollable->text(j, cellName); - } - } - multiSelected = true; - } - } - - scrollable->updateSelection(); - scrollable->selectRow(currentIndex, false); - scrollable->selectRow(scrollable->index(), true); - currentIndex = scrollable->index(); - - if (kDown & HidNpadButton_B) { - g_selectedCheatKey = key; - g_selectedCheatCodes.clear(); - for (size_t i = 0; i < scrollable->size(); i++) { - g_selectedCheatCodes.push_back(scrollable->cellName(i)); - } - me = std::make_shared( - screen, "Do you want to store the cheat file?", - []() { - CheatManager::getInstance().save(g_selectedCheatKey, g_selectedCheatCodes); - g_screen->removeOverlay(); - }, - []() { g_screen->removeOverlay(); }); - } -} \ No newline at end of file diff --git a/switch/source/MainScreen.cpp b/switch/source/MainScreen.cpp index 7efd647b..c794f3bb 100644 --- a/switch/source/MainScreen.cpp +++ b/switch/source/MainScreen.cpp @@ -120,10 +120,8 @@ MainScreen::MainScreen(const InputState& input) : hid(rowlen * collen, collen, i backupList = std::make_unique(608, 316, 400, 408, rows); buttonBackup = std::make_unique(1012, 316, 260, 64, COLOR_BLACK_DARKER, COLOR_GREY_LIGHT, "Backup \ue004", true); buttonRestore = std::make_unique(1012, 384, 260, 64, COLOR_BLACK_DARKER, COLOR_GREY_LIGHT, "Restore \ue005", true); - buttonCheats = std::make_unique(1012, 452, 260, 64, COLOR_BLACK_DARKER, COLOR_GREY_LIGHT, "Cheats \ue0c5", true); buttonBackup->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(true); - buttonCheats->canChangeColorWhenSelected(true); int filterY = TOPBAR_h + 12; for (int k = 0; k < 4; k++) { @@ -301,7 +299,6 @@ void MainScreen::draw() const backupList->draw(g_backupScrollEnabled); buttonBackup->draw(30, COLOR_PURPLE_LIGHT); buttonRestore->draw(30, COLOR_PURPLE_LIGHT); - buttonCheats->draw(30, COLOR_PURPLE_LIGHT); } else { const char* emptyMsg = SaveKind::of(mSaveTypeFilter).emptyMsg; @@ -804,24 +801,6 @@ void MainScreen::handleEvents(const InputState& input) } } } - - if ((buttonCheats->released() || (kdown & HidNpadButton_StickR)) && CheatManager::getInstance().cheats() != nullptr) { - if (MS::multipleSelectionEnabled()) { - MS::clearSelectedEntries(); - updateButtons(); - } - else { - Title title; - TitleCatalog::get().getTitle(title, g_currentUId, rawIndex()); - std::string key = StringUtils::format("%016llX", title.id()); - if (CheatManager::getInstance().areCheatsAvailable(key)) { - currentOverlay = std::make_shared(*this, key); - } - else { - currentOverlay = std::make_shared(*this, "No available cheat codes for this title."); - } - } - } } std::string MainScreen::nameFromCell(size_t index) const @@ -876,23 +855,18 @@ void MainScreen::updateButtons(void) if (MS::multipleSelectionEnabled()) { buttonRestore->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(false); - buttonCheats->canChangeColorWhenSelected(false); buttonBackup->setColors(COLOR_BLACK_DARKER, COLOR_WHITE); buttonRestore->setColors(COLOR_BLACK_DARKER, COLOR_GREY_LIGHT); - buttonCheats->setColors(COLOR_BLACK_DARKER, COLOR_GREY_LIGHT); } else if (g_backupScrollEnabled) { buttonBackup->canChangeColorWhenSelected(true); buttonRestore->canChangeColorWhenSelected(true); - buttonCheats->canChangeColorWhenSelected(true); buttonBackup->setColors(COLOR_BLACK_DARKER, COLOR_WHITE); buttonRestore->setColors(COLOR_BLACK_DARKER, COLOR_WHITE); - buttonCheats->setColors(COLOR_BLACK_DARKER, COLOR_WHITE); } else { buttonBackup->setColors(COLOR_BLACK_DARKER, COLOR_GREY_LIGHT); buttonRestore->setColors(COLOR_BLACK_DARKER, COLOR_GREY_LIGHT); - buttonCheats->setColors(COLOR_BLACK_DARKER, COLOR_GREY_LIGHT); } if (getPKSMBridgeFlag() && mSaveTypeFilter == FILTER_SAVES) { diff --git a/switch/source/cheatmanager.cpp b/switch/source/cheatmanager.cpp deleted file mode 100644 index b587a566..00000000 --- a/switch/source/cheatmanager.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of Checkpoint - * Copyright (C) 2017-2025 Bernardo Giordano, FlagBrew - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional Terms 7.b and 7.c of GPLv3 apply to this file: - * * Requiring preservation of specified reasonable legal notices or - * author attributions in that material or in the Appropriate Legal - * Notices displayed by works containing it. - * * Prohibiting misrepresentation of the origin of that material, - * or requiring that modified versions of such material be marked in - * reasonable ways as different from the original version. - */ - -#include "cheatmanager.hpp" - -CheatManager::CheatManager(void) -{ - mCheats = nullptr; - if (io::fileExists("/switch/Checkpoint/cheats.json")) { - const std::string path = "/switch/Checkpoint/cheats.json"; - FILE* in = fopen(path.c_str(), "rt"); - if (in != NULL) { - mCheats = std::make_shared(nlohmann::json::parse(in, nullptr, false)); - fclose(in); - } - else { - Logging::warning("Failed to open {} with errno {}.", path, errno); - } - } - else { - const std::string path = "romfs:/cheats/cheats.json.bz2"; - // load compressed archive in memory - FILE* f = fopen(path.c_str(), "rb"); - if (f != NULL) { - fseek(f, 0, SEEK_END); - u32 size = ftell(f); - unsigned int destLen = CHEAT_SIZE_DECOMPRESSED; - char* s = new char[size]; - char* d = new char[destLen + 1](); - rewind(f); - fread(s, 1, size, f); - - int r = BZ2_bzBuffToBuffDecompress(d, &destLen, s, size, 0, 0); - if (r == BZ_OK) { - mCheats = std::make_shared(nlohmann::json::parse(d)); - } - - delete[] s; - delete[] d; - fclose(f); - } - else { - Logging::warning("Failed to open {} with errno %d.", path, errno); - } - } -} - -bool CheatManager::areCheatsAvailable(const std::string& key) -{ - return mCheats->find(key) != mCheats->end(); -} - -void CheatManager::save(const std::string& key, const std::vector& s) -{ - static size_t MAGIC_LEN = strlen(SELECTED_MAGIC); - - std::string idfolder = StringUtils::format("/atmosphere/contents/%s", key.c_str()); - std::string rootfolder = idfolder + "/cheats"; - mkdir(idfolder.c_str(), 777); - mkdir(rootfolder.c_str(), 777); - - auto cheats = *CheatManager::getInstance().cheats().get(); - for (auto it = cheats[key].begin(); it != cheats[key].end(); ++it) { - std::string buildid = it.key(); - std::string cheatFile = ""; - for (size_t i = 0; i < s.size(); i++) { - std::string cellName = s.at(i); - if (cellName.compare(0, MAGIC_LEN, SELECTED_MAGIC) == 0) { - cellName = cellName.substr(strlen(SELECTED_MAGIC), cellName.length()); - if (cheats[key][buildid].find(cellName) != cheats[key][buildid].end()) { - cheatFile += "[" + cellName + "]\n"; - for (auto& it2 : cheats[key][buildid][cellName]) { - cheatFile += it2.get() + "\n"; - } - cheatFile += "\n"; - } - } - } - - std::string outPath = rootfolder + "/" + buildid + ".txt"; - FILE* f = fopen(outPath.c_str(), "w"); - if (f != NULL) { - fwrite(cheatFile.c_str(), 1, cheatFile.length(), f); - fclose(f); - } - else { - Logging::error("Failed to write {} with errno {}.", outPath, errno); - } - } -} \ No newline at end of file