openMSX
MSXKanji.cc
Go to the documentation of this file.
1 #include "MSXKanji.hh"
2 #include "MSXException.hh"
3 #include "one_of.hh"
4 #include "serialize.hh"
5 
6 namespace openmsx {
7 
9  : MSXDevice(config)
10  , rom(getName(), "Kanji ROM", config)
11  , isLascom(config.getChildData("type", {}) == "lascom")
12  , highAddressMask(config.getChildData("type", {}) == "hangul" ? 0x7F : 0x3F)
13 {
14  int size = rom.getSize();
15  if (size != one_of(0x20000, 0x40000)) {
16  throw MSXException("MSXKanji: wrong kanji ROM, it should be either 128kB or 256kB.");
17  }
18  if ((highAddressMask == 0x7F) && (size != 0x40000)) {
19  throw MSXException("MSXKanji: for hangul type, the font ROM must be 256kB.");
20  }
21 
22  reset(EmuTime::dummy());
23 }
24 
25 void MSXKanji::reset(EmuTime::param /*time*/)
26 {
27  adr1 = 0x00000; // TODO check this
28  adr2 = 0x20000; // TODO check this
29 }
30 
31 void MSXKanji::writeIO(word port, byte value, EmuTime::param /*time*/)
32 {
33  switch (port & 0x03) {
34  case 0:
35  adr1 = (adr1 & 0x1f800) | ((value & 0x3f) << 5);
36  break;
37  case 1:
38  adr1 = (adr1 & 0x007e0) | ((value & highAddressMask) << 11);
39  break;
40  case 2:
41  adr2 = (adr2 & 0x3f800) | ((value & 0x3f) << 5);
42  break;
43  case 3:
44  adr2 = (adr2 & 0x207e0) | ((value & 0x3f) << 11);
45  break;
46  }
47 }
48 
49 byte MSXKanji::readIO(word port, EmuTime::param time)
50 {
51  byte result = peekIO(port, time);
52  switch (port & 0x03) {
53  case 0:
54  if (!isLascom) {
55  break;
56  }
57  [[fallthrough]];
58  case 1:
59  adr1 = (adr1 & ~0x1f) | ((adr1 + 1) & 0x1f);
60  break;
61  case 3:
62  adr2 = (adr2 & ~0x1f) | ((adr2 + 1) & 0x1f);
63  break;
64  }
65  return result;
66 }
67 
68 byte MSXKanji::peekIO(word port, EmuTime::param /*time*/) const
69 {
70  byte result = 0xff;
71  switch (port & 0x03) {
72  case 0:
73  if (!isLascom) {
74  break;
75  }
76  [[fallthrough]];
77  case 1:
78  result = rom[adr1 & (rom.getSize() - 1)]; // mask to be safe
79  break;
80  case 3:
81  if (rom.getSize() == 0x40000) { // temp workaround
82  result = rom[adr2];
83  }
84  break;
85  }
86  return result;
87 }
88 
89 template<typename Archive>
90 void MSXKanji::serialize(Archive& ar, unsigned /*version*/)
91 {
92  ar.template serializeBase<MSXDevice>(*this);
93  ar.serialize("adr1", adr1,
94  "adr2", adr2);
95 }
98 
99 /*
100 This really works!
101 
102 10 DIM A(32)
103 20 FOR I=0 TO 4095
104 30 OUT &HD8, I MOD 64: OUT &HD9, I\64
105 40 FOR J=0 TO 31: A(J)=INP(&HD9): NEXT
106 50 FOR J=0 TO 7
107 60 PRINT RIGHT$("0000000"+BIN$(A(J)), 8);
108 70 PRINT RIGHT$("0000000"+BIN$(A(J+8)), 8)
109 80 NEXT
110 90 FOR J=16 TO 23
111 100 PRINT RIGHT$("0000000"+BIN$(A(J)), 8);
112 110 PRINT RIGHT$("0000000"+BIN$(A(J+8)), 8)
113 120 NEXT
114 130 PRINT
115 140 NEXT
116 */
117 
118 } // namespace openmsx
Definition: one_of.hh:7
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:32
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXKanji.cc:25
void serialize(Archive &ar, unsigned version)
Definition: MSXKanji.cc:90
MSXKanji(const DeviceConfig &config)
Definition: MSXKanji.cc:8
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXKanji.cc:68
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXKanji.cc:49
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXKanji.cc:31
unsigned getSize() const
Definition: Rom.hh:34
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:742
This file implemented 3 utility functions:
Definition: Autofire.cc:5
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
size_t size(std::string_view utf8)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:983