summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt1
-rw-r--r--app/controller/CMakeLists.txt14
-rw-r--r--app/controller/main.cc33
-rw-r--r--app/controller/serial-controller.cc96
-rw-r--r--app/controller/serial-controller.hh29
-rw-r--r--app/encrypt/CMakeLists.txt10
6 files changed, 178 insertions, 5 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 8cc4763..25c8c84 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -14,3 +14,4 @@ else()
endif()
add_subdirectory(encrypt)
+add_subdirectory(controller)
diff --git a/app/controller/CMakeLists.txt b/app/controller/CMakeLists.txt
new file mode 100644
index 0000000..27137e5
--- /dev/null
+++ b/app/controller/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_executable(nes_app_controller)
+
+target_include_directories(nes_app_controller PRIVATE .)
+target_link_libraries(
+ nes_app_controller
+ PRIVATE
+ nes::options
+ nes::nes)
+
+target_sources(
+ nes_app_controller
+ PRIVATE
+ main.cc
+ serial-controller.cc)
diff --git a/app/controller/main.cc b/app/controller/main.cc
new file mode 100644
index 0000000..a9ea5bd
--- /dev/null
+++ b/app/controller/main.cc
@@ -0,0 +1,33 @@
+#include <iostream>
+#include <cstdlib>
+#include <thread>
+#include "serial-controller.hh"
+
+int main(int argc, char** argv)
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage:\n";
+ std::cerr << " " << argv[0] << " <controller-path>" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ auto const path = argv[1];
+ auto controller = nes::app::test::serial_controller{ path };
+ if (!controller.is_reliable())
+ {
+ return EXIT_FAILURE;
+ }
+
+ while (true)
+ {
+ auto const buttons = controller.read_buttons();
+ if (!buttons.is_empty())
+ {
+ std::cout << "Buttons: " << buttons.get_raw_value() << std::endl;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/app/controller/serial-controller.cc b/app/controller/serial-controller.cc
new file mode 100644
index 0000000..8485ec4
--- /dev/null
+++ b/app/controller/serial-controller.cc
@@ -0,0 +1,96 @@
+#include "serial-controller.hh"
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+namespace nes::app::test
+{
+ serial_controller::serial_controller(char const* path)
+ : path_{ path }
+ {
+ fd_ = open(path, O_RDONLY | O_NOCTTY | O_NDELAY | O_NONBLOCK);
+ if (fd_ == -1)
+ {
+ perror("serial_controller: open");
+ return;
+ }
+
+ if (!set_up()) { close(); }
+ }
+
+ serial_controller::~serial_controller()
+ {
+ close();
+ }
+
+ auto serial_controller::is_reliable() const -> bool
+ {
+ return fd_ != -1;
+ }
+
+ auto serial_controller::read_buttons() -> sys::button_mask
+ {
+ if (fd_ == -1) { return sys::button_mask{}; }
+
+ // Poll for any updates until we can't read anymore.
+ while (true)
+ {
+ auto buf = u8{};
+ auto const res = read(fd_, &buf, 1);
+ if (res == -1)
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) { break; }
+
+ perror("read from controller");
+ close();
+ break;
+ }
+
+ current_ = sys::button_mask::from_raw_value(buf);
+ }
+
+ return current_;
+ }
+
+
+ auto serial_controller::set_up() -> bool
+ {
+ if (ioctl(fd_, TIOCEXCL) == -1)
+ {
+ perror("serial_controller: ioctl");
+ return false;
+ }
+
+ auto attr = termios{};
+ if (tcgetattr(fd_, &attr) == -1)
+ {
+ perror("serial_controller: tcgetattr");
+ return false;
+ }
+
+ cfsetispeed(&attr, B57600);
+ cfsetospeed(&attr, B57600);
+ attr.c_cflag = attr.c_cflag | CLOCAL | CREAD;
+ attr.c_cflag = (attr.c_cflag & static_cast<tcflag_t>(~CSIZE)) | CS8;
+
+ if (tcsetattr(fd_, TCSANOW, &attr) == -1)
+ {
+ perror("serial_controller: tcsetattr");
+ return false;
+ }
+
+ return true;
+ }
+
+ auto serial_controller::close() -> void
+ {
+ if (fd_ != -1)
+ {
+ ::close(fd_);
+ fd_ = -1;
+ }
+ }
+} // namespace nes::app::mac
diff --git a/app/controller/serial-controller.hh b/app/controller/serial-controller.hh
new file mode 100644
index 0000000..bc217b0
--- /dev/null
+++ b/app/controller/serial-controller.hh
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "nes/app/input/input-device-controller.hh"
+
+namespace nes::app::test
+{
+ /// Input device for an NES controller plugged in via serial port.
+ class serial_controller final : public input_device_controller
+ {
+ char const* path_;
+ int fd_{ -1 };
+ sys::button_mask current_{};
+ index index_{ index::unused };
+
+ public:
+ explicit serial_controller(char const* path);
+ ~serial_controller() override;
+
+ auto is_reliable() const -> bool override;
+ auto get_name() const -> string_view override { return path_; }
+ auto get_index() const -> index override { return index_; }
+ auto set_index(index const v) -> void override { index_ = v; }
+ auto read_buttons() -> sys::button_mask override;
+
+ private:
+ auto set_up() -> bool;
+ auto close() -> void;
+ };
+} // namespace nes::app:mac
diff --git a/app/encrypt/CMakeLists.txt b/app/encrypt/CMakeLists.txt
index 5da53af..d147284 100644
--- a/app/encrypt/CMakeLists.txt
+++ b/app/encrypt/CMakeLists.txt
@@ -1,13 +1,13 @@
-add_executable(nes_app_test)
+add_executable(nes_app_encrypt)
-target_include_directories(nes_app_test PRIVATE .)
+target_include_directories(nes_app_encrypt PRIVATE .)
target_link_libraries(
- nes_app_test
+ nes_app_encrypt
PRIVATE
nes::options
nes::nes)
target_sources(
- nes_app_test
+ nes_app_encrypt
PRIVATE
- main.cc) \ No newline at end of file
+ main.cc)