openMSX
ToshibaFDC.cc
Go to the documentation of this file.
1 #include "ToshibaFDC.hh"
2 #include "CacheLine.hh"
3 #include "DriveMultiplexer.hh"
4 #include "WD2793.hh"
5 #include "serialize.hh"
6 
7 // Based on studying the code in the Toshiba disk ROM.
8 // Thanks to Arjen Zeilemaker for an annotated disassembly:
9 // https://sourceforge.net/p/msxsyssrc/git/ci/master/tree/diskdrvs/hx-f101/driver.mac
10 // https://sourceforge.net/p/msxsyssrc/git/ci/master/tree/diskdrvs/hx-34/driver.mac
11 
12 namespace openmsx {
13 
15  : WD2793BasedFDC(config)
16 {
17 }
18 
19 byte ToshibaFDC::readMem(word address, EmuTime::param time)
20 {
21  switch (address) {
22  case 0x7FF0:
23  return controller.getStatusReg(time);
24  case 0x7FF1:
25  return controller.getTrackReg(time);
26  case 0x7FF2:
27  return controller.getSectorReg(time);
28  case 0x7FF3:
29  return controller.getDataReg(time);
30  case 0x7FF6:
31  return 0xFE | (multiplexer.diskChanged() ? 0 : 1);
32  case 0x7FF7: {
33  byte value = 0xFF;
34  if (controller.getIRQ(time)) value &= ~0x40;
35  if (controller.getDTRQ(time)) value &= ~0x80;
36  return value;
37  }
38  default:
39  return ToshibaFDC::peekMem(address, time);
40  }
41 }
42 
43 byte ToshibaFDC::peekMem(word address, EmuTime::param time) const
44 {
45  switch (address) { // checked on real HW: no mirroring
46  case 0x7FF0:
47  return controller.peekStatusReg(time);
48  case 0x7FF1:
49  return controller.peekTrackReg(time);
50  case 0x7FF2:
51  return controller.peekSectorReg(time);
52  case 0x7FF3:
53  return controller.peekDataReg(time);
54  case 0x7FF4:
55  // ToshibaFDC HX-F101 disk ROM doesn't read this, but HX-34
56  // does. No idea if this location is actually readable on
57  // HX-F101, but currently the emulation is the same for both.
58  return 0xFC
59  | (multiplexer.getSide() ? 1 : 0)
60  | (multiplexer.getMotor() ? 2 : 0);
61  case 0x7FF5:
62  return 0xFE | ((multiplexer.getSelectedDrive() == DriveMultiplexer::DRIVE_B) ? 1 : 0);
63  case 0x7FF6:
64  return 0xFE | (multiplexer.peekDiskChanged() ? 0 : 1);
65  case 0x7FF7: {
66  byte value = 0xFF; // unused bits read as 1
67  if (controller.peekIRQ(time)) value &= ~0x40;
68  if (controller.peekDTRQ(time)) value &= ~0x80;
69  return value;
70  }
71  default:
72  if (0x4000 <= address && address < 0x8000) {
73  // ROM only visible in 0x4000-0x7FFF.
74  return MSXFDC::peekMem(address, time);
75  } else {
76  return 0xFF;
77  }
78  }
79 }
80 
81 const byte* ToshibaFDC::getReadCacheLine(word start) const
82 {
83  if ((start & CacheLine::HIGH) == (0x7FF0 & CacheLine::HIGH)) {
84  // FDC at 0x7FF0-0x7FF7
85  return nullptr;
86  } else if (0x4000 <= start && start < 0x8000) {
87  // ROM at 0x4000-0x7FFF
88  return MSXFDC::getReadCacheLine(start);
89  } else {
90  return unmappedRead;
91  }
92 }
93 
94 void ToshibaFDC::writeMem(word address, byte value, EmuTime::param time)
95 {
96  switch (address) {
97  case 0x7FF0:
98  controller.setCommandReg(value, time);
99  break;
100  case 0x7FF1:
101  controller.setTrackReg(value, time);
102  break;
103  case 0x7FF2:
104  controller.setSectorReg(value, time);
105  break;
106  case 0x7FF3:
107  controller.setDataReg(value, time);
108  break;
109  case 0x7FF4:
110  multiplexer.setSide((value & 0x01) != 0); // no effect on HX-F101 because it has single sided drive
111  multiplexer.setMotor((value & 0x02) != 0, time);
112  break;
113  case 0x7FF5:
114  // Disk ROM only writes the values 0 or 1.
117  time);
118  break;
119  case 0x7FF6:
120  // Disk ROM writes '1' (to drive A) and shortly after '0' (to drive B).
121  // TODO What does this do? Activate the 'disk is changed' state?
122  // And if so, does the written value matter?
123  break;
124  case 0x7FF7:
125  // Probably no function, disk ROM doesn't write to this address.
126  break;
127  }
128 }
129 
131 {
132  if ((address & CacheLine::HIGH) == (0x7FF0 & CacheLine::HIGH)) {
133  return nullptr;
134  } else {
135  return unmappedWrite;
136  }
137 }
138 
139 template<typename Archive>
140 void ToshibaFDC::serialize(Archive& ar, unsigned /*version*/)
141 {
142  ar.template serializeBase<WD2793BasedFDC>(*this);
143 }
146 
147 } // 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)
DriveNum getSelectedDrive() const
bool getMotor() const override
Returns the previously set motor status.
bool getSide() const override
bool diskChanged() override
Is disk changed?
void setSide(bool side) override
Side select.
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:301
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
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: ToshibaFDC.cc:19
void serialize(Archive &ar, unsigned version)
Definition: ToshibaFDC.cc:140
ToshibaFDC(const DeviceConfig &config)
Definition: ToshibaFDC.cc:14
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: ToshibaFDC.cc:81
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: ToshibaFDC.cc:94
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: ToshibaFDC.cc:43
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: ToshibaFDC.cc:130
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