OXYGENHUB
◆ main openmsx / src / memory / RomGameMaster2.cc
3.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
// GAME MASTER 2
2
//
3
// This is a 1 megabit ROM cartridge with 8 Kb SRAM. Because of the SRAM,
4
// the mappers have special features.
5
//
6
// Since the size of the mapper is 8Kb, the memory banks are:
7
//   Bank 1: 4000h - 5FFFh
8
//   Bank 2: 6000h - 7FFFh
9
//   Bank 3: 8000h - 9FFFh
10
//   Bank 4: A000h - BFFFh
11
//
12
// And the addresses to change banks:
13
//   Bank 1: <none>
14
//   Bank 2: 6000h - 6FFFh (6000h used)
15
//   Bank 3: 8000h - 8FFFh (8000h used)
16
//   Bank 4: A000h - AFFFh (A000h used)
17
//   SRAM write: B000h - BFFFh
18
//
19
// If SRAM is selected in bank 4, you can write to it in the memory area
20
// B000h - BFFFh.
21
//
22
// The value you write to change banks also determines whether you select ROM
23
// or SRAM. SRAM can be in any memory bank (except bank 1 which can't be
24
// modified) but it can only be written too in bank 4.
25
//
26
//   bit      |  0 |  1 |  2 |  3 |      4       |  5 | 6 | 7 |
27
//   ----------------------------------------------------------
28
//   function | R0 | R1 | R2 | R3 | 1=SRAM/0=ROM | S0 | X | X |
29
//
30
// If bit 4 is reset, bits 0 - 3 select the ROM page as you would expect them
31
// to do. Bits 5 - 7 are ignored now. If bit 4 is set, bit 5 selects the SRAM
32
// page (first or second 4Kb of the 8Kb). Bits 6 - 7 and bits 0 - 3 are
33
// ignored now.
34
//
35
// Since you can only select 4Kb of the SRAM at once in a memory bank and a
36
// memory bank is 8Kb in size, the first and second 4Kb of the memory bank
37
// read the same 4Kb of SRAM if SRAM is selected.
38
39
#include "RomGameMaster2.hh"
40
#include "SRAM.hh"
41
#include "serialize.hh"
42
#include "xrange.hh"
43
#include <memory>
44
45
namespace openmsx {
46
47
RomGameMaster2::RomGameMaster2(const DeviceConfig& config, Rom&& rom_)
48
	: Rom4kBBlocks(config, std::move(rom_), 1)
49
{
50
	sram = std::make_unique<SRAM>(getName() + " SRAM", 0x2000, config);
51
	reset(EmuTime::dummy());
52
}
53
54
void RomGameMaster2::reset(EmuTime /*time*/)
55
{
56
	for (auto i : xrange(4)) {
57
		setUnmapped(i);
58
	}
59
	for (auto i : xrange(4, 12)) {
60
		setRom(i, i - 4);
61
	}
62
	for (auto i : xrange(12, 16)) {
63
		setUnmapped(i);
64
	}
65
	sramOffset = 0;
66
	sramEnabled = false;
67
}
68
69
void RomGameMaster2::writeMem(uint16_t address, byte value, EmuTime /*time*/)
70
{
71
	if ((0x6000 <= address) && (address < 0xB000)) {
72
		if (!(address & 0x1000)) {
73
			auto region = address >> 12; // 0x6, 0x8 or 0xA
74
			if (region == 0x0A) {
75
				sramEnabled = (value & 0x10) != 0;
76
				invalidateDeviceWCache(0xB000, 0x1000); // 'R' is handled below
77
			}
78
			if (value & 0x10) {
79
				// switch SRAM
80
				sramOffset = (value & 0x20) ? 0x1000: 0x0000;
81
				setBank(region,     &(*sram)[sramOffset], value);
82
				setBank(region + 1, &(*sram)[sramOffset], value);
83
			} else {
84
				// switch ROM
85
				setRom(region,     2 * (value & 0x0F));
86
				setRom(region + 1, 2 * (value & 0x0F) + 1);
87
			}
88
		}
89
	} else if ((0xB000 <= address) && (address < 0xC000)) {
90
		// write SRAM
91
		if (sramEnabled) {
92
			sram->write(sramOffset | (address & 0x0FFF), value);
93
		}
94
	}
95
}
96
97
byte* RomGameMaster2::getWriteCacheLine(uint16_t address)
98
{
99
	if ((0x6000 <= address) && (address < 0xB000)) {
100
		if (!(address & 0x1000)) {
101
			return nullptr;
102
		} else {
103
			return unmappedWrite.data();
104
		}
105
	} else if ((0xB000 <= address) && (address < 0xC000) && sramEnabled) {
106
		// write SRAM
107
		return nullptr;
108
	} else {
109
		return unmappedWrite.data();
110
	}
111
}
112
113
template<typename Archive>
114
void RomGameMaster2::serialize(Archive& ar, unsigned /*version*/)
115
{
116
	ar.template serializeBase<Rom4kBBlocks>(*this);
117
	ar.serialize("sramOffset",  sramOffset,
118
	             "sramEnabled", sramEnabled);
119
}
120
INSTANTIATE_SERIALIZE_METHODS(RomGameMaster2);
121
REGISTER_MSXDEVICE(RomGameMaster2, "RomGameMaster2");
122
123
} // namespace openmsx