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 
16 namespace openmsx {
17 
18 static byte decryptLUT[256];
19 
21  : MSXRom(config, std::move(rom_))
22  , romBlocks(*this)
23 {
24  // protection uses a simple rotation on databus, some lines inverted:
25  // out0 = ~in3 out1 = in7 out2 = ~in5 out3 = ~in1
26  // out4 = in0 out5 = in4 out6 = ~in2 out7 = in6
27  for (int i = 0; i < 256; ++i) {
28  decryptLUT[i] = (((i << 4) & 0x50) |
29  ((i >> 3) & 0x05) |
30  ((i << 1) & 0xa0) |
31  ((i << 2) & 0x08) |
32  ((i >> 6) & 0x02)) ^ 0x4d;
33  }
34 
35  if (rom.getSize() != 0x100000) { // 1MB
36  throw MSXException("Holy Quaran ROM should be exactly 1MB in size");
37  }
38  reset(EmuTime::dummy());
39 }
40 
41 void RomHolyQuran2::reset(EmuTime::param /*time*/)
42 {
43  for (auto& b : bank) {
44  b = &rom[0];
45  }
46  decrypt = false;
47 }
48 
49 byte RomHolyQuran2::readMem(word address, EmuTime::param time)
50 {
51  byte result = RomHolyQuran2::peekMem(address, time);
52  if (unlikely(!decrypt)) {
53  if (getCPU().isM1Cycle(address)) {
54  // start decryption when we start executing the rom
55  decrypt = true;
56  }
57  }
58  return result;
59 }
60 
61 byte RomHolyQuran2::peekMem(word address, EmuTime::param /*time*/) const
62 {
63  if ((0x4000 <= address) && (address < 0xc000)) {
64  unsigned b = (address - 0x4000) >> 13;
65  byte raw = bank[b][address & 0x1fff];
66  return decrypt ? decryptLUT[raw] : raw;
67  } else {
68  return 0xff;
69  }
70 }
71 
72 void RomHolyQuran2::writeMem(word address, byte value, EmuTime::param /*time*/)
73 {
74  // TODO are switch addresses mirrored?
75  if ((0x5000 <= address) && (address < 0x6000)) {
76  byte region = (address >> 10) & 3;
77  bank[region] = &rom[(value & 127) * 0x2000];
78  }
79 }
80 
81 const byte* RomHolyQuran2::getReadCacheLine(word address) const
82 {
83  if ((0x4000 <= address) && (address < 0xc000)) {
84  return nullptr;
85  } else {
86  return unmappedRead;
87  }
88 }
89 
91 {
92  if ((0x5000 <= address) && (address < 0x6000)) {
93  return nullptr;
94  } else {
95  return unmappedWrite;
96  }
97 }
98 
99 template<typename Archive>
100 void RomHolyQuran2::serialize(Archive& ar, unsigned /*version*/)
101 {
102  // skip MSXRom base class
103  ar.template serializeBase<MSXDevice>(*this);
104 
105  unsigned b[4];
106  if (ar.isLoader()) {
107  ar.serialize("banks", b);
108  for (unsigned i = 0; i < 4; ++i) {
109  bank[i] = &rom[(b[i] & 127) * 0x2000];
110  }
111  } else {
112  for (unsigned i = 0; i < 4; ++i) {
113  b[i] = (bank[i] - &rom[0]) / 0x2000;
114  }
115  ar.serialize("banks", b);
116  }
117 
118  ar.serialize("decrypt", decrypt);
119 }
122 
123 
124 RomHolyQuran2::Blocks::Blocks(RomHolyQuran2& device_)
125  : RomBlockDebuggableBase(device_)
126 {
127 }
128 
129 byte RomHolyQuran2::Blocks::read(unsigned address)
130 {
131  if ((address < 0x4000) || (address >= 0xc000)) return 255;
132  unsigned page = (address - 0x4000) / 0x2000;
133  auto& device = OUTER(RomHolyQuran2, romBlocks);
134  return (device.bank[page] - &device.rom[0]) / 0x2000;
135 }
136 
137 } // 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:81
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:61
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:20
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:41
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:49
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:72
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:90
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:100
openmsx::RomBlockDebuggableBase
Definition: RomBlockDebuggable.hh:11
openmsx::RomHolyQuran2
RomHolyQuran2
Definition: RomHolyQuran2.cc:120
openmsx::Rom::getSize
unsigned getSize() const
Definition: Rom.hh:32
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::RomHolyQuran2
Definition: RomHolyQuran2.hh:10
openmsx::MSXDevice::getCPU
MSXCPU & getCPU() const
Definition: MSXDevice.cc:135