openMSX
CanonFDC.cc
Go to the documentation of this file.
1#include "CanonFDC.hh"
2#include "CacheLine.hh"
3#include "serialize.hh"
4
5// Technical info and discussion on:
6// https://www.msx.org/forum/msx-talk/hardware/canon-v-30f-msx2?page=8
7//
8// 0x7FF8: MB8877A command register (W) / Status register (R)
9// 0x7FF9: MB8877A track register (R/W)
10// 0x7FFA: MB8877A sector register (R/W)
11// 0x7FFB: MB8877A data register (R/W)
12// 0x7FFC: drive control
13// b1,b0: (R/W) drive select (0 = drive 0, 1 = drive 1, 3 = deselect drive)
14// b2: (R/W) side select (0 = side 0, 1 = side 1)
15// b3: (R/W) motor on (1 = motor on)
16// b4: (R) disk changed (0 = changed)
17// b5 (R) some sort of ready (1 = ready)
18// b6 (R) DRQ (1 = DRQ)
19// b7 (R) IRQ (1 = IRQ)
20// Hardware registers are also visible in page 2 (0xBFF8-0xBFFC).
21
22namespace openmsx {
23
25 : WD2793BasedFDC(config)
26{
27}
28
29void CanonFDC::reset(EmuTime::param time)
30{
32 writeMem(0x3FFC, 0, time);
33}
34
35byte CanonFDC::readMem(word address, EmuTime::param time)
36{
37 switch (address & 0x3FFF) {
38 case 0x3FF8:
39 return controller.getStatusReg(time);
40 case 0x3FF9:
41 return controller.getTrackReg(time);
42 case 0x3FFA:
43 return controller.getSectorReg(time);
44 case 0x3FFB:
45 return controller.getDataReg(time);
46 case 0x3FFC: {
47 // At address 0x76F4 in the disk ROM bit 5 is checked. If this
48 // bit is 0, the code executes a delay loop. Not sure what that
49 // is for. Some kind of hardware debug feature??
50 byte value = 0x30 | controlReg;
51 if (controller.getIRQ(time)) value |= 0x40;
52 if (controller.getDTRQ(time)) value |= 0x80;
53 if (multiplexer.diskChanged()) value &= ~0x10;
54 return value;
55 }
56 default:
57 return CanonFDC::peekMem(address, time);
58 }
59}
60
61byte CanonFDC::peekMem(word address, EmuTime::param time) const
62{
63 switch (address & 0x3FFF) {
64 case 0x3FF8:
65 return controller.peekStatusReg(time);
66 case 0x3FF9:
67 return controller.peekTrackReg(time);
68 case 0x3FFA:
69 return controller.peekSectorReg(time);
70 case 0x3FFB:
71 return controller.peekDataReg(time);
72 case 0x3FFC: {
73 byte value = 0x30 | controlReg;
74 if (controller.peekIRQ(time)) value |= 0x40;
75 if (controller.peekDTRQ(time)) value |= 0x80;
76 if (multiplexer.peekDiskChanged()) value &= ~0x10;
77 return value;
78 }
79 default:
80 return MSXFDC::peekMem(address, time);
81 }
82}
83
84const byte* CanonFDC::getReadCacheLine(word start) const
85{
86 if ((start & 0x3FFF & CacheLine::HIGH) == (0x3FF0 & CacheLine::HIGH)) {
87 // FDC at 0x7FF8-0x7FFC and 0xBFF8-0xBFFC
88 return nullptr;
89 } else {
90 return MSXFDC::getReadCacheLine(start);
91 }
92}
93
94void CanonFDC::writeMem(word address, byte value, EmuTime::param time)
95{
96 switch (address & 0x3FFF) {
97 case 0x3FF8:
98 controller.setCommandReg(value, time);
99 break;
100 case 0x3FF9:
101 controller.setTrackReg(value, time);
102 break;
103 case 0x3FFA:
104 controller.setSectorReg(value, time);
105 break;
106 case 0x3FFB:
107 controller.setDataReg(value, time);
108 break;
109 case 0x3FFC: {
110 controlReg = value & 0x0F;
111 auto drive = [&] {
112 switch (value & 3) {
113 case 0: return DriveMultiplexer::DRIVE_A;
114 case 1: return DriveMultiplexer::DRIVE_B;
115 default: return DriveMultiplexer::NO_DRIVE;
116 }
117 }();
118 multiplexer.selectDrive(drive, time);
119 multiplexer.setSide ((value & 0x04) != 0);
120 multiplexer.setMotor((value & 0x08) != 0, time);
121 break;
122 }
123 }
124}
125
127{
128 if ((address & 0x3FFF & CacheLine::HIGH) == (0x3FF0 & CacheLine::HIGH)) {
129 return nullptr;
130 } else {
131 return unmappedWrite.data();
132 }
133}
134
135template<typename Archive>
136void CanonFDC::serialize(Archive& ar, unsigned /*version*/)
137{
138 ar.template serializeBase<WD2793BasedFDC>(*this);
139 ar.serialize("controlReg", controlReg);
140}
143
144} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:354
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition CanonFDC.cc:35
void reset(EmuTime::param time) override
This method is called on reset.
Definition CanonFDC.cc:29
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition CanonFDC.cc:84
void serialize(Archive &ar, unsigned version)
Definition CanonFDC.cc:136
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition CanonFDC.cc:61
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition CanonFDC.cc:126
CanonFDC(const DeviceConfig &config)
Definition CanonFDC.cc:24
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 CanonFDC.cc:94
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
bool peekDiskChanged() const override
void selectDrive(DriveNum num, EmuTime::param time)
bool diskChanged() override
Is disk changed?
void setSide(bool side) override
Side select.
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:305
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
void reset(EmuTime::param time) override
This method is called on reset.
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
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)