openMSX
NowindInterface.cc
Go to the documentation of this file.
1 #include "NowindInterface.hh"
2 #include "NowindCommand.hh"
3 #include "DiskChanger.hh"
4 #include "Clock.hh"
5 #include "MSXMotherBoard.hh"
6 #include "MSXException.hh"
7 #include "serialize.hh"
8 #include "serialize_stl.hh"
9 #include <cassert>
10 #include <functional>
11 #include <memory>
12 
13 using std::string;
14 
15 namespace openmsx {
16 
18  : MSXDevice(config)
19  , rom(getName() + " ROM", "rom", config)
20  , flashConfig(rom.getSize() / 0x10000, {0x10000, false})
21  , flash(rom, flashConfig, 0x01A4,
23  , host(drives)
24  , basename("nowindX")
25 {
26  nowindsInUse = getMotherBoard().getSharedStuff<NowindsInUse>("nowindsInUse");
27 
28  unsigned i = 0;
29  while ((*nowindsInUse)[i]) {
30  if (++i == MAX_NOWINDS) {
31  throw MSXException("Too many nowind interfaces.");
32  }
33  }
34  (*nowindsInUse)[i] = true;
35  basename[6] = char('a' + i);
36 
37  command = std::make_unique<NowindCommand>(
38  basename, getCommandController(), *this);
39 
40  // start with one (empty) drive
41  auto drive = command->createDiskChanger(basename, 0, getMotherBoard());
42  drive->createCommand();
43  drives.push_back(std::move(drive));
44 
45  reset(EmuTime::dummy());
46 }
47 
49 {
50  unsigned i = basename[6] - 'a';
51  assert((*nowindsInUse)[i]);
52  (*nowindsInUse)[i] = false;
53 }
54 
55 void NowindInterface::reset(EmuTime::param /*time*/)
56 {
57  // version 1 didn't change the bank number
58  // version 2 (produced by Sunrise) does reset the bank number
59  bank = 0;
60 
61  // Flash state is NOT changed on reset
62  //flash.reset();
63 }
64 
65 byte NowindInterface::peekMem(word address, EmuTime::param /*time*/) const
66 {
67  if (((0x2000 <= address) && (address < 0x4000)) ||
68  ((0x8000 <= address) && (address < 0xA000))) {
69  return host.peek();
70  } else if ((0x4000 <= address) && (address < 0xC000)) {
71  // note: range 0x8000-0xA000 is already handled above
72  return flash.peek(bank * 0x4000 + (address & 0x3FFF));
73  } else {
74  return 0xFF;
75  }
76 }
77 
78 byte NowindInterface::readMem(word address, EmuTime::param /*time*/)
79 {
80  if (((0x2000 <= address) && (address < 0x4000)) ||
81  ((0x8000 <= address) && (address < 0xA000))) {
82  return host.read();
83  } else if ((0x4000 <= address) && (address < 0xC000)) {
84  // note: range 0x8000-0xA000 is already handled above
85  return flash.read(bank * 0x4000 + (address & 0x3FFF));
86  } else {
87  return 0xFF;
88  }
89 }
90 
91 const byte* NowindInterface::getReadCacheLine(word address) const
92 {
93  if (((0x2000 <= address) && (address < 0x4000)) ||
94  ((0x8000 <= address) && (address < 0xA000))) {
95  // nowind region, not cacheable
96  return nullptr;
97  } else if ((0x4000 <= address) && (address < 0xC000)) {
98  // note: range 0x8000-0xA000 is already handled above
99  return flash.getReadCacheLine(bank * 0x4000 + (address & 0x3FFF));
100  } else {
101  return unmappedRead;
102  }
103 }
104 
105 void NowindInterface::writeMem(word address, byte value, EmuTime::param time)
106 {
107  if (address < 0x4000) {
108  flash.write(bank * 0x4000 + address, value);
109  } else if (((0x4000 <= address) && (address < 0x6000)) ||
110  ((0x8000 <= address) && (address < 0xA000))) {
111  constexpr Clock<1000> clock(EmuTime::zero());
112  host.write(value, clock.getTicksTill(time));
113  } else if (((0x6000 <= address) && (address < 0x8000)) ||
114  ((0xA000 <= address) && (address < 0xC000))) {
115  byte max = rom.getSize() / (16 * 1024);
116  bank = (value < max) ? value : value & (max - 1);
117  invalidateDeviceRCache(0x4000, 0x4000);
118  invalidateDeviceRCache(0xA000, 0x2000);
119  }
120 }
121 
123 {
124  if (address < 0xC000) {
125  // not cacheable
126  return nullptr;
127  } else {
128  return unmappedWrite;
129  }
130 }
131 
132 
133 template<typename Archive>
134 void NowindInterface::serialize(Archive& ar, unsigned /*version*/)
135 {
136  ar.template serializeBase<MSXDevice>(*this);
137  ar.serialize("flash", flash);
138  ar.serializeWithID("drives", drives, std::ref(getMotherBoard()));
139  ar.serialize("nowindhost", host,
140  "bank", bank);
141 
142  // don't serialize command, rom, basename
143 }
146 
147 } // namespace openmsx
void write(unsigned address, byte value)
Definition: AmdFlash.cc:268
byte peek(unsigned address) const
Definition: AmdFlash.cc:215
byte read(unsigned address) const
Definition: AmdFlash.cc:251
const byte * getReadCacheLine(unsigned address) const
Definition: AmdFlash.cc:257
Represents a clock with a fixed frequency.
Definition: Clock.hh:19
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:76
void invalidateDeviceRCache()
Definition: MSXDevice.hh:210
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:301
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
byte peek() const
Definition: NowindHost.cc:55
void write(byte data, unsigned time)
Definition: NowindHost.cc:73
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) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
void reset(EmuTime::param time) override
This method is called on reset.
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
NowindInterface(const DeviceConfig &config)
void serialize(Archive &ar, unsigned version)
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.
unsigned getSize() const
Definition: Rom.hh:34
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:287
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:742
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:983