openMSX
SpectravideoFDC.cc
Go to the documentation of this file.
1#include "SpectravideoFDC.hh"
2#include "CacheLine.hh"
3#include "DriveMultiplexer.hh"
4#include "WD2793.hh"
5#include "MSXException.hh"
6#include "serialize.hh"
7
8// Note: although this implementation seems to work, it has not been checked on
9// real hardware how the FDC registers are mirrored across the slot, nor how
10// the ROM is visible in the slot. Currently FDC registers are implemented to
11// be mirrored all over the slot (as it seems that the MSX-DOS that came with
12// the SVI-707 needs that), and ROMs are implemented to be visible in page 1.
13//
14// This implementation is solely based on the MSX SVI-728 Service and Technical
15// Manual [Vol.1], page 3-7 (memory mapping of registers) and page 3-1 (ROM).
16// Thanks to Leonard Oliveira for interpreting some of the hardware schematics
17// in that same manual.
18// Thanks to Benoit Delvaux for providing some extra info and software to test
19// with.
20
21namespace openmsx {
22
24 : WD2793BasedFDC(config, "msxdos")
25 , cpmRom(getName() + " CP/M ROM", "rom", config, "cpm")
26{
27 if (cpmRom.size() != 0x1000) {
28 throw MSXException("CP/M ROM must be exactly 4kB in size.");
29 }
31}
32
33void SpectravideoFDC::reset(EmuTime::param /*time*/)
34{
35 cpmRomEnabled = true;
36 invalidateDeviceRCache(0x4000, 0x4000);
37}
38
39byte SpectravideoFDC::readMem(word address, EmuTime::param time)
40{
41 switch (address & 0x3FFF) {
42 case 0x3FB8:
43 return controller.getStatusReg(time);
44 case 0x3FB9:
45 return controller.getTrackReg(time);
46 case 0x3FBA:
47 return controller.getSectorReg(time);
48 case 0x3FBB:
49 return controller.getDataReg(time);
50 case 0x3FBC: {
51 byte value = 0;
52 if ( controller.getIRQ (time)) value |= 0x80;
53 if (!controller.getDTRQ(time)) value |= 0x40;
54 return value;
55 }
56 case 0x3FBE: // Software switch to turn on CP/M,
57 // boot ROM and turn off MSX DOS ROM.
58 cpmRomEnabled = true;
59 invalidateDeviceRCache(0x4000, 0x4000);
60 return 0xFF;
61 case 0x3FBF: // Software switch to turn off CP/M,
62 // boot ROM and turn on MSX DOS ROM.
63 cpmRomEnabled = false;
64 invalidateDeviceRCache(0x4000, 0x4000);
65 return 0xFF;
66 default:
67 return SpectravideoFDC::peekMem(address, time);
68 }
69}
70
71byte SpectravideoFDC::peekMem(word address, EmuTime::param time) const
72{
73 switch (address & 0x3FFF) {
74 case 0x3FB8:
75 return controller.peekStatusReg(time);
76 case 0x3FB9:
77 return controller.peekTrackReg(time);
78 case 0x3FBA:
79 return controller.peekSectorReg(time);
80 case 0x3FBB:
81 return controller.peekDataReg(time);
82 case 0x3FBC: {
83 // Drive control IRQ and DRQ lines are not connected to Z80 interrupt request
84 // bit 7: interrupt of 1793 (1 for interrupt)
85 // bit 6: data request of 1793 (0 for request)
86 // TODO: other bits read 0?
87 byte value = 0;
88 if ( controller.peekIRQ (time)) value |= 0x80;
89 if (!controller.peekDTRQ(time)) value |= 0x40;
90 return value;
91 }
92 default:
93 if ((0x4000 <= address) && (address < 0x8000) && !cpmRomEnabled) {
94 // MSX-DOS ROM only visible in 0x4000-0x7FFF
95 return MSXFDC::peekMem(address, time);
96 } else if ((0x4000 <= address) && (address < 0x5000) && cpmRomEnabled) {
97 // CP/M ROM only visible in 0x4000-0x4FFF
98 return cpmRom[address & 0x0FFF];
99 } else {
100 return 0xFF;
101 }
102 }
103}
104
106{
107 if ((start & 0x3FFF & CacheLine::HIGH) == (0x3FB8 & CacheLine::HIGH)) {
108 // FDC at 0x7FB8-0x7FBF, and mirrored in other pages
109 return nullptr;
110 } else if ((0x4000 <= start) && (start < 0x8000) && !cpmRomEnabled) {
111 // MSX-DOS ROM at 0x4000-0x7FFF
112 return MSXFDC::getReadCacheLine(start);
113 } else if ((0x4000 <= start) && (start < 0x5000) && cpmRomEnabled) {
114 // CP/M ROM at 0x4000-0x4FFF
115 return &cpmRom[start & 0x0FFF];
116 } else {
117 return unmappedRead.data();
118 }
119}
120
121void SpectravideoFDC::writeMem(word address, byte value, EmuTime::param time)
122{
123 switch (address & 0x3FFF) {
124 case 0x3FB8:
125 controller.setCommandReg(value, time);
126 break;
127 case 0x3FB9:
128 controller.setTrackReg(value, time);
129 break;
130 case 0x3FBA:
131 controller.setSectorReg(value, time);
132 break;
133 case 0x3FBB:
134 controller.setDataReg(value, time);
135 break;
136 case 0x3FBC:
137 // bit 0 -> enable drive (1 for ENABLE)
138 // bit 2 -> side select (0 for side 0)
139 // bit 3 -> motor on (1 for ON)
141 multiplexer.setSide ((value & 0x04) != 0);
142 multiplexer.setMotor ((value & 0x08) != 0, time);
143 break;
144 case 0x3FBE: // Software switch to turn on CP/M,
145 // boot ROM and turn off MSX DOS ROM.
146 invalidateDeviceRCache(0x4000, 0x4000);
147 cpmRomEnabled = true;
148 break;
149 case 0x3FBF: // Software switch to turn off CP/M,
150 // boot ROM and turn on MSX DOS ROM.
151 invalidateDeviceRCache(0x4000, 0x4000);
152 cpmRomEnabled = false;
153 break;
154 }
155}
156
158{
159 if ((address & 0x3FFF & CacheLine::HIGH) == (0x3FB8 & CacheLine::HIGH)) {
160 // FDC at 0x7FB8-0x7FBF - mirrored
161 return nullptr;
162 } else {
163 return unmappedWrite.data();
164 }
165}
166
167template<typename Archive>
168void SpectravideoFDC::serialize(Archive& ar, unsigned /*version*/)
169{
170 ar.template serializeBase<WD2793BasedFDC>(*this);
171 ar.serialize("cpmRomEnabled", cpmRomEnabled);
172}
175
176} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
void selectDrive(Drive num, EmuTime::param time)
void setSide(bool side) override
Side select.
void invalidateDeviceRCache()
Definition MSXDevice.hh:215
static std::array< byte, 0x10000 > unmappedRead
Definition MSXDevice.hh:306
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:307
EmuTime::param getCurrentTime() const
Definition MSXDevice.cc:125
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
auto size() const
Definition Rom.hh:36
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.
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.
SpectravideoFDC(const DeviceConfig &config)
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
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.
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
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)