openMSX
MegaFlashRomSCCPlus.cc
Go to the documentation of this file.
3#include "MSXCPUInterface.hh"
4#include "CacheLine.hh"
5#include "narrow.hh"
6#include "ranges.hh"
7#include "serialize.hh"
8#include "xrange.hh"
9#include <array>
10#include <cassert>
11
12/******************************************************************************
13 * DOCUMENTATION AS PROVIDED BY MANUEL PAZOS, WHO DEVELOPED THE CARTRIDGE *
14 ******************************************************************************
15
16--------------------------------------------------------------------------------
17MegaFlashROM SCC+ Technical Details
18(c) Manuel Pazos 28-09-2010
19--------------------------------------------------------------------------------
20
21Main features:
22 - 1024KB flashROM memory (M29W800DB)
23 - SCC-I (2312P001)
24 - PSG (AY-3-8910/YM2149)
25 - Mappers: ASCII8, ASCII16, Konami, Konami SCC, linear 64K
26 - Subslot simulation (4 x 256K)
27
28
29--------------------------------------------------------------------------------
30[Memory]
31
32 - Model Numonyx M29W800DB TSOP48
33 - Datasheet: https://media-www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/parallel/m29w/m29w800d.pdf
34 - Block layout:
35 #00000 16K
36 #04000 8K
37 #06000 8K
38 #08000 32K
39 #10000 64K x 15
40 - Command addresses #4555 and #5AAA
41 - Commands:
42 AUTOSELECT #90
43 WRITE #A0
44 CHIP_ERASE #10
45 BLOCK_ERASE #30
46 RESET #F0
47 - FlashROM ID = #5B
48
49
50--------------------------------------------------------------------------------
51[PSG]
52
53 The PSG included in the cartridge is mapped to ports #10-#12
54
55 Port #A0 -> #10
56 Port #A1 -> #11
57 Port #A2 -> #12
58
59 The PSG is read only.
60
61--------------------------------------------------------------------------------
62[REGISTERS]
63
64 -#7FFE or #7FFF = CONFIGURATION REGISTER:
65 7 mapper mode 1: \ %00 = SCC, %01 = 64K
66 6 mapper mode 0: / %10 = ASC8, %11 = ASC16
67 5 mapper mode : Select Konami mapper (0 = SCC, 1 = normal)
68 4 Enable subslot mode and register #FFFF (1 = Enable, 0 = Disable)
69 3 Disable #4000-#5FFF mapper in Konami mode (0 = Enable, 1 = Disable)
70 2 Disable configuration register (1 = Disabled)
71 1 Disable mapper registers (0 = Enable, 1 = Disable)
72 0 Enable 512K mapper limit in SCC mapper or 256K limit in Konami mapper
73(1 = Enable, 0 = Disable)
74
75
76--------------------------------------------------------------------------------
77[MAPPERS]
78
79 - ASCII 8: Common ASC8 mapper
80
81 - ASCII 16: Common ASC16 mapper
82
83 - Konami: Common Konami mapper.
84 Bank0 (#4000-#5FFF) can be also changed unless CONF_REG bit3 is 1
85
86 - Konami SCC: Common Konami SCC mapper
87 Bank0 mapper register: if bank number bit 7 is 1 then bit 6-0 sets mapper offset.
88
89 - Linear 64: #0000-#3FFF bank0
90 #4000-#7FFF bank1
91 #8000-#BFFF bank2
92 #C000-#FFFF bank3
93 Banks mapper registers addresses = Konami
94
95--------------------------------------------------------------------------------
96[DEFAULT VALUES]
97 - CONFIGURATION REGISTER = 0
98 - Bank0 = 0
99 - Bank1 = 1
100 - Bank2 = 2
101 - Bank3 = 3
102 - Bank offset = 0
103 - Subslot register = 0
104
105--------------------------------------------------------------------------------
106[LOGIC]
107
108 Banks0-3: are set depending on the mapper mode.
109 Subslots: are set writing to #FFFF in the MegaFlashROM SCC+ slot when CONFIG_REG bit 4 is set.
110 Offset: is set by writing offset value + #80 to bank0 mapper register in Konami SCC mode.
111
112 -- Subslots offsets
113 SubOff0 = subslot(1-0) & "0000" + mapOff; -- In 64K mode, the banks are 16K, with the offsets halved
114 SubOff1 = subslot(3-2) & "0000" + mapOff when maptyp = "10" else subslot(3-2) & "00000" + mapOff;
115 SubOff2 = subslot(5-4) & "0000" + mapOff when maptyp = "10" else subslot(5-4) & "00000" + mapOff;
116 SubOff3 = subslot(7-6) & "0000" + mapOff when maptyp = "10" else subslot(7-6) & "00000";
117
118 -- Calculate the bank mapper to use taking into account the offset
119 Bank0 = SubBank0(x) + SubOff0 when SccModeA(4) = '1' and subslot(1 downto 0) = "00" and maptyp = "10" else
120 SubBank0(1) + SubOff0 when SccModeA(4) = '1' and subslot(1 downto 0) = "01" and maptyp = "10" else
121 SubBank0(2) + SubOff0 when SccModeA(4) = '1' and subslot(1 downto 0) = "10" and maptyp = "10" else
122 SubBank0(3) + SubOff0 when SccModeA(4) = '1' and subslot(1 downto 0) = "11" and maptyp = "10" else
123
124 SubBank0(0) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "00" else
125 SubBank0(1) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "01" else
126 SubBank0(2) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "10" else
127 SubBank0(3) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "11" else
128 SccBank0 + mapOff;
129
130 Bank1 <= SubBank1(0) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "00" else
131 SubBank1(1) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "01" else
132 SubBank1(2) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "10" else
133 SubBank1(3) + SubOff1 when SccModeA(4) = '1' and subslot(3 downto 2) = "11" else
134 SccBank1 + mapOff;
135
136 Bank2 <= SubBank2(0) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "00" else
137 SubBank2(1) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "01" else
138 SubBank2(2) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "10" else
139 SubBank2(3) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "11" else
140 SccBank2 + mapOff;
141
142 Bank3 <= SubBank3(0) + SubOff3 when SccModeA(4) = '1' and subslot(7 downto 6) = "00" and maptyp = "10" else
143 SubBank3(1) + SubOff3 when SccModeA(4) = '1' and subslot(7 downto 6) = "01" and maptyp = "10" else
144 SubBank3(2) + SubOff3 when SccModeA(4) = '1' and subslot(7 downto 6) = "10" and maptyp = "10" else
145 SubBank3(3) + SubOff3 when SccModeA(4) = '1' and subslot(7 downto 6) = "11" and maptyp = "10" else
146
147 SubBank3(0) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "00" else
148 SubBank3(1) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "01" else
149 SubBank3(2) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "10" else
150 SubBank3(3) + SubOff2 when SccModeA(4) = '1' and subslot(5 downto 4) = "11" else
151 SccBank3 + mapOff;
152
153
154 -- 64K Mode
155 RamAdr <= Bank0(5 downto 0) & adr(13 downto 0) when adr(15 downto 14) = "00" and maptyp = "10" else --#0000-#3FFF
156 Bank1(5 downto 0) & adr(13 downto 0) when adr(15 downto 14) = "01" and maptyp = "10" else --#4000-#7FFF
157 Bank2(5 downto 0) & adr(13 downto 0) when adr(15 downto 14) = "10" and maptyp = "10" else --#8000-#BFFF
158 Bank3(5 downto 0) & adr(13 downto 0) when adr(15 downto 14) = "11" and maptyp = "10" else --#C000-#FFFF
159 -- Modes SCC, ASC8 and ASC16
160 Bank0(6 downto 0) & adr(12 downto 0) when adr(14 downto 13) = "10" else --#4000-#5FFF
161 Bank1(6 downto 0) & adr(12 downto 0) when adr(14 downto 13) = "11" else --#6000-#7FFF
162 Bank2(6 downto 0) & adr(12 downto 0) when adr(14 downto 13) = "00" else --#8000-#9FFF
163 Bank3(6 downto 0) & adr(12 downto 0);
164
165--------------------------------------------------------------------------------
166[FLASH ROM ADDRESSING]
167
168 In order to be compatible with OPFX which sends command sequences like
169 (0x555) = 0xAA, (0xAAA) = 0x55, whilst dual mode 8/16-bit chips like the
170 M29W800DB expect (0xAAA) = 0xAA, (0x555) = 0x55 when operating in byte mode,
171 CPU line A12 is connected to Flash line A0.
172
173 CPU line | Flash line (-1 on datasheet)
174 ----------+------------------------------
175 A0-A11 | A1-A12
176 A12 | A0
177 A13-A15 | A13-A19 (through mapper)
178
179 Since the smallest sector size is 8 kB, sector numbers are unaffected, only
180 sector offsets are. Unfortunately, this prohibits read caching.
181
182******************************************************************************/
183
184namespace openmsx {
185
187 const DeviceConfig& config, Rom&& rom_)
188 : MSXRom(config, std::move(rom_))
189 , scc("MFR SCC+ SCC-I", config, getCurrentTime(), SCC::Mode::Compatible)
190 , psg("MFR SCC+ PSG", DummyAY8910Periphery::instance(), config,
191 getCurrentTime())
192 , flash(rom, AmdFlashChip::M29W800DB, {}, config)
193{
194 powerUp(getCurrentTime());
195 getCPUInterface().register_IO_Out_range(0x10, 2, this);
196}
197
202
203void MegaFlashRomSCCPlus::powerUp(EmuTime::param time)
204{
205 scc.powerUp(time);
206 reset(time);
207}
208
209void MegaFlashRomSCCPlus::reset(EmuTime::param time)
210{
211 configReg = 0;
212 offsetReg = 0;
213 subslotReg = 0;
214 for (auto& regs : bankRegs) {
215 ranges::iota(regs, byte(0));
216 }
217
218 sccMode = 0;
219 ranges::iota(sccBanks, byte(0));
220 scc.reset(time);
221
222 psgLatch = 0;
223 psg.reset(time);
224
225 flash.reset();
226
227 invalidateDeviceRCache(); // flush all to be sure
228}
229
230MegaFlashRomSCCPlus::SCCEnable MegaFlashRomSCCPlus::getSCCEnable() const
231{
232 if ((sccMode & 0x20) && (sccBanks[3] & 0x80)) {
233 return EN_SCCPLUS;
234 } else if ((!(sccMode & 0x20)) && ((sccBanks[2] & 0x3F) == 0x3F)) {
235 return EN_SCC;
236 } else {
237 return EN_NONE;
238 }
239}
240
241unsigned MegaFlashRomSCCPlus::getSubslot(unsigned addr) const
242{
243 return (configReg & 0x10)
244 ? (subslotReg >> (2 * (addr >> 14))) & 0x03
245 : 0;
246}
247
248unsigned MegaFlashRomSCCPlus::getFlashAddr(unsigned addr) const
249{
250 // Pazos: FlashROM A0 (A-1 on datasheet) is connected to CPU A12.
251 addr = (addr & 0xE000) | ((addr & 0x1000) >> 12) | ((addr & 0x0FFF) << 1);
252
253 unsigned subslot = getSubslot(addr);
254 unsigned tmp = [&] {
255 if ((configReg & 0xC0) == 0x40) {
256 unsigned bank = bankRegs[subslot][addr >> 14] + offsetReg;
257 return (bank * 0x4000) + (addr & 0x3FFF);
258 } else {
259 unsigned page = (addr >> 13) - 2;
260 if (page >= 4) {
261 // Bank: -2, -1, 4, 5. So not mapped in this region,
262 // returned value should not be used. But querying it
263 // anyway is easier, see start of writeMem().
264 return unsigned(-1);
265 }
266 unsigned bank = bankRegs[subslot][page] + offsetReg;
267 return (bank * 0x2000) + (addr & 0x1FFF);
268 }
269 }();
270 return ((0x40000 * subslot) + tmp) & 0xFFFFF; // wrap at 1MB
271}
272
273byte MegaFlashRomSCCPlus::peekMem(word addr, EmuTime::param time) const
274{
275 if ((configReg & 0x10) && (addr == 0xFFFF)) {
276 // read subslot register
277 return subslotReg ^ 0xFF;
278 }
279
280 if ((configReg & 0xE0) == 0x00) {
281 SCCEnable enable = getSCCEnable();
282 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
283 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
284 return scc.peekMem(narrow_cast<uint8_t>(addr & 0xFF), time);
285 }
286 }
287
288 if (((configReg & 0xC0) == 0x40) ||
289 ((0x4000 <= addr) && (addr < 0xC000))) {
290 // read (flash)rom content
291 unsigned flashAddr = getFlashAddr(addr);
292 assert(flashAddr != unsigned(-1));
293 return flash.peek(flashAddr);
294 } else {
295 // unmapped read
296 return 0xFF;
297 }
298}
299
300byte MegaFlashRomSCCPlus::readMem(word addr, EmuTime::param time)
301{
302 if ((configReg & 0x10) && (addr == 0xFFFF)) {
303 // read subslot register
304 return subslotReg ^ 0xFF;
305 }
306
307 if ((configReg & 0xE0) == 0x00) {
308 SCCEnable enable = getSCCEnable();
309 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
310 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
311 return scc.readMem(narrow_cast<uint8_t>(addr & 0xFF), time);
312 }
313 }
314
315 if (((configReg & 0xC0) == 0x40) ||
316 ((0x4000 <= addr) && (addr < 0xC000))) {
317 // read (flash)rom content
318 unsigned flashAddr = getFlashAddr(addr);
319 assert(flashAddr != unsigned(-1));
320 return flash.read(flashAddr);
321 } else {
322 // unmapped read
323 return 0xFF;
324 }
325}
326
328{
329 if ((configReg & 0x10) &&
330 ((addr & CacheLine::HIGH) == (0xFFFF & CacheLine::HIGH))) {
331 // read subslot register
332 return nullptr;
333 }
334
335 if ((configReg & 0xE0) == 0x00) {
336 SCCEnable enable = getSCCEnable();
337 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
338 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
339 return nullptr;
340 }
341 }
342
343 if (((configReg & 0xC0) == 0x40) ||
344 ((0x4000 <= addr) && (addr < 0xC000))) {
345 return nullptr; // uncacheable due to address swizzling
346 } else {
347 // unmapped read
348 return unmappedRead.data();
349 }
350}
351
352void MegaFlashRomSCCPlus::writeMem(word addr, byte value, EmuTime::param time)
353{
354 // address is calculated before writes to other regions take effect
355 unsigned flashAddr = getFlashAddr(addr);
356
357 // There are several overlapping functional regions in the address
358 // space. A single write can trigger behaviour in multiple regions. In
359 // other words there's no priority amongst the regions where a higher
360 // priority region blocks the write from the lower priority regions.
361 if ((configReg & 0x10) && (addr == 0xFFFF)) {
362 // write subslot register
363 byte diff = value ^ subslotReg;
364 subslotReg = value;
365 for (auto i : xrange(4)) {
366 if (diff & (3 << (2 * i))) {
367 invalidateDeviceRCache(0x4000 * i, 0x4000);
368 }
369 }
370 }
371
372 if (((configReg & 0x04) == 0x00) && ((addr & 0xFFFE) == 0x7FFE)) {
373 // write config register
374 configReg = value;
375 invalidateDeviceRCache(); // flush all to be sure
376 }
377
378 if ((configReg & 0xE0) == 0x00) {
379 // Konami-SCC
380 if ((addr & 0xFFFE) == 0xBFFE) {
381 sccMode = value;
382 scc.setMode((value & 0x20) ? SCC::Mode::Plus
384 invalidateDeviceRCache(0x9800, 0x800);
385 invalidateDeviceRCache(0xB800, 0x800);
386 }
387 SCCEnable enable = getSCCEnable();
388 bool isRamSegment2 = ((sccMode & 0x24) == 0x24) ||
389 ((sccMode & 0x10) == 0x10);
390 bool isRamSegment3 = ((sccMode & 0x10) == 0x10);
391 if (((enable == EN_SCC) && !isRamSegment2 &&
392 (0x9800 <= addr) && (addr < 0xA000)) ||
393 ((enable == EN_SCCPLUS) && !isRamSegment3 &&
394 (0xB800 <= addr) && (addr < 0xC000))) {
395 scc.writeMem(narrow_cast<uint8_t>(addr & 0xFF), value, time);
396 return; // Pazos: when SCC registers are selected flashROM is not seen, so it does not accept commands.
397 }
398 }
399
400 unsigned subslot = getSubslot(addr);
401 unsigned page8kB = (addr >> 13) - 2;
402 if (((configReg & 0x02) == 0x00) && (page8kB < 4)) {
403 // (possibly) write to bank registers
404 switch (configReg & 0xE0) {
405 case 0x00:
406 // Konami-SCC
407 if ((addr & 0x1800) == 0x1000) {
408 // Storing 'sccBanks' may seem redundant at
409 // first, but it's required to calculate
410 // whether the SCC is enabled or not.
411 sccBanks[page8kB] = value;
412 if ((value & 0x80) && (page8kB == 0)) {
413 offsetReg = value & 0x7F;
414 invalidateDeviceRCache(0x4000, 0x8000);
415 } else {
416 // Masking of the mapper bits is done on
417 // write (and only in Konami(-scc) mode)
418 byte mask = (configReg & 0x01) ? 0x3F : 0x7F;
419 bankRegs[subslot][page8kB] = value & mask;
420 invalidateDeviceRCache(0x4000 + 0x2000 * page8kB, 0x2000);
421 }
422 }
423 break;
424 case 0x20: {
425 // Konami
426 if (((configReg & 0x08) == 0x08) && (addr < 0x6000)) {
427 // Switching 0x4000-0x5FFF disabled.
428 // This bit blocks writing to the bank register
429 // (an alternative was forcing a 0 on read).
430 // It only has effect in Konami mode.
431 break;
432 }
433 // Making of the mapper bits is done on
434 // write (and only in Konami(-scc) mode)
435 if ((addr < 0x5000) || ((0x5800 <= addr) && (addr < 0x6000))) break; // only SCC range works
436 byte mask = (configReg & 0x01) ? 0x1F : 0x7F;
437 bankRegs[subslot][page8kB] = value & mask;
438 invalidateDeviceRCache(0x4000 + 0x2000 * page8kB, 0x2000);
439 break;
440 }
441 case 0x40:
442 case 0x60:
443 // 64kB
444 bankRegs[subslot][page8kB] = value;
445 invalidateDeviceRCache(0x0000 + 0x4000 * page8kB, 0x4000);
446 break;
447 case 0x80:
448 case 0xA0:
449 // ASCII-8
450 if ((0x6000 <= addr) && (addr < 0x8000)) {
451 byte bank = (addr >> 11) & 0x03;
452 bankRegs[subslot][bank] = value;
453 invalidateDeviceRCache(0x4000 + 0x2000 * bank, 0x2000);
454 }
455 break;
456 case 0xC0:
457 case 0xE0:
458 // ASCII-16
459 // This behaviour is confirmed by Manuel Pazos (creator
460 // of the cartridge): ASCII-16 uses all 4 bank registers
461 // and one bank switch changes 2 registers at once.
462 // This matters when switching mapper mode, because
463 // the content of the bank registers is unchanged after
464 // a switch.
465 if ((0x6000 <= addr) && (addr < 0x6800)) {
466 bankRegs[subslot][0] = narrow_cast<uint8_t>(2 * value + 0);
467 bankRegs[subslot][1] = narrow_cast<uint8_t>(2 * value + 1);
468 invalidateDeviceRCache(0x4000, 0x4000);
469 }
470 if ((0x7000 <= addr) && (addr < 0x7800)) {
471 bankRegs[subslot][2] = narrow_cast<uint8_t>(2 * value + 0);
472 bankRegs[subslot][3] = narrow_cast<uint8_t>(2 * value + 1);
473 invalidateDeviceRCache(0x8000, 0x4000);
474 }
475 break;
476 }
477 }
478
479 // write to flash
480 if (((configReg & 0xC0) == 0x40) ||
481 ((0x4000 <= addr) && (addr < 0xC000))) {
482 assert(flashAddr != unsigned(-1));
483 return flash.write(flashAddr, value);
484 }
485}
486
488{
489 return nullptr;
490}
491
492
493void MegaFlashRomSCCPlus::writeIO(word port, byte value, EmuTime::param time)
494{
495 if ((port & 0xFF) == 0x10) {
496 psgLatch = value & 0x0F;
497 } else {
498 assert((port & 0xFF) == 0x11);
499 psg.writeRegister(psgLatch, value, time);
500 }
501}
502
503
504template<typename Archive>
505void MegaFlashRomSCCPlus::serialize(Archive& ar, unsigned /*version*/)
506{
507 // skip MSXRom base class
508 ar.template serializeBase<MSXDevice>(*this);
509
510 ar.serialize("scc", scc,
511 "psg", psg,
512 "flash", flash,
513
514 "configReg", configReg,
515 "offsetReg", offsetReg,
516 "subslotReg", subslotReg,
517 "bankRegs", bankRegs,
518 "psgLatch", psgLatch,
519 "sccMode", sccMode,
520 "sccBanks", sccBanks);
521}
524
525} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void reset(EmuTime::param time)
Definition AY8910.cc:521
void writeRegister(unsigned reg, uint8_t value, EmuTime::param time)
Definition AY8910.cc:578
void write(size_t address, uint8_t value)
Definition AmdFlash.cc:456
uint8_t read(size_t address)
Definition AmdFlash.cc:432
uint8_t peek(size_t address) const
Definition AmdFlash.cc:186
void unregister_IO_Out_range(byte port, unsigned num, MSXDevice *device)
void invalidateDeviceRCache()
Definition MSXDevice.hh:215
static std::array< byte, 0x10000 > unmappedRead
Definition MSXDevice.hh:306
MSXCPUInterface & getCPUInterface() const
Definition MSXDevice.cc:133
void reset(EmuTime::param time) override
This method is called on reset.
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
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.
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
MegaFlashRomSCCPlus(const DeviceConfig &config, Rom &&rom)
void serialize(Archive &ar, unsigned version)
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.
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
void setMode(Mode newMode)
Definition SCC.cc:183
void powerUp(EmuTime::param time)
Definition SCC.cc:141
uint8_t readMem(uint8_t address, EmuTime::param time)
Definition SCC.cc:193
void reset(EmuTime::param time)
Definition SCC.cc:173
uint8_t peekMem(uint8_t address, EmuTime::param time) const
Definition SCC.cc:206
void writeMem(uint8_t address, uint8_t value, EmuTime::param time)
Definition SCC.cc:285
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
constexpr void iota(ForwardIt first, ForwardIt last, T value)
Definition ranges.hh:322
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)
Definition xrange.hh:132