openMSX
NinjaTap.cc
Go to the documentation of this file.
1#include "NinjaTap.hh"
2#include "JoystickPort.hh"
3#include "enumerate.hh"
4#include "ranges.hh"
5#include "serialize.hh"
6
7// See this (long) MRC thread for a detailed discussion on NinjaTap, including
8// an electric schema.
9// https://www.msx.org/forum/msx-talk/hardware/ninja-tap
10
11namespace openmsx {
12
13NinjaTap::NinjaTap(PluggingController& pluggingController_, std::string name_)
14 : JoyTap(pluggingController_, std::move(name_))
15{
16 ranges::fill(buf, 0xFF);
17}
18
19std::string_view NinjaTap::getDescription() const
20{
21 return "MSX Ninja Tap device";
22}
23
24
25void NinjaTap::plugHelper(Connector& /*connector*/, EmuTime::param time)
26{
27 createPorts("Ninja Tap port", time);
28}
29
30uint8_t NinjaTap::read(EmuTime::param /*time*/)
31{
32 return status;
33}
34
35void NinjaTap::write(uint8_t value, EmuTime::param time)
36{
37 // bit 0 -> pin 6
38 // bit 1 -> pin 7
39 // bit 2 -> pin 8
40 if (value & 2) {
41 // pin7 = 1 : read mode
42 if (!(value & 1) && (previous & 1)) {
43 // pin 6 1->0 : query joysticks
44 // TODO does output change?
45 for (auto [i, slave] : enumerate(slaves)) {
46 uint8_t t = slave->read(time);
47 buf[i] = ((t & 0x0F) << 4) |
48 ((t & 0x30) >> 4) |
49 0x0C;
50 }
51 }
52 if (!(value & 4) && (previous & 4)) {
53 // pin 8 1->0 : shift values
54 // TODO what about b4 and b5?
55 uint8_t t = 0;
56 for (auto [i, b] : enumerate(buf)) {
57 if (b & 1) t |= (1 << i);
58 b >>= 1;
59 }
60 status = (status & ~0x0F) | t;
61 }
62 }
63
64 // pin7 (b5) is always the inverse of pin8
65 // See Danjovic's post from 08-10-2022, 06:58
66 // https://www.msx.org/forum/msx-talk/hardware/ninja-tap?page=7
67 if (value & 4) {
68 status &= ~0x20;
69 } else {
70 status |= 0x20;
71 }
72
73 previous = value;
74}
75
76
77template<typename Archive>
78void NinjaTap::serialize(Archive& ar, unsigned /*version*/)
79{
80 ar.template serializeBase<JoyTap>(*this);
81 ar.serialize("status", status,
82 "previous", previous,
83 "buf", buf);
84}
87
88} // namespace openmsx
TclObject t
Represents something you can plug devices into.
Definition: Connector.hh:21
This device is plugged in into the joy-ports and consolidates several other joysticks plugged into it...
Definition: JoyTap.hh:23
std::array< std::optional< JoystickPort >, 4 > slaves
Definition: JoyTap.hh:44
void createPorts(static_string_view description, EmuTime::param time)
Definition: JoyTap.cc:17
void plugHelper(Connector &connector, EmuTime::param time) override
Definition: NinjaTap.cc:25
void serialize(Archive &ar, unsigned version)
Definition: NinjaTap.cc:78
std::string_view getDescription() const override
Description for this pluggable.
Definition: NinjaTap.cc:19
NinjaTap(PluggingController &pluggingController, std::string name)
Definition: NinjaTap.cc:13
uint8_t read(EmuTime::param time) override
Read from the joystick device.
Definition: NinjaTap.cc:30
void write(uint8_t value, EmuTime::param time) override
Write a value to the joystick device.
Definition: NinjaTap.cc:35
Central administration of Connectors and Pluggables.
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition: enumerate.hh:28
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
constexpr void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:287
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1021