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