diff --git a/CMakeLists.txt b/CMakeLists.txt index a83b9734..181a0569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,9 +41,9 @@ else() message(FATAL_ERROR "THIS IS NOT x64 WAIT FOR THE KVM IMPLEMENTATION") endif() -set(SOURCE_FILES src/main.cpp src/emulator.cpp src/cpu/cpu_dynarmic.cpp) +set(SOURCE_FILES src/main.cpp src/emulator.cpp src/core/CPU/cpu_dynarmic.cpp src/core/memory.cpp) set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/opengl.hpp include/termcolor.hpp - include/cpu.hpp include/cpu_dynarmic.hpp + include/cpu.hpp include/cpu_dynarmic.hpp include/memory.hpp ) set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp diff --git a/include/cpu_dynarmic.hpp b/include/cpu_dynarmic.hpp index 554eadbb..f5750cb5 100644 --- a/include/cpu_dynarmic.hpp +++ b/include/cpu_dynarmic.hpp @@ -3,6 +3,7 @@ #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/config.h" #include "helpers.hpp" +#include "memory.hpp" class MyEnvironment final : public Dynarmic::A32::UserCallbacks { public: @@ -79,9 +80,11 @@ public: class CPU { MyEnvironment env; Dynarmic::A32::Jit jit{ {.callbacks = &env} }; + Memory& mem; public: - CPU(); + CPU(Memory& mem); + void reset(); void setReg(int index, u32 value) { jit.Regs()[index] = value; diff --git a/include/emulator.hpp b/include/emulator.hpp index 6d9d7b51..088dda2e 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -8,12 +8,14 @@ class Emulator { CPU cpu; + Memory memory; sf::RenderWindow window; static constexpr u32 width = 400; static constexpr u32 height = 240 * 2; // * 2 because 2 screens public: - Emulator() : window(sf::VideoMode(width, height), "Alber", sf::Style::Default, sf::ContextSettings(0, 0, 0, 4, 3)) { + Emulator() : window(sf::VideoMode(width, height), "Alber", sf::Style::Default, sf::ContextSettings(0, 0, 0, 4, 3)), + cpu(memory) { reset(); window.setActive(true); } diff --git a/include/helpers.hpp b/include/helpers.hpp index 0b54ec0f..8a3eb2fc 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -17,8 +17,7 @@ using s16 = std::int16_t; using s32 = std::int32_t; using s64 = std::int64_t; -class Helpers { -public: +namespace Helpers { [[noreturn]] static void panic(const char* fmt, ...) { std::va_list args; va_start(args, fmt); @@ -133,6 +132,19 @@ public: } }; +// UDLs for memory size values +constexpr size_t operator""_KB(unsigned long long int x) { + return 1024ULL * x; +} + +constexpr size_t operator""_MB(unsigned long long int x) { + return 1024_KB * x; +} + +constexpr size_t operator""_GB(unsigned long long int x) { + return 1024_MB * x; +} + // useful macros // likely/unlikely #ifdef __GNUC__ diff --git a/include/memory.hpp b/include/memory.hpp new file mode 100644 index 00000000..a00ef4ff --- /dev/null +++ b/include/memory.hpp @@ -0,0 +1,18 @@ +#pragma once +#include +#include "helpers.hpp" + +class Memory { + u8* fcram; + + // Our dynarmic core uses page tables for reads and writes with 4096 byte pages + std::vector readTable, writeTable; + static constexpr u32 pageShift = 12; + static constexpr u32 pageSize = 1 << pageShift; + static constexpr u32 pageMask = pageSize - 1; + +public: + Memory(); + void* getReadPointer(u32 address); + void* getWritePointer(u32 address); +}; \ No newline at end of file diff --git a/src/CPU/cpu_dynarmic.cpp b/src/core/CPU/cpu_dynarmic.cpp similarity index 62% rename from src/CPU/cpu_dynarmic.cpp rename to src/core/CPU/cpu_dynarmic.cpp index d921c07a..ef751b22 100644 --- a/src/CPU/cpu_dynarmic.cpp +++ b/src/core/CPU/cpu_dynarmic.cpp @@ -1,15 +1,16 @@ #ifdef CPU_DYNARMIC #include "cpu_dynarmic.hpp" -CPU::CPU() { +CPU::CPU(Memory& mem) : mem(mem) { // Execute at least 1 instruction. // (Note: More than one instruction may be executed.) - env.ticks_left = 1; + env.ticks_left = 10; // Write some code to memory. env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2 env.MemoryWrite16(2, 0x3045); // adds r0, #69 - env.MemoryWrite16(4, 0xE7FE); // b +#0 (infinite loop) + env.MemoryWrite16(4, 0xdf45); // swi #69 + env.MemoryWrite16(6, 0xE7FE); // b +#0 (infinite loop) // Setup registers. auto& regs = jit.Regs(); @@ -25,4 +26,10 @@ CPU::CPU() { printf("R0: %u\n", jit.Regs()[0]); } +void CPU::reset() { + jit.Regs().fill(0); + // ARM mode, all flags disabled, interrupts and aborts all enabled, user mode + setCPSR(0x00000010); +} + #endif // CPU_DYNARMIC \ No newline at end of file diff --git a/src/core/memory.cpp b/src/core/memory.cpp new file mode 100644 index 00000000..c038d55c --- /dev/null +++ b/src/core/memory.cpp @@ -0,0 +1,23 @@ +#include "memory.hpp" + +Memory::Memory() { + fcram = new uint8_t[128_MB](); +} + +void* Memory::getReadPointer(u32 address) { + const auto page = address >> pageShift; + const auto offset = address & pageMask; + + uintptr_t pointer = readTable[page]; + if (pointer == 0) return nullptr; + return (void*)(pointer + offset); +} + +void* Memory::getWritePointer(u32 address) { + const auto page = address >> pageShift; + const auto offset = address & pageMask; + + uintptr_t pointer = writeTable[page]; + if (pointer == 0) return nullptr; + return (void*)(pointer + offset); +} \ No newline at end of file diff --git a/src/emulator.cpp b/src/emulator.cpp index 031aa6ed..6988c6ea 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,6 +1,8 @@ #include "emulator.hpp" -void Emulator::reset() {} +void Emulator::reset() { + cpu.reset(); +} void Emulator::step() {}