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