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