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
45namespace 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
63void SVIPSG::reset(EmuTime::param time)
64{
65 registerLatch = 0;
66 ay8910.reset(time);
67}
68
69void SVIPSG::powerDown(EmuTime::param /*time*/)
70{
72}
73
74byte SVIPSG::readIO(word /*port*/, EmuTime::param time)
75{
76 return ay8910.readRegister(registerLatch, time);
77}
78
79byte SVIPSG::peekIO(word /*port*/, EmuTime::param time) const
80{
81 return ay8910.peekRegister(registerLatch, time);
82}
83
84void 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
98byte SVIPSG::readA(EmuTime::param time)
99{
100 return ((ports[1]->read(time) & 0x0F) << 4) |
101 ((ports[0]->read(time) & 0x0F) << 0);
102}
103
104void 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
138template<typename Archive>
139void 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}
152
153} // namespace openmsx
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
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:1009