OXYGENHUB
◆ main openmsx / src / memory / CanonWordProcessor.cc
3.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
// EC701 - Japanese Word Processor Unit (Konami)
2
// Reverse engineered by Albert Beevendorp.
3
// Probably identical to Canon VWU-100.
4
//
5
// Select register in range 0xbff8-0xbfff (0xbfff used by software).
6
// This select the memory visible in area 0x4000-0x7fff.
7
// The value written here is inverted, then:
8
//   bit 5-3 = chip select:
9
//        000: program ROM (lower 16 kB)
10
//        100: dictionary ROM   0-128 kB
11
//        101: dictionary ROM 128-256 kB
12
//        110: dictionary ROM 256-384 kB
13
//     others: not mapped (reads as 0xc0)
14
//   bit 2-0 = block select within dictionary ROM
15
//
16
// Area 0x8000-0xbff7 reads from program ROM (upper 16 kB)
17
//
18
// Also check the electrical schema on:
19
//   http://d4.princess.ne.jp/msx/other/ec700/index.htm
20
21
#include "CanonWordProcessor.hh"
22
23
#include "CacheLine.hh"
24
#include "MSXException.hh"
25
#include "serialize.hh"
26
27
namespace openmsx {
28
29
CanonWordProcessor::CanonWordProcessor(DeviceConfig& config)
30
	: MSXDevice(config)
31
	, programRom   (strCat(config.getAttributeValue("id"), "_program"),    "rom", config, "program")
32
	, dictionaryRom(strCat(config.getAttributeValue("id"), "_dictionary"), "rom", config, "dictionary")
33
{
34
	if (programRom.size() != 32*1024) {
35
		throw MSXException("Program ROM must be 32kB.");
36
	}
37
	if (dictionaryRom.size() != 3*128*1024) {
38
		throw MSXException("Dictionary ROM must be 3x 128kB.");
39
	}
40
	reset(EmuTime::dummy());
41
}
42
43
void CanonWordProcessor::reset(EmuTime time)
44
{
45
	writeMem(0xbfff, 0xff, time);
46
}
47
48
byte CanonWordProcessor::readMem(uint16_t address, EmuTime time)
49
{
50
	return peekMem(address, time);
51
}
52
53
byte CanonWordProcessor::peekMem(uint16_t address, EmuTime /*time*/) const
54
{
55
	if ((0xbff8 <= address) && (address <= 0xbfff)) {
56
		return 0xc0; // select area, does NOT read from ROM
57
	} else {
58
		if (const auto* a = readHelper(address)) {
59
			return *a;
60
		}
61
		return 0xc0;
62
	}
63
}
64
65
const byte* CanonWordProcessor::getReadCacheLine(uint16_t start) const
66
{
67
	if ((start & CacheLine::HIGH) == (0xbfff & CacheLine::HIGH)) {
68
		return nullptr; // select register
69
	} else {
70
		return readHelper(start);
71
	}
72
}
73
74
const byte* CanonWordProcessor::readHelper(uint16_t address) const
75
{
76
	if ((0x4000 <= address) && (address <= 0x7fff)) {
77
		auto chip = (select & 0b00'111'000) >> 3;
78
		auto bank = (select & 0b00'011'111);
79
		address &= 0x3fff;
80
		switch (chip) {
81
		case 0b000:
82
			return &programRom[address];
83
		case 0b100: case 0b101: case 0b110:
84
			return &dictionaryRom[0x4000 * bank + address];
85
		// note: according to the schematic on
86
		// http://d4.princess.ne.jp/msx/other/ec700/index.htm, the
87
		// outputs of IC5's 3-to-8 decoder for '001' '010' '011' and
88
		// '111' are unconnected
89
		}
90
		return nullptr; // unmapped, but reads as 0xc0 instead of 0xff ??
91
	} else {
92
		// 0x8000 - 0xbfff
93
		return &programRom[0x4000 + (address & 0x3fff)];
94
	}
95
}
96
97
void CanonWordProcessor::writeMem(uint16_t address, byte value, EmuTime /*time*/)
98
{
99
	if ((0xbff8 <= address) && (address <= 0xbfff)) {
100
		select = ~value; // invert !!
101
		invalidateDeviceRCache(0x4000, 0x4000);
102
	}
103
}
104
105
byte* CanonWordProcessor::getWriteCacheLine(uint16_t /*start*/)
106
{
107
	return nullptr;
108
}
109
110
template<typename Archive>
111
void CanonWordProcessor::serialize(Archive& ar, unsigned /*version*/)
112
{
113
	ar.template serializeBase<MSXDevice>(*this);
114
	ar.serialize("select", select);
115
}
116
INSTANTIATE_SERIALIZE_METHODS(CanonWordProcessor);
117
REGISTER_MSXDEVICE(CanonWordProcessor, "CanonWordProcessor");
118
119
} // namespace openmsx