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 
16 {
18  writeMem(0x3FFC, 0x00, time);
19  writeMem(0x3FFD, 0x00, time);
20 }
21 
23 {
24  byte value;
25  switch (address & 0x3FFF) {
26  case 0x3FF8:
27  value = controller->getStatusReg(time);
28  break;
29  case 0x3FF9:
30  value = controller->getTrackReg(time);
31  break;
32  case 0x3FFA:
33  value = controller->getSectorReg(time);
34  break;
35  case 0x3FFB:
36  value = controller->getDataReg(time);
37  break;
38  case 0x3FFF:
39  value = 0xC0;
40  if (controller->getIRQ(time)) value &= ~0x40;
41  if (controller->getDTRQ(time)) value &= ~0x80;
42  break;
43  default:
44  value = PhilipsFDC::peekMem(address, time);
45  break;
46  }
47  return value;
48 }
49 
51 {
52  byte value;
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  value = controller->peekStatusReg(time);
61  break;
62  case 0x3FF9:
63  value = controller->peekTrackReg(time);
64  break;
65  case 0x3FFA:
66  value = controller->peekSectorReg(time);
67  break;
68  case 0x3FFB:
69  value = controller->peekDataReg(time);
70  break;
71  case 0x3FFC:
72  // bit 0 = side select
73  // TODO check other bits !!
74  value = sideReg; // value = multiplexer.getSideSelect();
75  break;
76  case 0x3FFD:
77  // bit 1,0 -> drive number
78  // (00 or 10: drive A, 01: drive B, 11: nothing)
79  // bit 7 -> motor on
80  // TODO check other bits !!
81  value = driveReg; // multiplexer.getSelectedDrive();
82  break;
83  case 0x3FFE:
84  // not used
85  value = 255;
86  break;
87  case 0x3FFF:
88  // Drive control IRQ and DRQ lines are not connected to Z80
89  // interrupt request
90  // bit 6: !intrq
91  // bit 7: !dtrq
92  // TODO check other bits !!
93  value = 0xC0;
94  if (controller->peekIRQ(time)) value &= ~0x40;
95  if (controller->peekDTRQ(time)) value &= ~0x80;
96  break;
97 
98  default:
99  if ((0x4000 <= address) && (address < 0x8000)) {
100  // ROM only visible in 0x4000-0x7FFF
101  value = MSXFDC::peekMem(address, time);
102  } else {
103  value = 255;
104  }
105  break;
106  }
107  return value;
108 }
109 
111 {
112  // if address overlap 0x7ff8-0x7ffb then return nullptr,
113  // else normal ROM behaviour
114  if ((start & 0x3FF8 & CacheLine::HIGH) == (0x3FF8 & CacheLine::HIGH)) {
115  return nullptr;
116  } else if ((0x4000 <= start) && (start < 0x8000)) {
117  // ROM visible in 0x4000-0x7FFF
118  return MSXFDC::getReadCacheLine(start);
119  } else {
120  return unmappedRead;
121  }
122 }
123 
124 void PhilipsFDC::writeMem(word address, byte value, EmuTime::param time)
125 {
126  switch (address & 0x3FFF) {
127  case 0x3FF8:
128  controller->setCommandReg(value, time);
129  break;
130  case 0x3FF9:
131  controller->setTrackReg(value, time);
132  break;
133  case 0x3FFA:
134  controller->setSectorReg(value, time);
135  break;
136  case 0x3FFB:
137  controller->setDataReg(value, time);
138  break;
139  case 0x3FFC:
140  // bit 0 = side select
141  // TODO check other bits !!
142  sideReg = value;
143  multiplexer->setSide(value & 1);
144  break;
145  case 0x3FFD:
146  // bit 1,0 -> drive number
147  // (00 or 10: drive A, 01: drive B, 11: nothing)
148  // TODO bit 6 -> drive LED (0 -> off, 1 -> on)
149  // bit 7 -> motor on
150  // TODO check other bits !!
151  driveReg = value;
153  switch (value & 3) {
154  case 0:
155  case 2:
157  break;
158  case 1:
160  break;
161  case 3:
162  default:
164  }
165  multiplexer->selectDrive(drive, time);
166  multiplexer->setMotor((value & 128) != 0, time);
167  break;
168  }
169 }
170 
172 {
173  if ((address & 0x3FF8) == (0x3FF8 & CacheLine::HIGH)) {
174  return nullptr;
175  } else {
176  return unmappedWrite;
177  }
178 }
179 
180 
181 template<typename Archive>
182 void PhilipsFDC::serialize(Archive& ar, unsigned /*version*/)
183 {
184  ar.template serializeBase<WD2793BasedFDC>(*this);
185  ar.serialize("sideReg", sideReg);
186  ar.serialize("driveReg", driveReg);
187 }
189 REGISTER_MSXDEVICE(PhilipsFDC, "PhilipsFDC");
190 
191 } // namespace openmsx
REGISTER_MSXDEVICE(DebugDevice,"DebugDevice")
void reset(EmuTime::param time) override
This method is called on reset.
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:110
const std::unique_ptr< DriveMultiplexer > multiplexer
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:136
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:27
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
void reset(EmuTime::param time) override
This method is called on reset.
Definition: PhilipsFDC.cc:15
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:58
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:124
const std::unique_ptr< WD2793 > controller
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:7
unsigned short word
16 bit unsigned integer
Definition: openmsx.hh:32
void serialize(Archive &ar, unsigned version)
Definition: PhilipsFDC.cc:182
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:266
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: MSXFDC.cc:53
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:802
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:267
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: PhilipsFDC.cc:50
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
Definition: PhilipsFDC.cc:171
PhilipsFDC(const DeviceConfig &config)
Definition: PhilipsFDC.cc:9