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 namespace openmsx {
8 
9 NinjaTap::NinjaTap(PluggingController& pluggingController_, std::string name_)
10  : JoyTap(pluggingController_, std::move(name_))
11  , status(0x3F) // TODO check initial value
12  , previous(0)
13 {
14  ranges::fill(buf, 0xFF);
15 }
16 
17 std::string_view NinjaTap::getDescription() const
18 {
19  return "MSX Ninja Tap device";
20 }
21 
22 
23 void NinjaTap::plugHelper(Connector& /*connector*/, EmuTime::param /*time*/)
24 {
25  createPorts("Ninja Tap port");
26 }
27 
28 byte NinjaTap::read(EmuTime::param /*time*/)
29 {
30  return status;
31 }
32 
33 void NinjaTap::write(byte value, EmuTime::param time)
34 {
35  // bit 0 -> pin 6
36  // bit 1 -> pin 7
37  // bit 2 -> pin 8
38  if (value & 2) {
39  // pin7 = 1 : read mode
40  if (!(value & 1) && (previous & 1)) {
41  // pin 6 1->0 : query joysticks
42  // TODO does output change?
43  for (auto [i, slave] : enumerate(slaves)) {
44  byte t = slave->read(time);
45  buf[i] = ((t & 0x0F) << 4) |
46  ((t & 0x30) >> 4) |
47  0x0C;
48  }
49  }
50  if (!(value & 4) && (previous & 4)) {
51  // pin 8 1->0 : shift values
52  // TODO what about b4 and b5?
53  byte t = 0;
54  for (auto [i, b] : enumerate(buf)) {
55  if (b & 1) t |= (1 << i);
56  b >>= 1;
57  }
58  status = (status & ~0x0F) | t;
59  }
60  } else {
61  // pin 7 = 0 : detect mode, b5 is inverse of pin8
62  // TODO what happens with other bits?
63  if (value & 4) {
64  status &= ~0x20;
65  } else {
66  status |= 0x20;
67  }
68  }
69  previous = value;
70 }
71 
72 
73 template<typename Archive>
74 void NinjaTap::serialize(Archive& ar, unsigned /*version*/)
75 {
76  ar.template serializeBase<JoyTap>(*this);
77  ar.serialize("status", status,
78  "previous", previous,
79  "buf", buf);
80 }
83 
84 } // namespace openmsx
TclObject t
Represents something you can plug devices into.
Definition: Connector.hh:21
This device is plugged in into the joyports and consolidates several other joysticks plugged into it.
Definition: JoyTap.hh:22
void createPorts(static_string_view description)
Definition: JoyTap.cc:16
std::optional< JoystickPort > slaves[4]
Definition: JoyTap.hh:43
void plugHelper(Connector &connector, EmuTime::param time) override
Definition: NinjaTap.cc:23
void serialize(Archive &ar, unsigned version)
Definition: NinjaTap.cc:74
std::string_view getDescription() const override
Description for this pluggable.
Definition: NinjaTap.cc:17
NinjaTap(PluggingController &pluggingController, std::string name)
Definition: NinjaTap.cc:9
byte read(EmuTime::param time) override
Read from the joystick device.
Definition: NinjaTap.cc:28
void write(byte value, EmuTime::param time) override
Write a value to the joystick device.
Definition: NinjaTap.cc:33
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")
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:257
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1009