Implement ARM image export.

This commit is contained in:
Christian Speckner 2024-08-21 22:36:54 +02:00
parent 57d9e120ce
commit 493f56e86a
5 changed files with 61 additions and 10 deletions

View File

@ -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);
}
);
}

View File

@ -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;

View File

@ -397,6 +397,23 @@ string CartridgeELF::getDebugLog() const
return s.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::pair<unique_ptr<uInt8[]>, size_t> CartridgeELF::getArmImage() const
{
const size_t imageSize = ADDR_TABLES_BASE + TABLES_SIZE;
unique_ptr<uInt8[]> image = make_unique<uInt8[]>(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<ElfLinker>(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, myElfParser);
try {
myLinker->link(externalSymbols(SystemType::ntsc));
} catch (const ElfLinker::ElfLinkError& e) {

View File

@ -89,6 +89,8 @@ class CartridgeELF: public Cartridge {
public:
string getDebugLog() const;
std::pair<unique_ptr<uInt8[]>, size_t> getArmImage() const;
private:
class BusFallbackDelegate: public CortexM0::BusTransactionDelegate {
public:

View File

@ -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<Dialog*>(parent);
if (parentDialog) {
parentDialog->getDynamicBounds(w, h);
} else {
w = FBMinimum::Width;
h = FBMinimum::Height;
}
static_cast<Dialog*>(parent)->getDynamicBounds(w, h);
if(w > static_cast<uInt32>(font.getMaxCharWidth() * 80))
w = font.getMaxCharWidth() * 80;