openMSX
PhilipsFDC.cc
Go to the documentation of this file.
1#include "PhilipsFDC.hh"
2#include "CacheLine.hh"
3#include "DriveMultiplexer.hh"
4#include "WD2793.hh"
5#include "serialize.hh"
6
7namespace openmsx {
8
10 : WD2793BasedFDC(config)
11{
13}
14
15void PhilipsFDC::reset(EmuTime::param time)
16{
18 writeMem(0x3FFC, 0x00, time);
19 writeMem(0x3FFD, 0x00, time);
20}
21
22byte PhilipsFDC::readMem(word address, EmuTime::param time)
23{
24 switch (address & 0x3FFF) {
25 case 0x3FF8:
26 return controller.getStatusReg(time);
27 case 0x3FF9:
28 return controller.getTrackReg(time);
29 case 0x3FFA:
30 return controller.getSectorReg(time);
31 case 0x3FFB:
32 return controller.getDataReg(time);
33 case 0x3FFD: {
34 byte res = driveReg & ~4;
35 if (!multiplexer.diskChanged()) {
36 res |= 4;
37 }
38 return res;
39 }
40 case 0x3FFF: {
41 byte value = 0xC0;
42 if (controller.getIRQ(time)) value &= ~0x40;
43 if (controller.getDTRQ(time)) value &= ~0x80;
44 return value;
45 }
46 default:
47 return PhilipsFDC::peekMem(address, time);
48 }
49}
50
51byte PhilipsFDC::peekMem(word address, EmuTime::param time) const
52{
53 // FDC registers are mirrored in
54 // 0x3FF8-0x3FFF
55 // 0x7FF8-0x7FFF
56 // 0xBFF8-0xBFFF
57 // 0xFFF8-0xFFFF
58 switch (address & 0x3FFF) {
59 case 0x3FF8:
60 return controller.peekStatusReg(time);
61 case 0x3FF9:
62 return controller.peekTrackReg(time);
63 case 0x3FFA:
64 return controller.peekSectorReg(time);
65 case 0x3FFB:
66 return controller.peekDataReg(time);
67 case 0x3FFC:
68 // bit 0 = side select
69 // TODO check other bits !!
70 return sideReg; // return multiplexer.getSideSelect();
71 case 0x3FFD: {
72 // bit 1,0 -> drive number
73 // (00 or 10: drive A, 01: drive B, 11: nothing)
74 // bit 2 -> 0 iff disk changed
75 // TODO This is required on Sony_HB-F500P.
76 // Do other machines have this bit as well?
77 // bit 7 -> motor on
78 // TODO check other bits !!
79 byte res = driveReg & ~4;
81 res |= 4;
82 }
83 return res;
84 }
85 case 0x3FFE:
86 // not used
87 return 255;
88 case 0x3FFF: {
89 // Drive control IRQ and DRQ lines are not connected to Z80
90 // interrupt request
91 // bit 6: !intrq
92 // bit 7: !dtrq
93 // TODO check other bits !!
94 byte value = 0xC0;
95 if (controller.peekIRQ(time)) value &= ~0x40;
96 if (controller.peekDTRQ(time)) value &= ~0x80;
97 return value;
98 }
99 default:
100 if ((0x4000 <= address) && (address < 0x8000)) {
101 // ROM only visible in 0x4000-0x7FFF
102 return MSXFDC::peekMem(address, time);
103 } else {
104 return 255;
105 }
106 }
107}
108
109const byte* PhilipsFDC::getReadCacheLine(word start) const
110{
111 // if address overlap 0x7ff8-0x7ffb then return nullptr,
112 // else normal ROM behaviour
113 if ((start & 0x3FF8 & CacheLine::HIGH) == (0x3FF8 & CacheLine::HIGH)) {
114 return nullptr;
115 } else if ((0x4000 <= start) && (start < 0x8000)) {
116 // ROM visible in 0x4000-0x7FFF
117 return MSXFDC::getReadCacheLine(start);
118 } else {
119 return unmappedRead.data();
120 }
121}
122
123void PhilipsFDC::writeMem(word address, byte value, EmuTime::param time)
124{
125 switch (address & 0x3FFF) {
126 case 0x3FF8:
127 controller.setCommandReg(value, time);
128 break;
129 case 0x3FF9:
130 controller.setTrackReg(value, time);
131 break;
132 case 0x3FFA:
133 controller.setSectorReg(value, time);
134 break;
135 case 0x3FFB:
136 controller.setDataReg(value, time);
137 break;
138 case 0x3FFC:
139 // bit 0 = side select
140 // TODO check other bits !!
141 sideReg = value;
142 multiplexer.setSide(value & 1);
143 break;
144 case 0x3FFD:
145 // bit 1,0 -> drive number
146 // (00 or 10: drive A, 01: drive B, 11: nothing)
147 // TODO bit 6 -> drive LED (0 -> off, 1 -> on)
148 // bit 7 -> motor on
149 // TODO check other bits !!
150 driveReg = value;
151 DriveMultiplexer::DriveNum drive = [&] {
152 switch (value & 3) {
153 case 0:
154 case 2:
156 case 1:
158 case 3:
159 default:
161 }
162 }();
163 multiplexer.selectDrive(drive, time);
164 multiplexer.setMotor((value & 128) != 0, time);
165 break;
166 }
167}
168
170{
171 if ((address & 0x3FF8) == (0x3FF8 & CacheLine::HIGH)) {
172 return nullptr;
173 } else {
174 return unmappedWrite.data();
175 }
176}
177
178
179template<typename Archive>
180void PhilipsFDC::serialize(Archive& ar, unsigned /*version*/)
181{
182 ar.template serializeBase<WD2793BasedFDC>(*this);
183 ar.serialize("sideReg", sideReg,
184 "driveReg", driveReg);
185}
188
189} // namespace openmsx
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
bool peekDiskChanged() const override
void selectDrive(DriveNum num, EmuTime::param time)
bool diskChanged() override
Is disk changed?
void setSide(bool side) override
Side select.
static std::array< byte, 0x10000 > unmappedRead
Definition: MSXDevice.hh:302
static std::array< byte, 0x10000 > unmappedWrite
Definition: MSXDevice.hh:303
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:125
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: MSXFDC.cc:55
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: MSXFDC.cc:60
void reset(EmuTime::param time) override
This method is called on reset.
Definition: PhilipsFDC.cc:15
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: PhilipsFDC.cc:169
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
Definition: PhilipsFDC.cc:123
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: PhilipsFDC.cc:109
void serialize(Archive &ar, unsigned version)
Definition: PhilipsFDC.cc:180
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: PhilipsFDC.cc:22
PhilipsFDC(const DeviceConfig &config)
Definition: PhilipsFDC.cc:9
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: PhilipsFDC.cc:51
void reset(EmuTime::param time) override
This method is called on reset.
DriveMultiplexer multiplexer
uint8_t peekDataReg(EmuTime::param time) const
Definition: WD2793.cc:314
bool peekIRQ(EmuTime::param time) const
Definition: WD2793.cc:99
uint8_t getStatusReg(EmuTime::param time)
Definition: WD2793.cc:159
void setTrackReg(uint8_t value, EmuTime::param time)
Definition: WD2793.cc:205
void setSectorReg(uint8_t value, EmuTime::param time)
Definition: WD2793.cc:220
uint8_t getTrackReg(EmuTime::param time) const
Definition: WD2793.cc:210
uint8_t peekSectorReg(EmuTime::param time) const
Definition: WD2793.cc:230
bool peekDTRQ(EmuTime::param time) const
Definition: WD2793.cc:84
void setCommandReg(uint8_t value, EmuTime::param time)
Definition: WD2793.cc:111
uint8_t peekTrackReg(EmuTime::param time) const
Definition: WD2793.cc:215
bool getDTRQ(EmuTime::param time) const
Definition: WD2793.cc:79
uint8_t peekStatusReg(EmuTime::param time) const
Definition: WD2793.cc:199
uint8_t getDataReg(EmuTime::param time)
Definition: WD2793.cc:249
void setDataReg(uint8_t value, EmuTime::param time)
Definition: WD2793.cc:235
bool getIRQ(EmuTime::param time) const
Definition: WD2793.cc:94
uint8_t getSectorReg(EmuTime::param time) const
Definition: WD2793.cc:225
constexpr unsigned HIGH
Definition: CacheLine.hh:10
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:1021