openMSX
RomDooly.cc
Go to the documentation of this file.
1//
2// Agigongnyong Dooly
3//
4
5#include "RomDooly.hh"
6#include "CacheLine.hh"
7#include "MSXException.hh"
8#include "serialize.hh"
9
10namespace openmsx {
11
12RomDooly::RomDooly(const DeviceConfig& config, Rom&& rom_)
13 : MSXRom(config, std::move(rom_))
14 , romBlockDebug(*this, std::span{&conversion, 1}, 0x4000, 0x8000, 15)
15{
16 if (rom.size() != 0x8000) {
17 throw MSXException("Dooly ROM-size must be exactly 32kB");
18 }
19}
20
21void RomDooly::reset(EmuTime::param /*time*/)
22{
23 conversion = 0;
24}
25
26byte RomDooly::peekMem(word address, EmuTime::param /*time*/) const
27{
28 if ((0x4000 <= address) && (address < 0xc000)) {
29 byte value = rom[address - 0x4000];
30 switch (conversion) {
31 case 0:
32 return value;
33 case 1:
34 return (value & 0xf8) | (value << 2 & 0x04) | (value >> 1 & 0x03);
35 case 4:
36 return (value & 0xf8) | (value >> 2 & 0x01) | (value << 1 & 0x06);
37 case 2:
38 case 5:
39 case 6:
40 switch (value & 0x07) {
41 case 1:
42 case 2:
43 case 4:
44 return value & 0xf8;
45 case 3:
46 case 5:
47 case 6:
48 if (conversion == 2) return (value & 0xf8) | (((value << 2 & 0x04) | (value >> 1 & 0x03)) ^ 0x07);
49 if (conversion == 5) return value ^ 0x07;
50 if (conversion == 6) return (value & 0xf8) | (((value >> 2 & 0x01) | (value << 1 & 0x06)) ^ 0x07);
51 [[fallthrough]];
52 default:
53 return value;
54 }
55 default:
56 return value | 0x07;
57 }
58 }
59 return 0xff;
60}
61
62byte RomDooly::readMem(word address, EmuTime::param time)
63{
64 return peekMem(address, time);
65}
66
67void RomDooly::writeMem(word address, byte value, EmuTime::param /*time*/)
68{
69 // TODO: To what region does the real cartridge react?
70 // * Using the full region [0x4000,0xc000) interferes with the
71 // RAM-check routine of many MSX machines (game doesn't boot)
72 // * The game seems to write at many different addresses. The min/max
73 // I've seen is 0x8780/0x8f86. So my best *guess* is to extend this
74 // region to [0x8000,0x9000).
75 // * This smaller region seems to make the game work (on the above
76 // machines that failed before).
77 if ((0x8000 <= address) && (address < 0x9000)) {
78 conversion = value & 0x07;
79 }
80}
81
83{
84 if (((0x4000 & CacheLine::HIGH) <= address) && (address < (0xc000 & CacheLine::HIGH))) {
85 return nullptr;
86 } else {
87 return unmappedWrite.data();
88 }
89}
90
91template<typename Archive>
92void RomDooly::serialize(Archive& ar, unsigned /*version*/)
93{
94 ar.template serializeBase<MSXDevice>(*this);
95 ar.serialize("conversion", conversion);
96}
99
100} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:354
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:305
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition RomDooly.cc:62
void reset(EmuTime::param time) override
This method is called on reset.
Definition RomDooly.cc:21
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 RomDooly.cc:67
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition RomDooly.cc:26
void serialize(Archive &ar, unsigned version)
Definition RomDooly.cc:92
RomDooly(const DeviceConfig &config, Rom &&rom)
Definition RomDooly.cc:12
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition RomDooly.cc:82
auto size() const
Definition Rom.hh:36
constexpr unsigned HIGH
Definition CacheLine.hh:10
This file implemented 3 utility functions:
Definition Autofire.cc:11
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)