openMSX
MSXPSG.cc
Go to the documentation of this file.
1 #include "MSXPSG.hh"
2 #include "AY8910.hh"
3 #include "LedStatus.hh"
4 #include "CassettePort.hh"
5 #include "MSXMotherBoard.hh"
6 #include "JoystickPort.hh"
7 #include "RenShaTurbo.hh"
8 #include "serialize.hh"
9 #include "checked_cast.hh"
10 #include <memory>
11 
12 namespace openmsx {
13 
14 // MSXDevice
16  : MSXDevice(config)
17  , cassette(getMotherBoard().getCassettePort())
18  , renShaTurbo(getMotherBoard().getRenShaTurbo())
19  , selectedPort(0)
20  , prev(255)
21  , keyLayout((config.getChildData("keyboardlayout", {}) == "JIS") ? 0x40 : 0x00)
22  , addressMask(config.getChildDataAsBool("mirrored_registers", true) ? 0x0f : 0xff)
23 {
24  ports[0] = &getMotherBoard().getJoystickPort(0);
25  ports[1] = &getMotherBoard().getJoystickPort(1);
26  ay8910 = std::make_unique<AY8910>("PSG", *this, config, getCurrentTime());
27 
29 }
30 
32 {
33  powerDown(EmuTime::dummy());
34 }
35 
36 void MSXPSG::reset(EmuTime::param time)
37 {
38  registerLatch = 0;
39  ay8910->reset(time);
40 }
41 
42 void MSXPSG::powerDown(EmuTime::param /*time*/)
43 {
45 }
46 
47 byte MSXPSG::readIO(word /*port*/, EmuTime::param time)
48 {
49  return ay8910->readRegister(registerLatch, time);
50 }
51 
52 byte MSXPSG::peekIO(word /*port*/, EmuTime::param time) const
53 {
54  return ay8910->peekRegister(registerLatch, time);
55 }
56 
57 void MSXPSG::writeIO(word port, byte value, EmuTime::param time)
58 {
59  switch (port & 0x03) {
60  case 0:
61  registerLatch = value & addressMask;
62  break;
63  case 1:
64  ay8910->writeRegister(registerLatch, value, time);
65  break;
66  }
67 }
68 
69 
70 // AY8910Periphery
71 byte MSXPSG::readA(EmuTime::param time)
72 {
73  byte joystick = ports[selectedPort]->read(time) |
74  ((renShaTurbo.getSignal(time)) ? 0x10 : 0x00);
75 
76  // pin 6,7 input is ANDed with pin 6,7 output
77  byte pin67 = prev << (4 - 2 * selectedPort);
78  joystick &= (pin67| 0xCF);
79 
80  byte cassetteInput = cassette.cassetteIn(time) ? 0x80 : 0x00;
81  return joystick | keyLayout | cassetteInput;
82 }
83 
84 void MSXPSG::writeB(byte value, EmuTime::param time)
85 {
86  byte val0 = (value & 0x03) | ((value & 0x10) >> 2);
87  byte val1 = ((value & 0x0C) >> 2) | ((value & 0x20) >> 3);
88  ports[0]->write(val0, time);
89  ports[1]->write(val1, time);
90  selectedPort = (value & 0x40) >> 6;
91 
92  if ((prev ^ value) & 0x80) {
93  getLedStatus().setLed(LedStatus::KANA, !(value & 0x80));
94  }
95  prev = value;
96 }
97 
98 // version 1: initial version
99 // version 2: joystickportA/B moved from here to MSXMotherBoard
100 template<typename Archive>
101 void MSXPSG::serialize(Archive& ar, unsigned version)
102 {
103  ar.template serializeBase<MSXDevice>(*this);
104  ar.serialize("ay8910", *ay8910);
105  if (ar.versionBelow(version, 2)) {
106  assert(ar.isLoader());
107  // in older versions there were always 2 real joytsick ports
108  ar.serialize("joystickportA", *checked_cast<JoystickPort*>(ports[0]),
109  "joystickportB", *checked_cast<JoystickPort*>(ports[1]));
110  }
111  ar.serialize("registerLatch", registerLatch);
112  byte portB = prev;
113  ar.serialize("portB", portB);
114  if (ar.isLoader()) {
115  writeB(portB, getCurrentTime());
116  }
117  // selectedPort is derived from portB
118 }
120 REGISTER_MSXDEVICE(MSXPSG, "PSG");
121 
122 } // namespace openmsx
void serialize(Archive &ar, unsigned version)
Definition: MSXPSG.cc:101
virtual bool cassetteIn(EmuTime::param time)=0
Reads one bit from the cassette port.
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
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:47
~MSXPSG() override
Definition: MSXPSG.cc:31
virtual byte read(EmuTime::param time)=0
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:129
LedStatus & getLedStatus() const
Definition: MSXDevice.cc:157
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXPSG.cc:52
bool getSignal(EmuTime::param time)
Get the output signal in negative logic.
Definition: RenShaTurbo.cc:27
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:73
JoystickPortIf & getJoystickPort(unsigned port)
virtual void write(byte value, EmuTime::param time)=0
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
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:57
MSXPSG(const DeviceConfig &config)
Definition: MSXPSG.cc:15
void setLed(Led led, bool status)
Definition: LedStatus.cc:39
void powerDown(EmuTime::param time) override
This method is called when MSX is powered down.
Definition: MSXPSG.cc:42
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXPSG.cc:36