Skip to content

Commit

Permalink
Core: replace InputDevice API with something simpler
Browse files Browse the repository at this point in the history
Also moves input changes on the emulator thread message queue.
  • Loading branch information
fleroviux committed Jan 13, 2024
1 parent fdfaecc commit 01fd36f
Show file tree
Hide file tree
Showing 18 changed files with 100 additions and 206 deletions.
1 change: 0 additions & 1 deletion src/nba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ set(HEADERS_PUBLIC
include/nba/common/punning.hpp
include/nba/common/scope_exit.hpp
include/nba/device/audio_device.hpp
include/nba/device/input_device.hpp
include/nba/device/video_device.hpp
include/nba/rom/backup/backup.hpp
include/nba/rom/backup/backup_file.hpp
Expand Down
2 changes: 0 additions & 2 deletions src/nba/include/nba/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include <memory>
#include <nba/device/audio_device.hpp>
#include <nba/device/input_device.hpp>
#include <nba/device/video_device.hpp>
#include <nba/integer.hpp>
#include <string>
Expand Down Expand Up @@ -47,7 +46,6 @@ struct Config {
} audio;

std::shared_ptr<AudioDevice> audio_dev = std::make_shared<NullAudioDevice>();
std::shared_ptr<InputDevice> input_dev = std::make_shared<NullInputDevice>();
std::shared_ptr<VideoDevice> video_dev = std::make_shared<NullVideoDevice>();
};

Expand Down
15 changes: 15 additions & 0 deletions src/nba/include/nba/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@

namespace nba {

enum class Key : u8 {
A = 0,
B = 1,
Select = 2,
Start = 3,
Right = 4,
Left = 5,
Up = 6,
Down = 7,
L = 8,
R = 9,
Count = 10
};

struct CoreBase {
static constexpr int kCyclesPerFrame = 280896;

Expand All @@ -32,6 +46,7 @@ struct CoreBase {
virtual auto CreateSolarSensor() -> std::unique_ptr<SolarSensor> = 0;
virtual void LoadState(SaveState const& state) = 0;
virtual void CopyState(SaveState& state) = 0;
virtual void SetKeyStatus(Key key, bool pressed) = 0;
virtual void Run(int cycles) = 0;

virtual auto GetROM() -> ROM& = 0;
Expand Down
62 changes: 0 additions & 62 deletions src/nba/include/nba/device/input_device.hpp

This file was deleted.

2 changes: 0 additions & 2 deletions src/nba/include/nba/scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ struct Scheduler {

SIO_transfer_done,

KeyPad_Poll,

EndOfQueue,
Count
};
Expand Down
6 changes: 5 additions & 1 deletion src/nba/src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Core::Core(std::shared_ptr<Config> config)
, apu(scheduler, dma, bus, config)
, ppu(scheduler, irq, dma, config)
, timer(scheduler, irq, apu)
, keypad(scheduler, irq, config)
, keypad(scheduler, irq)
, bus(scheduler, {cpu, irq, dma, apu, ppu, timer, keypad}) {
Reset();
}
Expand Down Expand Up @@ -71,6 +71,10 @@ auto Core::CreateSolarSensor() -> std::unique_ptr<SolarSensor> {
return std::make_unique<SolarSensor>();
}

void Core::SetKeyStatus(Key key, bool pressed) {
keypad.SetKeyStatus(key, pressed);
}

void Core::Run(int cycles) {
using HaltControl = Bus::Hardware::HaltControl;

Expand Down
1 change: 1 addition & 0 deletions src/nba/src/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct Core final : CoreBase {
auto CreateSolarSensor() -> std::unique_ptr<SolarSensor> override;
void LoadState(SaveState const& state) override;
void CopyState(SaveState& state) override;
void SetKeyStatus(Key key, bool pressed) override;
void Run(int cycles) override;

auto GetROM() -> ROM& override;
Expand Down
82 changes: 10 additions & 72 deletions src/nba/src/hw/keypad/keypad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@

namespace nba::core {

KeyPad::KeyPad(Scheduler& scheduler, IRQ& irq, std::shared_ptr<Config> config)
KeyPad::KeyPad(Scheduler& scheduler, IRQ& irq)
: scheduler(scheduler)
, irq(irq)
, config(config) {
scheduler.Register(Scheduler::EventClass::KeyPad_Poll, this, &KeyPad::Poll);

, irq(irq) {
Reset();
}

Expand All @@ -25,29 +22,18 @@ void KeyPad::Reset() {
input.keypad = this;
control = {};
control.keypad = this;
config->input_dev->SetOnChangeCallback(std::bind(&KeyPad::UpdateInput, this));

input_queue.Reset();
scheduler.Add(k_poll_interval, Scheduler::EventClass::KeyPad_Poll);
}

void KeyPad::UpdateInput() {
auto& input_device = config->input_dev;
void KeyPad::SetKeyStatus(Key key, bool pressed) {
const u16 bit = 1 << (int)key;

u16 input = 0;

if(!input_device->Poll(Key::A)) input |= 1;
if(!input_device->Poll(Key::B)) input |= 2;
if(!input_device->Poll(Key::Select)) input |= 4;
if(!input_device->Poll(Key::Start)) input |= 8;
if(!input_device->Poll(Key::Right)) input |= 16;
if(!input_device->Poll(Key::Left)) input |= 32;
if(!input_device->Poll(Key::Up)) input |= 64;
if(!input_device->Poll(Key::Down)) input |= 128;
if(!input_device->Poll(Key::R)) input |= 256;
if(!input_device->Poll(Key::L)) input |= 512;
if(pressed) {
input.value &= ~bit;
} else {
input.value |= bit;
}

input_queue.Enqueue(input);
UpdateIRQ();
}

void KeyPad::UpdateIRQ() {
Expand All @@ -64,21 +50,7 @@ void KeyPad::UpdateIRQ() {
}
}

void KeyPad::Poll() {
PollInternal();
scheduler.Add(k_poll_interval, Scheduler::EventClass::KeyPad_Poll);
}

void KeyPad::PollInternal() {
while(input_queue.DataAvailable()) {
input.value = input_queue.Dequeue();
UpdateIRQ();
}
}

auto KeyPad::KeyInput::ReadByte(uint offset) -> u8 {
keypad->PollInternal();

switch(offset) {
case 0:
return u8(value);
Expand Down Expand Up @@ -133,38 +105,4 @@ void KeyPad::KeyControl::WriteHalf(u16 value) {
keypad->UpdateIRQ();
}

void KeyPad::InputQueue::Reset() {
rd_ptr = 0;
wr_ptr = 0;
size = 0;
}

bool KeyPad::InputQueue::DataAvailable() {
return size > 0;
}

void KeyPad::InputQueue::Enqueue(u16 input) {
data[wr_ptr] = input;
wr_ptr = (wr_ptr + 1) % k_buffer_size;

std::size_t current_size = size.load();

while(!size.compare_exchange_weak(current_size, std::min(current_size + 1u, k_buffer_size))) {
current_size = size.load();
}
}

auto KeyPad::InputQueue::Dequeue() -> u16 {
const u16 value = data[rd_ptr];
rd_ptr = (rd_ptr + 1) % k_buffer_size;

std::size_t current_size = size.load();

while(!size.compare_exchange_weak(current_size, current_size - 1)) {
current_size = size.load();
}

return value;
}

} // namespace nba::core
29 changes: 3 additions & 26 deletions src/nba/src/hw/keypad/keypad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

#pragma once

#include <atomic>
#include <nba/config.hpp>
#include <nba/core.hpp>
#include <nba/save_state.hpp>
#include <nba/scheduler.hpp>
#include <memory>
Expand All @@ -18,9 +17,10 @@
namespace nba::core {

struct KeyPad {
KeyPad(Scheduler& scheduler, IRQ& irq, std::shared_ptr<Config> config);
KeyPad(Scheduler& scheduler, IRQ& irq);

void Reset();
void SetKeyStatus(Key key, bool pressed);

struct KeyInput {
u16 value = 0x3FF;
Expand Down Expand Up @@ -50,33 +50,10 @@ struct KeyPad {
void CopyState(SaveState& state);

private:
static constexpr int k_poll_interval = 16384;

using Key = InputDevice::Key;

void UpdateInput();
void UpdateIRQ();

void Poll();
void PollInternal();

Scheduler& scheduler;
IRQ& irq;
std::shared_ptr<Config> config;

struct InputQueue {
static constexpr std::size_t k_buffer_size = 16;

std::atomic<u16> data[k_buffer_size];
std::atomic<std::size_t> size = 0;
std::size_t rd_ptr = 0;
std::size_t wr_ptr = 0;

void Reset();
bool DataAvailable();
void Enqueue(u16 input);
auto Dequeue() -> u16;
} input_queue{};
};

} // namespace nba::core
17 changes: 16 additions & 1 deletion src/platform/core/include/platform/emulator_thread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,34 @@ struct EmulatorThread {
void Stop();

void Reset();
void SetKeyStatus(Key key, bool pressed);

private:
enum class MessageType : u8 {
Reset
Reset,
SetKeyStatus
};

struct Message {
MessageType type;
union {
struct {
Key key;
u8bool pressed;
} set_key_status;
};
};

void PushMessage(const Message& message);
void ProcessMessages();

static constexpr int k_input_subsample_count = 4;
static constexpr int k_cycles_per_second = 16777216;
static constexpr int k_cycles_per_frame = 280896;
static constexpr int k_cycles_per_subsample = k_cycles_per_frame / k_input_subsample_count;

static_assert(k_cycles_per_frame % k_input_subsample_count == 0);

std::queue<Message> msg_queue;
std::mutex msg_queue_mutex;

Expand Down
Loading

0 comments on commit 01fd36f

Please sign in to comment.