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
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 std::array< byte, 0x10000 > unmappedRead
Definition: MSXDevice.hh:302
static std::array< byte, 0x10000 > unmappedWrite
Definition: MSXDevice.hh:303
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)
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
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