openMSX
VDPIODelay.cc
Go to the documentation of this file.
1 #include "VDPIODelay.hh"
2 #include "MSXCPU.hh"
3 #include "MSXCPUInterface.hh"
4 #include "DummyDevice.hh"
5 #include "serialize.hh"
6 #include <cassert>
7 
8 namespace openmsx {
9 
11  : MSXDevice(config)
12  , cpu(getCPU()) // used frequently, so cache it
13  , lastTime(EmuTime::zero())
14 {
15  for (int port = 0x098; port <= 0x9B; ++port) {
16  getInDevicePtr (port) = &cpuInterface.getDummyDevice();
17  getOutDevicePtr(port) = &cpuInterface.getDummyDevice();
18  }
19 }
20 
22 {
23  assert((0x98 <= port) && (port <= 0x9B));
24  return *inDevices[port - 0x98];
25 }
26 
28 {
29  assert((0x98 <= port) && (port <= 0x9B));
30  return inDevices[port - 0x98];
31 }
32 
34 {
35  assert((0x98 <= port) && (port <= 0x9B));
36  return outDevices[port - 0x98];
37 }
38 
39 byte VDPIODelay::readIO(word port, EmuTime::param time)
40 {
41  delay(time);
42  return getInDevicePtr(byte(port))->readIO(byte(port), lastTime.getTime());
43 }
44 
45 byte VDPIODelay::peekIO(word port, EmuTime::param time) const
46 {
47  return getInDevice(byte(port)).peekIO(byte(port), time);
48 }
49 
50 void VDPIODelay::writeIO(word port, byte value, EmuTime::param time)
51 {
52  delay(time);
53  getOutDevicePtr(byte(port))->writeIO(byte(port), value, lastTime.getTime());
54 }
55 
56 void VDPIODelay::delay(EmuTime::param time)
57 {
58  if (cpu.isR800Active()) {
59  // Number of cycles based on measurements on real HW.
60  // See doc/turbor-vdp-io-timing.ods for details.
61  lastTime += 62; // 8us
62  if (time < lastTime.getTime()) {
63  cpu.wait(lastTime.getTime());
64  return;
65  }
66  }
67  lastTime.advance(time);
68 }
69 
70 template<typename Archive>
71 void VDPIODelay::serialize(Archive& ar, unsigned /*version*/)
72 {
73  ar.serialize("lastTime", lastTime);
74 }
76 
77 } // namespace openmsx
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
const MSXDevice & getInDevice(byte port) const
Definition: VDPIODelay.cc:21
constexpr void advance(EmuTime::param e)
Advance this clock in time until the last tick which is not past the given time.
Definition: Clock.hh:110
virtual byte readIO(word port, EmuTime::param time)
Read a byte from an IO port at a certain time from this device.
Definition: MSXDevice.cc:406
bool isR800Active() const
Is the R800 currently active?
Definition: MSXCPU.hh:124
void wait(EmuTime::param time)
Definition: MSXCPU.cc:307
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
DummyDevice & getDummyDevice()
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: VDPIODelay.cc:45
virtual void writeIO(word port, byte value, EmuTime::param time)
Write a byte to a given IO port at a certain time to this device.
Definition: MSXDevice.cc:412
constexpr EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
Definition: Clock.hh:46
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: VDPIODelay.cc:39
void serialize(Archive &ar, unsigned version)
Definition: VDPIODelay.cc:71
VDPIODelay(const DeviceConfig &config, MSXCPUInterface &cpuInterface)
Definition: VDPIODelay.cc:10
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
Definition: MSXDevice.cc:417
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.
Definition: VDPIODelay.cc:50
MSXDevice *& getOutDevicePtr(byte port)
Definition: VDPIODelay.cc:33
MSXDevice *& getInDevicePtr(byte port)
Definition: VDPIODelay.cc:27