From 3c65ac986e8d2bbf64e1f55371c03f06e0342ce7 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 29 May 2015 00:03:09 -0700 Subject: [PATCH] GBA: Palette RIFF exporter --- CHANGES | 2 +- src/gba/supervisor/export.c | 57 ++++++++++++++++++++++++++++++ src/gba/supervisor/export.h | 15 ++++++++ src/platform/qt/PaletteView.cpp | 31 +++++++++++++++++ src/platform/qt/PaletteView.h | 2 ++ src/platform/qt/PaletteView.ui | 61 +++++++++++++++++++++++++++++++-- 6 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 src/gba/supervisor/export.c create mode 100644 src/gba/supervisor/export.h diff --git a/CHANGES b/CHANGES index 7b0f35cf8..8d4c90921 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,7 @@ Features: - Ability to hide individual background layers, or OBJs - Ability to mute individual audio channels - - Palette viewer + - Palette viewer and exporter - Volume control - More shortcuts are editable (e.g. quick save/load) - Rewind now shows the frame after rewinding diff --git a/src/gba/supervisor/export.c b/src/gba/supervisor/export.c new file mode 100644 index 000000000..a0dbbecd6 --- /dev/null +++ b/src/gba/supervisor/export.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "export.h" + +#include "gba/video.h" +#include "util/vfs.h" + +bool GBAExportPaletteRIFF(struct VFile* vf, size_t entries, const uint16_t* colors) { + if (entries > 0xFFFF) { + return false; + } + uint32_t chunkSize = 4 + 4 * entries; + uint32_t size = chunkSize + 12; + + // Header + if (vf->write(vf, "RIFF", 4) < 4) { + return false; + } + if (VFileWrite32LE(vf, size) < 4) { + return false; + } + if (vf->write(vf, "PAL ", 4) < 4) { + return false; + } + + // Data chunk + if (vf->write(vf, "data", 4) < 4) { + return false; + } + if (VFileWrite32LE(vf, chunkSize) < 4) { + return false; + } + if (VFileWrite16LE(vf, 0x0300) < 2) { + return false; + } + if (VFileWrite16LE(vf, entries) < 2) { + return false; + } + + size_t i; + for (i = 0; i < entries; ++i) { + uint8_t block[4] = { + GBA_R8(colors[i]), + GBA_G8(colors[i]), + GBA_B8(colors[i]), + 0 + }; + if (vf->write(vf, block, 4) < 4) { + return false; + } + } + + return true; +} diff --git a/src/gba/supervisor/export.h b/src/gba/supervisor/export.h new file mode 100644 index 000000000..0db0836b0 --- /dev/null +++ b/src/gba/supervisor/export.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_EXPORT_H +#define GBA_EXPORT_H + +#include "util/common.h" + +struct VFile; + +bool GBAExportPaletteRIFF(struct VFile* vf, size_t entries, const uint16_t* colors); + +#endif diff --git a/src/platform/qt/PaletteView.cpp b/src/platform/qt/PaletteView.cpp index 421cd6de2..bd150912f 100644 --- a/src/platform/qt/PaletteView.cpp +++ b/src/platform/qt/PaletteView.cpp @@ -5,8 +5,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "PaletteView.h" +#include #include +extern "C" { +#include "gba/supervisor/export.h" +#include "util/vfs.h" +} + using namespace QGBA; PaletteView::PaletteView(GameController* controller, QWidget* parent) @@ -33,6 +39,8 @@ PaletteView::PaletteView(GameController* controller, QWidget* parent) connect(m_ui.bgGrid, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int))); connect(m_ui.objGrid, &Swatch::indexPressed, [this] (int index) { selectIndex(index + 256); }); + connect(m_ui.exportBG, &QAbstractButton::clicked, [this] () { exportPalette(0, 256); }); + connect(m_ui.exportOBJ, &QAbstractButton::clicked, [this] () { exportPalette(256, 256); }); connect(controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(close())); } @@ -64,3 +72,26 @@ void PaletteView::selectIndex(int index) { m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0'))); } + +void PaletteView::exportPalette(int start, int length) { + if (start >= 512) { + return; + } + if (start + length > 512) { + length = 512 - start; + } + m_controller->threadInterrupt(); + QString filename = QFileDialog::getSaveFileName(this, tr("Export palette"), QString(), tr("Windows PAL (*.pal)")); + if (filename.isNull()) { + m_controller->threadContinue(); + return; + } + VFile* vf = VFileOpen(filename.toLocal8Bit().constData(), O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + m_controller->threadContinue(); + return; + } + GBAExportPaletteRIFF(vf, length, &m_controller->thread()->gba->video.palette[start]); + vf->close(vf); + m_controller->threadContinue(); +} diff --git a/src/platform/qt/PaletteView.h b/src/platform/qt/PaletteView.h index 5a4d58252..ef807a565 100644 --- a/src/platform/qt/PaletteView.h +++ b/src/platform/qt/PaletteView.h @@ -32,6 +32,8 @@ private slots: void selectIndex(int); private: + void exportPalette(int start, int length); + Ui::PaletteView m_ui; GameController* m_controller; diff --git a/src/platform/qt/PaletteView.ui b/src/platform/qt/PaletteView.ui index 00eb54390..a941fd7b7 100644 --- a/src/platform/qt/PaletteView.ui +++ b/src/platform/qt/PaletteView.ui @@ -6,8 +6,8 @@ 0 0 - 452 - 349 + 440 + 397 @@ -292,6 +292,63 @@ + + + + + + Qt::Horizontal + + + + 20 + 0 + + + + + + + + Export BG + + + + + + + Qt::Horizontal + + + + 40 + 0 + + + + + + + + Export OBJ + + + + + + + Qt::Horizontal + + + + 20 + 0 + + + + + +