openMSX
ColecoJoystickIO.cc
Go to the documentation of this file.
1 #include "ColecoJoystickIO.hh"
2 #include "MSXMotherBoard.hh"
3 #include "Reactor.hh"
4 #include "JoystickPort.hh"
5 #include "Math.hh"
6 #include "enumerate.hh"
7 #include "serialize.hh"
8 
9 namespace openmsx {
10 
12  : MSXDevice(config)
13  , keyboard(
14  config.getMotherBoard(),
15  config.getMotherBoard().getScheduler(),
16  config.getMotherBoard().getCommandController(),
17  config.getMotherBoard().getReactor().getEventDistributor(),
18  config.getMotherBoard().getMSXEventDistributor(),
19  config.getMotherBoard().getStateChangeDistributor(),
20  Keyboard::MATRIX_CVJOY,
21  config)
22 {
23  MSXMotherBoard& motherBoard = getMotherBoard();
24  auto time = getCurrentTime();
25  for (auto [i, port] : enumerate(ports)) {
26  port = &motherBoard.getJoystickPort(unsigned(i));
27  // Clear strobe bit, or MSX joysticks will stay silent.
28  port->write(0xFB, time);
29  }
30  reset(time);
31 }
32 
33 void ColecoJoystickIO::reset(EmuTime::param /*time*/)
34 {
35  joyMode = 0;
36 }
37 
38 byte ColecoJoystickIO::peekIO(word port, EmuTime::param time) const
39 {
40  const int joyPort = (port >> 1) & 1;
41  const byte joyStatus = ports[joyPort]->read(time);
42  const byte* keys = keyboard.getKeys();
43 
44  if (joyMode == 0) {
45  // Combine keypad rows, convert to high-active and drop unused bits.
46  // Note: The keypad can only return one button press, but I don't know
47  // what happens if you press two buttons at once.
48  unsigned keypadStatus = ~(
49  keys[joyPort * 2 + 2] | (keys[joyPort * 2 + 3] << 8)
50  ) & 0xFFF;
51  constexpr byte keyEnc[] = {
52  0xF, 0xA, 0xD, 0x7, 0xC, 0x2, 0x3, 0xE, 0x5, 0x1, 0xB, 0x9, 0x6
53  };
54  return keyEnc[Math::findFirstSet(keypadStatus)]
55  | 0x30 // not connected
56  | ((joyStatus << 1) & (keys[joyPort] >> 1) & 0x40); // trigger B
57  } else {
58  // Map MSX joystick direction bits to Coleco bits.
59  byte value =
60  ( joyStatus & 0x01) // up
61  | ((joyStatus >> 2) & 0x02) // right
62  | ((joyStatus << 1) & 0x04) // down
63  | ((joyStatus << 1) & 0x08) // left
64  | 0x30 // not connected
65  | ((joyStatus << 2) & 0x40) // trigger A
66  ;
67  // Note: ColEm puts 0 in bit 7.
68  // I don't know why this is different from bit 4 and 5.
69  // Combine with row 0/1 of keyboard matrix.
70  return value & (keys[joyPort] | ~0x4F);
71  }
72 }
73 
74 byte ColecoJoystickIO::readIO(word port, EmuTime::param time)
75 {
76  return peekIO(port, time);
77 }
78 
79 void ColecoJoystickIO::writeIO(word port, byte /*value*/, EmuTime::param /*time*/)
80 {
81  joyMode = (port >> 6) & 1;
82 }
83 
84 template<typename Archive>
85 void ColecoJoystickIO::serialize(Archive& ar, unsigned version)
86 {
87  ar.template serializeBase<MSXDevice>(*this);
88  ar.serialize("joyMode", joyMode);
89  if (ar.versionAtLeast(version, 2)) {
90  ar.serialize("keyboard", keyboard);
91  }
92 }
95 
96 } // namespace openmsx
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
ColecoJoystickIO(const DeviceConfig &config)
void serialize(Archive &ar, unsigned version)
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
void reset(EmuTime::param time) override
This method is called on reset.
virtual void write(byte value, EmuTime::param time)=0
virtual byte read(EmuTime::param time)=0
const byte * getKeys() const
Returns a pointer to the current KeyBoard matrix.
Definition: Keyboard.cc:356
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:71
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:126
JoystickPortIf & getJoystickPort(unsigned port)
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
unsigned findFirstSet(uint32_t x)
Find the least significant bit that is set.
Definition: Math.hh:234
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998