diff --git a/include/cheats.hpp b/include/cheats.hpp index d995a883..1ffa83b7 100644 --- a/include/cheats.hpp +++ b/include/cheats.hpp @@ -24,10 +24,10 @@ class Cheats { }; Cheats(Memory& mem, HIDService& hid); - uint32_t addCheat(const Cheat& cheat); - void removeCheat(uint32_t id); - void enableCheat(uint32_t id); - void disableCheat(uint32_t id); + u32 addCheat(const Cheat& cheat); + void removeCheat(u32 id); + void enableCheat(u32 id); + void disableCheat(u32 id); void reset(); void run(); diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index 6841cdce..c359d432 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -7,7 +7,7 @@ void Cheats::reset() { ar.reset(); // Reset ActionReplay } -uint32_t Cheats::addCheat(const Cheat& cheat) { +u32 Cheats::addCheat(const Cheat& cheat) { cheatsLoaded = true; // Find an empty slot if a cheat was previously removed @@ -23,8 +23,10 @@ uint32_t Cheats::addCheat(const Cheat& cheat) { return cheats.size() - 1; } -void Cheats::removeCheat(uint32_t id) { - if (id >= cheats.size()) return; +void Cheats::removeCheat(u32 id) { + if (id >= cheats.size()) { + return; + } // Not using std::erase because we don't want to invalidate cheat IDs cheats[id].type = CheatType::None; @@ -38,14 +40,16 @@ void Cheats::removeCheat(uint32_t id) { cheatsLoaded = false; } -void Cheats::enableCheat(uint32_t id) { - if (id >= cheats.size()) return; - cheats[id].enabled = true; +void Cheats::enableCheat(u32 id) { + if (id < cheats.size()) { + cheats[id].enabled = true; + } } -void Cheats::disableCheat(uint32_t id) { - if (id >= cheats.size()) return; - cheats[id].enabled = false; +void Cheats::disableCheat(u32 id) { + if (id < cheats.size()) { + cheats[id].enabled = false; + } } void Cheats::clear() { @@ -63,6 +67,7 @@ void Cheats::run() { break; } + case CheatType::None: break; default: Helpers::panic("Unknown cheat device!"); } } diff --git a/src/hydra_core.cpp b/src/hydra_core.cpp index 1c711a02..25cecafc 100644 --- a/src/hydra_core.cpp +++ b/src/hydra_core.cpp @@ -30,17 +30,17 @@ class HC_GLOBAL HydraCore final : public hydra::IBase, // IFrontendDriven void runFrame() override; - uint16_t getFps() override; + u16 getFps() override; // IInput void setPollInputCallback(void (*callback)()) override; - void setCheckButtonCallback(int32_t (*callback)(uint32_t player, hydra::ButtonType button)) override; + void setCheckButtonCallback(s32 (*callback)(u32 player, hydra::ButtonType button)) override; // ICheat - uint32_t addCheat(const uint8_t* data, uint32_t size) override; - void removeCheat(uint32_t id) override; - void enableCheat(uint32_t id) override; - void disableCheat(uint32_t id) override; + u32 addCheat(const u8* data, u32 size) override; + void removeCheat(u32 id) override; + void enableCheat(u32 id) override; + void disableCheat(u32 id) override; std::unique_ptr emulator; RendererGL* renderer; @@ -104,7 +104,7 @@ void HydraCore::runFrame() { emulator->runFrame(); } -uint16_t HydraCore::getFps() { return 60; } +u16 HydraCore::getFps() { return 60; } void HydraCore::reset() { emulator->reset(Emulator::ReloadOption::Reload); } hydra::Size HydraCore::getNativeSize() { return {400, 480}; } @@ -131,29 +131,35 @@ void HydraCore::setFbo(unsigned handle) { renderer->setFBO(handle); } void HydraCore::setGetProcAddress(void* function) { getProcAddress = function; } void HydraCore::setPollInputCallback(void (*callback)()) { pollInputCallback = callback; } -void HydraCore::setCheckButtonCallback(int32_t (*callback)(uint32_t player, hydra::ButtonType button)) { checkButtonCallback = callback; } +void HydraCore::setCheckButtonCallback(s32 (*callback)(u32 player, hydra::ButtonType button)) { checkButtonCallback = callback; } -uint32_t HydraCore::addCheat(const uint8_t* data, uint32_t size) { - if ((size % 8) != 0) return hydra::BAD_CHEAT; +u32 HydraCore::addCheat(const u8* data, u32 size) { + // Every 3DS cheat is a multiple of 64 bits == 8 bytes + if ((size % 8) != 0) { + return hydra::BAD_CHEAT; + } Cheats::Cheat cheat; cheat.enabled = true; cheat.type = Cheats::CheatType::ActionReplay; - for (uint32_t i = 0; i < size; i += 8) { - uint32_t first_word = Common::swap32(*reinterpret_cast(data + i)); - uint32_t second_word = Common::swap32(*reinterpret_cast(data + i + 4)); - cheat.instructions.insert(cheat.instructions.end(), {first_word, second_word}); + for (u32 i = 0; i < size; i += 8) { + auto read32 = [](const u8* ptr) { + return (u32(ptr[3]) << 24) | (u32(ptr[2]) << 16) | (u32(ptr[1]) << 8) | u32(ptr[0]); + }; + + // Data is passed to us in big endian so we bswap + u32 firstWord = Common::swap32(read32(data + i)); + u32 secondWord = Common::swap32(read32(data + i + 4)); + cheat.instructions.insert(cheat.instructions.end(), {firstWord, secondWord}); } return emulator->getCheats().addCheat(cheat); }; -void HydraCore::removeCheat(uint32_t id) { emulator->getCheats().removeCheat(id); } - -void HydraCore::enableCheat(uint32_t id) { emulator->getCheats().enableCheat(id); } - -void HydraCore::disableCheat(uint32_t id) { emulator->getCheats().disableCheat(id); } +void HydraCore::removeCheat(u32 id) { emulator->getCheats().removeCheat(id); } +void HydraCore::enableCheat(u32 id) { emulator->getCheats().enableCheat(id); } +void HydraCore::disableCheat(u32 id) { emulator->getCheats().disableCheat(id); } HC_API hydra::IBase* createEmulator() { return new HydraCore; } HC_API void destroyEmulator(hydra::IBase* emulator) { delete emulator; }