//============================================================================ // // SSSS tt lll lll // SS SS tt ll ll // SS tttttt eeee ll ll aaaa // SSSS tt ee ee ll ll aa // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS SS tt ee ll ll aa aa // SSSS ttt eeeee llll llll aaaaa // // Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // and the Stella Team // // See the file "License.txt" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // // $Id$ //============================================================================ #include #include "OSystem.hxx" #include "FrameBuffer.hxx" #include "Widget.hxx" #include "GuiObject.hxx" #include "ContextMenu.hxx" #include "TiaZoomWidget.hxx" #include "Debugger.hxx" #include "DebuggerParser.hxx" #include "TIADebug.hxx" #include "TIASurface.hxx" #include "TIA.hxx" #include "TiaOutputWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TiaOutputWidget::TiaOutputWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) : Widget(boss, font, x, y, w, h), CommandSender(boss), myZoom(nullptr), myClickX(0), myClickY(0) { // Create context menu for commands VariantList l; VarList::push_back(l, "Fill to scanline", "scanline"); VarList::push_back(l, "Set breakpoint", "bp"); VarList::push_back(l, "Set zoom position", "zoom"); VarList::push_back(l, "Save snapshot", "snap"); VarList::push_back(l, "Toggle fixed debug colors (from beam pos)", "fixed"); myMenu = make_ptr(this, font, l); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TiaOutputWidget::~TiaOutputWidget() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::loadConfig() { setDirty(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::saveSnapshot() { int number = (int)(instance().getTicks() / 1000); ostringstream sspath; sspath << instance().snapshotSaveDir() << instance().console().properties().get(Cartridge_Name) << "_dbg_" << hex << setw(8) << setfill('0') << number << ".png"; const uInt32 width = instance().console().tia().width(), height = instance().console().tia().height(); FBSurface& s = dialog().surface(); GUI::Rect rect(_x, _y, _x + width*2, _y + height); string message = "Snapshot saved"; try { instance().png().saveImage(sspath.str(), s, rect); } catch(const runtime_error& e) { message = e.what(); } instance().frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::handleMouseDown(int x, int y, int button, int clickCount) { // Grab right mouse button for command context menu if(button == 2) { myClickX = x; myClickY = y; // Add menu at current x,y mouse location myMenu->show(x + getAbsX(), y + getAbsY()); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { int ystart = atoi(instance().console().properties().get(Display_YStart).c_str()); switch(cmd) { case ContextMenu::kItemSelectedCmd: { const string& rmb = myMenu->getSelectedTag().toString(); if(rmb == "scanline") { ostringstream command; int lines = myClickY + ystart; if(instance().console().tia().partialFrame()) lines -= instance().console().tia().scanlines(); if(lines > 0) { command << "scanline #" << lines; instance().debugger().parser().run(command.str()); } } else if(rmb == "bp") { ostringstream command; int scanline = myClickY + ystart; command << "breakif _scan==#" << scanline; instance().debugger().parser().run(command.str()); } else if(rmb == "zoom") { if(myZoom) myZoom->setPos(myClickX, myClickY); } else if(rmb == "snap") { instance().debugger().parser().run("savesnap"); } else if(rmb == "fixed") { instance().console().tia().toggleFixedColors(); } break; } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::drawWidget(bool hilite) { //cerr << "TiaOutputWidget::drawWidget\n"; const uInt32 width = instance().console().tia().width(), height = instance().console().tia().height(); FBSurface& s = dialog().surface(); // Get current scanline position // This determines where the frame greying should start, and where a // scanline 'pointer' should be drawn uInt16 scanx, scany, scanoffset; bool visible = instance().console().tia().scanlinePos(scanx, scany); scanoffset = width * scany + scanx; for(uInt32 y = 0, i = 0; y < height; ++y) { uInt32* line_ptr = myLineBuffer; for(uInt32 x = 0; x < width; ++x, ++i) { uInt8 shift = i > scanoffset ? 1 : 0; uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift); *line_ptr++ = pixel; *line_ptr++ = pixel; } s.drawPixels(myLineBuffer, _x, _y+y, width << 1); } // Show electron beam position if(visible && scanx < width && scany+2u < height) { s.fillRect(_x+(scanx<<1), _y+scany, 3, 3, kBtnTextColor); } }