openMSX
MSXPSG.cc
Go to the documentation of this file.
1#include "MSXPSG.hh"
2#include "LedStatus.hh"
3#include "CassettePort.hh"
4#include "MSXMotherBoard.hh"
5#include "JoystickPort.hh"
6#include "RenShaTurbo.hh"
7#include "StringOp.hh"
8#include "serialize.hh"
9#include "checked_cast.hh"
10#include "stl.hh"
11
12namespace openmsx {
13
14[[nodiscard]] static byte getKeyboardLayout(const MSXPSG& psg)
15{
16 // As many (mostly European) configs do not specify the layout
17 // in the PSG config, assume 50on for these cases.
18 auto value = psg.getDeviceConfig().getChildData("keyboardlayout", "50on");
19 StringOp::casecmp cmp; // case-insensitive
20 if (cmp(value, "50on")) {
21 return 0x00;
22 } else if (cmp(value, "jis")) {
23 return 0x40;
24 }
25 throw MSXException(
26 "Illegal keyboard layout configuration in '", psg.getName(),
27 "' device configuration: '", value,
28 "', expected 'jis' or '50on'.");
29}
30
31// MSXDevice
33 : MSXDevice(config)
34 , cassette(getMotherBoard().getCassettePort())
35 , renShaTurbo(getMotherBoard().getRenShaTurbo())
36 , ports(generate_array<2>([&](auto i) { return &getMotherBoard().getJoystickPort(unsigned(i)); }))
37 , selectedPort(0)
38 , prev(255)
39 , keyLayout(getKeyboardLayout(*this))
40 , addressMask(config.getChildDataAsBool("mirrored_registers", true) ? 0x0f : 0xff)
41 , ay8910(getName(), *this, config, getCurrentTime())
42{
43 reset(getCurrentTime());
44}
45
47{
48 powerDown(EmuTime::dummy());
49}
50
51void MSXPSG::reset(EmuTime::param time)
52{
53 registerLatch = 0;
54 ay8910.reset(time);
55}
56
57void MSXPSG::powerDown(EmuTime::param /*time*/)
58{
60}
61
62byte MSXPSG::readIO(word /*port*/, EmuTime::param time)
63{
64 return ay8910.readRegister(registerLatch, time);
65}
66
67byte MSXPSG::peekIO(word /*port*/, EmuTime::param time) const
68{
69 return ay8910.peekRegister(registerLatch, time);
70}
71
72void MSXPSG::writeIO(word port, byte value, EmuTime::param time)
73{
74 switch (port & 0x03) {
75 case 0:
76 registerLatch = value & addressMask;
77 break;
78 case 1:
79 ay8910.writeRegister(registerLatch, value, time);
80 break;
81 }
82}
83
84
85// AY8910Periphery
86byte MSXPSG::readA(EmuTime::param time)
87{
88 byte joystick = ports[selectedPort]->read(time) |
89 ((renShaTurbo.getSignal(time)) ? 0x10 : 0x00);
90
91#if 0
92 This breaks NinjaTap test programs.
93 Perhaps this behavior is different between MSX machines with a discrete
94 AY8910 chip versus machines with the PSG integrated in the MSX-engine?
95
96 // pin 6,7 input is ANDed with pin 6,7 output
97 byte pin67 = prev << (4 - 2 * selectedPort);
98 joystick &= (pin67| 0xCF);
99#endif
100
101 byte cassetteInput = cassette.cassetteIn(time) ? 0x80 : 0x00;
102 return joystick | keyLayout | cassetteInput;
103}
104
105void MSXPSG::writeB(byte value, EmuTime::param time)
106{
107 byte val0 = (value & 0x03) | ((value & 0x10) >> 2);
108 byte val1 = ((value & 0x0C) >> 2) | ((value & 0x20) >> 3);
109 ports[0]->write(val0, time);
110 ports[1]->write(val1, time);
111 selectedPort = (value & 0x40) >> 6;
112
113 if ((prev ^ value) & 0x80) {
114 getLedStatus().setLed(LedStatus::KANA, !(value & 0x80));
115 }
116 prev = value;
117}
118
119// version 1: initial version
120// version 2: joystickportA/B moved from here to MSXMotherBoard
121template<typename Archive>
122void MSXPSG::serialize(Archive& ar, unsigned version)
123{
124 ar.template serializeBase<MSXDevice>(*this);
125 ar.serialize("ay8910", ay8910);
126 if (ar.versionBelow(version, 2)) {
127 assert(Archive::IS_LOADER);
128 // in older versions there were always 2 real joystick ports
129 ar.serialize("joystickportA", *checked_cast<JoystickPort*>(ports[0]),
130 "joystickportB", *checked_cast<JoystickPort*>(ports[1]));
131 }
132 ar.serialize("registerLatch", registerLatch);
133 byte portB = prev;
134 ar.serialize("portB", portB);
135 if constexpr (Archive::IS_LOADER) {
136 writeB(portB, getCurrentTime());
137 }
138 // selectedPort is derived from portB
139}
142
143} // namespace openmsx
void test(const IterableBitSet< N > &s, std::initializer_list< size_t > list)
This class implements the AY-3-8910 sound chip.
Definition: AY8910.hh:20
void reset(EmuTime::param time)
Definition: AY8910.cc:524
byte readRegister(unsigned reg, EmuTime::param time)
Definition: AY8910.cc:537
byte peekRegister(unsigned reg, EmuTime::param time) const
Definition: AY8910.cc:562
void writeRegister(unsigned reg, byte value, EmuTime::param time)
Definition: AY8910.cc:581
virtual bool cassetteIn(EmuTime::param time)=0
Reads one bit from the cassette port.
void setLed(Led led, bool status)
Definition: LedStatus.cc:40
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
LedStatus & getLedStatus() const
Definition: MSXDevice.cc:154
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:126
JoystickPortIf & getJoystickPort(unsigned port)
MSXPSG(const DeviceConfig &config)
Definition: MSXPSG.cc:32
void powerDown(EmuTime::param time) override
This method is called when MSX is powered down.
Definition: MSXPSG.cc:57
~MSXPSG() override
Definition: MSXPSG.cc:46
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.
Definition: MSXPSG.cc:72
void serialize(Archive &ar, unsigned version)
Definition: MSXPSG.cc:122
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXPSG.cc:51
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXPSG.cc:62
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXPSG.cc:67
bool getSignal(EmuTime::param time)
Get the output signal in negative logic.
Definition: RenShaTurbo.cc:23
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:727
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:1009