OXYGENHUB
◆ main openmsx / src / MSXPPI.cc
3.6 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "MSXPPI.hh"
2
3
#include "CassettePort.hh"
4
#include "GlobalSettings.hh"
5
#include "LedStatus.hh"
6
#include "MSXCPUInterface.hh"
7
#include "MSXMotherBoard.hh"
8
#include "Reactor.hh"
9
#include "RenShaTurbo.hh"
10
#include "serialize.hh"
11
12
namespace openmsx {
13
14
MSXPPI::MSXPPI(const DeviceConfig& config)
15
	: MSXDevice(config)
16
	, cassettePort(getMotherBoard().getCassettePort())
17
	, renshaTurbo(getMotherBoard().getRenShaTurbo())
18
	, i8255(*this, getCurrentTime(), config.getGlobalSettings().getInvalidPpiModeSetting())
19
	, click(config)
20
	, keyboard(
21
		config.getMotherBoard(),
22
		config.getMotherBoard().getScheduler(),
23
		config.getMotherBoard().getCommandController(),
24
		config.getMotherBoard().getReactor().getEventDistributor(),
25
		config.getMotherBoard().getMSXEventDistributor(),
26
		config.getMotherBoard().getStateChangeDistributor(),
27
		Keyboard::Matrix::MSX, config)
28
{
29
	reset(getCurrentTime());
30
}
31
32
MSXPPI::~MSXPPI()
33
{
34
	powerDown(EmuTime::dummy());
35
}
36
37
void MSXPPI::reset(EmuTime time)
38
{
39
	i8255.reset(time);
40
	click.reset(time);
41
}
42
43
void MSXPPI::powerDown(EmuTime /*time*/)
44
{
45
	getLedStatus().setLed(LedStatus::CAPS, false);
46
}
47
48
uint8_t MSXPPI::readIO(uint16_t port, EmuTime time)
49
{
50
	return i8255.read(port & 0x03, time);
51
}
52
53
uint8_t MSXPPI::peekIO(uint16_t port, EmuTime time) const
54
{
55
	return i8255.peek(port & 0x03, time);
56
}
57
58
void MSXPPI::writeIO(uint16_t port, uint8_t value, EmuTime time)
59
{
60
	i8255.write(port & 0x03, value, time);
61
}
62
63
64
// I8255Interface
65
66
uint8_t MSXPPI::readA(EmuTime time)
67
{
68
	return peekA(time);
69
}
70
uint8_t MSXPPI::peekA(EmuTime /*time*/) const
71
{
72
	// port A is normally an output on MSX, reading from an output port
73
	// is handled internally in the 8255
74
	// TODO check this on a real MSX
75
	// TODO returning 0 fixes the 'get_selected_slot' script right after
76
	//      reset (when PPI directions are not yet set). For now this
77
	//      solution is good enough.
78
	return 0;
79
}
80
void MSXPPI::writeA(uint8_t value, EmuTime /*time*/)
81
{
82
	getCPUInterface().setPrimarySlots(value);
83
}
84
85
uint8_t MSXPPI::readB(EmuTime time)
86
{
87
	return peekB(time);
88
}
89
uint8_t MSXPPI::peekB(EmuTime time) const
90
{
91
	auto row = keyboard.getKeys()[selectedRow];
92
	if (selectedRow == 8) {
93
		row |= renshaTurbo.getSignal(time) ? 1 : 0;
94
	}
95
	return row;
96
}
97
void MSXPPI::writeB(uint8_t /*value*/, EmuTime /*time*/)
98
{
99
	// probably nothing happens on a real MSX
100
}
101
102
uint4_t MSXPPI::readC1(EmuTime time)
103
{
104
	return peekC1(time);
105
}
106
uint4_t MSXPPI::peekC1(EmuTime /*time*/) const
107
{
108
	return 15; // TODO check this
109
}
110
uint4_t MSXPPI::readC0(EmuTime time)
111
{
112
	return peekC0(time);
113
}
114
uint4_t MSXPPI::peekC0(EmuTime /*time*/) const
115
{
116
	return 15; // TODO check this
117
}
118
void MSXPPI::writeC1(uint4_t value, EmuTime time)
119
{
120
	if ((prevBits ^ value) & 1) {
121
		cassettePort.setMotor((value & 1) == 0, time); // 0=0n, 1=Off
122
	}
123
	if ((prevBits ^ value) & 2) {
124
		cassettePort.cassetteOut((value & 2) != 0, time);
125
	}
126
	if ((prevBits ^ value) & 4) {
127
		getLedStatus().setLed(LedStatus::CAPS, (value & 4) == 0);
128
	}
129
	if ((prevBits ^ value) & 8) {
130
		click.setClick((value & 8) != 0, time);
131
	}
132
	prevBits = value;
133
}
134
void MSXPPI::writeC0(uint4_t value, EmuTime /*time*/)
135
{
136
	selectedRow = value;
137
}
138
139
140
template<typename Archive>
141
void MSXPPI::serialize(Archive& ar, unsigned /*version*/)
142
{
143
	ar.template serializeBase<MSXDevice>(*this);
144
	ar.serialize("i8255", i8255);
145
146
	// merge prevBits and selectedRow into one byte
147
	auto portC = uint8_t((prevBits << 4) | (selectedRow << 0));
148
	ar.serialize("portC", portC);
149
	if constexpr (Archive::IS_LOADER) {
150
		selectedRow = (portC >> 0) & 0xF;
151
		uint4_t bits = (portC >> 4) & 0xF;
152
		writeC1(bits, getCurrentTime());
153
	}
154
	ar.serialize("keyboard", keyboard);
155
}
156
INSTANTIATE_SERIALIZE_METHODS(MSXPPI);
157
REGISTER_MSXDEVICE(MSXPPI, "PPI");
158
159
} // namespace openmsx