OXYGENHUB
◆ main openmsx / src / fdc / NationalFDC.cc
3.2 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "NationalFDC.hh"
2
3
#include "DriveMultiplexer.hh"
4
#include "WD2793.hh"
5
6
#include "CacheLine.hh"
7
#include "serialize.hh"
8
9
namespace openmsx {
10
11
NationalFDC::NationalFDC(DeviceConfig& config)
12
	: WD2793BasedFDC(config)
13
{
14
	// ROM only visible in 0x0000-0x7FFF by default
15
	parseRomVisibility(config, 0x0000, 0x8000);
16
}
17
18
byte NationalFDC::readMem(uint16_t address, EmuTime time)
19
{
20
	switch (address & 0x3FC7) {
21
	case 0x3F80:
22
		return controller.getStatusReg(time);
23
	case 0x3F81:
24
		return controller.getTrackReg(time);
25
	case 0x3F82:
26
		return controller.getSectorReg(time);
27
	case 0x3F83:
28
		return controller.getDataReg(time);
29
	case 0x3F84:
30
	case 0x3F85:
31
	case 0x3F86:
32
	case 0x3F87: {
33
		byte value = 0x7F;
34
		if (controller.getIRQ(time))  value |=  0x80;
35
		if (controller.getDTRQ(time)) value &= ~0x40;
36
		return value;
37
	}
38
	default:
39
		return NationalFDC::peekMem(address, time);
40
	}
41
}
42
43
byte NationalFDC::peekMem(uint16_t address, EmuTime time) const
44
{
45
	// According to atarulum:
46
	//  7FBC        is mirrored in 7FBC - 7FBF
47
	//  7FB8 - 7FBF is mirrored in 7F80 - 7FBF
48
	switch (address & 0x3FC7) {
49
	case 0x3F80:
50
		return controller.peekStatusReg(time);
51
	case 0x3F81:
52
		return controller.peekTrackReg(time);
53
	case 0x3F82:
54
		return controller.peekSectorReg(time);
55
	case 0x3F83:
56
		return controller.peekDataReg(time);
57
	case 0x3F84:
58
	case 0x3F85:
59
	case 0x3F86:
60
	case 0x3F87: {
61
		// Drive control IRQ and DRQ lines are not connected to Z80 interrupt request
62
		// bit 7: intrq
63
		// bit 6: !dtrq
64
		// other bits read 1
65
		byte value = 0x7F;
66
		if (controller.peekIRQ(time))  value |=  0x80;
67
		if (controller.peekDTRQ(time)) value &= ~0x40;
68
		return value;
69
	}
70
	default:
71
		return MSXFDC::peekMem(address, time);
72
	}
73
}
74
75
const byte* NationalFDC::getReadCacheLine(uint16_t start) const
76
{
77
	if ((start & 0x3FC0 & CacheLine::HIGH) == (0x3F80 & CacheLine::HIGH)) {
78
		// FDC at 0x7FB8-0x7FBC (also mirrored)
79
		return nullptr;
80
	} else {
81
		return MSXFDC::getReadCacheLine(start);
82
	}
83
}
84
85
void NationalFDC::writeMem(uint16_t address, byte value, EmuTime time)
86
{
87
	switch (address & 0x3FC7) {
88
	case 0x3F80:
89
		controller.setCommandReg(value, time);
90
		break;
91
	case 0x3F81:
92
		controller.setTrackReg(value, time);
93
		break;
94
	case 0x3F82:
95
		controller.setSectorReg(value, time);
96
		break;
97
	case 0x3F83:
98
		controller.setDataReg(value, time);
99
		break;
100
	case 0x3F84:
101
	case 0x3F85:
102
	case 0x3F86:
103
	case 0x3F87:
104
		// bit 0 -> select drive 0
105
		// bit 1 -> select drive 1
106
		// bit 2 -> side select
107
		// bit 3 -> motor on
108
		auto drive = [&] {
109
			switch (value & 3) {
110
				case 1:  return DriveMultiplexer::Drive::A;
111
				case 2:  return DriveMultiplexer::Drive::B;
112
				default: return DriveMultiplexer::Drive::NONE;
113
			}
114
		}();
115
		multiplexer.selectDrive(drive, time);
116
		multiplexer.setSide((value & 0x04) != 0);
117
		multiplexer.setMotor((value & 0x08) != 0, time);
118
		break;
119
	}
120
}
121
122
byte* NationalFDC::getWriteCacheLine(uint16_t address)
123
{
124
	if ((address & 0x3FC0) == (0x3F80 & CacheLine::HIGH)) {
125
		// FDC at 0x7FB8-0x7FBC (also mirrored)
126
		return nullptr;
127
	} else {
128
		return unmappedWrite.data();
129
	}
130
}
131
132
133
template<typename Archive>
134
void NationalFDC::serialize(Archive& ar, unsigned /*version*/)
135
{
136
	ar.template serializeBase<WD2793BasedFDC>(*this);
137
}
138
INSTANTIATE_SERIALIZE_METHODS(NationalFDC);
139
REGISTER_MSXDEVICE(NationalFDC, "NationalFDC");
140
141
} // namespace openmsx