Skip to content

Commit

Permalink
add controller support to frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
ITotalJustice committed Apr 24, 2022
1 parent 9a30b40 commit 6d6f570
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ gba emulator witten in c++23.
- init `REG_RCNT` when skipping bios. fixes [#67](https://github.com/ITotalJustice/notorious_beeg/issues/67)
- no loger mirror io r/w.
- force align dma r/w.
- add controller support to frontend.

0.0.2
- fixed neg flags being treated as logical flags, rather instead of sub. fixes [#1](https://github.com/ITotalJustice/notorious_beeg/issues/1)
Expand Down
146 changes: 140 additions & 6 deletions src/frontend/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "system.hpp"
#include "debugger/io.hpp"
#include "gba.hpp"
#include "trim_font.hpp"
#include "icon.hpp"

Expand Down Expand Up @@ -259,6 +260,11 @@ System::~System()
SDL_DestroyTexture(text);
}

for (auto& [_, controller] : System::controllers)
{
SDL_GameControllerClose(controller);
}

if (audio_device != 0) { SDL_CloseAudioDevice(audio_device); }
if (audio_stream != nullptr) { SDL_FreeAudioStream(audio_stream); }
if (texture != nullptr) { SDL_DestroyTexture(texture); }
Expand Down Expand Up @@ -484,6 +490,125 @@ auto System::on_dropfile_event(SDL_DropEvent& e) -> void
}
}

auto System::on_controlleraxis_event(const SDL_ControllerAxisEvent& e) -> void
{
// sdl recommends deadzone of 8000
constexpr auto DEADZONE = 8000;
constexpr auto LEFT = -DEADZONE;
constexpr auto RIGHT = +DEADZONE;
constexpr auto UP = -DEADZONE;
constexpr auto DOWN = +DEADZONE;

switch (e.axis)
{
case SDL_CONTROLLER_AXIS_LEFTX:
case SDL_CONTROLLER_AXIS_RIGHTX:
if (e.value < LEFT)
{
System::emu_set_button(gba::LEFT, true);
}
else if (e.value > RIGHT)
{
System::emu_set_button(gba::RIGHT, true);
}
else
{
System::emu_set_button(gba::LEFT, false);
System::emu_set_button(gba::RIGHT, false);
}
break;

case SDL_CONTROLLER_AXIS_LEFTY:
case SDL_CONTROLLER_AXIS_RIGHTY:
if (e.value < UP)
{
System::emu_set_button(gba::UP, true);
}
else if (e.value > DOWN)
{
System::emu_set_button(gba::DOWN, true);
}
else
{
{
System::emu_set_button(gba::UP, false);
System::emu_set_button(gba::DOWN, false);
}
}
break;

// don't handle yet
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
return;

default: return; // silence enum warning
}
}

auto System::on_controllerbutton_event(const SDL_ControllerButtonEvent& e) -> void
{
const auto down = e.type == SDL_CONTROLLERBUTTONDOWN;

switch (e.button)
{
case SDL_CONTROLLER_BUTTON_A: System::emu_set_button(gba::A, down); break;
case SDL_CONTROLLER_BUTTON_B: System::emu_set_button(gba::B, down); break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: System::emu_set_button(gba::L, down); break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: System::emu_set_button(gba::R, down); break;
case SDL_CONTROLLER_BUTTON_START: System::emu_set_button(gba::START, down); break;
case SDL_CONTROLLER_BUTTON_GUIDE: System::emu_set_button(gba::SELECT, down); break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: System::emu_set_button(gba::UP, down); break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: System::emu_set_button(gba::DOWN, down); break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: System::emu_set_button(gba::LEFT, down); break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: System::emu_set_button(gba::RIGHT, down); break;

default: break; // silence enum warning
}
}

auto System::on_controllerdevice_event(const SDL_ControllerDeviceEvent& e) -> void
{
switch (e.type)
{
case SDL_CONTROLLERDEVICEADDED: {
const auto itr = System::controllers.find(e.which);
if (itr == System::controllers.end())
{
auto controller = SDL_GameControllerOpen(e.which);
if (controller != nullptr)
{
std::printf("[CONTROLLER] opened: %s\n", SDL_GameControllerNameForIndex(e.which));
}
else
{
std::printf("[CONTROLLER] failed to open: %s error: %s\n", SDL_GameControllerNameForIndex(e.which), SDL_GetError());
}
}
else
{
std::printf("[CONTROLLER] already added, ignoring: %s\n", SDL_GameControllerNameForIndex(e.which));
}
} break;

case SDL_CONTROLLERDEVICEREMOVED: {
const auto itr = System::controllers.find(e.which);
if (itr != System::controllers.end())
{
std::printf("[CONTROLLER] removed controller\n");

// have to manually close to free struct
SDL_GameControllerClose(itr->second);
System::controllers.erase(itr);
}
} break;

case SDL_CONTROLLERDEVICEREMAPPED:
std::printf("mapping updated for: %s\n", SDL_GameControllerNameForIndex(e.which));
break;
}
}

auto System::init(int argc, char** argv) -> bool
{
// enable to record audio
Expand Down Expand Up @@ -628,6 +753,21 @@ auto System::run_events() -> void
on_window_event(e.window);
break;

case SDL_CONTROLLERAXISMOTION:
on_controlleraxis_event(e.caxis);
break;

case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
on_controllerbutton_event(e.cbutton);
break;

case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
on_controllerdevice_event(e.cdevice);
break;

case SDL_DROPFILE:
on_dropfile_event(e.drop);
break;
Expand Down Expand Up @@ -658,12 +798,6 @@ auto System::run_events() -> void
case SDL_JOYBUTTONUP:
case SDL_JOYDEVICEADDED:
case SDL_JOYDEVICEREMOVED:
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP:
Expand Down
15 changes: 11 additions & 4 deletions src/frontend/system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string>
#include <mutex>
#include <chrono>
#include <unordered_map>
#include <SDL.h>

namespace sys {
Expand All @@ -19,10 +20,6 @@ struct System

static auto init(int argc, char** argv) -> bool;
static auto run() -> void;
static auto on_key_event(const SDL_KeyboardEvent& e) -> void;
static auto on_display_event(const SDL_DisplayEvent& e) -> void;
static auto on_window_event(const SDL_WindowEvent& e) -> void;
static auto on_dropfile_event(SDL_DropEvent& e) -> void;

static auto loadrom(const std::string& path) -> bool;
static auto closerom() -> void;
Expand Down Expand Up @@ -95,6 +92,16 @@ struct System
private:
// static inline bool
static inline bool show_grid{false};
static inline std::unordered_map<Sint32, SDL_GameController*> controllers;

private:
static auto on_display_event(const SDL_DisplayEvent& e) -> void;
static auto on_window_event(const SDL_WindowEvent& e) -> void;
static auto on_key_event(const SDL_KeyboardEvent& e) -> void;
static auto on_controlleraxis_event(const SDL_ControllerAxisEvent& e) -> void;
static auto on_controllerbutton_event(const SDL_ControllerButtonEvent& e) -> void;
static auto on_controllerdevice_event(const SDL_ControllerDeviceEvent& e) -> void;
static auto on_dropfile_event(SDL_DropEvent& e) -> void;

private:
static auto run_events() -> void;
Expand Down

0 comments on commit 6d6f570

Please sign in to comment.