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