diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index c3766de8d..979c61f2e 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -20,8 +20,90 @@ #include "dmnt_cheat_manager.hpp" bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { - /* TODO: Parse opcodes */ - return false; + /* If we've ever seen a decode failure, return true. */ + bool valid = this->decode_success; + CheatVmOpcode opcode = {}; + ON_SCOPE_EXIT { + this->decode_success &= valid; + if (valid) { + *out = opcode; + } + }; + + /* If we have ever seen a decode failure, don't decode any more. */ + if (!valid) { + return valid; + } + + /* Validate instruction pointer. */ + if (this->instruction_ptr >= this->num_opcodes) { + valid = false; + return valid; + } + + /* Read opcode. */ + const u32 first_dword = this->program[this->instruction_ptr++]; + opcode.opcode = (CheatVmOpcodeType)(((first_dword >> 28) & 0xF)); + + switch (opcode.opcode) { + case CheatVmOpcodeType_StoreStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginConditionalBlock: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_EndConditionalBlock: + { + /* There's actually nothing left to process here! */ + } + break; + case CheatVmOpcodeType_ControlLoop: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_LoadRegisterStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_LoadRegisterMemory: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_StoreToRegisterAddress: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_PerformArithmeticStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginKeypressConditionalBlock: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_PerformArithmeticRegister: + { + /* TODO */ + } + break; + default: + /* Unrecognized instruction cannot be decoded. */ + valid = false; + break; + } + + /* End decoding. */ + return valid; } void DmntCheatVm::SkipConditionalBlock() { @@ -64,6 +146,15 @@ u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata* metadata, Me } } +void DmntCheatVm::ResetState() { + for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) { + this->registers[i] = 0; + this->loop_tops[i] = 0; + } + this->instruction_ptr = 0; + this->decode_success = true; +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; @@ -71,10 +162,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { /* TODO: Get Keys down. */ /* Clear VM state. */ - for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) { - this->registers[i] = 0; - this->loop_tops[i] = 0; - } + this->ResetState(); /* Loop until program finishes. */ while (this->DecodeNextOpcode(&cur_opcode)) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 705f26a4a..089870e58 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -162,12 +162,14 @@ class DmntCheatVm { private: size_t num_opcodes = 0; size_t instruction_ptr = 0; + bool decode_success = false; u32 program[MaximumProgramOpcodeCount] = {0}; u64 registers[NumRegisters] = {0}; size_t loop_tops[NumRegisters] = {0}; private: bool DecodeNextOpcode(CheatVmOpcode *out); void SkipConditionalBlock(); + void ResetState(); static u64 GetVmInt(VmInt value, u32 bit_width); static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address); diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index e4321328f..bea0dfffb 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -57,6 +57,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + SetFirmwareVersionForLibnx(); + rc = smInitialize(); if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); @@ -133,7 +135,11 @@ int main(int argc, char **argv) auto server_manager = new WaitableManager(5); /* Create services. */ - server_manager->AddWaitable(new ServiceServer("dmnt:-", 4)); + + /* TODO: Implement rest of dmnt:- in ams.tma development branch. */ + /* server_manager->AddWaitable(new ServiceServer("dmnt:-", 4)); */ + + server_manager->AddWaitable(new ServiceServer("dmnt:cht", 1)); /* Loop forever, servicing our services. */