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