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