openMSX
DebugDevice.cc
Go to the documentation of this file.
1 #include "DebugDevice.hh"
2 #include "Clock.hh"
3 #include "FileOperations.hh"
4 #include "serialize.hh"
5 #include <iostream>
6 #include <iomanip>
7 
8 namespace openmsx {
9 
11  : MSXDevice(config)
12  , fileNameSetting(
13  getCommandController(), "debugoutput",
14  "name of the file the debugdevice outputs to",
15  config.getChildData("filename", "stdout"))
16 {
17  openOutput(fileNameSetting.getString());
18  reset(EmuTime::dummy());
19 }
20 
21 void DebugDevice::reset(EmuTime::param /*time*/)
22 {
23  mode = OFF;
24  modeParameter = 0;
25 }
26 
27 void DebugDevice::writeIO(word port, byte value, EmuTime::param time)
28 {
29  const auto& newName = fileNameSetting.getString();
30  if (newName != fileNameString) {
31  openOutput(newName);
32  }
33 
34  switch (port & 0x01) {
35  case 0:
36  switch ((value & 0x30) >> 4) {
37  case 0:
38  mode = OFF;
39  break;
40  case 1:
41  mode = SINGLEBYTE;
42  modeParameter = value & 0x0F;
43  break;
44  case 2:
45  mode = MULTIBYTE;
46  modeParameter = value & 0x03;
47  break;
48  case 3:
49  break;
50  }
51  if (!(value & 0x40)){
52  (*outputstrm) << '\n' << std::flush;
53  }
54  break;
55  case 1:
56  switch (mode) {
57  case OFF:
58  break;
59  case SINGLEBYTE:
60  outputSingleByte(value, time);
61  break;
62  case MULTIBYTE:
63  outputMultiByte(value);
64  break;
65  default:
66  break;
67  }
68  break;
69  }
70 }
71 
72 void DebugDevice::outputSingleByte(byte value, EmuTime::param time)
73 {
74  if (modeParameter & 0x01) {
75  displayByte(value, HEX);
76  }
77  if (modeParameter & 0x02) {
78  displayByte(value, BIN);
79  }
80  if (modeParameter & 0x04) {
81  displayByte(value, DEC);
82  }
83  if (modeParameter & 0x08) {
84  (*outputstrm) << '\'';
85  byte tmp = ((value >= ' ') && (value != 127)) ? value : '.';
86  displayByte(tmp, ASC);
87  (*outputstrm) << "' ";
88  }
89  Clock<3579545> zero(EmuTime::zero());
90  (*outputstrm) << "emutime: " << std::dec << zero.getTicksTill(time);
91  if ((modeParameter & 0x08) && ((value < ' ') || (value == 127))) {
92  displayByte(value, ASC); // do special effects
93  }
94  (*outputstrm) << '\n' << std::flush;
95 }
96 
97 void DebugDevice::outputMultiByte(byte value)
98 {
99  DisplayType dispType = [&] {
100  switch (modeParameter) {
101  case 0: return HEX;
102  case 1: return BIN;
103  case 2: return DEC;
104  case 3:
105  default: return ASC;
106  }
107  }();
108  displayByte(value, dispType);
109 }
110 
111 void DebugDevice::displayByte(byte value, DisplayType type)
112 {
113  switch (type) {
114  case HEX:
115  (*outputstrm) << std::hex << std::setw(2)
116  << std::setfill('0')
117  << int(value) << "h " << std::flush;
118  break;
119  case BIN: {
120  for (byte mask = 0x80; mask; mask >>= 1) {
121  (*outputstrm) << ((value & mask) ? '1' : '0');
122  }
123  (*outputstrm) << "b " << std::flush;
124  break;
125  }
126  case DEC:
127  (*outputstrm) << std::dec << std::setw(3)
128  << std::setfill('0')
129  << int(value) << ' ' << std::flush;
130  break;
131  case ASC:
132  (*outputstrm).put(value);
133  (*outputstrm) << std::flush;
134  break;
135  }
136 }
137 
138 void DebugDevice::openOutput(std::string_view name)
139 {
140  fileNameString = name;
141  debugOut.close();
142  if (name == "stdout") {
143  outputstrm = &std::cout;
144  } else if (name == "stderr") {
145  outputstrm = &std::cerr;
146  } else {
147  auto realName = FileOperations::expandTilde(fileNameString);
148  FileOperations::openofstream(debugOut, realName, std::ios::app);
149  outputstrm = &debugOut;
150  }
151 }
152 
153 static constexpr std::initializer_list<enum_string<DebugDevice::DebugMode>> debugModeInfo = {
154  { "OFF", DebugDevice::OFF },
155  { "SINGLEBYTE", DebugDevice::SINGLEBYTE },
156  { "MULTIBYTE", DebugDevice::MULTIBYTE },
157  { "ASCII", DebugDevice::ASCII }
158 };
160 
161 template<typename Archive>
162 void DebugDevice::serialize(Archive& ar, unsigned /*version*/)
163 {
164  ar.template serializeBase<MSXDevice>(*this);
165  ar.serialize("mode", mode,
166  "modeParameter", modeParameter);
167 }
170 
171 } // namespace openmsx
void reset(EmuTime::param time) override
This method is called on reset.
Definition: DebugDevice.cc:21
DebugDevice(const DeviceConfig &config)
Definition: DebugDevice.cc:10
void serialize(Archive &ar, unsigned version)
Definition: DebugDevice.cc:162
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: DebugDevice.cc:27
zstring_view getString() const noexcept
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
void openofstream(std::ofstream &stream, zstring_view filename)
Open an ofstream in a platform-independent manner.
string expandTilde(string path)
Expand the '~' character to the users home directory.
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
constexpr nibble mask[4][13]
Definition: RP5C01.cc:34
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1009