123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- #include "DebugDevice.hh"
- #include "Clock.hh"
- #include "FileOperations.hh"
- #include "serialize.hh"
- #include <iostream>
- #include <iomanip>
- using std::string;
- namespace openmsx {
- DebugDevice::DebugDevice(const DeviceConfig& config)
- : MSXDevice(config)
- , fileNameSetting(
- getCommandController(), "debugoutput",
- "name of the file the debugdevice outputs to",
- config.getChildData("filename", "stdout"))
- {
- openOutput(fileNameSetting.getString());
- reset(EmuTime::dummy());
- }
- void DebugDevice::reset(EmuTime::param /*time*/)
- {
- mode = OFF;
- modeParameter = 0;
- }
- void DebugDevice::writeIO(word port, byte value, EmuTime::param time)
- {
- const auto& newName = fileNameSetting.getString();
- if (newName != fileNameString) {
- openOutput(newName);
- }
- switch (port & 0x01) {
- case 0:
- switch ((value & 0x30) >> 4) {
- case 0:
- mode = OFF;
- break;
- case 1:
- mode = SINGLEBYTE;
- modeParameter = value & 0x0F;
- break;
- case 2:
- mode = MULTIBYTE;
- modeParameter = value & 0x03;
- break;
- case 3:
- break;
- }
- if (!(value & 0x40)){
- (*outputstrm) << '\n' << std::flush;
- }
- break;
- case 1:
- switch (mode) {
- case OFF:
- break;
- case SINGLEBYTE:
- outputSingleByte(value, time);
- break;
- case MULTIBYTE:
- outputMultiByte(value);
- break;
- default:
- break;
- }
- break;
- }
- }
- void DebugDevice::outputSingleByte(byte value, EmuTime::param time)
- {
- if (modeParameter & 0x01) {
- displayByte(value, HEX);
- }
- if (modeParameter & 0x02) {
- displayByte(value, BIN);
- }
- if (modeParameter & 0x04) {
- displayByte(value, DEC);
- }
- if (modeParameter & 0x08) {
- (*outputstrm) << '\'';
- byte tmp = ((value >= ' ') && (value != 127)) ? value : '.';
- displayByte(tmp, ASC);
- (*outputstrm) << "' ";
- }
- Clock<3579545> zero(EmuTime::zero());
- (*outputstrm) << "emutime: " << std::dec << zero.getTicksTill(time);
- if ((modeParameter & 0x08) && ((value < ' ') || (value == 127))) {
- displayByte(value, ASC); // do special effects
- }
- (*outputstrm) << '\n' << std::flush;
- }
- void DebugDevice::outputMultiByte(byte value)
- {
- DisplayType dispType;
- switch (modeParameter) {
- case 0:
- dispType = HEX;
- break;
- case 1:
- dispType = BIN;
- break;
- case 2:
- dispType = DEC;
- break;
- case 3:
- default:
- dispType = ASC;
- break;
- }
- displayByte(value, dispType);
- }
- void DebugDevice::displayByte(byte value, DisplayType type)
- {
- switch (type) {
- case HEX:
- (*outputstrm) << std::hex << std::setw(2)
- << std::setfill('0')
- << int(value) << "h " << std::flush;
- break;
- case BIN: {
- for (byte mask = 0x80; mask; mask >>= 1) {
- (*outputstrm) << ((value & mask) ? '1' : '0');
- }
- (*outputstrm) << "b " << std::flush;
- break;
- }
- case DEC:
- (*outputstrm) << std::dec << std::setw(3)
- << std::setfill('0')
- << int(value) << ' ' << std::flush;
- break;
- case ASC:
- (*outputstrm).put(value);
- (*outputstrm) << std::flush;
- break;
- }
- }
- void DebugDevice::openOutput(std::string_view name)
- {
- fileNameString = name;
- debugOut.close();
- if (name == "stdout") {
- outputstrm = &std::cout;
- } else if (name == "stderr") {
- outputstrm = &std::cerr;
- } else {
- string realName = FileOperations::expandTilde(name);
- FileOperations::openofstream(debugOut, realName, std::ios::app);
- outputstrm = &debugOut;
- }
- }
- static std::initializer_list<enum_string<DebugDevice::DebugMode>> debugModeInfo = {
- { "OFF", DebugDevice::OFF },
- { "SINGLEBYTE", DebugDevice::SINGLEBYTE },
- { "MULTIBYTE", DebugDevice::MULTIBYTE },
- { "ASCII", DebugDevice::ASCII }
- };
- SERIALIZE_ENUM(DebugDevice::DebugMode, debugModeInfo);
- template<typename Archive>
- void DebugDevice::serialize(Archive& ar, unsigned /*version*/)
- {
- ar.template serializeBase<MSXDevice>(*this);
- ar.serialize("mode", mode,
- "modeParameter", modeParameter);
- }
- INSTANTIATE_SERIALIZE_METHODS(DebugDevice);
- REGISTER_MSXDEVICE(DebugDevice, "DebugDevice");
- } // namespace openmsx
|