openMSX
SVIPSG.cc
Go to the documentation of this file.
1 #include "SVIPSG.hh"
2 #include "LedStatus.hh"
3 #include "MSXCPUInterface.hh"
4 #include "MSXMotherBoard.hh"
5 #include "JoystickPort.hh"
6 #include "serialize.hh"
7 #include "stl.hh"
8 
9 // Slot 0 Slot 1 Slot 2 Slot 3
10 // FFFF +---------+---------+---------+---------+
11 // | Bank 2 | Bank 12 | Bank 22 | Bank 32 | Page 3
12 // | RAM |ROM Cart | RAM | RAM |
13 // 8000 |00000000 |01010000 |10100000 |11110000 | Page 2
14 // +---------+---------+---------+---------+
15 // 7FFF | Bank 1 | Bank 11 | Bank 21 | Bank 31 | Page 1
16 // |ROM BASIC|ROM Cart | RAM | RAM |
17 // |00000000 |00000101 |00001010 |00001111 | Page 0
18 // 0000 +---------+---------+---------+---------+
19 //
20 // PSG Port A Input
21 // Bit Name Description
22 // 0 FWD1 Joystick 1, Forward
23 // 1 BACK1 Joystick 1, Back
24 // 2 LEFT1 Joystick 1, Left
25 // 3 RIGHT1 Joystick 1, Right
26 // 4 FWD2 Joystick 2, Forward
27 // 5 BACK2 Joystick 2, Back
28 // 6 LEFT2 Joystick 2, Left
29 // 7 RIGHT2 Joystick 2, Right
30 //
31 // PSG Port B Output
32 // Bit Name Description
33 // 0 /CART Memory bank 11, ROM 0000-7FFF (cartridge /CCS1, /CCS2)
34 // 1 /BK21 Memory bank 21, RAM 0000-7FFF
35 // 2 /BK22 Memory bank 22, RAM 8000-FFFF
36 // 3 /BK31 Memory bank 31, RAM 0000-7FFF
37 // 4 /BK32 Memory bank 32, RAM 8000-7FFF
38 // 5 CAPS Caps-Lock LED
39 // 6 /ROMEN0 Memory bank 12, ROM 8000-BFFF* (cartridge /CCS3)
40 // 7 /ROMEN1 Memory bank 12, ROM C000-FFFF* (cartridge /CCS4)
41 //
42 // * The /CART signal must be active for any effect,
43 // then all banks of RAM are disabled.
44 
45 namespace openmsx {
46 
47 // MSXDevice
48 
50  : MSXDevice(config)
51  , ports(generate_array<2>([&](auto i) { return &getMotherBoard().getJoystickPort(unsigned(i)); }))
52  , ay8910("PSG", *this, config, getCurrentTime())
53  , prev(255)
54 {
55  reset(getCurrentTime());
56 }
57 
59 {
60  powerDown(EmuTime::dummy());
61 }
62 
63 void SVIPSG::reset(EmuTime::param time)
64 {
65  registerLatch = 0;
66  ay8910.reset(time);
67 }
68 
69 void SVIPSG::powerDown(EmuTime::param /*time*/)
70 {
72 }
73 
74 byte SVIPSG::readIO(word /*port*/, EmuTime::param time)
75 {
76  return ay8910.readRegister(registerLatch, time);
77 }
78 
79 byte SVIPSG::peekIO(word /*port*/, EmuTime::param time) const
80 {
81  return ay8910.peekRegister(registerLatch, time);
82 }
83 
84 void SVIPSG::writeIO(word port, byte value, EmuTime::param time)
85 {
86  switch (port & 0x07) {
87  case 0:
88  registerLatch = value & 0x0F;
89  break;
90  case 4:
91  ay8910.writeRegister(registerLatch, value, time);
92  break;
93  }
94 }
95 
96 // AY8910Periphery
97 
98 byte SVIPSG::readA(EmuTime::param time)
99 {
100  return ((ports[1]->read(time) & 0x0F) << 4) |
101  ((ports[0]->read(time) & 0x0F) << 0);
102 }
103 
104 void SVIPSG::writeB(byte value, EmuTime::param /*time*/)
105 {
106  getMotherBoard().getLedStatus().setLed(LedStatus::CAPS, (value & 0x20) != 0);
107 
108  // Default to bank 1 and 2
109  byte psReg = 0;
110  switch (~value & 0x14) {
111  case 0x04: // bk22
112  psReg = 0xa0;
113  break;
114  case 0x10: // bk32
115  psReg = 0xf0;
116  break;
117  }
118  switch (~value & 0x0B) {
119  case 1: // bk12 (cart)?
120  if ((~value & 0x80) || (~value & 0x40)) {
121  psReg = 0x50;
122  }
123  // bk11 (cart)
124  psReg |= 0x05;
125  break;
126  case 2: // bk21
127  psReg |= 0x0a;
128  break;
129  case 8: // bk31
130  psReg |= 0x0f;
131  break;
132  }
134 
135  prev = value;
136 }
137 
138 template<typename Archive>
139 void SVIPSG::serialize(Archive& ar, unsigned /*version*/)
140 {
141  ar.template serializeBase<MSXDevice>(*this);
142  ar.serialize("ay8910", ay8910,
143  "registerLatch", registerLatch);
144  byte portB = prev;
145  ar.serialize("portB", portB);
146  if constexpr (Archive::IS_LOADER) {
147  writeB(portB, getCurrentTime());
148  }
149 }
151 REGISTER_MSXDEVICE(SVIPSG, "SVI-328 PSG");
152 
153 } // namespace openmsx
void reset(EmuTime::param time)
Definition: AY8910.cc:525
byte readRegister(unsigned reg, EmuTime::param time)
Definition: AY8910.cc:538
byte peekRegister(unsigned reg, EmuTime::param time) const
Definition: AY8910.cc:563
void writeRegister(unsigned reg, byte value, EmuTime::param time)
Definition: AY8910.cc:582
void setLed(Led led, bool status)
Definition: LedStatus.cc:40
void setPrimarySlots(byte value)
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
MSXCPUInterface & getCPUInterface()
JoystickPortIf & getJoystickPort(unsigned port)
void powerDown(EmuTime::param time) override
This method is called when MSX is powered down.
Definition: SVIPSG.cc:69
SVIPSG(const DeviceConfig &config)
Definition: SVIPSG.cc:49
~SVIPSG() override
Definition: SVIPSG.cc:58
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: SVIPSG.cc:79
void serialize(Archive &ar, unsigned version)
Definition: SVIPSG.cc:139
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: SVIPSG.cc:74
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: SVIPSG.cc:84
void reset(EmuTime::param time) override
This method is called on reset.
Definition: SVIPSG.cc:63
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