diff --git a/src/dual/CMakeLists.txt b/src/dual/CMakeLists.txt index d5edf97..1fa8a96 100644 --- a/src/dual/CMakeLists.txt +++ b/src/dual/CMakeLists.txt @@ -112,8 +112,3 @@ target_include_directories(dual PRIVATE src) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(dual PRIVATE $<$:-fbracket-depth=8192>) endif() - -# @todo: remove this when properly implementing key input -find_package(PkgConfig REQUIRED) -pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2) -target_link_libraries(dual PRIVATE PkgConfig::SDL2) \ No newline at end of file diff --git a/src/dual/include/dual/nds/arm7/memory.hpp b/src/dual/include/dual/nds/arm7/memory.hpp index 8ce87ae..7e32ba4 100644 --- a/src/dual/include/dual/nds/arm7/memory.hpp +++ b/src/dual/include/dual/nds/arm7/memory.hpp @@ -38,6 +38,7 @@ namespace dual::nds::arm7 { RTC& rtc; APU& apu; WIFI& wifi; + u32& key_input; }; MemoryBus(SystemMemory& memory, const HW& hw); diff --git a/src/dual/include/dual/nds/arm9/memory.hpp b/src/dual/include/dual/nds/arm9/memory.hpp index d820452..8ff9073 100644 --- a/src/dual/include/dual/nds/arm9/memory.hpp +++ b/src/dual/include/dual/nds/arm9/memory.hpp @@ -32,6 +32,7 @@ namespace dual::nds::arm9 { Math& math; VideoUnit& video_unit; Cartridge& cartridge; + u32& key_input; }; struct TCM { diff --git a/src/dual/include/dual/nds/enums.hpp b/src/dual/include/dual/nds/enums.hpp index eaece11..ab45c4b 100644 --- a/src/dual/include/dual/nds/enums.hpp +++ b/src/dual/include/dual/nds/enums.hpp @@ -5,6 +5,21 @@ namespace dual::nds { + enum class Key : u8 { + A = 0, + B = 1, + Select = 2, + Start = 3, + Right = 4, + Left = 5, + Up = 6, + Down = 7, + R = 8, + L = 10, + X = 16, + Y = 17 + }; + enum class CPU { ARM7 = 0, ARM9 = 1 diff --git a/src/dual/include/dual/nds/nds.hpp b/src/dual/include/dual/nds/nds.hpp index 7aa8b0f..c9cf770 100644 --- a/src/dual/include/dual/nds/nds.hpp +++ b/src/dual/include/dual/nds/nds.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ namespace dual::nds { return m_arm7.apu; } + void SetKeyState(Key key, bool pressed); void SetTouchState(bool pen_down, u8 x, u8 y); private: @@ -56,6 +58,8 @@ namespace dual::nds { Cartridge m_cartridge{m_scheduler, m_arm9.irq, m_arm7.irq, m_arm9.dma, m_arm7.dma, m_memory}; + u32 m_key_input{}; + struct ARM9 { CycleCounter cycle_counter{1}; std::unique_ptr cpu{}; @@ -66,7 +70,7 @@ namespace dual::nds { arm9::DMA dma{bus, irq}; arm9::Math math{}; - ARM9(Scheduler& scheduler, SystemMemory& memory, IPC& ipc, VideoUnit& video_unit, Cartridge& cartridge) + ARM9(Scheduler& scheduler, SystemMemory& memory, IPC& ipc, VideoUnit& video_unit, Cartridge& cartridge, u32& key_input) : bus{memory, { irq, timer, @@ -76,10 +80,11 @@ namespace dual::nds { memory.vram, math, video_unit, - cartridge + cartridge, + key_input }} , timer{scheduler, cycle_counter, irq} {} - } m_arm9{m_scheduler, m_memory, m_ipc, m_video_unit, m_cartridge}; + } m_arm9{m_scheduler, m_memory, m_ipc, m_video_unit, m_cartridge, m_key_input}; struct ARM7 { CycleCounter cycle_counter{0}; @@ -93,7 +98,7 @@ namespace dual::nds { arm7::APU apu; arm7::WIFI wifi{}; - ARM7(Scheduler& scheduler, SystemMemory& memory, IPC& ipc, VideoUnit& video_unit, Cartridge& cartridge) + ARM7(Scheduler& scheduler, SystemMemory& memory, IPC& ipc, VideoUnit& video_unit, Cartridge& cartridge, u32& key_input) : bus{memory, { irq, timer, @@ -106,11 +111,12 @@ namespace dual::nds { cartridge, rtc, apu, - wifi + wifi, + key_input }} , timer{scheduler, cycle_counter, irq} , apu{scheduler, bus} {} - } m_arm7{m_scheduler, m_memory, m_ipc, m_video_unit, m_cartridge}; + } m_arm7{m_scheduler, m_memory, m_ipc, m_video_unit, m_cartridge, m_key_input}; IPC m_ipc{m_arm9.irq, m_arm7.irq}; diff --git a/src/dual/src/nds/arm7/io.cpp b/src/dual/src/nds/arm7/io.cpp index 5eb582f..bfc13f5 100644 --- a/src/dual/src/nds/arm7/io.cpp +++ b/src/dual/src/nds/arm7/io.cpp @@ -125,6 +125,10 @@ namespace dual::nds::arm7 { case REG(0x04000108): return hw.timer.Read_TMCNT(2); case REG(0x0400010C): return hw.timer.Read_TMCNT(3); + // Key Input + case REG(0x04000130): return (u16)hw.key_input; + case REG(0x04000134): return hw.key_input & ~0xFFFFu; + // RTC case REG(0x04000138): return hw.rtc.Read_RTC(); diff --git a/src/dual/src/nds/arm7/memory.cpp b/src/dual/src/nds/arm7/memory.cpp index c1a4204..721a48b 100644 --- a/src/dual/src/nds/arm7/memory.cpp +++ b/src/dual/src/nds/arm7/memory.cpp @@ -1,6 +1,4 @@ -#include - #include namespace dual::nds::arm7 { @@ -37,17 +35,6 @@ namespace dual::nds::arm7 { return atom::read(m_swram.arm7.data, address & m_swram.arm7.mask); } case 0x04: { - if(address == 0x04000136) { - const u8* key_state = SDL_GetKeyboardState(nullptr); - - u16 extkeyinput = 0x3Fu; - - if(key_state[SDL_SCANCODE_Q]) extkeyinput &= ~1u; - if(key_state[SDL_SCANCODE_W]) extkeyinput &= ~2u; - - return extkeyinput; - } - if constexpr(std::is_same_v) return m_io.ReadByte(address); if constexpr(std::is_same_v) return m_io.ReadHalf(address); if constexpr(std::is_same_v) return m_io.ReadWord(address); diff --git a/src/dual/src/nds/arm9/io.cpp b/src/dual/src/nds/arm9/io.cpp index 42eb3bc..327c4bc 100644 --- a/src/dual/src/nds/arm9/io.cpp +++ b/src/dual/src/nds/arm9/io.cpp @@ -155,6 +155,9 @@ namespace dual::nds::arm9 { case REG(0x04000108): return hw.timer.Read_TMCNT(2); case REG(0x0400010C): return hw.timer.Read_TMCNT(3); + // Key Input + case REG(0x04000130): return (u16)hw.key_input; + // IPC case REG(0x04000180): return hw.ipc.Read_SYNC(CPU::ARM9); case REG(0x04000184): return hw.ipc.Read_FIFOCNT(CPU::ARM9); diff --git a/src/dual/src/nds/arm9/memory.cpp b/src/dual/src/nds/arm9/memory.cpp index a9ef82b..c238fa2 100644 --- a/src/dual/src/nds/arm9/memory.cpp +++ b/src/dual/src/nds/arm9/memory.cpp @@ -1,6 +1,4 @@ -#include - #include namespace dual::nds::arm9 { @@ -61,25 +59,6 @@ namespace dual::nds::arm9 { return atom::read(m_swram.arm9.data, address & m_swram.arm9.mask); } case 0x04: { - if(address == 0x04000130) { - const u8* key_state = SDL_GetKeyboardState(nullptr); - - u16 keyinput = 0x03FFu; - - if(key_state[SDL_SCANCODE_A]) keyinput &= ~1u; - if(key_state[SDL_SCANCODE_S]) keyinput &= ~2u; - if(key_state[SDL_SCANCODE_BACKSPACE]) keyinput &= ~4u; - if(key_state[SDL_SCANCODE_RETURN]) keyinput &= ~8u; - if(key_state[SDL_SCANCODE_RIGHT]) keyinput &= ~16u; - if(key_state[SDL_SCANCODE_LEFT]) keyinput &= ~32u; - if(key_state[SDL_SCANCODE_UP]) keyinput &= ~64u; - if(key_state[SDL_SCANCODE_DOWN]) keyinput &= ~128u; - if(key_state[SDL_SCANCODE_F]) keyinput &= ~256u; - if(key_state[SDL_SCANCODE_D]) keyinput &= ~512u; - - return keyinput; - } - if constexpr(std::is_same_v) return m_io.ReadByte(address); if constexpr(std::is_same_v) return m_io.ReadHalf(address); if constexpr(std::is_same_v) return m_io.ReadWord(address); diff --git a/src/dual/src/nds/nds.cpp b/src/dual/src/nds/nds.cpp index 479f427..48b1a94 100644 --- a/src/dual/src/nds/nds.cpp +++ b/src/dual/src/nds/nds.cpp @@ -38,6 +38,8 @@ namespace dual::nds { m_cartridge.Reset(); + m_key_input = 0x007F03FFu; + m_memory.ewram.fill(0); m_memory.swram.Reset(); m_memory.vram.Reset(); @@ -198,8 +200,22 @@ namespace dual::nds { m_video_unit.DirectBoot(); } + void NDS::SetKeyState(Key key, bool pressed) { + if(pressed) { + m_key_input &= ~(1u << (int)key); + } else { + m_key_input |= 1u << (int)key; + } + } + void NDS::SetTouchState(bool pen_down, u8 x, u8 y) { m_arm7.spi.GetTouchScreen().SetTouchState(pen_down, x, y); + + if(pen_down) { + m_key_input &= ~(1 << 22); + } else { + m_key_input |= 1 << 22; + } } } // namespace dual::nds diff --git a/src/platform/sdl/src/application.cpp b/src/platform/sdl/src/application.cpp index 782cc51..3b4d550 100644 --- a/src/platform/sdl/src/application.cpp +++ b/src/platform/sdl/src/application.cpp @@ -161,6 +161,8 @@ void Application::MainLoop() { UpdateFPS(); } + // @todo: move this logic into HandleEvent() + m_emu_thread.SetFastForward(SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_SPACE]); if(SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_F11]) { @@ -226,6 +228,29 @@ void Application::HandleEvent(const SDL_Event& event) { set_touch_state(window_x, window_y); } + + if(type == SDL_KEYUP || type == SDL_KEYDOWN) { + const SDL_KeyboardEvent& keyboard_event = (const SDL_KeyboardEvent&)event; + + const auto update_key = [&](dual::nds::Key key) { + m_emu_thread.SetKeyState(key, type == SDL_KEYDOWN); + }; + + switch(keyboard_event.keysym.sym) { + case SDLK_a: update_key(dual::nds::Key::A); break; + case SDLK_s: update_key(dual::nds::Key::B); break; + case SDLK_d: update_key(dual::nds::Key::L); break; + case SDLK_f: update_key(dual::nds::Key::R); break; + case SDLK_q: update_key(dual::nds::Key::X); break; + case SDLK_w: update_key(dual::nds::Key::Y); break; + case SDLK_BACKSPACE: update_key(dual::nds::Key::Select); break; + case SDLK_RETURN: update_key(dual::nds::Key::Start); break; + case SDLK_UP: update_key(dual::nds::Key::Up); break; + case SDLK_DOWN: update_key(dual::nds::Key::Down); break; + case SDLK_LEFT: update_key(dual::nds::Key::Left); break; + case SDLK_RIGHT: update_key(dual::nds::Key::Right); break; + } + } } void Application::UpdateFPS() { diff --git a/src/platform/sdl/src/emulator_thread.cpp b/src/platform/sdl/src/emulator_thread.cpp index 2fd35cb..76786da 100644 --- a/src/platform/sdl/src/emulator_thread.cpp +++ b/src/platform/sdl/src/emulator_thread.cpp @@ -33,6 +33,13 @@ std::unique_ptr EmulatorThread::Stop() { return std::move(m_nds); } +void EmulatorThread::SetKeyState(dual::nds::Key key, bool pressed) { + PushMessage({ + .type = MessageType::SetKeyState, + .set_key_state = { .key = key, .pressed = (u8)(pressed ? 1 : 0) } + }); +} + void EmulatorThread::SetTouchState(bool pen_down, u8 x, u8 y) { PushMessage({ .type = MessageType::SetTouchState, @@ -66,6 +73,10 @@ void EmulatorThread::ProcessMessages() { const Message& message = m_msg_queue.front(); switch(message.type) { + case MessageType::SetKeyState: { + m_nds->SetKeyState(message.set_key_state.key, message.set_key_state.pressed); + break; + } case MessageType::SetTouchState: { m_nds->SetTouchState(message.set_touch_state.pen_down, message.set_touch_state.x, message.set_touch_state.y); break; diff --git a/src/platform/sdl/src/emulator_thread.hpp b/src/platform/sdl/src/emulator_thread.hpp index e0067d7..19859c3 100644 --- a/src/platform/sdl/src/emulator_thread.hpp +++ b/src/platform/sdl/src/emulator_thread.hpp @@ -20,6 +20,7 @@ class EmulatorThread { void Start(std::unique_ptr nds); std::unique_ptr Stop(); + void SetKeyState(dual::nds::Key key, bool pressed); void SetTouchState(bool pen_down, u8 x, u8 y); [[nodiscard]] bool GetFastForward() const; @@ -30,12 +31,17 @@ class EmulatorThread { private: enum class MessageType : u8 { + SetKeyState, SetTouchState }; struct Message { MessageType type; union { + struct { + dual::nds::Key key; + u8 pressed; + } set_key_state; struct { u8 pen_down; u8 x;