diff --git a/src/debugger/gui/CartELFWidget.cxx b/src/debugger/gui/CartELFWidget.cxx index 219d03c6f..48887bd08 100644 --- a/src/debugger/gui/CartELFWidget.cxx +++ b/src/debugger/gui/CartELFWidget.cxx @@ -22,7 +22,10 @@ #include "StringParser.hxx" #include "ScrollBarWidget.hxx" #include "StringListWidget.hxx" -#include "EditTextWidget.hxx" +#include "BrowserDialog.hxx" +#include "OSystem.hxx" +#include "FrameBuffer.hxx" +#include "bspf.hxx" namespace { constexpr int SAVE_ARM_IMAGE_CMD = 'sarm'; @@ -66,24 +69,42 @@ void CartridgeELFWidget::initialize() logWidget->setList(logLines); y += visibleLogLines * lineHeight + lineHeight / 2; - const auto saveImageButtonWidth = 17 * _font.getMaxCharWidth(); WidgetArray wid; const auto saveImageButton = new ButtonWidget(_boss, _font, x, y, "Save ARM image", SAVE_ARM_IMAGE_CMD); saveImageButton->setTarget(this); - const auto imageNameEdit = new EditTextWidget( - _boss, _font, x + saveImageButtonWidth, y, width - saveImageButtonWidth, lineHeight + 2, "arm_image.bin" - ); - wid.push_back(saveImageButton); - wid.push_back(imageNameEdit); addToFocusList(wid); } +void CartridgeELFWidget::saveArmImage(const FSNode& node) +{ + try { + const auto [buffer, size] = myCart.getArmImage(); + + const size_t sizeWritten = node.write(buffer, size); + if (sizeWritten != size) throw runtime_error("failed to write arm image"); + + instance().frameBuffer().showTextMessage("Successfully exported ARM executable image"); + } + catch (...) { + instance().frameBuffer().showTextMessage("Failed to export ARM executable image"); + } +} + void CartridgeELFWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { - if (cmd == SAVE_ARM_IMAGE_CMD) cout << "save image" << std::endl; + if (cmd == SAVE_ARM_IMAGE_CMD) + BrowserDialog::show( + _boss, + "Save ARM image", + instance().userDir().getPath() + "arm_image.bin", + BrowserDialog::Mode::FileSave, + [this](bool ok, const FSNode& node) { + if (ok) saveArmImage(node); + } + ); } diff --git a/src/debugger/gui/CartELFWidget.hxx b/src/debugger/gui/CartELFWidget.hxx index 5d705b6a1..c9743f11a 100644 --- a/src/debugger/gui/CartELFWidget.hxx +++ b/src/debugger/gui/CartELFWidget.hxx @@ -21,6 +21,8 @@ #include "CartDebugWidget.hxx" class CartridgeELF; +class EditTextWidget; +class FSNode; class CartridgeELFWidget: public CartDebugWidget { @@ -34,6 +36,7 @@ class CartridgeELFWidget: public CartDebugWidget private: void initialize(); + void saveArmImage(const FSNode& node); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; diff --git a/src/emucore/CartELF.cxx b/src/emucore/CartELF.cxx index baeea7359..35471b848 100644 --- a/src/emucore/CartELF.cxx +++ b/src/emucore/CartELF.cxx @@ -397,6 +397,23 @@ string CartridgeELF::getDebugLog() const return s.str(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +std::pair, size_t> CartridgeELF::getArmImage() const +{ + const size_t imageSize = ADDR_TABLES_BASE + TABLES_SIZE; + unique_ptr image = make_unique(imageSize); + + memset(image.get(), 0, imageSize); + + memcpy(image.get() + ADDR_STACK_BASE, mySectionStack.get(), STACK_SIZE); + memcpy(image.get() + ADDR_TEXT_BASE, mySectionText.get(), TEXT_SIZE); + memcpy(image.get() + ADDR_DATA_BASE, mySectionData.get(), DATA_SIZE); + memcpy(image.get() + ADDR_RODATA_BASE, mySectionRodata.get(), RODATA_SIZE); + memcpy(image.get() + ADDR_TABLES_BASE, mySectionTables.get(), TABLES_SIZE); + + return std::pair(std::move(image), imageSize); +} + #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -444,6 +461,7 @@ void CartridgeELF::parseAndLinkElf() if (dump) dumpElf(myElfParser, cout); myLinker = make_unique(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, myElfParser); + try { myLinker->link(externalSymbols(SystemType::ntsc)); } catch (const ElfLinker::ElfLinkError& e) { diff --git a/src/emucore/CartELF.hxx b/src/emucore/CartELF.hxx index aaee2305d..5e42fa3c7 100644 --- a/src/emucore/CartELF.hxx +++ b/src/emucore/CartELF.hxx @@ -89,6 +89,8 @@ class CartridgeELF: public Cartridge { public: string getDebugLog() const; + std::pair, size_t> getArmImage() const; + private: class BusFallbackDelegate: public CortexM0::BusTransactionDelegate { public: diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 1de98b0a3..019e59766 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -117,9 +117,16 @@ void BrowserDialog::show(GuiObject* parent, const GUI::Font& font, const Command& command, const FSNode::NameFilter& namefilter) { - uInt32 w = 0, h = 0; + uInt32 w, h; + + const auto parentDialog = dynamic_cast(parent); + if (parentDialog) { + parentDialog->getDynamicBounds(w, h); + } else { + w = FBMinimum::Width; + h = FBMinimum::Height; + } - static_cast(parent)->getDynamicBounds(w, h); if(w > static_cast(font.getMaxCharWidth() * 80)) w = font.getMaxCharWidth() * 80;