openMSX
MSXWatchIODevice.cc
Go to the documentation of this file.
1 #include "MSXWatchIODevice.hh"
2 #include "MSXMotherBoard.hh"
3 #include "Reactor.hh"
4 #include "MSXCPUInterface.hh"
5 #include "TclObject.hh"
6 #include "Interpreter.hh"
7 #include <cassert>
8 #include <memory>
9 
10 namespace openmsx {
11 
12 // class WatchIO
13 
15  WatchPoint::Type type_,
16  unsigned beginAddr_, unsigned endAddr_,
17  TclObject command_, TclObject condition_,
18  bool once_, unsigned newId /*= -1*/)
19  : WatchPoint(command_, condition_, type_, beginAddr_, endAddr_, once_, newId)
20  , motherboard(motherboard_)
21 {
22  for (unsigned i = byte(beginAddr_); i <= byte(endAddr_); ++i) {
23  ios.push_back(std::make_unique<MSXWatchIODevice>(
24  *motherboard.getMachineConfig(), *this));
25  }
26 }
27 
29 {
30  byte begin = getBeginAddress();
31  return *ios[port - begin];
32 }
33 
34 void WatchIO::doReadCallback(unsigned port)
35 {
36  auto& cpuInterface = motherboard.getCPUInterface();
37  if (cpuInterface.isFastForward()) return;
38 
39  auto& cliComm = motherboard.getReactor().getGlobalCliComm();
40  auto& interp = motherboard.getReactor().getInterpreter();
41  interp.setVariable(TclObject("wp_last_address"), TclObject(int(port)));
42 
43  // keep this object alive by holding a shared_ptr to it, for the case
44  // this watchpoint deletes itself in checkAndExecute()
45  auto keepAlive = shared_from_this();
46  checkAndExecute(cliComm, interp);
47  if (onlyOnce()) {
48  cpuInterface.removeWatchPoint(keepAlive);
49  }
50 
51  interp.unsetVariable("wp_last_address");
52 }
53 
54 void WatchIO::doWriteCallback(unsigned port, unsigned value)
55 {
56  auto& cpuInterface = motherboard.getCPUInterface();
57  if (cpuInterface.isFastForward()) return;
58 
59  auto& cliComm = motherboard.getReactor().getGlobalCliComm();
60  auto& interp = motherboard.getReactor().getInterpreter();
61  interp.setVariable(TclObject("wp_last_address"), TclObject(int(port)));
62  interp.setVariable(TclObject("wp_last_value"), TclObject(int(value)));
63 
64  // see comment in doReadCallback() above
65  auto keepAlive = shared_from_this();
66  checkAndExecute(cliComm, interp);
67  if (onlyOnce()) {
68  cpuInterface.removeWatchPoint(keepAlive);
69  }
70 
71  interp.unsetVariable("wp_last_address");
72  interp.unsetVariable("wp_last_value");
73 }
74 
75 
76 // class MSXWatchIODevice
77 
79  const HardwareConfig& hwConf, WatchIO& watchIO_)
80  : MSXMultiDevice(hwConf)
81  , watchIO(watchIO_)
82  , device(nullptr)
83 {
84 }
85 
86 std::string MSXWatchIODevice::getName() const
87 {
88  assert(device);
89  return device->getName();
90 }
91 
92 byte MSXWatchIODevice::peekIO(word port, EmuTime::param time) const
93 {
94  assert(device);
95  return device->peekIO(port, time);
96 }
97 
98 byte MSXWatchIODevice::readIO(word port, EmuTime::param time)
99 {
100  assert(device);
101 
102  // first trigger watchpoint, then read from device
103  watchIO.doReadCallback(port);
104  return device->readIO(port, time);
105 }
106 
107 void MSXWatchIODevice::writeIO(word port, byte value, EmuTime::param time)
108 {
109  assert(device);
110 
111  // first write to device, then trigger watchpoint
112  device->writeIO(port, value, time);
113  watchIO.doWriteCallback(port, value);
114 }
115 
116 } // namespace openmsx
MSXCPUInterface & getCPUInterface()
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
virtual std::string getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:379
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
WatchIO(MSXMotherBoard &motherboard, WatchPoint::Type type, unsigned beginAddr, unsigned endAddr, TclObject command, TclObject condition, bool once, unsigned newId=-1)
Base class for CPU breakpoints.
Definition: WatchPoint.hh:13
const HardwareConfig * getMachineConfig() const
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
void checkAndExecute(GlobalCliComm &cliComm, Interpreter &interp)
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
GlobalCliComm & getGlobalCliComm()
Definition: Reactor.hh:82
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
MSXWatchIODevice(const HardwareConfig &hwConf, WatchIO &watchIO)
void setVariable(const TclObject &name, const TclObject &value)
Definition: Interpreter.cc:239
unsigned getBeginAddress() const
Definition: WatchPoint.hh:34
virtual byte peekIO(word port, EmuTime::param time) const
Read a byte from a given IO port.
Definition: MSXDevice.cc:417
MSXWatchIODevice & getDevice(byte port)
Interpreter & getInterpreter()
Definition: Reactor.cc:311