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 
7 namespace openmsx {
8 
10  : WD2793BasedFDC(config)
11 {
13 }
14 
15 void PhilipsFDC::reset(EmuTime::param time)
16 {
18  writeMem(0x3FFC, 0x00, time);
19  writeMem(0x3FFD, 0x00, time);
20 }
21 
22 byte 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 
51 byte 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 
109 const 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;
120  }
121 }
122 
123 void 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;
175  }
176 }
177 
178 
179 template<typename Archive>
180 void 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 byte unmappedRead[0x10000]
Definition: MSXDevice.hh:301
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:131
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: MSXFDC.cc:57
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:62
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
bool peekIRQ(EmuTime::param time) const
Definition: WD2793.cc:110
byte peekStatusReg(EmuTime::param time) const
Definition: WD2793.cc:210
byte getTrackReg(EmuTime::param time) const
Definition: WD2793.cc:221
byte getDataReg(EmuTime::param time)
Definition: WD2793.cc:260
byte getSectorReg(EmuTime::param time) const
Definition: WD2793.cc:236
bool peekDTRQ(EmuTime::param time) const
Definition: WD2793.cc:95
bool getDTRQ(EmuTime::param time) const
Definition: WD2793.cc:90
byte getStatusReg(EmuTime::param time)
Definition: WD2793.cc:170
byte peekTrackReg(EmuTime::param time) const
Definition: WD2793.cc:226
void setTrackReg(byte value, EmuTime::param time)
Definition: WD2793.cc:216
void setDataReg(byte value, EmuTime::param time)
Definition: WD2793.cc:246
byte peekDataReg(EmuTime::param time) const
Definition: WD2793.cc:325
void setCommandReg(byte value, EmuTime::param time)
Definition: WD2793.cc:122
bool getIRQ(EmuTime::param time) const
Definition: WD2793.cc:105
void setSectorReg(byte value, EmuTime::param time)
Definition: WD2793.cc:231
byte peekSectorReg(EmuTime::param time) const
Definition: WD2793.cc:241
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:983