openMSX
RomHolyQuran2.cc
Go to the documentation of this file.
1 // Holy Qu'ran cartridge
2 // It is like an ASCII 8KB, but using the 5000h, 5400h, 5800h and 5C00h
3 // addresses.
4 //
5 // This is very similar to RomHolyQuran, but this mapper type works with the
6 // encrypted ROM content. Thanks to n_n for implementing it in meisei and
7 // sharing his implementation with us (and pointing us to it).
8 
9 #include "RomHolyQuran2.hh"
10 #include "MSXCPU.hh"
11 #include "MSXException.hh"
12 #include "likely.hh"
13 #include "outer.hh"
14 #include "serialize.hh"
15 #include <array>
16 
17 namespace openmsx {
18 
19 // protection uses a simple rotation on databus, some lines inverted:
20 // out0 = ~in3 out1 = in7 out2 = ~in5 out3 = ~in1
21 // out4 = in0 out5 = in4 out6 = ~in2 out7 = in6
22 static constexpr auto decryptLUT = [] {
23  std::array<byte, 256> result = {};
24  for (int i = 0; i < 256; ++i) {
25  result[i] = (((i << 4) & 0x50) |
26  ((i >> 3) & 0x05) |
27  ((i << 1) & 0xa0) |
28  ((i << 2) & 0x08) |
29  ((i >> 6) & 0x02)) ^ 0x4d;
30  }
31  return result;
32 }();
33 
35  : MSXRom(config, std::move(rom_))
36  , romBlocks(*this)
37 {
38  if (rom.getSize() != 0x100000) { // 1MB
39  throw MSXException("Holy Quaran ROM should be exactly 1MB in size");
40  }
41  reset(EmuTime::dummy());
42 }
43 
44 void RomHolyQuran2::reset(EmuTime::param /*time*/)
45 {
46  for (auto& b : bank) {
47  b = &rom[0];
48  }
49  decrypt = false;
50 }
51 
52 byte RomHolyQuran2::readMem(word address, EmuTime::param time)
53 {
54  byte result = RomHolyQuran2::peekMem(address, time);
55  if (unlikely(!decrypt)) {
56  if (getCPU().isM1Cycle(address)) {
57  // start decryption when we start executing the rom
58  decrypt = true;
59  }
60  }
61  return result;
62 }
63 
64 byte RomHolyQuran2::peekMem(word address, EmuTime::param /*time*/) const
65 {
66  if ((0x4000 <= address) && (address < 0xc000)) {
67  unsigned b = (address - 0x4000) >> 13;
68  byte raw = bank[b][address & 0x1fff];
69  return decrypt ? decryptLUT[raw] : raw;
70  } else {
71  return 0xff;
72  }
73 }
74 
75 void RomHolyQuran2::writeMem(word address, byte value, EmuTime::param /*time*/)
76 {
77  // TODO are switch addresses mirrored?
78  if ((0x5000 <= address) && (address < 0x6000)) {
79  byte region = (address >> 10) & 3;
80  bank[region] = &rom[(value & 127) * 0x2000];
81  }
82 }
83 
84 const byte* RomHolyQuran2::getReadCacheLine(word address) const
85 {
86  if ((0x4000 <= address) && (address < 0xc000)) {
87  return nullptr;
88  } else {
89  return unmappedRead;
90  }
91 }
92 
94 {
95  if ((0x5000 <= address) && (address < 0x6000)) {
96  return nullptr;
97  } else {
98  return unmappedWrite;
99  }
100 }
101 
102 template<typename Archive>
103 void RomHolyQuran2::serialize(Archive& ar, unsigned /*version*/)
104 {
105  // skip MSXRom base class
106  ar.template serializeBase<MSXDevice>(*this);
107 
108  unsigned b[4];
109  if (ar.isLoader()) {
110  ar.serialize("banks", b);
111  for (unsigned i = 0; i < 4; ++i) {
112  bank[i] = &rom[(b[i] & 127) * 0x2000];
113  }
114  } else {
115  for (unsigned i = 0; i < 4; ++i) {
116  b[i] = (bank[i] - &rom[0]) / 0x2000;
117  }
118  ar.serialize("banks", b);
119  }
120 
121  ar.serialize("decrypt", decrypt);
122 }
125 
126 
127 RomHolyQuran2::Blocks::Blocks(RomHolyQuran2& device_)
128  : RomBlockDebuggableBase(device_)
129 {
130 }
131 
132 byte RomHolyQuran2::Blocks::read(unsigned address)
133 {
134  if ((address < 0x4000) || (address >= 0xc000)) return 255;
135  unsigned page = (address - 0x4000) / 0x2000;
136  auto& device = OUTER(RomHolyQuran2, romBlocks);
137  return (device.bank[page] - &device.rom[0]) / 0x2000;
138 }
139 
140 } // namespace openmsx
unlikely
#define unlikely(x)
Definition: likely.hh:15
serialize.hh
openmsx::RomHolyQuran2::getReadCacheLine
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: RomHolyQuran2.cc:84
openmsx::DeviceConfig
Definition: DeviceConfig.hh:20
openmsx::RomHolyQuran2::peekMem
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: RomHolyQuran2.cc:64
openmsx::MSXDevice::unmappedWrite
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:301
MSXCPU.hh
RomHolyQuran2.hh
MSXException.hh
openmsx::MSXException
Definition: MSXException.hh:10
openmsx::RomHolyQuran2::RomHolyQuran2
RomHolyQuran2(const DeviceConfig &config, Rom &&rom)
Definition: RomHolyQuran2.cc:34
openmsx::REGISTER_MSXDEVICE
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
openmsx::RomHolyQuran2::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: RomHolyQuran2.cc:44
openmsx::MSXRom
Definition: MSXRom.hh:10
likely.hh
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
openmsx::RomHolyQuran2::readMem
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: RomHolyQuran2.cc:52
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::RomHolyQuran2::writeMem
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: RomHolyQuran2.cc:75
openmsx::MSXRom::rom
Rom rom
Definition: MSXRom.hh:20
openmsx::Rom
Definition: Rom.hh:21
openmsx::RomHolyQuran2::getWriteCacheLine
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: RomHolyQuran2.cc:93
outer.hh
openmsx::MSXDevice::unmappedRead
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:300
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
openmsx::RomHolyQuran2::serialize
void serialize(Archive &ar, unsigned version)
Definition: RomHolyQuran2.cc:103
openmsx::RomBlockDebuggableBase
Definition: RomBlockDebuggable.hh:11
openmsx::RomHolyQuran2
RomHolyQuran2
Definition: RomHolyQuran2.cc:123
openmsx::Rom::getSize
unsigned getSize() const
Definition: Rom.hh:32
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
openmsx::RomHolyQuran2
Definition: RomHolyQuran2.hh:10
openmsx::MSXDevice::getCPU
MSXCPU & getCPU() const
Definition: MSXDevice.cc:135