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
12namespace openmsx {
13
15 : WD2793BasedFDC(config)
16{
17}
18
19byte 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
43byte 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
81const 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.data();
91 }
92}
93
94void 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.data();
136 }
137}
138
139template<typename Archive>
140void ToshibaFDC::serialize(Archive& ar, unsigned /*version*/)
141{
142 ar.template serializeBase<WD2793BasedFDC>(*this);
143}
146
147} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
bool peekDiskChanged() const override
void selectDrive(Drive num, EmuTime::param time)
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 std::array< byte, 0x10000 > unmappedRead
Definition MSXDevice.hh:306
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:307
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
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)
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
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
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:11
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)